Commit fffb8b51 authored by Deepak Saxena's avatar Deepak Saxena Committed by Deepak Saxena

Merge plexity.net:/home/dsaxena/src/linux-2.6-arm-timer

into plexity.net:/home/dsaxena/src/linux-2.6-for-rmk
parents f0b3c84e 01c0a4a6
README on the SDRAM Controller for the LH7a40X
==============================================
The standard configuration for the SDRAM controller generates a sparse
memory array. The precise layout is determined by the SDRAM chips. A
default kernel configuration assembles the discontiguous memory
regions into separate memory nodes via the NUMA (Non-Uniform Memory
Architecture) facilities. In this default configuration, the kernel
is forgiving about the precise layout. As long as it is given an
accurate picture of available memory by the bootloader the kernel will
execute correctly.
The SDRC supports a mode where some of the chip select lines are
swapped in order to make SDRAM look like a synchronous ROM. Setting
this bit means that the RAM will present as a contiguous array. Some
programmers prefer this to the discontiguous layout. Be aware that
may be a penalty for this feature where some some configurations of
memory are significantly reduced; i.e. 64MiB of RAM appears as only 32
MiB.
There are a couple of configuration options to override the default
behavior. When the SROMLL bit is set and memory appears as a
contiguous array, there is no reason to support NUMA.
CONFIG_LH7A40X_CONTIGMEM disables NUMA support. When physical memory
is discontiguous, the memory tables are organized such that there are
two banks per nodes with a small gap between them. This layout wastes
some kernel memory for page tables representing non-existent memory.
CONFIG_LH7A40X_ONE_BANK_PER_NODE optimizes the node tables such that
there are no gaps. These options control the low level organization
of the memory management tables in ways that may prevent the kernel
from booting or may cause the kernel to allocated excessively large
page tables. Be warned. Only change these options if you know what
you are doing. The default behavior is a reasonable compromise that
will suit all users.
--
A typical 32MiB system with the default configuration options will
find physical memory managed as follows.
node 0: 0xc0000000 4MiB
0xc1000000 4MiB
node 1: 0xc4000000 4MiB
0xc5000000 4MiB
node 2: 0xc8000000 4MiB
0xc9000000 4MiB
node 3: 0xcc000000 4MiB
0xcd000000 4MiB
Setting CONFIG_LH7A40X_ONE_BANK_PER_NODE will put each bank into a
separate node.
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 7
EXTRAVERSION =-rc3
EXTRAVERSION =
NAME=Zonked Quokka
# *DOCUMENTATION*
......
......@@ -248,10 +248,10 @@ menu "General setup"
# Select various configuration options depending on the machine type
config DISCONTIGMEM
bool
depends on ARCH_EDB7211 || ARCH_SA1100 || ARCH_LH7A40X
depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_SROMLL)
default y
help
Say Y to upport efficient handling of discontiguous physical memory,
Say Y to support efficient handling of discontiguous physical memory,
for architectures which are either NUMA (Non-Uniform Memory Access)
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
......
......@@ -565,7 +565,8 @@
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
ldr \rx, =0x80000700 @ physical base address
mov \rx, #0x00000700 @ offset from base
orreq \rx, \rx, #0x80000000 @ physical base
orrne \rx, \rx, #0xf8000000 @ virtual base
.endm
......
......@@ -4,7 +4,7 @@
# Object file lists.
obj-y := core.o lm.o time.o
obj-y := clock.o core.o lm.o time.o
obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
......
/*
* linux/arch/arm/mach-integrator/clock.c
*
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
*
* 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/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <asm/semaphore.h>
#include <asm/hardware/clock.h>
#include <asm/hardware/icst525.h>
#include "clock.h"
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
down(&clocks_sem);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
up(&clocks_sem);
return clk;
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
module_put(clk->owner);
}
EXPORT_SYMBOL(clk_put);
int clk_enable(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_disable);
int clk_use(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_use);
void clk_unuse(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_unuse);
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
long clk_round_rate(struct clk *clk, unsigned long rate)
{
return rate;
}
EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = -EIO;
if (clk->setvco) {
struct icst525_vco vco;
vco = icst525_khz_to_vco(clk->params, rate);
clk->rate = icst525_khz(clk->params, vco);
printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
clk->name, vco.s, vco.r, vco.v);
clk->setvco(clk, vco);
ret = 0;
}
return 0;
}
EXPORT_SYMBOL(clk_set_rate);
/*
* These are fixed clocks.
*/
static struct clk kmi_clk = {
.name = "KMIREFCLK",
.rate = 24000000,
};
static struct clk uart_clk = {
.name = "UARTCLK",
.rate = 14745600,
};
int clk_register(struct clk *clk)
{
down(&clocks_sem);
list_add(&clk->node, &clocks);
up(&clocks_sem);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
down(&clocks_sem);
list_del(&clk->node);
up(&clocks_sem);
}
EXPORT_SYMBOL(clk_unregister);
static int __init clk_init(void)
{
clk_register(&kmi_clk);
clk_register(&uart_clk);
return 0;
}
arch_initcall(clk_init);
/*
* linux/arch/arm/mach-integrator/clock.h
*
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
*
* 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.
*/
struct module;
struct icst525_params;
struct clk {
struct list_head node;
unsigned long rate;
struct module *owner;
const char *name;
const struct icst525_params *params;
void *data;
void (*setvco)(struct clk *, struct icst525_vco vco);
};
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
......@@ -25,13 +25,16 @@
#include <asm/arch/impd1.h>
#include <asm/sizes.h>
#include "clock.h"
static int module_id;
module_param_named(lmid, module_id, int, 0444);
MODULE_PARM_DESC(lmid, "logic module stack position");
struct impd1_module {
void *base;
void *base;
struct clk vcos[2];
};
static const struct icst525_params impd1_vco_params = {
......@@ -43,25 +46,20 @@ static const struct icst525_params impd1_vco_params = {
.rd_max = 120,
};
void impd1_set_vco(struct device *dev, int vconr, unsigned long period)
static void impd1_setvco(struct clk *clk, struct icst525_vco vco)
{
struct impd1_module *impd1 = dev_get_drvdata(dev);
struct icst525_vco vco;
struct impd1_module *impd1 = clk->data;
int vconr = clk - impd1->vcos;
u32 val;
vco = icst525_ps_to_vco(&impd1_vco_params, period);
pr_debug("Guessed VCO reg params: S=%d R=%d V=%d\n",
vco.s, vco.r, vco.v);
val = vco.v | (vco.r << 9) | (vco.s << 16);
writel(0xa05f, impd1->base + IMPD1_LOCK);
switch (vconr) {
case 1:
case 0:
writel(val, impd1->base + IMPD1_OSC1);
break;
case 2:
case 1:
writel(val, impd1->base + IMPD1_OSC2);
break;
}
......@@ -77,8 +75,6 @@ void impd1_set_vco(struct device *dev, int vconr, unsigned long period)
#endif
}
EXPORT_SYMBOL(impd1_set_vco);
void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
{
struct impd1_module *impd1 = dev_get_drvdata(dev);
......@@ -140,6 +136,11 @@ static struct impd1_device impd1_devs[] = {
}
};
static const char *impd1_vconames[2] = {
"CLCDCLK",
"AUXVCO2",
};
static int impd1_probe(struct lm_device *dev)
{
struct impd1_module *impd1;
......@@ -168,6 +169,16 @@ static int impd1_probe(struct lm_device *dev)
printk("IM-PD1 found at 0x%08lx\n", dev->resource.start);
for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) {
impd1->vcos[i].owner = THIS_MODULE,
impd1->vcos[i].name = impd1_vconames[i],
impd1->vcos[i].params = &impd1_vco_params,
impd1->vcos[i].data = impd1,
impd1->vcos[i].setvco = impd1_setvco;
clk_register(&impd1->vcos[i]);
}
for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
struct impd1_device *idev = impd1_devs + i;
struct amba_device *d;
......@@ -216,6 +227,7 @@ static void impd1_remove(struct lm_device *dev)
{
struct impd1_module *impd1 = lm_get_drvdata(dev);
struct list_head *l, *n;
int i;
list_for_each_safe(l, n, &dev->dev.children) {
struct device *d = list_to_dev(l);
......@@ -223,6 +235,9 @@ static void impd1_remove(struct lm_device *dev)
device_unregister(d);
}
for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++)
clk_unregister(&impd1->vcos[i]);
lm_set_drvdata(dev, NULL);
iounmap(impd1->base);
......
......@@ -23,6 +23,7 @@
#include <asm/mach-types.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/amba_kmi.h>
#include <asm/hardware/icst525.h>
#include <asm/arch/lm.h>
......@@ -32,12 +33,16 @@
#include <asm/mach/mmc.h>
#include <asm/mach/map.h>
#include "clock.h"
#define INTCP_PA_MMC_BASE 0x1c000000
#define INTCP_PA_AACI_BASE 0x1d000000
#define INTCP_PA_FLASH_BASE 0x24000000
#define INTCP_FLASH_SIZE SZ_32M
#define INTCP_PA_CLCD_BASE 0xc0000000
#define INTCP_VA_CIC_BASE 0xf1000040
#define INTCP_VA_PIC_BASE 0xf1400000
#define INTCP_VA_SIC_BASE 0xfca00000
......@@ -209,6 +214,44 @@ static void __init intcp_init_irq(void)
pic_unmask_irq(IRQ_CP_CPPLDINT);
}
/*
* Clock handling
*/
#define CM_LOCK (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
#define CM_AUXOSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+0x1c)
static const struct icst525_params cp_auxvco_params = {
.ref = 24000,
.vco_max = 320000,
.vd_min = 8,
.vd_max = 263,
.rd_min = 3,
.rd_max = 65,
};
static void cp_auxvco_set(struct clk *clk, struct icst525_vco vco)
{
u32 val;
val = readl(CM_AUXOSC) & ~0x7ffff;
val |= vco.v | (vco.r << 9) | (vco.s << 16);
writel(0xa05f, CM_LOCK);
writel(val, CM_AUXOSC);
writel(0, CM_LOCK);
}
static struct clk cp_clcd_clk = {
.name = "CLCDCLK",
.params = &cp_auxvco_params,
.setvco = cp_auxvco_set,
};
static struct clk cp_mmci_clk = {
.name = "MCLK",
.rate = 33000000,
};
/*
* Flash handling.
*/
......@@ -340,15 +383,34 @@ static struct amba_device aaci_device = {
.periphid = 0,
};
static struct amba_device clcd_device = {
.dev = {
.bus_id = "mb:c0",
.coherent_dma_mask = ~0,
},
.res = {
.start = INTCP_PA_CLCD_BASE,
.end = INTCP_PA_CLCD_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.dma_mask = ~0,
.irq = { IRQ_CP_CLCDCINT, NO_IRQ },
.periphid = 0,
};
static struct amba_device *amba_devs[] __initdata = {
&mmc_device,
&aaci_device,
&clcd_device,
};
static void __init intcp_init(void)
{
int i;
clk_register(&cp_clcd_clk);
clk_register(&cp_mmci_clk);
platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
......
......@@ -34,6 +34,37 @@ config ARCH_LH7A400
config ARCH_LH7A404
bool
config LH7A40X_CONTIGMEM
bool "Disable NUMA Support"
depends on ARCH_LH7A40X
help
Say Y here if your bootloader sets the SROMLL bit(s) in
the SDRAM controller, organizing memory as a contiguous
array. This option will disable CONFIG_DISCONTIGMEM and
force the kernel to manage all memory in one node.
Setting this option incorrectly may prevent the kernel from
booting. It is OK to leave it N.
For more information, consult
<file:Documentation/arm/Sharp-LH/SDRAM>.
config LH7A40X_ONE_BANK_PER_NODE
bool "Optimize NUMA Node Tables for Size"
depends on ARCH_LH7A40X && !LH7A40X_CONTIGMEM
help
Say Y here to produce compact memory node tables. By
default pairs of adjacent physical RAM banks are managed
together in a single node, incurring some wasted overhead
in the node tables, however also maintaining compatibility
with systems where physical memory is truly contiguous.
Setting this option incorrectly may prevent the kernel from
booting. It is OK to leave it N.
For more information, consult
<file:Documentation/arm/Sharp-LH/SDRAM>.
endmenu
endif
......@@ -2,4 +2,4 @@
# Makefile for the linux kernel.
#
obj-y := core.o
obj-y := core.o clock.o
/*
* linux/arch/arm/mach-versatile/clock.c
*
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
*
* 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/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <asm/semaphore.h>
#include <asm/hardware/clock.h>
#include <asm/hardware/icst525.h>
#include "clock.h"
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
down(&clocks_sem);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
up(&clocks_sem);
return clk;
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
module_put(clk->owner);
}
EXPORT_SYMBOL(clk_put);
int clk_enable(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_disable);
int clk_use(struct clk *clk)
{
return 0;
}
EXPORT_SYMBOL(clk_use);
void clk_unuse(struct clk *clk)
{
}
EXPORT_SYMBOL(clk_unuse);
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
long clk_round_rate(struct clk *clk, unsigned long rate)
{
return rate;
}
EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = -EIO;
#if 0 // Not yet
if (clk->setvco) {
struct icst525_vco vco;
vco = icst525_khz_to_vco(clk->params, rate);
clk->rate = icst525_khz(clk->params, vco);
printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
clk->name, vco.s, vco.r, vco.v);
clk->setvco(clk, vco);
ret = 0;
}
#endif
return 0;
}
EXPORT_SYMBOL(clk_set_rate);
/*
* These are fixed clocks.
*/
static struct clk kmi_clk = {
.name = "KMIREFCLK",
.rate = 24000000,
};
static struct clk uart_clk = {
.name = "UARTCLK",
.rate = 24000000,
};
static struct clk mmci_clk = {
.name = "MCLK",
.rate = 33000000,
};
int clk_register(struct clk *clk)
{
down(&clocks_sem);
list_add(&clk->node, &clocks);
up(&clocks_sem);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
down(&clocks_sem);
list_del(&clk->node);
up(&clocks_sem);
}
EXPORT_SYMBOL(clk_unregister);
static int __init clk_init(void)
{
clk_register(&kmi_clk);
clk_register(&uart_clk);
clk_register(&mmci_clk);
return 0;
}
arch_initcall(clk_init);
/*
* linux/arch/arm/mach-versatile/clock.h
*
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
*
* 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.
*/
struct module;
struct icst525_params;
struct clk {
struct list_head node;
unsigned long rate;
struct module *owner;
const char *name;
const struct icst525_params *params;
void *data;
void (*setvco)(struct clk *, struct icst525_vco vco);
};
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
......@@ -137,8 +137,8 @@ static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *re
return &win->locals[reg - 16];
}
static inline unsigned long compute_effective_address(struct pt_regs *regs,
unsigned int insn)
static unsigned long compute_effective_address(struct pt_regs *regs,
unsigned int insn)
{
unsigned int rs1 = (insn >> 14) & 0x1f;
unsigned int rs2 = insn & 0x1f;
......@@ -153,8 +153,8 @@ static inline unsigned long compute_effective_address(struct pt_regs *regs,
}
}
static inline unsigned long safe_compute_effective_address(struct pt_regs *regs,
unsigned int insn)
unsigned long safe_compute_effective_address(struct pt_regs *regs,
unsigned int insn)
{
unsigned int rs1 = (insn >> 14) & 0x1f;
unsigned int rs2 = insn & 0x1f;
......
......@@ -201,6 +201,25 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
return 0;
}
extern unsigned long safe_compute_effective_address(struct pt_regs *,
unsigned int);
static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
{
unsigned int insn;
if (text_fault)
return regs->pc;
if (regs->psr & PSR_PS) {
insn = *(unsigned int *) regs->pc;
} else {
__get_user(insn, (unsigned int *) regs->pc);
}
return safe_compute_effective_address(regs, insn);
}
asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
unsigned long address)
{
......@@ -307,7 +326,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
info.si_errno = 0;
/* info.si_code set above to make clear whether
this was a SEGV_MAPERR or SEGV_ACCERR fault. */
info.si_addr = (void *)address;
info.si_addr = (void *) compute_si_addr(regs, text_fault);
info.si_trapno = 0;
force_sig_info (SIGSEGV, &info, tsk);
return;
......@@ -361,7 +380,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRERR;
info.si_addr = (void *)address;
info.si_addr = (void *) compute_si_addr(regs, text_fault);
info.si_trapno = 0;
force_sig_info (SIGBUS, &info, tsk);
if (!from_user)
......@@ -530,7 +549,7 @@ inline void force_user_fault(unsigned long address, int write)
info.si_errno = 0;
/* info.si_code set above to make clear whether
this was a SEGV_MAPERR or SEGV_ACCERR fault. */
info.si_addr = (void *)address;
info.si_addr = (void *) address;
info.si_trapno = 0;
force_sig_info (SIGSEGV, &info, tsk);
return;
......@@ -540,7 +559,7 @@ inline void force_user_fault(unsigned long address, int write)
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRERR;
info.si_addr = (void *)address;
info.si_addr = (void *) address;
info.si_trapno = 0;
force_sig_info (SIGBUS, &info, tsk);
}
......
......@@ -158,8 +158,8 @@ static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
}
}
static unsigned long compute_effective_address(struct pt_regs *regs,
unsigned int insn, unsigned int rd)
unsigned long compute_effective_address(struct pt_regs *regs,
unsigned int insn, unsigned int rd)
{
unsigned int rs1 = (insn >> 14) & 0x1f;
unsigned int rs2 = insn & 0x1f;
......
......@@ -207,14 +207,21 @@ static unsigned int get_user_insn(unsigned long tpc)
return insn;
}
static void do_fault_siginfo(int code, int sig, unsigned long address)
extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);
static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
unsigned int insn, int fault_code)
{
siginfo_t info;
info.si_code = code;
info.si_signo = sig;
info.si_errno = 0;
info.si_addr = (void *) address;
if (fault_code & FAULT_CODE_ITLB)
info.si_addr = (void *) regs->tpc;
else
info.si_addr = (void *)
compute_effective_address(regs, insn, 0);
info.si_trapno = 0;
force_sig_info(sig, &info, current);
}
......@@ -295,7 +302,7 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
/* The si_code was set to make clear whether
* this was a SEGV_MAPERR or SEGV_ACCERR fault.
*/
do_fault_siginfo(si_code, SIGSEGV, address);
do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code);
return;
}
......@@ -471,7 +478,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs)
* Send a sigbus, regardless of whether we were in kernel
* or user mode.
*/
do_fault_siginfo(BUS_ADRERR, SIGBUS, address);
do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code);
/* Kernel mode? Handle exceptions or die */
if (regs->tstate & TSTATE_PRIV)
......
......@@ -70,7 +70,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#define WD_VER "1.16 (03/27/2004)"
#define WD_VER "1.16 (06/12/2004)"
#define PFX "pcwd: "
/*
......@@ -299,10 +299,11 @@ static int pcwd_stop(void)
return 0;
}
static void pcwd_keepalive(void)
static int pcwd_keepalive(void)
{
/* user land ping */
next_heartbeat = jiffies + (heartbeat * HZ);
return 0;
}
static int pcwd_set_heartbeat(int t)
......@@ -529,12 +530,12 @@ static int pcwd_close(struct inode *inode, struct file *file)
{
if (expect_close == 42) {
pcwd_stop();
atomic_inc( &open_allowed );
} else {
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
pcwd_keepalive();
}
expect_close = 0;
atomic_inc( &open_allowed );
return 0;
}
......
......@@ -49,7 +49,7 @@
/* Module and version information */
#define WATCHDOG_VERSION "1.00"
#define WATCHDOG_DATE "13/03/2004"
#define WATCHDOG_DATE "12 Jun 2004"
#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
#define WATCHDOG_NAME "pcwd_pci"
#define PFX WATCHDOG_NAME ": "
......@@ -73,7 +73,7 @@
#define WD_PCI_TTRP 0x04 /* Temperature Trip status */
/* according to documentation max. time to process a command for the pci
watchdog card is 100 ms, so we give it 150 ms to do it's job */
* watchdog card is 100 ms, so we give it 150 ms to do it's job */
#define PCI_COMMAND_TIMEOUT 150
/* Watchdog's internal commands */
......@@ -404,8 +404,8 @@ static int pcipcwd_release(struct inode *inode, struct file *file)
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
pcipcwd_keepalive();
}
clear_bit(0, &is_active);
expect_release = 0;
clear_bit(0, &is_active);
return 0;
}
......@@ -585,15 +585,12 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n");
/* Check that the heartbeat value is within it's range ; if not reset to the default */
if (heartbeat < 1 || heartbeat > 0xFFFF) {
heartbeat = WATCHDOG_HEARTBEAT;
if (pcipcwd_set_heartbeat(heartbeat)) {
pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
heartbeat);
WATCHDOG_HEARTBEAT);
}
/* Calculate the watchdog's heartbeat */
pcipcwd_set_heartbeat(heartbeat);
ret = register_reboot_notifier(&pcipcwd_notifier);
if (ret != 0) {
printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
......@@ -601,29 +598,30 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
goto err_out_release_region;
}
ret = misc_register(&pcipcwd_miscdev);
if (ret != 0) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
goto err_out_unregister_reboot;
}
if (pcipcwd_private.supports_temp) {
ret = misc_register(&pcipcwd_temp_miscdev);
if (ret != 0) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
TEMP_MINOR, ret);
goto err_out_misc_deregister;
goto err_out_unregister_reboot;
}
}
ret = misc_register(&pcipcwd_miscdev);
if (ret != 0) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
goto err_out_misc_deregister;
}
printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
heartbeat, nowayout);
return 0;
err_out_misc_deregister:
misc_deregister(&pcipcwd_miscdev);
if (pcipcwd_private.supports_temp)
misc_deregister(&pcipcwd_temp_miscdev);
err_out_unregister_reboot:
unregister_reboot_notifier(&pcipcwd_notifier);
err_out_release_region:
......@@ -640,9 +638,9 @@ static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
pcipcwd_stop();
/* Deregister */
misc_deregister(&pcipcwd_miscdev);
if (pcipcwd_private.supports_temp)
misc_deregister(&pcipcwd_temp_miscdev);
misc_deregister(&pcipcwd_miscdev);
unregister_reboot_notifier(&pcipcwd_notifier);
pci_release_regions(pdev);
pci_disable_device(pdev);
......
......@@ -56,7 +56,8 @@
/* Module and Version Information */
#define DRIVER_VERSION "v1.00 (28/02/2004)"
#define DRIVER_VERSION "1.00"
#define DRIVER_DATE "12 Jun 2004"
#define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
#define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
#define DRIVER_LICENSE "GPL"
......@@ -456,8 +457,8 @@ static int usb_pcwd_release(struct inode *inode, struct file *file)
printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
usb_pcwd_keepalive(usb_pcwd_device);
}
clear_bit(0, &is_active);
expect_release = 0;
clear_bit(0, &is_active);
return 0;
}
......@@ -681,15 +682,12 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
((option_switches & 0x08) ? "ON" : "OFF"));
/* Check that the heartbeat value is within it's range ; if not reset to the default */
if (heartbeat < 1 || heartbeat > 0xFFFF) {
heartbeat = WATCHDOG_HEARTBEAT;
if (usb_pcwd_set_heartbeat(usb_pcwd, heartbeat)) {
usb_pcwd_set_heartbeat(usb_pcwd, WATCHDOG_HEARTBEAT);
printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
heartbeat);
WATCHDOG_HEARTBEAT);
}
/* Calculate the watchdog's heartbeat */
usb_pcwd_set_heartbeat(usb_pcwd, heartbeat);
retval = register_reboot_notifier(&usb_pcwd_notifier);
if (retval != 0) {
printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
......@@ -697,17 +695,17 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
goto error;
}
retval = misc_register(&usb_pcwd_miscdev);
retval = misc_register(&usb_pcwd_temperature_miscdev);
if (retval != 0) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, retval);
TEMP_MINOR, retval);
goto err_out_unregister_reboot;
}
retval = misc_register(&usb_pcwd_temperature_miscdev);
retval = misc_register(&usb_pcwd_miscdev);
if (retval != 0) {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
TEMP_MINOR, retval);
WATCHDOG_MINOR, retval);
goto err_out_misc_deregister;
}
......@@ -720,7 +718,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
return 0;
err_out_misc_deregister:
misc_deregister(&usb_pcwd_miscdev);
misc_deregister(&usb_pcwd_temperature_miscdev);
err_out_unregister_reboot:
unregister_reboot_notifier(&usb_pcwd_notifier);
error:
......@@ -758,8 +756,8 @@ static void usb_pcwd_disconnect(struct usb_interface *interface)
usb_pcwd->exists = 0;
/* Deregister */
misc_deregister(&usb_pcwd_temperature_miscdev);
misc_deregister(&usb_pcwd_miscdev);
misc_deregister(&usb_pcwd_temperature_miscdev);
unregister_reboot_notifier(&usb_pcwd_notifier);
up (&usb_pcwd->sem);
......@@ -791,7 +789,7 @@ static int __init usb_pcwd_init(void)
return result;
}
printk(KERN_INFO PFX DRIVER_DESC " " DRIVER_VERSION "\n");
printk(KERN_INFO PFX DRIVER_DESC " v" DRIVER_VERSION " (" DRIVER_DATE ")\n");
return 0;
}
......
......@@ -571,7 +571,7 @@ ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat)
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
......@@ -605,7 +605,7 @@ ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg)
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
......
......@@ -16,25 +16,9 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/pnp.h>
#define GENERIC_HD_DATA 0
#define GENERIC_HD_ERROR 1
#define GENERIC_HD_NSECTOR 2
#define GENERIC_HD_SECTOR 3
#define GENERIC_HD_LCYL 4
#define GENERIC_HD_HCYL 5
#define GENERIC_HD_SELECT 6
#define GENERIC_HD_STATUS 7
static int generic_ide_offsets[IDE_NR_PORTS] = {
GENERIC_HD_DATA, GENERIC_HD_ERROR, GENERIC_HD_NSECTOR,
GENERIC_HD_SECTOR, GENERIC_HD_LCYL, GENERIC_HD_HCYL,
GENERIC_HD_SELECT, GENERIC_HD_STATUS, -1, -1
};
#include <linux/ide.h>
/* Add your devices here :)) */
struct pnp_device_id idepnp_devices[] = {
......@@ -52,12 +36,11 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
return -1;
ide_setup_ports(&hw, (unsigned long) pnp_port_start(dev, 0),
generic_ide_offsets,
(unsigned long) pnp_port_start(dev, 1),
0, NULL,
// generic_pnp_ide_iops,
pnp_irq(dev, 0));
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, pnp_port_start(dev, 0),
pnp_port_start(dev, 1));
hw.irq = pnp_irq(dev, 0);
hw.dma = NO_DMA;
index = ide_register_hw(&hw, &hwif);
......@@ -86,11 +69,7 @@ static struct pnp_driver idepnp_driver = {
.remove = idepnp_remove,
};
void pnpide_init(int enable)
void __init pnpide_init(void)
{
if(enable)
pnp_register_driver(&idepnp_driver);
else
pnp_unregister_driver(&idepnp_driver);
pnp_register_driver(&idepnp_driver);
}
......@@ -233,27 +233,6 @@ static int proc_ide_write_config(struct file *file, const char __user *buffer,
}
#endif /* CONFIG_BLK_DEV_IDEPCI */
} else { /* not pci */
#if !defined(__mc68000__) && !defined(CONFIG_APUS)
/*
* Geert Uytterhoeven
*
* unless you can explain me what it really does.
* On m68k, we don't have outw() and outl() yet,
* and I need a good reason to implement it.
*
* BTW, IMHO the main remaining portability problem with the IDE driver
* is that it mixes IO (ioport) and MMIO (iomem) access on different platforms.
*
* I think all accesses should be done using
*
* ide_in[bwl](ide_device_instance, offset)
* ide_out[bwl](ide_device_instance, value, offset)
*
* so the architecture specific code can #define ide_{in,out}[bwl] to the
* appropriate function.
*
*/
switch (r->size) {
case 1: hwif->OUTB(val, reg);
break;
......@@ -262,7 +241,6 @@ static int proc_ide_write_config(struct file *file, const char __user *buffer,
case 4: hwif->OUTL(val, reg);
break;
}
#endif /* !__mc68000__ && !CONFIG_APUS */
}
}
spin_unlock_irqrestore(&ide_lock, flags);
......
This diff is collapsed.
......@@ -2003,6 +2003,7 @@ int __init ide_setup (char *s)
return 1;
}
extern void pnpide_init(void);
extern void h8300_ide_init(void);
/*
......@@ -2069,12 +2070,9 @@ static void __init probe_for_hwifs (void)
buddha_init();
}
#endif /* CONFIG_BLK_DEV_BUDDHA */
#if defined(CONFIG_BLK_DEV_IDEPNP) && defined(CONFIG_PNP)
{
extern void pnpide_init(int enable);
pnpide_init(1);
}
#endif /* CONFIG_BLK_DEV_IDEPNP */
#ifdef CONFIG_BLK_DEV_IDEPNP
pnpide_init();
#endif
#ifdef CONFIG_H8300
h8300_ide_init();
#endif
......@@ -2212,9 +2210,6 @@ int ide_unregister_subdriver (ide_drive_t *drive)
up(&ide_setting_sem);
return 1;
}
#if defined(CONFIG_BLK_DEV_IDEPNP) && defined(CONFIG_PNP) && defined(MODULE)
pnpide_init(0);
#endif /* CONFIG_BLK_DEV_IDEPNP */
#ifdef CONFIG_PROC_FS
ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
......
......@@ -409,7 +409,7 @@ static int aec62xx_irq_timeout (ide_drive_t *drive)
return 0;
}
static unsigned int __init init_chipset_aec62xx (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
{
int bus_speed = system_bus_clock();
......@@ -435,7 +435,7 @@ static unsigned int __init init_chipset_aec62xx (struct pci_dev *dev, const char
return dev->irq;
}
static void __init init_hwif_aec62xx (ide_hwif_t *hwif)
static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
{
hwif->autodma = 0;
hwif->tuneproc = &aec62xx_tune_drive;
......@@ -468,7 +468,7 @@ static void __init init_hwif_aec62xx (ide_hwif_t *hwif)
hwif->drives[1].autodma = hwif->autodma;
}
static void __init init_dma_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
static void __devinit init_dma_aec62xx(ide_hwif_t *hwif, unsigned long dmabase)
{
struct pci_dev *dev = hwif->pci_dev;
......@@ -490,12 +490,12 @@ static void __init init_dma_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
static void __init init_setup_aec62xx (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d)
{
ide_setup_pci_device(dev, d);
}
static void __init init_setup_aec6x80 (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_aec6x80(struct pci_dev *dev, ide_pci_device_t *d)
{
unsigned long bar4reg = pci_resource_start(dev, 4);
......
......@@ -38,7 +38,7 @@
#include <asm/io.h>
#include "alim15x3.h"
#define DISPLAY_ALI_TIMINGS
/*
* ALi devices are not plug in. Otherwise these static values would
......@@ -853,6 +853,16 @@ static void __init init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
static ide_pci_device_t ali15x3_chipset __devinitdata = {
.name = "ALI15X3",
.init_chipset = init_chipset_ali15x3,
.init_hwif = init_hwif_ali15x3,
.init_dma = init_dma_ali15x3,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
};
/**
* alim15x3_init_one - set up an ALi15x3 IDE controller
* @dev: PCI device to set up
......@@ -863,8 +873,8 @@ static void __init init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_pci_device_t *d = &ali15x3_chipsets[id->driver_data];
ide_pci_device_t *d = &ali15x3_chipset;
if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, NULL))
printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not yet fully tested.\n");
......
#ifndef ALI15X3_H
#define ALI15X3_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_ALI_TIMINGS
static unsigned int init_chipset_ali15x3(struct pci_dev *, const char *);
static void init_hwif_common_ali15x3(ide_hwif_t *);
static void init_hwif_ali15x3(ide_hwif_t *);
static void init_dma_ali15x3(ide_hwif_t *, unsigned long);
static ide_pci_device_t ali15x3_chipsets[] __devinitdata = {
{ /* 0 */
.name = "ALI15X3",
.init_chipset = init_chipset_ali15x3,
.init_hwif = init_hwif_ali15x3,
.init_dma = init_dma_ali15x3,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
}
};
#endif /* ALI15X3 */
......@@ -586,7 +586,7 @@ static int cmd646_1_ide_dma_end (ide_drive_t *drive)
return (dma_stat & 7) != 4;
}
static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
{
u32 class_rev = 0;
u8 mrdmode = 0;
......@@ -674,7 +674,7 @@ static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char
return 0;
}
static unsigned int __init ata66_cmd64x (ide_hwif_t *hwif)
static unsigned int __devinit ata66_cmd64x(ide_hwif_t *hwif)
{
u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01;
......@@ -689,7 +689,7 @@ static unsigned int __init ata66_cmd64x (ide_hwif_t *hwif)
return (ata66 & mask) ? 1 : 0;
}
static void __init init_hwif_cmd64x (ide_hwif_t *hwif)
static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
unsigned int class_rev;
......
......@@ -51,7 +51,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include "cs5520.h"
#define DISPLAY_CS5520_TIMINGS
#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
......@@ -251,7 +251,24 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
}
#define DECLARE_CS_DEV(name_str) \
{ \
.name = name_str, \
.init_chipset = init_chipset_cs5520, \
.init_setup_dma = cs5520_init_setup_dma, \
.init_hwif = init_hwif_cs5520, \
.channels = 2, \
.autodma = AUTODMA, \
.bootable = ON_BOARD, \
.flags = IDEPCI_FLAG_ISA_PORTS, \
}
static ide_pci_device_t cyrix_chipsets[] __devinitdata = {
/* 0 */ DECLARE_CS_DEV("Cyrix 5510"),
/* 1 */ DECLARE_CS_DEV("Cyrix 5520")
};
/*
* The 5510/5520 are a bit weird. They don't quite set up the way
* the PCI helper layer expects so we must do much of the set up
......
#ifndef CS5520_H
#define CS5520_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_CS5520_TIMINGS
static unsigned int init_chipset_cs5520(struct pci_dev *, const char *);
static void init_hwif_cs5520(ide_hwif_t *);
static void cs5520_init_setup_dma(struct pci_dev *dev, struct ide_pci_device_s *d, ide_hwif_t *hwif);
static ide_pci_device_t cyrix_chipsets[] __devinitdata = {
{
.name = "Cyrix 5510",
.init_chipset = init_chipset_cs5520,
.init_setup_dma = cs5520_init_setup_dma,
.init_hwif = init_hwif_cs5520,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
.flags = IDEPCI_FLAG_ISA_PORTS,
},
{
.name = "Cyrix 5520",
.init_chipset = init_chipset_cs5520,
.init_setup_dma = cs5520_init_setup_dma,
.init_hwif = init_hwif_cs5520,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
.flags = IDEPCI_FLAG_ISA_PORTS,
}
};
#endif /* CS5520_H */
......@@ -31,7 +31,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include "cs5530.h"
#define DISPLAY_CS5530_TIMINGS
#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
......@@ -404,9 +404,19 @@ static void __init init_hwif_cs5530 (ide_hwif_t *hwif)
hwif->drives[1].autodma = hwif->autodma;
}
static ide_pci_device_t cs5530_chipset __devinitdata = {
.name = "CS5530",
.init_chipset = init_chipset_cs5530,
.init_hwif = init_hwif_cs5530,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
.flags = IDEPCI_FLAG_FORCE_MASTER,
};
static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &cs5530_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &cs5530_chipset);
return 0;
}
......
#ifndef CS5530_H
#define CS5530_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_CS5530_TIMINGS
static unsigned int init_chipset_cs5530(struct pci_dev *, const char *);
static void init_hwif_cs5530(ide_hwif_t *);
static ide_pci_device_t cs5530_chipsets[] __devinitdata = {
{ /* 0 */
.name = "CS5530",
.init_chipset = init_chipset_cs5530,
.init_hwif = init_hwif_cs5530,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
.flags = IDEPCI_FLAG_FORCE_MASTER,
}
};
#endif /* CS5530_H */
......@@ -235,7 +235,7 @@ static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive)
*/
#define HPT34X_PCI_INIT_REG 0x80
static unsigned int __init init_chipset_hpt34x (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const char *name)
{
int i = 0;
unsigned long hpt34xIoBase = pci_resource_start(dev, 4);
......@@ -289,7 +289,7 @@ static unsigned int __init init_chipset_hpt34x (struct pci_dev *dev, const char
return dev->irq;
}
static void __init init_hwif_hpt34x (ide_hwif_t *hwif)
static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
{
u16 pcicmd = 0;
......
......@@ -795,7 +795,7 @@ static int hpt370_busproc(ide_drive_t * drive, int state)
return 0;
}
static int __init init_hpt37x(struct pci_dev *dev)
static int __devinit init_hpt37x(struct pci_dev *dev)
{
int adjust, i;
u16 freq;
......@@ -923,7 +923,7 @@ static int __init init_hpt37x(struct pci_dev *dev)
return 0;
}
static int __init init_hpt366 (struct pci_dev *dev)
static int __devinit init_hpt366(struct pci_dev *dev)
{
u32 reg1 = 0;
u8 drive_fast = 0;
......@@ -958,7 +958,7 @@ static int __init init_hpt366 (struct pci_dev *dev)
return 0;
}
static unsigned int __init init_chipset_hpt366 (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
{
int ret = 0;
u8 test = 0;
......@@ -1004,7 +1004,7 @@ static unsigned int __init init_chipset_hpt366 (struct pci_dev *dev, const char
return dev->irq;
}
static void __init init_hwif_hpt366 (ide_hwif_t *hwif)
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
......@@ -1116,7 +1116,7 @@ static void __init init_hwif_hpt366 (ide_hwif_t *hwif)
hwif->drives[1].autodma = hwif->autodma;
}
static void __init init_dma_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
{
u8 masterdma = 0, slavedma = 0;
u8 dma_new = 0, dma_old = 0;
......@@ -1151,7 +1151,7 @@ static void __init init_dma_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
static void __init init_setup_hpt374 (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
{
struct pci_dev *findev = NULL;
......@@ -1176,12 +1176,12 @@ static void __init init_setup_hpt374 (struct pci_dev *dev, ide_pci_device_t *d)
ide_setup_pci_device(dev, d);
}
static void __init init_setup_hpt37x (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d)
{
ide_setup_pci_device(dev, d);
}
static void __init init_setup_hpt366 (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
{
struct pci_dev *findev = NULL;
u8 pin1 = 0, pin2 = 0;
......
......@@ -25,8 +25,6 @@
#include <asm/io.h>
#include "ns87415.h"
static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
/*
......@@ -217,9 +215,17 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif)
hwif->drives[1].autodma = hwif->autodma;
}
static ide_pci_device_t ns87415_chipset __devinitdata = {
.name = "NS87415",
.init_hwif = init_hwif_ns87415,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
};
static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &ns87415_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &ns87415_chipset);
return 0;
}
......
#ifndef NS87415_H
#define NS87415_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
static void init_hwif_ns87415(ide_hwif_t *);
static ide_pci_device_t ns87415_chipsets[] __devinitdata = {
{ /* 0 */
.name = "NS87415",
.init_hwif = init_hwif_ns87415,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
}
};
#endif /* NS87415_H */
......@@ -404,7 +404,7 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev)
}
#endif /* CONFIG_PPC_PMAC */
static unsigned int __init init_chipset_pdcnew (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name)
{
if (dev->resource[PCI_ROM_RESOURCE].start) {
pci_write_config_dword(dev, PCI_ROM_ADDRESS,
......@@ -429,7 +429,7 @@ static unsigned int __init init_chipset_pdcnew (struct pci_dev *dev, const char
return dev->irq;
}
static void __init init_hwif_pdc202new (ide_hwif_t *hwif)
static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
{
hwif->autodma = 0;
......@@ -457,12 +457,12 @@ static void __init init_hwif_pdc202new (ide_hwif_t *hwif)
#endif /* PDC202_DEBUG_CABLE */
}
static void __init init_setup_pdcnew (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_pdcnew(struct pci_dev *dev, ide_pci_device_t *d)
{
ide_setup_pci_device(dev, d);
}
static void __init init_setup_pdc20270 (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_pdc20270(struct pci_dev *dev, ide_pci_device_t *d)
{
struct pci_dev *findev = NULL;
......@@ -488,7 +488,7 @@ static void __init init_setup_pdc20270 (struct pci_dev *dev, ide_pci_device_t *d
ide_setup_pci_device(dev, d);
}
static void __init init_setup_pdc20276 (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d)
{
if ((dev->bus->self) &&
(dev->bus->self->vendor == PCI_VENDOR_ID_INTEL) &&
......
......@@ -670,7 +670,7 @@ static int pdc202xx_tristate (ide_drive_t * drive, int state)
return 0;
}
static unsigned int __init init_chipset_pdc202xx (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, const char *name)
{
if (dev->resource[PCI_ROM_RESOURCE].start) {
pci_write_config_dword(dev, PCI_ROM_ADDRESS,
......@@ -715,7 +715,7 @@ static unsigned int __init init_chipset_pdc202xx (struct pci_dev *dev, const cha
return dev->irq;
}
static void __init init_hwif_pdc202xx (ide_hwif_t *hwif)
static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
{
hwif->autodma = 0;
hwif->tuneproc = &config_chipset_for_pio;
......@@ -755,7 +755,7 @@ static void __init init_hwif_pdc202xx (ide_hwif_t *hwif)
#endif /* PDC202_DEBUG_CABLE */
}
static void __init init_dma_pdc202xx (ide_hwif_t *hwif, unsigned long dmabase)
static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
{
u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
......@@ -807,7 +807,7 @@ static void __init init_dma_pdc202xx (ide_hwif_t *hwif, unsigned long dmabase)
ide_setup_dma(hwif, dmabase, 8);
}
static void __init init_setup_pdc202ata4 (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d)
{
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
u8 irq = 0, irq2 = 0;
......@@ -837,7 +837,7 @@ static void __init init_setup_pdc202ata4 (struct pci_dev *dev, ide_pci_device_t
ide_setup_pci_device(dev, d);
}
static void __init init_setup_pdc20265 (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_pdc20265(struct pci_dev *dev, ide_pci_device_t *d)
{
if ((dev->bus->self) &&
(dev->bus->self->vendor == PCI_VENDOR_ID_INTEL) &&
......@@ -866,7 +866,7 @@ static void __init init_setup_pdc20265 (struct pci_dev *dev, ide_pci_device_t *d
ide_setup_pci_device(dev, d);
}
static void __init init_setup_pdc202xx (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_pdc202xx(struct pci_dev *dev, ide_pci_device_t *d)
{
ide_setup_pci_device(dev, d);
}
......
......@@ -650,8 +650,8 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
* Set up the ide_hwif_t for the PIIX interface according to the
* capabilities of the hardware.
*/
static void __init init_hwif_piix (ide_hwif_t *hwif)
static void __devinit init_hwif_piix(ide_hwif_t *hwif)
{
u8 reg54h = 0, reg55h = 0, ata66 = 0;
u8 mask = hwif->channel ? 0xc0 : 0x30;
......@@ -720,8 +720,8 @@ static void __init init_hwif_piix (ide_hwif_t *hwif)
* Enable the xp fixup for the PIIX controller and then perform
* a standard ide PCI setup
*/
static void __init init_setup_piix (struct pci_dev *dev, ide_pci_device_t *d)
static void __devinit init_setup_piix(struct pci_dev *dev, ide_pci_device_t *d)
{
ide_setup_pci_device(dev, d);
}
......@@ -749,8 +749,8 @@ static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_
* Check for the present of 450NX errata #19 and errata #25. If
* they are found, disable use of DMA IDE
*/
static void __init piix_check_450nx(void)
static void __devinit piix_check_450nx(void)
{
struct pci_dev *pdev = NULL;
u16 cfg;
......
......@@ -33,8 +33,6 @@
#include <asm/io.h>
#include "rz1000.h"
static void __init init_hwif_rz1000 (ide_hwif_t *hwif)
{
u16 reg;
......@@ -54,15 +52,23 @@ static void __init init_hwif_rz1000 (ide_hwif_t *hwif)
}
}
static ide_pci_device_t rz1000_chipset __devinitdata = {
.name = "RZ100x",
.init_hwif = init_hwif_rz1000,
.channels = 2,
.autodma = NODMA,
.bootable = ON_BOARD,
};
static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &rz1000_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &rz1000_chipset);
return 0;
}
static struct pci_device_id rz1000_pci_tbl[] = {
{ PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
{ PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
......
#ifndef RZ100X_H
#define RZ100X_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
static void init_hwif_rz1000(ide_hwif_t *);
static ide_pci_device_t rz1000_chipsets[] __devinitdata = {
{
.name = "RZ1000",
.init_hwif = init_hwif_rz1000,
.channels = 2,
.autodma = NODMA,
.bootable = ON_BOARD,
},{
.name = "RZ1001",
.init_hwif = init_hwif_rz1000,
.channels = 2,
.autodma = NODMA,
.bootable = ON_BOARD,
}
};
#endif /* RZ100X_H */
......@@ -29,8 +29,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include "sc1200.h"
#define SC1200_REV_A 0x00
#define SC1200_REV_B1 0x01
#define SC1200_REV_B3 0x02
......@@ -545,9 +543,18 @@ static void __init init_hwif_sc1200 (ide_hwif_t *hwif)
hwif->drives[1].autodma = hwif->autodma;
}
static ide_pci_device_t sc1200_chipset __devinitdata = {
.name = "SC1200",
.init_chipset = init_chipset_sc1200,
.init_hwif = init_hwif_sc1200,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
};
static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &sc1200_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &sc1200_chipset);
return 0;
}
......
#ifndef SC1200_H
#define SC1200_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_SC1200_TIMINGS
static unsigned int init_chipset_sc1200(struct pci_dev *, const char *);
static void init_hwif_sc1200(ide_hwif_t *);
static ide_pci_device_t sc1200_chipsets[] __devinitdata = {
{ /* 0 */
.name = "SC1200",
.init_chipset = init_chipset_sc1200,
.init_hwif = init_hwif_sc1200,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
}
};
#endif /* SC1200_H */
......@@ -31,7 +31,8 @@
#include <asm/io.h>
#include "siimage.h"
#undef SIIMAGE_VIRTUAL_DMAPIO
#undef SIIMAGE_LARGE_DMA
/**
* pdev_is_sata - check if device is SATA
......@@ -812,7 +813,7 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
* to 133MHz clocking if the system isn't already set up to do it.
*/
static unsigned int __init init_chipset_siimage (struct pci_dev *dev, const char *name)
static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const char *name)
{
u32 class_rev = 0;
u8 tmpbyte = 0;
......@@ -877,8 +878,8 @@ static unsigned int __init init_chipset_siimage (struct pci_dev *dev, const char
* The hardware supports buffered taskfiles and also some rather nice
* extended PRD tables. Unfortunately right now we don't.
*/
static void __init init_mmio_iops_siimage (ide_hwif_t *hwif)
static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
void *addr = pci_get_drvdata(dev);
......@@ -996,8 +997,8 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
* look in we get for setting up the hwif so that we
* can get the iops right before using them.
*/
static void __init init_iops_siimage (ide_hwif_t *hwif)
static void __devinit init_iops_siimage(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
u32 class_rev = 0;
......@@ -1023,8 +1024,8 @@ static void __init init_iops_siimage (ide_hwif_t *hwif)
* Check for the presence of an ATA66 capable cable on the
* interface.
*/
static unsigned int __init ata66_siimage (ide_hwif_t *hwif)
static unsigned int __devinit ata66_siimage(ide_hwif_t *hwif)
{
unsigned long addr = siimage_selreg(hwif, 0);
if (pci_get_drvdata(hwif->pci_dev) == NULL) {
......@@ -1044,8 +1045,8 @@ static unsigned int __init ata66_siimage (ide_hwif_t *hwif)
* requires several custom handlers so we override the default
* ide DMA handlers appropriately
*/
static void __init init_hwif_siimage (ide_hwif_t *hwif)
static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
{
hwif->autodma = 0;
......@@ -1092,6 +1093,23 @@ static void __init init_hwif_siimage (ide_hwif_t *hwif)
hwif->drives[1].autodma = hwif->autodma;
}
#define DECLARE_SII_DEV(name_str) \
{ \
.name = name_str, \
.init_chipset = init_chipset_siimage, \
.init_iops = init_iops_siimage, \
.init_hwif = init_hwif_siimage, \
.channels = 2, \
.autodma = AUTODMA, \
.bootable = ON_BOARD, \
}
static ide_pci_device_t siimage_chipsets[] __devinitdata = {
/* 0 */ DECLARE_SII_DEV("SiI680"),
/* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA"),
/* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA")
};
/**
* siimage_init_one - pci layer discovery entry
* @dev: PCI device
......
#ifndef SIIMAGE_H
#define SIIMAGE_H
#include <linux/pci.h>
#include <linux/ide.h>
#include <asm/io.h>
#undef SIIMAGE_VIRTUAL_DMAPIO
#undef SIIMAGE_BUFFERED_TASKFILE
#undef SIIMAGE_LARGE_DMA
#define SII_DEBUG 0
#if SII_DEBUG
#define siiprintk(x...) printk(x)
#else
#define siiprintk(x...)
#endif
static unsigned int init_chipset_siimage(struct pci_dev *, const char *);
static void init_iops_siimage(ide_hwif_t *);
static void init_hwif_siimage(ide_hwif_t *);
static ide_pci_device_t siimage_chipsets[] __devinitdata = {
{ /* 0 */
.name = "SiI680",
.init_chipset = init_chipset_siimage,
.init_iops = init_iops_siimage,
.init_hwif = init_hwif_siimage,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
},{ /* 1 */
.name = "SiI3112 Serial ATA",
.init_chipset = init_chipset_siimage,
.init_iops = init_iops_siimage,
.init_hwif = init_hwif_siimage,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
},{ /* 2 */
.name = "Adaptec AAR-1210SA",
.init_chipset = init_chipset_siimage,
.init_iops = init_iops_siimage,
.init_hwif = init_hwif_siimage,
.channels = 2,
.autodma = AUTODMA,
.bootable = ON_BOARD,
}
};
#endif /* SIIMAGE_H */
......@@ -63,7 +63,8 @@
#include <asm/irq.h>
#include "ide-timing.h"
#include "sis5513.h"
#define DISPLAY_SIS_TIMINGS
/* registers layout and init values are chipset family dependant */
......@@ -944,9 +945,19 @@ static void __init init_hwif_sis5513 (ide_hwif_t *hwif)
return;
}
static ide_pci_device_t sis5513_chipset __devinitdata = {
.name = "SIS5513",
.init_chipset = init_chipset_sis5513,
.init_hwif = init_hwif_sis5513,
.channels = 2,
.autodma = NOAUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.bootable = ON_BOARD,
};
static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &sis5513_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &sis5513_chipset);
return 0;
}
......
#ifndef SIS5513_H
#define SIS5513_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_SIS_TIMINGS
static unsigned int init_chipset_sis5513(struct pci_dev *, const char *);
static void init_hwif_sis5513(ide_hwif_t *);
static ide_pci_device_t sis5513_chipsets[] __devinitdata = {
{ /* 0 */
.name = "SIS5513",
.init_chipset = init_chipset_sis5513,
.init_hwif = init_hwif_sis5513,
.channels = 2,
.autodma = NOAUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.bootable = ON_BOARD,
}
};
#endif /* SIS5513_H */
......@@ -29,8 +29,6 @@
#include <asm/io.h>
#include <asm/dma.h>
#include "sl82c105.h"
#undef DEBUG
#ifdef DEBUG
......@@ -481,9 +479,20 @@ static void __init init_hwif_sl82c105(ide_hwif_t *hwif)
#endif /* CONFIG_BLK_DEV_IDEDMA */
}
static ide_pci_device_t sl82c105_chipset __devinitdata = {
.name = "W82C105",
.init_chipset = init_chipset_sl82c105,
.init_hwif = init_hwif_sl82c105,
.init_dma = init_dma_sl82c105,
.channels = 2,
.autodma = NOAUTODMA,
.enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
.bootable = ON_BOARD,
};
static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &sl82c105_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &sl82c105_chipset);
return 0;
}
......
#ifndef W82C105_H
#define W82C105_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
static unsigned int init_chipset_sl82c105(struct pci_dev *, const char *);
static void init_hwif_sl82c105(ide_hwif_t *);
static void init_dma_sl82c105(ide_hwif_t *, unsigned long);
static ide_pci_device_t sl82c105_chipsets[] __devinitdata = {
{ /* 0 */
.name = "W82C105",
.init_chipset = init_chipset_sl82c105,
.init_hwif = init_hwif_sl82c105,
.init_dma = init_dma_sl82c105,
.channels = 2,
.autodma = NOAUTODMA,
.enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
.bootable = ON_BOARD,
}
};
#endif /* W82C105_H */
......@@ -21,7 +21,7 @@
#include <asm/io.h>
#include "slc90e66.h"
#define DISPLAY_SLC90E66_TIMINGS
#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
......@@ -364,9 +364,19 @@ static void __init init_hwif_slc90e66 (ide_hwif_t *hwif)
#endif /* !CONFIG_BLK_DEV_IDEDMA */
}
static ide_pci_device_t slc90e66_chipset __devinitdata = {
.name = "SLC90E66",
.init_chipset = init_chipset_slc90e66,
.init_hwif = init_hwif_slc90e66,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
.bootable = ON_BOARD,
};
static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &slc90e66_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &slc90e66_chipset);
return 0;
}
......
#ifndef SLC90E66_H
#define SLC90E66_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_SLC90E66_TIMINGS
#define SLC90E66_DEBUG_DRIVE_INFO 0
static unsigned int init_chipset_slc90e66(struct pci_dev *, const char *);
static void init_hwif_slc90e66(ide_hwif_t *);
static ide_pci_device_t slc90e66_chipsets[] __devinitdata = {
{ /* 0 */
.name = "SLC90E66",
.init_chipset = init_chipset_slc90e66,
.init_hwif = init_hwif_slc90e66,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}},
.bootable = ON_BOARD,
}
};
#endif /* SLC90E66_H */
......@@ -41,8 +41,6 @@
#include <linux/ide.h>
#include <linux/init.h>
#include "triflex.h"
static struct pci_dev *triflex_dev;
#ifdef CONFIG_PROC_FS
......@@ -217,15 +215,32 @@ static unsigned int __init init_chipset_triflex(struct pci_dev *dev,
return 0;
}
static ide_pci_device_t triflex_device __devinitdata = {
.name = "TRIFLEX",
.init_chipset = init_chipset_triflex,
.init_hwif = init_hwif_triflex,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
.bootable = ON_BOARD,
};
static int __devinit triflex_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &triflex_devices[id->driver_data]);
ide_setup_pci_device(dev, &triflex_device);
triflex_dev = dev;
return 0;
}
static struct pci_device_id triflex_pci_tbl[] = {
{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
static struct pci_driver driver = {
.name = "TRIFLEX IDE",
.id_table = triflex_pci_tbl,
......
/*
* triflex.h
*
* Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
* Author: Torben Mathiasen <torben.mathiasen@hp.com>
*
*/
#ifndef TRIFLEX_H
#define TRIFLEX_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *);
static void init_hwif_triflex(ide_hwif_t *);
static ide_pci_device_t triflex_devices[] __devinitdata = {
{
.name = "TRIFLEX",
.init_chipset = init_chipset_triflex,
.init_hwif = init_hwif_triflex,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
.bootable = ON_BOARD,
}
};
static struct pci_device_id triflex_pci_tbl[] = {
{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
#endif /* TRIFLEX_H */
......@@ -140,8 +140,6 @@
#include <asm/io.h>
#include "trm290.h"
static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
ide_hwif_t *hwif = HWIF(drive);
......@@ -302,7 +300,7 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive)
/*
* Invoked from ide-dma.c at boot time.
*/
void __init init_hwif_trm290 (ide_hwif_t *hwif)
void __devinit init_hwif_trm290(ide_hwif_t *hwif)
{
unsigned int cfgbase = 0;
unsigned long flags;
......@@ -395,9 +393,17 @@ void __init init_hwif_trm290 (ide_hwif_t *hwif)
#endif
}
static ide_pci_device_t trm290_chipset __devinitdata = {
.name = "TRM290",
.init_hwif = init_hwif_trm290,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = ON_BOARD,
};
static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &trm290_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &trm290_chipset);
return 0;
}
......
#ifndef TRM290_H
#define TRM290_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
extern void init_hwif_trm290(ide_hwif_t *);
static ide_pci_device_t trm290_chipsets[] __devinitdata = {
{ /* 0 */
.name = "TRM290",
.init_hwif = init_hwif_trm290,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = ON_BOARD,
}
};
#endif /* TRM290_H */
......@@ -37,7 +37,8 @@
#include <asm/io.h>
#include "ide-timing.h"
#include "via82cxxx.h"
#define DISPLAY_VIA_TIMINGS
#define VIA_IDE_ENABLE 0x40
#define VIA_IDE_CONFIG 0x41
......@@ -607,9 +608,19 @@ static void __init init_hwif_via82cxxx(ide_hwif_t *hwif)
hwif->drives[1].autodma = hwif->autodma;
}
static ide_pci_device_t via82cxxx_chipset __devinitdata = {
.name = "VP_IDE",
.init_chipset = init_chipset_via82cxxx,
.init_hwif = init_hwif_via82cxxx,
.channels = 2,
.autodma = NOAUTODMA,
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
.bootable = ON_BOARD,
};
static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]);
ide_setup_pci_device(dev, &via82cxxx_chipset);
return 0;
}
......
#ifndef VIA82CXXX_H
#define VIA82CXXX_H
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/ide.h>
#define DISPLAY_VIA_TIMINGS
static unsigned int init_chipset_via82cxxx(struct pci_dev *, const char *);
static void init_hwif_via82cxxx(ide_hwif_t *);
static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = {
{ /* 0 */
.name = "VP_IDE",
.init_chipset = init_chipset_via82cxxx,
.init_hwif = init_hwif_via82cxxx,
.channels = 2,
.autodma = NOAUTODMA,
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
.bootable = ON_BOARD,
}
};
#endif /* VIA82CXXX_H */
......@@ -18,17 +18,19 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/amba_kmi.h>
#include <asm/hardware/clock.h>
#define KMI_BASE (kmi->base)
struct amba_kmi_port {
struct serio io;
struct amba_kmi_port *next;
struct clk *clk;
unsigned char *base;
unsigned int irq;
unsigned int divisor;
......@@ -67,21 +69,38 @@ static int amba_kmi_write(struct serio *io, unsigned char val)
static int amba_kmi_open(struct serio *io)
{
struct amba_kmi_port *kmi = io->driver;
unsigned int divisor;
int ret;
writeb(kmi->divisor, KMICLKDIV);
ret = clk_use(kmi->clk);
if (ret)
goto out;
ret = clk_enable(kmi->clk);
if (ret)
goto clk_unuse;
divisor = clk_get_rate(kmi->clk) / 8000000 - 1;
writeb(divisor, KMICLKDIV);
writeb(KMICR_EN, KMICR);
ret = request_irq(kmi->irq, amba_kmi_int, 0, "kmi-pl050", kmi);
if (ret) {
printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
writeb(0, KMICR);
return ret;
goto clk_disable;
}
writeb(KMICR_EN | KMICR_RXINTREN, KMICR);
return 0;
clk_disable:
clk_disable(kmi->clk);
clk_unuse:
clk_unuse(kmi->clk);
out:
return ret;
}
static void amba_kmi_close(struct serio *io)
......@@ -91,6 +110,8 @@ static void amba_kmi_close(struct serio *io)
writeb(0, KMICR);
free_irq(kmi->irq, kmi);
clk_disable(kmi->clk);
clk_unuse(kmi->clk);
}
static int amba_kmi_probe(struct amba_device *dev, void *id)
......@@ -124,14 +145,20 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
goto out;
}
kmi->irq = dev->irq[0];
kmi->divisor = 24 / 8 - 1;
kmi->clk = clk_get(&dev->dev, "KMIREFCLK");
if (IS_ERR(kmi->clk)) {
ret = PTR_ERR(kmi->clk);
goto unmap;
}
kmi->irq = dev->irq[0];
amba_set_drvdata(dev, kmi);
serio_register_port(&kmi->io);
return 0;
unmap:
iounmap(kmi->base);
out:
kfree(kmi);
amba_release_regions(dev);
......@@ -145,6 +172,7 @@ static int amba_kmi_remove(struct amba_device *dev)
amba_set_drvdata(dev, NULL);
serio_unregister_port(&kmi->io);
clk_put(kmi->clk);
iounmap(kmi->base);
kfree(kmi);
amba_release_regions(dev);
......
......@@ -1078,6 +1078,7 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1451A, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1620, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX),
......
......@@ -318,6 +318,13 @@ ide_startstop_t idescsi_atapi_error (ide_drive_t *drive, const char *msg, byte s
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
......@@ -334,6 +341,13 @@ ide_startstop_t idescsi_atapi_abort (ide_drive_t *drive, const char *msg)
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
#if IDESCSI_DEBUG_LOG
printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n",
((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
......
......@@ -437,7 +437,7 @@ static struct pnp_driver serial_pnp_driver = {
.name = "serial",
.id_table = pnp_dev_table,
.probe = serial_pnp_probe,
.remove = serial_pnp_remove,
.remove = __devexit_p(serial_pnp_remove),
};
static int __init serial8250_pnp_init(void)
......
......@@ -44,6 +44,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/clock.h>
#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
......@@ -68,6 +69,7 @@
*/
struct uart_amba_port {
struct uart_port port;
struct clk *clk;
unsigned int im; /* interrupt mask */
unsigned int old_status;
};
......@@ -351,12 +353,21 @@ static int pl011_startup(struct uart_port *port)
unsigned int cr;
int retval;
/*
* Try to enable the clock producer.
*/
retval = clk_enable(uap->clk);
if (retval)
goto out;
uap->port.uartclk = clk_get_rate(uap->clk);
/*
* Allocate the IRQ
*/
retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
if (retval)
goto out;
goto clk_dis;
writew(UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
uap->port.membase + UART011_IFLS);
......@@ -391,6 +402,8 @@ static int pl011_startup(struct uart_port *port)
return 0;
clk_dis:
clk_disable(uap->clk);
out:
return retval;
}
......@@ -425,6 +438,11 @@ static void pl011_shutdown(struct uart_port *port)
val = readw(uap->port.membase + UART011_LCRH);
val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
writew(val, uap->port.membase + UART011_LCRH);
/*
* Shut down the clock producer
*/
clk_disable(uap->clk);
}
static void
......@@ -594,38 +612,40 @@ static struct uart_amba_port *amba_ports[UART_NR];
#ifdef CONFIG_SERIAL_AMBA_PL011_CONSOLE
static inline void
pl011_console_write_char(struct uart_port *port, char ch)
pl011_console_write_char(struct uart_amba_port *uap, char ch)
{
unsigned int status;
do {
status = readw(port->membase + UART01x_FR);
status = readw(uap->port.membase + UART01x_FR);
} while (status & UART01x_FR_TXFF);
writew(ch, port->membase + UART01x_DR);
writew(ch, uap->port.membase + UART01x_DR);
}
static void
pl011_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_port *port = &amba_ports[co->index]->port;
struct uart_amba_port *uap = amba_ports[co->index];
unsigned int status, old_cr, new_cr;
int i;
clk_enable(uap->clk);
/*
* First save the CR then disable the interrupts
*/
old_cr = readw(port->membase + UART011_CR);
old_cr = readw(uap->port.membase + UART011_CR);
new_cr = old_cr & ~UART011_CR_CTSEN;
new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
writew(new_cr, port->membase + UART011_CR);
writew(new_cr, uap->port.membase + UART011_CR);
/*
* Now, do each character
*/
for (i = 0; i < count; i++) {
pl011_console_write_char(port, s[i]);
pl011_console_write_char(uap, s[i]);
if (s[i] == '\n')
pl011_console_write_char(port, '\r');
pl011_console_write_char(uap, '\r');
}
/*
......@@ -633,19 +653,21 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
* and restore the TCR
*/
do {
status = readw(port->membase + UART01x_FR);
status = readw(uap->port.membase + UART01x_FR);
} while (status & UART01x_FR_BUSY);
writew(old_cr, port->membase + UART011_CR);
writew(old_cr, uap->port.membase + UART011_CR);
clk_disable(uap->clk);
}
static void __init
pl011_console_get_options(struct uart_port *port, int *baud,
pl011_console_get_options(struct uart_amba_port *uap, int *baud,
int *parity, int *bits)
{
if (readw(port->membase + UART011_CR) & UART01x_CR_UARTEN) {
if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
unsigned int lcr_h, ibrd, fbrd;
lcr_h = readw(port->membase + UART011_LCRH);
lcr_h = readw(uap->port.membase + UART011_LCRH);
*parity = 'n';
if (lcr_h & UART01x_LCRH_PEN) {
......@@ -660,10 +682,10 @@ pl011_console_get_options(struct uart_port *port, int *baud,
else
*bits = 8;
ibrd = readw(port->membase + UART011_IBRD);
fbrd = readw(port->membase + UART011_FBRD);
ibrd = readw(uap->port.membase + UART011_IBRD);
fbrd = readw(uap->port.membase + UART011_FBRD);
*baud = port->uartclk * 4 / (64 * ibrd + fbrd);
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
}
}
......@@ -685,10 +707,12 @@ static int __init pl011_console_setup(struct console *co, char *options)
co->index = 0;
uap = amba_ports[co->index];
uap->port.uartclk = clk_get_rate(uap->clk);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
pl011_console_get_options(&uap->port, &baud, &parity, &bits);
pl011_console_get_options(uap, &baud, &parity, &bits);
return uart_set_options(&uap->port, co, baud, parity, bits, flow);
}
......@@ -747,16 +771,21 @@ static int pl011_probe(struct amba_device *dev, void *id)
}
memset(uap, 0, sizeof(struct uart_amba_port));
uap->clk = clk_get(&dev->dev, "UARTCLK");
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
goto unmap;
}
ret = clk_use(uap->clk);
if (ret)
goto putclk;
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;
uap->port.iotype = UPIO_MEM;
uap->port.irq = dev->irq[0];
#if 0 /* FIXME */
uap->port.uartclk = 14745600;
#else
uap->port.uartclk = 24000000;
#endif
uap->port.fifosize = 16;
uap->port.ops = &amba_pl011_pops;
uap->port.flags = UPF_BOOT_AUTOCONF;
......@@ -769,6 +798,10 @@ static int pl011_probe(struct amba_device *dev, void *id)
if (ret) {
amba_set_drvdata(dev, NULL);
amba_ports[i] = NULL;
clk_unuse(uap->clk);
putclk:
clk_put(uap->clk);
unmap:
iounmap(base);
free:
kfree(uap);
......@@ -791,6 +824,8 @@ static int pl011_remove(struct amba_device *dev)
amba_ports[i] = NULL;
iounmap(uap->port.membase);
clk_unuse(uap->clk);
clk_put(uap->clk);
kfree(uap);
return 0;
}
......
This diff is collapsed.
Version 1.18
------------
Do not rename hardlinked files (since that should be a noop). Flush
cached write behind data when reopening a file after session abend,
except when already in write. Grab per socket sem during reconnect
to avoid oops in sendmsg if overlapping with reconnect.
Version 1.17
------------
Update number of blocks in file so du command is happier (in Linux a fake
......
......@@ -97,7 +97,9 @@ Linux:
case sensitive = yes
delete readonly = yes
ea support = yes
Note that ea support is required for supporting Linux xattrs.
Some administrators also change the "map archive" and the "create mask"
parameters from their default values. Creating special devices (mknod) remotely
may require specifying a mkdev function to Samba. For more information on these
......@@ -268,11 +270,12 @@ Misc /proc/fs/cifs Flags and Debug Info
=======================================
Informational pseudo-files:
DebugData Displays information about active CIFS sessions
as well as per share statistics (if CONFIG_CIFS_STATS
is enabled in the kernel configuration).
and shares.
SimultaneousOps Counter which holds maximum number of
simultaneous outstanding SMB/CIFS requests.
Stats Lists summary resource usage information
Stats Lists summary resource usage information as well as per
share statistics, if CONFIG_CIFS_STATS in enabled
in the kernel configuration.
Configuration pseudo-files:
MultiuserMount If set to one, more than one CIFS session to
......
......@@ -80,27 +80,13 @@ symlink text beginning with slash
but recognizes them
3) create of new files to FAT partitions on Windows servers can
succeed but still return access denied (appears to be Windows
not client problem) and has not been reproduced recently.
server not cifs client problem) and has not been reproduced recently.
NTFS partitions do not have this problem.
4) debug connectation lock test case 10 which fails against
Samba (may be unmappable due to POSIX to Windows lock model
differences but worth investigating). Also debug Samba to
see why lock test case 7 takes longer to complete to Samba
than to Windows.
5) prepare_write does not initialize pages properly when partial
page writes begin in the middle of a page (pages can get zeroed).
6) Write caching done incorrectly when files are only opened
with write permission by the application.
7) Rename of files that are hardlinked does not work correctly e.g.
ln source target
mv source target
This should be no op since files are linked but in cifs it causes
the source file to go away. This may require implementation of
the cifs POSIX extensions (Unix Extensions version 2) for
it to be done correctly since Samba is failing the rename,
(rather than ignoring it) so the client not knowing they
are linked proceeds to delete the target and then retry the
move which succeeds this time (but the source is gone).
Misc testing to do
==================
......
......@@ -190,26 +190,26 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
struct cifsTconInfo *tcon;
length = sprintf(buf,
"Currently Allocated structures\nCIFS Sessions: %d\n",
"Resources in use\nCIFS Session: %d\n",
sesInfoAllocCount.counter);
buf += length;
item_length =
sprintf(buf,"Shares (unique mount targets): %d\n",
sprintf(buf,"Share (unique mount targets): %d\n",
tconInfoAllocCount.counter);
length += item_length;
buf += item_length;
item_length =
sprintf(buf,"Allocated SMB Request/Response Buffers: %d\n",
sprintf(buf,"SMB Request/Response Buffer: %d\n",
bufAllocCount.counter);
length += item_length;
buf += item_length;
item_length =
sprintf(buf,"Active Operations (MIDs in use): %d\n",
sprintf(buf,"Operations (MIDs): %d\n",
midCount.counter);
length += item_length;
buf += item_length;
item_length = sprintf(buf,
"%d sessions and %d shares reconnected after failure\n",
"\n%d session %d share reconnects\n",
tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
length += item_length;
buf += item_length;
......@@ -400,7 +400,7 @@ cifsFYI_read(char *page, char **start, off_t off, int count,
return len;
}
static int
cifsFYI_write(struct file *file, const char *buffer,
cifsFYI_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -439,7 +439,7 @@ oplockEnabled_read(char *page, char **start, off_t off,
return len;
}
static int
oplockEnabled_write(struct file *file, const char *buffer,
oplockEnabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -479,7 +479,7 @@ quotaEnabled_read(char *page, char **start, off_t off,
return len;
}
static int
quotaEnabled_write(struct file *file, const char *buffer,
quotaEnabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -519,7 +519,7 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
return len;
}
static int
linuxExtensionsEnabled_write(struct file *file, const char *buffer,
linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -559,7 +559,7 @@ lookupFlag_read(char *page, char **start, off_t off,
return len;
}
static int
lookupFlag_write(struct file *file, const char *buffer,
lookupFlag_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -597,7 +597,7 @@ traceSMB_read(char *page, char **start, off_t off, int count,
return len;
}
static int
traceSMB_write(struct file *file, const char *buffer,
traceSMB_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -636,7 +636,7 @@ multiuser_mount_read(char *page, char **start, off_t off,
return len;
}
static int
multiuser_mount_write(struct file *file, const char *buffer,
multiuser_mount_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -675,7 +675,7 @@ extended_security_read(char *page, char **start, off_t off,
return len;
}
static int
extended_security_write(struct file *file, const char *buffer,
extended_security_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -714,7 +714,7 @@ ntlmv2_enabled_read(char *page, char **start, off_t off,
return len;
}
static int
ntlmv2_enabled_write(struct file *file, const char *buffer,
ntlmv2_enabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......@@ -753,7 +753,7 @@ packet_signing_enabled_read(char *page, char **start, off_t off,
return len;
}
static int
packet_signing_enabled_write(struct file *file, const char *buffer,
packet_signing_enabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char c;
......
......@@ -426,7 +426,7 @@ cifs_get_sb(struct file_system_type *fs_type,
}
static ssize_t
cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
loff_t * poffset)
{
if(file == NULL)
......@@ -455,7 +455,7 @@ cifs_read_wrapper(struct file * file, char *read_data, size_t read_size,
}
static ssize_t
cifs_write_wrapper(struct file * file, const char *write_data,
cifs_write_wrapper(struct file * file, const char __user *write_data,
size_t write_size, loff_t * poffset)
{
ssize_t written;
......
......@@ -85,7 +85,7 @@ extern struct dentry_operations cifs_dentry_ops;
/* Functions related to symlinks */
extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname);
extern int cifs_removexattr(struct dentry *, const char *);
......@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#define CIFS_VERSION "1.17"
#define CIFS_VERSION "1.18"
#endif /* _CIFSFS_H */
......@@ -1046,9 +1046,12 @@ typedef union smb_com_transaction2 {
/* PathInfo/FileInfo infolevels */
#define SMB_INFO_STANDARD 1
#define SMB_INFO_QUERY_EAS_FROM_LIST 3
#define SMB_INFO_QUERY_ALL_EAS 4
#define SMB_INFO_IS_NAME_VALID 6
#define SMB_QUERY_FILE_BASIC_INFO 0x101
#define SMB_QUERY_FILE_STANDARD_INFO 0x102
#define SMB_QUERY_FILE_EA_INFO 0x103
#define SMB_QUERY_FILE_NAME_INFO 0x104
#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
......@@ -1687,16 +1690,17 @@ struct gealist {
};
struct fea {
unsigned char fEA;
unsigned char cbName;
unsigned short cbValue;
unsigned char EA_flags;
__u8 name_len;
__u16 value_len;
char szName[1];
/* optionally followed by value */
};
/* flags for _FEA.fEA */
#define FEA_NEEDEA 0x80 /* need EA bit */
struct fealist {
unsigned long cbList;
__u32 list_len;
struct fea list[1];
};
......
......@@ -247,4 +247,8 @@ extern int CIFSSMBCopy(int xid,
extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
const int notify_subdirs,const __u16 netfid,__u32 filter,
const struct nls_table *nls_codepage);
extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char * EAData, size_t size,
const struct nls_table *nls_codepage);
#endif /* _CIFSPROTO_H */
......@@ -1596,6 +1596,8 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
/* BB also check enough total bytes returned */
/* BB we need to improve the validity checking
of these trans2 responses */
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
rc = -EIO; /* bad smb */
else if (pFindData){
......@@ -2879,3 +2881,101 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
goto NotifyRetry; */
return rc;
}
#ifdef CONFIG_CIFS_XATTR
int
CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char * EAData, size_t size,
const struct nls_table *nls_codepage)
{
/* BB assumes one setup word */
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0;
int bytes_returned;
int name_len;
cFYI(1, ("In Query All EAs path %s", searchName));
QAllEAsRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
name_len /* includes null */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = cpu_to_le16(offsetof(
struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += pSMB->ByteCount;
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in QueryAllEAs = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
/* BB also check enough total bytes returned */
/* BB we need to improve the validity checking
of these trans2 responses */
if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
rc = -EIO; /* bad smb */
/* else if (pFindData){
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
pSMBr->DataOffset, kl);
}*/ else {
/* check that length of list is not more than bcc */
/* check that each entry does not go beyond length
of list */
/* check that each element of each entry does not
go beyond end of list */
struct fealist * ea_response_data;
rc = 0;
/* validate_trans2_offsets() */
/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
ea_response_data = (struct fealist *)
(((char *) &pSMBr->hdr.Protocol) +
pSMBr->DataOffset);
cFYI(1,("ea length %d",ea_response_data->list_len));
}
}
if (pSMB)
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto QAllEAsRetry;
return rc;
}
#endif
......@@ -128,7 +128,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
}
read_unlock(&GlobalSMBSeslock);
/* do not want to be sending data on a socket we are freeing */
down(&server->tcpSem);
if(server->ssocket) {
cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
server->ssocket->flags));
......@@ -154,7 +155,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
}
spin_unlock(&GlobalMid_Lock);
up(&server->tcpSem);
while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
{
......@@ -279,7 +280,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
length = sock_recvmsg(csocket, &smb_msg, 4, 0);
cFYI(0,("Received 4 byte keep alive packet"));
} else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
iov.iov_base = smb_buffer;
iov.iov_base = smb_buffer;
iov.iov_len = 4;
length = sock_recvmsg(csocket, &smb_msg, 4, 0);
cFYI(1,("Good RFC 1002 session rsp"));
......@@ -1559,7 +1560,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr +=
pSMBr->resp.SecurityBlobLength;
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
(BCC(smb_buffer_response)
......@@ -1812,7 +1813,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
pSMBr->resp.SecurityBlobLength));
}
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
(BCC(smb_buffer_response)
......@@ -2123,7 +2124,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
ses->server->secMode |=
SECMODE_SIGN_ENABLED;
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
(BCC(smb_buffer_response)
......@@ -2519,7 +2520,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
cFYI(1,
("NTLMSSP response to Authenticate "));
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
remaining_words =
(BCC(smb_buffer_response)
......@@ -2718,7 +2719,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
/* skip service field (NB: this field is always ASCII) */
bcc_ptr += length + 1;
strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
length = UniStrnlen((wchar_t *) bcc_ptr, 512);
if (((long) bcc_ptr + (2 * length)) -
(long) pByteArea(smb_buffer_response) <=
......
......@@ -143,6 +143,10 @@ cifs_open(struct inode *inode, struct file *file)
/* Also refresh inode by passing in file_info buf returned by SMBOpen
and calling get_inode_info with returned buf (at least
helps non-Unix server case */
/* BB we can not do this if this is the second open of a file
and the first handle has writebehind data, we might be
able to simply do a filemap_fdatawrite/filemap_fdatawait first */
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
if(buf==0) {
if (full_path)
......@@ -263,7 +267,7 @@ static int cifs_relock_file(struct cifsFileInfo * cifsFile)
return rc;
}
static int cifs_reopen_file(struct inode *inode, struct file *file)
static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
{
int rc = -EACCES;
int xid, oplock;
......@@ -275,7 +279,6 @@ static int cifs_reopen_file(struct inode *inode, struct file *file)
int desiredAccess = 0x20197;
int disposition = FILE_OPEN;
__u16 netfid;
FILE_ALL_INFO * buf = NULL;
if(inode == NULL)
return -EBADF;
......@@ -328,21 +331,23 @@ and we can never tell if the caller already has the rename_sem */
else
oplock = FALSE;
/* BB pass O_SYNC flag through on file attributes .. BB */
/* Can not refresh inode by passing in file_info buf to be returned
by SMBOpen and then calling get_inode_info with returned buf
since file might have write behind data that needs to be flushed
and server version of file size can be stale. If we
knew for sure that inode was not dirty locally we could do this */
/* Also refresh inode by passing in file_info buf returned by SMBOpen
and calling get_inode_info with returned buf (at least
helps non-Unix server case */
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
if(buf==0) {
up(&pCifsFile->fh_sem);
if (full_path)
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
}*/
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
if (rc) {
up(&pCifsFile->fh_sem);
cFYI(1, ("cifs_open returned 0x%x ", rc));
......@@ -353,13 +358,25 @@ and we can never tell if the caller already has the rename_sem */
up(&pCifsFile->fh_sem);
pCifsInode = CIFS_I(inode);
if(pCifsInode) {
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&inode,
if(can_flush) {
filemap_fdatawrite(inode->i_mapping);
filemap_fdatawait(inode->i_mapping);
/* temporarily disable caching while we
go to server to get inode info */
pCifsInode->clientCanCacheAll = FALSE;
pCifsInode->clientCanCacheRead = FALSE;
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&inode,
full_path, inode->i_sb);
else
rc = cifs_get_inode_info(&inode,
full_path, buf, inode->i_sb);
else
rc = cifs_get_inode_info(&inode,
full_path, NULL, inode->i_sb);
} /* else we are writing out data to server already
and could deadlock if we tried to flush data, and
since we do not know if we have data that would
invalidate the current end of file on the server
we can not go to the server to get the new
inod info */
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
......@@ -375,8 +392,6 @@ and we can never tell if the caller already has the rename_sem */
}
}
if (buf)
kfree(buf);
if (full_path)
kfree(full_path);
FreeXid(xid);
......@@ -612,7 +627,11 @@ cifs_write(struct file * file, const char *write_data,
FreeXid(xid);
return total_written;
}
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
/* we could deadlock if we called
filemap_fdatawait from here so tell
reopen_file not to flush data to server now */
rc = cifs_reopen_file(file->f_dentry->d_inode,
file,FALSE);
if(rc != 0)
break;
}
......@@ -829,7 +848,7 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset,
cFYI(1,(" SetEOF (commit write) rc = %d",rc));
}*/
}
if (!PageUptodate(page)) {
if (!PageUptodate(page)) {
position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
/* can not rely on (or let) writepage write this data */
if(to < offset) {
......@@ -968,7 +987,8 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
rc = -EAGAIN;
while(rc == -EAGAIN) {
if ((open_file->invalidHandle) && (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
rc = cifs_reopen_file(file->f_dentry->d_inode,
file,TRUE);
if(rc != 0)
break;
}
......@@ -1123,7 +1143,8 @@ cifs_readpages(struct file *file, struct address_space *mapping,
rc = -EAGAIN;
while(rc == -EAGAIN) {
if ((open_file->invalidHandle) && (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,file);
rc = cifs_reopen_file(file->f_dentry->d_inode,
file, TRUE);
if(rc != 0)
break;
}
......@@ -1263,6 +1284,49 @@ cifs_readpage(struct file *file, struct page *page)
return rc;
}
/* We do not want to update the file size from server for inodes
open for write - to avoid races with writepage extending
the file - in the future we could consider allowing
refreshing the inode only on increases in the file size
but this is tricky to do without racing with writebehind
page caching in the current Linux kernel design */
int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
{
struct list_head *tmp;
struct list_head *tmp1;
struct cifsFileInfo *open_file = NULL;
int rc = TRUE;
if(cifsInode == NULL)
return rc;
read_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
open_file = list_entry(tmp,struct cifsFileInfo, flist);
if(open_file == NULL)
break;
if(open_file->closePend)
continue;
/* We check if file is open for writing,
BB we could supplement this with a check to see if file size
changes have been flushed to server - ie inode metadata dirty */
if((open_file->pfile) &&
((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) {
rc = FALSE;
break;
}
if(tmp->next == NULL) {
cFYI(1,("File instance %p removed",tmp));
break;
}
}
read_unlock(&GlobalSMBSeslock);
return rc;
}
void
fill_in_inode(struct inode *tmp_inode,
FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
......@@ -1322,11 +1386,15 @@ fill_in_inode(struct inode *tmp_inode,
atomic_set(&cifsInfo->inUse,1);
}
i_size_write(tmp_inode,pfindData->EndOfFile);
if(is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write(tmp_inode,pfindData->EndOfFile);
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, even though the reported blocksize is larger */
tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
}
if (pfindData->AllocationSize < pfindData->EndOfFile)
cFYI(1, ("Possible sparse file: allocation size less than end of file "));
......@@ -1398,12 +1466,17 @@ unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
i_size_write(tmp_inode,pfindData->EndOfFile);
if(is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
i_size_write(tmp_inode,pfindData->EndOfFile);
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation, not the real blocksize */
tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
}
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, ("File inode"));
......@@ -1547,9 +1620,9 @@ cifs_filldir_unix(struct qstr *pqstring,
pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
return -ENOMEM;
}
if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
return -ENOMEM;
}
unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
......
......@@ -30,6 +30,8 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
extern int is_size_safe_to_change(struct cifsInodeInfo *);
int
cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
......@@ -43,9 +45,6 @@ cifs_get_inode_info_unix(struct inode **pinode,
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
char *tmp_path;
/* BB add caching check so we do not go to server to overwrite inode info to cached file
where the local file sizes are correct and the server info is stale BB */
xid = GetXid();
pTcon = cifs_sb->tcon;
......@@ -125,7 +124,12 @@ cifs_get_inode_info_unix(struct inode **pinode,
inode->i_nlink = le64_to_cpu(findData.Nlinks);
findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
i_size_write(inode,findData.EndOfFile);
if(is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write(inode,findData.EndOfFile);
/* blksize needs to be multiple of two. So safer to default to blksize
and blkbits set in superblock so 2**blkbits and blksize will match */
/* inode->i_blksize =
......@@ -141,7 +145,8 @@ cifs_get_inode_info_unix(struct inode **pinode,
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
}
if (findData.NumOfBytes < findData.EndOfFile)
cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
......@@ -283,12 +288,18 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
inode->i_mode &= ~(S_IWUGO);
/* BB add code here - validate if device or weird share or device type? */
}
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
if(is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
>> 9;
}
pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
......@@ -568,9 +579,38 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls);
if(rc == -EEXIST) {
cifs_unlink(target_inode, target_direntry);
rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls);
/* check if they are the same file
because rename of hardlinked files is a noop */
FILE_UNIX_BASIC_INFO * info_buf_source;
FILE_UNIX_BASIC_INFO * info_buf_target;
info_buf_source =
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
if(info_buf_source != NULL) {
info_buf_target = info_buf_source+1;
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
info_buf_source, cifs_sb_source->local_nls);
if(rc == 0) {
rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
info_buf_target,
cifs_sb_target->local_nls);
}
if((rc == 0) &&
(info_buf_source->UniqueId ==
info_buf_target->UniqueId)) {
/* do not rename since the files are hardlinked
which is a noop */
} else {
/* we either can not tell the files are hardlinked
(as with Windows servers) or files are not hardlinked
so delete the target manually before renaming to
follow POSIX rather than Windows semantics */
cifs_unlink(target_inode, target_direntry);
rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls);
}
kfree(info_buf_source);
} /* if we can not get memory just leave rc as EEXIST */
}
if((rc == -EIO)||(rc == -EEXIST)) {
......
......@@ -210,7 +210,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
}
int
cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
{
struct inode *inode = direntry->d_inode;
int rc = -EACCES;
......
......@@ -120,6 +120,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
unsigned int smb_buf_length, struct sockaddr *sin)
{
int rc = 0;
int i = 0;
struct msghdr smb_msg;
struct iovec iov;
mm_segment_t temp_fs;
......@@ -151,6 +152,14 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
while(iov.iov_len > 0) {
rc = sock_sendmsg(ssocket, &smb_msg, smb_buf_length + 4);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++;
if(i > 60) {
cERROR(1,
("sends on sock %p stuck for 30 seconds",
ssocket));
rc = -EAGAIN;
break;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/2);
continue;
......@@ -259,7 +268,17 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
midQ->midState = MID_REQUEST_SUBMITTED;
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
(struct sockaddr *) &(ses->server->addr.sockAddr));
up(&ses->server->tcpSem);
if(rc < 0) {
DeleteMidQEntry(midQ);
up(&ses->server->tcpSem);
/* If not lock req, update # of requests on wire to server */
if(long_op < 3) {
atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q);
}
return rc;
} else
up(&ses->server->tcpSem);
if (long_op == -1)
goto cifs_no_response_exit;
else if (long_op == 2) /* writes past end of file can take looooong time */
......
......@@ -20,37 +20,68 @@
*/
#include <linux/fs.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
int cifs_removexattr(struct dentry * direntry, const char * name)
{
int rc = -EOPNOTSUPP;
return rc;
int rc = -EOPNOTSUPP;
return rc;
}
int cifs_setxattr(struct dentry * direntry, const char * name,
const void * value, size_t size, int flags)
{
int rc = -EOPNOTSUPP;
return rc;
int rc = -EOPNOTSUPP;
return rc;
}
ssize_t cifs_getxattr(struct dentry * direntry, const char * name,
void * value, size_t size)
{
ssize_t rc = -EOPNOTSUPP;
return rc;
ssize_t rc = -EOPNOTSUPP;
return rc;
}
ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
{
ssize_t rc = -EOPNOTSUPP;
ssize_t rc = -EOPNOTSUPP;
#ifdef CONFIG_CIFS_XATTR
int xid;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct super_block * sb;
char * full_path;
if(direntry == NULL)
return -EIO;
if(direntry->d_inode == NULL)
return -EIO;
sb = direntry->d_inode->i_sb;
if(sb == NULL)
return -EIO;
xid = GetXid();
cifs_sb = CIFS_SB(sb);
pTcon = cifs_sb->tcon;
down(&sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
up(&sb->s_vfs_rename_sem);
if(full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
/* return dosattributes as pseudo xattr */
/* return alt name if available as pseudo attr */
/* if proc/fs/cifs/streamstoxattr is set then
search server for EAs or streams to
returns as xattrs */
return rc;
rc = CIFSSMBQAllEAs(xid,pTcon,full_path,ea_data,ea_size,cifs_sb->local_nls);
FreeXid(xid);
#endif
return rc;
}
......@@ -14,6 +14,5 @@
struct device;
void impd1_set_vco(struct device *dev, int vconr, unsigned long period);
void impd1_tweak_control(struct device *dev, u32 mask, u32 val);
......@@ -6,14 +6,14 @@
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*
* Refer to <file:Documentation/arm/Sharp-LH/SDRAM> for more information.
*
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
#define BANKS_PER_NODE 1 /* Define as either 1 or 2 */
/*
* Physical DRAM offset.
*/
......@@ -30,57 +30,30 @@
#define __bus_to_virt(x) __phys_to_virt(x)
#ifdef CONFIG_DISCONTIGMEM
/*
* Because of the wide memory address space between physical RAM
* banks, it's convenient to use Linux's NUMA support to represent our
* memory map. Assuming all memory nodes have equal access
* characteristics, we then have a generic discontiguous memory setup.
*
* Of course, all this isn't mandatory for implementations with only
* one used memory bank. For those, simply undefine
* CONFIG_DISCONTIGMEM. However, keep in mind that a featurefull
* system will need more than 4MiB of RAM.
*
* The contiguous memory blocks are small enough that it pays to
* aggregate two banks into one node. Setting BANKS_PER_NODE to 2
* puts pairs of banks into a node.
*
* A typical layout would start like this:
*
* node 0: 0xc0000000
* 0xc1000000
* node 1: 0xc4000000
* 0xc5000000
* node 2: 0xc8000000
* 0xc9000000
*
* The proximity of the pairs of blocks makes it feasible to combine them.
*
*/
/*
* Given a kernel address, find the home node of the underlying memory.
*/
#if BANKS_PER_NODE==1
#define KVADDR_TO_NID(addr) \
# ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
# define KVADDR_TO_NID(addr) \
( ((((unsigned long) (addr) - PAGE_OFFSET) >> 24) & 1)\
| ((((unsigned long) (addr) - PAGE_OFFSET) >> 25) & ~1))
#else /* 2 banks per node */
#define KVADDR_TO_NID(addr) \
((unsigned long) (addr) - PAGE_OFFSET) >> 26)
#endif
# else /* 2 banks per node */
# define KVADDR_TO_NID(addr) \
(((unsigned long) (addr) - PAGE_OFFSET) >> 26)
# endif
/*
* Given a page frame number, convert it to a node id.
*/
#if BANKS_PER_NODE==1
#define PFN_TO_NID(pfn) \
# ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
# define PFN_TO_NID(pfn) \
(((((pfn) - PHYS_PFN_OFFSET) >> (24 - PAGE_SHIFT)) & 1)\
| ((((pfn) - PHYS_PFN_OFFSET) >> (25 - PAGE_SHIFT)) & ~1))
#else /* 2 banks per node */
#define PFN_TO_NID(addr) \
# else /* 2 banks per node */
# define PFN_TO_NID(pfn) \
(((pfn) - PHYS_PFN_OFFSET) >> (26 - PAGE_SHIFT))
#endif
......@@ -88,13 +61,13 @@
* Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
* and return the mem_map of that node.
*/
#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
# define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
/*
* Given a page frame number, find the owning node of the memory
* and return the mem_map of that node.
*/
#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
# define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
/*
* Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
......@@ -102,17 +75,17 @@
* node's mem_map.
*/
#if BANKS_PER_NODE==1
#define LOCAL_MAP_NR(addr) \
# ifdef CONFIG_LH7A40X_ONE_BANK_PER_NODE
# define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x003fffff) >> PAGE_SHIFT)
#else /* 2 banks per node */
#define LOCAL_MAP_NR(addr) \
# else /* 2 banks per node */
# define LOCAL_MAP_NR(addr) \
(((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT)
#endif
# endif
#else
#define PFN_TO_NID(addr) (0)
# define PFN_TO_NID(addr) (0)
#endif
......
/*
* linux/include/asm-arm/hardware/clock.h
*
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
*
* 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 ASMARM_CLOCK_H
#define ASMARM_CLOCK_H
struct device;
/*
* The base API.
*/
/*
* struct clk - an machine class defined object / cookie.
*/
struct clk;
/**
* clk_get - lookup and obtain a reference to a clock producer.
* @dev: device for clock "consumer"
* @id: device ID
*
* Returns a struct clk corresponding to the clock producer, or
* valid IS_ERR() condition containing errno.
*/
struct clk *clk_get(struct device *dev, const char *id);
/**
* clk_enable - inform the system when the clock source should be running.
* @clk: clock source
*
* If the clock can not be enabled/disabled, this should return success.
*
* Returns success (0) or negative errno.
*/
int clk_enable(struct clk *clk);
/**
* clk_disable - inform the system when the clock source is no longer required.
* @clk: clock source
*/
void clk_disable(struct clk *clk);
/**
* clk_use - increment the use count
* @clk: clock source
*
* Returns success (0) or negative errno.
*/
int clk_use(struct clk *clk);
/**
* clk_unuse - decrement the use count
* @clk: clock source
*/
void clk_unuse(struct clk *clk);
/**
* clk_get_rate - obtain the current clock rate for a clock source.
* This is only valid once the clock source has been enabled.
* @clk: clock source
*/
unsigned long clk_get_rate(struct clk *clk);
/**
* clk_put - "free" the clock source
* @clk: clock source
*/
void clk_put(struct clk *clk);
/*
* The remaining APIs are optional for machine class support.
*/
/**
* clk_round_rate - adjust a rate to the exact rate a clock can provide
* @clk: clock source
* @rate: desired clock rate in kHz
*
* Returns rounded clock rate, or negative errno.
*/
long clk_round_rate(struct clk *clk, unsigned long rate);
/**
* clk_set_rate - set the clock rate for a clock source
* @clk: clock source
* @rate: desired clock rate in kHz
*
* Returns success (0) or negative errno.
*/
int clk_set_rate(struct clk *clk, unsigned long rate);
/**
* clk_set_parent - set the parent clock source for this clock
* @clk: clock source
* @parent: parent clock source
*
* Returns success (0) or negative errno.
*/
int clk_set_parent(struct clk *clk, struct clk *parent);
/**
* clk_get_parent - get the parent clock source for this clock
* @clk: clock source
*
* Returns struct clk corresponding to parent clock source, or
* valid IS_ERR() condition containing errno.
*/
struct clk *clk_get_parent(struct clk *clk);
#endif
......@@ -730,6 +730,7 @@
#define PCI_DEVICE_ID_TI_1410 0xac50
#define PCI_DEVICE_ID_TI_1420 0xac51
#define PCI_DEVICE_ID_TI_1451A 0xac52
#define PCI_DEVICE_ID_TI_1620 0xac54
#define PCI_DEVICE_ID_TI_1520 0xac55
#define PCI_DEVICE_ID_TI_1510 0xac56
......
......@@ -332,8 +332,8 @@ int insert_resource(struct resource *parent, struct resource *new)
if (next->sibling->start > new->end)
break;
/* existing resource overlaps end of new resource */
if (next->end > new->end) {
/* existing resource includes new resource */
if (next->end >= new->end) {
parent = next;
result = 0;
goto begin;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment