Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
[CRYPTO] geode: Fix not inplace encryption
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index ab82b7f..d6cb1a8 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -25,6 +25,7 @@
#include <linux/genetlink.h>
#include <linux/taskstats.h>
+#include <linux/cgroupstats.h>
/*
* Generic macros for dealing with netlink sockets. Might be duplicated
@@ -78,6 +79,7 @@
fprintf(stderr, " -i: print IO accounting (works only with -p)\n");
fprintf(stderr, " -l: listen forever\n");
fprintf(stderr, " -v: debug on\n");
+ fprintf(stderr, " -C: container path\n");
}
/*
@@ -212,6 +214,14 @@
t->nvcsw, t->nivcsw);
}
+void print_cgroupstats(struct cgroupstats *c)
+{
+ printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
+ "uninterruptible %llu\n", c->nr_sleeping, c->nr_io_wait,
+ c->nr_running, c->nr_stopped, c->nr_uninterruptible);
+}
+
+
void print_ioacct(struct taskstats *t)
{
printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
@@ -239,11 +249,14 @@
int maskset = 0;
char *logfile = NULL;
int loop = 0;
+ int containerset = 0;
+ char containerpath[1024];
+ int cfd = 0;
struct msgtemplate msg;
while (1) {
- c = getopt(argc, argv, "qdiw:r:m:t:p:vl");
+ c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:");
if (c < 0)
break;
@@ -260,6 +273,10 @@
printf("printing task/process context switch rates\n");
print_task_context_switch_counts = 1;
break;
+ case 'C':
+ containerset = 1;
+ strncpy(containerpath, optarg, strlen(optarg) + 1);
+ break;
case 'w':
logfile = strdup(optarg);
printf("write to file %s\n", logfile);
@@ -334,6 +351,11 @@
}
}
+ if (tid && containerset) {
+ fprintf(stderr, "Select either -t or -C, not both\n");
+ goto err;
+ }
+
if (tid) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
cmd_type, &tid, sizeof(__u32));
@@ -344,6 +366,20 @@
}
}
+ if (containerset) {
+ cfd = open(containerpath, O_RDONLY);
+ if (cfd < 0) {
+ perror("error opening container file");
+ goto err;
+ }
+ rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET,
+ CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32));
+ if (rc < 0) {
+ perror("error sending cgroupstats command");
+ goto err;
+ }
+ }
+
do {
int i;
@@ -422,6 +458,9 @@
}
break;
+ case CGROUPSTATS_TYPE_CGROUP_STATS:
+ print_cgroupstats(NLA_DATA(na));
+ break;
default:
fprintf(stderr, "Unknown nla_type %d\n",
na->nla_type);
@@ -443,5 +482,7 @@
close(nl_sd);
if (fd)
close(fd);
+ if (cfd)
+ close(cfd);
return 0;
}
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 6bb9be5..20c4c8b 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -181,15 +181,6 @@
---------------------------
-What: Interrupt only SA_* flags
-When: September 2007
-Why: The interrupt related SA_* flags are replaced by IRQF_* to move them
- out of the signal namespace.
-
-Who: Thomas Gleixner <tglx@linutronix.de>
-
----------------------------
-
What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
When: October 2008
Why: The stacking of class devices makes these values misleading and
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index a17b692..f4a8ebc 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -328,6 +328,37 @@
Unit: milliampere
RO
+*********
+* Power *
+*********
+
+power[1-*]_average Average power use
+ Unit: microWatt
+ RO
+
+power[1-*]_average_highest Historical average maximum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_average_lowest Historical average minimum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_input Instantaneous power use
+ Unit: microWatt
+ RO
+
+power[1-*]_input_highest Historical maximum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_input_lowest Historical minimum power use
+ Unit: microWatt
+ RO
+
+power[1-*]_reset_history Reset input_highest, input_lowest,
+ average_highest and average_lowest.
+ WO
**********
* Alarms *
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index f266839..4200839 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -62,8 +62,8 @@
#endif
/* We can have up to 256 pages for devices. */
#define DEVICE_PAGES 256
-/* This fits nicely in a single 4096-byte page. */
-#define VIRTQUEUE_NUM 127
+/* This will occupy 2 pages: it must be a power of 2. */
+#define VIRTQUEUE_NUM 128
/*L:120 verbose is both a global flag and a macro. The C preprocessor allows
* this, and although I wouldn't recommend it, it works quite nicely here. */
@@ -1036,7 +1036,8 @@
void *p;
/* First we need some pages for this virtqueue. */
- pages = (vring_size(num_descs) + getpagesize() - 1) / getpagesize();
+ pages = (vring_size(num_descs, getpagesize()) + getpagesize() - 1)
+ / getpagesize();
p = get_pages(pages);
/* Initialize the configuration. */
@@ -1045,7 +1046,7 @@
vq->config.pfn = to_guest_phys(p) / getpagesize();
/* Initialize the vring. */
- vring_init(&vq->vring, num_descs, p);
+ vring_init(&vq->vring, num_descs, p, getpagesize());
/* Add the configuration information to this device's descriptor. */
add_desc_field(dev, VIRTIO_CONFIG_F_VIRTQUEUE,
@@ -1342,7 +1343,7 @@
if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
fprintf(stderr, "Scsi commands unsupported\n");
in->status = VIRTIO_BLK_S_UNSUPP;
- wlen = sizeof(in);
+ wlen = sizeof(*in);
} else if (out->type & VIRTIO_BLK_T_OUT) {
/* Write */
@@ -1363,7 +1364,7 @@
/* Die, bad Guest, die. */
errx(1, "Write past end %llu+%u", off, ret);
}
- wlen = sizeof(in);
+ wlen = sizeof(*in);
in->status = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
} else {
/* Read */
@@ -1376,10 +1377,10 @@
ret = readv(vblk->fd, iov+1, in_num-1);
verbose("READ from sector %llu: %i\n", out->sector, ret);
if (ret >= 0) {
- wlen = sizeof(in) + ret;
+ wlen = sizeof(*in) + ret;
in->status = VIRTIO_BLK_S_OK;
} else {
- wlen = sizeof(in);
+ wlen = sizeof(*in);
in->status = VIRTIO_BLK_S_IOERR;
}
}
diff --git a/Documentation/markers.txt b/Documentation/markers.txt
index 295a71b..d9f50a1 100644
--- a/Documentation/markers.txt
+++ b/Documentation/markers.txt
@@ -35,12 +35,14 @@
And,
-trace_mark(subsystem_event, "%d %s", someint, somestring);
+trace_mark(subsystem_event, "myint %d mystring %s", someint, somestring);
Where :
- subsystem_event is an identifier unique to your event
- subsystem is the name of your subsystem.
- event is the name of the event to mark.
-- "%d %s" is the formatted string for the serializer.
+- "myint %d mystring %s" is the formatted string for the serializer. "myint" and
+ "mystring" are repectively the field names associated with the first and
+ second parameter.
- someint is an integer.
- somestring is a char pointer.
diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt
index b9d5b72..72f38b1 100644
--- a/Documentation/networking/3c505.txt
+++ b/Documentation/networking/3c505.txt
@@ -14,8 +14,7 @@
ports 0x300, 0x280 and 0x310 (in that order). If no IRQ is given, the driver
will try to probe for it.
-The driver can be used as a loadable module. See net-modules.txt for details
-of the parameters it can take.
+The driver can be used as a loadable module.
Theoretically, one instance of the driver can now run multiple cards,
in the standard way (when loading a module, say "modprobe 3c505
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index c931d61..e20b19c 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -180,9 +180,10 @@
* RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
to set the frequency while the framework will handle the read for you
since the frequency is stored in the irq_freq member of the rtc_device
- structure. Also make sure you set the max_user_freq member in your
- initialization routines so the framework can sanity check the user
- input for you.
+ structure. Your driver needs to initialize the irq_freq member during
+ init. Make sure you check the requested frequency is in range of your
+ hardware in the irq_set_freq function. If you cannot actually change
+ the frequency, just return -ENOTTY.
If all else fails, check out the rtc-test.c driver!
diff --git a/MAINTAINERS b/MAINTAINERS
index 6a97027..cad0882 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3454,15 +3454,10 @@
S: Maintained
SOFTMAC LAYER (IEEE 802.11)
-P: Johannes Berg
-M: johannes@sipsolutions.net
-P: Joe Jezak
-M: josejx@gentoo.org
P: Daniel Drake
M: dsd@gentoo.org
-W: http://softmac.sipsolutions.net/
L: linux-wireless@vger.kernel.org
-S: Maintained
+S: Obsolete
SOFTWARE RAID (Multiple Disks) SUPPORT
P: Ingo Molnar
diff --git a/Makefile b/Makefile
index e28dde8..9c9c4bf 100644
--- a/Makefile
+++ b/Makefile
@@ -197,8 +197,15 @@
UTS_MACHINE := $(ARCH)
SRCARCH := $(ARCH)
-# for i386 and x86_64 we use SRCARCH equal to x86
-SRCARCH := $(if $(filter x86_64 i386,$(SRCARCH)),x86,$(SRCARCH))
+# Additional ARCH settings for x86
+ifeq ($(ARCH),i386)
+ SRCARCH := x86
+ K64BIT := n
+endif
+ifeq ($(ARCH),x86_64)
+ SRCARCH := x86
+ K64BIT := y
+endif
KCONFIG_CONFIG ?= .config
@@ -334,7 +341,7 @@
KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
-export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
+export ARCH SRCARCH K64BIT CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
diff --git a/README b/README
index 159912c..592f8a2 100644
--- a/README
+++ b/README
@@ -194,6 +194,8 @@
"make *config" checks for a file named "all{yes/mod/no/random}.config"
for symbol values that are to be forced. If this file is not found,
it checks for a file named "all.config" to contain forced values.
+ Finally it checks the environment variable K64BIT and if found, sets
+ the config symbol "64BIT" to the value of the K64BIT variable.
NOTES on "make config":
- having unnecessary drivers will make the kernel bigger, and can
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 1873bd8..bc91d6e 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -16,6 +16,7 @@
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/f75375s.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -200,11 +201,21 @@
.resource = &n2100_uart_resource,
};
+static struct f75375s_platform_data n2100_f75375s = {
+ .pwm = { 255, 255 },
+ .pwm_enable = { 0, 0 },
+};
+
static struct i2c_board_info __initdata n2100_i2c_devices[] = {
{
I2C_BOARD_INFO("rtc-rs5c372", 0x32),
.type = "rs5c372b",
},
+ {
+ I2C_BOARD_INFO("f75375", 0x2e),
+ .type = "f75375",
+ .platform_data = &n2100_f75375s,
+ },
};
/*
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 21900a9..222da15 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -13,6 +13,10 @@
bool
default y
+config NO_DMA
+ bool
+ default y
+
config RWSEM_GENERIC_SPINLOCK
bool
default y
@@ -57,6 +61,10 @@
source "fs/Kconfig.binfmt"
+config GENERIC_HARDIRQS
+ bool
+ default y
+
config ETRAX_CMDLINE
string "Kernel command line"
default "root=/dev/mtdblock3"
@@ -149,7 +157,8 @@
# bring in ETRAX built-in drivers
menu "Drivers for built-in interfaces"
-source arch/cris/arch-v10/drivers/Kconfig
+# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32)
+source arch/cris/arch/drivers/Kconfig
endmenu
@@ -180,6 +189,10 @@
source "drivers/telephony/Kconfig"
+source "drivers/i2c/Kconfig"
+
+source "drivers/rtc/Kconfig"
+
#
# input before char - char/joystick depends on it. As does USB.
#
@@ -194,6 +207,10 @@
source "sound/Kconfig"
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/Kconfig"
+
source "drivers/usb/Kconfig"
source "kernel/Kconfig.instrumentation"
diff --git a/arch/cris/arch-v10/defconfig b/arch/cris/arch-v10/defconfig
index 710c20b..572f119 100644
--- a/arch/cris/arch-v10/defconfig
+++ b/arch/cris/arch-v10/defconfig
@@ -99,7 +99,6 @@
CONFIG_MTD_CFI=y
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_AMDSTD=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_ETRAX_I2C=y
@@ -145,7 +144,6 @@
# CONFIG_MTD_CFI_GEOMETRY is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_AMDSTD=y
# CONFIG_MTD_SHARP is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_NORA is not set
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index 03e2e68..faf8b4d 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -2,6 +2,7 @@
bool "Ethernet support"
depends on ETRAX_ARCH_V10
select NET_ETHERNET
+ select MII
help
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
controller.
@@ -605,8 +606,6 @@
select MTD
select MTD_CFI
select MTD_CFI_AMDSTD
- select MTD_OBSOLETE_CHIPS
- select MTD_AMDSTD
select MTD_CHAR
select MTD_BLOCK
select MTD_PARTITIONS
diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c
index efd7b0f..ea3cf2e 100644
--- a/arch/cris/arch-v10/drivers/axisflashmap.c
+++ b/arch/cris/arch-v10/drivers/axisflashmap.c
@@ -312,12 +312,12 @@
"%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
map_cs->name, map_cs->size, map_cs->map_priv_1);
-#ifdef CONFIG_MTD_AMDSTD
- mtd_cs = do_map_probe("amd_flash", map_cs);
-#endif
#ifdef CONFIG_MTD_CFI
+ mtd_cs = do_map_probe("cfi_probe", map_cs);
+#endif
+#ifdef CONFIG_MTD_JEDECPROBE
if (!mtd_cs) {
- mtd_cs = do_map_probe("cfi_probe", map_cs);
+ mtd_cs = do_map_probe("jedec_probe", map_cs);
}
#endif
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index f389ed6..0d347a7 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -297,8 +297,10 @@
data = *R_PORT_PB_DATA;
else if (priv->minor == GPIO_MINOR_G)
data = *R_PORT_G_DATA;
- else
+ else {
+ spin_unlock(&gpio_lock);
return 0;
+ }
if ((data & priv->highalarm) ||
(~data & priv->lowalarm)) {
@@ -381,18 +383,21 @@
ssize_t retval = count;
if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
- return -EFAULT;
+ retval = -EFAULT;
+ goto out;
}
if (!access_ok(VERIFY_READ, buf, count)) {
- return -EFAULT;
+ retval = -EFAULT;
+ goto out;
}
clk_mask = priv->clk_mask;
data_mask = priv->data_mask;
/* It must have been configured using the IO_CFG_WRITE_MODE */
/* Perhaps a better error code? */
if (clk_mask == 0 || data_mask == 0) {
- return -EPERM;
+ retval = -EPERM;
+ goto out;
}
write_msb = priv->write_msb;
D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb));
@@ -425,6 +430,7 @@
}
}
}
+out:
spin_unlock(&gpio_lock);
return retval;
}
@@ -506,6 +512,7 @@
while (p) {
if (p->highalarm | p->lowalarm) {
gpio_some_alarms = 1;
+ spin_unlock(&gpio_lock);
return 0;
}
p = p->next;
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index c5844cb..ec62c95 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -500,9 +500,8 @@
;; deal with pending signals and notify-resume requests
move.d $r9, $r10 ; do_notify_resume syscall/irq param
- moveq 0, $r11 ; oldset param - 0 in this case
- move.d $sp, $r12 ; the regs param
- move.d $r1, $r13 ; the thread_info_flags parameter
+ move.d $sp, $r11 ; the regs param
+ move.d $r1, $r12 ; the thread_info_flags parameter
jsr do_notify_resume
ba _Rexit
@@ -678,13 +677,19 @@
push $r10 ; push orig_r10
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
+ ;; If there is a glitch on the NMI pin shorter than ~100ns
+ ;; (i.e. non-active by the time we get here) then the nmi_pin bit
+ ;; in R_IRQ_MASK0_RD will already be cleared. The watchdog_nmi bit
+ ;; is cleared by us however (when feeding the watchdog), which is why
+ ;; we use that bit to determine what brought us here.
+
move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?
- and.d 0x80000000, $r1
- beq wdog
+ and.d (1<<30), $r1
+ bne wdog
move.d $sp, $r10
jsr handle_nmi
setf m ; Enable NMI again
- retb ; Return from NMI
+ ba _Rexit ; Return the standard way
nop
wdog:
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
@@ -775,22 +780,9 @@
push $r10 ; push orig_r10
clear.d [$sp=$sp-4] ; frametype == 0, normal frame
- moveq 2, $r2 ; first bit we care about is the timer0 irq
- move.d [R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq
- move.d $r0, [R_VECT_MASK_CLR] ; Block all active IRQs
-1:
- btst $r2, $r0 ; check for the irq given by bit r2
- bpl 2f
- move.d $r2, $r10 ; First argument to do_IRQ
- move.d $sp, $r11 ; second argument to do_IRQ
- jsr do_IRQ
-2:
- addq 1, $r2 ; next vector bit
- cmp.b 32, $r2
- bne 1b ; process all irq's up to and including number 31
- moveq 0, $r9 ; make ret_from_intr realise we came from an ir
+ move.d $sp, $r10
+ jsr do_multiple_IRQ
- move.d $r0, [R_VECT_MASK_SET] ; Unblock all the IRQs
jump ret_from_intr
do_sigtrap:
@@ -837,6 +829,13 @@
ba do_sigtrap ; SIGTRAP the offending process.
pop $dccr ; Restore dccr in delay slot.
+ .global kernel_execve
+kernel_execve:
+ move.d __NR_execve, $r9
+ break 13
+ ret
+ nop
+
.data
hw_bp_trigs:
@@ -1135,6 +1134,42 @@
.long sys_add_key
.long sys_request_key
.long sys_keyctl
+ .long sys_ioprio_set
+ .long sys_ioprio_get /* 290 */
+ .long sys_inotify_init
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_migrate_pages
+ .long sys_openat /* 295 */
+ .long sys_mkdirat
+ .long sys_mknodat
+ .long sys_fchownat
+ .long sys_futimesat
+ .long sys_fstatat64 /* 300 */
+ .long sys_unlinkat
+ .long sys_renameat
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat /* 305 */
+ .long sys_fchmodat
+ .long sys_faccessat
+ .long sys_pselect6
+ .long sys_ppoll
+ .long sys_unshare /* 310 */
+ .long sys_set_robust_list
+ .long sys_get_robust_list
+ .long sys_splice
+ .long sys_sync_file_range
+ .long sys_tee /* 315 */
+ .long sys_vmsplice
+ .long sys_move_pages
+ .long sys_getcpu
+ .long sys_epoll_pwait
+ .long sys_utimensat /* 320 */
+ .long sys_signalfd
+ .long sys_timerfd
+ .long sys_eventfd
+ .long sys_fallocate
/*
* NOTE!! This doesn't have to be exact - we just have
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c
index d3ea052..c1a3a21 100644
--- a/arch/cris/arch-v10/kernel/fasttimer.c
+++ b/arch/cris/arch-v10/kernel/fasttimer.c
@@ -1,97 +1,9 @@
-/* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $
+/*
* linux/arch/cris/kernel/fasttimer.c
*
* Fast timers for ETRAX100/ETRAX100LX
- * This may be useful in other OS than Linux so use 2 space indentation...
*
- * $Log: fasttimer.c,v $
- * Revision 1.9 2005/03/04 08:16:16 starvik
- * Merge of Linux 2.6.11.
- *
- * Revision 1.8 2005/01/05 06:09:29 starvik
- * cli()/sti() will be obsolete in 2.6.11.
- *
- * Revision 1.7 2005/01/03 13:35:46 starvik
- * Removed obsolete stuff.
- * Mark fast timer IRQ as not shared.
- *
- * Revision 1.6 2004/05/14 10:18:39 starvik
- * Export fast_timer_list
- *
- * Revision 1.5 2004/05/14 07:58:01 starvik
- * Merge of changes from 2.4
- *
- * Revision 1.4 2003/07/04 08:27:41 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.3 2002/12/12 08:26:32 starvik
- * Don't use C-comments inside CVS comments
- *
- * Revision 1.2 2002/12/11 15:42:02 starvik
- * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/
- *
- * Revision 1.1 2002/11/18 07:58:06 starvik
- * Fast timers (from Linux 2.4)
- *
- * Revision 1.5 2002/10/15 06:21:39 starvik
- * Added call to init_waitqueue_head
- *
- * Revision 1.4 2002/05/28 17:47:59 johana
- * Added del_fast_timer()
- *
- * Revision 1.3 2002/05/28 16:16:07 johana
- * Handle empty fast_timer_list
- *
- * Revision 1.2 2002/05/27 15:38:42 johana
- * Made it compile without warnings on Linux 2.4.
- * (includes, wait_queue, PROC_FS and snprintf)
- *
- * Revision 1.1 2002/05/27 15:32:25 johana
- * arch/etrax100/kernel/fasttimer.c v1.8 from the elinux tree.
- *
- * Revision 1.8 2001/11/27 13:50:40 pkj
- * Disable interrupts while stopping the timer and while modifying the
- * list of active timers in timer1_handler() as it may be interrupted
- * by other interrupts (e.g., the serial interrupt) which may add fast
- * timers.
- *
- * Revision 1.7 2001/11/22 11:50:32 pkj
- * * Only store information about the last 16 timers.
- * * proc_fasttimer_read() now uses an allocated buffer, since it
- * requires more space than just a page even for only writing the
- * last 16 timers. The buffer is only allocated on request, so
- * unless /proc/fasttimer is read, it is never allocated.
- * * Renamed fast_timer_started to fast_timers_started to match
- * fast_timers_added and fast_timers_expired.
- * * Some clean-up.
- *
- * Revision 1.6 2000/12/13 14:02:08 johana
- * Removed volatile for fast_timer_list
- *
- * Revision 1.5 2000/12/13 13:55:35 johana
- * Added DEBUG_LOG, added som cli() and cleanup
- *
- * Revision 1.4 2000/12/05 13:48:50 johana
- * Added range check when writing proc file, modified timer int handling
- *
- * Revision 1.3 2000/11/23 10:10:20 johana
- * More debug/logging possibilities.
- * Moved GET_JIFFIES_USEC() to timex.h and time.c
- *
- * Revision 1.2 2000/11/01 13:41:04 johana
- * Clean up and bugfixes.
- * Created new do_gettimeofday_fast() that gets a timeval struct
- * with time based on jiffies and *R_TIMER0_DATA, uses a table
- * for fast conversion of timer value to microseconds.
- * (Much faster the standard do_gettimeofday() and we don't really
- * want to use the true time - we want the "uptime" so timers don't screw up
- * when we change the time.
- * TODO: Add efficient support for continuous timers as well.
- *
- * Revision 1.1 2000/10/26 15:49:16 johana
- * Added fasttimer, highresolution timers.
- *
- * Copyright (C) 2000,2001 2002 Axis Communications AB, Lund, Sweden
+ * Copyright (C) 2000-2007 Axis Communications AB, Lund, Sweden
*/
#include <linux/errno.h>
@@ -125,7 +37,7 @@
#ifdef FAST_TIMER_SANITY_CHECKS
#define SANITYCHECK(x) x
-static int sanity_failed = 0;
+static int sanity_failed;
#else
#define SANITYCHECK(x)
#endif
@@ -134,15 +46,13 @@
#define D2(x)
#define DP(x)
-#define __INLINE__ inline
-
-static int fast_timer_running = 0;
-static int fast_timers_added = 0;
-static int fast_timers_started = 0;
-static int fast_timers_expired = 0;
-static int fast_timers_deleted = 0;
-static int fast_timer_is_init = 0;
-static int fast_timer_ints = 0;
+static unsigned int fast_timer_running;
+static unsigned int fast_timers_added;
+static unsigned int fast_timers_started;
+static unsigned int fast_timers_expired;
+static unsigned int fast_timers_deleted;
+static unsigned int fast_timer_is_init;
+static unsigned int fast_timer_ints;
struct fast_timer *fast_timer_list = NULL;
@@ -150,8 +60,8 @@
#define DEBUG_LOG_MAX 128
static const char * debug_log_string[DEBUG_LOG_MAX];
static unsigned long debug_log_value[DEBUG_LOG_MAX];
-static int debug_log_cnt = 0;
-static int debug_log_cnt_wrapped = 0;
+static unsigned int debug_log_cnt;
+static unsigned int debug_log_cnt_wrapped;
#define DEBUG_LOG(string, value) \
{ \
@@ -206,45 +116,29 @@
int timer_delay_settings[NUM_TIMER_STATS];
/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */
-void __INLINE__ do_gettimeofday_fast(struct timeval *tv)
+inline void do_gettimeofday_fast(struct fasttime_t *tv)
{
- unsigned long sec = jiffies;
- unsigned long usec = GET_JIFFIES_USEC();
-
- usec += (sec % HZ) * (1000000 / HZ);
- sec = sec / HZ;
-
- if (usec > 1000000)
- {
- usec -= 1000000;
- sec++;
- }
- tv->tv_sec = sec;
- tv->tv_usec = usec;
+ tv->tv_jiff = jiffies;
+ tv->tv_usec = GET_JIFFIES_USEC();
}
-int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1)
+inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1)
{
- if (t0->tv_sec < t1->tv_sec)
- {
- return -1;
- }
- else if (t0->tv_sec > t1->tv_sec)
- {
- return 1;
- }
- if (t0->tv_usec < t1->tv_usec)
- {
- return -1;
- }
- else if (t0->tv_usec > t1->tv_usec)
- {
- return 1;
- }
- return 0;
+ /* Compare jiffies. Takes care of wrapping */
+ if (time_before(t0->tv_jiff, t1->tv_jiff))
+ return -1;
+ else if (time_after(t0->tv_jiff, t1->tv_jiff))
+ return 1;
+
+ /* Compare us */
+ if (t0->tv_usec < t1->tv_usec)
+ return -1;
+ else if (t0->tv_usec > t1->tv_usec)
+ return 1;
+ return 0;
}
-void __INLINE__ start_timer1(unsigned long delay_us)
+inline void start_timer1(unsigned long delay_us)
{
int freq_index = 0; /* This is the lowest resolution */
unsigned long upper_limit = MAX_DELAY_US;
@@ -285,7 +179,7 @@
timer_freq_settings[fast_timers_started % NUM_TIMER_STATS] = freq_index;
timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us;
- D1(printk("start_timer1 : %d us freq: %i div: %i\n",
+ D1(printk(KERN_DEBUG "start_timer1 : %d us freq: %i div: %i\n",
delay_us, freq_index, div));
/* Clear timer1 irq */
*R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
@@ -340,7 +234,7 @@
printk(KERN_WARNING
"timer name: %s data: 0x%08lX already in list!\n", name, data);
sanity_failed++;
- return;
+ goto done;
}
else
{
@@ -356,11 +250,11 @@
t->name = name;
t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
- t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000;
+ t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ;
if (t->tv_expires.tv_usec > 1000000)
{
t->tv_expires.tv_usec -= 1000000;
- t->tv_expires.tv_sec++;
+ t->tv_expires.tv_jiff += HZ;
}
#ifdef FAST_TIMER_LOG
timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
@@ -368,7 +262,7 @@
fast_timers_added++;
/* Check if this should timeout before anything else */
- if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
+ if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
{
/* Put first in list and modify the timer value */
t->prev = NULL;
@@ -384,8 +278,8 @@
start_timer1(delay_us);
} else {
/* Put in correct place in list */
- while (tmp->next &&
- timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
+ while (tmp->next && fasttime_cmp(&t->tv_expires,
+ &tmp->next->tv_expires) > 0)
{
tmp = tmp->next;
}
@@ -401,6 +295,7 @@
D2(printk("start_one_shot_timer: %d us done\n", delay_us));
+done:
local_irq_restore(flags);
} /* start_one_shot_timer */
@@ -444,11 +339,18 @@
/* Timer 1 interrupt handler */
static irqreturn_t
-timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
+timer1_handler(int irq, void *dev_id)
{
struct fast_timer *t;
unsigned long flags;
+ /* We keep interrupts disabled not only when we modify the
+ * fast timer list, but any time we hold a reference to a
+ * timer in the list, since del_fast_timer may be called
+ * from (another) interrupt context. Thus, the only time
+ * when interrupts are enabled is when calling the timer
+ * callback function.
+ */
local_irq_save(flags);
/* Clear timer1 irq */
@@ -466,18 +368,19 @@
fast_timer_running = 0;
fast_timer_ints++;
- local_irq_restore(flags);
-
t = fast_timer_list;
while (t)
{
- struct timeval tv;
+ struct fasttime_t tv;
+ fast_timer_function_type *f;
+ unsigned long d;
/* Has it really expired? */
do_gettimeofday_fast(&tv);
- D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec));
+ D1(printk(KERN_DEBUG "t: %is %06ius\n",
+ tv.tv_jiff, tv.tv_usec));
- if (timeval_cmp(&t->tv_expires, &tv) <= 0)
+ if (fasttime_cmp(&t->tv_expires, &tv) <= 0)
{
/* Yes it has expired */
#ifdef FAST_TIMER_LOG
@@ -486,7 +389,6 @@
fast_timers_expired++;
/* Remove this timer before call, since it may reuse the timer */
- local_irq_save(flags);
if (t->prev)
{
t->prev->next = t->next;
@@ -501,16 +403,23 @@
}
t->prev = NULL;
t->next = NULL;
- local_irq_restore(flags);
- if (t->function != NULL)
- {
- t->function(t->data);
- }
- else
- {
+ /* Save function callback data before enabling
+ * interrupts, since the timer may be removed and
+ * we don't know how it was allocated
+ * (e.g. ->function and ->data may become overwritten
+ * after deletion if the timer was stack-allocated).
+ */
+ f = t->function;
+ d = t->data;
+
+ if (f != NULL) {
+ /* Run callback with interrupts enabled. */
+ local_irq_restore(flags);
+ f(d);
+ local_irq_save(flags);
+ } else
DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
- }
}
else
{
@@ -518,16 +427,20 @@
D1(printk(".\n"));
}
- local_irq_save(flags);
if ((t = fast_timer_list) != NULL)
{
/* Start next timer.. */
- long us;
- struct timeval tv;
+ long us = 0;
+ struct fasttime_t tv;
do_gettimeofday_fast(&tv);
- us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 +
- t->tv_expires.tv_usec - tv.tv_usec);
+
+ /* time_after_eq takes care of wrapping */
+ if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff))
+ us = ((t->tv_expires.tv_jiff - tv.tv_jiff) *
+ 1000000 / HZ + t->tv_expires.tv_usec -
+ tv.tv_usec);
+
if (us > 0)
{
if (!fast_timer_running)
@@ -537,7 +450,6 @@
#endif
start_timer1(us);
}
- local_irq_restore(flags);
break;
}
else
@@ -548,9 +460,10 @@
D1(printk("e! %d\n", us));
}
}
- local_irq_restore(flags);
}
+ local_irq_restore(flags);
+
if (!t)
{
D1(printk("t1 stop!\n"));
@@ -575,28 +488,17 @@
void schedule_usleep(unsigned long us)
{
struct fast_timer t;
-#ifdef DECLARE_WAITQUEUE
wait_queue_head_t sleep_wait;
init_waitqueue_head(&sleep_wait);
- {
- DECLARE_WAITQUEUE(wait, current);
-#else
- struct wait_queue *sleep_wait = NULL;
- struct wait_queue wait = { current, NULL };
-#endif
D1(printk("schedule_usleep(%d)\n", us));
- add_wait_queue(&sleep_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us,
"usleep");
- schedule();
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&sleep_wait, &wait);
+ /* Uninterruptible sleep on the fast timer. (The condition is somewhat
+ * redundant since the timer is what wakes us up.) */
+ wait_event(sleep_wait, !fast_timer_pending(&t));
+
D1(printk("done schedule_usleep(%d)\n", us));
-#ifdef DECLARE_WAITQUEUE
- }
-#endif
}
#ifdef CONFIG_PROC_FS
@@ -616,7 +518,7 @@
unsigned long flags;
int i = 0;
int num_to_show;
- struct timeval tv;
+ struct fasttime_t tv;
struct fast_timer *t, *nextt;
static char *bigbuf = NULL;
static unsigned long used;
@@ -624,7 +526,8 @@
if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE)))
{
used = 0;
- bigbuf[0] = '\0';
+ if (buf)
+ buf[0] = '\0';
return 0;
}
@@ -646,7 +549,7 @@
used += sprintf(bigbuf + used, "Fast timer running: %s\n",
fast_timer_running ? "yes" : "no");
used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n",
- (unsigned long)tv.tv_sec,
+ (unsigned long)tv.tv_jiff,
(unsigned long)tv.tv_usec);
#ifdef FAST_TIMER_SANITY_CHECKS
used += sprintf(bigbuf + used, "Sanity failed: %i\n",
@@ -696,9 +599,9 @@
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -718,9 +621,9 @@
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -738,9 +641,9 @@
"d: %6li us data: 0x%08lX"
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
@@ -761,15 +664,15 @@
/* " func: 0x%08lX" */
"\n",
t->name,
- (unsigned long)t->tv_set.tv_sec,
+ (unsigned long)t->tv_set.tv_jiff,
(unsigned long)t->tv_set.tv_usec,
- (unsigned long)t->tv_expires.tv_sec,
+ (unsigned long)t->tv_expires.tv_jiff,
(unsigned long)t->tv_expires.tv_usec,
t->delay_us,
t->data
/* , t->function */
);
- local_irq_disable();
+ local_irq_save(flags);
if (t->next != nextt)
{
printk(KERN_WARNING "timer removed!\n");
@@ -798,7 +701,7 @@
static struct fast_timer tr[10];
static int exp_num[10];
-static struct timeval tv_exp[100];
+static struct fasttime_t tv_exp[100];
static void test_timeout(unsigned long data)
{
@@ -836,7 +739,7 @@
int prev_num;
int j;
- struct timeval tv, tv0, tv1, tv2;
+ struct fasttime_t tv, tv0, tv1, tv2;
printk("fast_timer_test() start\n");
do_gettimeofday_fast(&tv);
@@ -849,7 +752,8 @@
{
do_gettimeofday_fast(&tv_exp[j]);
}
- printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec);
+ printk(KERN_DEBUG "fast_timer_test() %is %06i\n",
+ tv.tv_jiff, tv.tv_usec);
for (j = 0; j < 1000; j++)
{
@@ -858,12 +762,12 @@
}
for (j = 0; j < 100; j++)
{
- printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n",
- tv_exp[j].tv_sec,tv_exp[j].tv_usec,
- tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec,
- tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec,
- tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec,
- tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec);
+ printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n",
+ tv_exp[j].tv_jiff, tv_exp[j].tv_usec,
+ tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec,
+ tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec,
+ tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec,
+ tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec);
j += 4;
}
do_gettimeofday_fast(&tv0);
@@ -895,9 +799,12 @@
}
}
do_gettimeofday_fast(&tv2);
- printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec);
- printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec);
- printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec);
+ printk(KERN_DEBUG "Timers started %is %06i\n",
+ tv0.tv_jiff, tv0.tv_usec);
+ printk(KERN_DEBUG "Timers started at %is %06i\n",
+ tv1.tv_jiff, tv1.tv_usec);
+ printk(KERN_DEBUG "Timers done %is %06i\n",
+ tv2.tv_jiff, tv2.tv_usec);
DP(printk("buf0:\n");
printk(buf0);
printk("buf1:\n");
@@ -919,9 +826,9 @@
printk("%-10s set: %6is %06ius exp: %6is %06ius "
"data: 0x%08X func: 0x%08X\n",
t->name,
- t->tv_set.tv_sec,
+ t->tv_set.tv_jiff,
t->tv_set.tv_usec,
- t->tv_expires.tv_sec,
+ t->tv_expires.tv_jiff,
t->tv_expires.tv_usec,
t->data,
t->function
@@ -929,10 +836,12 @@
printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n",
t->delay_us,
- tv_exp[j].tv_sec,
+ tv_exp[j].tv_jiff,
tv_exp[j].tv_usec,
exp_num[j],
- (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec);
+ (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) *
+ 1000000 + tv_exp[j].tv_usec -
+ t->tv_expires.tv_usec);
}
proc_fasttimer_read(buf5, NULL, 0, 0, 0);
printk("buf5 after all done:\n");
@@ -942,7 +851,7 @@
#endif
-void fast_timer_init(void)
+int fast_timer_init(void)
{
/* For some reason, request_irq() hangs when called froom time_init() */
if (!fast_timer_is_init)
@@ -975,4 +884,6 @@
fast_timer_test();
#endif
}
+ return 0;
}
+__initcall(fast_timer_init);
diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c
index 29d48ad..3a9114e 100644
--- a/arch/cris/arch-v10/kernel/io_interface_mux.c
+++ b/arch/cris/arch-v10/kernel/io_interface_mux.c
@@ -304,7 +304,7 @@
static struct if_group *get_group(const unsigned char groups)
{
int i;
- for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) {
+ for (i = 0; i < ARRAY_SIZE(if_groups); i++) {
if (groups & if_groups[i].group) {
return &if_groups[i];
}
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
index 845c95f..e06ab00 100644
--- a/arch/cris/arch-v10/kernel/irq.c
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -12,10 +12,16 @@
*/
#include <asm/irq.h>
+#include <asm/current.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/init.h>
+/* From kgdb.c. */
+extern void kgdb_init(void);
+extern void breakpoint(void);
+
#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
@@ -75,8 +81,8 @@
BUILD_IRQ(13, 0x2000)
void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */
void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
-BUILD_IRQ(16, 0x10000)
-BUILD_IRQ(17, 0x20000)
+BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */
+BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */
BUILD_IRQ(18, 0x40000)
BUILD_IRQ(19, 0x80000)
BUILD_IRQ(20, 0x100000)
@@ -147,6 +153,55 @@
void do_sigtrap(void); /* from entry.S */
void gdb_handle_breakpoint(void); /* from entry.S */
+extern void do_IRQ(int irq, struct pt_regs * regs);
+
+/* Handle multiple IRQs */
+void do_multiple_IRQ(struct pt_regs* regs)
+{
+ int bit;
+ unsigned masked;
+ unsigned mask;
+ unsigned ethmask = 0;
+
+ /* Get interrupts to mask and handle */
+ mask = masked = *R_VECT_MASK_RD;
+
+ /* Never mask timer IRQ */
+ mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0));
+
+ /*
+ * If either ethernet interrupt (rx or tx) is active then block
+ * the other one too. Unblock afterwards also.
+ */
+ if (mask &
+ (IO_STATE(R_VECT_MASK_RD, dma0, active) |
+ IO_STATE(R_VECT_MASK_RD, dma1, active))) {
+ ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) |
+ IO_MASK(R_VECT_MASK_RD, dma1));
+ }
+
+ /* Block them */
+ *R_VECT_MASK_CLR = (mask | ethmask);
+
+ /* An extra irq_enter here to prevent softIRQs to run after
+ * each do_IRQ. This will decrease the interrupt latency.
+ */
+ irq_enter();
+
+ /* Handle all IRQs */
+ for (bit = 2; bit < 32; bit++) {
+ if (masked & (1 << bit)) {
+ do_IRQ(bit, regs);
+ }
+ }
+
+ /* This irq_exit() will trigger the soft IRQs. */
+ irq_exit();
+
+ /* Unblock the IRQs again */
+ *R_VECT_MASK_SET = (masked | ethmask);
+}
+
/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
setting the irq vector table.
*/
diff --git a/arch/cris/arch-v10/kernel/setup.c b/arch/cris/arch-v10/kernel/setup.c
index 682ef95..de27b50 100644
--- a/arch/cris/arch-v10/kernel/setup.c
+++ b/arch/cris/arch-v10/kernel/setup.c
@@ -13,6 +13,7 @@
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
+#include <linux/param.h>
#ifdef CONFIG_PROC_FS
#define HAS_FPU 0x0001
@@ -56,8 +57,8 @@
revision = rdvr();
- if (revision >= sizeof cpu_info/sizeof *cpu_info)
- info = &cpu_info[sizeof cpu_info/sizeof *cpu_info - 1];
+ if (revision >= ARRAY_SIZE(cpu_info))
+ info = &cpu_info[ARRAY_SIZE(cpu_info) - 1];
else
info = &cpu_info[revision];
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index 575a14b..5976f61 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -1,5 +1,4 @@
-/* $Id: time.c,v 1.5 2004/09/29 06:12:46 starvik Exp $
- *
+/*
* linux/arch/cris/arch-v10/kernel/time.c
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
@@ -20,6 +19,7 @@
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/rtc.h>
+#include <asm/irq_regs.h>
/* define this if you need to use print_timestamp */
/* it will make jiffies at 96 hz instead of 100 hz though */
@@ -201,8 +201,9 @@
extern void cris_do_profile(struct pt_regs *regs);
static inline irqreturn_t
-timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+timer_interrupt(int irq, void *dev_id)
{
+ struct pt_regs *regs = get_irq_regs();
/* acknowledge the timer irq */
#ifdef USE_CASCADE_TIMERS
@@ -221,9 +222,11 @@
#endif
/* reset watchdog otherwise it resets us! */
-
reset_watchdog();
+ /* Update statistics. */
+ update_process_times(user_mode(regs));
+
/* call the real timer interrupt handler */
do_timer(1);
diff --git a/arch/cris/arch-v10/lib/memset.c b/arch/cris/arch-v10/lib/memset.c
index 82bb668..42c1101 100644
--- a/arch/cris/arch-v10/lib/memset.c
+++ b/arch/cris/arch-v10/lib/memset.c
@@ -66,7 +66,7 @@
{
register char *dst __asm__ ("r13") = pdst;
-
+
/* This is NONPORTABLE, but since this whole routine is */
/* grossly nonportable that doesn't matter. */
@@ -110,52 +110,52 @@
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
"r13=r13, r12=r12, r11=r11" */
- __asm__ volatile ("
- ;; Check that the following is true (same register names on
- ;; both sides of equal sign, as in r8=r8):
- ;; %0=r13, %1=r12, %4=r11
- ;;
- ;; Save the registers we'll clobber in the movem process
- ;; on the stack. Don't mention them to gcc, it will only be
- ;; upset.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- move.d $r11,$r0
- move.d $r11,$r1
- move.d $r11,$r2
- move.d $r11,$r3
- move.d $r11,$r4
- move.d $r11,$r5
- move.d $r11,$r6
- move.d $r11,$r7
- move.d $r11,$r8
- move.d $r11,$r9
- move.d $r11,$r10
-
- ;; Now we've got this:
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 12*4,$r12
-0:
- subq 12*4,$r12
- bge 0b
- movem $r11,[$r13+]
-
- addq 12*4,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10"
+ __asm__ volatile ("\n\
+ ;; Check that the following is true (same register names on \n\
+ ;; both sides of equal sign, as in r8=r8): \n\
+ ;; %0=r13, %1=r12, %4=r11 \n\
+ ;; \n\
+ ;; Save the registers we'll clobber in the movem process \n\
+ ;; on the stack. Don't mention them to gcc, it will only be \n\
+ ;; upset. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ move.d $r11,$r0 \n\
+ move.d $r11,$r1 \n\
+ move.d $r11,$r2 \n\
+ move.d $r11,$r3 \n\
+ move.d $r11,$r4 \n\
+ move.d $r11,$r5 \n\
+ move.d $r11,$r6 \n\
+ move.d $r11,$r7 \n\
+ move.d $r11,$r8 \n\
+ move.d $r11,$r9 \n\
+ move.d $r11,$r10 \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 12*4,$r12 \n\
+0: \n\
+ subq 12*4,$r12 \n\
+ bge 0b \n\
+ movem $r11,[$r13+] \n\
+ \n\
+ addq 12*4,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10"
/* Outputs */ : "=r" (dst), "=r" (n)
/* Inputs */ : "0" (dst), "1" (n), "r" (lc));
-
+
}
/* Either we directly starts copying, using dword copying
- in a loop, or we copy as much as possible with 'movem'
+ in a loop, or we copy as much as possible with 'movem'
and then the last block (<44 bytes) is copied here.
This will work since 'movem' will have updated src,dst,n. */
diff --git a/arch/cris/arch-v10/lib/string.c b/arch/cris/arch-v10/lib/string.c
index 15d6662..7161a2b 100644
--- a/arch/cris/arch-v10/lib/string.c
+++ b/arch/cris/arch-v10/lib/string.c
@@ -95,33 +95,33 @@
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
"r13=r13, r11=r11, r12=r12" */
- __asm__ volatile ("
- ;; Check that the following is true (same register names on
- ;; both sides of equal sign, as in r8=r8):
- ;; %0=r13, %1=r11, %2=r12
- ;;
- ;; Save the registers we'll use in the movem process
- ;; on the stack.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- ;; Now we've got this:
- ;; r11 - src
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 44,$r12
-0:
- movem [$r11+],$r10
- subq 44,$r12
- bge 0b
- movem $r10,[$r13+]
-
- addq 44,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10"
+ __asm__ volatile ("\n\
+ ;; Check that the following is true (same register names on \n\
+ ;; both sides of equal sign, as in r8=r8): \n\
+ ;; %0=r13, %1=r11, %2=r12 \n\
+ ;; \n\
+ ;; Save the registers we'll use in the movem process \n\
+ ;; on the stack. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r11 - src \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 44,$r12 \n\
+0: \n\
+ movem [$r11+],$r10 \n\
+ subq 44,$r12 \n\
+ bge 0b \n\
+ movem $r10,[$r13+] \n\
+ \n\
+ addq 44,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10"
/* Outputs */ : "=r" (dst), "=r" (src), "=r" (n)
/* Inputs */ : "0" (dst), "1" (src), "2" (n));
diff --git a/arch/cris/arch-v10/lib/usercopy.c b/arch/cris/arch-v10/lib/usercopy.c
index a12c708..b8e6c04 100644
--- a/arch/cris/arch-v10/lib/usercopy.c
+++ b/arch/cris/arch-v10/lib/usercopy.c
@@ -92,58 +92,58 @@
.ifnc %0%1%2%3,$r13$r11$r12$r10 \n\
.err \n\
.endif \n\
-
- ;; Save the registers we'll use in the movem process
- ;; on the stack.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- ;; Now we've got this:
- ;; r11 - src
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 44,$r12
-
-; Since the noted PC of a faulting instruction in a delay-slot of a taken
-; branch, is that of the branch target, we actually point at the from-movem
-; for this case. There is no ambiguity here; if there was a fault in that
-; instruction (meaning a kernel oops), the faulted PC would be the address
-; after *that* movem.
-
-0:
- movem [$r11+],$r10
- subq 44,$r12
- bge 0b
- movem $r10,[$r13+]
-1:
- addq 44,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10
-2:
- .section .fixup,\"ax\"
-
-; To provide a correct count in r10 of bytes that failed to be copied,
-; we jump back into the loop if the loop-branch was taken. There is no
-; performance penalty for sany use; the program will segfault soon enough.
-
-3:
- move.d [$sp],$r10
- addq 44,$r10
- move.d $r10,[$sp]
- jump 0b
-4:
- movem [$sp+],$r10
- addq 44,$r10
- addq 44,$r12
- jump 2b
-
- .previous
- .section __ex_table,\"a\"
- .dword 0b,3b
- .dword 1b,4b
+ \n\
+ ;; Save the registers we'll use in the movem process \n\
+ ;; on the stack. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r11 - src \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 44,$r12 \n\
+ \n\
+; Since the noted PC of a faulting instruction in a delay-slot of a taken \n\
+; branch, is that of the branch target, we actually point at the from-movem \n\
+; for this case. There is no ambiguity here; if there was a fault in that \n\
+; instruction (meaning a kernel oops), the faulted PC would be the address \n\
+; after *that* movem. \n\
+ \n\
+0: \n\
+ movem [$r11+],$r10 \n\
+ subq 44,$r12 \n\
+ bge 0b \n\
+ movem $r10,[$r13+] \n\
+1: \n\
+ addq 44,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10 \n\
+2: \n\
+ .section .fixup,\"ax\" \n\
+ \n\
+; To provide a correct count in r10 of bytes that failed to be copied, \n\
+; we jump back into the loop if the loop-branch was taken. There is no \n\
+; performance penalty for sany use; the program will segfault soon enough.\n\
+ \n\
+3: \n\
+ move.d [$sp],$r10 \n\
+ addq 44,$r10 \n\
+ move.d $r10,[$sp] \n\
+ jump 0b \n\
+4: \n\
+ movem [$sp+],$r10 \n\
+ addq 44,$r10 \n\
+ addq 44,$r12 \n\
+ jump 2b \n\
+ \n\
+ .previous \n\
+ .section __ex_table,\"a\" \n\
+ .dword 0b,3b \n\
+ .dword 1b,4b \n\
.previous"
/* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
@@ -253,59 +253,59 @@
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
"r13=r13, r11=r11, r12=r12" */
- __asm__ volatile ("
+ __asm__ volatile ("\n\
.ifnc %0%1%2%3,$r13$r11$r12$r10 \n\
.err \n\
.endif \n\
-
- ;; Save the registers we'll use in the movem process
- ;; on the stack.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- ;; Now we've got this:
- ;; r11 - src
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 44,$r12
-0:
- movem [$r11+],$r10
-1:
- subq 44,$r12
- bge 0b
- movem $r10,[$r13+]
-
- addq 44,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10
-4:
- .section .fixup,\"ax\"
-
-;; Do not jump back into the loop if we fail. For some uses, we get a
-;; page fault somewhere on the line. Without checking for page limits,
-;; we don't know where, but we need to copy accurately and keep an
-;; accurate count; not just clear the whole line. To do that, we fall
-;; down in the code below, proceeding with smaller amounts. It should
-;; be kept in mind that we have to cater to code like what at one time
-;; was in fs/super.c:
-;; i = size - copy_from_user((void *)page, data, size);
-;; which would cause repeated faults while clearing the remainder of
-;; the SIZE bytes at PAGE after the first fault.
-;; A caveat here is that we must not fall through from a failing page
-;; to a valid page.
-
-3:
- movem [$sp+],$r10
- addq 44,$r12 ;; Get back count before faulting point.
- subq 44,$r11 ;; Get back pointer to faulting movem-line.
- jump 4b ;; Fall through, pretending the fault didn't happen.
-
- .previous
- .section __ex_table,\"a\"
- .dword 1b,3b
+ \n\
+ ;; Save the registers we'll use in the movem process \n\
+ ;; on the stack. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r11 - src \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 44,$r12 \n\
+0: \n\
+ movem [$r11+],$r10 \n\
+1: \n\
+ subq 44,$r12 \n\
+ bge 0b \n\
+ movem $r10,[$r13+] \n\
+ \n\
+ addq 44,$r12 ;; compensate for last loop underflowing n \n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10 \n\
+4: \n\
+ .section .fixup,\"ax\" \n\
+ \n\
+;; Do not jump back into the loop if we fail. For some uses, we get a \n\
+;; page fault somewhere on the line. Without checking for page limits, \n\
+;; we don't know where, but we need to copy accurately and keep an \n\
+;; accurate count; not just clear the whole line. To do that, we fall \n\
+;; down in the code below, proceeding with smaller amounts. It should \n\
+;; be kept in mind that we have to cater to code like what at one time \n\
+;; was in fs/super.c: \n\
+;; i = size - copy_from_user((void *)page, data, size); \n\
+;; which would cause repeated faults while clearing the remainder of \n\
+;; the SIZE bytes at PAGE after the first fault. \n\
+;; A caveat here is that we must not fall through from a failing page \n\
+;; to a valid page. \n\
+ \n\
+3: \n\
+ movem [$sp+],$r10 \n\
+ addq 44,$r12 ;; Get back count before faulting point. \n\
+ subq 44,$r11 ;; Get back pointer to faulting movem-line. \n\
+ jump 4b ;; Fall through, pretending the fault didn't happen.\n\
+ \n\
+ .previous \n\
+ .section __ex_table,\"a\" \n\
+ .dword 1b,3b \n\
.previous"
/* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
@@ -425,64 +425,64 @@
If you want to check that the allocation was right; then
check the equalities in the first comment. It should say
something like "r13=r13, r11=r11, r12=r12". */
- __asm__ volatile ("
+ __asm__ volatile ("\n\
.ifnc %0%1%2,$r13$r12$r10 \n\
.err \n\
.endif \n\
-
- ;; Save the registers we'll clobber in the movem process
- ;; on the stack. Don't mention them to gcc, it will only be
- ;; upset.
- subq 11*4,$sp
- movem $r10,[$sp]
-
- clear.d $r0
- clear.d $r1
- clear.d $r2
- clear.d $r3
- clear.d $r4
- clear.d $r5
- clear.d $r6
- clear.d $r7
- clear.d $r8
- clear.d $r9
- clear.d $r10
- clear.d $r11
-
- ;; Now we've got this:
- ;; r13 - dst
- ;; r12 - n
-
- ;; Update n for the first loop
- subq 12*4,$r12
-0:
- subq 12*4,$r12
- bge 0b
- movem $r11,[$r13+]
-1:
- addq 12*4,$r12 ;; compensate for last loop underflowing n
-
- ;; Restore registers from stack
- movem [$sp+],$r10
-2:
- .section .fixup,\"ax\"
-3:
- move.d [$sp],$r10
- addq 12*4,$r10
- move.d $r10,[$sp]
- clear.d $r10
- jump 0b
-
-4:
- movem [$sp+],$r10
- addq 12*4,$r10
- addq 12*4,$r12
- jump 2b
-
- .previous
- .section __ex_table,\"a\"
- .dword 0b,3b
- .dword 1b,4b
+ \n\
+ ;; Save the registers we'll clobber in the movem process \n\
+ ;; on the stack. Don't mention them to gcc, it will only be \n\
+ ;; upset. \n\
+ subq 11*4,$sp \n\
+ movem $r10,[$sp] \n\
+ \n\
+ clear.d $r0 \n\
+ clear.d $r1 \n\
+ clear.d $r2 \n\
+ clear.d $r3 \n\
+ clear.d $r4 \n\
+ clear.d $r5 \n\
+ clear.d $r6 \n\
+ clear.d $r7 \n\
+ clear.d $r8 \n\
+ clear.d $r9 \n\
+ clear.d $r10 \n\
+ clear.d $r11 \n\
+ \n\
+ ;; Now we've got this: \n\
+ ;; r13 - dst \n\
+ ;; r12 - n \n\
+ \n\
+ ;; Update n for the first loop \n\
+ subq 12*4,$r12 \n\
+0: \n\
+ subq 12*4,$r12 \n\
+ bge 0b \n\
+ movem $r11,[$r13+] \n\
+1: \n\
+ addq 12*4,$r12 ;; compensate for last loop underflowing n\n\
+ \n\
+ ;; Restore registers from stack \n\
+ movem [$sp+],$r10 \n\
+2: \n\
+ .section .fixup,\"ax\" \n\
+3: \n\
+ move.d [$sp],$r10 \n\
+ addq 12*4,$r10 \n\
+ move.d $r10,[$sp] \n\
+ clear.d $r10 \n\
+ jump 0b \n\
+ \n\
+4: \n\
+ movem [$sp+],$r10 \n\
+ addq 12*4,$r10 \n\
+ addq 12*4,$r12 \n\
+ jump 2b \n\
+ \n\
+ .previous \n\
+ .section __ex_table,\"a\" \n\
+ .dword 0b,3b \n\
+ .dword 1b,4b \n\
.previous"
/* Outputs */ : "=r" (dst), "=r" (n), "=r" (retn)
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index cc6ba54..7f72d7c 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -362,8 +362,6 @@
select MTD
select MTD_CFI
select MTD_CFI_AMDSTD
- select MTD_OBSOLETE_CHIPS
- select MTD_AMDSTD
select MTD_CHAR
select MTD_BLOCK
select MTD_PARTITIONS
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index 3ec12ea..c5ff95e 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -190,13 +190,12 @@
"%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n",
map_cs->name, map_cs->size, map_cs->map_priv_1);
-#ifdef CONFIG_MTD_AMDSTD
- mtd_cs = do_map_probe("amd_flash", map_cs);
-#endif
#ifdef CONFIG_MTD_CFI
- if (!mtd_cs) {
mtd_cs = do_map_probe("cfi_probe", map_cs);
- }
+#endif
+#ifdef CONFIG_MTD_JEDECPROBE
+ if (!mtd_cs)
+ mtd_cs = do_map_probe("jedec_probe", map_cs);
#endif
return mtd_cs;
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index df89298..d581b0a 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -185,7 +185,7 @@
}
};
-#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
+#define NUMBER_OF_PORTS ARRAY_SIZE(ports)
static const struct file_operations sync_serial_fops = {
.owner = THIS_MODULE,
diff --git a/arch/cris/arch-v32/kernel/cache.c b/arch/cris/arch-v32/kernel/cache.c
new file mode 100644
index 0000000..80da7b8
--- /dev/null
+++ b/arch/cris/arch-v32/kernel/cache.c
@@ -0,0 +1,33 @@
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/arch/cache.h>
+#include <asm/arch/hwregs/dma.h>
+
+/* This file is used to workaround a cache bug, Guinness TR 106. */
+
+inline void flush_dma_descr(struct dma_descr_data *descr, int flush_buf)
+{
+ /* Flush descriptor to make sure we get correct in_eop and after. */
+ asm volatile ("ftagd [%0]" :: "r" (descr));
+ /* Flush buffer pointed out by descriptor. */
+ if (flush_buf)
+ cris_flush_cache_range(phys_to_virt((unsigned)descr->buf),
+ (unsigned)(descr->after - descr->buf));
+}
+EXPORT_SYMBOL(flush_dma_descr);
+
+void flush_dma_list(struct dma_descr_data *descr)
+{
+ while (1) {
+ flush_dma_descr(descr, 1);
+ if (descr->eol)
+ break;
+ descr = phys_to_virt((unsigned)descr->next);
+ }
+}
+EXPORT_SYMBOL(flush_dma_list);
+
+/* From cacheflush.S */
+EXPORT_SYMBOL(cris_flush_cache);
+/* From cacheflush.S */
+EXPORT_SYMBOL(cris_flush_cache_range);
diff --git a/arch/cris/arch-v32/kernel/cacheflush.S b/arch/cris/arch-v32/kernel/cacheflush.S
new file mode 100644
index 0000000..956e8fb
--- /dev/null
+++ b/arch/cris/arch-v32/kernel/cacheflush.S
@@ -0,0 +1,94 @@
+ .global cris_flush_cache_range
+cris_flush_cache_range:
+ move.d 1024, $r12
+ cmp.d $r11, $r12
+ bhi cris_flush_1KB
+ nop
+ add.d $r10, $r11
+ ftagd [$r10]
+cris_flush_last:
+ addq 32, $r10
+ cmp.d $r11, $r10
+ blt cris_flush_last
+ ftagd [$r10]
+ ret
+ nop
+cris_flush_1KB:
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ftagd [$r10]
+ addq 32, $r10
+ ba cris_flush_cache_range
+ sub.d $r12, $r11
+
+ .global cris_flush_cache
+cris_flush_cache:
+ moveq 0, $r10
+cris_flush_line:
+ move.d 16*1024, $r11
+ addq 16, $r10
+ cmp.d $r10, $r11
+ blt cris_flush_line
+ fidxd [$r10]
+ ret
+ nop
diff --git a/arch/cris/arch-v32/kernel/io.c b/arch/cris/arch-v32/kernel/io.c
index dfbfcb8..a22a9e0 100644
--- a/arch/cris/arch-v32/kernel/io.c
+++ b/arch/cris/arch-v32/kernel/io.c
@@ -49,7 +49,7 @@
}
};
-#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
+#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports)
struct crisv32_iopin crisv32_led1_green;
struct crisv32_iopin crisv32_led1_red;
diff --git a/arch/cris/arch-v32/kernel/setup.c b/arch/cris/arch-v32/kernel/setup.c
index 4662f36..72e9e83 100644
--- a/arch/cris/arch-v32/kernel/setup.c
+++ b/arch/cris/arch-v32/kernel/setup.c
@@ -54,12 +54,10 @@
{
int i;
int cpu = (int)v - 1;
- int entries;
unsigned long revision;
struct cpu_info *info;
- entries = sizeof cpinfo / sizeof(struct cpu_info);
- info = &cpinfo[entries - 1];
+ info = &cpinfo[ARRAY_SIZE(cpinfo) - 1];
#ifdef CONFIG_SMP
if (!cpu_online(cpu))
@@ -68,7 +66,7 @@
revision = rdvr();
- for (i = 0; i < entries; i++) {
+ for (i = 0; i < ARRAY_SIZE(cpinfo); i++) {
if (cpinfo[i].rev == revision) {
info = &cpinfo[i];
break;
diff --git a/arch/cris/defconfig b/arch/cris/defconfig
index 142a108..9c33ae6 100644
--- a/arch/cris/defconfig
+++ b/arch/cris/defconfig
@@ -226,8 +226,6 @@
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-CONFIG_MTD_OBSOLETE_CHIPS=y
-CONFIG_MTD_AMDSTD=y
# CONFIG_MTD_SHARP is not set
# CONFIG_MTD_JEDEC is not set
@@ -276,6 +274,7 @@
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
@@ -302,16 +301,14 @@
#
# ATA/ATAPI/MFM/RLL support
#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_IDE is not set
+# CONFIG_PARIDE is not set
#
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
@@ -321,7 +318,6 @@
#
# CONFIG_IDE_GENERIC is not set
# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
@@ -329,6 +325,7 @@
# SCSI device support
#
# CONFIG_SCSI is not set
+# CONFIG_ISCSI_TCP is not set
#
# IEEE 1394 (FireWire) support
@@ -414,26 +411,11 @@
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-# CONFIG_BT_SCO is not set
-CONFIG_BT_RFCOMM=y
-# CONFIG_BT_RFCOMM_TTY is not set
-CONFIG_BT_BNEP=y
-# CONFIG_BT_BNEP_MC_FILTER is not set
-# CONFIG_BT_BNEP_PROTO_FILTER is not set
-# CONFIG_BT_HIDP is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_BT is not set
+# CONFIG_I2C is not set
-#
-# Bluetooth device drivers
-#
-CONFIG_BT_HCIUSB=y
-# CONFIG_BT_HCIUSB_SCO is not set
-# CONFIG_BT_HCIUART is not set
-# CONFIG_BT_HCIBCM203X is not set
-# CONFIG_BT_HCIBPA10X is not set
-# CONFIG_BT_HCIBFUSB is not set
-# CONFIG_BT_HCIVHCI is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
@@ -485,31 +467,17 @@
#
# Input device support
#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT is not set
#
# Input I/O drivers
#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_LIBPS2 is not set
# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
#
# Input Device Drivers
@@ -525,6 +493,7 @@
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -542,6 +511,8 @@
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -559,6 +530,8 @@
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
+# CONFIG_RTC_LIB is not set
+# CONFIG_RTC_CLASS is not set
#
# Ftape, the floppy tape device driver
@@ -660,7 +633,9 @@
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -686,9 +661,21 @@
# CONFIG_SOUND is not set
#
+# Generic devices
+#
+# CONFIG_SND_MPU401_UART is not set
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
+# CONFIG_NET_PCMCIA is not set
#
# PC-card bridges
@@ -734,6 +721,7 @@
# USB Input Devices
#
# CONFIG_USB_HID is not set
+# HID_SUPPORT is not set
#
# USB HID Boot Protocol drivers
@@ -829,7 +817,7 @@
#
# Hardware crypto devices
-#
+# CONFIG_CRYPTO_HW is not set
#
# Library routines
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index 105bb5e..62f0e75 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -27,6 +27,7 @@
extern void __ashldi3(void);
extern void __ashrdi3(void);
extern void __lshrdi3(void);
+extern void __negdi2(void);
extern void iounmap(volatile void * __iomem);
/* Platform dependent support */
@@ -34,19 +35,6 @@
EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(loops_per_usec);
-/* String functions */
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-
/* Math functions */
EXPORT_SYMBOL(__Udiv);
EXPORT_SYMBOL(__Umod);
@@ -55,6 +43,7 @@
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__negdi2);
/* Memory functions */
EXPORT_SYMBOL(__ioremap);
@@ -84,4 +73,4 @@
EXPORT_SYMBOL(del_fast_timer);
EXPORT_SYMBOL(schedule_usleep);
#endif
-
+EXPORT_SYMBOL(csum_partial);
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
index 5c27ff8..2dfac8c 100644
--- a/arch/cris/kernel/irq.c
+++ b/arch/cris/kernel/irq.c
@@ -2,7 +2,7 @@
*
* linux/arch/cris/kernel/irq.c
*
- * Copyright (c) 2000,2001 Axis Communications AB
+ * Copyright (c) 2000,2007 Axis Communications AB
*
* Authors: Bjorn Wesen (bjornw@axis.com)
*
@@ -92,14 +92,16 @@
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
unsigned long sp;
+ struct pt_regs *old_regs = set_irq_regs(regs);
irq_enter();
sp = rdsp();
if (unlikely((sp & (PAGE_SIZE - 1)) < (PAGE_SIZE/8))) {
printk("do_IRQ: stack overflow: %lX\n", sp);
show_stack(NULL, (unsigned long *)sp);
}
- __do_IRQ(irq, regs);
+ __do_IRQ(irq);
irq_exit();
+ set_irq_regs(old_regs);
}
void weird_irq(void)
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 123451c..9ca558f 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -195,6 +195,11 @@
*/
void (*pm_idle)(void);
+extern void default_idle(void);
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
index 1085d03..3ccd20e 100644
--- a/arch/cris/kernel/ptrace.c
+++ b/arch/cris/kernel/ptrace.c
@@ -81,13 +81,13 @@
/* notification of userspace execution resumption
* - triggered by current->work.notify_resume
*/
-extern int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
+extern int do_signal(int canrestart, struct pt_regs *regs);
-void do_notify_resume(int canrestart, sigset_t *oldset, struct pt_regs *regs,
+void do_notify_resume(int canrestart, struct pt_regs *regs,
__u32 thread_info_flags )
{
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(canrestart,oldset,regs);
+ do_signal(canrestart,regs);
}
diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c
index 514359b..8b99841 100644
--- a/arch/cris/kernel/sys_cris.c
+++ b/arch/cris/kernel/sys_cris.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <linux/mm.h>
+#include <linux/fs.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index acfd045..7a2cc7e 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -171,10 +171,6 @@
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
- printk(KERN_DEBUG
- "rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n",
- sec, min, hour, day, mon, year);
-
BCD_TO_BIN(sec);
BCD_TO_BIN(min);
BCD_TO_BIN(hour);
@@ -207,12 +203,12 @@
cris_do_profile(struct pt_regs* regs)
{
-#if CONFIG_SYSTEM_PROFILER
+#ifdef CONFIG_SYSTEM_PROFILER
cris_profile_sample(regs);
#endif
-#if CONFIG_PROFILING
- profile_tick(CPU_PROFILING, regs);
+#ifdef CONFIG_PROFILING
+ profile_tick(CPU_PROFILING);
#endif
}
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 5181bf5..8e8f8b6 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -1113,7 +1113,7 @@
if (md->num_pages == 0) /* should not happen */
continue;
- flags = IORESOURCE_MEM;
+ flags = IORESOURCE_MEM | IORESOURCE_BUSY;
switch (md->type) {
case EFI_MEMORY_MAPPED_IO:
@@ -1135,12 +1135,11 @@
case EFI_ACPI_MEMORY_NVS:
name = "ACPI Non-volatile Storage";
- flags |= IORESOURCE_BUSY;
break;
case EFI_UNUSABLE_MEMORY:
name = "reserved";
- flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED;
+ flags |= IORESOURCE_DISABLED;
break;
case EFI_RESERVED_TYPE:
@@ -1149,7 +1148,6 @@
case EFI_ACPI_RECLAIM_MEMORY:
default:
name = "reserved";
- flags |= IORESOURCE_BUSY;
break;
}
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 33506ff..5b10ac1 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -430,6 +430,7 @@
break;
default:
+ spin_unlock_irq(¤t->sighand->siglock);
return -EINVAL;
}
recalc_sigpending();
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index 1899601..3f23d9f 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -525,6 +525,7 @@
intassign1 |= (uint16_t)assign << 9;
break;
default:
+ spin_unlock_irq(&desc->lock);
return -EINVAL;
}
@@ -592,6 +593,7 @@
intassign3 |= (uint16_t)assign << 12;
break;
default:
+ spin_unlock_irq(&desc->lock);
return -EINVAL;
}
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 4e16534..bd87626 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -107,6 +107,9 @@
# No AltiVec instruction when building kernel
KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
+# No SPE instruction when building kernel
+KBUILD_CFLAGS += $(call cc-option,-mno-spe)
+
# Enable unit-at-a-time mode when possible. It shrinks the
# kernel considerably.
KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 3ef51fb..9c74fdf 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -186,7 +186,9 @@
pitch = *prop;
if (pitch == 1)
pitch = 0x1000;
- prop = of_get_property(np, "address", NULL);
+ prop = of_get_property(np, "linux,bootx-addr", NULL);
+ if (prop == NULL)
+ prop = of_get_property(np, "address", NULL);
if (prop)
address = *prop;
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index a7572cf..69a91bd 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -251,6 +251,9 @@
bne- 2f
1:
#endif /* CONFIG_44x */
+BEGIN_FTR_SECTION
+ lwarx r7,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
lwz r4,_LINK(r1)
lwz r5,_CCR(r1)
@@ -717,6 +720,9 @@
mtctr r11
PPC405_ERR77(0,r1)
+BEGIN_FTR_SECTION
+ lwarx r11,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 4beb632..c0d7772 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -829,7 +829,7 @@
*dec = decrementer_clockevent;
dec->cpumask = cpumask_of_cpu(cpu);
- printk(KERN_INFO "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n",
+ printk(KERN_DEBUG "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n",
dec->name, dec->mult, dec->shift, cpu);
clockevents_register_device(dec);
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index d9c82d3..c0f5cff 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -19,8 +19,6 @@
*
*/
-#undef DEBUG
-
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -66,12 +64,6 @@
#include "mmu_decl.h"
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
-
#if PGTABLE_RANGE > USER_VSID_RANGE
#warning Limited user VSID range means pagetable space is wasted
#endif
@@ -175,8 +167,8 @@
int size = pgtable_cache_size[i];
const char *name = pgtable_cache_name[i];
- DBG("Allocating page table cache %s (#%d) "
- "for size: %08x...\n", name, i, size);
+ pr_debug("Allocating page table cache %s (#%d) "
+ "for size: %08x...\n", name, i, size);
pgtable_cache[i] = kmem_cache_create(name,
size, size,
SLAB_PANIC,
@@ -239,8 +231,8 @@
if (!p)
return -ENOMEM;
- printk(KERN_WARNING "vmemmap %08lx allocated at %p, "
- "physical %08lx.\n", start, p, __pa(p));
+ pr_debug("vmemmap %08lx allocated at %p, physical %08lx.\n",
+ start, p, __pa(p));
mapped = htab_bolt_mapping(start, start + page_size,
__pa(p), mode_rw, mmu_linear_psize,
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index eafbca5..e2d867c 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -54,12 +54,10 @@
((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
/ sizeof(pgtable_free_t))
-#ifdef CONFIG_SMP
static void pte_free_smp_sync(void *arg)
{
/* Do nothing, just ensure we sync with all CPUs */
}
-#endif
/* This is only called when we are critically out of memory
* (and fail to get a page in pte_free_tlb).
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 66c8ad4..165981c 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -77,8 +77,6 @@
int i = 0;
int ret = 0;
- printk("cpm_muram_init\n");
-
spin_lock_init(&cpm_muram_lock);
/* initialize the info header */
rh_init(&cpm_muram_info, 1,
@@ -193,7 +191,7 @@
EXPORT_SYMBOL(cpm_muram_addr);
/**
- * cpm_muram_phys - turn a muram virtual address into a DMA address
+ * cpm_muram_dma - turn a muram virtual address into a DMA address
* @offset: virtual address from cpm_muram_addr() to convert
*/
dma_addr_t cpm_muram_dma(void __iomem *addr)
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index b19bfef..59e77eb 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -251,6 +251,9 @@
bne- 2f
1:
#endif /* CONFIG_44x */
+BEGIN_FTR_SECTION
+ lwarx r7,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
lwz r4,_LINK(r1)
lwz r5,_CCR(r1)
@@ -713,6 +716,9 @@
mtctr r11
PPC405_ERR77(0,r1)
+BEGIN_FTR_SECTION
+ lwarx r11,0,r1
+END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
stwcx. r0,0,r1 /* to clear the reservation */
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 768a5d1..31999bc 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -168,7 +168,7 @@
$(Q)mkdir -p $(objtree)/include/asm-um
$(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch
else
- $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(HEADER_ARCH) arch
+ $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(SUBARCH) arch
endif
$(objtree)/$(ARCH_DIR)/include:
@@ -180,7 +180,7 @@
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
else
- $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
+ $(Q)cd $(ARCH_DIR)/include && ln -fsn sysdep-$(SUBARCH) sysdep
endif
$(ARCH_DIR)/os:
@@ -188,7 +188,7 @@
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree)/$(ARCH_DIR)/os-$(OS) $(ARCH_DIR)/os
else
- $(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os
+ $(Q)cd $(ARCH_DIR) && ln -fsn os-$(OS) os
endif
# Generated files
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 8c01fa8..73681f1 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -753,6 +753,7 @@
.remove = net_remove,
};
+#ifdef CONFIG_INET
static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
@@ -789,14 +790,13 @@
.notifier_call = uml_inetaddr_event,
};
-static int uml_net_init(void)
+static void inet_register(void)
{
struct list_head *ele;
struct uml_net_private *lp;
struct in_device *ip;
struct in_ifaddr *in;
- mconsole_register_dev(&net_mc);
register_inetaddr_notifier(¨_inetaddr_notifier);
/* Devices may have been opened already, so the uml_inetaddr_notifier
@@ -816,7 +816,17 @@
}
}
spin_unlock(&opened_lock);
+}
+#else
+static inline void inet_register(void)
+{
+}
+#endif
+static int uml_net_init(void)
+{
+ mconsole_register_dev(&net_mc);
+ inet_register();
return 0;
}
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 99033ff..1723fac 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -1,11 +1,13 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#ifndef __USER_H__
#define __USER_H__
+#include "uml-config.h"
+
/*
* The usual definition - copied here because the kernel provides its own,
* fancier, type-safe, definition. Using that one would require
@@ -23,8 +25,17 @@
extern void panic(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+
+#ifdef UML_CONFIG_PRINTK
extern int printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+#else
+static inline int printk(const char *fmt, ...)
+{
+ return 0;
+}
+#endif
+
extern void schedule(void);
extern int in_aton(char *str);
extern int open_gdb_chan(void);
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 70c2d62..ba11ccd 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -347,14 +347,15 @@
{
int err;
- err = request_irq(irq, handler, irqflags, devname, dev_id);
- if (err)
- return err;
-
- if (fd != -1)
+ if (fd != -1) {
err = activate_fd(irq, fd, type, dev_id);
- return err;
+ if (err)
+ return err;
+ }
+
+ return request_irq(irq, handler, irqflags, devname, dev_id);
}
+
EXPORT_SYMBOL(um_request_irq);
EXPORT_SYMBOL(reactivate_fd);
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
index d119f4f..8d07a7a 100644
--- a/arch/um/kernel/skas/clone.c
+++ b/arch/um/kernel/skas/clone.c
@@ -3,7 +3,6 @@
#include <sys/mman.h>
#include <sys/time.h>
#include <asm/unistd.h>
-#include <asm/page.h>
#include "as-layout.h"
#include "ptrace_user.h"
#include "skas.h"
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index b542a3a..f834627 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -496,8 +496,7 @@
n = recvmsg(fd, &msg, 0);
if(n < 0)
return -errno;
-
- else if(n != sizeof(iov.iov_len))
+ else if(n != iov.iov_len)
*helper_pid_out = -1;
cmsg = CMSG_FIRSTHDR(&msg);
diff --git a/arch/x86/Kconfig.i386 b/arch/x86/Kconfig
similarity index 74%
rename from arch/x86/Kconfig.i386
rename to arch/x86/Kconfig
index 7331efe..1eb5997 100644
--- a/arch/x86/Kconfig.i386
+++ b/arch/x86/Kconfig
@@ -1,18 +1,24 @@
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.txt.
-#
+# x86 configuration
+mainmenu "Linux Kernel Configuration for x86"
-mainmenu "Linux Kernel Configuration"
+# Select 32 or 64 bit
+config 64BIT
+ bool "64-bit kernel"
+ default n
+ help
+ Say yes to build a 64-bit kernel - formerly known as x86_64
+ Say no to build a 32-bit kernel - formerly known as i386
config X86_32
+ def_bool !64BIT
+
+config X86_64
+ def_bool 64BIT
+
+### Arch settings
+config X86
bool
default y
- help
- This is Linux's home port. Linux was originally native to the Intel
- 386, and runs on all the later x86 processors including the Intel
- 486, 586, Pentiums, and various instruction-set-compatible chips by
- AMD, Cyrix, and others.
config GENERIC_TIME
bool
@@ -33,7 +39,7 @@
config GENERIC_CLOCKEVENTS_BROADCAST
bool
default y
- depends on X86_LOCAL_APIC
+ depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
config LOCKDEP_SUPPORT
bool
@@ -47,10 +53,6 @@
bool
default y
-config X86
- bool
- default y
-
config MMU
bool
default y
@@ -61,7 +63,7 @@
config QUICKLIST
bool
- default y
+ default X86_32
config SBUS
bool
@@ -91,6 +93,76 @@
bool
default y
+config RWSEM_GENERIC_SPINLOCK
+ def_bool !X86_XADD
+
+config RWSEM_XCHGADD_ALGORITHM
+ def_bool X86_XADD
+
+config ARCH_HAS_ILOG2_U32
+ def_bool n
+
+config ARCH_HAS_ILOG2_U64
+ def_bool n
+
+config GENERIC_CALIBRATE_DELAY
+ def_bool y
+
+config GENERIC_TIME_VSYSCALL
+ bool
+ default X86_64
+
+
+
+
+
+config ZONE_DMA32
+ bool
+ default X86_64
+
+config ARCH_POPULATES_NODE_MAP
+ def_bool y
+
+config AUDIT_ARCH
+ bool
+ default X86_64
+
+# Use the generic interrupt handling code in kernel/irq/:
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+config GENERIC_PENDING_IRQ
+ bool
+ depends on GENERIC_HARDIRQS && SMP
+ default y
+
+config X86_SMP
+ bool
+ depends on X86_32 && SMP && !X86_VOYAGER
+ default y
+
+config X86_HT
+ bool
+ depends on SMP && !(X86_VISWS || X86_VOYAGER || MK8)
+ default y
+
+config X86_BIOS_REBOOT
+ bool
+ depends on X86_32 && !(X86_VISWS || X86_VOYAGER)
+ default y
+
+config X86_TRAMPOLINE
+ bool
+ depends on X86_SMP || (X86_VOYAGER && SMP)
+ default y
+
+config KTIME_SCALAR
+ def_bool X86_32
source "init/Kconfig"
menu "Processor type and features"
@@ -137,6 +209,7 @@
config X86_ELAN
bool "AMD Elan"
+ depends on X86_32
help
Select this for an AMD Elan processor.
@@ -146,6 +219,7 @@
config X86_VOYAGER
bool "Voyager (NCR)"
+ depends on X86_32
select SMP if !BROKEN
help
Voyager is an MCA-based 32-way capable SMP architecture proprietary
@@ -160,6 +234,7 @@
bool "NUMAQ (IBM/Sequent)"
select SMP
select NUMA
+ depends on X86_32
help
This option is used for getting Linux to run on a (IBM/Sequent) NUMA
multiquad box. This changes the way that processors are bootstrapped,
@@ -169,7 +244,7 @@
config X86_SUMMIT
bool "Summit/EXA (IBM x440)"
- depends on SMP
+ depends on X86_32 && SMP
help
This option is needed for IBM systems that use the Summit/EXA chipset.
In particular, it is needed for the x440.
@@ -179,7 +254,7 @@
config X86_BIGSMP
bool "Support for other sub-arch SMP systems with more than 8 CPUs"
- depends on SMP
+ depends on X86_32 && SMP
help
This option is needed for the systems that have more than 8 CPUs
and if the system is not of any sub-arch type above.
@@ -188,6 +263,7 @@
config X86_VISWS
bool "SGI 320/540 (Visual Workstation)"
+ depends on X86_32
help
The SGI Visual Workstation series is an IA32-based workstation
based on SGI systems chips with some legacy PC hardware attached.
@@ -199,6 +275,7 @@
config X86_GENERICARCH
bool "Generic architecture (Summit, bigsmp, ES7000, default)"
+ depends on X86_32
help
This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
It is intended for a generic binary kernel.
@@ -206,18 +283,27 @@
config X86_ES7000
bool "Support for Unisys ES7000 IA32 series"
- depends on SMP
+ depends on X86_32 && SMP
help
Support for Unisys ES7000 systems. Say 'Y' here if this kernel is
supposed to run on an IA32-based Unisys ES7000 system.
Only choose this option if you have such a system, otherwise you
should say N here.
+config X86_VSMP
+ bool "Support for ScaleMP vSMP"
+ depends on X86_64 && PCI
+ help
+ Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
+ supposed to run on these EM64T-based machines. Only choose this option
+ if you have one of these machines.
+
endchoice
config SCHED_NO_NO_OMIT_FRAME_POINTER
bool "Single-depth WCHAN output"
default y
+ depends on X86_32
help
Calculate simpler /proc/<PID>/wchan values. If this option
is disabled then wchan values will recurse back to the
@@ -228,7 +314,7 @@
config PARAVIRT
bool
- depends on !(X86_VISWS || X86_VOYAGER)
+ depends on X86_32 && !(X86_VISWS || X86_VOYAGER)
help
This changes the kernel so it can modify itself when it is run
under a hypervisor, potentially improving performance significantly
@@ -237,6 +323,7 @@
menuconfig PARAVIRT_GUEST
bool "Paravirtualized guest support"
+ depends on X86_32
help
Say Y here to get to see options related to running Linux under
various hypervisors. This option alone does not add any kernel code.
@@ -264,7 +351,7 @@
config ACPI_SRAT
bool
default y
- depends on ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
+ depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
select ACPI_NUMA
config HAVE_ARCH_PARSE_SRAT
@@ -275,12 +362,12 @@
config X86_SUMMIT_NUMA
bool
default y
- depends on NUMA && (X86_SUMMIT || X86_GENERICARCH)
+ depends on X86_32 && NUMA && (X86_SUMMIT || X86_GENERICARCH)
config X86_CYCLONE_TIMER
bool
default y
- depends on X86_SUMMIT || X86_GENERICARCH
+ depends on X86_32 && X86_SUMMIT || X86_GENERICARCH
config ES7000_CLUSTERED_APIC
bool
@@ -290,21 +377,89 @@
source "arch/x86/Kconfig.cpu"
config HPET_TIMER
- bool "HPET Timer Support"
+ bool
+ prompt "HPET Timer Support" if X86_32
+ default X86_64
help
- This enables the use of the HPET for the kernel's internal timer.
- HPET is the next generation timer replacing legacy 8254s.
- You can safely choose Y here. However, HPET will only be
- activated if the platform and the BIOS support this feature.
- Otherwise the 8254 will be used for timing services.
+ Use the IA-PC HPET (High Precision Event Timer) to manage
+ time in preference to the PIT and RTC, if a HPET is
+ present.
+ HPET is the next generation timer replacing legacy 8254s.
+ The HPET provides a stable time base on SMP
+ systems, unlike the TSC, but it is more expensive to access,
+ as it is off-chip. You can find the HPET spec at
+ <http://www.intel.com/hardwaredesign/hpetspec.htm>.
- Choose N to continue using the legacy 8254 timer.
+ You can safely choose Y here. However, HPET will only be
+ activated if the platform and the BIOS support this feature.
+ Otherwise the 8254 will be used for timing services.
+
+ Choose N to continue using the legacy 8254 timer.
config HPET_EMULATE_RTC
bool
depends on HPET_TIMER && RTC=y
default y
+# Mark as embedded because too many people got it wrong.
+# The code disables itself when not needed.
+config GART_IOMMU
+ bool "GART IOMMU support" if EMBEDDED
+ default y
+ select SWIOTLB
+ select AGP
+ depends on X86_64 && PCI
+ help
+ Support for full DMA access of devices with 32bit memory access only
+ on systems with more than 3GB. This is usually needed for USB,
+ sound, many IDE/SATA chipsets and some other devices.
+ Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
+ based hardware IOMMU and a software bounce buffer based IOMMU used
+ on Intel systems and as fallback.
+ The code is only active when needed (enough memory and limited
+ device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
+ too.
+
+config CALGARY_IOMMU
+ bool "IBM Calgary IOMMU support"
+ select SWIOTLB
+ depends on X86_64 && PCI && EXPERIMENTAL
+ help
+ Support for hardware IOMMUs in IBM's xSeries x366 and x460
+ systems. Needed to run systems with more than 3GB of memory
+ properly with 32-bit PCI devices that do not support DAC
+ (Double Address Cycle). Calgary also supports bus level
+ isolation, where all DMAs pass through the IOMMU. This
+ prevents them from going anywhere except their intended
+ destination. This catches hard-to-find kernel bugs and
+ mis-behaving drivers and devices that do not use the DMA-API
+ properly to set up their DMA buffers. The IOMMU can be
+ turned off at boot time with the iommu=off parameter.
+ Normally the kernel will make the right choice by itself.
+ If unsure, say Y.
+
+config CALGARY_IOMMU_ENABLED_BY_DEFAULT
+ bool "Should Calgary be enabled by default?"
+ default y
+ depends on CALGARY_IOMMU
+ help
+ Should Calgary be enabled by default? if you choose 'y', Calgary
+ will be used (if it exists). If you choose 'n', Calgary will not be
+ used even if it exists. If you choose 'n' and would like to use
+ Calgary anyway, pass 'iommu=calgary' on the kernel command line.
+ If unsure, say Y.
+
+# need this always selected by IOMMU for the VIA workaround
+config SWIOTLB
+ bool
+ help
+ Support for software bounce buffers used on x86-64 systems
+ which don't have a hardware IOMMU (e.g. the current generation
+ of Intel's x86-64 CPUs). Using this PCI devices which can only
+ access 32-bits of memory can be used on systems with more than
+ 3 GB of memory. If unsure, say Y.
+
+
config NR_CPUS
int "Maximum number of CPUs (2-255)"
range 2 255
@@ -321,7 +476,7 @@
config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
- depends on X86_HT
+ depends on (X86_64 && SMP) || (X86_32 && X86_HT)
help
SMT scheduler support improves the CPU scheduler's decision making
when dealing with Intel Pentium 4 chips with HyperThreading at a
@@ -330,7 +485,7 @@
config SCHED_MC
bool "Multi-core scheduler support"
- depends on X86_HT
+ depends on (X86_64 && SMP) || (X86_32 && X86_HT)
default y
help
Multi-core scheduler support improves the CPU scheduler's decision
@@ -341,7 +496,7 @@
config X86_UP_APIC
bool "Local APIC support on uniprocessors"
- depends on !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH)
+ depends on X86_32 && !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH)
help
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
@@ -366,17 +521,17 @@
config X86_LOCAL_APIC
bool
- depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH
+ depends on X86_64 || (X86_32 && (X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH))
default y
config X86_IO_APIC
bool
- depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH
+ depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH))
default y
config X86_VISWS_APIC
bool
- depends on X86_VISWS
+ depends on X86_32 && X86_VISWS
default y
config X86_MCE
@@ -396,9 +551,25 @@
to disable it. MCE support simply ignores non-MCE processors like
the 386 and 486, so nearly everyone can say Y here.
+config X86_MCE_INTEL
+ bool "Intel MCE features"
+ depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+ default y
+ help
+ Additional support for intel specific MCE features such as
+ the thermal monitor.
+
+config X86_MCE_AMD
+ bool "AMD MCE features"
+ depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+ default y
+ help
+ Additional support for AMD specific MCE features such as
+ the DRAM Error Threshold.
+
config X86_MCE_NONFATAL
tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
- depends on X86_MCE
+ depends on X86_32 && X86_MCE
help
Enabling this feature starts a timer that triggers every 5 seconds which
will look at the machine check registers to see if anything happened.
@@ -411,14 +582,15 @@
config X86_MCE_P4THERMAL
bool "check for P4 thermal throttling interrupt."
- depends on X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS
+ depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS
help
Enabling this feature will cause a message to be printed when the P4
enters thermal throttling.
config VM86
- default y
bool "Enable VM86 support" if EMBEDDED
+ default y
+ depends on X86_32
help
This option is required by programs like DOSEMU to run 16-bit legacy
code on X86 processors. It also may be needed by software like
@@ -427,6 +599,7 @@
config TOSHIBA
tristate "Toshiba Laptop support"
+ depends on X86_32
---help---
This adds a driver to safely access the System Management Mode of
the CPU on Toshiba portables with a genuine Toshiba BIOS. It does
@@ -442,6 +615,7 @@
config I8K
tristate "Dell laptop support"
+ depends on X86_32
---help---
This adds a driver to safely access the System Management Mode
of the CPU on the Dell Inspiron 8000. The System Management Mode
@@ -462,7 +636,7 @@
config X86_REBOOTFIXUPS
bool "Enable X86 board specific fixups for reboot"
- depends on X86
+ depends on X86_32 && X86
default n
---help---
This enables chipset and/or board specific fixups to be done
@@ -517,12 +691,11 @@
with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
/dev/cpu/31/cpuid.
-source "drivers/firmware/Kconfig"
-
choice
prompt "High Memory Support"
default HIGHMEM4G if !X86_NUMAQ
default HIGHMEM64G if X86_NUMAQ
+ depends on X86_32
config NOHIGHMEM
bool "off"
@@ -582,6 +755,7 @@
depends on EXPERIMENTAL
prompt "Memory split" if EMBEDDED
default VMSPLIT_3G
+ depends on X86_32
help
Select the desired split between kernel and user memory.
@@ -619,16 +793,17 @@
default 0x78000000 if VMSPLIT_2G_OPT
default 0x40000000 if VMSPLIT_1G
default 0xC0000000
+ depends on X86_32
config HIGHMEM
bool
- depends on HIGHMEM64G || HIGHMEM4G
+ depends on X86_32 && (HIGHMEM64G || HIGHMEM4G)
default y
config X86_PAE
bool "PAE (Physical Address Extension) Support"
default n
- depends on !HIGHMEM4G
+ depends on X86_32 && !HIGHMEM4G
select RESOURCES_64BIT
help
PAE is required for NX support, and furthermore enables
@@ -639,46 +814,82 @@
# Common NUMA Features
config NUMA
bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)"
- depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) && EXPERIMENTAL
+ depends on SMP
+ depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) && EXPERIMENTAL)
default n if X86_PC
default y if (X86_NUMAQ || X86_SUMMIT)
help
- NUMA support for i386. This is currently highly experimental
- and should be only used for kernel development. It might also
- cause boot failures.
+ Enable NUMA (Non Uniform Memory Access) support.
+ The kernel will try to allocate memory used by a CPU on the
+ local memory controller of the CPU and add some more
+ NUMA awareness to the kernel.
+
+ For i386 this is currently highly experimental and should be only
+ used for kernel development. It might also cause boot failures.
+ For x86_64 this is recommended on all multiprocessor Opteron systems.
+ If the system is EM64T, you should say N unless your system is
+ EM64T NUMA.
comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
- depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+ depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+
+config K8_NUMA
+ bool "Old style AMD Opteron NUMA detection"
+ depends on X86_64 && NUMA && PCI
+ default y
+ help
+ Enable K8 NUMA node topology detection. You should say Y here if
+ you have a multi processor AMD K8 system. This uses an old
+ method to read the NUMA configuration directly from the builtin
+ Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
+ instead, which also takes priority if both are compiled in.
+
+config X86_64_ACPI_NUMA
+ bool "ACPI NUMA detection"
+ depends on X86_64 && NUMA && ACPI && PCI
+ select ACPI_NUMA
+ default y
+ help
+ Enable ACPI SRAT based node topology detection.
+
+config NUMA_EMU
+ bool "NUMA emulation"
+ depends on X86_64 && NUMA
+ help
+ Enable NUMA emulation. A flat machine will be split
+ into virtual nodes when booted with "numa=fake=N", where N is the
+ number of nodes. This is only useful for debugging.
config NODES_SHIFT
int
+ default "6" if X86_64
default "4" if X86_NUMAQ
default "3"
depends on NEED_MULTIPLE_NODES
config HAVE_ARCH_BOOTMEM_NODE
bool
- depends on NUMA
+ depends on X86_32 && NUMA
default y
config ARCH_HAVE_MEMORY_PRESENT
bool
- depends on DISCONTIGMEM
+ depends on X86_32 && DISCONTIGMEM
default y
config NEED_NODE_MEMMAP_SIZE
bool
- depends on DISCONTIGMEM || SPARSEMEM
+ depends on X86_32 && (DISCONTIGMEM || SPARSEMEM)
default y
config HAVE_ARCH_ALLOC_REMAP
bool
- depends on NUMA
+ depends on X86_32 && NUMA
default y
config ARCH_FLATMEM_ENABLE
def_bool y
- depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC)
+ depends on (X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC) || (X86_64 && !NUMA)
config ARCH_DISCONTIGMEM_ENABLE
def_bool y
@@ -690,21 +901,23 @@
config ARCH_SPARSEMEM_ENABLE
def_bool y
- depends on (NUMA || (X86_PC && EXPERIMENTAL))
- select SPARSEMEM_STATIC
+ depends on NUMA || (EXPERIMENTAL && (X86_PC || X86_64))
+ select SPARSEMEM_STATIC if X86_32
+ select SPARSEMEM_VMEMMAP_ENABLE if X86_64
config ARCH_SELECT_MEMORY_MODEL
def_bool y
- depends on ARCH_SPARSEMEM_ENABLE
+ depends on X86_32 && ARCH_SPARSEMEM_ENABLE
-config ARCH_POPULATES_NODE_MAP
- def_bool y
+config ARCH_MEMORY_PROBE
+ def_bool X86_64
+ depends on MEMORY_HOTPLUG
source "mm/Kconfig"
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
- depends on HIGHMEM4G || HIGHMEM64G
+ depends on X86_32 && (HIGHMEM4G || HIGHMEM64G)
help
The VM uses one page table entry for each page of physical memory.
For systems with a lot of RAM, this can be wasteful of precious
@@ -712,7 +925,8 @@
entries in high memory.
config MATH_EMULATION
- bool "Math emulation"
+ bool
+ prompt "Math emulation" if X86_32
---help---
Linux can emulate a math coprocessor (used for floating point
operations) if you don't have one. 486DX and Pentium processors have
@@ -772,7 +986,7 @@
config EFI
bool "Boot from EFI support"
- depends on ACPI
+ depends on X86_32 && ACPI
default n
---help---
This enables the kernel to boot on EFI platforms using
@@ -789,18 +1003,18 @@
kernel should continue to boot on existing non-EFI platforms.
config IRQBALANCE
- bool "Enable kernel irq balancing"
- depends on SMP && X86_IO_APIC
+ bool "Enable kernel irq balancing"
+ depends on X86_32 && SMP && X86_IO_APIC
default y
help
- The default yes will allow the kernel to do irq load balancing.
+ The default yes will allow the kernel to do irq load balancing.
Saying no will keep the kernel from doing irq load balancing.
# turning this on wastes a bunch of space.
# Summit needs it only when NUMA is on
config BOOT_IOREMAP
bool
- depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
+ depends on X86_32 && (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
default y
config SECCOMP
@@ -820,6 +1034,30 @@
If unsure, say Y. Only embedded should say N here.
+config CC_STACKPROTECTOR
+ bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
+ depends on X86_64 && EXPERIMENTAL
+ help
+ This option turns on the -fstack-protector GCC feature. This
+ feature puts, at the beginning of critical functions, a canary
+ value on the stack just before the return address, and validates
+ the value just before actually returning. Stack based buffer
+ overflows (that need to overwrite this return address) now also
+ overwrite the canary, which gets detected and the attack is then
+ neutralized via a kernel panic.
+
+ This feature requires gcc version 4.2 or above, or a distribution
+ gcc with the feature backported. Older versions are automatically
+ detected and for those versions, this configuration option is ignored.
+
+config CC_STACKPROTECTOR_ALL
+ bool "Use stack-protector for all functions"
+ depends on CC_STACKPROTECTOR
+ help
+ Normally, GCC only inserts the canary value protection for
+ functions that use large-ish on-stack buffers. By enabling
+ this option, GCC will be asked to do this for ALL functions.
+
source kernel/Kconfig.hz
config KEXEC
@@ -841,7 +1079,7 @@
config CRASH_DUMP
bool "kernel crash dumps (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on HIGHMEM
+ depends on X86_64 || (X86_32 && HIGHMEM)
help
Generate crash dump after being started by kexec.
This should be normally only set in special crash dump kernels
@@ -856,6 +1094,7 @@
config PHYSICAL_START
hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
default "0x1000000" if X86_NUMAQ
+ default "0x200000" if X86_64
default "0x100000"
help
This gives the physical address where the kernel is loaded.
@@ -908,25 +1147,31 @@
must live at a different physical address than the primary
kernel.
+ Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
+ it has been loaded at and the compile time physical address
+ (CONFIG_PHYSICAL_START) is ignored.
+
config PHYSICAL_ALIGN
- hex "Alignment value to which kernel should be aligned"
- default "0x100000"
+ hex
+ prompt "Alignment value to which kernel should be aligned" if X86_32
+ default "0x100000" if X86_32
+ default "0x200000" if X86_64
range 0x2000 0x400000
help
This value puts the alignment restrictions on physical address
- where kernel is loaded and run from. Kernel is compiled for an
- address which meets above alignment restriction.
+ where kernel is loaded and run from. Kernel is compiled for an
+ address which meets above alignment restriction.
- If bootloader loads the kernel at a non-aligned address and
- CONFIG_RELOCATABLE is set, kernel will move itself to nearest
- address aligned to above value and run from there.
+ If bootloader loads the kernel at a non-aligned address and
+ CONFIG_RELOCATABLE is set, kernel will move itself to nearest
+ address aligned to above value and run from there.
- If bootloader loads the kernel at a non-aligned address and
- CONFIG_RELOCATABLE is not set, kernel will ignore the run time
- load address and decompress itself to the address it has been
- compiled for and run from there. The address for which kernel is
- compiled already meets above alignment restrictions. Hence the
- end result is that kernel runs from a physical address meeting
+ If bootloader loads the kernel at a non-aligned address and
+ CONFIG_RELOCATABLE is not set, kernel will ignore the run time
+ load address and decompress itself to the address it has been
+ compiled for and run from there. The address for which kernel is
+ compiled already meets above alignment restrictions. Hence the
+ end result is that kernel runs from a physical address meeting
above alignment restrictions.
Don't change this unless you know what you are doing.
@@ -938,10 +1183,13 @@
Say Y here to experiment with turning CPUs off and on, and to
enable suspend on SMP systems. CPUs can be controlled through
/sys/devices/system/cpu.
+ Say N if you want to disable CPU hotplug and don't need to
+ suspend.
config COMPAT_VDSO
bool "Compat VDSO support"
default y
+ depends on X86_32
help
Map the VDSO to the predictable old-style address too.
---help---
@@ -955,18 +1203,35 @@
config ARCH_ENABLE_MEMORY_HOTPLUG
def_bool y
- depends on HIGHMEM
+ depends on X86_64 || (X86_32 && HIGHMEM)
-menu "Power management options (ACPI, APM)"
+config MEMORY_HOTPLUG_RESERVE
+ def_bool X86_64
+ depends on (MEMORY_HOTPLUG && DISCONTIGMEM)
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+ def_bool X86_64
+ depends on NUMA
+
+config OUT_OF_LINE_PFN_TO_PAGE
+ def_bool X86_64
+ depends on DISCONTIGMEM
+
+menu "Power management options"
depends on !X86_VOYAGER
-source kernel/power/Kconfig
+config ARCH_HIBERNATION_HEADER
+ bool
+ depends on X86_64 && HIBERNATION
+ default y
+
+source "kernel/power/Kconfig"
source "drivers/acpi/Kconfig"
menuconfig APM
tristate "APM (Advanced Power Management) BIOS support"
- depends on PM_SLEEP && !X86_VISWS
+ depends on X86_32 && PM_SLEEP && !X86_VISWS
---help---
APM is a BIOS specification for saving power using several different
techniques. This is mostly useful for battery powered laptops with
@@ -1092,13 +1357,14 @@
endif # APM
-source "arch/x86/kernel/cpu/cpufreq/Kconfig_32"
+source "arch/x86/kernel/cpu/cpufreq/Kconfig"
source "drivers/cpuidle/Kconfig"
endmenu
-menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+
+menu "Bus options (PCI etc.)"
config PCI
bool "PCI support" if !X86_VISWS
@@ -1118,7 +1384,7 @@
choice
prompt "PCI access mode"
- depends on PCI && !X86_VISWS
+ depends on X86_32 && PCI && !X86_VISWS
default PCI_GOANY
---help---
On PCI systems, the BIOS can be used to detect the PCI devices and
@@ -1151,17 +1417,18 @@
config PCI_BIOS
bool
- depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
+ depends on X86_32 && !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
default y
+# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
config PCI_DIRECT
bool
- depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
+ depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
default y
config PCI_MMCONFIG
bool
- depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
+ depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
default y
config PCI_DOMAINS
@@ -1169,14 +1436,52 @@
depends on PCI
default y
+config PCI_MMCONFIG
+ bool "Support mmconfig PCI config space access"
+ depends on X86_64 && PCI && ACPI
+
+config DMAR
+ bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
+ depends on X86_64 && PCI_MSI && ACPI && EXPERIMENTAL
+ help
+ DMA remapping (DMAR) devices support enables independent address
+ translations for Direct Memory Access (DMA) from devices.
+ These DMA remapping devices are reported via ACPI tables
+ and include PCI device scope covered by these DMA
+ remapping devices.
+
+config DMAR_GFX_WA
+ bool "Support for Graphics workaround"
+ depends on DMAR
+ default y
+ help
+ Current Graphics drivers tend to use physical address
+ for DMA and avoid using DMA APIs. Setting this config
+ option permits the IOMMU driver to set a unity map for
+ all the OS-visible memory. Hence the driver can continue
+ to use physical addresses for DMA.
+
+config DMAR_FLOPPY_WA
+ bool
+ depends on DMAR
+ default y
+ help
+ Floppy disk drivers are know to bypass DMA API calls
+ thereby failing to work when IOMMU is enabled. This
+ workaround will setup a 1:1 mapping for the first
+ 16M to make floppy (an ISA device) work.
+
source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig"
+# x86_64 have no ISA slots, but do have ISA-style DMA.
config ISA_DMA_API
bool
default y
+if X86_32
+
config ISA
bool "ISA support"
depends on !(X86_VOYAGER || X86_VISWS)
@@ -1248,9 +1553,11 @@
MFGPTs have a better resolution and max interval than the
generic PIT, and are suitable for use as high-res timers.
+endif # X86_32
+
config K8_NB
def_bool y
- depends on AGP_AMD64
+ depends on AGP_AMD64 || (X86_64 && (GART_IOMMU || (PCI && NUMA)))
source "drivers/pcmcia/Kconfig"
@@ -1258,16 +1565,48 @@
endmenu
-menu "Executable file formats"
+
+menu "Executable file formats / Emulations"
source "fs/Kconfig.binfmt"
+config IA32_EMULATION
+ bool "IA32 Emulation"
+ depends on X86_64
+ help
+ Include code to run 32-bit programs under a 64-bit kernel. You should
+ likely turn this on, unless you're 100% sure that you don't have any
+ 32-bit programs left.
+
+config IA32_AOUT
+ tristate "IA32 a.out support"
+ depends on IA32_EMULATION
+ help
+ Support old a.out binaries in the 32bit emulation.
+
+config COMPAT
+ bool
+ depends on IA32_EMULATION
+ default y
+
+config COMPAT_FOR_U64_ALIGNMENT
+ def_bool COMPAT
+ depends on X86_64
+
+config SYSVIPC_COMPAT
+ bool
+ depends on X86_64 && COMPAT && SYSVIPC
+ default y
+
endmenu
+
source "net/Kconfig"
source "drivers/Kconfig"
+source "drivers/firmware/Kconfig"
+
source "fs/Kconfig"
source "kernel/Kconfig.instrumentation"
@@ -1279,43 +1618,3 @@
source "crypto/Kconfig"
source "lib/Kconfig"
-
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
- bool
- default y
-
-config GENERIC_IRQ_PROBE
- bool
- default y
-
-config GENERIC_PENDING_IRQ
- bool
- depends on GENERIC_HARDIRQS && SMP
- default y
-
-config X86_SMP
- bool
- depends on SMP && !X86_VOYAGER
- default y
-
-config X86_HT
- bool
- depends on SMP && !(X86_VISWS || X86_VOYAGER)
- default y
-
-config X86_BIOS_REBOOT
- bool
- depends on !(X86_VISWS || X86_VOYAGER)
- default y
-
-config X86_TRAMPOLINE
- bool
- depends on X86_SMP || (X86_VOYAGER && SMP)
- default y
-
-config KTIME_SCALAR
- bool
- default y
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 0e2adad..c301622 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -3,11 +3,12 @@
choice
prompt "Processor family"
- default M686
+ default M686 if X86_32
+ default GENERIC_CPU if X86_64
config M386
bool "386"
- depends on !UML
+ depends on X86_32 && !UML
---help---
This is the processor type of your CPU. This information is used for
optimizing purposes. In order to compile a kernel that can run on
@@ -49,6 +50,7 @@
config M486
bool "486"
+ depends on X86_32
help
Select this for a 486 series processor, either Intel or one of the
compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX,
@@ -57,6 +59,7 @@
config M586
bool "586/K5/5x86/6x86/6x86MX"
+ depends on X86_32
help
Select this for an 586 or 686 series processor such as the AMD K5,
the Cyrix 5x86, 6x86 and 6x86MX. This choice does not
@@ -64,18 +67,21 @@
config M586TSC
bool "Pentium-Classic"
+ depends on X86_32
help
Select this for a Pentium Classic processor with the RDTSC (Read
Time Stamp Counter) instruction for benchmarking.
config M586MMX
bool "Pentium-MMX"
+ depends on X86_32
help
Select this for a Pentium with the MMX graphics/multimedia
extended instructions.
config M686
bool "Pentium-Pro"
+ depends on X86_32
help
Select this for Intel Pentium Pro chips. This enables the use of
Pentium Pro extended instructions, and disables the init-time guard
@@ -83,6 +89,7 @@
config MPENTIUMII
bool "Pentium-II/Celeron(pre-Coppermine)"
+ depends on X86_32
help
Select this for Intel chips based on the Pentium-II and
pre-Coppermine Celeron core. This option enables an unaligned
@@ -92,6 +99,7 @@
config MPENTIUMIII
bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon"
+ depends on X86_32
help
Select this for Intel chips based on the Pentium-III and
Celeron-Coppermine core. This option enables use of some
@@ -100,19 +108,14 @@
config MPENTIUMM
bool "Pentium M"
+ depends on X86_32
help
Select this for Intel Pentium M (not Pentium-4 M)
notebook chips.
-config MCORE2
- bool "Core 2/newer Xeon"
- help
- Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
- CPUs. You can distinguish newer from older Xeons by the CPU family
- in /proc/cpuinfo. Newer ones have 6 and older ones 15 (not a typo)
-
config MPENTIUM4
bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon"
+ depends on X86_32
help
Select this for Intel Pentium 4 chips. This includes the
Pentium 4, Pentium D, P4-based Celeron and Xeon, and
@@ -148,6 +151,7 @@
config MK6
bool "K6/K6-II/K6-III"
+ depends on X86_32
help
Select this for an AMD K6-family processor. Enables use of
some extended instructions, and passes appropriate optimization
@@ -155,6 +159,7 @@
config MK7
bool "Athlon/Duron/K7"
+ depends on X86_32
help
Select this for an AMD Athlon K7-family processor. Enables use of
some extended instructions, and passes appropriate optimization
@@ -169,6 +174,7 @@
config MCRUSOE
bool "Crusoe"
+ depends on X86_32
help
Select this for a Transmeta Crusoe processor. Treats the processor
like a 586 with TSC, and sets some GCC optimization flags (like a
@@ -176,11 +182,13 @@
config MEFFICEON
bool "Efficeon"
+ depends on X86_32
help
Select this for a Transmeta Efficeon processor.
config MWINCHIPC6
bool "Winchip-C6"
+ depends on X86_32
help
Select this for an IDT Winchip C6 chip. Linux and GCC
treat this chip as a 586TSC with some extended instructions
@@ -188,6 +196,7 @@
config MWINCHIP2
bool "Winchip-2"
+ depends on X86_32
help
Select this for an IDT Winchip-2. Linux and GCC
treat this chip as a 586TSC with some extended instructions
@@ -195,6 +204,7 @@
config MWINCHIP3D
bool "Winchip-2A/Winchip-3"
+ depends on X86_32
help
Select this for an IDT Winchip-2A or 3. Linux and GCC
treat this chip as a 586TSC with some extended instructions
@@ -204,16 +214,19 @@
config MGEODEGX1
bool "GeodeGX1"
+ depends on X86_32
help
Select this for a Geode GX1 (Cyrix MediaGX) chip.
config MGEODE_LX
bool "Geode GX/LX"
+ depends on X86_32
help
Select this for AMD Geode GX and LX processors.
config MCYRIXIII
bool "CyrixIII/VIA-C3"
+ depends on X86_32
help
Select this for a Cyrix III or C3 chip. Presently Linux and GCC
treat this chip as a generic 586. Whilst the CPU is 686 class,
@@ -225,6 +238,7 @@
config MVIAC3_2
bool "VIA C3-2 (Nehemiah)"
+ depends on X86_32
help
Select this for a VIA C3 "Nehemiah". Selecting this enables usage
of SSE and tells gcc to treat the CPU as a 686.
@@ -232,15 +246,42 @@
config MVIAC7
bool "VIA C7"
+ depends on X86_32
help
Select this for a VIA C7. Selecting this uses the correct cache
shift and tells gcc to treat the CPU as a 686.
+config MPSC
+ bool "Intel P4 / older Netburst based Xeon"
+ depends on X86_64
+ help
+ Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey
+ Xeon CPUs with Intel 64bit which is compatible with x86-64.
+ Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
+ Netburst core and shouldn't use this option. You can distinguish them
+ using the cpu family field
+ in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one.
+
+config MCORE2
+ bool "Core 2/newer Xeon"
+ help
+ Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx)
+ CPUs. You can distinguish newer from older Xeons by the CPU family
+ in /proc/cpuinfo. Newer ones have 6 and older ones 15 (not a typo)
+
+config GENERIC_CPU
+ bool "Generic-x86-64"
+ depends on X86_64
+ help
+ Generic x86-64 CPU.
+ Run equally well on all x86-64 CPUs.
+
endchoice
config X86_GENERIC
- bool "Generic x86 support"
- help
+ bool "Generic x86 support"
+ depends on X86_32
+ help
Instead of just including optimizations for the selected
x86 variant (e.g. PII, Crusoe or Athlon), include some more
generic optimizations as well. This will make the kernel
@@ -253,44 +294,31 @@
#
# Define implied options from the CPU selection here
-#
+config X86_L1_CACHE_BYTES
+ int
+ default "128" if GENERIC_CPU || MPSC
+ default "64" if MK8 || MCORE2
+ depends on X86_64
+
+config X86_INTERNODE_CACHE_BYTES
+ int
+ default "4096" if X86_VSMP
+ default X86_L1_CACHE_BYTES if !X86_VSMP
+ depends on X86_64
+
config X86_CMPXCHG
- bool
- depends on !M386
- default y
+ def_bool X86_64 || (X86_32 && !M386)
config X86_L1_CACHE_SHIFT
int
- default "7" if MPENTIUM4 || X86_GENERIC
+ default "7" if MPENTIUM4 || X86_GENERIC || GENERIC_CPU || MPSC
default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7
config X86_XADD
bool
- depends on !M386
- default y
-
-config RWSEM_GENERIC_SPINLOCK
- bool
- depends on !X86_XADD
- default y
-
-config RWSEM_XCHGADD_ALGORITHM
- bool
- depends on X86_XADD
- default y
-
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
-config GENERIC_CALIBRATE_DELAY
- bool
+ depends on X86_32 && !M386
default y
config X86_PPRO_FENCE
@@ -305,22 +333,22 @@
config X86_WP_WORKS_OK
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_INVLPG
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_BSWAP
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_POPAD_OK
bool
- depends on !M386
+ depends on X86_32 && !M386
default y
config X86_ALIGNMENT_16
@@ -330,7 +358,7 @@
config X86_GOOD_APIC
bool
- depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7
+ depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 || X86_64
default y
config X86_INTEL_USERCOPY
@@ -355,7 +383,7 @@
config X86_TSC
bool
- depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ
+ depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64
default y
# this should be set for all -march=.. options where the compiler
@@ -367,6 +395,7 @@
config X86_MINIMUM_CPU_FAMILY
int
- default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK
+ default "64" if X86_64
+ default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK)
default "3"
diff --git a/arch/x86/Kconfig.x86_64 b/arch/x86/Kconfig.x86_64
deleted file mode 100644
index cc468ea..0000000
--- a/arch/x86/Kconfig.x86_64
+++ /dev/null
@@ -1,839 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/kconfig-language.txt.
-#
-# Note: ISA is disabled and will hopefully never be enabled.
-# If you managed to buy an ISA x86-64 box you'll have to fix all the
-# ISA drivers you need yourself.
-#
-
-mainmenu "Linux Kernel Configuration"
-
-config X86_64
- bool
- default y
- help
- Port to the x86-64 architecture. x86-64 is a 64-bit extension to the
- classical 32-bit x86 architecture. For details see
- <http://www.x86-64.org/>.
-
-config 64BIT
- def_bool y
-
-config X86
- bool
- default y
-
-config GENERIC_TIME
- bool
- default y
-
-config GENERIC_TIME_VSYSCALL
- bool
- default y
-
-config GENERIC_CMOS_UPDATE
- bool
- default y
-
-config CLOCKSOURCE_WATCHDOG
- bool
- default y
-
-config GENERIC_CLOCKEVENTS
- bool
- default y
-
-config GENERIC_CLOCKEVENTS_BROADCAST
- bool
- default y
-
-config ZONE_DMA32
- bool
- default y
-
-config LOCKDEP_SUPPORT
- bool
- default y
-
-config STACKTRACE_SUPPORT
- bool
- default y
-
-config SEMAPHORE_SLEEPERS
- bool
- default y
-
-config MMU
- bool
- default y
-
-config ZONE_DMA
- bool
- default y
-
-config ISA
- bool
-
-config SBUS
- bool
-
-config RWSEM_GENERIC_SPINLOCK
- bool
- default y
-
-config RWSEM_XCHGADD_ALGORITHM
- bool
-
-config GENERIC_HWEIGHT
- bool
- default y
-
-config GENERIC_CALIBRATE_DELAY
- bool
- default y
-
-config X86_CMPXCHG
- bool
- default y
-
-config GENERIC_ISA_DMA
- bool
- default y
-
-config GENERIC_IOMAP
- bool
- default y
-
-config ARCH_MAY_HAVE_PC_FDC
- bool
- default y
-
-config ARCH_POPULATES_NODE_MAP
- def_bool y
-
-config DMI
- bool
- default y
-
-config AUDIT_ARCH
- bool
- default y
-
-config GENERIC_BUG
- bool
- default y
- depends on BUG
-
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
-source "init/Kconfig"
-
-
-menu "Processor type and features"
-
-source "kernel/time/Kconfig"
-
-choice
- prompt "Subarchitecture Type"
- default X86_PC
-
-config X86_PC
- bool "PC-compatible"
- help
- Choose this option if your computer is a standard PC or compatible.
-
-config X86_VSMP
- bool "Support for ScaleMP vSMP"
- depends on PCI
- help
- Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
- supposed to run on these EM64T-based machines. Only choose this option
- if you have one of these machines.
-
-endchoice
-
-choice
- prompt "Processor family"
- default GENERIC_CPU
-
-config MK8
- bool "AMD-Opteron/Athlon64"
- help
- Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs.
-
-config MPSC
- bool "Intel P4 / older Netburst based Xeon"
- help
- Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey
- Xeon CPUs with Intel 64bit which is compatible with x86-64.
- Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
- Netburst core and shouldn't use this option. You can distinguish them
- using the cpu family field
- in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one.
-
-config MCORE2
- bool "Intel Core2 / newer Xeon"
- help
- Optimize for Intel Core2 and newer Xeons (51xx)
- You can distinguish the newer Xeons from the older ones using
- the cpu family field in /proc/cpuinfo. 15 is an older Xeon
- (use CONFIG_MPSC then), 6 is a newer one.
-
-config GENERIC_CPU
- bool "Generic-x86-64"
- help
- Generic x86-64 CPU.
- Run equally well on all x86-64 CPUs.
-
-endchoice
-
-#
-# Define implied options from the CPU selection here
-#
-config X86_L1_CACHE_BYTES
- int
- default "128" if GENERIC_CPU || MPSC
- default "64" if MK8 || MCORE2
-
-config X86_L1_CACHE_SHIFT
- int
- default "7" if GENERIC_CPU || MPSC
- default "6" if MK8 || MCORE2
-
-config X86_INTERNODE_CACHE_BYTES
- int
- default "4096" if X86_VSMP
- default X86_L1_CACHE_BYTES if !X86_VSMP
-
-config X86_TSC
- bool
- default y
-
-config X86_GOOD_APIC
- bool
- default y
-
-config MICROCODE
- tristate "/dev/cpu/microcode - Intel CPU microcode support"
- select FW_LOADER
- ---help---
- If you say Y here the 'File systems' section, you will be
- able to update the microcode on Intel processors. You will
- obviously need the actual microcode binary data itself which is
- not shipped with the Linux kernel.
-
- For latest news and information on obtaining all the required
- ingredients for this driver, check:
- <http://www.urbanmyth.org/microcode/>.
-
- To compile this driver as a module, choose M here: the
- module will be called microcode.
- If you use modprobe or kmod you may also want to add the line
- 'alias char-major-10-184 microcode' to your /etc/modules.conf file.
-
-config MICROCODE_OLD_INTERFACE
- bool
- depends on MICROCODE
- default y
-
-config X86_MSR
- tristate "/dev/cpu/*/msr - Model-specific register support"
- help
- This device gives privileged processes access to the x86
- Model-Specific Registers (MSRs). It is a character device with
- major 202 and minors 0 to 31 for /dev/cpu/0/msr to /dev/cpu/31/msr.
- MSR accesses are directed to a specific CPU on multi-processor
- systems.
-
-config X86_CPUID
- tristate "/dev/cpu/*/cpuid - CPU information support"
- help
- This device gives processes access to the x86 CPUID instruction to
- be executed on a specific processor. It is a character device
- with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to
- /dev/cpu/31/cpuid.
-
-config X86_HT
- bool
- depends on SMP && !MK8
- default y
-
-config MATH_EMULATION
- bool
-
-config MCA
- bool
-
-config EISA
- bool
-
-config X86_IO_APIC
- bool
- default y
-
-config X86_LOCAL_APIC
- bool
- default y
-
-config MTRR
- bool "MTRR (Memory Type Range Register) support"
- ---help---
- On Intel P6 family processors (Pentium Pro, Pentium II and later)
- the Memory Type Range Registers (MTRRs) may be used to control
- processor access to memory ranges. This is most useful if you have
- a video (VGA) card on a PCI or AGP bus. Enabling write-combining
- allows bus write transfers to be combined into a larger transfer
- before bursting over the PCI/AGP bus. This can increase performance
- of image write operations 2.5 times or more. Saying Y here creates a
- /proc/mtrr file which may be used to manipulate your processor's
- MTRRs. Typically the X server should use this.
-
- This code has a reasonably generic interface so that similar
- control registers on other processors can be easily supported
- as well.
-
- Saying Y here also fixes a problem with buggy SMP BIOSes which only
- set the MTRRs for the boot CPU and not for the secondary CPUs. This
- can lead to all sorts of problems, so it's good to say Y here.
-
- Just say Y here, all x86-64 machines support MTRRs.
-
- See <file:Documentation/mtrr.txt> for more information.
-
-config SMP
- bool "Symmetric multi-processing support"
- ---help---
- This enables support for systems with more than one CPU. If you have
- a system with only one CPU, like most personal computers, say N. If
- you have a system with more than one CPU, say Y.
-
- If you say N here, the kernel will run on single and multiprocessor
- machines, but will use only one CPU of a multiprocessor machine. If
- you say Y here, the kernel will run on many, but not all,
- singleprocessor machines. On a singleprocessor machine, the kernel
- will run faster if you say N here.
-
- If you don't know what to do here, say N.
-
-config SCHED_SMT
- bool "SMT (Hyperthreading) scheduler support"
- depends on SMP
- default n
- help
- SMT scheduler support improves the CPU scheduler's decision making
- when dealing with Intel Pentium 4 chips with HyperThreading at a
- cost of slightly increased overhead in some places. If unsure say
- N here.
-
-config SCHED_MC
- bool "Multi-core scheduler support"
- depends on SMP
- default y
- help
- Multi-core scheduler support improves the CPU scheduler's decision
- making when dealing with multi-core CPU chips at a cost of slightly
- increased overhead in some places. If unsure say N here.
-
-source "kernel/Kconfig.preempt"
-
-config NUMA
- bool "Non Uniform Memory Access (NUMA) Support"
- depends on SMP
- help
- Enable NUMA (Non Uniform Memory Access) support. The kernel
- will try to allocate memory used by a CPU on the local memory
- controller of the CPU and add some more NUMA awareness to the kernel.
- This code is recommended on all multiprocessor Opteron systems.
- If the system is EM64T, you should say N unless your system is EM64T
- NUMA.
-
-config K8_NUMA
- bool "Old style AMD Opteron NUMA detection"
- depends on NUMA && PCI
- default y
- help
- Enable K8 NUMA node topology detection. You should say Y here if
- you have a multi processor AMD K8 system. This uses an old
- method to read the NUMA configuration directly from the builtin
- Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA
- instead, which also takes priority if both are compiled in.
-
-config NODES_SHIFT
- int
- default "6"
- depends on NEED_MULTIPLE_NODES
-
-# Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig.
-
-config X86_64_ACPI_NUMA
- bool "ACPI NUMA detection"
- depends on NUMA
- select ACPI
- select PCI
- select ACPI_NUMA
- default y
- help
- Enable ACPI SRAT based node topology detection.
-
-config NUMA_EMU
- bool "NUMA emulation"
- depends on NUMA
- help
- Enable NUMA emulation. A flat machine will be split
- into virtual nodes when booted with "numa=fake=N", where N is the
- number of nodes. This is only useful for debugging.
-
-config ARCH_DISCONTIGMEM_ENABLE
- bool
- depends on NUMA
- default y
-
-config ARCH_DISCONTIGMEM_DEFAULT
- def_bool y
- depends on NUMA
-
-config ARCH_SPARSEMEM_ENABLE
- def_bool y
- depends on (NUMA || EXPERIMENTAL)
- select SPARSEMEM_VMEMMAP_ENABLE
-
-config ARCH_MEMORY_PROBE
- def_bool y
- depends on MEMORY_HOTPLUG
-
-config ARCH_FLATMEM_ENABLE
- def_bool y
- depends on !NUMA
-
-source "mm/Kconfig"
-
-config MEMORY_HOTPLUG_RESERVE
- def_bool y
- depends on (MEMORY_HOTPLUG && DISCONTIGMEM)
-
-config HAVE_ARCH_EARLY_PFN_TO_NID
- def_bool y
- depends on NUMA
-
-config OUT_OF_LINE_PFN_TO_PAGE
- def_bool y
- depends on DISCONTIGMEM
-
-config NR_CPUS
- int "Maximum number of CPUs (2-255)"
- range 2 255
- depends on SMP
- default "8"
- help
- This allows you to specify the maximum number of CPUs which this
- kernel will support. Current maximum is 255 CPUs due to
- APIC addressing limits. Less depending on the hardware.
-
- This is purely to save memory - each supported CPU requires
- memory in the static kernel configuration.
-
-config PHYSICAL_ALIGN
- hex
- default "0x200000"
-
-config HOTPLUG_CPU
- bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
- depends on SMP && HOTPLUG && EXPERIMENTAL
- help
- Say Y here to experiment with turning CPUs off and on. CPUs
- can be controlled through /sys/devices/system/cpu/cpu#.
- This is also required for suspend/hibernation on SMP systems.
-
- Say N if you want to disable CPU hotplug and don't need to
- suspend.
-
-config ARCH_ENABLE_MEMORY_HOTPLUG
- def_bool y
-
-config HPET_TIMER
- bool
- default y
- help
- Use the IA-PC HPET (High Precision Event Timer) to manage
- time in preference to the PIT and RTC, if a HPET is
- present. The HPET provides a stable time base on SMP
- systems, unlike the TSC, but it is more expensive to access,
- as it is off-chip. You can find the HPET spec at
- <http://www.intel.com/hardwaredesign/hpetspec.htm>.
-
-config HPET_EMULATE_RTC
- bool
- depends on HPET_TIMER && RTC=y
- default y
-
-# Mark as embedded because too many people got it wrong.
-# The code disables itself when not needed.
-config GART_IOMMU
- bool "GART IOMMU support" if EMBEDDED
- default y
- select SWIOTLB
- select AGP
- depends on PCI
- help
- Support for full DMA access of devices with 32bit memory access only
- on systems with more than 3GB. This is usually needed for USB,
- sound, many IDE/SATA chipsets and some other devices.
- Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
- based hardware IOMMU and a software bounce buffer based IOMMU used
- on Intel systems and as fallback.
- The code is only active when needed (enough memory and limited
- device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
- too.
-
-config CALGARY_IOMMU
- bool "IBM Calgary IOMMU support"
- select SWIOTLB
- depends on PCI && EXPERIMENTAL
- help
- Support for hardware IOMMUs in IBM's xSeries x366 and x460
- systems. Needed to run systems with more than 3GB of memory
- properly with 32-bit PCI devices that do not support DAC
- (Double Address Cycle). Calgary also supports bus level
- isolation, where all DMAs pass through the IOMMU. This
- prevents them from going anywhere except their intended
- destination. This catches hard-to-find kernel bugs and
- mis-behaving drivers and devices that do not use the DMA-API
- properly to set up their DMA buffers. The IOMMU can be
- turned off at boot time with the iommu=off parameter.
- Normally the kernel will make the right choice by itself.
- If unsure, say Y.
-
-config CALGARY_IOMMU_ENABLED_BY_DEFAULT
- bool "Should Calgary be enabled by default?"
- default y
- depends on CALGARY_IOMMU
- help
- Should Calgary be enabled by default? if you choose 'y', Calgary
- will be used (if it exists). If you choose 'n', Calgary will not be
- used even if it exists. If you choose 'n' and would like to use
- Calgary anyway, pass 'iommu=calgary' on the kernel command line.
- If unsure, say Y.
-
-# need this always selected by IOMMU for the VIA workaround
-config SWIOTLB
- bool
- help
- Support for software bounce buffers used on x86-64 systems
- which don't have a hardware IOMMU (e.g. the current generation
- of Intel's x86-64 CPUs). Using this PCI devices which can only
- access 32-bits of memory can be used on systems with more than
- 3 GB of memory. If unsure, say Y.
-
-config X86_MCE
- bool "Machine check support" if EMBEDDED
- default y
- help
- Include a machine check error handler to report hardware errors.
- This version will require the mcelog utility to decode some
- machine check error logs. See
- ftp://ftp.x86-64.org/pub/linux/tools/mcelog
-
-config X86_MCE_INTEL
- bool "Intel MCE features"
- depends on X86_MCE && X86_LOCAL_APIC
- default y
- help
- Additional support for intel specific MCE features such as
- the thermal monitor.
-
-config X86_MCE_AMD
- bool "AMD MCE features"
- depends on X86_MCE && X86_LOCAL_APIC
- default y
- help
- Additional support for AMD specific MCE features such as
- the DRAM Error Threshold.
-
-config KEXEC
- bool "kexec system call"
- help
- kexec is a system call that implements the ability to shutdown your
- current kernel, and to start another kernel. It is like a reboot
- but it is independent of the system firmware. And like a reboot
- you can start any kernel with it, not just Linux.
-
- The name comes from the similarity to the exec system call.
-
- It is an ongoing process to be certain the hardware in a machine
- is properly shutdown, so do not be surprised if this code does not
- initially work for you. It may help to enable device hotplugging
- support. As of this writing the exact hardware interface is
- strongly in flux, so no good recommendation can be made.
-
-config CRASH_DUMP
- bool "kernel crash dumps (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- help
- Generate crash dump after being started by kexec.
- This should be normally only set in special crash dump kernels
- which are loaded in the main kernel with kexec-tools into
- a specially reserved region and then later executed after
- a crash by kdump/kexec. The crash dump kernel must be compiled
- to a memory address not used by the main kernel or BIOS using
- PHYSICAL_START, or it must be built as a relocatable image
- (CONFIG_RELOCATABLE=y).
- For more details see Documentation/kdump/kdump.txt
-
-config RELOCATABLE
- bool "Build a relocatable kernel (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- help
- Builds a relocatable kernel. This enables loading and running
- a kernel binary from a different physical address than it has
- been compiled for.
-
- One use is for the kexec on panic case where the recovery kernel
- must live at a different physical address than the primary
- kernel.
-
- Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
- it has been loaded at and the compile time physical address
- (CONFIG_PHYSICAL_START) is ignored.
-
-config PHYSICAL_START
- hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
- default "0x200000"
- help
- This gives the physical address where the kernel is loaded. It
- should be aligned to 2MB boundary.
-
- If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then
- bzImage will decompress itself to above physical address and
- run from there. Otherwise, bzImage will run from the address where
- it has been loaded by the boot loader and will ignore above physical
- address.
-
- In normal kdump cases one does not have to set/change this option
- as now bzImage can be compiled as a completely relocatable image
- (CONFIG_RELOCATABLE=y) and be used to load and run from a different
- address. This option is mainly useful for the folks who don't want
- to use a bzImage for capturing the crash dump and want to use a
- vmlinux instead.
-
- So if you are using bzImage for capturing the crash dump, leave
- the value here unchanged to 0x200000 and set CONFIG_RELOCATABLE=y.
- Otherwise if you plan to use vmlinux for capturing the crash dump
- change this value to start of the reserved region (Typically 16MB
- 0x1000000). In other words, it can be set based on the "X" value as
- specified in the "crashkernel=YM@XM" command line boot parameter
- passed to the panic-ed kernel. Typically this parameter is set as
- crashkernel=64M@16M. Please take a look at
- Documentation/kdump/kdump.txt for more details about crash dumps.
-
- Usage of bzImage for capturing the crash dump is advantageous as
- one does not have to build two kernels. Same kernel can be used
- as production kernel and capture kernel.
-
- Don't change this unless you know what you are doing.
-
-config SECCOMP
- bool "Enable seccomp to safely compute untrusted bytecode"
- depends on PROC_FS
- default y
- help
- This kernel feature is useful for number crunching applications
- that may need to compute untrusted bytecode during their
- execution. By using pipes or other transports made available to
- the process as file descriptors supporting the read/write
- syscalls, it's possible to isolate those applications in
- their own address space using seccomp. Once seccomp is
- enabled via /proc/<pid>/seccomp, it cannot be disabled
- and the task is only allowed to execute a few safe syscalls
- defined by each seccomp mode.
-
- If unsure, say Y. Only embedded should say N here.
-
-config CC_STACKPROTECTOR
- bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- help
- This option turns on the -fstack-protector GCC feature. This
- feature puts, at the beginning of critical functions, a canary
- value on the stack just before the return address, and validates
- the value just before actually returning. Stack based buffer
- overflows (that need to overwrite this return address) now also
- overwrite the canary, which gets detected and the attack is then
- neutralized via a kernel panic.
-
- This feature requires gcc version 4.2 or above, or a distribution
- gcc with the feature backported. Older versions are automatically
- detected and for those versions, this configuration option is ignored.
-
-config CC_STACKPROTECTOR_ALL
- bool "Use stack-protector for all functions"
- depends on CC_STACKPROTECTOR
- help
- Normally, GCC only inserts the canary value protection for
- functions that use large-ish on-stack buffers. By enabling
- this option, GCC will be asked to do this for ALL functions.
-
-source kernel/Kconfig.hz
-
-config K8_NB
- def_bool y
- depends on AGP_AMD64 || GART_IOMMU || (PCI && NUMA)
-
-endmenu
-
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
- bool
- default y
-
-config GENERIC_IRQ_PROBE
- bool
- default y
-
-# we have no ISA slots, but we do have ISA-style DMA.
-config ISA_DMA_API
- bool
- default y
-
-config GENERIC_PENDING_IRQ
- bool
- depends on GENERIC_HARDIRQS && SMP
- default y
-
-menu "Power management options"
-
-source kernel/power/Kconfig
-
-config ARCH_HIBERNATION_HEADER
- bool
- depends on HIBERNATION
- default y
-
-source "drivers/acpi/Kconfig"
-
-source "arch/x86/kernel/cpu/cpufreq/Kconfig_64"
-
-source "drivers/cpuidle/Kconfig"
-
-endmenu
-
-menu "Bus options (PCI etc.)"
-
-config PCI
- bool "PCI support"
- select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
-
-# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
-config PCI_DIRECT
- bool
- depends on PCI
- default y
-
-config PCI_MMCONFIG
- bool "Support mmconfig PCI config space access"
- depends on PCI && ACPI
-
-config PCI_DOMAINS
- bool
- depends on PCI
- default y
-
-config DMAR
- bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
- depends on PCI_MSI && ACPI && EXPERIMENTAL
- help
- DMA remapping (DMAR) devices support enables independent address
- translations for Direct Memory Access (DMA) from devices.
- These DMA remapping devices are reported via ACPI tables
- and include PCI device scope covered by these DMA
- remapping devices.
-
-config DMAR_GFX_WA
- bool "Support for Graphics workaround"
- depends on DMAR
- default y
- help
- Current Graphics drivers tend to use physical address
- for DMA and avoid using DMA APIs. Setting this config
- option permits the IOMMU driver to set a unity map for
- all the OS-visible memory. Hence the driver can continue
- to use physical addresses for DMA.
-
-config DMAR_FLOPPY_WA
- bool
- depends on DMAR
- default y
- help
- Floppy disk drivers are know to bypass DMA API calls
- thereby failing to work when IOMMU is enabled. This
- workaround will setup a 1:1 mapping for the first
- 16M to make floppy (an ISA device) work.
-
-source "drivers/pci/pcie/Kconfig"
-
-source "drivers/pci/Kconfig"
-
-source "drivers/pcmcia/Kconfig"
-
-source "drivers/pci/hotplug/Kconfig"
-
-endmenu
-
-
-menu "Executable file formats / Emulations"
-
-source "fs/Kconfig.binfmt"
-
-config IA32_EMULATION
- bool "IA32 Emulation"
- help
- Include code to run 32-bit programs under a 64-bit kernel. You should
- likely turn this on, unless you're 100% sure that you don't have any
- 32-bit programs left.
-
-config IA32_AOUT
- tristate "IA32 a.out support"
- depends on IA32_EMULATION
- help
- Support old a.out binaries in the 32bit emulation.
-
-config COMPAT
- bool
- depends on IA32_EMULATION
- default y
-
-config COMPAT_FOR_U64_ALIGNMENT
- def_bool COMPAT
-
-config SYSVIPC_COMPAT
- bool
- depends on COMPAT && SYSVIPC
- default y
-
-endmenu
-
-source "net/Kconfig"
-
-source drivers/Kconfig
-
-source "drivers/firmware/Kconfig"
-
-source fs/Kconfig
-
-source "kernel/Kconfig.instrumentation"
-
-source "arch/x86/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 3095973..116b03a 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -1,12 +1,16 @@
# Unified Makefile for i386 and x86_64
# select defconfig based on actual architecture
-KBUILD_DEFCONFIG := $(ARCH)_defconfig
+ifeq ($(ARCH),x86)
+ KBUILD_DEFCONFIG := i386_defconfig
+else
+ KBUILD_DEFCONFIG := $(ARCH)_defconfig
+endif
-# # No need to remake these files
+# No need to remake these files
$(srctree)/arch/x86/Makefile%: ;
-ifeq ($(ARCH),i386)
+ifeq ($(CONFIG_X86_32),y)
include $(srctree)/arch/x86/Makefile_32
else
include $(srctree)/arch/x86/Makefile_64
diff --git a/arch/x86/Makefile_32 b/arch/x86/Makefile_32
index 346ac07..50394da 100644
--- a/arch/x86/Makefile_32
+++ b/arch/x86/Makefile_32
@@ -160,7 +160,7 @@
$(Q)$(MAKE) $(clean)=arch/x86/boot
define archhelp
- echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
+ echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
echo ' install - Install kernel using'
echo ' (your) ~/bin/installkernel or'
echo ' (distribution) /sbin/installkernel or'
@@ -170,6 +170,6 @@
echo ' isoimage - Create a boot CD-ROM image'
endef
-CLEAN_FILES += arch/$(ARCH)/boot/fdimage \
- arch/$(ARCH)/boot/image.iso \
- arch/$(ARCH)/boot/mtools.conf
+CLEAN_FILES += arch/x86/boot/fdimage \
+ arch/x86/boot/image.iso \
+ arch/x86/boot/mtools.conf
diff --git a/arch/x86/Makefile_64 b/arch/x86/Makefile_64
index 57e714a..a804860 100644
--- a/arch/x86/Makefile_64
+++ b/arch/x86/Makefile_64
@@ -127,7 +127,7 @@
$(Q)$(MAKE) $(clean)=$(boot)
define archhelp
- echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
+ echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
echo ' install - Install kernel using'
echo ' (your) ~/bin/installkernel or'
echo ' (distribution) /sbin/installkernel or'
@@ -137,8 +137,8 @@
echo ' isoimage - Create a boot CD-ROM image'
endef
-CLEAN_FILES += arch/$(ARCH)/boot/fdimage \
- arch/$(ARCH)/boot/image.iso \
- arch/$(ARCH)/boot/mtools.conf
+CLEAN_FILES += arch/x86/boot/fdimage \
+ arch/x86/boot/image.iso \
+ arch/x86/boot/mtools.conf
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 89dbf97..7a3116c 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -49,10 +49,10 @@
# How to compile the 16-bit code. Note we always compile for -march=i386,
# that way we can complain to the user if the CPU is insufficient.
-cflags-i386 :=
-cflags-x86_64 := -m32
+cflags-$(CONFIG_X86_32) :=
+cflags-$(CONFIG_X86_64) := -m32
KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
- $(cflags-$(ARCH)) \
+ $(cflags-y) \
-Wall -Wstrict-prototypes \
-march=i386 -mregparm=3 \
-include $(srctree)/$(src)/code16gcc.h \
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index e655a89..769065b 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -42,13 +42,7 @@
static u32 cpu_vendor[3];
static u32 err_flags[NCAPINTS];
-#ifdef CONFIG_X86_64
-static const int req_level = 64;
-#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY)
static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
-#else
-static const int req_level = 3;
-#endif
static const u32 req_flags[NCAPINTS] =
{
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32
index b9d67982..a7bc93c 100644
--- a/arch/x86/kernel/Makefile_32
+++ b/arch/x86/kernel/Makefile_32
@@ -3,6 +3,7 @@
#
extra-y := head_32.o init_task.o vmlinux.lds
+CPPFLAGS_vmlinux.lds += -Ui386
obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \
ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \
@@ -60,7 +61,7 @@
cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
-export CPPFLAGS_vsyscall_32.lds += -P -C -U$(ARCH)
+export CPPFLAGS_vsyscall_32.lds += -P -C -Ui386
vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \
$(call ld-option, -Wl$(comma)--hash-style=sysv)
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64
index 24671c3..5a88890 100644
--- a/arch/x86/kernel/Makefile_64
+++ b/arch/x86/kernel/Makefile_64
@@ -3,7 +3,9 @@
#
extra-y := head_64.o head64.o init_task.o vmlinux.lds
+CPPFLAGS_vmlinux.lds += -Ux86_64
EXTRA_AFLAGS := -traditional
+
obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \
ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \
x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig_32 b/arch/x86/kernel/cpu/cpufreq/Kconfig
similarity index 77%
rename from arch/x86/kernel/cpu/cpufreq/Kconfig_32
rename to arch/x86/kernel/cpu/cpufreq/Kconfig
index d8c6f13..151eda0 100644
--- a/arch/x86/kernel/cpu/cpufreq/Kconfig_32
+++ b/arch/x86/kernel/cpu/cpufreq/Kconfig
@@ -19,6 +19,9 @@
Processor Performance States.
This driver also supports Intel Enhanced Speedstep.
+ To compile this driver as a module, choose M here: the
+ module will be called acpi-cpufreq.
+
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
@@ -26,7 +29,7 @@
config ELAN_CPUFREQ
tristate "AMD Elan SC400 and SC410"
select CPU_FREQ_TABLE
- depends on X86_ELAN
+ depends on X86_32 && X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC400 and SC410
processors.
@@ -42,7 +45,7 @@
config SC520_CPUFREQ
tristate "AMD Elan SC520"
select CPU_FREQ_TABLE
- depends on X86_ELAN
+ depends on X86_32 && X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC520 processor.
@@ -54,6 +57,7 @@
config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
select CPU_FREQ_TABLE
+ depends on X86_32
help
This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
AMD K6-3+ processors.
@@ -65,6 +69,7 @@
config X86_POWERNOW_K7
tristate "AMD Mobile Athlon/Duron PowerNow!"
select CPU_FREQ_TABLE
+ depends on X86_32
help
This adds the CPUFreq driver for mobile AMD K7 mobile processors.
@@ -76,23 +81,27 @@
bool
depends on X86_POWERNOW_K7 && ACPI_PROCESSOR
depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)
+ depends on X86_32
default y
config X86_POWERNOW_K8
tristate "AMD Opteron/Athlon64 PowerNow!"
select CPU_FREQ_TABLE
- depends on EXPERIMENTAL
help
This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
+ To compile this driver as a module, choose M here: the
+ module will be called powernow-k8.
+
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
config X86_POWERNOW_K8_ACPI
- bool "ACPI Support"
- select ACPI_PROCESSOR
- depends on ACPI && X86_POWERNOW_K8
+ bool
+ prompt "ACPI Support" if X86_32
+ depends on ACPI && X86_POWERNOW_K8 && ACPI_PROCESSOR
+ depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
default y
help
This provides access to the K8s Processor Performance States via ACPI.
@@ -104,7 +113,7 @@
config X86_GX_SUSPMOD
tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
- depends on PCI
+ depends on X86_32 && PCI
help
This add the CPUFreq driver for NatSemi Geode processors which
support suspend modulation.
@@ -114,15 +123,20 @@
If in doubt, say N.
config X86_SPEEDSTEP_CENTRINO
- tristate "Intel Enhanced SpeedStep"
+ tristate "Intel Enhanced SpeedStep (deprecated)"
select CPU_FREQ_TABLE
- select X86_SPEEDSTEP_CENTRINO_TABLE
+ select X86_SPEEDSTEP_CENTRINO_TABLE if X86_32
+ depends on X86_32 || (X86_64 && ACPI_PROCESSOR)
help
+ This is deprecated and this functionality is now merged into
+ acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
+ speedstep_centrino.
This adds the CPUFreq driver for Enhanced SpeedStep enabled
- mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However,
- you also need to say Y to "Use ACPI tables to decode..." below
- [which might imply enabling ACPI] if you want to use this driver
- on non-Banias CPUs.
+ mobile CPUs. This means Intel Pentium M (Centrino) CPUs
+ or 64bit enabled Intel Xeons.
+
+ To compile this driver as a module, choose M here: the
+ module will be called speedstep-centrino.
For details, take a look at <file:Documentation/cpu-freq/>.
@@ -130,7 +144,7 @@
config X86_SPEEDSTEP_CENTRINO_TABLE
bool "Built-in tables for Banias CPUs"
- depends on X86_SPEEDSTEP_CENTRINO
+ depends on X86_32 && X86_SPEEDSTEP_CENTRINO
default y
help
Use built-in tables for Banias CPUs if ACPI encoding
@@ -141,6 +155,7 @@
config X86_SPEEDSTEP_ICH
tristate "Intel Speedstep on ICH-M chipsets (ioport interface)"
select CPU_FREQ_TABLE
+ depends on X86_32
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tualatin) and all
@@ -154,7 +169,7 @@
config X86_SPEEDSTEP_SMI
tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)"
select CPU_FREQ_TABLE
- depends on EXPERIMENTAL
+ depends on X86_32 && EXPERIMENTAL
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tualatin)
@@ -169,15 +184,24 @@
select CPU_FREQ_TABLE
help
This adds the CPUFreq driver for Intel Pentium 4 / XEON
- processors.
+ processors. When enabled it will lower CPU temperature by skipping
+ clocks.
+
+ This driver should be only used in exceptional
+ circumstances when very low power is needed because it causes severe
+ slowdowns and noticeable latencies. Normally Speedstep should be used
+ instead.
+
+ To compile this driver as a module, choose M here: the
+ module will be called p4-clockmod.
For details, take a look at <file:Documentation/cpu-freq/>.
- If in doubt, say N.
+ Unless you are absolutely sure say N.
config X86_CPUFREQ_NFORCE2
tristate "nVidia nForce2 FSB changing"
- depends on EXPERIMENTAL
+ depends on X86_32 && EXPERIMENTAL
help
This adds the CPUFreq driver for FSB changing on nVidia nForce2
platforms.
@@ -188,6 +212,7 @@
config X86_LONGRUN
tristate "Transmeta LongRun"
+ depends on X86_32
help
This adds the CPUFreq driver for Transmeta Crusoe and Efficeon processors
which support LongRun.
@@ -199,7 +224,7 @@
config X86_LONGHAUL
tristate "VIA Cyrix III Longhaul"
select CPU_FREQ_TABLE
- depends on ACPI_PROCESSOR
+ depends on X86_32 && ACPI_PROCESSOR
help
This adds the CPUFreq driver for VIA Samuel/CyrixIII,
VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
@@ -212,7 +237,7 @@
config X86_E_POWERSAVER
tristate "VIA C7 Enhanced PowerSaver (EXPERIMENTAL)"
select CPU_FREQ_TABLE
- depends on EXPERIMENTAL
+ depends on X86_32 && EXPERIMENTAL
help
This adds the CPUFreq driver for VIA C7 processors.
@@ -233,11 +258,11 @@
config X86_SPEEDSTEP_LIB
tristate
- default X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD
+ default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
config X86_SPEEDSTEP_RELAXED_CAP_CHECK
bool "Relaxed speedstep capability checks"
- depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
+ depends on X86_32 && (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH)
help
Don't perform all checks for a speedstep capable system which would
normally be done. Some ancient or strange systems, though speedstep
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig_64 b/arch/x86/kernel/cpu/cpufreq/Kconfig_64
deleted file mode 100644
index 9c9699f..0000000
--- a/arch/x86/kernel/cpu/cpufreq/Kconfig_64
+++ /dev/null
@@ -1,108 +0,0 @@
-#
-# CPU Frequency scaling
-#
-
-menu "CPU Frequency scaling"
-
-source "drivers/cpufreq/Kconfig"
-
-if CPU_FREQ
-
-comment "CPUFreq processor drivers"
-
-config X86_POWERNOW_K8
- tristate "AMD Opteron/Athlon64 PowerNow!"
- select CPU_FREQ_TABLE
- help
- This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
-
- To compile this driver as a module, choose M here: the
- module will be called powernow-k8.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
-
-config X86_POWERNOW_K8_ACPI
- bool
- depends on X86_POWERNOW_K8 && ACPI_PROCESSOR
- depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
- default y
-
-config X86_SPEEDSTEP_CENTRINO
- tristate "Intel Enhanced SpeedStep (deprecated)"
- select CPU_FREQ_TABLE
- depends on ACPI_PROCESSOR
- help
- This is deprecated and this functionality is now merged into
- acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
- speedstep_centrino.
- This adds the CPUFreq driver for Enhanced SpeedStep enabled
- mobile CPUs. This means Intel Pentium M (Centrino) CPUs
- or 64bit enabled Intel Xeons.
-
- To compile this driver as a module, choose M here: the
- module will be called speedstep-centrino.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
-
-config X86_ACPI_CPUFREQ
- tristate "ACPI Processor P-States driver"
- select CPU_FREQ_TABLE
- depends on ACPI_PROCESSOR
- help
- This driver adds a CPUFreq driver which utilizes the ACPI
- Processor Performance States.
- This driver also supports Intel Enhanced Speedstep.
-
- To compile this driver as a module, choose M here: the
- module will be called acpi-cpufreq.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- If in doubt, say N.
-
-comment "shared options"
-
-config X86_ACPI_CPUFREQ_PROC_INTF
- bool "/proc/acpi/processor/../performance interface (deprecated)"
- depends on PROC_FS
- depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K8_ACPI
- help
- This enables the deprecated /proc/acpi/processor/../performance
- interface. While it is helpful for debugging, the generic,
- cross-architecture cpufreq interfaces should be used.
-
- If in doubt, say N.
-
-config X86_P4_CLOCKMOD
- tristate "Intel Pentium 4 clock modulation"
- depends on EMBEDDED
- select CPU_FREQ_TABLE
- help
- This adds the clock modulation driver for Intel Pentium 4 / XEON
- processors. When enabled it will lower CPU temperature by skipping
- clocks.
-
- This driver should be only used in exceptional
- circumstances when very low power is needed because it causes severe
- slowdowns and noticeable latencies. Normally Speedstep should be used
- instead.
-
- To compile this driver as a module, choose M here: the
- module will be called p4-clockmod.
-
- For details, take a look at <file:Documentation/cpu-freq/>.
-
- Unless you are absolutely sure say N.
-
-
-config X86_SPEEDSTEP_LIB
- tristate
- default X86_P4_CLOCKMOD
-
-endif
-
-endmenu
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index b9f802e..447b351 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -802,6 +802,8 @@
NULL
};
+static cpumask_t mce_device_initialized = CPU_MASK_NONE;
+
/* Per cpu sysdev init. All of the cpus still share the same ctl bank */
static __cpuinit int mce_create_device(unsigned int cpu)
{
@@ -825,6 +827,7 @@
if (err)
goto error;
}
+ cpu_set(cpu, mce_device_initialized);
return 0;
error:
@@ -841,10 +844,14 @@
{
int i;
+ if (!cpu_isset(cpu, mce_device_initialized))
+ return;
+
for (i = 0; mce_attributes[i]; i++)
sysdev_remove_file(&per_cpu(device_mce,cpu),
mce_attributes[i]);
sysdev_unregister(&per_cpu(device_mce,cpu));
+ cpu_clear(cpu, mce_device_initialized);
}
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
@@ -852,21 +859,18 @@
mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
- int err = 0;
switch (action) {
- case CPU_UP_PREPARE:
- case CPU_UP_PREPARE_FROZEN:
- err = mce_create_device(cpu);
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ mce_create_device(cpu);
break;
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
mce_remove_device(cpu);
break;
}
- return err ? NOTIFY_BAD : NOTIFY_OK;
+ return NOTIFY_OK;
}
static struct notifier_block mce_cpu_notifier = {
diff --git a/arch/x86/kernel/i387_64.c b/arch/x86/kernel/i387_64.c
index 56c1f11..bfaff28 100644
--- a/arch/x86/kernel/i387_64.c
+++ b/arch/x86/kernel/i387_64.c
@@ -92,13 +92,14 @@
if (task_thread_info(tsk)->status & TS_USEDFPU) {
err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
if (err) return err;
+ task_thread_info(tsk)->status &= ~TS_USEDFPU;
stts();
- } else {
- if (__copy_to_user(buf, &tsk->thread.i387.fxsave,
+ } else {
+ if (__copy_to_user(buf, &tsk->thread.i387.fxsave,
sizeof(struct i387_fxsave_struct)))
return -1;
- }
- return 1;
+ }
+ return 1;
}
/*
diff --git a/arch/x86/lib/delay_32.c b/arch/x86/lib/delay_32.c
index 952e7a8..aad9d95 100644
--- a/arch/x86/lib/delay_32.c
+++ b/arch/x86/lib/delay_32.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/preempt.h>
#include <linux/delay.h>
#include <asm/processor.h>
@@ -42,11 +43,13 @@
{
unsigned long bclock, now;
+ preempt_disable(); /* TSC's are per-cpu */
rdtscl(bclock);
do {
rep_nop();
rdtscl(now);
} while ((now-bclock) < loops);
+ preempt_enable();
}
/*
diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c
index 0ebbfb9..45cdd3f 100644
--- a/arch/x86/lib/delay_64.c
+++ b/arch/x86/lib/delay_64.c
@@ -10,7 +10,9 @@
#include <linux/module.h>
#include <linux/sched.h>
+#include <linux/preempt.h>
#include <linux/delay.h>
+
#include <asm/delay.h>
#include <asm/msr.h>
@@ -27,14 +29,15 @@
void __delay(unsigned long loops)
{
unsigned bclock, now;
-
+
+ preempt_disable(); /* TSC's are pre-cpu */
rdtscl(bclock);
- do
- {
+ do {
rep_nop();
rdtscl(now);
}
- while((now-bclock) < loops);
+ while ((now-bclock) < loops);
+ preempt_enable();
}
EXPORT_SYMBOL(__delay);
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index 7a2ba45..e7bff0f 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -20,7 +20,7 @@
cmd_syscall = $(CC) -m elf_x86_64 -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
-export CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+export CPPFLAGS_vdso.lds += -P -C
vdso-flags = -fPIC -shared -Wl,-soname=linux-vdso.so.1 \
$(call ld-option, -Wl$(comma)--hash-style=sysv) \
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ce9dead..087a702 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -50,6 +50,7 @@
config ACPI_PROCFS
bool "Deprecated /proc/acpi files"
depends on PROC_FS
+ default y
---help---
For backwards compatibility, this option allows
deprecated /proc/acpi/ files to exist, even when
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index e03de37..30238f6 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -27,8 +27,10 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
+#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#endif
#include <linux/power_supply.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -49,12 +51,15 @@
MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");
+#ifdef CONFIG_ACPI_PROCFS
extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
+static int acpi_ac_open_fs(struct inode *inode, struct file *file);
+#endif
static int acpi_ac_add(struct acpi_device *device);
static int acpi_ac_remove(struct acpi_device *device, int type);
-static int acpi_ac_open_fs(struct inode *inode, struct file *file);
+static int acpi_ac_resume(struct acpi_device *device);
const static struct acpi_device_id ac_device_ids[] = {
{"ACPI0003", 0},
@@ -69,6 +74,7 @@
.ops = {
.add = acpi_ac_add,
.remove = acpi_ac_remove,
+ .resume = acpi_ac_resume,
},
};
@@ -80,12 +86,15 @@
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
+#ifdef CONFIG_ACPI_PROCFS
static const struct file_operations acpi_ac_fops = {
.open = acpi_ac_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
+#endif
+
static int get_ac_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -127,6 +136,7 @@
return 0;
}
+#ifdef CONFIG_ACPI_PROCFS
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
@@ -206,6 +216,7 @@
return 0;
}
+#endif
/* --------------------------------------------------------------------------
Driver Model
@@ -264,7 +275,9 @@
if (result)
goto end;
+#ifdef CONFIG_ACPI_PROCFS
result = acpi_ac_add_fs(device);
+#endif
if (result)
goto end;
ac->charger.name = acpi_device_bid(device);
@@ -287,13 +300,30 @@
end:
if (result) {
+#ifdef CONFIG_ACPI_PROCFS
acpi_ac_remove_fs(device);
+#endif
kfree(ac);
}
return result;
}
+static int acpi_ac_resume(struct acpi_device *device)
+{
+ struct acpi_ac *ac;
+ unsigned old_state;
+ if (!device || !acpi_driver_data(device))
+ return -EINVAL;
+ ac = acpi_driver_data(device);
+ old_state = ac->state;
+ if (acpi_ac_get_state(ac))
+ return 0;
+ if (old_state != ac->state)
+ kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
+ return 0;
+}
+
static int acpi_ac_remove(struct acpi_device *device, int type)
{
acpi_status status = AE_OK;
@@ -309,7 +339,9 @@
ACPI_ALL_NOTIFY, acpi_ac_notify);
if (ac->charger.dev)
power_supply_unregister(&ac->charger);
+#ifdef CONFIG_ACPI_PROCFS
acpi_ac_remove_fs(device);
+#endif
kfree(ac);
@@ -323,13 +355,17 @@
if (acpi_disabled)
return -ENODEV;
+#ifdef CONFIG_ACPI_PROCFS
acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir)
return -ENODEV;
+#endif
result = acpi_bus_register_driver(&acpi_ac_driver);
if (result < 0) {
+#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_ac_dir(acpi_ac_dir);
+#endif
return -ENODEV;
}
@@ -341,7 +377,9 @@
acpi_bus_unregister_driver(&acpi_ac_driver);
+#ifdef CONFIG_ACPI_PROCFS
acpi_unlock_ac_dir(acpi_ac_dir);
+#endif
return;
}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index c2ce0ad..192c244f 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -132,7 +132,7 @@
return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
}
-static int acpi_battery_update(struct acpi_battery *battery);
+static int acpi_battery_get_state(struct acpi_battery *battery);
static int acpi_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
@@ -140,10 +140,11 @@
{
struct acpi_battery *battery = to_acpi_battery(psy);
- if ((!acpi_battery_present(battery)) &&
- psp != POWER_SUPPLY_PROP_PRESENT)
+ if (acpi_battery_present(battery)) {
+ /* run battery update only if it is present */
+ acpi_battery_get_state(battery);
+ } else if (psp != POWER_SUPPLY_PROP_PRESENT)
return -ENODEV;
- acpi_battery_update(battery);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
if (battery->state & 0x01)
@@ -457,6 +458,7 @@
return;
device_remove_file(battery->bat.dev, &alarm_attr);
power_supply_unregister(&battery->bat);
+ battery->bat.dev = NULL;
}
static int acpi_battery_update(struct acpi_battery *battery)
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index a736ef7..9e8c20c 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -591,9 +591,12 @@
NULL,
&toshiba_backlight_data);
if (IS_ERR(toshiba_backlight_device)) {
+ int ret = PTR_ERR(toshiba_backlight_device);
+
printk(KERN_ERR "Could not register toshiba backlight device\n");
toshiba_backlight_device = NULL;
toshiba_acpi_exit();
+ return ret;
}
toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 6332aca..b4c0888 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -28,6 +28,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <net/sock.h>
+#include <linux/net.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -126,7 +127,7 @@
if (lo->sock) {
printk(KERN_WARNING "%s: shutting down socket\n",
lo->disk->disk_name);
- lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN);
+ kernel_sock_shutdown(lo->sock, SHUT_RDWR);
lo->sock = NULL;
}
if (lock)
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index ceffa60..e7fe6ca 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -488,13 +488,11 @@
return r;
}
-#define DBMSG(msg) ((verbose>1)?(msg):NULL)
-
static void pf_lock(struct pf_unit *pf, int func)
{
char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 };
- pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock");
+ pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock");
}
static void pf_eject(struct pf_unit *pf)
@@ -555,7 +553,7 @@
{ ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 };
char buf[8];
- pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense"));
+ pf_atapi(pf, ms_cmd, 8, buf, "mode sense");
pf->media_status = PF_RW;
if (buf[3] & 0x80)
pf->media_status = PF_RO;
@@ -591,7 +589,7 @@
char buf[8];
int bs;
- if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) {
+ if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) {
pf->media_status = PF_NM;
return;
}
@@ -804,13 +802,18 @@
pf_buf += 512;
pf_block++;
if (!pf_run)
- return 0;
- if (!pf_count)
return 1;
- spin_lock_irqsave(&pf_spin_lock, saved_flags);
- pf_end_request(1);
- spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
- return 1;
+ if (!pf_count) {
+ spin_lock_irqsave(&pf_spin_lock, saved_flags);
+ pf_end_request(1);
+ pf_req = elv_next_request(pf_queue);
+ spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
+ if (!pf_req)
+ return 1;
+ pf_count = pf_req->current_nr_sectors;
+ pf_buf = pf_req->buffer;
+ }
+ return 0;
}
static inline void next_request(int success)
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 47f8ac6..82f4eec 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -189,6 +189,18 @@
return 0;
}
+/*
+ * releasepage is called by pagevec_strip/try_to_release_page if
+ * buffers_heads_over_limit is true. Without a releasepage function
+ * try_to_free_buffers is called instead. That can unset the dirty
+ * bit of our ram disk pages, which will be eventually freed, even
+ * if the page is still in use.
+ */
+static int ramdisk_releasepage(struct page *page, gfp_t dummy)
+{
+ return 0;
+}
+
static const struct address_space_operations ramdisk_aops = {
.readpage = ramdisk_readpage,
.prepare_write = ramdisk_prepare_write,
@@ -196,6 +208,7 @@
.writepage = ramdisk_writepage,
.set_page_dirty = ramdisk_set_page_dirty,
.writepages = ramdisk_writepages,
+ .releasepage = ramdisk_releasepage,
};
static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector,
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index cc5d777..02518da 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -47,7 +47,7 @@
/* #define ATR_CSUM */
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index a0b9c87..5f291bf 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -41,7 +41,7 @@
#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
+#define reader_to_dev(x) (&handle_to_dev(x->p_dev))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 1756b1f..5fee056 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1494,7 +1494,7 @@
seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
seq += keyptr->count;
- seq += ktime_get_real().tv64;
+ seq += ktime_to_ns(ktime_get_real());
return seq;
}
@@ -1556,7 +1556,7 @@
* overlaps less than one time per MSL (2 minutes).
* Choosing a clock of 64 ns period is OK. (period of 274 s)
*/
- seq += ktime_get_real().tv64 >> 6;
+ seq += ktime_to_ns(ktime_get_real()) >> 6;
#if 0
printk("init_seq(%lx, %lx, %d, %d) = %d\n",
saddr, daddr, sport, dport, seq);
@@ -1616,7 +1616,7 @@
seq = half_md4_transform(hash, keyptr->secret);
seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
- seq += ktime_get_real().tv64;
+ seq += ktime_to_ns(ktime_get_real());
seq &= (1ull << 48) - 1;
#if 0
printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n",
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index ec6b65e..0c66b80 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -918,6 +918,31 @@
};
#endif
+static resource_size_t rtc_size;
+
+static struct resource * __init rtc_request_region(resource_size_t size)
+{
+ struct resource *r;
+
+ if (RTC_IOMAPPED)
+ r = request_region(RTC_PORT(0), size, "rtc");
+ else
+ r = request_mem_region(RTC_PORT(0), size, "rtc");
+
+ if (r)
+ rtc_size = size;
+
+ return r;
+}
+
+static void rtc_release_region(void)
+{
+ if (RTC_IOMAPPED)
+ release_region(RTC_PORT(0), rtc_size);
+ else
+ release_mem_region(RTC_PORT(0), rtc_size);
+}
+
static int __init rtc_init(void)
{
#ifdef CONFIG_PROC_FS
@@ -968,10 +993,17 @@
}
no_irq:
#else
- if (RTC_IOMAPPED)
- r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
- else
- r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
+ r = rtc_request_region(RTC_IO_EXTENT);
+
+ /*
+ * If we've already requested a smaller range (for example, because
+ * PNPBIOS or ACPI told us how the device is configured), the request
+ * above might fail because it's too big.
+ *
+ * If so, request just the range we actually use.
+ */
+ if (!r)
+ r = rtc_request_region(RTC_IO_EXTENT_USED);
if (!r) {
#ifdef RTC_IRQ
rtc_has_irq = 0;
@@ -992,10 +1024,7 @@
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
rtc_has_irq = 0;
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
- if (RTC_IOMAPPED)
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- else
- release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
return -EIO;
}
hpet_rtc_timer_init();
@@ -1009,7 +1038,7 @@
free_irq(RTC_IRQ, NULL);
rtc_has_irq = 0;
#endif
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
return -ENODEV;
}
@@ -1091,10 +1120,7 @@
if (rtc_has_irq)
free_irq (rtc_irq, &rtc_port);
#else
- if (RTC_IOMAPPED)
- release_region(RTC_PORT(0), RTC_IO_EXTENT);
- else
- release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
+ rtc_release_region();
#ifdef RTC_IRQ
if (rtc_has_irq)
free_irq (RTC_IRQ, NULL);
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 8248992..d59b2f4 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -182,10 +182,9 @@
/* we are done once this client rejects
* an available resource
*/
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_get(chan);
- kref_get(&device->refcount);
- } else if (ack == DMA_NAK)
+ else if (ack == DMA_NAK)
return;
}
}
@@ -272,11 +271,8 @@
/* client was holding resources for this channel so
* free it
*/
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_put(chan);
- kref_put(&chan->device->refcount,
- dma_async_device_cleanup);
- }
}
mutex_unlock(&dma_list_mutex);
@@ -316,11 +312,8 @@
ack = client->event_callback(client, chan,
DMA_RESOURCE_REMOVED);
- if (ack == DMA_ACK) {
+ if (ack == DMA_ACK)
dma_chan_put(chan);
- kref_put(&chan->device->refcount,
- dma_async_device_cleanup);
- }
}
list_del(&client->global_node);
@@ -397,6 +390,8 @@
goto err_out;
}
+ /* One for the channel, one of the class device */
+ kref_get(&device->refcount);
kref_get(&device->refcount);
kref_init(&chan->refcount);
chan->slow_ref = 0;
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index f204c39..16e0fd8 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -39,10 +39,14 @@
MODULE_AUTHOR("Intel Corporation");
static struct pci_device_id ioat_pci_tbl[] = {
+ /* I/OAT v1 platforms */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) },
{ PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
+
+ /* I/OAT v2 platforms */
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
{ 0, }
};
@@ -74,10 +78,17 @@
if (device->dma && ioat_dca_enabled)
device->dca = ioat_dca_init(pdev, iobase);
break;
+ case IOAT_VER_2_0:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat2_dca_init(pdev, iobase);
+ break;
default:
err = -ENODEV;
break;
}
+ if (!device->dma)
+ err = -ENODEV;
return err;
}
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
index ba98571..0fa8a98 100644
--- a/drivers/dma/ioat_dca.c
+++ b/drivers/dma/ioat_dca.c
@@ -261,3 +261,167 @@
return dca;
}
+
+static int ioat2_dca_add_requester(struct dca_provider *dca, struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 id;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+ id = dcaid_from_pcidev(pdev);
+
+ if (ioatdca->requester_count == ioatdca->max_requesters)
+ return -ENODEV;
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == NULL) {
+ /* found an empty slot */
+ ioatdca->requester_count++;
+ ioatdca->req_slots[i].pdev = pdev;
+ ioatdca->req_slots[i].rid = id;
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET);
+ writel(id | IOAT_DCA_GREQID_VALID,
+ ioatdca->iobase + global_req_table + (i * 4));
+ return i;
+ }
+ }
+ /* Error, ioatdma->requester_count is out of whack */
+ return -EFAULT;
+}
+
+static int ioat2_dca_remove_requester(struct dca_provider *dca,
+ struct device *dev)
+{
+ struct ioat_dca_priv *ioatdca = dca_priv(dca);
+ struct pci_dev *pdev;
+ int i;
+ u16 global_req_table;
+
+ /* This implementation only supports PCI-Express */
+ if (dev->bus != &pci_bus_type)
+ return -ENODEV;
+ pdev = to_pci_dev(dev);
+
+ for (i = 0; i < ioatdca->max_requesters; i++) {
+ if (ioatdca->req_slots[i].pdev == pdev) {
+ global_req_table =
+ readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET);
+ writel(0, ioatdca->iobase + global_req_table + (i * 4));
+ ioatdca->req_slots[i].pdev = NULL;
+ ioatdca->req_slots[i].rid = 0;
+ ioatdca->requester_count--;
+ return i;
+ }
+ }
+ return -ENODEV;
+}
+
+static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu)
+{
+ u8 tag;
+
+ tag = ioat_dca_get_tag(dca, cpu);
+ tag = (~tag) & 0x1F;
+ return tag;
+}
+
+static struct dca_ops ioat2_dca_ops = {
+ .add_requester = ioat2_dca_add_requester,
+ .remove_requester = ioat2_dca_remove_requester,
+ .get_tag = ioat2_dca_get_tag,
+};
+
+static int ioat2_dca_count_dca_slots(void *iobase, u16 dca_offset)
+{
+ int slots = 0;
+ u32 req;
+ u16 global_req_table;
+
+ global_req_table = readw(iobase + dca_offset + IOAT_DCA_GREQID_OFFSET);
+ if (global_req_table == 0)
+ return 0;
+ do {
+ req = readl(iobase + global_req_table + (slots * sizeof(u32)));
+ slots++;
+ } while ((req & IOAT_DCA_GREQID_LASTID) == 0);
+
+ return slots;
+}
+
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+{
+ struct dca_provider *dca;
+ struct ioat_dca_priv *ioatdca;
+ int slots;
+ int i;
+ int err;
+ u32 tag_map;
+ u16 dca_offset;
+ u16 csi_fsb_control;
+ u16 pcie_control;
+ u8 bit;
+
+ if (!system_has_dca_enabled(pdev))
+ return NULL;
+
+ dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET);
+ if (dca_offset == 0)
+ return NULL;
+
+ slots = ioat2_dca_count_dca_slots(iobase, dca_offset);
+ if (slots == 0)
+ return NULL;
+
+ dca = alloc_dca_provider(&ioat2_dca_ops,
+ sizeof(*ioatdca)
+ + (sizeof(struct ioat_dca_slot) * slots));
+ if (!dca)
+ return NULL;
+
+ ioatdca = dca_priv(dca);
+ ioatdca->iobase = iobase;
+ ioatdca->dca_base = iobase + dca_offset;
+ ioatdca->max_requesters = slots;
+
+ /* some bios might not know to turn these on */
+ csi_fsb_control = readw(ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET);
+ if ((csi_fsb_control & IOAT_FSB_CAP_ENABLE_PREFETCH) == 0) {
+ csi_fsb_control |= IOAT_FSB_CAP_ENABLE_PREFETCH;
+ writew(csi_fsb_control,
+ ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET);
+ }
+ pcie_control = readw(ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET);
+ if ((pcie_control & IOAT_PCI_CAP_ENABLE_MEMWR) == 0) {
+ pcie_control |= IOAT_PCI_CAP_ENABLE_MEMWR;
+ writew(pcie_control,
+ ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET);
+ }
+
+
+ /* TODO version, compatibility and configuration checks */
+
+ /* copy out the APIC to DCA tag map */
+ tag_map = readl(ioatdca->dca_base + IOAT_APICID_TAG_MAP_OFFSET);
+ for (i = 0; i < 5; i++) {
+ bit = (tag_map >> (4 * i)) & 0x0f;
+ if (bit < 8)
+ ioatdca->tag_map[i] = bit | DCA_TAG_MAP_VALID;
+ else
+ ioatdca->tag_map[i] = 0;
+ }
+
+ err = register_dca_provider(dca, &pdev->dev);
+ if (err) {
+ free_dca_provider(dca);
+ return NULL;
+ }
+
+ return dca;
+}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index 7e4a785..c1c2dcc 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -36,18 +36,24 @@
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
-#define INITIAL_IOAT_DESC_COUNT 128
-
#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
#define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common)
#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
+static int ioat_pending_level = 4;
+module_param(ioat_pending_level, int, 0644);
+MODULE_PARM_DESC(ioat_pending_level,
+ "high-water mark for pushing ioat descriptors (default: 4)");
+
/* internal functions */
static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan);
static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
+
static struct ioat_desc_sw *
-ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
+ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
+static struct ioat_desc_sw *
+ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan);
static inline struct ioat_dma_chan *ioat_lookup_chan_by_index(
struct ioatdma_device *device,
@@ -130,6 +136,12 @@
ioat_chan->device = device;
ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
ioat_chan->xfercap = xfercap;
+ ioat_chan->desccount = 0;
+ if (ioat_chan->device->version != IOAT_VER_1_2) {
+ writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
+ | IOAT_DMA_DCA_ANY_CPU,
+ ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
+ }
spin_lock_init(&ioat_chan->cleanup_lock);
spin_lock_init(&ioat_chan->desc_lock);
INIT_LIST_HEAD(&ioat_chan->free_desc);
@@ -161,13 +173,17 @@
tx_to_ioat_desc(tx)->dst = addr;
}
-static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx)
+static inline void __ioat1_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan);
+static inline void __ioat2_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan);
+
+static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
struct ioat_desc_sw *first = tx_to_ioat_desc(tx);
struct ioat_desc_sw *prev, *new;
struct ioat_dma_descriptor *hw;
- int append = 0;
dma_cookie_t cookie;
LIST_HEAD(new_chain);
u32 copy;
@@ -209,7 +225,7 @@
list_add_tail(&new->node, &new_chain);
desc_count++;
prev = new;
- } while (len && (new = ioat_dma_get_next_descriptor(ioat_chan)));
+ } while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan)));
hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
if (new->async_tx.callback) {
@@ -246,20 +262,98 @@
first->async_tx.phys;
__list_splice(&new_chain, ioat_chan->used_desc.prev);
+ ioat_chan->dmacount += desc_count;
ioat_chan->pending += desc_count;
- if (ioat_chan->pending >= 4) {
- append = 1;
- ioat_chan->pending = 0;
- }
+ if (ioat_chan->pending >= ioat_pending_level)
+ __ioat1_dma_memcpy_issue_pending(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
- if (append)
- writeb(IOAT_CHANCMD_APPEND,
- ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
-
return cookie;
}
+static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+ struct ioat_desc_sw *first = tx_to_ioat_desc(tx);
+ struct ioat_desc_sw *new;
+ struct ioat_dma_descriptor *hw;
+ dma_cookie_t cookie;
+ u32 copy;
+ size_t len;
+ dma_addr_t src, dst;
+ int orig_ack;
+ unsigned int desc_count = 0;
+
+ /* src and dest and len are stored in the initial descriptor */
+ len = first->len;
+ src = first->src;
+ dst = first->dst;
+ orig_ack = first->async_tx.ack;
+ new = first;
+
+ /* ioat_chan->desc_lock is still in force in version 2 path */
+
+ do {
+ copy = min((u32) len, ioat_chan->xfercap);
+
+ new->async_tx.ack = 1;
+
+ hw = new->hw;
+ hw->size = copy;
+ hw->ctl = 0;
+ hw->src_addr = src;
+ hw->dst_addr = dst;
+
+ len -= copy;
+ dst += copy;
+ src += copy;
+ desc_count++;
+ } while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan)));
+
+ hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ if (new->async_tx.callback) {
+ hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
+ if (first != new) {
+ /* move callback into to last desc */
+ new->async_tx.callback = first->async_tx.callback;
+ new->async_tx.callback_param
+ = first->async_tx.callback_param;
+ first->async_tx.callback = NULL;
+ first->async_tx.callback_param = NULL;
+ }
+ }
+
+ new->tx_cnt = desc_count;
+ new->async_tx.ack = orig_ack; /* client is in control of this ack */
+
+ /* store the original values for use in later cleanup */
+ if (new != first) {
+ new->src = first->src;
+ new->dst = first->dst;
+ new->len = first->len;
+ }
+
+ /* cookie incr and addition to used_list must be atomic */
+ cookie = ioat_chan->common.cookie;
+ cookie++;
+ if (cookie < 0)
+ cookie = 1;
+ ioat_chan->common.cookie = new->async_tx.cookie = cookie;
+
+ ioat_chan->dmacount += desc_count;
+ ioat_chan->pending += desc_count;
+ if (ioat_chan->pending >= ioat_pending_level)
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ return cookie;
+}
+
+/**
+ * ioat_dma_alloc_descriptor - allocate and return a sw and hw descriptor pair
+ * @ioat_chan: the channel supplying the memory pool for the descriptors
+ * @flags: allocation flags
+ */
static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
struct ioat_dma_chan *ioat_chan,
gfp_t flags)
@@ -284,15 +378,57 @@
dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
desc_sw->async_tx.tx_set_src = ioat_set_src;
desc_sw->async_tx.tx_set_dest = ioat_set_dest;
- desc_sw->async_tx.tx_submit = ioat_tx_submit;
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc_sw->async_tx.tx_submit = ioat1_tx_submit;
+ break;
+ case IOAT_VER_2_0:
+ desc_sw->async_tx.tx_submit = ioat2_tx_submit;
+ break;
+ }
INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
+
desc_sw->hw = desc;
desc_sw->async_tx.phys = phys;
return desc_sw;
}
-/* returns the actual number of allocated descriptors */
+static int ioat_initial_desc_count = 256;
+module_param(ioat_initial_desc_count, int, 0644);
+MODULE_PARM_DESC(ioat_initial_desc_count,
+ "initial descriptors per channel (default: 256)");
+
+/**
+ * ioat2_dma_massage_chan_desc - link the descriptors into a circle
+ * @ioat_chan: the channel to be massaged
+ */
+static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *desc, *_desc;
+
+ /* setup used_desc */
+ ioat_chan->used_desc.next = ioat_chan->free_desc.next;
+ ioat_chan->used_desc.prev = NULL;
+
+ /* pull free_desc out of the circle so that every node is a hw
+ * descriptor, but leave it pointing to the list
+ */
+ ioat_chan->free_desc.prev->next = ioat_chan->free_desc.next;
+ ioat_chan->free_desc.next->prev = ioat_chan->free_desc.prev;
+
+ /* circle link the hw descriptors */
+ desc = to_ioat_desc(ioat_chan->free_desc.next);
+ desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;
+ list_for_each_entry_safe(desc, _desc, ioat_chan->free_desc.next, node) {
+ desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys;
+ }
+}
+
+/**
+ * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors
+ * @chan: the channel to be filled out
+ */
static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
@@ -304,7 +440,7 @@
/* have we already been set up? */
if (!list_empty(&ioat_chan->free_desc))
- return INITIAL_IOAT_DESC_COUNT;
+ return ioat_chan->desccount;
/* Setup register to interrupt and write completion status on error */
chanctrl = IOAT_CHANCTRL_ERR_INT_EN |
@@ -320,7 +456,7 @@
}
/* Allocate descriptors */
- for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) {
+ for (i = 0; i < ioat_initial_desc_count; i++) {
desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
if (!desc) {
dev_err(&ioat_chan->device->pdev->dev,
@@ -330,7 +466,10 @@
list_add_tail(&desc->node, &tmp_list);
}
spin_lock_bh(&ioat_chan->desc_lock);
+ ioat_chan->desccount = i;
list_splice(&tmp_list, &ioat_chan->free_desc);
+ if (ioat_chan->device->version != IOAT_VER_1_2)
+ ioat2_dma_massage_chan_desc(ioat_chan);
spin_unlock_bh(&ioat_chan->desc_lock);
/* allocate a completion writeback area */
@@ -347,10 +486,14 @@
ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
tasklet_enable(&ioat_chan->cleanup_task);
- ioat_dma_start_null_desc(ioat_chan);
- return i;
+ ioat_dma_start_null_desc(ioat_chan); /* give chain to dma device */
+ return ioat_chan->desccount;
}
+/**
+ * ioat_dma_free_chan_resources - release all the descriptors
+ * @chan: the channel to be cleaned
+ */
static void ioat_dma_free_chan_resources(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
@@ -364,22 +507,45 @@
/* Delay 100ms after reset to allow internal DMA logic to quiesce
* before removing DMA descriptor resources.
*/
- writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+ writeb(IOAT_CHANCMD_RESET,
+ ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
mdelay(100);
spin_lock_bh(&ioat_chan->desc_lock);
- list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
- in_use_descs++;
- list_del(&desc->node);
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->used_desc, node) {
+ in_use_descs++;
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->free_desc, node) {
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ break;
+ case IOAT_VER_2_0:
+ list_for_each_entry_safe(desc, _desc,
+ ioat_chan->free_desc.next, node) {
+ list_del(&desc->node);
+ pci_pool_free(ioatdma_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
+ kfree(desc);
+ }
+ desc = to_ioat_desc(ioat_chan->free_desc.next);
pci_pool_free(ioatdma_device->dma_pool, desc->hw,
desc->async_tx.phys);
kfree(desc);
- }
- list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
- list_del(&desc->node);
- pci_pool_free(ioatdma_device->dma_pool, desc->hw,
- desc->async_tx.phys);
- kfree(desc);
+ INIT_LIST_HEAD(&ioat_chan->free_desc);
+ INIT_LIST_HEAD(&ioat_chan->used_desc);
+ break;
}
spin_unlock_bh(&ioat_chan->desc_lock);
@@ -395,6 +561,7 @@
ioat_chan->last_completion = ioat_chan->completion_addr = 0;
ioat_chan->pending = 0;
+ ioat_chan->dmacount = 0;
}
/**
@@ -406,7 +573,7 @@
* has run out.
*/
static struct ioat_desc_sw *
-ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
+ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
{
struct ioat_desc_sw *new = NULL;
@@ -425,7 +592,82 @@
return new;
}
-static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy(
+static struct ioat_desc_sw *
+ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
+{
+ struct ioat_desc_sw *new = NULL;
+
+ /*
+ * used.prev points to where to start processing
+ * used.next points to next free descriptor
+ * if used.prev == NULL, there are none waiting to be processed
+ * if used.next == used.prev.prev, there is only one free descriptor,
+ * and we need to use it to as a noop descriptor before
+ * linking in a new set of descriptors, since the device
+ * has probably already read the pointer to it
+ */
+ if (ioat_chan->used_desc.prev &&
+ ioat_chan->used_desc.next == ioat_chan->used_desc.prev->prev) {
+
+ struct ioat_desc_sw *desc = NULL;
+ struct ioat_desc_sw *noop_desc = NULL;
+ int i;
+
+ /* set up the noop descriptor */
+ noop_desc = to_ioat_desc(ioat_chan->used_desc.next);
+ noop_desc->hw->size = 0;
+ noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
+ noop_desc->hw->src_addr = 0;
+ noop_desc->hw->dst_addr = 0;
+
+ ioat_chan->used_desc.next = ioat_chan->used_desc.next->next;
+ ioat_chan->pending++;
+ ioat_chan->dmacount++;
+
+ /* get a few more descriptors */
+ for (i = 16; i; i--) {
+ desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
+ BUG_ON(!desc);
+ list_add_tail(&desc->node, ioat_chan->used_desc.next);
+
+ desc->hw->next
+ = to_ioat_desc(desc->node.next)->async_tx.phys;
+ to_ioat_desc(desc->node.prev)->hw->next
+ = desc->async_tx.phys;
+ ioat_chan->desccount++;
+ }
+
+ ioat_chan->used_desc.next = noop_desc->node.next;
+ }
+ new = to_ioat_desc(ioat_chan->used_desc.next);
+ prefetch(new);
+ ioat_chan->used_desc.next = new->node.next;
+
+ if (ioat_chan->used_desc.prev == NULL)
+ ioat_chan->used_desc.prev = &new->node;
+
+ prefetch(new->hw);
+ return new;
+}
+
+static struct ioat_desc_sw *ioat_dma_get_next_descriptor(
+ struct ioat_dma_chan *ioat_chan)
+{
+ if (!ioat_chan)
+ return NULL;
+
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ return ioat1_dma_get_next_descriptor(ioat_chan);
+ break;
+ case IOAT_VER_2_0:
+ return ioat2_dma_get_next_descriptor(ioat_chan);
+ break;
+ }
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
struct dma_chan *chan,
size_t len,
int int_en)
@@ -441,19 +683,62 @@
return new ? &new->async_tx : NULL;
}
+static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
+ struct dma_chan *chan,
+ size_t len,
+ int int_en)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ struct ioat_desc_sw *new;
+
+ spin_lock_bh(&ioat_chan->desc_lock);
+ new = ioat2_dma_get_next_descriptor(ioat_chan);
+ new->len = len;
+
+ /* leave ioat_chan->desc_lock set in version 2 path */
+ return new ? &new->async_tx : NULL;
+}
+
+
/**
* ioat_dma_memcpy_issue_pending - push potentially unrecognized appended
* descriptors to hw
* @chan: DMA channel handle
*/
-static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
+static inline void __ioat1_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET);
+}
+
+static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
if (ioat_chan->pending != 0) {
- ioat_chan->pending = 0;
- writeb(IOAT_CHANCMD_APPEND,
- ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat1_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ }
+}
+
+static inline void __ioat2_dma_memcpy_issue_pending(
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writew(ioat_chan->dmacount,
+ ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+}
+
+static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (ioat_chan->pending != 0) {
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
}
}
@@ -465,11 +750,17 @@
chan->reg_base + IOAT_CHANCTRL_OFFSET);
}
+/**
+ * ioat_dma_memcpy_cleanup - cleanup up finished descriptors
+ * @chan: ioat channel to be cleaned up
+ */
static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
{
unsigned long phys_complete;
struct ioat_desc_sw *desc, *_desc;
dma_cookie_t cookie = 0;
+ unsigned long desc_phys;
+ struct ioat_desc_sw *latest_desc;
prefetch(ioat_chan->completion_virt);
@@ -507,56 +798,115 @@
cookie = 0;
spin_lock_bh(&ioat_chan->desc_lock);
- list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
-
- /*
- * Incoming DMA requests may use multiple descriptors, due to
- * exceeding xfercap, perhaps. If so, only the last one will
- * have a cookie, and require unmapping.
- */
- if (desc->async_tx.cookie) {
- cookie = desc->async_tx.cookie;
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ list_for_each_entry_safe(desc, _desc,
+ &ioat_chan->used_desc, node) {
/*
- * yes we are unmapping both _page and _single alloc'd
- * regions with unmap_page. Is this *really* that bad?
+ * Incoming DMA requests may use multiple descriptors,
+ * due to exceeding xfercap, perhaps. If so, only the
+ * last one will have a cookie, and require unmapping.
*/
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, dst),
- pci_unmap_len(desc, len),
- PCI_DMA_FROMDEVICE);
- pci_unmap_page(ioat_chan->device->pdev,
- pci_unmap_addr(desc, src),
- pci_unmap_len(desc, len),
- PCI_DMA_TODEVICE);
- if (desc->async_tx.callback) {
- desc->async_tx.callback(
- desc->async_tx.callback_param);
- desc->async_tx.callback = NULL;
+ if (desc->async_tx.cookie) {
+ cookie = desc->async_tx.cookie;
+
+ /*
+ * yes we are unmapping both _page and _single
+ * alloc'd regions with unmap_page. Is this
+ * *really* that bad?
+ */
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+
+ if (desc->async_tx.callback) {
+ desc->async_tx.callback(desc->async_tx.callback_param);
+ desc->async_tx.callback = NULL;
+ }
+ }
+
+ if (desc->async_tx.phys != phys_complete) {
+ /*
+ * a completed entry, but not the last, so clean
+ * up if the client is done with the descriptor
+ */
+ if (desc->async_tx.ack) {
+ list_del(&desc->node);
+ list_add_tail(&desc->node,
+ &ioat_chan->free_desc);
+ } else
+ desc->async_tx.cookie = 0;
+ } else {
+ /*
+ * last used desc. Do not remove, so we can
+ * append from it, but don't look at it next
+ * time, either
+ */
+ desc->async_tx.cookie = 0;
+
+ /* TODO check status bits? */
+ break;
}
}
-
- if (desc->async_tx.phys != phys_complete) {
- /*
- * a completed entry, but not the last, so cleanup
- * if the client is done with the descriptor
- */
- if (desc->async_tx.ack) {
- list_del(&desc->node);
- list_add_tail(&desc->node,
- &ioat_chan->free_desc);
- } else
- desc->async_tx.cookie = 0;
- } else {
- /*
- * last used desc. Do not remove, so we can append from
- * it, but don't look at it next time, either
- */
- desc->async_tx.cookie = 0;
-
- /* TODO check status bits? */
+ break;
+ case IOAT_VER_2_0:
+ /* has some other thread has already cleaned up? */
+ if (ioat_chan->used_desc.prev == NULL)
break;
+
+ /* work backwards to find latest finished desc */
+ desc = to_ioat_desc(ioat_chan->used_desc.next);
+ latest_desc = NULL;
+ do {
+ desc = to_ioat_desc(desc->node.prev);
+ desc_phys = (unsigned long)desc->async_tx.phys
+ & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+ if (desc_phys == phys_complete) {
+ latest_desc = desc;
+ break;
+ }
+ } while (&desc->node != ioat_chan->used_desc.prev);
+
+ if (latest_desc != NULL) {
+
+ /* work forwards to clear finished descriptors */
+ for (desc = to_ioat_desc(ioat_chan->used_desc.prev);
+ &desc->node != latest_desc->node.next &&
+ &desc->node != ioat_chan->used_desc.next;
+ desc = to_ioat_desc(desc->node.next)) {
+ if (desc->async_tx.cookie) {
+ cookie = desc->async_tx.cookie;
+ desc->async_tx.cookie = 0;
+
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, dst),
+ pci_unmap_len(desc, len),
+ PCI_DMA_FROMDEVICE);
+ pci_unmap_page(ioat_chan->device->pdev,
+ pci_unmap_addr(desc, src),
+ pci_unmap_len(desc, len),
+ PCI_DMA_TODEVICE);
+
+ if (desc->async_tx.callback) {
+ desc->async_tx.callback(desc->async_tx.callback_param);
+ desc->async_tx.callback = NULL;
+ }
+ }
+ }
+
+ /* move used.prev up beyond those that are finished */
+ if (&desc->node == ioat_chan->used_desc.next)
+ ioat_chan->used_desc.prev = NULL;
+ else
+ ioat_chan->used_desc.prev = &desc->node;
}
+ break;
}
spin_unlock_bh(&ioat_chan->desc_lock);
@@ -621,8 +971,6 @@
return dma_async_is_complete(cookie, last_complete, last_used);
}
-/* PCI API */
-
static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
{
struct ioat_desc_sw *desc;
@@ -633,21 +981,34 @@
desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL
| IOAT_DMA_DESCRIPTOR_CTL_INT_GN
| IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
- desc->hw->next = 0;
desc->hw->size = 0;
desc->hw->src_addr = 0;
desc->hw->dst_addr = 0;
desc->async_tx.ack = 1;
+ switch (ioat_chan->device->version) {
+ case IOAT_VER_1_2:
+ desc->hw->next = 0;
+ list_add_tail(&desc->node, &ioat_chan->used_desc);
- list_add_tail(&desc->node, &ioat_chan->used_desc);
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+ writeb(IOAT_CHANCMD_START, ioat_chan->reg_base
+ + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+ break;
+ case IOAT_VER_2_0:
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);
+
+ ioat_chan->dmacount++;
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ break;
+ }
spin_unlock_bh(&ioat_chan->desc_lock);
-
- writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
- ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW);
- writel(((u64) desc->async_tx.phys) >> 32,
- ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH);
-
- writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
}
/*
@@ -693,14 +1054,14 @@
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (ioat_dma_alloc_chan_resources(dma_chan) < 1) {
+ if (device->common.device_alloc_chan_resources(dma_chan) < 1) {
dev_err(&device->pdev->dev,
"selftest cannot allocate chan resource\n");
err = -ENODEV;
goto out;
}
- tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+ tx = device->common.device_prep_dma_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
if (!tx) {
dev_err(&device->pdev->dev,
"Self-test prep failed, disabling\n");
@@ -710,24 +1071,25 @@
async_tx_ack(tx);
addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
- DMA_TO_DEVICE);
- ioat_set_src(addr, tx, 0);
+ DMA_TO_DEVICE);
+ tx->tx_set_src(addr, tx, 0);
addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
- DMA_FROM_DEVICE);
- ioat_set_dest(addr, tx, 0);
+ DMA_FROM_DEVICE);
+ tx->tx_set_dest(addr, tx, 0);
tx->callback = ioat_dma_test_callback;
tx->callback_param = (void *)0x8086;
- cookie = ioat_tx_submit(tx);
+ cookie = tx->tx_submit(tx);
if (cookie < 0) {
dev_err(&device->pdev->dev,
"Self-test setup failed, disabling\n");
err = -ENODEV;
goto free_resources;
}
- ioat_dma_memcpy_issue_pending(dma_chan);
+ device->common.device_issue_pending(dma_chan);
msleep(1);
- if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+ if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
+ != DMA_SUCCESS) {
dev_err(&device->pdev->dev,
"Self-test copy timed out, disabling\n");
err = -ENODEV;
@@ -741,7 +1103,7 @@
}
free_resources:
- ioat_dma_free_chan_resources(dma_chan);
+ device->common.device_free_chan_resources(dma_chan);
out:
kfree(src);
kfree(dest);
@@ -941,16 +1303,28 @@
INIT_LIST_HEAD(&device->common.channels);
ioat_dma_enumerate_channels(device);
- dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
device->common.device_alloc_chan_resources =
ioat_dma_alloc_chan_resources;
device->common.device_free_chan_resources =
ioat_dma_free_chan_resources;
- device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
- device->common.device_is_tx_complete = ioat_dma_is_complete;
- device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
- device->common.device_dependency_added = ioat_dma_dependency_added;
device->common.dev = &pdev->dev;
+
+ dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
+ device->common.device_is_tx_complete = ioat_dma_is_complete;
+ device->common.device_dependency_added = ioat_dma_dependency_added;
+ switch (device->version) {
+ case IOAT_VER_1_2:
+ device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
+ device->common.device_issue_pending =
+ ioat1_dma_memcpy_issue_pending;
+ break;
+ case IOAT_VER_2_0:
+ device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy;
+ device->common.device_issue_pending =
+ ioat2_dma_memcpy_issue_pending;
+ break;
+ }
+
dev_err(&device->pdev->dev,
"Intel(R) I/OAT DMA Engine found,"
" %d channels, device version 0x%02x, driver version %s\n",
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index 5f9881e7..b668234 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -28,7 +28,7 @@
#include <linux/cache.h>
#include <linux/pci_ids.h>
-#define IOAT_DMA_VERSION "1.26"
+#define IOAT_DMA_VERSION "2.04"
enum ioat_interrupt {
none = 0,
@@ -39,6 +39,8 @@
};
#define IOAT_LOW_COMPLETION_MASK 0xffffffc0
+#define IOAT_DMA_DCA_ANY_CPU ~0
+
/**
* struct ioatdma_device - internal representation of a IOAT device
@@ -47,6 +49,9 @@
* @dma_pool: for allocating DMA descriptors
* @common: embedded struct dma_device
* @version: version of ioatdma device
+ * @irq_mode: which style irq to use
+ * @msix_entries: irq handlers
+ * @idx: per channel data
*/
struct ioatdma_device {
@@ -63,23 +68,7 @@
/**
* struct ioat_dma_chan - internal representation of a DMA channel
- * @device:
- * @reg_base:
- * @sw_in_use:
- * @completion:
- * @completion_low:
- * @completion_high:
- * @completed_cookie: last cookie seen completed on cleanup
- * @cookie: value of last cookie given to client
- * @last_completion:
- * @xfercap:
- * @desc_lock:
- * @free_desc:
- * @used_desc:
- * @resource:
- * @device_node:
*/
-
struct ioat_dma_chan {
void __iomem *reg_base;
@@ -95,6 +84,8 @@
struct list_head used_desc;
int pending;
+ int dmacount;
+ int desccount;
struct ioatdma_device *device;
struct dma_chan common;
@@ -134,12 +125,13 @@
struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
void __iomem *iobase);
void ioat_dma_remove(struct ioatdma_device *device);
-struct dca_provider *ioat_dca_init(struct pci_dev *pdev,
- void __iomem *iobase);
+struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
#else
#define ioat_dma_probe(pdev, iobase) NULL
#define ioat_dma_remove(device) do { } while (0)
#define ioat_dca_init(pdev, iobase) NULL
+#define ioat2_dca_init(pdev, iobase) NULL
#endif
#endif /* IOATDMA_H */
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
index 9e7434e..dd470fa 100644
--- a/drivers/dma/ioatdma_hw.h
+++ b/drivers/dma/ioatdma_hw.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -22,12 +22,19 @@
#define _IOAT_HW_H_
/* PCI Configuration Space Values */
-#define IOAT_PCI_VID 0x8086
-#define IOAT_PCI_DID 0x1A38
-#define IOAT_PCI_RID 0x00
-#define IOAT_PCI_SVID 0x8086
-#define IOAT_PCI_SID 0x8086
-#define IOAT_VER_1_2 0x12 /* Version 1.2 */
+#define IOAT_PCI_VID 0x8086
+
+/* CB device ID's */
+#define IOAT_PCI_DID_5000 0x1A38
+#define IOAT_PCI_DID_CNB 0x360B
+#define IOAT_PCI_DID_SCNB 0x65FF
+#define IOAT_PCI_DID_SNB 0x402F
+
+#define IOAT_PCI_RID 0x00
+#define IOAT_PCI_SVID 0x8086
+#define IOAT_PCI_SID 0x8086
+#define IOAT_VER_1_2 0x12 /* Version 1.2 */
+#define IOAT_VER_2_0 0x20 /* Version 2.0 */
struct ioat_dma_descriptor {
uint32_t size;
@@ -47,6 +54,16 @@
#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008
#define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x00000010
#define IOAT_DMA_DESCRIPTOR_NUL 0x00000020
-#define IOAT_DMA_DESCRIPTOR_OPCODE 0xFF000000
+#define IOAT_DMA_DESCRIPTOR_CTL_SP_BRK 0x00000040
+#define IOAT_DMA_DESCRIPTOR_CTL_DP_BRK 0x00000080
+#define IOAT_DMA_DESCRIPTOR_CTL_BNDL 0x00000100
+#define IOAT_DMA_DESCRIPTOR_CTL_DCA 0x00000200
+#define IOAT_DMA_DESCRIPTOR_CTL_BUFHINT 0x00000400
+
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_CONTEXT 0xFF000000
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_DMA 0x00000000
+
+#define IOAT_DMA_DESCRIPTOR_CTL_CONTEXT_DCA 0x00000001
+#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_MASK 0xFF000000
#endif
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
index baaab5e..9832d7e 100644
--- a/drivers/dma/ioatdma_registers.h
+++ b/drivers/dma/ioatdma_registers.h
@@ -42,26 +42,25 @@
#define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */
#define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */
#define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */
-#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */
+#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */
#define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */
#define IOAT_VER_OFFSET 0x08 /* 8-bit */
#define IOAT_VER_MAJOR_MASK 0xF0
#define IOAT_VER_MINOR_MASK 0x0F
-#define GET_IOAT_VER_MAJOR(x) ((x) & IOAT_VER_MAJOR_MASK)
+#define GET_IOAT_VER_MAJOR(x) (((x) & IOAT_VER_MAJOR_MASK) >> 4)
#define GET_IOAT_VER_MINOR(x) ((x) & IOAT_VER_MINOR_MASK)
#define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */
#define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */
#define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */
-#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalesing Supported */
+#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */
#define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */
#define IOAT_DEVICE_STATUS_DEGRADED_MODE 0x0001
-
#define IOAT_CHANNEL_MMIO_SIZE 0x80 /* Each Channel MMIO space is this size */
/* DMA Channel Registers */
@@ -74,25 +73,101 @@
#define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004
#define IOAT_CHANCTRL_INT_DISABLE 0x0001
-#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatability */
-#define IOAT_DMA_COMP_V1 0x0001 /* Compatability with DMA version 1 */
+#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatibility */
+#define IOAT_DMA_COMP_V1 0x0001 /* Compatibility with DMA version 1 */
+#define IOAT_DMA_COMP_V2 0x0002 /* Compatibility with DMA version 2 */
-#define IOAT_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */
-#define IOAT_CHANSTS_OFFSET_LOW 0x04
-#define IOAT_CHANSTS_OFFSET_HIGH 0x08
-#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0UL
+
+#define IOAT1_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */
+#define IOAT2_CHANSTS_OFFSET 0x08 /* 64-bit Channel Status Register */
+#define IOAT_CHANSTS_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET : IOAT2_CHANSTS_OFFSET)
+#define IOAT1_CHANSTS_OFFSET_LOW 0x04
+#define IOAT2_CHANSTS_OFFSET_LOW 0x08
+#define IOAT_CHANSTS_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET_LOW : IOAT2_CHANSTS_OFFSET_LOW)
+#define IOAT1_CHANSTS_OFFSET_HIGH 0x08
+#define IOAT2_CHANSTS_OFFSET_HIGH 0x0C
+#define IOAT_CHANSTS_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANSTS_OFFSET_HIGH : IOAT2_CHANSTS_OFFSET_HIGH)
+#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR ~0x3F
#define IOAT_CHANSTS_SOFT_ERR 0x0000000000000010
+#define IOAT_CHANSTS_UNAFFILIATED_ERR 0x0000000000000008
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS 0x0000000000000007
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE 0x0
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE 0x1
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED 0x2
#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED 0x3
-#define IOAT_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
-#define IOAT_CHAINADDR_OFFSET_LOW 0x0C
-#define IOAT_CHAINADDR_OFFSET_HIGH 0x10
-#define IOAT_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */
+
+#define IOAT_CHAN_DMACOUNT_OFFSET 0x06 /* 16-bit DMA Count register */
+
+#define IOAT_DCACTRL_OFFSET 0x30 /* 32 bit Direct Cache Access Control Register */
+#define IOAT_DCACTRL_CMPL_WRITE_ENABLE 0x10000
+#define IOAT_DCACTRL_TARGET_CPU_MASK 0xFFFF /* APIC ID */
+
+/* CB DCA Memory Space Registers */
+#define IOAT_DCAOFFSET_OFFSET 0x14
+/* CB_BAR + IOAT_DCAOFFSET value */
+#define IOAT_DCA_VER_OFFSET 0x00
+#define IOAT_DCA_VER_MAJOR_MASK 0xF0
+#define IOAT_DCA_VER_MINOR_MASK 0x0F
+
+#define IOAT_DCA_COMP_OFFSET 0x02
+#define IOAT_DCA_COMP_V1 0x1
+
+#define IOAT_FSB_CAPABILITY_OFFSET 0x04
+#define IOAT_FSB_CAPABILITY_PREFETCH 0x1
+
+#define IOAT_PCI_CAPABILITY_OFFSET 0x06
+#define IOAT_PCI_CAPABILITY_MEMWR 0x1
+
+#define IOAT_FSB_CAP_ENABLE_OFFSET 0x08
+#define IOAT_FSB_CAP_ENABLE_PREFETCH 0x1
+
+#define IOAT_PCI_CAP_ENABLE_OFFSET 0x0A
+#define IOAT_PCI_CAP_ENABLE_MEMWR 0x1
+
+#define IOAT_APICID_TAG_MAP_OFFSET 0x0C
+#define IOAT_APICID_TAG_MAP_TAG0 0x0000000F
+#define IOAT_APICID_TAG_MAP_TAG0_SHIFT 0
+#define IOAT_APICID_TAG_MAP_TAG1 0x000000F0
+#define IOAT_APICID_TAG_MAP_TAG1_SHIFT 4
+#define IOAT_APICID_TAG_MAP_TAG2 0x00000F00
+#define IOAT_APICID_TAG_MAP_TAG2_SHIFT 8
+#define IOAT_APICID_TAG_MAP_TAG3 0x0000F000
+#define IOAT_APICID_TAG_MAP_TAG3_SHIFT 12
+#define IOAT_APICID_TAG_MAP_TAG4 0x000F0000
+#define IOAT_APICID_TAG_MAP_TAG4_SHIFT 16
+#define IOAT_APICID_TAG_CB2_VALID 0x8080808080
+
+#define IOAT_DCA_GREQID_OFFSET 0x10
+#define IOAT_DCA_GREQID_SIZE 0x04
+#define IOAT_DCA_GREQID_MASK 0xFFFF
+#define IOAT_DCA_GREQID_IGNOREFUN 0x10000000
+#define IOAT_DCA_GREQID_VALID 0x20000000
+#define IOAT_DCA_GREQID_LASTID 0x80000000
+
+
+
+#define IOAT1_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */
+#define IOAT2_CHAINADDR_OFFSET 0x10 /* 64-bit Descriptor Chain Address Register */
+#define IOAT_CHAINADDR_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET : IOAT2_CHAINADDR_OFFSET)
+#define IOAT1_CHAINADDR_OFFSET_LOW 0x0C
+#define IOAT2_CHAINADDR_OFFSET_LOW 0x10
+#define IOAT_CHAINADDR_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET_LOW : IOAT2_CHAINADDR_OFFSET_LOW)
+#define IOAT1_CHAINADDR_OFFSET_HIGH 0x10
+#define IOAT2_CHAINADDR_OFFSET_HIGH 0x14
+#define IOAT_CHAINADDR_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHAINADDR_OFFSET_HIGH : IOAT2_CHAINADDR_OFFSET_HIGH)
+
+#define IOAT1_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */
+#define IOAT2_CHANCMD_OFFSET 0x04 /* 8-bit DMA Channel Command Register */
+#define IOAT_CHANCMD_OFFSET(ver) ((ver) < IOAT_VER_2_0 \
+ ? IOAT1_CHANCMD_OFFSET : IOAT2_CHANCMD_OFFSET)
#define IOAT_CHANCMD_RESET 0x20
#define IOAT_CHANCMD_RESUME 0x10
#define IOAT_CHANCMD_ABORT 0x08
@@ -124,6 +199,7 @@
#define IOAT_CHANERR_COMPLETION_ADDR_ERR 0x1000
#define IOAT_CHANERR_INT_CONFIGURATION_ERR 0x2000
#define IOAT_CHANERR_SOFT_ERR 0x4000
+#define IOAT_CHANERR_UNAFFILIATED_ERR 0x8000
#define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index 96f7e63..a1f24c4 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1462,7 +1462,7 @@
*
*/
static struct pci_driver i5000_driver = {
- .name = __stringify(KBUILD_BASENAME),
+ .name = KBUILD_BASENAME,
.probe = i5000_init_one,
.remove = __devexit_p(i5000_remove_one),
.id_table = i5000_pci_tbl,
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 700a165..a0445be 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -216,6 +216,16 @@
This driver can also be built as a module. If so, the module
will be called ds1621.
+config SENSORS_I5K_AMB
+ tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
+ depends on PCI && EXPERIMENTAL
+ help
+ If you say yes here you get support for FB-DIMM AMB temperature
+ monitoring chips on systems with the Intel 5000 series chipset.
+
+ This driver can also be built as a module. If so, the module
+ will be called i5k_amb.
+
config SENSORS_F71805F
tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
depends on EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 6da3eef..55595f6 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -38,6 +38,7 @@
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
+obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index cb2331b..d9f04ce 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -503,7 +503,7 @@
{ "AUX3 FAN", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001A, "unknown", {
+ { 0x001A, "Abit IP35 Pro", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -530,6 +530,60 @@
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
+ { 0x001B, "unknown", {
+ { "CPU Core", 0, 0, 10, 1, 0 },
+ { "DDR3", 1, 0, 20, 1, 0 },
+ { "DDR3 VTT", 2, 0, 10, 1, 0 },
+ { "CPU VTT", 3, 0, 10, 1, 0 },
+ { "MCH 1.25V", 4, 0, 10, 1, 0 },
+ { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
+ { "ICH 1.05V", 6, 0, 10, 1, 0 },
+ { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+ { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
+ { "ATX +5V", 9, 0, 30, 1, 0 },
+ { "+3.3V", 10, 0, 20, 1, 0 },
+ { "5VSB", 11, 0, 30, 1, 0 },
+ { "CPU", 24, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
+ { "PWM Phase1", 26, 1, 1, 1, 0 },
+ { "PWM Phase2", 27, 1, 1, 1, 0 },
+ { "PWM Phase3", 28, 1, 1, 1, 0 },
+ { "PWM Phase4", 29, 1, 1, 1, 0 },
+ { "PWM Phase5", 30, 1, 1, 1, 0 },
+ { "CPU Fan", 32, 2, 60, 1, 0 },
+ { "SYS Fan", 34, 2, 60, 1, 0 },
+ { "AUX1 Fan", 33, 2, 60, 1, 0 },
+ { "AUX2 Fan", 35, 2, 60, 1, 0 },
+ { "AUX3 Fan", 36, 2, 60, 1, 0 },
+ { NULL, 0, 0, 0, 0, 0 } }
+ },
+ { 0x001C, "unknown", {
+ { "CPU Core", 0, 0, 10, 1, 0 },
+ { "DDR2", 1, 0, 20, 1, 0 },
+ { "DDR2 VTT", 2, 0, 10, 1, 0 },
+ { "CPU VTT", 3, 0, 10, 1, 0 },
+ { "MCH 1.25V", 4, 0, 10, 1, 0 },
+ { "ICHIO 1.5V", 5, 0, 10, 1, 0 },
+ { "ICH 1.05V", 6, 0, 10, 1, 0 },
+ { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+ { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 },
+ { "ATX +5V", 9, 0, 30, 1, 0 },
+ { "+3.3V", 10, 0, 20, 1, 0 },
+ { "5VSB", 11, 0, 30, 1, 0 },
+ { "CPU", 24, 1, 1, 1, 0 },
+ { "System", 25, 1, 1, 1, 0 },
+ { "PWM Phase1", 26, 1, 1, 1, 0 },
+ { "PWM Phase2", 27, 1, 1, 1, 0 },
+ { "PWM Phase3", 28, 1, 1, 1, 0 },
+ { "PWM Phase4", 29, 1, 1, 1, 0 },
+ { "PWM Phase5", 30, 1, 1, 1, 0 },
+ { "CPU Fan", 32, 2, 60, 1, 0 },
+ { "SYS Fan", 34, 2, 60, 1, 0 },
+ { "AUX1 Fan", 33, 2, 60, 1, 0 },
+ { "AUX2 Fan", 35, 2, 60, 1, 0 },
+ { "AUX3 Fan", 36, 2, 60, 1, 0 },
+ { NULL, 0, 0, 0, 0, 0 } }
+ },
{ 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
};
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 1001d2e..86c66c3 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -80,7 +80,7 @@
/*
* Temperature sensors keys (sp78 - 2 bytes).
*/
-static const char* temperature_sensors_sets[][13] = {
+static const char* temperature_sensors_sets[][36] = {
/* Set 0: Macbook Pro */
{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
"Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
@@ -88,7 +88,13 @@
{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
"Th1H", "Ts0P", NULL },
/* Set 2: Macmini set */
- { "TC0D", "TC0P", NULL }
+ { "TC0D", "TC0P", NULL },
+/* Set 3: Mac Pro (2 x Quad-Core) */
+ { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
+ "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
+ "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
+ "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
+ "TM9S", "TN0H", "TS0C", NULL },
};
/* List of keys used to read/write fan speeds */
@@ -990,14 +996,18 @@
/*
* Create the needed functions for each fan using the macro defined above
- * (2 fans are supported)
+ * (4 fans are supported)
*/
sysfs_fan_speeds_offset(1);
sysfs_fan_speeds_offset(2);
+sysfs_fan_speeds_offset(3);
+sysfs_fan_speeds_offset(4);
static const struct attribute_group fan_attribute_groups[] = {
{ .attrs = fan1_attributes },
- { .attrs = fan2_attributes }
+ { .attrs = fan2_attributes },
+ { .attrs = fan3_attributes },
+ { .attrs = fan4_attributes },
};
/*
@@ -1027,6 +1037,52 @@
applesmc_show_temperature, NULL, 10);
static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
applesmc_show_temperature, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 14);
+static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 15);
+static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 16);
+static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 17);
+static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 18);
+static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 19);
+static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 20);
+static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 21);
+static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 22);
+static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 23);
+static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 24);
+static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 25);
+static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 26);
+static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 27);
+static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 28);
+static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 29);
+static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 30);
+static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 31);
+static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 32);
+static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 33);
+static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 34);
static struct attribute *temperature_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -1041,6 +1097,29 @@
&sensor_dev_attr_temp10_input.dev_attr.attr,
&sensor_dev_attr_temp11_input.dev_attr.attr,
&sensor_dev_attr_temp12_input.dev_attr.attr,
+ &sensor_dev_attr_temp13_input.dev_attr.attr,
+ &sensor_dev_attr_temp14_input.dev_attr.attr,
+ &sensor_dev_attr_temp15_input.dev_attr.attr,
+ &sensor_dev_attr_temp16_input.dev_attr.attr,
+ &sensor_dev_attr_temp17_input.dev_attr.attr,
+ &sensor_dev_attr_temp18_input.dev_attr.attr,
+ &sensor_dev_attr_temp19_input.dev_attr.attr,
+ &sensor_dev_attr_temp20_input.dev_attr.attr,
+ &sensor_dev_attr_temp21_input.dev_attr.attr,
+ &sensor_dev_attr_temp22_input.dev_attr.attr,
+ &sensor_dev_attr_temp23_input.dev_attr.attr,
+ &sensor_dev_attr_temp24_input.dev_attr.attr,
+ &sensor_dev_attr_temp25_input.dev_attr.attr,
+ &sensor_dev_attr_temp26_input.dev_attr.attr,
+ &sensor_dev_attr_temp27_input.dev_attr.attr,
+ &sensor_dev_attr_temp28_input.dev_attr.attr,
+ &sensor_dev_attr_temp29_input.dev_attr.attr,
+ &sensor_dev_attr_temp30_input.dev_attr.attr,
+ &sensor_dev_attr_temp31_input.dev_attr.attr,
+ &sensor_dev_attr_temp32_input.dev_attr.attr,
+ &sensor_dev_attr_temp33_input.dev_attr.attr,
+ &sensor_dev_attr_temp34_input.dev_attr.attr,
+ &sensor_dev_attr_temp35_input.dev_attr.attr,
NULL
};
@@ -1137,6 +1216,8 @@
{ .accelerometer = 1, .light = 0, .temperature_set = 1 },
/* MacMini: temperature set 2 */
{ .accelerometer = 0, .light = 0, .temperature_set = 2 },
+/* MacPro: temperature set 3 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 3 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1154,6 +1235,10 @@
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
(void*)&applesmc_dmi_data[2]},
+ { applesmc_dmi_match, "Apple MacPro2", {
+ DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
+ (void*)&applesmc_dmi_data[3]},
{ .ident = NULL }
};
@@ -1204,9 +1289,19 @@
switch (count) {
default:
- printk(KERN_WARNING "applesmc: More than 2 fans found,"
- " but at most 2 fans are supported"
+ printk(KERN_WARNING "applesmc: More than 4 fans found,"
+ " but at most 4 fans are supported"
" by the driver.\n");
+ case 4:
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[3]);
+ if (ret)
+ goto out_key_enumeration;
+ case 3:
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[2]);
+ if (ret)
+ goto out_key_enumeration;
case 2:
ret = sysfs_create_group(&pdev->dev.kobj,
&fan_attribute_groups[1]);
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 13a0413..6892f76 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -34,6 +34,7 @@
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/f75375s.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END };
@@ -86,7 +87,7 @@
struct f75375_data {
unsigned short addr;
- struct i2c_client client;
+ struct i2c_client *client;
struct device *hwmon_dev;
const char *name;
@@ -116,13 +117,23 @@
static int f75375_attach_adapter(struct i2c_adapter *adapter);
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
static int f75375_detach_client(struct i2c_client *client);
+static int f75375_probe(struct i2c_client *client);
+static int f75375_remove(struct i2c_client *client);
+
+static struct i2c_driver f75375_legacy_driver = {
+ .driver = {
+ .name = "f75375_legacy",
+ },
+ .attach_adapter = f75375_attach_adapter,
+ .detach_client = f75375_detach_client,
+};
static struct i2c_driver f75375_driver = {
.driver = {
.name = "f75375",
},
- .attach_adapter = f75375_attach_adapter,
- .detach_client = f75375_detach_client,
+ .probe = f75375_probe,
+ .remove = f75375_remove,
};
static inline int f75375_read8(struct i2c_client *client, u8 reg)
@@ -276,19 +287,14 @@
return sprintf(buf, "%d\n", data->pwm_enable[nr]);
}
-static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
{
- int nr = to_sensor_dev_attr(attr)->index;
- struct i2c_client *client = to_i2c_client(dev);
struct f75375_data *data = i2c_get_clientdata(client);
- int val = simple_strtoul(buf, NULL, 10);
u8 fanmode;
if (val < 0 || val > 4)
return -EINVAL;
- mutex_lock(&data->update_lock);
fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
fanmode = ~(3 << FAN_CTRL_MODE(nr));
@@ -310,8 +316,22 @@
}
f75375_write8(client, F75375_REG_FAN_TIMER, fanmode);
data->pwm_enable[nr] = val;
+ return 0;
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct f75375_data *data = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ int err = 0;
+
+ mutex_lock(&data->update_lock);
+ err = set_pwm_enable_direct(client, nr, val);
mutex_unlock(&data->update_lock);
- return count;
+ return err ? err : count;
}
static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
@@ -323,7 +343,7 @@
int val = simple_strtoul(buf, NULL, 10);
u8 conf = 0;
- if (val != 0 || val != 1 || data->kind == f75373)
+ if (!(val == 0 || val == 1))
return -EINVAL;
mutex_lock(&data->update_lock);
@@ -529,13 +549,13 @@
show_pwm, set_pwm, 0);
static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR,
show_pwm_enable, set_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO,
show_pwm_mode, set_pwm_mode, 0);
static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR,
show_pwm, set_pwm, 1);
static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR,
show_pwm_enable, set_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO,
show_pwm_mode, set_pwm_mode, 1);
static struct attribute *f75375_attributes[] = {
@@ -580,12 +600,9 @@
static int f75375_detach_client(struct i2c_client *client)
{
- struct f75375_data *data = i2c_get_clientdata(client);
int err;
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &f75375_group);
-
+ f75375_remove(client);
err = i2c_detach_client(client);
if (err) {
dev_err(&client->dev,
@@ -593,7 +610,91 @@
"client not detached.\n");
return err;
}
+ kfree(client);
+ return 0;
+}
+
+static void f75375_init(struct i2c_client *client, struct f75375_data *data,
+ struct f75375s_platform_data *f75375s_pdata)
+{
+ int nr;
+ set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]);
+ set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]);
+ for (nr = 0; nr < 2; nr++) {
+ data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255);
+ f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr),
+ data->pwm[nr]);
+ }
+
+}
+
+static int f75375_probe(struct i2c_client *client)
+{
+ struct f75375_data *data = i2c_get_clientdata(client);
+ struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+ if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ data->client = client;
+ mutex_init(&data->update_lock);
+
+ if (strcmp(client->name, "f75375") == 0)
+ data->kind = f75375;
+ else if (strcmp(client->name, "f75373") == 0)
+ data->kind = f75373;
+ else {
+ dev_err(&client->dev, "Unsupported device: %s\n", client->name);
+ return -ENODEV;
+ }
+
+ if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+ goto exit_free;
+
+ if (data->kind == f75375) {
+ err = sysfs_chmod_file(&client->dev.kobj,
+ &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+ S_IRUGO | S_IWUSR);
+ if (err)
+ goto exit_remove;
+ err = sysfs_chmod_file(&client->dev.kobj,
+ &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+ S_IRUGO | S_IWUSR);
+ if (err)
+ goto exit_remove;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ if (f75375s_pdata != NULL)
+ f75375_init(client, data, f75375s_pdata);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &f75375_group);
+exit_free:
kfree(data);
+ i2c_set_clientdata(client, NULL);
+ return err;
+}
+
+static int f75375_remove(struct i2c_client *client)
+{
+ struct f75375_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &f75375_group);
+ kfree(data);
+ i2c_set_clientdata(client, NULL);
return 0;
}
@@ -608,20 +709,17 @@
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
- struct f75375_data *data;
u8 version = 0;
int err = 0;
const char *name = "";
- if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) {
+ if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
- client = &data->client;
- i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
- client->driver = &f75375_driver;
+ client->driver = &f75375_legacy_driver;
if (kind < 0) {
u16 vendid = f75375_read16(client, F75375_REG_VENDOR);
@@ -644,42 +742,42 @@
} else if (kind == f75373) {
name = "f75373";
}
-
dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
strlcpy(client->name, name, I2C_NAME_SIZE);
- data->kind = kind;
- mutex_init(&data->update_lock);
+
if ((err = i2c_attach_client(client)))
goto exit_free;
- if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+ if ((err = f75375_probe(client)) < 0)
goto exit_detach;
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
return 0;
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &f75375_group);
exit_detach:
i2c_detach_client(client);
exit_free:
- kfree(data);
+ kfree(client);
exit:
return err;
}
static int __init sensors_f75375_init(void)
{
- return i2c_add_driver(&f75375_driver);
+ int status;
+ status = i2c_add_driver(&f75375_driver);
+ if (status)
+ return status;
+
+ status = i2c_add_driver(&f75375_legacy_driver);
+ if (status)
+ i2c_del_driver(&f75375_driver);
+
+ return status;
}
static void __exit sensors_f75375_exit(void)
{
+ i2c_del_driver(&f75375_legacy_driver);
i2c_del_driver(&f75375_driver);
}
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
new file mode 100644
index 0000000..6ac5c6f
--- /dev/null
+++ b/drivers/hwmon/i5k_amb.c
@@ -0,0 +1,552 @@
+/*
+ * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB
+ * temperature sensors
+ * Copyright (C) 2007 IBM
+ *
+ * Author: Darrick J. Wong <djwong@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#define DRVNAME "i5k_amb"
+
+#define I5K_REG_AMB_BASE_ADDR 0x48
+#define I5K_REG_AMB_LEN_ADDR 0x50
+#define I5K_REG_CHAN0_PRESENCE_ADDR 0x64
+#define I5K_REG_CHAN1_PRESENCE_ADDR 0x66
+
+#define AMB_REG_TEMP_MIN_ADDR 0x80
+#define AMB_REG_TEMP_MID_ADDR 0x81
+#define AMB_REG_TEMP_MAX_ADDR 0x82
+#define AMB_REG_TEMP_STATUS_ADDR 0x84
+#define AMB_REG_TEMP_ADDR 0x85
+
+#define AMB_CONFIG_SIZE 2048
+#define AMB_FUNC_3_OFFSET 768
+
+static unsigned long amb_reg_temp_status(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_min(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_mid(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_max(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp(unsigned int amb)
+{
+ return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR +
+ AMB_CONFIG_SIZE * amb;
+}
+
+#define MAX_MEM_CHANNELS 4
+#define MAX_AMBS_PER_CHANNEL 16
+#define MAX_AMBS (MAX_MEM_CHANNELS * \
+ MAX_AMBS_PER_CHANNEL)
+/*
+ * Ugly hack: For some reason the highest bit is set if there
+ * are _any_ DIMMs in the channel. Attempting to read from
+ * this "high-order" AMB results in a memory bus error, so
+ * for now we'll just ignore that top bit, even though that
+ * might prevent us from seeing the 16th DIMM in the channel.
+ */
+#define REAL_MAX_AMBS_PER_CHANNEL 15
+#define KNOBS_PER_AMB 5
+
+static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit)
+{
+ return byte_num * MAX_AMBS_PER_CHANNEL + bit;
+}
+
+#define AMB_SYSFS_NAME_LEN 16
+struct i5k_device_attribute {
+ struct sensor_device_attribute s_attr;
+ char name[AMB_SYSFS_NAME_LEN];
+};
+
+struct i5k_amb_data {
+ struct device *hwmon_dev;
+
+ unsigned long amb_base;
+ unsigned long amb_len;
+ u16 amb_present[MAX_MEM_CHANNELS];
+ void __iomem *amb_mmio;
+ struct i5k_device_attribute *attrs;
+ unsigned int num_attrs;
+};
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", DRVNAME);
+}
+
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct platform_device *amb_pdev;
+
+static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset)
+{
+ return ioread8(data->amb_mmio + offset);
+}
+
+static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset,
+ u8 val)
+{
+ iowrite8(val, data->amb_mmio + offset);
+}
+
+static ssize_t show_amb_alarm(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+
+ if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) &&
+ (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8))
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t store_amb_min(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_min(attr->index), temp);
+ return count;
+}
+
+static ssize_t store_amb_mid(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_mid(attr->index), temp);
+ return count;
+}
+
+static ssize_t store_amb_max(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+ if (temp > 255)
+ temp = 255;
+
+ amb_write_byte(data, amb_reg_temp_max(attr->index), temp);
+ return count;
+}
+
+static ssize_t show_amb_min(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_min(attr->index)));
+}
+
+static ssize_t show_amb_mid(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_mid(attr->index)));
+}
+
+static ssize_t show_amb_max(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp_max(attr->index)));
+}
+
+static ssize_t show_amb_temp(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i5k_amb_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ 500 * amb_read_byte(data, amb_reg_temp(attr->index)));
+}
+
+static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
+{
+ int i, j, k, d = 0;
+ u16 c;
+ int res = 0;
+ int num_ambs = 0;
+ struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+ /* Count the number of AMBs found */
+ /* ignore the high-order bit, see "Ugly hack" comment above */
+ for (i = 0; i < MAX_MEM_CHANNELS; i++)
+ num_ambs += hweight16(data->amb_present[i] & 0x7fff);
+
+ /* Set up sysfs stuff */
+ data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB,
+ GFP_KERNEL);
+ if (!data->attrs)
+ return -ENOMEM;
+ data->num_attrs = 0;
+
+ for (i = 0; i < MAX_MEM_CHANNELS; i++) {
+ c = data->amb_present[i];
+ for (j = 0; j < REAL_MAX_AMBS_PER_CHANNEL; j++, c >>= 1) {
+ struct i5k_device_attribute *iattr;
+
+ k = amb_num_from_reg(i, j);
+ if (!(c & 0x1))
+ continue;
+ d++;
+
+ /* Temperature sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_input", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_temp;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature min sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_min", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_min;
+ iattr->s_attr.dev_attr.store = store_amb_min;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature mid sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_mid", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_mid;
+ iattr->s_attr.dev_attr.store = store_amb_mid;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature max sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_max", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_max;
+ iattr->s_attr.dev_attr.store = store_amb_max;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+
+ /* Temperature alarm sysfs knob */
+ iattr = data->attrs + data->num_attrs;
+ snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+ "temp%d_alarm", d);
+ iattr->s_attr.dev_attr.attr.name = iattr->name;
+ iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+ iattr->s_attr.dev_attr.show = show_amb_alarm;
+ iattr->s_attr.index = k;
+ res = device_create_file(&pdev->dev,
+ &iattr->s_attr.dev_attr);
+ if (res)
+ goto exit_remove;
+ data->num_attrs++;
+ }
+ }
+
+ res = device_create_file(&pdev->dev, &dev_attr_name);
+ if (res)
+ goto exit_remove;
+
+ data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ res = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ return res;
+
+exit_remove:
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < data->num_attrs; i++)
+ device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+ kfree(data->attrs);
+
+ return res;
+}
+
+static int __devinit i5k_amb_add(void)
+{
+ int res = -ENODEV;
+
+ /* only ever going to be one of these */
+ amb_pdev = platform_device_alloc(DRVNAME, 0);
+ if (!amb_pdev)
+ return -ENOMEM;
+
+ res = platform_device_add(amb_pdev);
+ if (res)
+ goto err;
+ return 0;
+
+err:
+ platform_device_put(amb_pdev);
+ return res;
+}
+
+static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
+{
+ struct pci_dev *pcidev;
+ u32 val32;
+ int res = -ENODEV;
+
+ /* Find AMB register memory space */
+ pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5000_ERR,
+ NULL);
+ if (!pcidev)
+ return -ENODEV;
+
+ if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32))
+ goto out;
+ data->amb_base = val32;
+
+ if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32))
+ goto out;
+ data->amb_len = val32;
+
+ /* Is it big enough? */
+ if (data->amb_len < AMB_CONFIG_SIZE * MAX_AMBS) {
+ dev_err(&pcidev->dev, "AMB region too small!\n");
+ goto out;
+ }
+
+ res = 0;
+out:
+ pci_dev_put(pcidev);
+ return res;
+}
+
+static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+{
+ struct pci_dev *pcidev;
+ u16 val16;
+ int res = -ENODEV;
+
+ /* Copy the DIMM presence map for these two channels */
+ pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL);
+ if (!pcidev)
+ return -ENODEV;
+
+ if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16))
+ goto out;
+ amb_present[0] = val16;
+
+ if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16))
+ goto out;
+ amb_present[1] = val16;
+
+ res = 0;
+
+out:
+ pci_dev_put(pcidev);
+ return res;
+}
+
+static int __devinit i5k_amb_probe(struct platform_device *pdev)
+{
+ struct i5k_amb_data *data;
+ struct resource *reso;
+ int res = -ENODEV;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* Figure out where the AMB registers live */
+ res = i5k_find_amb_registers(data);
+ if (res)
+ goto err;
+
+ /* Copy the DIMM presence map for the first two channels */
+ res = i5k_channel_probe(&data->amb_present[0],
+ PCI_DEVICE_ID_INTEL_5000_FBD0);
+ if (res)
+ goto err;
+
+ /* Copy the DIMM presence map for the optional second two channels */
+ i5k_channel_probe(&data->amb_present[2],
+ PCI_DEVICE_ID_INTEL_5000_FBD1);
+
+ /* Set up resource regions */
+ reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME);
+ if (!reso) {
+ res = -EBUSY;
+ goto err;
+ }
+
+ data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len);
+ if (!data->amb_mmio) {
+ res = -EBUSY;
+ goto err_map_failed;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ res = i5k_amb_hwmon_init(pdev);
+ if (res)
+ goto err_init_failed;
+
+ return res;
+
+err_init_failed:
+ iounmap(data->amb_mmio);
+ platform_set_drvdata(pdev, NULL);
+err_map_failed:
+ release_mem_region(data->amb_base, data->amb_len);
+err:
+ kfree(data);
+ return res;
+}
+
+static int __devexit i5k_amb_remove(struct platform_device *pdev)
+{
+ int i;
+ struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ device_remove_file(&pdev->dev, &dev_attr_name);
+ for (i = 0; i < data->num_attrs; i++)
+ device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+ kfree(data->attrs);
+ iounmap(data->amb_mmio);
+ release_mem_region(data->amb_base, data->amb_len);
+ platform_set_drvdata(pdev, NULL);
+ kfree(data);
+ return 0;
+}
+
+static struct platform_driver i5k_amb_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRVNAME,
+ },
+ .probe = i5k_amb_probe,
+ .remove = __devexit_p(i5k_amb_remove),
+};
+
+static int __init i5k_amb_init(void)
+{
+ int res;
+
+ res = platform_driver_register(&i5k_amb_driver);
+ if (res)
+ return res;
+
+ res = i5k_amb_add();
+ if (res)
+ platform_driver_unregister(&i5k_amb_driver);
+
+ return res;
+}
+
+static void __exit i5k_amb_exit(void)
+{
+ platform_device_unregister(amb_pdev);
+ platform_driver_unregister(&i5k_amb_driver);
+}
+
+MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
+MODULE_DESCRIPTION("Intel 5000 chipset FB-DIMM AMB temperature sensor");
+MODULE_LICENSE("GPL");
+
+module_init(i5k_amb_init);
+module_exit(i5k_amb_exit);
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index c462824..9c9cdb0 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -140,10 +140,10 @@
return 0;
out1:
- printk(KERN_ERR "%s: request_settime=%x\n", __FUNCTION__, err);
+ dev_err(data->bmc_device, "request_settime=%x\n", err);
return err;
out:
- printk(KERN_ERR "%s: validate_addr=%x\n", __FUNCTION__, err);
+ dev_err(data->bmc_device, "validate_addr=%x\n", err);
return err;
}
@@ -161,14 +161,14 @@
data->sensor_major = data->rx_msg_data[0];
data->sensor_minor = data->rx_msg_data[1];
- printk(KERN_INFO DRVNAME ": Found BMC with sensor interface "
- "v%d.%d %d-%02d-%02d on interface %d\n",
- data->sensor_major,
- data->sensor_minor,
- extract_value(data->rx_msg_data, 2),
- data->rx_msg_data[4],
- data->rx_msg_data[5],
- data->interface);
+ dev_info(data->bmc_device, "Found BMC with sensor interface "
+ "v%d.%d %d-%02d-%02d on interface %d\n",
+ data->sensor_major,
+ data->sensor_minor,
+ extract_value(data->rx_msg_data, 2),
+ data->rx_msg_data[4],
+ data->rx_msg_data[5],
+ data->interface);
return 0;
}
@@ -212,8 +212,8 @@
wait_for_completion(&data->read_complete);
if (data->rx_result || data->rx_msg_len < 26) {
- printk(KERN_ERR "Error reading sensor %d, please check.\n",
- sensor);
+ dev_err(data->bmc_device, "Error reading sensor %d.\n",
+ sensor);
return -ENOENT;
}
@@ -456,8 +456,7 @@
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
- printk(KERN_ERR DRVNAME ": Insufficient memory for BMC "
- "interface %d.\n", data->interface);
+ dev_err(dev, "Insufficient memory for BMC interface.\n");
return;
}
@@ -471,9 +470,8 @@
err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
data, &data->user);
if (err < 0) {
- printk(KERN_ERR DRVNAME ": Error, unable to register user with "
- "ipmi interface %d\n",
- data->interface);
+ dev_err(dev, "Unable to register user with IPMI "
+ "interface %d\n", data->interface);
goto out;
}
@@ -495,9 +493,9 @@
data->hwmon_dev = hwmon_device_register(data->bmc_device);
if (IS_ERR(data->hwmon_dev)) {
- printk(KERN_ERR DRVNAME ": Error, unable to register hwmon "
- "class device for interface %d\n",
- data->interface);
+ dev_err(data->bmc_device, "Unable to register hwmon "
+ "device for IPMI interface %d\n",
+ data->interface);
goto out_user;
}
@@ -508,7 +506,7 @@
/* Now go find all the sensors */
err = ibmpex_find_sensors(data);
if (err) {
- printk(KERN_ERR "Error %d allocating memory\n", err);
+ dev_err(data->bmc_device, "Error %d finding sensors\n", err);
goto out_register;
}
@@ -561,10 +559,10 @@
struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data;
if (msg->msgid != data->tx_msgid) {
- printk(KERN_ERR "Received msgid (%02x) and transmitted "
- "msgid (%02x) mismatch!\n",
- (int)msg->msgid,
- (int)data->tx_msgid);
+ dev_err(data->bmc_device, "Mismatch between received msgid "
+ "(%02x) and transmitted msgid (%02x)!\n",
+ (int)msg->msgid,
+ (int)data->tx_msgid);
ipmi_free_recv_msg(msg);
return;
}
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index dd36688..d435f00 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -31,14 +31,15 @@
#include <linux/err.h>
#include <linux/sysfs.h>
#include <linux/hwmon.h>
+#include <linux/mutex.h>
#include <linux/spi/spi.h>
-#include <asm/semaphore.h>
+
#define DRVNAME "lm70"
struct lm70 {
struct device *hwmon_dev;
- struct semaphore sem;
+ struct mutex lock;
};
/* sysfs hook function */
@@ -51,7 +52,7 @@
s16 raw=0;
struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
- if (down_interruptible(&p_lm70->sem))
+ if (mutex_lock_interruptible(&p_lm70->lock))
return -ERESTARTSYS;
/*
@@ -83,7 +84,7 @@
val = ((int)raw/32) * 250;
status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */
out:
- up(&p_lm70->sem);
+ mutex_unlock(&p_lm70->lock);
return status;
}
@@ -112,7 +113,7 @@
if (!p_lm70)
return -ENOMEM;
- init_MUTEX(&p_lm70->sem);
+ mutex_init(&p_lm70->lock);
/* sysfs hook */
p_lm70->hwmon_dev = hwmon_device_register(&spi->dev);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 7e2d978..a276806 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -435,6 +435,22 @@
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ int nr = to_sensor_dev_attr(da)->index;
+ return sprintf(buf, "%u\n", (data->alarms >> nr) & 1);
+}
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 15);
+
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -447,22 +463,28 @@
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
&sensor_dev_attr_in0_max.dev_attr.attr,
+ &sensor_dev_attr_in0_alarm.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in1_min.dev_attr.attr,
&sensor_dev_attr_in1_max.dev_attr.attr,
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in2_min.dev_attr.attr,
&sensor_dev_attr_in2_max.dev_attr.attr,
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_in3_min.dev_attr.attr,
&sensor_dev_attr_in3_max.dev_attr.attr,
+ &sensor_dev_attr_in3_alarm.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan1_min.dev_attr.attr,
&sensor_dev_attr_fan1_div.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
&sensor_dev_attr_fan2_input.dev_attr.attr,
&sensor_dev_attr_fan2_min.dev_attr.attr,
&sensor_dev_attr_fan2_div.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
&dev_attr_alarms.attr,
&dev_attr_name.attr,
@@ -473,19 +495,28 @@
.attrs = sis5595_attributes,
};
-static struct attribute *sis5595_attributes_opt[] = {
+static struct attribute *sis5595_attributes_in4[] = {
&sensor_dev_attr_in4_input.dev_attr.attr,
&sensor_dev_attr_in4_min.dev_attr.attr,
&sensor_dev_attr_in4_max.dev_attr.attr,
-
- &dev_attr_temp1_input.attr,
- &dev_attr_temp1_max.attr,
- &dev_attr_temp1_max_hyst.attr,
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
NULL
};
-static const struct attribute_group sis5595_group_opt = {
- .attrs = sis5595_attributes_opt,
+static const struct attribute_group sis5595_group_in4 = {
+ .attrs = sis5595_attributes_in4,
+};
+
+static struct attribute *sis5595_attributes_temp1[] = {
+ &dev_attr_temp1_input.attr,
+ &dev_attr_temp1_max.attr,
+ &dev_attr_temp1_max_hyst.attr,
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group sis5595_group_temp1 = {
+ .attrs = sis5595_attributes_temp1,
};
/* This is called when the module is loaded */
@@ -540,20 +571,12 @@
if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group)))
goto exit_free;
if (data->maxins == 4) {
- if ((err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_input.dev_attr))
- || (err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_min.dev_attr))
- || (err = device_create_file(&pdev->dev,
- &sensor_dev_attr_in4_max.dev_attr)))
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &sis5595_group_in4)))
goto exit_remove_files;
} else {
- if ((err = device_create_file(&pdev->dev,
- &dev_attr_temp1_input))
- || (err = device_create_file(&pdev->dev,
- &dev_attr_temp1_max))
- || (err = device_create_file(&pdev->dev,
- &dev_attr_temp1_max_hyst)))
+ if ((err = sysfs_create_group(&pdev->dev.kobj,
+ &sis5595_group_temp1)))
goto exit_remove_files;
}
@@ -567,7 +590,8 @@
exit_remove_files:
sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
- sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
exit_free:
kfree(data);
exit_release:
@@ -582,7 +606,8 @@
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
- sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+ sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
release_region(data->addr, SIS5595_EXTENT);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 20ae425..879d0a6 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -170,20 +170,16 @@
#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \
(0x550 + (nr) - 7))
-#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
-#define W83781D_REG_FAN(nr) (0x27 + (nr))
+/* nr:0-2 for fans:1-3 */
+#define W83627HF_REG_FAN_MIN(nr) (0x3b + (nr))
+#define W83627HF_REG_FAN(nr) (0x28 + (nr))
-#define W83781D_REG_TEMP2_CONFIG 0x152
-#define W83781D_REG_TEMP3_CONFIG 0x252
-#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \
- ((nr == 2) ? (0x0150) : \
- (0x27)))
-#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \
- ((nr == 2) ? (0x153) : \
- (0x3A)))
-#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \
- ((nr == 2) ? (0x155) : \
- (0x39)))
+#define W83627HF_REG_TEMP2_CONFIG 0x152
+#define W83627HF_REG_TEMP3_CONFIG 0x252
+/* these are zero-based, unlike config constants above */
+static const u16 w83627hf_reg_temp[] = { 0x27, 0x150, 0x250 };
+static const u16 w83627hf_reg_temp_hyst[] = { 0x3A, 0x153, 0x253 };
+static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 };
#define W83781D_REG_BANK 0x4E
@@ -360,12 +356,9 @@
u8 in_min[9]; /* Register value */
u8 fan[3]; /* Register value */
u8 fan_min[3]; /* Register value */
- u8 temp;
- u8 temp_max; /* Register value */
- u8 temp_max_hyst; /* Register value */
- u16 temp_add[2]; /* Register value */
- u16 temp_max_add[2]; /* Register value */
- u16 temp_max_hyst_add[2]; /* Register value */
+ u16 temp[3]; /* Register value */
+ u16 temp_max[3]; /* Register value */
+ u16 temp_max_hyst[3]; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */
@@ -590,7 +583,7 @@
mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
- w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1),
+ w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
data->fan_min[nr]);
mutex_unlock(&data->update_lock);
@@ -611,12 +604,10 @@
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp));
- }
+
+ u16 tmp = data->temp[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -625,13 +616,10 @@
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n",
- (long)TEMP_FROM_REG(data->temp_max));
- }
+
+ u16 tmp = data->temp_max[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -640,13 +628,10 @@
{
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = w83627hf_update_device(dev);
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- return sprintf(buf, "%ld\n",
- (long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2]));
- } else { /* TEMP1 */
- return sprintf(buf, "%ld\n",
- (long)TEMP_FROM_REG(data->temp_max_hyst));
- }
+
+ u16 tmp = data->temp_max_hyst[nr];
+ return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+ : (long) TEMP_FROM_REG(tmp));
}
static ssize_t
@@ -656,18 +641,11 @@
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10);
+ u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
-
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
- data->temp_max_add[nr-2]);
- } else { /* TEMP1 */
- data->temp_max = TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
- data->temp_max);
- }
+ data->temp_max[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
@@ -679,29 +657,22 @@
int nr = to_sensor_dev_attr(devattr)->index;
struct w83627hf_data *data = dev_get_drvdata(dev);
long val = simple_strtol(buf, NULL, 10);
+ u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
mutex_lock(&data->update_lock);
-
- if (nr >= 2) { /* TEMP2 and TEMP3 */
- data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
- data->temp_max_hyst_add[nr-2]);
- } else { /* TEMP1 */
- data->temp_max_hyst = TEMP_TO_REG(val);
- w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
- data->temp_max_hyst);
- }
+ data->temp_max_hyst[nr] = tmp;
+ w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
mutex_unlock(&data->update_lock);
return count;
}
#define sysfs_temp_decl(offset) \
static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
- show_temp, NULL, offset); \
+ show_temp, NULL, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \
- show_temp_max, store_temp_max, offset); \
+ show_temp_max, store_temp_max, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \
- show_temp_max_hyst, store_temp_max_hyst, offset);
+ show_temp_max_hyst, store_temp_max_hyst, offset - 1);
sysfs_temp_decl(1);
sysfs_temp_decl(2);
@@ -844,7 +815,7 @@
/* Restore fan_min */
data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
- w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+ w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
mutex_unlock(&data->update_lock);
return count;
@@ -1170,7 +1141,7 @@
struct w83627hf_sio_data *sio_data = dev->platform_data;
struct w83627hf_data *data;
struct resource *res;
- int err;
+ int err, i;
static const char *names[] = {
"w83627hf",
@@ -1204,9 +1175,9 @@
w83627hf_init_device(pdev);
/* A few vars need to be filled upon startup */
- data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1));
- data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2));
- data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3));
+ for (i = 0; i <= 2; i++)
+ data->fan_min[i] = w83627hf_read_value(
+ data, W83627HF_REG_FAN_MIN(i));
w83627hf_update_fan_div(data);
/* Register common device attributes */
@@ -1514,23 +1485,23 @@
if(init) {
/* Enable temp2 */
- tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG);
+ tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
if (tmp & 0x01) {
dev_warn(&pdev->dev, "Enabling temp2, readings "
"might not make sense\n");
- w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG,
+ w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
tmp & 0xfe);
}
/* Enable temp3 */
if (type != w83697hf) {
tmp = w83627hf_read_value(data,
- W83781D_REG_TEMP3_CONFIG);
+ W83627HF_REG_TEMP3_CONFIG);
if (tmp & 0x01) {
dev_warn(&pdev->dev, "Enabling temp3, "
"readings might not make sense\n");
w83627hf_write_value(data,
- W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+ W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
}
}
}
@@ -1563,7 +1534,7 @@
static struct w83627hf_data *w83627hf_update_device(struct device *dev)
{
struct w83627hf_data *data = dev_get_drvdata(dev);
- int i;
+ int i, num_temps = (data->type == w83697hf) ? 2 : 3;
mutex_lock(&data->update_lock);
@@ -1584,12 +1555,12 @@
w83627hf_read_value(data,
W83781D_REG_IN_MAX(i));
}
- for (i = 1; i <= 3; i++) {
- data->fan[i - 1] =
- w83627hf_read_value(data, W83781D_REG_FAN(i));
- data->fan_min[i - 1] =
+ for (i = 0; i <= 2; i++) {
+ data->fan[i] =
+ w83627hf_read_value(data, W83627HF_REG_FAN(i));
+ data->fan_min[i] =
w83627hf_read_value(data,
- W83781D_REG_FAN_MIN(i));
+ W83627HF_REG_FAN_MIN(i));
}
for (i = 0; i <= 2; i++) {
u8 tmp = w83627hf_read_value(data,
@@ -1616,25 +1587,13 @@
break;
}
}
-
- data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
- data->temp_max =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1));
- data->temp_max_hyst =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1));
- data->temp_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP(2));
- data->temp_max_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2));
- data->temp_max_hyst_add[0] =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2));
- if (data->type != w83697hf) {
- data->temp_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP(3));
- data->temp_max_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3));
- data->temp_max_hyst_add[1] =
- w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3));
+ for (i = 0; i < num_temps; i++) {
+ data->temp[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp[i]);
+ data->temp_max[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_over[i]);
+ data->temp_max_hyst[i] = w83627hf_read_value(
+ data, w83627hf_reg_temp_hyst[i]);
}
w83627hf_update_fan_div(data);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index a6a1edf..e0fa752 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1122,12 +1122,13 @@
&sensor_dev_attr_temp3_beep.dev_attr)))
return err;
- if (kind != w83781d)
+ if (kind != w83781d) {
err = sysfs_chmod_file(&dev->kobj,
&sensor_dev_attr_temp3_alarm.dev_attr.attr,
S_IRUGO | S_IWUSR);
if (err)
return err;
+ }
}
if (kind != w83781d && kind != as99127f) {
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index d1e8df1..e445fe6 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -203,10 +203,6 @@
CD-ROM drive, you can say N to all other CD-ROM options, but be sure
to say Y or M to "ISO 9660 CD-ROM file system support".
- Note that older versions of LILO (LInux LOader) cannot properly deal
- with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from
- <http://lilo.go.dyndns.org/>.
-
To compile this driver as a module, choose M here: the
module will be called ide-cd.
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index e196aef..7f5bc2e 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -748,8 +748,7 @@
hold = ATA_DMA2_HOLD;
break;
default:
- BUG();
- break;
+ return;
}
if (speed >= XFER_UDMA_0)
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 7550118..db22d1f 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -885,7 +885,6 @@
return do_rw_taskfile(drive, args);
} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
u8 *args = rq->buffer;
- u8 sel;
if (!args)
goto done;
@@ -903,10 +902,7 @@
hwif->OUTB(args[3], IDE_SECTOR_REG);
hwif->OUTB(args[4], IDE_LCYL_REG);
hwif->OUTB(args[5], IDE_HCYL_REG);
- sel = (args[6] & ~0x10);
- if (drive->select.b.unit)
- sel |= 0x10;
- hwif->OUTB(sel, IDE_SELECT_REG);
+ hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG);
ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
return ide_started;
} else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index af86433b..1609b86 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -514,6 +514,7 @@
if (drive->addressing == 1) {
__u64 sectors = 0;
u32 low = 0, high = 0;
+ hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
low = ide_read_24(drive);
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
high = ide_read_24(drive);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index ea0143e..51fca44 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007
+ * linux/drivers/ide/pci/cmd64x.c Version 1.51 Nov 8, 2007
*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
@@ -339,7 +339,8 @@
u8 mrdmode = inb(hwif->dma_master + 0x01);
/* clear the interrupt bit */
- outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
+ outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
+ hwif->dma_master + 0x01);
return err;
}
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 5994089..5476903 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -117,8 +117,7 @@
case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break;
default:
- BUG();
- break;
+ return;
}
basereg = CS5530_BASEREG(drive->hwif);
reg = inl(basereg + 4); /* get drive0 config register */
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 5c99754..99b7d76 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -653,8 +653,7 @@
static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
- return 0;
+ return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]);
}
static const struct pci_device_id it821x_pci_tbl[] = {
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index bdf64d9..0083eaf 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -139,8 +139,7 @@
static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_setup_pci_device(dev, &jmicron_chipset);
- return 0;
+ return ide_setup_pci_device(dev, &jmicron_chipset);
}
/* All JMB PATA controllers have and will continue to have the same
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 0a7b320..707d5ff 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -186,8 +186,7 @@
}
break;
default:
- BUG();
- break;
+ return;
}
if (unit == 0) { /* are we configuring drive0? */
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 6b7bb53..f6e2ab3 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -356,7 +356,6 @@
sis_program_timings(drive, speed);
break;
default:
- BUG();
break;
}
}
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 816b531..5afdfef 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1138,6 +1138,7 @@
hwif->drives[0].autotune = IDE_TUNE_AUTO;
hwif->drives[1].autotune = IDE_TUNE_AUTO;
hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+ IDE_HFLAG_PIO_NO_DOWNGRADE |
IDE_HFLAG_POST_SET_MODE;
hwif->pio_mask = ATA_PIO4;
hwif->set_pio_mode = pmac_ide_set_pio_mode;
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 02d14bf..25fd090 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -7,11 +7,6 @@
* May be copied or modified under the terms of the GNU General Public License
*/
-/*
- * This module provides support for automatic detection and
- * configuration of all PCI IDE interfaces present in a system.
- */
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index f0c7775..b5436ca 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1000,6 +1000,7 @@
props->max_sge = dev->attr.max_sge_per_wr;
props->max_sge_rd = 1;
props->max_qp_rd_atom = dev->attr.max_rdma_reads_per_qp;
+ props->max_qp_init_rd_atom = dev->attr.max_rdma_reads_per_qp;
props->max_cq = dev->attr.max_cqs;
props->max_cqe = dev->attr.max_cqes_per_cq;
props->max_mr = dev->attr.max_mem_regs;
diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
index 97d1086..453eb99 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -50,6 +50,38 @@
static struct kmem_cache *av_cache;
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd)
+{
+ int path = ib_rate_to_mult(path_rate);
+ int link, ret;
+ struct ib_port_attr pa;
+
+ if (path_rate == IB_RATE_PORT_CURRENT) {
+ *ipd = 0;
+ return 0;
+ }
+
+ if (unlikely(path < 0)) {
+ ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x",
+ path_rate);
+ return -EINVAL;
+ }
+
+ ret = ehca_query_port(&shca->ib_device, port, &pa);
+ if (unlikely(ret < 0)) {
+ ehca_err(&shca->ib_device, "Failed to query port ret=%i", ret);
+ return ret;
+ }
+
+ link = ib_width_enum_to_int(pa.active_width) * pa.active_speed;
+
+ /* IPD = round((link / path) - 1) */
+ *ipd = ((link + (path >> 1)) / path) - 1;
+
+ return 0;
+}
+
struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
{
int ret;
@@ -69,15 +101,13 @@
av->av.slid_path_bits = ah_attr->src_path_bits;
if (ehca_static_rate < 0) {
- int ah_mult = ib_rate_to_mult(ah_attr->static_rate);
- int ehca_mult =
- ib_rate_to_mult(shca->sport[ah_attr->port_num].rate );
-
- if (ah_mult >= ehca_mult)
- av->av.ipd = 0;
- else
- av->av.ipd = (ah_mult > 0) ?
- ((ehca_mult - 1) / ah_mult) : 0;
+ u32 ipd;
+ if (ehca_calc_ipd(shca, ah_attr->port_num,
+ ah_attr->static_rate, &ipd)) {
+ ret = -EINVAL;
+ goto create_ah_exit1;
+ }
+ av->av.ipd = ipd;
} else
av->av.ipd = ehca_static_rate;
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 2d660ae..87f12d4 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -95,7 +95,6 @@
struct ehca_sport {
struct ib_cq *ibcq_aqp1;
struct ib_qp *ibqp_aqp1;
- enum ib_rate rate;
enum ib_port_state port_state;
struct ehca_sma_attr saved_attr;
};
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index 15806d1..5bd7b59 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -151,7 +151,6 @@
}
memset(props, 0, sizeof(struct ib_port_attr));
- props->state = rblock->state;
switch (rblock->max_mtu) {
case 0x1:
@@ -188,11 +187,20 @@
props->subnet_timeout = rblock->subnet_timeout;
props->init_type_reply = rblock->init_type_reply;
- props->active_width = IB_WIDTH_12X;
- props->active_speed = 0x1;
-
- /* at the moment (logical) link state is always LINK_UP */
- props->phys_state = 0x5;
+ if (rblock->state && rblock->phys_width) {
+ props->phys_state = rblock->phys_pstate;
+ props->state = rblock->phys_state;
+ props->active_width = rblock->phys_width;
+ props->active_speed = rblock->phys_speed;
+ } else {
+ /* old firmware releases don't report physical
+ * port info, so use default values
+ */
+ props->phys_state = 5;
+ props->state = rblock->state;
+ props->active_width = IB_WIDTH_12X;
+ props->active_speed = 0x1;
+ }
query_port1:
ehca_free_fw_ctrlblock(rblock);
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index dce503b..5485799 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -189,6 +189,9 @@
void ehca_poll_eqs(unsigned long data);
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+ enum ib_rate path_rate, u32 *ipd);
+
#ifdef CONFIG_PPC_64K_PAGES
void *ehca_alloc_fw_ctrlblock(gfp_t flags);
void ehca_free_fw_ctrlblock(void *ptr);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c6cd38c..90d4334 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -327,9 +327,6 @@
shca->hw_level = ehca_hw_level;
ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
- shca->sport[0].rate = IB_RATE_30_GBPS;
- shca->sport[1].rate = IB_RATE_30_GBPS;
-
shca->hca_cap = rblock->hca_cap_indicators;
ehca_gen_dbg(" ... HCA capabilities:");
for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index de18264..2e3e654 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -1196,10 +1196,6 @@
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1);
}
if (attr_mask & IB_QP_AV) {
- int ah_mult = ib_rate_to_mult(attr->ah_attr.static_rate);
- int ehca_mult = ib_rate_to_mult(shca->sport[my_qp->
- init_attr.port_num].rate);
-
mqpcb->dlid = attr->ah_attr.dlid;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1);
mqpcb->source_path_bits = attr->ah_attr.src_path_bits;
@@ -1207,11 +1203,12 @@
mqpcb->service_level = attr->ah_attr.sl;
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1);
- if (ah_mult < ehca_mult)
- mqpcb->max_static_rate = (ah_mult > 0) ?
- ((ehca_mult - 1) / ah_mult) : 0;
- else
- mqpcb->max_static_rate = 0;
+ if (ehca_calc_ipd(shca, my_qp->init_attr.port_num,
+ attr->ah_attr.static_rate,
+ &mqpcb->max_static_rate)) {
+ ret = -EINVAL;
+ goto modify_qp_exit2;
+ }
update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1);
/*
@@ -1280,10 +1277,6 @@
(MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1);
}
if (attr_mask & IB_QP_ALT_PATH) {
- int ah_mult = ib_rate_to_mult(attr->alt_ah_attr.static_rate);
- int ehca_mult = ib_rate_to_mult(
- shca->sport[my_qp->init_attr.port_num].rate);
-
if (attr->alt_port_num < 1
|| attr->alt_port_num > shca->num_ports) {
ret = -EINVAL;
@@ -1309,10 +1302,12 @@
mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;
mqpcb->service_level_al = attr->alt_ah_attr.sl;
- if (ah_mult > 0 && ah_mult < ehca_mult)
- mqpcb->max_static_rate_al = (ehca_mult - 1) / ah_mult;
- else
- mqpcb->max_static_rate_al = 0;
+ if (ehca_calc_ipd(shca, my_qp->init_attr.port_num,
+ attr->alt_ah_attr.static_rate,
+ &mqpcb->max_static_rate_al)) {
+ ret = -EINVAL;
+ goto modify_qp_exit2;
+ }
/* OpenIB doesn't support alternate retry counts - copy them */
mqpcb->retry_count_al = mqpcb->retry_count;
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
index d9739e5..485b840 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -402,7 +402,11 @@
u64 max_msg_sz;
u32 max_mtu;
u32 vl_cap;
- u8 reserved2[1900];
+ u32 phys_pstate;
+ u32 phys_state;
+ u32 phys_speed;
+ u32 phys_width;
+ u8 reserved2[1884];
u64 guid_entries[255];
} __attribute__ ((packed));
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
index 645ed71..08d8ae1 100644
--- a/drivers/infiniband/hw/ipath/ipath_cq.c
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -404,7 +404,7 @@
ret = ib_copy_to_udata(udata, &offset, sizeof(offset));
if (ret)
- goto bail;
+ goto bail_free;
}
spin_lock_irq(&cq->lock);
@@ -424,10 +424,8 @@
else
n = head - tail;
if (unlikely((u32)cqe < n)) {
- spin_unlock_irq(&cq->lock);
- vfree(wc);
ret = -EOVERFLOW;
- goto bail;
+ goto bail_unlock;
}
for (n = 0; tail != head; n++) {
if (cq->ip)
@@ -459,7 +457,12 @@
}
ret = 0;
+ goto bail;
+bail_unlock:
+ spin_unlock_irq(&cq->lock);
+bail_free:
+ vfree(wc);
bail:
return ret;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index 5c29b2b..120a61b0 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -959,8 +959,9 @@
/* If this is a partial ACK, reset the retransmit timer. */
if (qp->s_last != qp->s_tail) {
spin_lock(&dev->pending_lock);
- list_add_tail(&qp->timerwait,
- &dev->pending[dev->pending_index]);
+ if (list_empty(&qp->timerwait))
+ list_add_tail(&qp->timerwait,
+ &dev->pending[dev->pending_index]);
spin_unlock(&dev->pending_lock);
/*
* If we get a partial ACK for a resent operation,
diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h
index 5992f63..0120bcf 100644
--- a/drivers/isdn/sc/card.h
+++ b/drivers/isdn/sc/card.h
@@ -109,7 +109,7 @@
int get_card_from_id(int driver);
int indicate_status(int card, int event, ulong Channel, char *Data);
irqreturn_t interrupt_handler(int interrupt, void *cardptr);
-int sndpkt(int devId, int channel, struct sk_buff *data);
+int sndpkt(int devId, int channel, int ack, struct sk_buff *data);
void rcvpkt(int card, RspMessage *rcvmsg);
int command(isdn_ctrl *cmd);
int reset(int card);
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index 92016a2..5ff6ae8 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -20,7 +20,7 @@
#include "message.h"
#include "card.h"
-int sndpkt(int devId, int channel, struct sk_buff *data)
+int sndpkt(int devId, int channel, int ack, struct sk_buff *data)
{
LLData ReqLnkWrite;
int status;
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index e0331e0..712220c 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -50,7 +50,7 @@
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
- memcpy_toio(sc_adapter[card]->rambase + dest_rem, src, n);
+ memcpy_toio((void __iomem *)(sc_adapter[card]->rambase + dest_rem), src, n);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 729f1cd..7a6eead 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -494,6 +494,7 @@
*/
/* (1ULL << INTERCEPT_SELECTIVE_CR0) | */
(1ULL << INTERCEPT_CPUID) |
+ (1ULL << INTERCEPT_INVD) |
(1ULL << INTERCEPT_HLT) |
(1ULL << INTERCEPT_INVLPGA) |
(1ULL << INTERCEPT_IOIO_PROT) |
@@ -507,6 +508,7 @@
(1ULL << INTERCEPT_STGI) |
(1ULL << INTERCEPT_CLGI) |
(1ULL << INTERCEPT_SKINIT) |
+ (1ULL << INTERCEPT_WBINVD) |
(1ULL << INTERCEPT_MONITOR) |
(1ULL << INTERCEPT_MWAIT);
@@ -561,6 +563,12 @@
struct vcpu_svm *svm = to_svm(vcpu);
init_vmcb(svm->vmcb);
+
+ if (vcpu->vcpu_id != 0) {
+ svm->vmcb->save.rip = 0;
+ svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12;
+ svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8;
+ }
}
static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
@@ -1241,6 +1249,7 @@
[SVM_EXIT_VINTR] = interrupt_window_interception,
/* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */
[SVM_EXIT_CPUID] = cpuid_interception,
+ [SVM_EXIT_INVD] = emulate_on_interception,
[SVM_EXIT_HLT] = halt_interception,
[SVM_EXIT_INVLPG] = emulate_on_interception,
[SVM_EXIT_INVLPGA] = invalid_op_interception,
@@ -1255,6 +1264,7 @@
[SVM_EXIT_STGI] = invalid_op_interception,
[SVM_EXIT_CLGI] = invalid_op_interception,
[SVM_EXIT_SKINIT] = invalid_op_interception,
+ [SVM_EXIT_WBINVD] = emulate_on_interception,
[SVM_EXIT_MONITOR] = invalid_op_interception,
[SVM_EXIT_MWAIT] = invalid_op_interception,
};
@@ -1579,10 +1589,6 @@
#endif
: "cc", "memory" );
- local_irq_disable();
-
- stgi();
-
if ((svm->vmcb->save.dr7 & 0xff))
load_db_regs(svm->host_db_regs);
@@ -1599,6 +1605,10 @@
reload_tss(vcpu);
+ local_irq_disable();
+
+ stgi();
+
svm->next_rip = 0;
}
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index a6ace30..33b1814 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -167,7 +167,7 @@
static u16 twobyte_table[256] = {
/* 0x00 - 0x0F */
0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0,
- 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+ ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
/* 0x10 - 0x1F */
0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 - 0x2F */
@@ -980,17 +980,6 @@
goto cannot_emulate;
dst.val = (s32) src.val;
break;
- case 0x6a: /* push imm8 */
- src.val = 0L;
- src.val = insn_fetch(s8, 1, _eip);
-push:
- dst.type = OP_MEM;
- dst.bytes = op_bytes;
- dst.val = src.val;
- register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
- dst.ptr = (void *) register_address(ctxt->ss_base,
- _regs[VCPU_REGS_RSP]);
- break;
case 0x80 ... 0x83: /* Grp1 */
switch (modrm_reg) {
case 0:
@@ -1243,6 +1232,17 @@
register_address_increment(_regs[VCPU_REGS_RSP], op_bytes);
no_wb = 1; /* Disable writeback. */
break;
+ case 0x6a: /* push imm8 */
+ src.val = 0L;
+ src.val = insn_fetch(s8, 1, _eip);
+ push:
+ dst.type = OP_MEM;
+ dst.bytes = op_bytes;
+ dst.val = src.val;
+ register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes);
+ dst.ptr = (void *) register_address(ctxt->ss_base,
+ _regs[VCPU_REGS_RSP]);
+ break;
case 0x6c: /* insb */
case 0x6d: /* insw/insd */
if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
@@ -1532,6 +1532,8 @@
case 0x06:
emulate_clts(ctxt->vcpu);
break;
+ case 0x08: /* invd */
+ break;
case 0x09: /* wbinvd */
break;
case 0x0d: /* GrpP (prefetch) */
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 8904f72..66f3872 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -200,7 +200,8 @@
/* Figure out how many pages the ring will take, and map that memory */
lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT,
- DIV_ROUND_UP(vring_size(lvq->config.num),
+ DIV_ROUND_UP(vring_size(lvq->config.num,
+ PAGE_SIZE),
PAGE_SIZE));
if (!lvq->pages) {
err = -ENOMEM;
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 9d716fa..3b92a61 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -184,7 +184,7 @@
free_regs:
free_page(lg->regs_page);
release_guest:
- memset(lg, 0, sizeof(*lg));
+ kfree(lg);
unlock:
mutex_unlock(&lguest_lock);
return err;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 1cfc984..a5aad8c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -688,7 +688,8 @@
}
static struct dma_async_tx_descriptor *
-ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ unsigned long pending)
{
int disks = sh->disks;
int pd_idx = sh->pd_idx, i;
@@ -696,7 +697,7 @@
/* check if prexor is active which means only process blocks
* that are part of a read-modify-write (Wantprexor)
*/
- int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
pr_debug("%s: stripe %llu\n", __FUNCTION__,
(unsigned long long)sh->sector);
@@ -773,7 +774,8 @@
}
static void
-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+ unsigned long pending)
{
/* kernel stack size limits the total number of disks */
int disks = sh->disks;
@@ -781,7 +783,7 @@
int count = 0, pd_idx = sh->pd_idx, i;
struct page *xor_dest;
- int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
unsigned long flags;
dma_async_tx_callback callback;
@@ -808,7 +810,7 @@
}
/* check whether this postxor is part of a write */
- callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+ callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ?
ops_complete_write : ops_complete_postxor;
/* 1/ if we prexor'd then the dest is reused as a source
@@ -896,12 +898,12 @@
tx = ops_run_prexor(sh, tx);
if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
- tx = ops_run_biodrain(sh, tx);
+ tx = ops_run_biodrain(sh, tx, pending);
overlap_clear++;
}
if (test_bit(STRIPE_OP_POSTXOR, &pending))
- ops_run_postxor(sh, tx);
+ ops_run_postxor(sh, tx, pending);
if (test_bit(STRIPE_OP_CHECK, &pending))
ops_run_check(sh);
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 6a5a05d..05172d2 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -244,10 +244,11 @@
idd->idd_pdev->bus->number == pdev->bus->number &&
3 == PCI_SLOT(pdev->devfn))
found = 1;
- pci_dev_put(pdev);
} while (pdev && !found);
- if (NULL != pdev)
+ if (NULL != pdev) {
+ pci_dev_put(pdev);
return IOC4_VARIANT_IO9;
+ }
/* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
pdev = NULL;
@@ -258,10 +259,11 @@
idd->idd_pdev->bus->number == pdev->bus->number &&
3 == PCI_SLOT(pdev->devfn))
found = 1;
- pci_dev_put(pdev);
} while (pdev && !found);
- if (NULL != pdev)
+ if (NULL != pdev) {
+ pci_dev_put(pdev);
return IOC4_VARIANT_IO10;
+ }
/* PCI-RT: No SCSI/SATA controller will be present */
return IOC4_VARIANT_PCI_RT;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index bf8890e..e8d69b0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -366,8 +366,7 @@
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. This module will
+ To compile this driver as a module, choose M here. This module will
be called mac89x0.
config MACSONIC
@@ -380,8 +379,7 @@
one of these say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. This module will
+ To compile this driver as a module, choose M here. This module will
be called macsonic.
config MACMACE
@@ -619,8 +617,7 @@
have problems. Some people suggest to ping ("man ping") a nearby
machine every minute ("man cron") when using this card.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c501.
config EL2
@@ -632,8 +629,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c503.
config ELPLUS
@@ -645,8 +641,7 @@
this type, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c505.
config EL16
@@ -657,8 +652,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c507.
config EL3
@@ -673,8 +667,7 @@
setup disk to disable Plug & Play mode, and to select the default
media type.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c509.
config 3C515
@@ -685,8 +678,7 @@
network card, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c515.
config ELMC
@@ -697,8 +689,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c523.
config ELMC_II
@@ -709,8 +700,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called 3c527.
config VORTEX
@@ -733,8 +723,7 @@
<file:Documentation/networking/vortex.txt> and in the comments at
the beginning of <file:drivers/net/3c59x.c>.
- To compile this support as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>.
+ To compile this support as a module, choose M here.
config TYPHOON
tristate "3cr990 series \"Typhoon\" support"
@@ -751,8 +740,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called typhoon.
config LANCE
@@ -789,8 +777,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called wd.
config ULTRAMCA
@@ -802,8 +789,7 @@
an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
available from <http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-mca.
config ULTRA
@@ -822,8 +808,7 @@
this but keep it in mind if you have such a SCSI card and have
problems.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-ultra.
config ULTRA32
@@ -835,8 +820,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc-ultra32.
config BFIN_MAC
@@ -897,8 +881,7 @@
<file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
available from <http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called smc9194.
config SMC91X
@@ -916,8 +899,7 @@
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called smc91x. If you want to compile it as a
- module, say M here and read <file:Documentation/kbuild/modules.txt>
- as well as <file:Documentation/networking/net-modules.txt>.
+ module, say M here and read <file:Documentation/kbuild/modules.txt>.
config NET_NETX
tristate "NetX Ethernet support"
@@ -926,8 +908,7 @@
help
This is support for the Hilscher netX builtin Ethernet ports
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called netx-eth.
config DM9000
@@ -938,9 +919,8 @@
---help---
Support for DM9000 chipset.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called dm9000.
+ To compile this driver as a module, choose M here. The module
+ will be called dm9000.
config SMC911X
tristate "SMSC LAN911[5678] support"
@@ -980,8 +960,7 @@
<http://www.tldp.org/docs.html#howto>. Note that this is still
experimental code.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni5010.
config NI52
@@ -992,8 +971,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni52.
config NI65
@@ -1004,8 +982,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ni65.
source "drivers/net/tulip/Kconfig"
@@ -1019,8 +996,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called at1700.
config DEPCA
@@ -1033,8 +1009,7 @@
<http://www.tldp.org/docs.html#howto> as well as
<file:drivers/net/depca.c>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called depca.
config HP100
@@ -1045,8 +1020,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp100.
config NET_ISA
@@ -1075,8 +1049,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e2100.
config EWRK3
@@ -1090,8 +1063,7 @@
well as the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ewrk3.
config EEXPRESS
@@ -1105,8 +1077,7 @@
because the driver was very unreliable. We now have a new driver
that should do better.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eexpress.
config EEXPRESS_PRO
@@ -1119,8 +1090,7 @@
driver. Please read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eepro.
config HPLAN_PLUS
@@ -1132,8 +1102,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp-plus.
config HPLAN
@@ -1145,8 +1114,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called hp.
config LP486E
@@ -1165,8 +1133,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eth16i.
config NE2000
@@ -1186,8 +1153,7 @@
laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
below.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne.
config ZNET
@@ -1208,8 +1174,7 @@
is for you, read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called seeq8005.
config NE2_MCA
@@ -1221,8 +1186,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne2.
config IBMLANA
@@ -1233,8 +1197,7 @@
CONFIG_MCA to use this driver. It is both available as an in-kernel
driver and as a module.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The only
+ To compile this driver as a module, choose M here. The only
currently supported card is the IBM LAN Adapter/A for Ethernet. It
will both support 16K and 32K memory windows, however a 32K window
gives a better security against packet losses. Usage of multiple
@@ -1248,8 +1211,7 @@
This driver supports virtual ethernet adapters on newer IBM iSeries
and pSeries systems.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called ibmveth.
source "drivers/net/ibm_emac/Kconfig"
@@ -1279,8 +1241,7 @@
answer Y here and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called pcnet32.
config PCNET32_NAPI
@@ -1307,8 +1268,7 @@
answer Y here and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called amd8111e.
config AMD8111E_NAPI
@@ -1362,8 +1322,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ac3200.
config APRICOT
@@ -1374,9 +1333,8 @@
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called apricot.
+ To compile this driver as a module, choose M here. The module
+ will be called apricot.
config B44
tristate "Broadcom 440x/47xx ethernet support"
@@ -1388,9 +1346,8 @@
or M and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called b44.
+ To compile this driver as a module, choose M here. The module
+ will be called b44.
# Auto-select SSB PCI-HOST support, if possible
config B44_PCI_AUTOSELECT
@@ -1419,9 +1376,8 @@
read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called forcedeth.
+ To compile this driver as a module, choose M here. The module
+ will be called forcedeth.
config FORCEDETH_NAPI
bool "Use Rx Polling (NAPI) (EXPERIMENTAL)"
@@ -1447,9 +1403,8 @@
<http://www.tldp.org/docs.html#howto> as well as
<file:Documentation/networking/cs89x0.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called cs89x0.
+ To compile this driver as a module, choose M here. The module
+ will be called cs89x0.
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
@@ -1465,8 +1420,7 @@
card, say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called eepro100.
@@ -1493,8 +1447,7 @@
More specific information on configuring the driver is in
<file:Documentation/networking/e100.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e100.
config LNE390
@@ -1506,8 +1459,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called lne390.
config FEALNX
@@ -1547,8 +1499,7 @@
NetVin NV5000SC Via 86C926 SureCom NE34 Winbond
Holtek HT80232 Holtek HT80229
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne2k-pci.
config NE3210
@@ -1561,8 +1512,7 @@
<http://www.tldp.org/docs.html#howto>. Note that this driver
will NOT WORK for NE3200 cards as they are completely different.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ne3210.
config ES3210
@@ -1574,8 +1524,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called es3210.
config 8139CP
@@ -1705,8 +1654,7 @@
Compaq NetFlex and Olicom cards. Please read the file
<file:Documentation/networking/tlan.txt> for more details.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called tlan.
Please email feedback to <torben.mathiasen@compaq.com>.
@@ -1996,8 +1944,7 @@
More specific information on configuring the driver is in
<file:Documentation/networking/e1000.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e1000.
config E1000_NAPI
@@ -2042,8 +1989,7 @@
More specific information on configuring the driver is in
<file:Documentation/networking/e1000e.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called e1000e.
source "drivers/net/ixp2000/Kconfig"
@@ -2076,8 +2022,7 @@
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
+ To compile this driver as a module, choose M here. The module will be
called hamachi.
config YELLOWFIN
@@ -2526,8 +2471,7 @@
More specific information on configuring the driver is in
<file:Documentation/networking/ixgbe.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ixgbe.
config IXGB
@@ -2549,8 +2493,7 @@
More specific information on configuring the driver is in
<file:Documentation/networking/ixgb.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called ixgb.
config IXGB_NAPI
@@ -2603,8 +2546,7 @@
<http://www.myri.com/scs/download-Myri10GE.html>
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
+ To compile this driver as a module, choose M here. The module
will be called myri10ge.
config NETXEN_NIC
@@ -2828,10 +2770,9 @@
with the PLIP support in Linux versions 1.0.x. This option enlarges
your kernel by about 8 KB.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called plip. If unsure, say Y or M, in case you buy a laptop
- later.
+ To compile this driver as a module, choose M here. The module
+ will be called plip. If unsure, say Y or M, in case you buy
+ a laptop later.
config PPP
tristate "PPP (point-to-point protocol) support"
@@ -2861,8 +2802,7 @@
If you said Y to "Version information on all symbols" above, then
you cannot compile the PPP driver into the kernel; you can then only
compile it as a module. To compile this driver as a module, choose M
- here and read <file:Documentation/networking/net-modules.txt>.
- The module will be called ppp_generic.
+ here. The module will be called ppp_generic.
config PPP_MULTILINK
bool "PPP multilink support (EXPERIMENTAL)"
@@ -3023,9 +2963,8 @@
<http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
support will enlarge your kernel by about 4 KB. If unsure, say N.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will be
- called slip.
+ To compile this driver as a module, choose M here. The module
+ will be called slip.
config SLIP_COMPRESSED
bool "CSLIP compressed headers"
diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig
index 4030274..3b2f7f1 100644
--- a/drivers/net/arcnet/Kconfig
+++ b/drivers/net/arcnet/Kconfig
@@ -19,8 +19,7 @@
from <http://www.tldp.org/docs.html#howto>(even though ARCnet
is not really Ethernet).
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called arcnet.
if ARCNET
@@ -81,8 +80,7 @@
have always used the old ARCnet driver without knowing what type of
card you had, this is probably the one for you.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com90xx.
config ARCNET_COM90xxIO
@@ -93,8 +91,7 @@
the normal driver. Only use it if your card doesn't support shared
memory.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com90io.
config ARCNET_RIM_I
@@ -105,8 +102,7 @@
driver is completely untested, so if you have one of these cards,
please mail <dwmw2@infradead.org>, especially if it works!
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called arc-rimi.
config ARCNET_COM20020
@@ -116,8 +112,7 @@
things as promiscuous mode, so packet sniffing is possible, and
extra diagnostic information.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called com20020.
config ARCNET_COM20020_ISA
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 7f016f3..91a6590 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -417,7 +417,7 @@
if (status & REG_INTSTS_RX) {
spin_lock(&ep->rx_lock);
- if (likely(__netif_rx_schedule_prep(dev, &ep->napi))) {
+ if (likely(netif_rx_schedule_prep(dev, &ep->napi))) {
wrl(ep, REG_INTEN, REG_INTEN_TX);
__netif_rx_schedule(dev, &ep->napi);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a198404..423298c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1847,9 +1847,9 @@
*/
void bond_destroy(struct bonding *bond)
{
- unregister_netdevice(bond->dev);
bond_deinit(bond->dev);
bond_destroy_sysfs_entry(bond);
+ unregister_netdevice(bond->dev);
}
/*
@@ -4475,8 +4475,8 @@
bond_mc_list_destroy(bond);
/* Release the bonded slaves */
bond_release_all(bond_dev);
- unregister_netdevice(bond_dev);
bond_deinit(bond_dev);
+ unregister_netdevice(bond_dev);
}
#ifdef CONFIG_PROC_FS
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index edd6828..917b7b4 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -250,6 +250,7 @@
#include <asm/system.h>
#include <asm/ethernet.h>
#include <asm/cache.h>
+#include <asm/arch/io_interface_mux.h>
//#define ETHDEBUG
#define D(x)
@@ -279,6 +280,9 @@
* by this lock as well.
*/
spinlock_t lock;
+
+ spinlock_t led_lock; /* Protect LED state */
+ spinlock_t transceiver_lock; /* Protect transceiver state. */
};
typedef struct etrax_eth_descr
@@ -295,8 +299,6 @@
void (*check_duplex)(struct net_device* dev);
};
-struct transceiver_ops* transceiver;
-
/* Duplex settings */
enum duplex
{
@@ -307,7 +309,7 @@
/* Dma descriptors etc. */
-#define MAX_MEDIA_DATA_SIZE 1518
+#define MAX_MEDIA_DATA_SIZE 1522
#define MIN_PACKET_LEN 46
#define ETHER_HEAD_LEN 14
@@ -332,8 +334,8 @@
/*Intel LXT972A specific*/
#define MDIO_INT_STATUS_REG_2 0x0011
-#define MDIO_INT_FULL_DUPLEX_IND ( 1 << 9 )
-#define MDIO_INT_SPEED ( 1 << 14 )
+#define MDIO_INT_FULL_DUPLEX_IND (1 << 9)
+#define MDIO_INT_SPEED (1 << 14)
/* Network flash constants */
#define NET_FLASH_TIME (HZ/50) /* 20 ms */
@@ -344,8 +346,8 @@
#define NO_NETWORK_ACTIVITY 0
#define NETWORK_ACTIVITY 1
-#define NBR_OF_RX_DESC 64
-#define NBR_OF_TX_DESC 256
+#define NBR_OF_RX_DESC 32
+#define NBR_OF_TX_DESC 16
/* Large packets are sent directly to upper layers while small packets are */
/* copied (to reduce memory waste). The following constant decides the breakpoint */
@@ -367,7 +369,6 @@
static etrax_eth_descr *myNextRxDesc; /* Points to the next descriptor to
to be processed */
static etrax_eth_descr *myLastRxDesc; /* The last processed descriptor */
-static etrax_eth_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */
static etrax_eth_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(32)));
@@ -377,7 +378,6 @@
static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32)));
static unsigned int network_rec_config_shadow = 0;
-static unsigned int mdio_phy_addr; /* Transciever address */
static unsigned int network_tr_ctrl_shadow = 0;
@@ -411,7 +411,7 @@
static void e100_tx_timeout(struct net_device *dev);
static struct net_device_stats *e100_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
-static void e100_hardware_send_packet(char *buf, int length);
+static void e100_hardware_send_packet(struct net_local* np, char *buf, int length);
static void update_rx_stats(struct net_device_stats *);
static void update_tx_stats(struct net_device_stats *);
static int e100_probe_transceiver(struct net_device* dev);
@@ -434,7 +434,10 @@
static void e100_set_network_leds(int active);
static const struct ethtool_ops e100_ethtool_ops;
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void dummy_check_speed(struct net_device* dev);
+static void dummy_check_duplex(struct net_device* dev);
+#else
static void broadcom_check_speed(struct net_device* dev);
static void broadcom_check_duplex(struct net_device* dev);
static void tdk_check_speed(struct net_device* dev);
@@ -443,16 +446,28 @@
static void intel_check_duplex(struct net_device* dev);
static void generic_check_speed(struct net_device* dev);
static void generic_check_duplex(struct net_device* dev);
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void e100_netpoll(struct net_device* dev);
+#endif
+
+static int autoneg_normal = 1;
struct transceiver_ops transceivers[] =
{
+#if defined(CONFIG_ETRAX_NO_PHY)
+ {0x0000, dummy_check_speed, dummy_check_duplex} /* Dummy */
+#else
{0x1018, broadcom_check_speed, broadcom_check_duplex}, /* Broadcom */
{0xC039, tdk_check_speed, tdk_check_duplex}, /* TDK 2120 */
{0x039C, tdk_check_speed, tdk_check_duplex}, /* TDK 2120C */
{0x04de, intel_check_speed, intel_check_duplex}, /* Intel LXT972A*/
{0x0000, generic_check_speed, generic_check_duplex} /* Generic, must be last */
+#endif
};
+struct transceiver_ops* transceiver = &transceivers[0];
+
#define tx_done(dev) (*R_DMA_CH0_CMD == 0)
/*
@@ -471,14 +486,22 @@
int i, err;
printk(KERN_INFO
- "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n");
+ "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 1998-2007 Axis Communications AB\n");
+
+ if (cris_request_io_interface(if_eth, cardname)) {
+ printk(KERN_CRIT "etrax_ethernet_init failed to get IO interface\n");
+ return -EBUSY;
+ }
dev = alloc_etherdev(sizeof(struct net_local));
- np = dev->priv;
-
if (!dev)
return -ENOMEM;
+ np = netdev_priv(dev);
+
+ /* we do our own locking */
+ dev->features |= NETIF_F_LLTX;
+
dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
/* now setup our etrax specific stuff */
@@ -498,14 +521,22 @@
dev->do_ioctl = e100_ioctl;
dev->set_config = e100_set_config;
dev->tx_timeout = e100_tx_timeout;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = e100_netpoll;
+#endif
+
+ spin_lock_init(&np->lock);
+ spin_lock_init(&np->led_lock);
+ spin_lock_init(&np->transceiver_lock);
/* Initialise the list of Etrax DMA-descriptors */
/* Initialise receive descriptors */
for (i = 0; i < NBR_OF_RX_DESC; i++) {
- /* Allocate two extra cachelines to make sure that buffer used by DMA
- * does not share cacheline with any other data (to avoid cache bug)
+ /* Allocate two extra cachelines to make sure that buffer used
+ * by DMA does not share cacheline with any other data (to
+ * avoid cache bug)
*/
RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
if (!RxDescList[i].skb)
@@ -541,7 +572,6 @@
myNextRxDesc = &RxDescList[0];
myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
- myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
myFirstTxDesc = &TxDescList[0];
myNextTxDesc = &TxDescList[0];
myLastTxDesc = &TxDescList[NBR_OF_TX_DESC - 1];
@@ -562,10 +592,11 @@
current_speed = 10;
current_speed_selection = 0; /* Auto */
speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
- duplex_timer.data = (unsigned long)dev;
+ speed_timer.data = (unsigned long)dev;
speed_timer.function = e100_check_speed;
clear_led_timer.function = e100_clear_network_leds;
+ clear_led_timer.data = (unsigned long)dev;
full_duplex = 0;
current_duplex = autoneg;
@@ -574,7 +605,6 @@
duplex_timer.function = e100_check_duplex;
/* Initialize mii interface */
- np->mii_if.phy_id = mdio_phy_addr;
np->mii_if.phy_id_mask = 0x1f;
np->mii_if.reg_num_mask = 0x1f;
np->mii_if.dev = dev;
@@ -585,6 +615,9 @@
/* unwanted addresses are matched */
*R_NETWORK_GA_0 = 0x00000000;
*R_NETWORK_GA_1 = 0x00000000;
+
+ /* Initialize next time the led can flash */
+ led_next_time = jiffies;
return 0;
}
@@ -595,9 +628,9 @@
static int
e100_set_mac_address(struct net_device *dev, void *p)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
struct sockaddr *addr = p;
- int i;
+ DECLARE_MAC_BUF(mac);
spin_lock(&np->lock); /* preemption protection */
@@ -686,6 +719,25 @@
goto grace_exit2;
}
+ /*
+ * Always allocate the DMA channels after the IRQ,
+ * and clean up on failure.
+ */
+
+ if (cris_request_dma(NETWORK_TX_DMA_NBR,
+ cardname,
+ DMA_VERBOSE_ON_ERROR,
+ dma_eth)) {
+ goto grace_exit3;
+ }
+
+ if (cris_request_dma(NETWORK_RX_DMA_NBR,
+ cardname,
+ DMA_VERBOSE_ON_ERROR,
+ dma_eth)) {
+ goto grace_exit4;
+ }
+
/* give the HW an idea of what MAC address we want */
*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |
@@ -700,6 +752,7 @@
*R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */
#else
+ SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, max_size, size1522);
SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, broadcast, receive);
SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, ma0, enable);
SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex);
@@ -719,8 +772,7 @@
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable);
*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* enable the irq's for ethernet DMA */
@@ -752,12 +804,13 @@
*R_DMA_CH0_FIRST = 0;
*R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc);
+ netif_start_queue(dev);
- restore_flags(flags);
+ local_irq_restore(flags);
/* Probe for transceiver */
if (e100_probe_transceiver(dev))
- goto grace_exit3;
+ goto grace_exit5;
/* Start duplex/speed timers */
add_timer(&speed_timer);
@@ -766,10 +819,14 @@
/* We are now ready to accept transmit requeusts from
* the queueing layer of the networking.
*/
- netif_start_queue(dev);
+ netif_carrier_on(dev);
return 0;
+grace_exit5:
+ cris_free_dma(NETWORK_RX_DMA_NBR, cardname);
+grace_exit4:
+ cris_free_dma(NETWORK_TX_DMA_NBR, cardname);
grace_exit3:
free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
grace_exit2:
@@ -780,12 +837,20 @@
return -EAGAIN;
}
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void
+dummy_check_speed(struct net_device* dev)
+{
+ current_speed = 100;
+}
+#else
static void
generic_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE);
if ((data & ADVERTISE_100FULL) ||
(data & ADVERTISE_100HALF))
current_speed = 100;
@@ -797,7 +862,10 @@
tdk_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_TDK_DIAGNOSTIC_REG);
current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10);
}
@@ -805,7 +873,10 @@
broadcom_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_AUX_CTRL_STATUS_REG);
current_speed = (data & MDIO_BC_SPEED ? 100 : 10);
}
@@ -813,46 +884,62 @@
intel_check_speed(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_INT_STATUS_REG_2);
current_speed = (data & MDIO_INT_SPEED ? 100 : 10);
}
-
+#endif
static void
e100_check_speed(unsigned long priv)
{
struct net_device* dev = (struct net_device*)priv;
+ struct net_local *np = netdev_priv(dev);
static int led_initiated = 0;
unsigned long data;
int old_speed = current_speed;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR);
+ spin_lock(&np->transceiver_lock);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMSR);
if (!(data & BMSR_LSTATUS)) {
current_speed = 0;
} else {
transceiver->check_speed(dev);
}
+ spin_lock(&np->led_lock);
if ((old_speed != current_speed) || !led_initiated) {
led_initiated = 1;
e100_set_network_leds(NO_NETWORK_ACTIVITY);
+ if (current_speed)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
}
+ spin_unlock(&np->led_lock);
/* Reinitialize the timer. */
speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
add_timer(&speed_timer);
+
+ spin_unlock(&np->transceiver_lock);
}
static void
e100_negotiate(struct net_device* dev)
{
- unsigned short data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+ unsigned short data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MII_ADVERTISE);
/* Discard old speed and duplex settings */
data &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL |
ADVERTISE_10HALF | ADVERTISE_10FULL);
switch (current_speed_selection) {
- case 10 :
+ case 10:
if (current_duplex == full)
data |= ADVERTISE_10FULL;
else if (current_duplex == half)
@@ -861,7 +948,7 @@
data |= ADVERTISE_10HALF | ADVERTISE_10FULL;
break;
- case 100 :
+ case 100:
if (current_duplex == full)
data |= ADVERTISE_100FULL;
else if (current_duplex == half)
@@ -870,7 +957,7 @@
data |= ADVERTISE_100HALF | ADVERTISE_100FULL;
break;
- case 0 : /* Auto */
+ case 0: /* Auto */
if (current_duplex == full)
data |= ADVERTISE_100FULL | ADVERTISE_10FULL;
else if (current_duplex == half)
@@ -880,35 +967,44 @@
ADVERTISE_100HALF | ADVERTISE_100FULL;
break;
- default : /* assume autoneg speed and duplex */
+ default: /* assume autoneg speed and duplex */
data |= ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL;
+ break;
}
- e100_set_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE, data);
+ e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE, data);
/* Renegotiate with link partner */
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR);
+ if (autoneg_normal) {
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR);
data |= BMCR_ANENABLE | BMCR_ANRESTART;
-
- e100_set_mdio_reg(dev, mdio_phy_addr, MII_BMCR, data);
+ }
+ e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR, data);
}
static void
e100_set_speed(struct net_device* dev, unsigned long speed)
{
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
if (speed != current_speed_selection) {
current_speed_selection = speed;
e100_negotiate(dev);
}
+ spin_unlock(&np->transceiver_lock);
}
static void
e100_check_duplex(unsigned long priv)
{
struct net_device *dev = (struct net_device *)priv;
- struct net_local *np = (struct net_local *)dev->priv;
- int old_duplex = full_duplex;
+ struct net_local *np = netdev_priv(dev);
+ int old_duplex;
+
+ spin_lock(&np->transceiver_lock);
+ old_duplex = full_duplex;
transceiver->check_duplex(dev);
if (old_duplex != full_duplex) {
/* Duplex changed */
@@ -920,13 +1016,22 @@
duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL;
add_timer(&duplex_timer);
np->mii_if.full_duplex = full_duplex;
+ spin_unlock(&np->transceiver_lock);
}
-
+#if defined(CONFIG_ETRAX_NO_PHY)
+static void
+dummy_check_duplex(struct net_device* dev)
+{
+ full_duplex = 1;
+}
+#else
static void
generic_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE);
if ((data & ADVERTISE_10FULL) ||
(data & ADVERTISE_100FULL))
full_duplex = 1;
@@ -938,7 +1043,10 @@
tdk_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_TDK_DIAGNOSTIC_REG);
full_duplex = (data & MDIO_TDK_DIAGNOSTIC_DPLX) ? 1 : 0;
}
@@ -946,7 +1054,10 @@
broadcom_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_AUX_CTRL_STATUS_REG);
full_duplex = (data & MDIO_BC_FULL_DUPLEX_IND) ? 1 : 0;
}
@@ -954,38 +1065,55 @@
intel_check_duplex(struct net_device* dev)
{
unsigned long data;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2);
+ struct net_local *np = netdev_priv(dev);
+
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id,
+ MDIO_INT_STATUS_REG_2);
full_duplex = (data & MDIO_INT_FULL_DUPLEX_IND) ? 1 : 0;
}
-
+#endif
static void
e100_set_duplex(struct net_device* dev, enum duplex new_duplex)
{
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
if (new_duplex != current_duplex) {
current_duplex = new_duplex;
e100_negotiate(dev);
}
+ spin_unlock(&np->transceiver_lock);
}
static int
e100_probe_transceiver(struct net_device* dev)
{
+ int ret = 0;
+
+#if !defined(CONFIG_ETRAX_NO_PHY)
unsigned int phyid_high;
unsigned int phyid_low;
unsigned int oui;
struct transceiver_ops* ops = NULL;
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->transceiver_lock);
/* Probe MDIO physical address */
- for (mdio_phy_addr = 0; mdio_phy_addr <= 31; mdio_phy_addr++) {
- if (e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR) != 0xffff)
+ for (np->mii_if.phy_id = 0; np->mii_if.phy_id <= 31;
+ np->mii_if.phy_id++) {
+ if (e100_get_mdio_reg(dev,
+ np->mii_if.phy_id, MII_BMSR) != 0xffff)
break;
}
- if (mdio_phy_addr == 32)
- return -ENODEV;
+ if (np->mii_if.phy_id == 32) {
+ ret = -ENODEV;
+ goto out;
+ }
/* Get manufacturer */
- phyid_high = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID1);
- phyid_low = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID2);
+ phyid_high = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID1);
+ phyid_low = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID2);
oui = (phyid_high << 6) | (phyid_low >> 10);
for (ops = &transceivers[0]; ops->oui; ops++) {
@@ -993,8 +1121,10 @@
break;
}
transceiver = ops;
-
- return 0;
+out:
+ spin_unlock(&np->transceiver_lock);
+#endif
+ return ret;
}
static int
@@ -1088,13 +1218,14 @@
static void
e100_reset_transceiver(struct net_device* dev)
{
+ struct net_local *np = netdev_priv(dev);
unsigned short cmd;
unsigned short data;
int bitCounter;
- data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR);
+ data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR);
- cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (mdio_phy_addr << 7) | (MII_BMCR << 2);
+ cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (np->mii_if.phy_id << 7) | (MII_BMCR << 2);
e100_send_mdio_cmd(cmd, 1);
@@ -1112,7 +1243,7 @@
static void
e100_tx_timeout(struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&np->lock, flags);
@@ -1134,8 +1265,7 @@
e100_reset_transceiver(dev);
/* and get rid of the packets that never got an interrupt */
- while (myFirstTxDesc != myNextTxDesc)
- {
+ while (myFirstTxDesc != myNextTxDesc) {
dev_kfree_skb(myFirstTxDesc->skb);
myFirstTxDesc->skb = 0;
myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
@@ -1161,7 +1291,7 @@
static int
e100_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned char *buf = skb->data;
unsigned long flags;
@@ -1174,7 +1304,7 @@
dev->trans_start = jiffies;
- e100_hardware_send_packet(buf, skb->len);
+ e100_hardware_send_packet(np, buf, skb->len);
myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next);
@@ -1197,13 +1327,15 @@
e100rxtx_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct net_local *np = (struct net_local *)dev->priv;
- unsigned long irqbits = *R_IRQ_MASK2_RD;
+ struct net_local *np = netdev_priv(dev);
+ unsigned long irqbits;
- /* Disable RX/TX IRQs to avoid reentrancy */
- *R_IRQ_MASK2_CLR =
- IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) |
- IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr);
+ /*
+ * Note that both rx and tx interrupts are blocked at this point,
+ * regardless of which got us here.
+ */
+
+ irqbits = *R_IRQ_MASK2_RD;
/* Handle received packets */
if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) {
@@ -1219,7 +1351,7 @@
* allocate a new buffer to put a packet in.
*/
e100_rx(dev);
- ((struct net_local *)dev->priv)->stats.rx_packets++;
+ np->stats.rx_packets++;
/* restart/continue on the channel, for safety */
*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart);
/* clear dma channel 1 eop/descr irq bits */
@@ -1233,9 +1365,8 @@
}
/* Report any packets that have been sent */
- while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) &&
- myFirstTxDesc != myNextTxDesc)
- {
+ while (virt_to_phys(myFirstTxDesc) != *R_DMA_CH0_FIRST &&
+ (netif_queue_stopped(dev) || myFirstTxDesc != myNextTxDesc)) {
np->stats.tx_bytes += myFirstTxDesc->skb->len;
np->stats.tx_packets++;
@@ -1244,18 +1375,14 @@
dev_kfree_skb_irq(myFirstTxDesc->skb);
myFirstTxDesc->skb = 0;
myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next);
- }
-
- if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) {
- /* acknowledge the eop interrupt and wake up queue */
- *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
+ /* Wake up queue. */
netif_wake_queue(dev);
}
- /* Enable RX/TX IRQs again */
- *R_IRQ_MASK2_SET =
- IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) |
- IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set);
+ if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) {
+ /* acknowledge the eop interrupt. */
+ *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
+ }
return IRQ_HANDLED;
}
@@ -1264,7 +1391,7 @@
e100nw_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned long irqbits = *R_IRQ_MASK0_RD;
/* check for underrun irq */
@@ -1286,7 +1413,6 @@
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr);
*R_NETWORK_TR_CTRL = network_tr_ctrl_shadow;
SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop);
- *R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr);
np->stats.tx_errors++;
D(printk("ethernet excessive collisions!\n"));
}
@@ -1299,12 +1425,13 @@
{
struct sk_buff *skb;
int length = 0;
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
unsigned char *skb_data_ptr;
#ifdef ETHDEBUG
int i;
#endif
-
+ etrax_eth_descr *prevRxDesc; /* The descriptor right before myNextRxDesc */
+ spin_lock(&np->led_lock);
if (!led_active && time_after(jiffies, led_next_time)) {
/* light the network leds depending on the current speed. */
e100_set_network_leds(NETWORK_ACTIVITY);
@@ -1314,9 +1441,10 @@
led_active = 1;
mod_timer(&clear_led_timer, jiffies + HZ/10);
}
+ spin_unlock(&np->led_lock);
length = myNextRxDesc->descr.hw_len - 4;
- ((struct net_local *)dev->priv)->stats.rx_bytes += length;
+ np->stats.rx_bytes += length;
#ifdef ETHDEBUG
printk("Got a packet of length %d:\n", length);
@@ -1336,7 +1464,7 @@
if (!skb) {
np->stats.rx_errors++;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- return;
+ goto update_nextrxdesc;
}
skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */
@@ -1354,15 +1482,15 @@
else {
/* Large packet, send directly to upper layers and allocate new
* memory (aligned to cache line boundary to avoid bug).
- * Before sending the skb to upper layers we must make sure that
- * skb->data points to the aligned start of the packet.
+ * Before sending the skb to upper layers we must make sure
+ * that skb->data points to the aligned start of the packet.
*/
int align;
struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES);
if (!new_skb) {
np->stats.rx_errors++;
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
- return;
+ goto update_nextrxdesc;
}
skb = myNextRxDesc->skb;
align = (int)phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data;
@@ -1377,9 +1505,10 @@
/* Send the packet to the upper layers */
netif_rx(skb);
+ update_nextrxdesc:
/* Prepare for next packet */
myNextRxDesc->descr.status = 0;
- myPrevRxDesc = myNextRxDesc;
+ prevRxDesc = myNextRxDesc;
myNextRxDesc = phys_to_virt(myNextRxDesc->descr.next);
rx_queue_len++;
@@ -1387,9 +1516,9 @@
/* Check if descriptors should be returned */
if (rx_queue_len == RX_QUEUE_THRESHOLD) {
flush_etrax_cache();
- myPrevRxDesc->descr.ctrl |= d_eol;
+ prevRxDesc->descr.ctrl |= d_eol;
myLastRxDesc->descr.ctrl &= ~d_eol;
- myLastRxDesc = myPrevRxDesc;
+ myLastRxDesc = prevRxDesc;
rx_queue_len = 0;
}
}
@@ -1398,7 +1527,7 @@
static int
e100_close(struct net_device *dev)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
printk(KERN_INFO "Closing %s.\n", dev->name);
@@ -1426,6 +1555,9 @@
free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev);
free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev);
+ cris_free_dma(NETWORK_TX_DMA_NBR, cardname);
+ cris_free_dma(NETWORK_RX_DMA_NBR, cardname);
+
/* Update the statistics here. */
update_rx_stats(&np->stats);
@@ -1443,18 +1575,11 @@
{
struct mii_ioctl_data *data = if_mii(ifr);
struct net_local *np = netdev_priv(dev);
+ int rc = 0;
+ int old_autoneg;
spin_lock(&np->lock); /* Preempt protection */
switch (cmd) {
- case SIOCGMIIPHY: /* Get PHY address */
- data->phy_id = mdio_phy_addr;
- break;
- case SIOCGMIIREG: /* Read MII register */
- data->val_out = e100_get_mdio_reg(dev, mdio_phy_addr, data->reg_num);
- break;
- case SIOCSMIIREG: /* Write MII register */
- e100_set_mdio_reg(dev, mdio_phy_addr, data->reg_num, data->val_in);
- break;
/* The ioctls below should be considered obsolete but are */
/* still present for compatability with old scripts/apps */
case SET_ETH_SPEED_10: /* 10 Mbps */
@@ -1463,60 +1588,47 @@
case SET_ETH_SPEED_100: /* 100 Mbps */
e100_set_speed(dev, 100);
break;
- case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */
+ case SET_ETH_SPEED_AUTO: /* Auto-negotiate speed */
e100_set_speed(dev, 0);
break;
- case SET_ETH_DUPLEX_HALF: /* Half duplex. */
+ case SET_ETH_DUPLEX_HALF: /* Half duplex */
e100_set_duplex(dev, half);
break;
- case SET_ETH_DUPLEX_FULL: /* Full duplex. */
+ case SET_ETH_DUPLEX_FULL: /* Full duplex */
e100_set_duplex(dev, full);
break;
- case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex*/
+ case SET_ETH_DUPLEX_AUTO: /* Auto-negotiate duplex */
e100_set_duplex(dev, autoneg);
break;
+ case SET_ETH_AUTONEG:
+ old_autoneg = autoneg_normal;
+ autoneg_normal = *(int*)data;
+ if (autoneg_normal != old_autoneg)
+ e100_negotiate(dev);
+ break;
default:
- return -EINVAL;
+ rc = generic_mii_ioctl(&np->mii_if, if_mii(ifr),
+ cmd, NULL);
+ break;
}
spin_unlock(&np->lock);
- return 0;
+ return rc;
}
-static int e100_set_settings(struct net_device *dev,
- struct ethtool_cmd *ecmd)
+static int e100_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
{
- ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |
- SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
- ecmd->port = PORT_TP;
- ecmd->transceiver = XCVR_EXTERNAL;
- ecmd->phy_address = mdio_phy_addr;
- ecmd->speed = current_speed;
- ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
- ecmd->advertising = ADVERTISED_TP;
+ struct net_local *np = netdev_priv(dev);
+ int err;
- if (current_duplex == autoneg && current_speed_selection == 0)
- ecmd->advertising |= ADVERTISED_Autoneg;
- else {
- ecmd->advertising |=
- ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
- if (current_speed_selection == 10)
- ecmd->advertising &= ~(ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full);
- else if (current_speed_selection == 100)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full);
- if (current_duplex == half)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Full |
- ADVERTISED_100baseT_Full);
- else if (current_duplex == full)
- ecmd->advertising &= ~(ADVERTISED_10baseT_Half |
- ADVERTISED_100baseT_Half);
- }
+ spin_lock_irq(&np->lock);
+ err = mii_ethtool_gset(&np->mii_if, cmd);
+ spin_unlock_irq(&np->lock);
- ecmd->autoneg = AUTONEG_ENABLE;
- return 0;
+ /* The PHY may support 1000baseT, but the Etrax100 does not. */
+ cmd->supported &= ~(SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full);
+ return err;
}
static int e100_set_settings(struct net_device *dev,
@@ -1560,7 +1672,8 @@
static int
e100_set_config(struct net_device *dev, struct ifmap *map)
{
- struct net_local *np = (struct net_local *)dev->priv;
+ struct net_local *np = netdev_priv(dev);
+
spin_lock(&np->lock); /* Preempt protection */
switch(map->port) {
@@ -1612,7 +1725,6 @@
es->collisions +=
IO_EXTRACT(R_TR_COUNTERS, single_col, r) +
IO_EXTRACT(R_TR_COUNTERS, multiple_col, r);
- es->tx_errors += IO_EXTRACT(R_TR_COUNTERS, deferred, r);
}
/*
@@ -1622,8 +1734,9 @@
static struct net_device_stats *
e100_get_stats(struct net_device *dev)
{
- struct net_local *lp = (struct net_local *)dev->priv;
+ struct net_local *lp = netdev_priv(dev);
unsigned long flags;
+
spin_lock_irqsave(&lp->lock, flags);
update_rx_stats(&lp->stats);
@@ -1643,13 +1756,13 @@
static void
set_multicast_list(struct net_device *dev)
{
- struct net_local *lp = (struct net_local *)dev->priv;
+ struct net_local *lp = netdev_priv(dev);
int num_addr = dev->mc_count;
unsigned long int lo_bits;
unsigned long int hi_bits;
+
spin_lock(&lp->lock);
- if (dev->flags & IFF_PROMISC)
- {
+ if (dev->flags & IFF_PROMISC) {
/* promiscuous mode */
lo_bits = 0xfffffffful;
hi_bits = 0xfffffffful;
@@ -1679,9 +1792,10 @@
struct dev_mc_list *dmi = dev->mc_list;
int i;
char *baddr;
+
lo_bits = 0x00000000ul;
hi_bits = 0x00000000ul;
- for (i=0; i<num_addr; i++) {
+ for (i = 0; i < num_addr; i++) {
/* Calculate the hash index for the GA registers */
hash_ix = 0;
@@ -1708,8 +1822,7 @@
if (hash_ix >= 32) {
hi_bits |= (1 << (hash_ix-32));
- }
- else {
+ } else {
lo_bits |= (1 << hash_ix);
}
dmi = dmi->next;
@@ -1724,10 +1837,11 @@
}
void
-e100_hardware_send_packet(char *buf, int length)
+e100_hardware_send_packet(struct net_local *np, char *buf, int length)
{
D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));
+ spin_lock(&np->led_lock);
if (!led_active && time_after(jiffies, led_next_time)) {
/* light the network leds depending on the current speed. */
e100_set_network_leds(NETWORK_ACTIVITY);
@@ -1737,6 +1851,7 @@
led_active = 1;
mod_timer(&clear_led_timer, jiffies + HZ/10);
}
+ spin_unlock(&np->led_lock);
/* configure the tx dma descriptor */
myNextTxDesc->descr.sw_len = length;
@@ -1754,6 +1869,11 @@
static void
e100_clear_network_leds(unsigned long dummy)
{
+ struct net_device *dev = (struct net_device *)dummy;
+ struct net_local *np = netdev_priv(dev);
+
+ spin_lock(&np->led_lock);
+
if (led_active && time_after(jiffies, led_next_time)) {
e100_set_network_leds(NO_NETWORK_ACTIVITY);
@@ -1761,6 +1881,8 @@
led_next_time = jiffies + NET_FLASH_PAUSE;
led_active = 0;
}
+
+ spin_unlock(&np->led_lock);
}
static void
@@ -1781,19 +1903,25 @@
#else
LED_NETWORK_SET(LED_OFF);
#endif
- }
- else if (light_leds) {
+ } else if (light_leds) {
if (current_speed == 10) {
LED_NETWORK_SET(LED_ORANGE);
} else {
LED_NETWORK_SET(LED_GREEN);
}
- }
- else {
+ } else {
LED_NETWORK_SET(LED_OFF);
}
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void
+e100_netpoll(struct net_device* netdev)
+{
+ e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL);
+}
+#endif
+
static int
etrax_init_module(void)
{
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 72deff0..cf39473 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -4804,6 +4804,7 @@
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
+ spin_unlock_irqrestore(&adapter->stats_lock, flags);
if (adapter->hw.media_type == e1000_media_type_copper) {
switch (data->reg_num) {
case PHY_CTRL:
@@ -4824,12 +4825,8 @@
DUPLEX_HALF;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if (retval) {
- spin_unlock_irqrestore(
- &adapter->stats_lock,
- flags);
+ if (retval)
return retval;
- }
}
if (netif_running(adapter->netdev))
e1000_reinit_locked(adapter);
@@ -4838,11 +4835,8 @@
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if (e1000_phy_reset(&adapter->hw)) {
- spin_unlock_irqrestore(
- &adapter->stats_lock, flags);
+ if (e1000_phy_reset(&adapter->hw))
return -EIO;
- }
break;
}
} else {
@@ -4857,7 +4851,6 @@
break;
}
}
- spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 2765e49..562ea68 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -2,6 +2,7 @@
tristate "Freescale Ethernet Driver"
depends on CPM1 || CPM2
select MII
+ select PHYLIB
config FS_ENET_HAS_SCC
bool "Chip has an SCC usable for ethernet"
@@ -11,11 +12,19 @@
config FS_ENET_HAS_FCC
bool "Chip has an FCC usable for ethernet"
depends on FS_ENET && CPM2
- select MDIO_BITBANG
default y
config FS_ENET_HAS_FEC
bool "Chip has an FEC usable for ethernet"
depends on FS_ENET && CPM1
+ select FS_ENET_MDIO_FEC
default y
+config FS_ENET_MDIO_FEC
+ tristate "MDIO driver for FEC"
+ depends on FS_ENET && CPM1
+
+config FS_ENET_MDIO_FCC
+ tristate "MDIO driver for FCC"
+ depends on FS_ENET && CPM2
+ select MDIO_BITBANG
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index 02d4dc1..1ffbe07 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -4,7 +4,16 @@
obj-$(CONFIG_FS_ENET) += fs_enet.o
-obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
-obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
+fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o
+fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o
+fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o
-fs_enet-objs := fs_enet-main.o
+ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y)
+obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
+obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
+else
+fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
+fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
+endif
+
+fs_enet-objs := fs_enet-main.o $(fs_enet-m)
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 45f30a2..662b8d1 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -284,7 +284,7 @@
unregister_netdev(dev);
}
-static struct pernet_operations loopback_net_ops = {
+static struct pernet_operations __net_initdata loopback_net_ops = {
.init = loopback_net_init,
.exit = loopback_net_exit,
};
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index f8d63d3..b226e01 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -171,9 +171,10 @@
buf->u.direct.map);
else {
for (i = 0; i < buf->nbufs; ++i)
- dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
- buf->u.page_list[i].buf,
- buf->u.page_list[i].map);
+ if (buf->u.page_list[i].buf)
+ dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+ buf->u.page_list[i].buf,
+ buf->u.page_list[i].map);
kfree(buf->u.page_list);
}
}
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index cc4b1be..42b4763 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -240,7 +240,7 @@
mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
- if (qp->qpn < dev->caps.sqp_start + 8)
+ if (qp->qpn >= dev->caps.sqp_start + 8)
mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
}
EXPORT_SYMBOL_GPL(mlx4_qp_free);
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 8d29319..656a260 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -134,7 +134,7 @@
myri_disable_irq(mp->lregs, cregs);
- while (tick++ <= 25) {
+ while (tick++ < 25) {
u32 softstate;
/* Wake it up. */
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index eb0aff7..5267e03 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -128,8 +128,8 @@
FIFO_PTR_FRAMELEN(len));
ndev->trans_start = jiffies;
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
netif_stop_queue(ndev);
spin_unlock_irq(&priv->lock);
@@ -155,7 +155,7 @@
if (unlikely(skb == NULL)) {
printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
ndev->name);
- dev->stats.rx_dropped++;
+ ndev->stats.rx_dropped++;
return;
}
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 8d278c8..f023d5b 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -160,7 +160,7 @@
err = -ENOMEM;
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
- if (ap == 0)
+ if (!ap)
goto out;
/* initialize the asyncppp structure */
@@ -215,7 +215,7 @@
ap = tty->disc_data;
tty->disc_data = NULL;
write_unlock_irq(&disc_data_lock);
- if (ap == 0)
+ if (!ap)
return;
/*
@@ -230,10 +230,10 @@
tasklet_kill(&ap->tsk);
ppp_unregister_channel(&ap->chan);
- if (ap->rpkt != 0)
+ if (ap->rpkt)
kfree_skb(ap->rpkt);
skb_queue_purge(&ap->rqueue);
- if (ap->tpkt != 0)
+ if (ap->tpkt)
kfree_skb(ap->tpkt);
kfree(ap);
}
@@ -285,13 +285,13 @@
int err, val;
int __user *p = (int __user *)arg;
- if (ap == 0)
+ if (!ap)
return -ENXIO;
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
@@ -301,7 +301,7 @@
case PPPIOCGUNIT:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
@@ -350,7 +350,7 @@
struct asyncppp *ap = ap_get(tty);
unsigned long flags;
- if (ap == 0)
+ if (!ap)
return;
spin_lock_irqsave(&ap->recv_lock, flags);
ppp_async_input(ap, buf, cflags, count);
@@ -369,7 +369,7 @@
struct asyncppp *ap = ap_get(tty);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- if (ap == 0)
+ if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
@@ -684,7 +684,7 @@
tty_stuffed = 1;
continue;
}
- if (ap->optr >= ap->olim && ap->tpkt != 0) {
+ if (ap->optr >= ap->olim && ap->tpkt) {
if (ppp_async_encode(ap)) {
/* finished processing ap->tpkt */
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -704,7 +704,7 @@
clear_bit(XMIT_BUSY, &ap->xmit_flags);
/* any more work to do? if not, exit the loop */
if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
- || (!tty_stuffed && ap->tpkt != 0)))
+ || (!tty_stuffed && ap->tpkt)))
break;
/* more work to do, see if we can do it now */
if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
@@ -715,7 +715,7 @@
flush:
clear_bit(XMIT_BUSY, &ap->xmit_flags);
- if (ap->tpkt != 0) {
+ if (ap->tpkt) {
kfree_skb(ap->tpkt);
ap->tpkt = NULL;
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -848,7 +848,7 @@
s = 0;
for (i = 0; i < count; ++i) {
c = buf[i];
- if (flags != 0 && flags[i] != 0)
+ if (flags && flags[i] != 0)
continue;
s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;
c = ((c >> 4) ^ c) & 0xf;
@@ -865,7 +865,7 @@
n = scan_ordinary(ap, buf, count);
f = 0;
- if (flags != 0 && (ap->state & SC_TOSS) == 0) {
+ if (flags && (ap->state & SC_TOSS) == 0) {
/* check the flags to see if any char had an error */
for (j = 0; j < n; ++j)
if ((f = flags[j]) != 0)
@@ -878,9 +878,9 @@
} else if (n > 0 && (ap->state & SC_TOSS) == 0) {
/* stuff the chars in the skb */
skb = ap->rpkt;
- if (skb == 0) {
+ if (!skb) {
skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
- if (skb == 0)
+ if (!skb)
goto nomem;
ap->rpkt = skb;
}
@@ -927,7 +927,7 @@
++n;
buf += n;
- if (flags != 0)
+ if (flags)
flags += n;
count -= n;
}
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 4b49d0e..4f690378 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -367,7 +367,7 @@
struct ppp_file *pf = file->private_data;
struct ppp *ppp;
- if (pf != 0) {
+ if (pf) {
file->private_data = NULL;
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
@@ -398,7 +398,7 @@
ret = count;
- if (pf == 0)
+ if (!pf)
return -ENXIO;
add_wait_queue(&pf->rwait, &wait);
for (;;) {
@@ -431,7 +431,7 @@
set_current_state(TASK_RUNNING);
remove_wait_queue(&pf->rwait, &wait);
- if (skb == 0)
+ if (!skb)
goto out;
ret = -EOVERFLOW;
@@ -455,11 +455,11 @@
struct sk_buff *skb;
ssize_t ret;
- if (pf == 0)
+ if (!pf)
return -ENXIO;
ret = -ENOMEM;
skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
- if (skb == 0)
+ if (!skb)
goto out;
skb_reserve(skb, pf->hdrlen);
ret = -EFAULT;
@@ -491,11 +491,11 @@
struct ppp_file *pf = file->private_data;
unsigned int mask;
- if (pf == 0)
+ if (!pf)
return 0;
poll_wait(file, &pf->rwait, wait);
mask = POLLOUT | POLLWRNORM;
- if (skb_peek(&pf->rq) != 0)
+ if (skb_peek(&pf->rq))
mask |= POLLIN | POLLRDNORM;
if (pf->dead)
mask |= POLLHUP;
@@ -559,7 +559,7 @@
void __user *argp = (void __user *)arg;
int __user *p = argp;
- if (pf == 0)
+ if (!pf)
return ppp_unattached_ioctl(pf, file, cmd, arg);
if (cmd == PPPIOCDETACH) {
@@ -689,13 +689,13 @@
val &= 0xffff;
}
vj = slhc_init(val2+1, val+1);
- if (vj == 0) {
+ if (!vj) {
printk(KERN_ERR "PPP: no memory (VJ compressor)\n");
err = -ENOMEM;
break;
}
ppp_lock(ppp);
- if (ppp->vj != 0)
+ if (ppp->vj)
slhc_free(ppp->vj);
ppp->vj = vj;
ppp_unlock(ppp);
@@ -786,7 +786,7 @@
if (get_user(unit, p))
break;
ppp = ppp_create_interface(unit, &err);
- if (ppp == 0)
+ if (!ppp)
break;
file->private_data = &ppp->file;
ppp->owner = file;
@@ -803,7 +803,7 @@
mutex_lock(&all_ppp_mutex);
err = -ENXIO;
ppp = ppp_find_unit(unit);
- if (ppp != 0) {
+ if (ppp) {
atomic_inc(&ppp->file.refcnt);
file->private_data = &ppp->file;
err = 0;
@@ -817,7 +817,7 @@
spin_lock_bh(&all_channels_lock);
err = -ENXIO;
chan = ppp_find_channel(unit);
- if (chan != 0) {
+ if (chan) {
atomic_inc(&chan->file.refcnt);
file->private_data = &chan->file;
err = 0;
@@ -946,9 +946,9 @@
case SIOCGPPPCSTATS:
memset(&cstats, 0, sizeof(cstats));
- if (ppp->xc_state != 0)
+ if (ppp->xc_state)
ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c);
- if (ppp->rc_state != 0)
+ if (ppp->rc_state)
ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d);
if (copy_to_user(addr, &cstats, sizeof(cstats)))
break;
@@ -993,14 +993,14 @@
struct sk_buff *skb;
ppp_xmit_lock(ppp);
- if (ppp->dev != 0) {
+ if (ppp->dev) {
ppp_push(ppp);
- while (ppp->xmit_pending == 0
- && (skb = skb_dequeue(&ppp->file.xq)) != 0)
+ while (!ppp->xmit_pending
+ && (skb = skb_dequeue(&ppp->file.xq)))
ppp_send_frame(ppp, skb);
/* If there's no work left to do, tell the core net
code that we can accept some more. */
- if (ppp->xmit_pending == 0 && skb_peek(&ppp->file.xq) == 0)
+ if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
netif_wake_queue(ppp->dev);
}
ppp_xmit_unlock(ppp);
@@ -1100,12 +1100,12 @@
switch (proto) {
case PPP_IP:
- if (ppp->vj == 0 || (ppp->flags & SC_COMP_TCP) == 0)
+ if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0)
break;
/* try to do VJ TCP header compression */
new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
GFP_ATOMIC);
- if (new_skb == 0) {
+ if (!new_skb) {
printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n");
goto drop;
}
@@ -1140,7 +1140,7 @@
}
/* try to do packet compression */
- if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0
+ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state
&& proto != PPP_LCP && proto != PPP_CCP) {
if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) {
if (net_ratelimit())
@@ -1185,7 +1185,7 @@
struct channel *pch;
struct sk_buff *skb = ppp->xmit_pending;
- if (skb == 0)
+ if (!skb)
return;
list = &ppp->channels;
@@ -1355,7 +1355,7 @@
if (flen == len && nfree == 0)
bits |= E;
frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
- if (frag == 0)
+ if (!frag)
goto noskb;
q = skb_put(frag, flen + hdrlen);
@@ -1425,7 +1425,7 @@
struct ppp *ppp;
spin_lock_bh(&pch->downl);
- if (pch->chan != 0) {
+ if (pch->chan) {
while (!skb_queue_empty(&pch->file.xq)) {
skb = skb_dequeue(&pch->file.xq);
if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
@@ -1443,7 +1443,7 @@
if (skb_queue_empty(&pch->file.xq)) {
read_lock_bh(&pch->upl);
ppp = pch->ppp;
- if (ppp != 0)
+ if (ppp)
ppp_xmit_process(ppp);
read_unlock_bh(&pch->upl);
}
@@ -1462,7 +1462,7 @@
{
ppp_recv_lock(ppp);
/* ppp->dev == 0 means interface is closing down */
- if (ppp->dev != 0)
+ if (ppp->dev)
ppp_receive_frame(ppp, skb, pch);
else
kfree_skb(skb);
@@ -1475,19 +1475,19 @@
struct channel *pch = chan->ppp;
int proto;
- if (pch == 0 || skb->len == 0) {
+ if (!pch || skb->len == 0) {
kfree_skb(skb);
return;
}
proto = PPP_PROTO(skb);
read_lock_bh(&pch->upl);
- if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) {
+ if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) {
/* put it on the channel queue */
skb_queue_tail(&pch->file.rq, skb);
/* drop old frames if queue too long */
while (pch->file.rq.qlen > PPP_MAX_RQLEN
- && (skb = skb_dequeue(&pch->file.rq)) != 0)
+ && (skb = skb_dequeue(&pch->file.rq)))
kfree_skb(skb);
wake_up_interruptible(&pch->file.rwait);
} else {
@@ -1503,13 +1503,13 @@
struct channel *pch = chan->ppp;
struct sk_buff *skb;
- if (pch == 0)
+ if (!pch)
return;
read_lock_bh(&pch->upl);
- if (pch->ppp != 0) {
+ if (pch->ppp) {
skb = alloc_skb(0, GFP_ATOMIC);
- if (skb != 0) {
+ if (skb) {
skb->len = 0; /* probably unnecessary */
skb->cb[0] = code;
ppp_do_recv(pch->ppp, skb, pch);
@@ -1548,7 +1548,7 @@
ppp_receive_error(struct ppp *ppp)
{
++ppp->stats.rx_errors;
- if (ppp->vj != 0)
+ if (ppp->vj)
slhc_toss(ppp->vj);
}
@@ -1563,7 +1563,7 @@
* Note that some decompressors need to see uncompressed frames
* that come in as well as compressed frames.
*/
- if (ppp->rc_state != 0 && (ppp->rstate & SC_DECOMP_RUN)
+ if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN)
&& (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0)
skb = ppp_decompress_frame(ppp, skb);
@@ -1574,13 +1574,13 @@
switch (proto) {
case PPP_VJC_COMP:
/* decompress VJ compressed packets */
- if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
+ if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
goto err;
if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
/* copy to a new sk_buff with more tailroom */
ns = dev_alloc_skb(skb->len + 128);
- if (ns == 0) {
+ if (!ns) {
printk(KERN_ERR"PPP: no memory (VJ decomp)\n");
goto err;
}
@@ -1606,7 +1606,7 @@
break;
case PPP_VJC_UNCOMP:
- if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
+ if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
goto err;
/* Until we fix the decompressor need to make sure
@@ -1636,7 +1636,7 @@
skb_queue_tail(&ppp->file.rq, skb);
/* limit queue length by dropping old frames */
while (ppp->file.rq.qlen > PPP_MAX_RQLEN
- && (skb = skb_dequeue(&ppp->file.rq)) != 0)
+ && (skb = skb_dequeue(&ppp->file.rq)))
kfree_skb(skb);
/* wake up any process polling or blocking on read */
wake_up_interruptible(&ppp->file.rwait);
@@ -1718,7 +1718,7 @@
}
ns = dev_alloc_skb(obuff_size);
- if (ns == 0) {
+ if (!ns) {
printk(KERN_ERR "ppp_decompress_frame: no memory\n");
goto err;
}
@@ -1836,7 +1836,7 @@
ppp->minseq = ppp->mrq.next->sequence;
/* Pull completed packets off the queue and receive them. */
- while ((skb = ppp_mp_reconstruct(ppp)) != 0)
+ while ((skb = ppp_mp_reconstruct(ppp)))
ppp_receive_nonmp_frame(ppp, skb);
return;
@@ -2002,7 +2002,7 @@
struct channel *pch;
pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
- if (pch == 0)
+ if (!pch)
return -ENOMEM;
pch->ppp = NULL;
pch->chan = chan;
@@ -2030,7 +2030,7 @@
{
struct channel *pch = chan->ppp;
- if (pch != 0)
+ if (pch)
return pch->file.index;
return -1;
}
@@ -2043,9 +2043,9 @@
struct channel *pch = chan->ppp;
int unit = -1;
- if (pch != 0) {
+ if (pch) {
read_lock_bh(&pch->upl);
- if (pch->ppp != 0)
+ if (pch->ppp)
unit = pch->ppp->file.index;
read_unlock_bh(&pch->upl);
}
@@ -2061,7 +2061,7 @@
{
struct channel *pch = chan->ppp;
- if (pch == 0)
+ if (!pch)
return; /* should never happen */
chan->ppp = NULL;
@@ -2093,7 +2093,7 @@
{
struct channel *pch = chan->ppp;
- if (pch == 0)
+ if (!pch)
return;
ppp_channel_push(pch);
}
@@ -2124,18 +2124,18 @@
cp = find_compressor(ccp_option[0]);
#ifdef CONFIG_KMOD
- if (cp == 0) {
+ if (!cp) {
request_module("ppp-compress-%d", ccp_option[0]);
cp = find_compressor(ccp_option[0]);
}
#endif /* CONFIG_KMOD */
- if (cp == 0)
+ if (!cp)
goto out;
err = -ENOBUFS;
if (data.transmit) {
state = cp->comp_alloc(ccp_option, data.length);
- if (state != 0) {
+ if (state) {
ppp_xmit_lock(ppp);
ppp->xstate &= ~SC_COMP_RUN;
ocomp = ppp->xcomp;
@@ -2143,7 +2143,7 @@
ppp->xcomp = cp;
ppp->xc_state = state;
ppp_xmit_unlock(ppp);
- if (ostate != 0) {
+ if (ostate) {
ocomp->comp_free(ostate);
module_put(ocomp->owner);
}
@@ -2153,7 +2153,7 @@
} else {
state = cp->decomp_alloc(ccp_option, data.length);
- if (state != 0) {
+ if (state) {
ppp_recv_lock(ppp);
ppp->rstate &= ~SC_DECOMP_RUN;
ocomp = ppp->rcomp;
@@ -2161,7 +2161,7 @@
ppp->rcomp = cp;
ppp->rc_state = state;
ppp_recv_unlock(ppp);
- if (ostate != 0) {
+ if (ostate) {
ocomp->decomp_free(ostate);
module_put(ocomp->owner);
}
@@ -2228,7 +2228,7 @@
break;
if (inbound) {
/* we will start receiving compressed packets */
- if (ppp->rc_state == 0)
+ if (!ppp->rc_state)
break;
if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len,
ppp->file.index, 0, ppp->mru, ppp->debug)) {
@@ -2237,7 +2237,7 @@
}
} else {
/* we will soon start sending compressed packets */
- if (ppp->xc_state == 0)
+ if (!ppp->xc_state)
break;
if (ppp->xcomp->comp_init(ppp->xc_state, dp, len,
ppp->file.index, 0, ppp->debug))
@@ -2320,11 +2320,11 @@
int ret;
spin_lock(&compressor_list_lock);
ret = -EEXIST;
- if (find_comp_entry(cp->compress_proto) != 0)
+ if (find_comp_entry(cp->compress_proto))
goto out;
ret = -ENOMEM;
ce = kmalloc(sizeof(struct compressor_entry), GFP_ATOMIC);
- if (ce == 0)
+ if (!ce)
goto out;
ret = 0;
ce->comp = cp;
@@ -2342,7 +2342,7 @@
spin_lock(&compressor_list_lock);
ce = find_comp_entry(cp->compress_proto);
- if (ce != 0 && ce->comp == cp) {
+ if (ce && ce->comp == cp) {
list_del(&ce->list);
kfree(ce);
}
@@ -2358,7 +2358,7 @@
spin_lock(&compressor_list_lock);
ce = find_comp_entry(type);
- if (ce != 0) {
+ if (ce) {
cp = ce->comp;
if (!try_module_get(cp->owner))
cp = NULL;
@@ -2383,7 +2383,7 @@
st->p.ppp_opackets = ppp->stats.tx_packets;
st->p.ppp_oerrors = ppp->stats.tx_errors;
st->p.ppp_obytes = ppp->stats.tx_bytes;
- if (vj == 0)
+ if (!vj)
return;
st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
st->vj.vjs_compressed = vj->sls_o_compressed;
@@ -2604,11 +2604,11 @@
mutex_lock(&all_ppp_mutex);
ppp = ppp_find_unit(unit);
- if (ppp == 0)
+ if (!ppp)
goto out;
write_lock_bh(&pch->upl);
ret = -EINVAL;
- if (pch->ppp != 0)
+ if (pch->ppp)
goto outl;
ppp_lock(ppp);
@@ -2644,7 +2644,7 @@
ppp = pch->ppp;
pch->ppp = NULL;
write_unlock_bh(&pch->upl);
- if (ppp != 0) {
+ if (ppp) {
/* remove it from the ppp unit's list */
ppp_lock(ppp);
list_del(&pch->clist);
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 00e2fb4..f0c6a19 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -209,7 +209,7 @@
ap = kzalloc(sizeof(*ap), GFP_KERNEL);
err = -ENOMEM;
- if (ap == 0)
+ if (!ap)
goto out;
/* initialize the syncppp structure */
@@ -262,7 +262,7 @@
ap = tty->disc_data;
tty->disc_data = NULL;
write_unlock_irq(&disc_data_lock);
- if (ap == 0)
+ if (!ap)
return;
/*
@@ -278,7 +278,7 @@
ppp_unregister_channel(&ap->chan);
skb_queue_purge(&ap->rqueue);
- if (ap->tpkt != 0)
+ if (ap->tpkt)
kfree_skb(ap->tpkt);
kfree(ap);
}
@@ -325,13 +325,13 @@
int __user *p = (int __user *)arg;
int err, val;
- if (ap == 0)
+ if (!ap)
return -ENXIO;
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
@@ -341,7 +341,7 @@
case PPPIOCGUNIT:
err = -ENXIO;
- if (ap == 0)
+ if (!ap)
break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
@@ -390,7 +390,7 @@
struct syncppp *ap = sp_get(tty);
unsigned long flags;
- if (ap == 0)
+ if (!ap)
return;
spin_lock_irqsave(&ap->recv_lock, flags);
ppp_sync_input(ap, buf, cflags, count);
@@ -409,7 +409,7 @@
struct syncppp *ap = sp_get(tty);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- if (ap == 0)
+ if (!ap)
return;
set_bit(XMIT_WAKEUP, &ap->xmit_flags);
tasklet_schedule(&ap->tsk);
@@ -651,7 +651,7 @@
for (;;) {
if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
tty_stuffed = 0;
- if (!tty_stuffed && ap->tpkt != 0) {
+ if (!tty_stuffed && ap->tpkt) {
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len);
if (sent < 0)
@@ -669,7 +669,7 @@
/* haven't made any progress */
spin_unlock_bh(&ap->xmit_lock);
if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
- || (!tty_stuffed && ap->tpkt != 0)))
+ || (!tty_stuffed && ap->tpkt)))
break;
if (!spin_trylock_bh(&ap->xmit_lock))
break;
@@ -677,7 +677,7 @@
return done;
flush:
- if (ap->tpkt != 0) {
+ if (ap->tpkt) {
kfree_skb(ap->tpkt);
ap->tpkt = NULL;
clear_bit(XMIT_FULL, &ap->xmit_flags);
@@ -732,7 +732,8 @@
ppp_print_buffer ("receive buffer", buf, count);
/* stuff the chars in the skb */
- if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
+ skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
+ if (!skb) {
printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
goto err;
}
@@ -740,7 +741,7 @@
if (buf[0] != PPP_ALLSTATIONS)
skb_reserve(skb, 2 + (buf[0] & 1));
- if (flags != 0 && *flags) {
+ if (flags && *flags) {
/* error flag set, ignore frame */
goto err;
} else if (count > skb_tailroom(skb)) {
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index b8c0e7b..6326667 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -84,7 +84,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.5"
+#define DRV_VERSION "2.0.26.6"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -3775,6 +3775,40 @@
return err;
}
+
+static void remove_msix_isr(struct s2io_nic *sp)
+{
+ int i;
+ u16 msi_control;
+
+ for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+ if (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+ free_irq(vector, arg);
+ }
+ }
+
+ kfree(sp->entries);
+ kfree(sp->s2io_entries);
+ sp->entries = NULL;
+ sp->s2io_entries = NULL;
+
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+ pci_disable_msix(sp->pdev);
+}
+
+static void remove_inta_isr(struct s2io_nic *sp)
+{
+ struct net_device *dev = sp->dev;
+
+ free_irq(sp->pdev->irq, dev);
+}
+
/* ********************************************************* *
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
@@ -3809,28 +3843,9 @@
int ret = s2io_enable_msi_x(sp);
if (!ret) {
- u16 msi_control;
-
ret = s2io_test_msi(sp);
-
/* rollback MSI-X, will re-enable during add_isr() */
- kfree(sp->entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
-
+ remove_msix_isr(sp);
}
if (ret) {
@@ -6719,15 +6734,22 @@
}
}
if (err) {
+ remove_msix_isr(sp);
DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
"failed\n", dev->name, i);
- DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
- return -1;
+ DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n",
+ dev->name);
+ sp->config.intr_type = INTA;
+ break;
}
sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
}
- printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
- printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
+ if (!err) {
+ printk(KERN_INFO "MSI-X-TX %d entries enabled\n",
+ msix_tx_cnt);
+ printk(KERN_INFO "MSI-X-RX %d entries enabled\n",
+ msix_rx_cnt);
+ }
}
if (sp->config.intr_type == INTA) {
err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
@@ -6742,40 +6764,10 @@
}
static void s2io_rem_isr(struct s2io_nic * sp)
{
- struct net_device *dev = sp->dev;
- struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
-
- if (sp->config.intr_type == MSI_X) {
- int i;
- u16 msi_control;
-
- for (i=1; (sp->s2io_entries[i].in_use ==
- MSIX_REGISTERED_SUCCESS); i++) {
- int vector = sp->entries[i].vector;
- void *arg = sp->s2io_entries[i].arg;
-
- synchronize_irq(vector);
- free_irq(vector, arg);
- }
-
- kfree(sp->entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
- } else {
- synchronize_irq(sp->pdev->irq);
- free_irq(sp->pdev->irq, dev);
- }
+ if (sp->config.intr_type == MSI_X)
+ remove_msix_isr(sp);
+ else
+ remove_inta_isr(sp);
}
static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 53b8344..f6fedcc 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2333,10 +2333,10 @@
{
struct gem *gp = dev->priv;
- napi_disable(&gp->napi);
-
mutex_lock(&gp->pm_mutex);
+ napi_disable(&gp->napi);
+
gp->opened = 0;
if (!gp->asleep)
gem_do_stop(dev, 0);
@@ -2355,8 +2355,6 @@
mutex_lock(&gp->pm_mutex);
- napi_disable(&gp->napi);
-
printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",
dev->name,
(gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
@@ -2370,6 +2368,8 @@
/* If the driver is opened, we stop the MAC */
if (gp->opened) {
+ napi_disable(&gp->napi);
+
/* Stop traffic, mark us closed */
netif_device_detach(dev);
@@ -2460,6 +2460,7 @@
/* Re-attach net device */
netif_device_attach(dev);
+ napi_enable(&gp->napi);
}
spin_lock_irqsave(&gp->lock, flags);
@@ -2479,8 +2480,6 @@
spin_unlock(&gp->tx_lock);
spin_unlock_irqrestore(&gp->lock, flags);
- napi_enable(&gp->napi);
-
mutex_unlock(&gp->pm_mutex);
return 0;
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 4e1b84e..21230c9 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -2168,10 +2168,10 @@
{
struct bdx_priv *priv = netdev->priv;
- strncat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
- strncat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
- strncat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
- strncat(drvinfo->bus_info, pci_name(priv->pdev),
+ strlcat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
+ strlcat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
+ strlcat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+ strlcat(drvinfo->bus_info, pci_name(priv->pdev),
sizeof(drvinfo->bus_info));
drvinfo->n_stats = ((priv->stats_flag) ?
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index cad5199..4942f7d 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.85"
-#define DRV_MODULE_RELDATE "October 18, 2007"
+#define DRV_MODULE_VERSION "3.86"
+#define DRV_MODULE_RELDATE "November 9, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -1106,6 +1106,24 @@
if (err)
return err;
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ u32 val;
+
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
+ CPMU_LSPD_1000MB_MACCLK_12_5) {
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ udelay(40);
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
+ /* Disable GPHY autopowerdown. */
+ tg3_writephy(tp, MII_TG3_MISC_SHDW,
+ MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_APD_SEL |
+ MII_TG3_MISC_SHDW_APD_WKTM_84MS);
+ }
+
out:
if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1297,6 +1315,8 @@
static void tg3_power_down_phy(struct tg3 *tp)
{
+ u32 val;
+
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
@@ -1311,8 +1331,6 @@
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u32 val;
-
tg3_bmcr_reset(tp);
val = tr32(GRC_MISC_CFG);
tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
@@ -1332,6 +1350,14 @@
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
+
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
+ val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
+ val |= CPMU_LSPD_1000MB_MACCLK_12_5;
+ tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
+ }
+
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
}
@@ -3126,6 +3152,23 @@
err = tg3_setup_copper_phy(tp, force_reset);
}
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+ u32 val, scale;
+
+ val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
+ if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5)
+ scale = 65;
+ else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25)
+ scale = 6;
+ else
+ scale = 12;
+
+ val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK;
+ val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT);
+ tw32(GRC_MISC_CFG, val);
+ }
+
if (tp->link_config.active_speed == SPEED_1000 &&
tp->link_config.active_duplex == DUPLEX_HALF)
tw32(MAC_TX_LENGTHS,
@@ -5054,12 +5097,15 @@
pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
- if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+ pcie_set_readrq(tp->pdev, 4096);
+ else {
pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
tp->pci_cacheline_sz);
pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
tp->pci_lat_timer);
}
+
/* Make sure PCI-X relaxed ordering bit is clear. */
if (tp->pcix_cap) {
u16 pcix_cmd;
@@ -6343,10 +6389,26 @@
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) {
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
+
+ val = tr32(TG3_CPMU_LSPD_10MB_CLK);
+ val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
+ val |= CPMU_LSPD_10MB_MACCLK_6_25;
+ tw32(TG3_CPMU_LSPD_10MB_CLK, val);
+
+ val = tr32(TG3_CPMU_LNK_AWARE_PWRMD);
+ val &= ~CPMU_LNK_AWARE_MACCLK_MASK;
+ val |= CPMU_LNK_AWARE_MACCLK_6_25;
+ tw32(TG3_CPMU_LNK_AWARE_PWRMD, val);
+
+ val = tr32(TG3_CPMU_HST_ACC);
+ val &= ~CPMU_HST_ACC_MACCLK_MASK;
+ val |= CPMU_HST_ACC_MACCLK_6_25;
+ tw32(TG3_CPMU_HST_ACC, val);
}
/* This works around an issue with Athlon chipsets on
@@ -8267,7 +8329,7 @@
SUPPORTED_100baseT_Full |
SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
+ SUPPORTED_TP);
cmd->port = PORT_TP;
} else {
cmd->supported |= SUPPORTED_FIBRE;
@@ -8664,7 +8726,9 @@
}
#define NVRAM_TEST_SIZE 0x100
-#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14
+#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18
+#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c
#define NVRAM_SELFBOOT_HW_SIZE 0x20
#define NVRAM_SELFBOOT_DATA_SIZE 0x1c
@@ -8679,9 +8743,22 @@
if (magic == TG3_EEPROM_MAGIC)
size = NVRAM_TEST_SIZE;
else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) {
- if ((magic & 0xe00000) == 0x200000)
- size = NVRAM_SELFBOOT_FORMAT1_SIZE;
- else
+ if ((magic & TG3_EEPROM_SB_FORMAT_MASK) ==
+ TG3_EEPROM_SB_FORMAT_1) {
+ switch (magic & TG3_EEPROM_SB_REVISION_MASK) {
+ case TG3_EEPROM_SB_REVISION_0:
+ size = NVRAM_SELFBOOT_FORMAT1_0_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_2:
+ size = NVRAM_SELFBOOT_FORMAT1_2_SIZE;
+ break;
+ case TG3_EEPROM_SB_REVISION_3:
+ size = NVRAM_SELFBOOT_FORMAT1_3_SIZE;
+ break;
+ default:
+ return 0;
+ }
+ } else
return 0;
} else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW)
size = NVRAM_SELFBOOT_HW_SIZE;
@@ -8708,8 +8785,17 @@
TG3_EEPROM_MAGIC_FW) {
u8 *buf8 = (u8 *) buf, csum8 = 0;
- for (i = 0; i < size; i++)
- csum8 += buf8[i];
+ if ((cpu_to_be32(buf[0]) & TG3_EEPROM_SB_REVISION_MASK) ==
+ TG3_EEPROM_SB_REVISION_2) {
+ /* For rev 2, the csum doesn't include the MBA. */
+ for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++)
+ csum8 += buf8[i];
+ for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++)
+ csum8 += buf8[i];
+ } else {
+ for (i = 0; i < size; i++)
+ csum8 += buf8[i];
+ }
if (csum8 == 0) {
err = 0;
@@ -9293,7 +9379,7 @@
if (err)
return TG3_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
int i;
u32 status;
@@ -9310,17 +9396,17 @@
if (status != CPMU_MUTEX_GNT_DRIVER)
return TG3_LOOPBACK_FAILED;
- cpmuctrl = tr32(TG3_CPMU_CTRL);
-
/* Turn off power management based on link speed. */
+ cpmuctrl = tr32(TG3_CPMU_CTRL);
tw32(TG3_CPMU_CTRL,
- cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE);
+ cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE |
+ CPMU_CTRL_LINK_AWARE_MODE));
}
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
- if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
+ if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
/* Release the mutex */
@@ -10541,6 +10627,10 @@
tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1)
+ tp->led_ctrl = LED_CTRL_MODE_MAC;
+
if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) {
tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
if ((tp->pdev->subsystem_vendor ==
@@ -10859,7 +10949,7 @@
}
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
- (tp->tg3_flags & TG3_FLG3_ENABLE_APE))
+ (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;
for (offset = TG3_NVM_DIR_START;
@@ -11127,6 +11217,9 @@
pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
if (pcie_cap != 0) {
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+
+ pcie_set_readrq(tp->pdev, 4096);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u16 lnkctl;
@@ -11307,9 +11400,16 @@
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
+ tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
+ tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
+ }
+
/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
* GPIO1 driven high will bring 5700's external PHY out of reset.
* It is also used as eeprom write protect on LOMs.
@@ -12464,43 +12564,6 @@
goto err_out_iounmap;
}
- /*
- * Reset chip in case UNDI or EFI driver did not shutdown
- * DMA self test will enable WDMAC and we'll see (spurious)
- * pending DMA on the PCI bus at that point.
- */
- if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
- (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
- tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
- tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- }
-
- err = tg3_test_dma(tp);
- if (err) {
- printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
- goto err_out_iounmap;
- }
-
- /* Tigon3 can do ipv4 only... and some chips have buggy
- * checksumming.
- */
- if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
- dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
- dev->features |= NETIF_F_IPV6_CSUM;
-
- tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
- } else
- tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
-
- /* flow control autonegotiation is default behavior */
- tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
-
- tg3_init_coal(tp);
-
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX "Cannot find proper PCI device "
@@ -12523,6 +12586,43 @@
tg3_ape_lock_init(tp);
}
+ /*
+ * Reset chip in case UNDI or EFI driver did not shutdown
+ * DMA self test will enable WDMAC and we'll see (spurious)
+ * pending DMA on the PCI bus at that point.
+ */
+ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
+ (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+ tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+ }
+
+ err = tg3_test_dma(tp);
+ if (err) {
+ printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
+ goto err_out_apeunmap;
+ }
+
+ /* Tigon3 can do ipv4 only... and some chips have buggy
+ * checksumming.
+ */
+ if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
+ dev->features |= NETIF_F_IPV6_CSUM;
+
+ tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
+ } else
+ tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
+
+ /* flow control autonegotiation is default behavior */
+ tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+
+ tg3_init_coal(tp);
+
pci_set_drvdata(pdev, dev);
err = register_netdev(dev);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 1d5b2a3..da18fb2 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -109,6 +109,9 @@
#define CHIPREV_ID_5714_A2 0x9002
#define CHIPREV_ID_5906_A1 0xc001
#define CHIPREV_ID_5784_A0 0x5784000
+#define CHIPREV_ID_5784_A1 0x5784001
+#define CHIPREV_ID_5761_A0 0x5761000
+#define CHIPREV_ID_5761_A1 0x5761001
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00
@@ -856,7 +859,31 @@
#define CPMU_CTRL_LINK_IDLE_MODE 0x00000200
#define CPMU_CTRL_LINK_AWARE_MODE 0x00000400
#define CPMU_CTRL_LINK_SPEED_MODE 0x00004000
-/* 0x3604 --> 0x365c unused */
+#define TG3_CPMU_LSPD_10MB_CLK 0x00003604
+#define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000
+#define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000
+/* 0x3608 --> 0x360c unused */
+
+#define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c
+#define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000
+#define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000
+#define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000
+#define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610
+#define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000
+#define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000
+/* 0x3614 --> 0x361c unused */
+
+#define TG3_CPMU_HST_ACC 0x0000361c
+#define CPMU_HST_ACC_MACCLK_MASK 0x001f0000
+#define CPMU_HST_ACC_MACCLK_6_25 0x00130000
+/* 0x3620 --> 0x3630 unused */
+
+#define TG3_CPMU_CLCK_STAT 0x00003630
+#define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000
+#define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000
+#define CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000
+#define CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000
+/* 0x3634 --> 0x365c unused */
#define TG3_CPMU_MUTEX_REQ 0x0000365c
#define CPMU_MUTEX_REQ_DRIVER 0x00001000
@@ -1537,6 +1564,12 @@
#define TG3_EEPROM_MAGIC 0x669955aa
#define TG3_EEPROM_MAGIC_FW 0xa5000000
#define TG3_EEPROM_MAGIC_FW_MSK 0xff000000
+#define TG3_EEPROM_SB_FORMAT_MASK 0x00e00000
+#define TG3_EEPROM_SB_FORMAT_1 0x00200000
+#define TG3_EEPROM_SB_REVISION_MASK 0x001f0000
+#define TG3_EEPROM_SB_REVISION_0 0x00000000
+#define TG3_EEPROM_SB_REVISION_2 0x00020000
+#define TG3_EEPROM_SB_REVISION_3 0x00030000
#define TG3_EEPROM_MAGIC_HW 0xabcd
#define TG3_EEPROM_MAGIC_HW_MSK 0xffff
@@ -1691,6 +1724,12 @@
#define MII_TG3_ISTAT 0x1a /* IRQ status register */
#define MII_TG3_IMASK 0x1b /* IRQ mask register */
+#define MII_TG3_MISC_SHDW 0x1c
+#define MII_TG3_MISC_SHDW_WREN 0x8000
+#define MII_TG3_MISC_SHDW_APD_SEL 0x2800
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
+
/* ISTAT/IMASK event bits */
#define MII_TG3_INT_LINKCHG 0x0002
#define MII_TG3_INT_SPEEDCHG 0x0004
@@ -1747,6 +1786,8 @@
/* APE convenience enumerations. */
#define TG3_APE_LOCK_MEM 4
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+
/* There are two ways to manage the TX descriptors on the tigon3.
* Either the descriptors are in host DMA'able memory, or they
@@ -2352,6 +2393,7 @@
u32 tg3_flags3;
#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
#define TG3_FLG3_ENABLE_APE 0x00000002
+#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
struct timer_list timer;
u16 timer_counter;
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 49d7a29..20ac150 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -24,8 +24,7 @@
will say Y here.) Do read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called de2104x.
config TULIP
@@ -42,8 +41,7 @@
will say Y here.) Do read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called tulip.
config TULIP_MWI
@@ -104,8 +102,7 @@
information is contained in
<file:Documentation/networking/de4x5.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called de4x5.
config WINBOND_840
@@ -129,8 +126,7 @@
(Ethernet) card, say Y. Some information is contained in the file
<file:Documentation/networking/dmfe.txt>.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called dmfe.
config ULI526X
@@ -141,8 +137,7 @@
This driver is for ULi M5261/M5263 10/100M Ethernet Controller
(<http://www.uli.com.tw/>).
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called uli526x.
config PCMCIA_XIRCOM
@@ -154,8 +149,7 @@
as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
ASIX.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called xircom_cb. If unsure, say N.
config PCMCIA_XIRTULIP
@@ -168,8 +162,7 @@
as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and
ASIX.
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module will
+ To compile this driver as a module, choose M here. The module will
be called xircom_tulip_cb. If unsure, say N.
endif # NET_TULIP
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index e396c9d..a75be57 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -146,6 +146,7 @@
struct scatterlist sg[1+MAX_SKB_FRAGS];
int num, err;
+ sg_init_table(sg, 1+MAX_SKB_FRAGS);
for (;;) {
skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
if (unlikely(!skb))
@@ -231,6 +232,8 @@
const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
DECLARE_MAC_BUF(mac);
+ sg_init_table(sg, 1+MAX_SKB_FRAGS);
+
pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest));
free_old_xmit_skbs(vi);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 4f22a71..ee752f1 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -4850,7 +4850,7 @@
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared */
IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
- goto none;
+ goto unplugged;
}
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -4858,6 +4858,7 @@
/* iwl_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
+unplugged:
spin_unlock(&priv->lock);
return IRQ_HANDLED;
@@ -8354,6 +8355,8 @@
}
SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->rate_control_algorithm = "iwl-3945-rs";
+
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index d60adcb..6757c6c 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -8955,6 +8955,8 @@
}
SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->rate_control_algorithm = "iwl-4965-rs";
+
IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index a83c3db..c93d3d2 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -64,6 +64,8 @@
b->head_pos = 0;
b->sample_received = 0;
b->sample_lost_overflow = 0;
+ b->backtrace_aborted = 0;
+ b->sample_invalid_eip = 0;
b->cpu = i;
INIT_DELAYED_WORK(&b->work, wq_sync_buffer);
}
@@ -175,6 +177,11 @@
cpu_buf->sample_received++;
+ if (pc == ESCAPE_CODE) {
+ cpu_buf->sample_invalid_eip++;
+ return 0;
+ }
+
if (nr_available_slots(cpu_buf) < 3) {
cpu_buf->sample_lost_overflow++;
return 0;
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
index 49900d9..c66c025 100644
--- a/drivers/oprofile/cpu_buffer.h
+++ b/drivers/oprofile/cpu_buffer.h
@@ -42,6 +42,7 @@
unsigned long sample_received;
unsigned long sample_lost_overflow;
unsigned long backtrace_aborted;
+ unsigned long sample_invalid_eip;
int cpu;
struct delayed_work work;
} ____cacheline_aligned;
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index f0acb66..d1f6d77 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -26,6 +26,8 @@
cpu_buf = &cpu_buffer[i];
cpu_buf->sample_received = 0;
cpu_buf->sample_lost_overflow = 0;
+ cpu_buf->backtrace_aborted = 0;
+ cpu_buf->sample_invalid_eip = 0;
}
atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
@@ -61,6 +63,8 @@
&cpu_buf->sample_lost_overflow);
oprofilefs_create_ro_ulong(sb, cpudir, "backtrace_aborted",
&cpu_buf->backtrace_aborted);
+ oprofilefs_create_ro_ulong(sb, cpudir, "sample_invalid_eip",
+ &cpu_buf->sample_invalid_eip);
}
oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index cbde770..e5cdc02 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -36,7 +36,9 @@
help
The RTC device that will be used to (re)initialize the system
clock, usually rtc0. Initialization is done when the system
- starts up, and when it resumes from a low power state.
+ starts up, and when it resumes from a low power state. This
+ device should record time in UTC, since the kernel won't do
+ timezone correction.
The driver for this RTC device must be loaded before late_initcall
functions run, so it must usually be statically linked.
@@ -133,8 +135,8 @@
The first seven registers on these chips hold an RTC, and other
registers may add features such as NVRAM, a trickle charger for
- the RTC/NVRAM backup power, and alarms. This driver may not
- expose all those available chip features.
+ the RTC/NVRAM backup power, and alarms. NVRAM is visible in
+ sysfs, but other chip features may not be available.
This driver can also be built as a module. If so, the module
will be called rtc-ds1307.
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index 1785272..33c0e98 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -47,8 +47,8 @@
do_settimeofday(&tv);
dev_info(rtc->dev.parent,
- "setting the system clock to "
- "%d-%02d-%02d %02d:%02d:%02d (%u)\n",
+ "setting system clock to "
+ "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
(unsigned int) tv.tv_sec);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index db6f3f0..bc1c7fe 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -89,6 +89,7 @@
struct ds1307 {
u8 reg_addr;
+ bool has_nvram;
u8 regs[8];
enum ds_type type;
struct i2c_msg msg[2];
@@ -242,6 +243,87 @@
.set_time = ds1307_set_time,
};
+/*----------------------------------------------------------------------*/
+
+#define NVRAM_SIZE 56
+
+static ssize_t
+ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client;
+ struct ds1307 *ds1307;
+ struct i2c_msg msg[2];
+ int result;
+
+ client = to_i2c_client(container_of(kobj, struct device, kobj));
+ ds1307 = i2c_get_clientdata(client);
+
+ if (unlikely(off >= NVRAM_SIZE))
+ return 0;
+ if ((off + count) > NVRAM_SIZE)
+ count = NVRAM_SIZE - off;
+ if (unlikely(!count))
+ return count;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = buf;
+
+ buf[0] = 8 + off;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = count;
+ msg[1].buf = buf;
+
+ result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2);
+ if (result != 2) {
+ dev_err(&client->dev, "%s error %d\n", "nvram read", result);
+ return -EIO;
+ }
+ return count;
+}
+
+static ssize_t
+ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client;
+ u8 buffer[NVRAM_SIZE + 1];
+ int ret;
+
+ client = to_i2c_client(container_of(kobj, struct device, kobj));
+
+ if (unlikely(off >= NVRAM_SIZE))
+ return -EFBIG;
+ if ((off + count) > NVRAM_SIZE)
+ count = NVRAM_SIZE - off;
+ if (unlikely(!count))
+ return count;
+
+ buffer[0] = 8 + off;
+ memcpy(buffer + 1, buf, count);
+
+ ret = i2c_master_send(client, buffer, count + 1);
+ return (ret < 0) ? ret : (ret - 1);
+}
+
+static struct bin_attribute nvram = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+
+ .read = ds1307_nvram_read,
+ .write = ds1307_nvram_write,
+ .size = NVRAM_SIZE,
+};
+
+/*----------------------------------------------------------------------*/
+
static struct i2c_driver ds1307_driver;
static int __devinit ds1307_probe(struct i2c_client *client)
@@ -413,6 +495,14 @@
goto exit_free;
}
+ if (chip->nvram56) {
+ err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
+ if (err == 0) {
+ ds1307->has_nvram = true;
+ dev_info(&client->dev, "56 bytes nvram\n");
+ }
+ }
+
return 0;
exit_bad:
@@ -432,6 +522,9 @@
{
struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ if (ds1307->has_nvram)
+ sysfs_remove_bin_file(&client->dev.kobj, &nvram);
+
rtc_device_unregister(ds1307->rtc);
kfree(ds1307);
return 0;
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index bb53c09..d9e848d 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -291,7 +291,7 @@
static struct bin_attribute ds1553_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
},
.size = RTC_OFFSET,
.read = ds1553_nvram_read,
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index c535b78..2e73f0b 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -160,10 +160,13 @@
static struct bin_attribute ds1742_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
},
.read = ds1742_nvram_read,
.write = ds1742_nvram_write,
+ /* REVISIT: size in sysfs won't match actual size... if it's
+ * not a constant, each RTC should have its own attribute.
+ */
};
static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 2bad163..cd0bbc0 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -353,11 +353,12 @@
static struct bin_attribute m48t59_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.read = m48t59_nvram_read,
.write = m48t59_nvram_write,
+ .size = M48T59_NVRAM_SIZE,
};
static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 8288b6b..a265da7 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -291,7 +291,7 @@
static struct bin_attribute stk17ta8_nvram_attr = {
.attr = {
.name = "nvram",
- .mode = S_IRUGO | S_IWUGO,
+ .mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},
.size = RTC_OFFSET,
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
index 5b0932f..06509bf 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -377,7 +377,7 @@
#define FLASH_RESET 0xF0
-#define FLASH_SIZE 0x200000
+#define ASD_FLASH_SIZE 0x200000
#define FLASH_DIR_COOKIE "*** ADAPTEC FLASH DIRECTORY *** "
#define FLASH_NEXT_ENTRY_OFFS 0x2000
#define FLASH_MAX_DIR_ENTRIES 32
@@ -609,7 +609,7 @@
struct asd_flash_dir *flash_dir)
{
u32 v;
- for (v = 0; v < FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
+ for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
asd_read_flash_seg(asd_ha, flash_dir, v,
sizeof(FLASH_DIR_COOKIE)-1);
if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE,
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index 926f58a..1de098e 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -69,6 +69,8 @@
{ "CTL3001", 0 },
/* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
{ "CTL3011", 0 },
+ /* Davicom ISA 33.6K Modem */
+ { "DAV0336", 0 },
/* Creative */
/* Creative Modem Blaster Flash56 DI5601-1 */
{ "DMB1032", 0 },
@@ -345,6 +347,11 @@
/* Fujitsu Wacom Tablet PC devices */
{ "FUJ02E5", 0 },
{ "FUJ02E6", 0 },
+ /*
+ * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in
+ * disguise)
+ */
+ { "LTS0001", 0 },
/* Rockwell's (PORALiNK) 33600 INT PNP */
{ "WCI0003", 0 },
/* Unkown PnP modems */
@@ -432,7 +439,8 @@
}
memset(&port, 0, sizeof(struct uart_port));
- port.irq = pnp_irq(dev, 0);
+ if (pnp_irq_valid(dev, 0))
+ port.irq = pnp_irq(dev, 0);
if (pnp_port_valid(dev, 0)) {
port.iobase = pnp_port_start(dev, 0);
port.iotype = UPIO_PORT;
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 4d6b3c5..111da57 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -204,8 +204,6 @@
*/
static void atmel_stop_tx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IDR(port, ATMEL_US_TXRDY);
}
@@ -214,8 +212,6 @@
*/
static void atmel_start_tx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IER(port, ATMEL_US_TXRDY);
}
@@ -224,8 +220,6 @@
*/
static void atmel_stop_rx(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
UART_PUT_IDR(port, ATMEL_US_RXRDY);
}
@@ -409,7 +403,6 @@
*/
static int atmel_startup(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
int retval;
/*
@@ -456,8 +449,6 @@
*/
static void atmel_shutdown(struct uart_port *port)
{
- struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
-
/*
* Disable all interrupts, port and break condition.
*/
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index f523cdf..a4e23cf 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -1,426 +1,10 @@
-/* $Id: serial.c,v 1.25 2004/09/29 10:33:49 starvik Exp $
- *
+/*
* Serial port driver for the ETRAX 100LX chip
*
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Axis Communications AB
+ * Copyright (C) 1998-2007 Axis Communications AB
*
* Many, many authors. Based once upon a time on serial.c for 16x50.
*
- * $Log: serial.c,v $
- * Revision 1.25 2004/09/29 10:33:49 starvik
- * Resolved a dealock when printing debug from kernel.
- *
- * Revision 1.24 2004/08/27 23:25:59 johana
- * rs_set_termios() must call change_speed() if c_iflag has changed or
- * automatic XOFF handling will be enabled and transmitter will stop
- * if 0x13 is received.
- *
- * Revision 1.23 2004/08/24 06:57:13 starvik
- * More whitespace cleanup
- *
- * Revision 1.22 2004/08/24 06:12:20 starvik
- * Whitespace cleanup
- *
- * Revision 1.20 2004/05/24 12:00:20 starvik
- * Big merge of stuff from Linux 2.4 (e.g. manual mode for the serial port).
- *
- * Revision 1.19 2004/05/17 13:12:15 starvik
- * Kernel console hook
- * Big merge from Linux 2.4 still pending.
- *
- * Revision 1.18 2003/10/28 07:18:30 starvik
- * Compiles with debug info
- *
- * Revision 1.17 2003/07/04 08:27:37 starvik
- * Merge of Linux 2.5.74
- *
- * Revision 1.16 2003/06/13 10:05:19 johana
- * Help the user to avoid trouble by:
- * Forcing mixed mode for status/control lines if not all pins are used.
- *
- * Revision 1.15 2003/06/13 09:43:01 johana
- * Merged in the following changes from os/linux/arch/cris/drivers/serial.c
- * + some minor changes to reduce diff.
- *
- * Revision 1.49 2003/05/30 11:31:54 johana
- * Merged in change-branch--serial9bit that adds CMSPAR support for sticky
- * parity (mark/space)
- *
- * Revision 1.48 2003/05/30 11:03:57 johana
- * Implemented rs_send_xchar() by disabling the DMA and writing manually.
- * Added e100_disable_txdma_channel() and e100_enable_txdma_channel().
- * Fixed rs_throttle() and rs_unthrottle() to properly call rs_send_xchar
- * instead of setting info->x_char and check the CRTSCTS flag before
- * controlling the rts pin.
- *
- * Revision 1.14 2003/04/09 08:12:44 pkj
- * Corrected typo changes made upstream.
- *
- * Revision 1.13 2003/04/09 05:20:47 starvik
- * Merge of Linux 2.5.67
- *
- * Revision 1.11 2003/01/22 06:48:37 starvik
- * Fixed warnings issued by GCC 3.2.1
- *
- * Revision 1.9 2002/12/13 09:07:47 starvik
- * Alert user that RX_TIMEOUT_TICKS==0 doesn't work
- *
- * Revision 1.8 2002/12/11 13:13:57 starvik
- * Added arch/ to v10 specific includes
- * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer)
- *
- * Revision 1.7 2002/12/06 07:13:57 starvik
- * Corrected work queue stuff
- * Removed CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- *
- * Revision 1.6 2002/11/21 07:17:46 starvik
- * Change static inline to extern inline where otherwise outlined with gcc-3.2
- *
- * Revision 1.5 2002/11/14 15:59:49 starvik
- * Linux 2.5 port of the latest serial driver from 2.4. The work queue stuff
- * probably doesn't work yet.
- *
- * Revision 1.42 2002/11/05 09:08:47 johana
- * Better implementation of rs_stop() and rs_start() that uses the XOFF
- * register to start/stop transmission.
- * change_speed() also initilises XOFF register correctly so that
- * auto_xoff is enabled when IXON flag is set by user.
- * This gives fast XOFF response times.
- *
- * Revision 1.41 2002/11/04 18:40:57 johana
- * Implemented rs_stop() and rs_start().
- * Simple tests using hwtestserial indicates that this should be enough
- * to make it work.
- *
- * Revision 1.40 2002/10/14 05:33:18 starvik
- * RS-485 uses fast timers even if SERIAL_FAST_TIMER is disabled
- *
- * Revision 1.39 2002/09/30 21:00:57 johana
- * Support for CONFIG_ETRAX_SERx_DTR_RI_DSR_CD_MIXED where the status and
- * control pins can be mixed between PA and PB.
- * If no serial port uses MIXED old solution is used
- * (saves a few bytes and cycles).
- * control_pins struct uses masks instead of bit numbers.
- * Corrected dummy values and polarity in line_info() so
- * /proc/tty/driver/serial is now correct.
- * (the E100_xxx_GET() macros is really active low - perhaps not obvious)
- *
- * Revision 1.38 2002/08/23 11:01:36 starvik
- * Check that serial port is enabled in all interrupt handlers to avoid
- * restarts of DMA channels not assigned to serial ports
- *
- * Revision 1.37 2002/08/13 13:02:37 bjornw
- * Removed some warnings because of unused code
- *
- * Revision 1.36 2002/08/08 12:50:01 starvik
- * Serial interrupt is shared with synchronous serial port driver
- *
- * Revision 1.35 2002/06/03 10:40:49 starvik
- * Increased RS-485 RTS toggle timer to 2 characters
- *
- * Revision 1.34 2002/05/28 18:59:36 johana
- * Whitespace and comment fixing to be more like etrax100ser.c 1.71.
- *
- * Revision 1.33 2002/05/28 17:55:43 johana
- * RS-485 uses FAST_TIMER if enabled, and starts a short (one char time)
- * timer from tranismit_chars (interrupt context).
- * The timer toggles RTS in interrupt context when expired giving minimum
- * latencies.
- *
- * Revision 1.32 2002/05/22 13:58:00 johana
- * Renamed rs_write() to raw_write() and made it inline.
- * New rs_write() handles RS-485 if configured and enabled
- * (moved code from e100_write_rs485()).
- * RS-485 ioctl's uses copy_from_user() instead of verify_area().
- *
- * Revision 1.31 2002/04/22 11:20:03 johana
- * Updated copyright years.
- *
- * Revision 1.30 2002/04/22 09:39:12 johana
- * RS-485 support compiles.
- *
- * Revision 1.29 2002/01/14 16:10:01 pkj
- * Allocate the receive buffers dynamically. The static 4kB buffer was
- * too small for the peaks. This means that we can get rid of the extra
- * buffer and the copying to it. It also means we require less memory
- * under normal operations, but can use more when needed (there is a
- * cap at 64kB for safety reasons). If there is no memory available
- * we panic(), and die a horrible death...
- *
- * Revision 1.28 2001/12/18 15:04:53 johana
- * Cleaned up write_rs485() - now it works correctly without padding extra
- * char.
- * Added sane default initialisation of rs485.
- * Added #ifdef around dummy variables.
- *
- * Revision 1.27 2001/11/29 17:00:41 pkj
- * 2kB seems to be too small a buffer when using 921600 bps,
- * so increase it to 4kB (this was already done for the elinux
- * version of the serial driver).
- *
- * Revision 1.26 2001/11/19 14:20:41 pkj
- * Minor changes to comments and unused code.
- *
- * Revision 1.25 2001/11/12 20:03:43 pkj
- * Fixed compiler warnings.
- *
- * Revision 1.24 2001/11/12 15:10:05 pkj
- * Total redesign of the receiving part of the serial driver.
- * Uses eight chained descriptors to write to a 4kB buffer.
- * This data is then serialised into a 2kB buffer. From there it
- * is copied into the TTY's flip buffers when they become available.
- * A lot of copying, and the sizes of the buffers might need to be
- * tweaked, but all in all it should work better than the previous
- * version, without the need to modify the TTY code in any way.
- * Also note that erroneous bytes are now correctly marked in the
- * flag buffers (instead of always marking the first byte).
- *
- * Revision 1.23 2001/10/30 17:53:26 pkj
- * * Set info->uses_dma to 0 when a port is closed.
- * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT).
- * * Call start_flush_timer() in start_receive() if
- * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined.
- *
- * Revision 1.22 2001/10/30 17:44:03 pkj
- * Use %lu for received and transmitted counters in line_info().
- *
- * Revision 1.21 2001/10/30 17:40:34 pkj
- * Clean-up. The only change to functionality is that
- * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of
- * MAX_FLUSH_TIME(=8).
- *
- * Revision 1.20 2001/10/30 15:24:49 johana
- * Added char_time stuff from 2.0 driver.
- *
- * Revision 1.19 2001/10/30 15:23:03 johana
- * Merged with 1.13.2 branch + fixed indentation
- * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ
- *
- * Revision 1.18 2001/09/24 09:27:22 pkj
- * Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud().
- *
- * Revision 1.17 2001/08/24 11:32:49 ronny
- * More fixes for the CONFIG_ETRAX_SERIAL_PORT0 define.
- *
- * Revision 1.16 2001/08/24 07:56:22 ronny
- * Added config ifdefs around ser0 irq requests.
- *
- * Revision 1.15 2001/08/16 09:10:31 bjarne
- * serial.c - corrected the initialization of rs_table, the wrong defines
- * where used.
- * Corrected a test in timed_flush_handler.
- * Changed configured to enabled.
- * serial.h - Changed configured to enabled.
- *
- * Revision 1.14 2001/08/15 07:31:23 bjarne
- * Introduced two new members to the e100_serial struct.
- * configured - Will be set to 1 if the port has been configured in .config
- * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set
- * to 1
- * when a port is opened. This is used to limit the DMA interrupt
- * routines to only manipulate DMA channels actually used by the
- * serial driver.
- *
- * Revision 1.13.2.2 2001/10/17 13:57:13 starvik
- * Receiver was broken by the break fixes
- *
- * Revision 1.13.2.1 2001/07/20 13:57:39 ronny
- * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff
- * like break handling.
- *
- * Revision 1.13 2001/05/09 12:40:31 johana
- * Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h
- *
- * Revision 1.12 2001/04/19 12:23:07 bjornw
- * CONFIG_RS485 -> CONFIG_ETRAX_RS485
- *
- * Revision 1.11 2001/04/05 14:29:48 markusl
- * Updated according to review remarks i.e.
- * -Use correct types in port structure to avoid compiler warnings
- * -Try to use IO_* macros whenever possible
- * -Open should never return -EBUSY
- *
- * Revision 1.10 2001/03/05 13:14:07 bjornw
- * Another spelling fix
- *
- * Revision 1.9 2001/02/23 13:46:38 bjornw
- * Spellling check
- *
- * Revision 1.8 2001/01/23 14:56:35 markusl
- * Made use of ser1 optional
- * Needed by USB
- *
- * Revision 1.7 2001/01/19 16:14:48 perf
- * Added kernel options for serial ports 234.
- * Changed option names from CONFIG_ETRAX100_XYZ to CONFIG_ETRAX_XYZ.
- *
- * Revision 1.6 2000/11/22 16:36:09 bjornw
- * Please marketing by using the correct case when spelling Etrax.
- *
- * Revision 1.5 2000/11/21 16:43:37 bjornw
- * Fixed so it compiles under CONFIG_SVINTO_SIM
- *
- * Revision 1.4 2000/11/15 17:34:12 bjornw
- * Added a timeout timer for flushing input channels. The interrupt-based
- * fast flush system should be easy to merge with this later (works the same
- * way, only with an irq instead of a system timer_list)
- *
- * Revision 1.3 2000/11/13 17:19:57 bjornw
- * * Incredibly, this almost complete rewrite of serial.c worked (at least
- * for output) the first time.
- *
- * Items worth noticing:
- *
- * No Etrax100 port 1 workarounds (does only compile on 2.4 anyway now)
- * RS485 is not ported (why can't it be done in userspace as on x86 ?)
- * Statistics done through async_icount - if any more stats are needed,
- * that's the place to put them or in an arch-dep version of it.
- * timeout_interrupt and the other fast timeout stuff not ported yet
- * There be dragons in this 3k+ line driver
- *
- * Revision 1.2 2000/11/10 16:50:28 bjornw
- * First shot at a 2.4 port, does not compile totally yet
- *
- * Revision 1.1 2000/11/10 16:47:32 bjornw
- * Added verbatim copy of rev 1.49 etrax100ser.c from elinux
- *
- * Revision 1.49 2000/10/30 15:47:14 tobiasa
- * Changed version number.
- *
- * Revision 1.48 2000/10/25 11:02:43 johana
- * Changed %ul to %lu in printf's
- *
- * Revision 1.47 2000/10/18 15:06:53 pkj
- * Compile correctly with CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST and
- * CONFIG_ETRAX_SERIAL_PROC_ENTRY together.
- * Some clean-up of the /proc/serial file.
- *
- * Revision 1.46 2000/10/16 12:59:40 johana
- * Added CONFIG_ETRAX_SERIAL_PROC_ENTRY for statistics and debug info.
- *
- * Revision 1.45 2000/10/13 17:10:59 pkj
- * Do not flush DMAs while flipping TTY buffers.
- *
- * Revision 1.44 2000/10/13 16:34:29 pkj
- * Added a delay in ser_interrupt() for 2.3ms when an error is detected.
- * We do not know why this delay is required yet, but without it the
- * irmaflash program does not work (this was the program that needed
- * the ser_interrupt() to be needed in the first place). This should not
- * affect normal use of the serial ports.
- *
- * Revision 1.43 2000/10/13 16:30:44 pkj
- * New version of the fast flush of serial buffers code. This time
- * it is localized to the serial driver and uses a fast timer to
- * do the work.
- *
- * Revision 1.42 2000/10/13 14:54:26 bennyo
- * Fix for switching RTS when using rs485
- *
- * Revision 1.41 2000/10/12 11:43:44 pkj
- * Cleaned up a number of comments.
- *
- * Revision 1.40 2000/10/10 11:58:39 johana
- * Made RS485 support generic for all ports.
- * Toggle rts in interrupt if no delay wanted.
- * WARNING: No true transmitter empty check??
- * Set d_wait bit when sending data so interrupt is delayed until
- * fifo flushed. (Fix tcdrain() problem)
- *
- * Revision 1.39 2000/10/04 16:08:02 bjornw
- * * Use virt_to_phys etc. for DMA addresses
- * * Removed CONFIG_FLUSH_DMA_FAST hacks
- * * Indentation fix
- *
- * Revision 1.38 2000/10/02 12:27:10 mattias
- * * added variable used when using fast flush on serial dma.
- * (CONFIG_FLUSH_DMA_FAST)
- *
- * Revision 1.37 2000/09/27 09:44:24 pkj
- * Uncomment definition of SERIAL_HANDLE_EARLY_ERRORS.
- *
- * Revision 1.36 2000/09/20 13:12:52 johana
- * Support for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS:
- * Number of timer ticks between flush of receive fifo (1 tick = 10ms).
- * Try 0-3 for low latency applications. Approx 5 for high load
- * applications (e.g. PPP). Maybe this should be more adaptive some day...
- *
- * Revision 1.35 2000/09/20 10:36:08 johana
- * Typo in get_lsr_info()
- *
- * Revision 1.34 2000/09/20 10:29:59 johana
- * Let rs_chars_in_buffer() check fifo content as well.
- * get_lsr_info() might work now (not tested).
- * Easier to change the port to debug.
- *
- * Revision 1.33 2000/09/13 07:52:11 torbjore
- * Support RS485
- *
- * Revision 1.32 2000/08/31 14:45:37 bjornw
- * After sending a break we need to reset the transmit DMA channel
- *
- * Revision 1.31 2000/06/21 12:13:29 johana
- * Fixed wait for all chars sent when closing port.
- * (Used to always take 1 second!)
- * Added shadows for directions of status/ctrl signals.
- *
- * Revision 1.30 2000/05/29 16:27:55 bjornw
- * Simulator ifdef moved a bit
- *
- * Revision 1.29 2000/05/09 09:40:30 mattias
- * * Added description of dma registers used in timeout_interrupt
- * * Removed old code
- *
- * Revision 1.28 2000/05/08 16:38:58 mattias
- * * Bugfix for flushing fifo in timeout_interrupt
- * Problem occurs when bluetooth stack waits for a small number of bytes
- * containing an event acknowledging free buffers in bluetooth HW
- * As before, data was stuck in fifo until more data came on uart and
- * flushed it up to the stack.
- *
- * Revision 1.27 2000/05/02 09:52:28 jonasd
- * Added fix for peculiar etrax behaviour when eop is forced on an empty
- * fifo. This is used when flashing the IRMA chip. Disabled by default.
- *
- * Revision 1.26 2000/03/29 15:32:02 bjornw
- * 2.0.34 updates
- *
- * Revision 1.25 2000/02/16 16:59:36 bjornw
- * * Receive DMA directly into the flip-buffer, eliminating an intermediary
- * receive buffer and a memcpy. Will avoid some overruns.
- * * Error message on debug port if an overrun or flip buffer overrun occurs.
- * * Just use the first byte in the flag flip buffer for errors.
- * * Check for timeout on the serial ports only each 5/100 s, not 1/100.
- *
- * Revision 1.24 2000/02/09 18:02:28 bjornw
- * * Clear serial errors (overrun, framing, parity) correctly. Before, the
- * receiver would get stuck if an error occurred and we did not restart
- * the input DMA.
- * * Cosmetics (indentation, some code made into inlines)
- * * Some more debug options
- * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop)
- * when the last open is closed. Corresponding fixes in startup().
- * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed
- * and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that)
- * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS
- *
- * Revision 1.23 2000/01/24 17:46:19 johana
- * Wait for flush of DMA/FIFO when closing port.
- *
- * Revision 1.22 2000/01/20 18:10:23 johana
- * Added TIOCMGET ioctl to return modem status.
- * Implemented modem status/control that works with the extra signals
- * (DTR, DSR, RI,CD) as well.
- * 3 different modes supported:
- * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy)
- * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when
- * closing the last filehandle, NASTY!.
- * Added break generation, not tested though!
- * Use IRQF_SHARED when request_irq() for ser2 and ser3 (shared with) par0 and par1.
- * You can't use them at the same time (yet..), but you can hopefully switch
- * between ser2/par0, ser3/par1 with the same kernel config.
- * Replaced some magic constants with defines
- *
- *
*/
static char *serial_version = "$Revision: 1.25 $";
@@ -446,6 +30,7 @@
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/dma.h>
#include <asm/system.h>
#include <linux/delay.h>
@@ -454,8 +39,9 @@
/* non-arch dependent serial structures are in linux/serial.h */
#include <linux/serial.h>
/* while we keep our own stuff (struct e100_serial) in a local .h file */
-#include "serial.h"
+#include "crisv10.h"
#include <asm/fasttimer.h>
+#include <asm/arch/io_interface_mux.h>
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
#ifndef CONFIG_ETRAX_FAST_TIMER
@@ -504,18 +90,6 @@
from eLinux */
#define SERIAL_HANDLE_EARLY_ERRORS
-/* Defined and used in n_tty.c, but we need it here as well */
-#define TTY_THRESHOLD_THROTTLE 128
-
-/* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE
- * must not be to high or flow control won't work if we leave it to the tty
- * layer so we have our own throttling in flush_to_flip
- * TTY_FLIPBUF_SIZE=512,
- * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128
- * BUF_SIZE can't be > 128
- */
-#define CRIS_BUF_SIZE 512
-
/* Currently 16 descriptors x 128 bytes = 2048 bytes */
#define SERIAL_DESCR_BUF_SIZE 256
@@ -588,13 +162,13 @@
static void change_speed(struct e100_serial *info);
static void rs_throttle(struct tty_struct * tty);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-static int rs_write(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count);
+static int rs_write(struct tty_struct *tty,
+ const unsigned char *buf, int count);
#ifdef CONFIG_ETRAX_RS485
-static int e100_write_rs485(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count);
+static int e100_write_rs485(struct tty_struct *tty,
+ const unsigned char *buf, int count);
#endif
-static int get_lsr_info(struct e100_serial * info, unsigned int *value);
+static int get_lsr_info(struct e100_serial *info, unsigned int *value);
#define DEF_BAUD 115200 /* 115.2 kbit/s */
@@ -679,20 +253,39 @@
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 2,
+ .dma_owner = dma_ser0,
+ .io_if = if_serial_0,
#ifdef CONFIG_ETRAX_SERIAL_PORT0
.enabled = 1,
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER0_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 0 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER0_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 0 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -714,20 +307,42 @@
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 3,
+ .dma_owner = dma_ser1,
+ .io_if = if_serial_1,
#ifdef CONFIG_ETRAX_SERIAL_PORT1
.enabled = 1,
+ .io_if_description = "ser1",
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER1_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 1 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER1_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 1 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
+ .dma_in_irq_nbr = 0,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -748,20 +363,40 @@
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 0,
+ .dma_owner = dma_ser2,
+ .io_if = if_serial_2,
#ifdef CONFIG_ETRAX_SERIAL_PORT2
.enabled = 1,
+ .io_if_description = "ser2",
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER2_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 2 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER2_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 2 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL,
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -782,20 +417,40 @@
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 1,
+ .dma_owner = dma_ser3,
+ .io_if = if_serial_3,
#ifdef CONFIG_ETRAX_SERIAL_PORT3
.enabled = 1,
+ .io_if_description = "ser3",
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
.dma_out_enabled = 1,
+ .dma_out_nbr = SER3_TX_DMA_NBR,
+ .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR,
+ .dma_out_irq_flags = IRQF_DISABLED,
+ .dma_out_irq_description = "serial 3 dma tr",
#else
.dma_out_enabled = 0,
+ .dma_out_nbr = UINT_MAX,
+ .dma_out_irq_nbr = 0,
+ .dma_out_irq_flags = 0,
+ .dma_out_irq_description = NULL,
#endif
#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
.dma_in_enabled = 1,
+ .dma_in_nbr = SER3_RX_DMA_NBR,
+ .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR,
+ .dma_in_irq_flags = IRQF_DISABLED,
+ .dma_in_irq_description = "serial 3 dma rec",
#else
- .dma_in_enabled = 0
+ .dma_in_enabled = 0,
+ .dma_in_nbr = UINT_MAX,
+ .dma_in_irq_nbr = 0,
+ .dma_in_irq_flags = 0,
+ .dma_in_irq_description = NULL
#endif
#else
.enabled = 0,
+ .io_if_description = NULL,
.dma_out_enabled = 0,
.dma_in_enabled = 0
#endif
@@ -1416,12 +1071,11 @@
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].dtr_shadow &= ~mask;
*e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#ifdef SERIAL_DEBUG_IO
@@ -1440,12 +1094,11 @@
{
#ifndef CONFIG_SVINTO_SIM
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
info->rx_ctrl &= ~E100_RTS_MASK;
info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */
info->port[REG_REC_CTRL] = info->rx_ctrl;
- restore_flags(flags);
+ local_irq_restore(flags);
#ifdef SERIAL_DEBUG_IO
printk("ser%i rts %i\n", info->line, set);
#endif
@@ -1463,12 +1116,11 @@
unsigned char mask = e100_modem_pins[info->line].ri_mask;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].ri_shadow &= ~mask;
*e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#endif
}
@@ -1481,12 +1133,11 @@
unsigned char mask = e100_modem_pins[info->line].cd_mask;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
*e100_modem_pins[info->line].cd_shadow &= ~mask;
*e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask);
*e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#endif
}
@@ -1560,8 +1211,7 @@
/* Disable output DMA channel for the serial port in question
* ( set to something other then serialX)
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line));
if (info->line == 0) {
if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) ==
@@ -1589,7 +1239,7 @@
}
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1597,8 +1247,7 @@
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line));
/* Enable output DMA channel for the serial port in question */
if (info->line == 0) {
@@ -1615,7 +1264,7 @@
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3);
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void e100_disable_rxdma_channel(struct e100_serial *info)
@@ -1625,8 +1274,7 @@
/* Disable input DMA channel for the serial port in question
* ( set to something other then serialX)
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (info->line == 0) {
if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) ==
IO_STATE(R_GEN_CONFIG, dma7, serial0)) {
@@ -1653,7 +1301,7 @@
}
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1661,8 +1309,7 @@
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Enable input DMA channel for the serial port in question */
if (info->line == 0) {
genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7);
@@ -1678,7 +1325,7 @@
genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3);
}
*R_GEN_CONFIG = genconfig_shadow;
- restore_flags(flags);
+ local_irq_restore(flags);
}
#ifdef SERIAL_HANDLE_EARLY_ERRORS
@@ -1785,7 +1432,7 @@
}
static int
-e100_write_rs485(struct tty_struct *tty, int from_user,
+e100_write_rs485(struct tty_struct *tty,
const unsigned char *buf, int count)
{
struct e100_serial * info = (struct e100_serial *)tty->driver_data;
@@ -1798,7 +1445,7 @@
*/
info->rs485.enabled = 1;
/* rs_write now deals with RS485 if enabled */
- count = rs_write(tty, from_user, buf, count);
+ count = rs_write(tty, buf, count);
info->rs485.enabled = old_enabled;
return count;
}
@@ -1836,7 +1483,7 @@
unsigned long flags;
unsigned long xoff;
- save_flags(flags); cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n",
CIRC_CNT(info->xmit.head,
info->xmit.tail,SERIAL_XMIT_SIZE)));
@@ -1848,7 +1495,7 @@
}
*((unsigned long *)&info->port[REG_XOFF]) = xoff;
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
@@ -1860,7 +1507,7 @@
unsigned long flags;
unsigned long xoff;
- save_flags(flags); cli();
+ local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n",
CIRC_CNT(info->xmit.head,
info->xmit.tail,SERIAL_XMIT_SIZE)));
@@ -1875,7 +1522,7 @@
info->xmit.head != info->xmit.tail && info->xmit.buf)
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
@@ -2055,8 +1702,7 @@
static void flush_timeout_function(unsigned long data);
#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\
unsigned long timer_flags; \
- save_flags(timer_flags); \
- cli(); \
+ local_irq_save(timer_flags); \
if (fast_timers[info->line].function == NULL) { \
serial_fast_timer_started++; \
TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \
@@ -2070,7 +1716,7 @@
else { \
TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \
} \
- restore_flags(timer_flags); \
+ local_irq_restore(timer_flags); \
}
#define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec)
@@ -2099,8 +1745,7 @@
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!info->first_recv_buffer)
info->first_recv_buffer = buffer;
@@ -2113,7 +1758,7 @@
if (info->recv_cnt > info->max_recv_cnt)
info->max_recv_cnt = info->recv_cnt;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static int
@@ -2133,11 +1778,7 @@
info->icount.rx++;
} else {
struct tty_struct *tty = info->tty;
- *tty->flip.char_buf_ptr = data;
- *tty->flip.flag_buf_ptr = flag;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, data, flag);
info->icount.rx++;
}
@@ -2322,7 +1963,6 @@
*/
return;
#endif
- info->tty->flip.count = 0;
if (info->uses_dma_in) {
/* reset the input dma channel to be sure it works */
@@ -2484,32 +2124,20 @@
{
struct tty_struct *tty;
struct etrax_recv_buffer *buffer;
- unsigned int length;
unsigned long flags;
- int max_flip_size;
- if (!info->first_recv_buffer)
- return;
+ local_irq_save(flags);
+ tty = info->tty;
- save_flags(flags);
- cli();
-
- if (!(tty = info->tty)) {
- restore_flags(flags);
+ if (!tty) {
+ local_irq_restore(flags);
return;
}
while ((buffer = info->first_recv_buffer) != NULL) {
unsigned int count = buffer->length;
- count = tty_buffer_request_room(tty, count);
- if (count == 0) /* Throttle ?? */
- break;
-
- if (count > 1)
- tty_insert_flip_strings(tty, buffer->buffer, count - 1);
- tty_insert_flip_char(tty, buffer->buffer[count-1], buffer->error);
-
+ tty_insert_flip_string(tty, buffer->buffer, count);
info->recv_cnt -= count;
if (count == buffer->length) {
@@ -2525,18 +2153,9 @@
if (!info->first_recv_buffer)
info->last_recv_buffer = NULL;
- restore_flags(flags);
+ local_irq_restore(flags);
- DFLIP(
- if (1) {
- DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx);
- DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty));
- DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty));
- }
-
- );
-
- /* this includes a check for low-latency */
+ /* This includes a check for low-latency */
tty_flip_buffer_push(tty);
}
@@ -2679,21 +2298,7 @@
printk("!NO TTY!\n");
return info;
}
- if (tty->flip.count >= CRIS_BUF_SIZE - TTY_THRESHOLD_THROTTLE) {
- /* check TTY_THROTTLED first so it indicates our state */
- if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) {
- DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count));
- rs_throttle(tty);
- }
- }
- if (tty->flip.count >= CRIS_BUF_SIZE) {
- DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count);
- tty->flip.work.func((void *) tty);
- if (tty->flip.count >= CRIS_BUF_SIZE) {
- DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count);
- return info; /* if TTY_DONT_FLIP is set */
- }
- }
+
/* Read data and status at the same time */
data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]);
more_data:
@@ -2746,27 +2351,26 @@
DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt);
info->errorcode = ERRCODE_INSERT_BREAK;
} else {
+ unsigned char data = IO_EXTRACT(R_SERIAL0_READ,
+ data_in, data_read);
+ char flag = TTY_NORMAL;
if (info->errorcode == ERRCODE_INSERT_BREAK) {
- info->icount.brk++;
- *tty->flip.char_buf_ptr = 0;
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ struct tty_struct *tty = info->tty;
+ tty_insert_flip_char(tty, 0, flag);
info->icount.rx++;
}
- *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read);
if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) {
info->icount.parity++;
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) {
info->icount.overrun++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
} else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) {
info->icount.frame++;
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
+ tty_insert_flip_char(tty, data, flag);
info->errorcode = 0;
}
info->break_detected_cnt = 0;
@@ -2782,16 +2386,14 @@
log_int(rdpc(), 0, 0);
}
);
- *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read);
- *tty->flip.flag_buf_ptr = 0;
+ tty_insert_flip_char(tty,
+ IO_EXTRACT(R_SERIAL0_READ, data_in, data_read),
+ TTY_NORMAL);
} else {
DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read);
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
info->icount.rx++;
data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]);
if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) {
@@ -2929,7 +2531,7 @@
if (info->x_char) {
unsigned char rstat;
DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char));
- save_flags(flags); cli();
+ local_irq_save(flags);
rstat = info->port[REG_STATUS];
DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
@@ -2938,7 +2540,7 @@
info->x_char = 0;
/* We must enable since it is disabled in ser_interrupt */
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
if (info->uses_dma_out) {
@@ -2946,7 +2548,7 @@
int i;
/* We only use normal tx interrupt when sending x_char */
DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0));
- save_flags(flags); cli();
+ local_irq_save(flags);
rstat = info->port[REG_STATUS];
DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat));
e100_disable_serial_tx_ready_irq(info);
@@ -2959,7 +2561,7 @@
nop();
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
/* Normal char-by-char interrupt */
@@ -2973,7 +2575,7 @@
}
DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail]));
/* Send a byte, rs485 timing is critical so turn of ints */
- save_flags(flags); cli();
+ local_irq_save(flags);
info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail];
info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1);
info->icount.tx++;
@@ -2997,7 +2599,7 @@
/* We must enable since it is disabled in ser_interrupt */
e100_enable_serial_tx_ready_irq(info);
}
- restore_flags(flags);
+ local_irq_restore(flags);
if (CIRC_CNT(info->xmit.head,
info->xmit.tail,
@@ -3022,7 +2624,7 @@
int handled = 0;
static volatile unsigned long reentered_ready_mask = 0;
- save_flags(flags); cli();
+ local_irq_save(flags);
irq_mask1_rd = *R_IRQ_MASK1_RD;
/* First handle all rx interrupts with ints disabled */
info = rs_table;
@@ -3067,7 +2669,7 @@
/* Unblock the serial interrupt */
*R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set);
- sti();
+ local_irq_enable();
ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */
info = rs_table;
for (i = 0; i < NR_PORTS; i++) {
@@ -3080,11 +2682,11 @@
ready_mask <<= 2;
}
/* handle_ser_tx_interrupt enables tr_ready interrupts */
- cli();
+ local_irq_disable();
/* Handle reentered TX interrupt */
irq_mask1_rd = reentered_ready_mask;
}
- cli();
+ local_irq_disable();
tx_started = 0;
} else {
unsigned long ready_mask;
@@ -3100,7 +2702,7 @@
}
}
- restore_flags(flags);
+ local_irq_restore(flags);
return IRQ_RETVAL(handled);
} /* ser_interrupt */
#endif
@@ -3121,11 +2723,13 @@
* them using rs_sched_event(), and they get done here.
*/
static void
-do_softint(void *private_)
+do_softint(struct work_struct *work)
{
- struct e100_serial *info = (struct e100_serial *) private_;
+ struct e100_serial *info;
struct tty_struct *tty;
+ info = container_of(work, struct e100_serial, work);
+
tty = info->tty;
if (!tty)
return;
@@ -3145,13 +2749,12 @@
if (!xmit_page)
return -ENOMEM;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* if it was already initialized, skip this */
if (info->flags & ASYNC_INITIALIZED) {
- restore_flags(flags);
+ local_irq_restore(flags);
free_page(xmit_page);
return 0;
}
@@ -3277,7 +2880,7 @@
info->flags |= ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -3328,8 +2931,7 @@
info->irq);
#endif
- save_flags(flags);
- cli(); /* Disable interrupts */
+ local_irq_save(flags);
if (info->xmit.buf) {
free_page((unsigned long)info->xmit.buf);
@@ -3353,7 +2955,7 @@
set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -3411,7 +3013,6 @@
DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8));
info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8;
}
- }
#endif
else
{
@@ -3445,8 +3046,7 @@
#ifndef CONFIG_SVINTO_SIM
/* start with default settings and then fill in changes */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* 8 bit, no/even parity */
info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) |
IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) |
@@ -3510,7 +3110,7 @@
}
*((unsigned long *)&info->port[REG_XOFF]) = xoff;
- restore_flags(flags);
+ local_irq_restore(flags);
#endif /* !CONFIG_SVINTO_SIM */
update_char_time(info);
@@ -3538,13 +3138,12 @@
/* this protection might not exactly be necessary here */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
start_transmit(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
-static int rs_raw_write(struct tty_struct * tty, int from_user,
+static int rs_raw_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
int c, ret = 0;
@@ -3567,53 +3166,19 @@
SIMCOUT(buf, count);
return count;
#endif
- save_flags(flags);
+ local_save_flags(flags);
DFLOW(DEBUG_LOG(info->line, "write count %i ", count));
DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty)));
- /* the cli/restore_flags pairs below are needed because the
- * DMA interrupt handler moves the info->xmit values. the memcpy
- * needs to be in the critical region unfortunately, because we
- * need to read xmit values, memcpy, write xmit values in one
- * atomic operation... this could perhaps be avoided by more clever
- * design.
+ /* The local_irq_disable/restore_flags pairs below are needed
+ * because the DMA interrupt handler moves the info->xmit values.
+ * the memcpy needs to be in the critical region unfortunately,
+ * because we need to read xmit values, memcpy, write xmit values
+ * in one atomic operation... this could perhaps be avoided by
+ * more clever design.
*/
- if (from_user) {
- mutex_lock(&tmp_buf_mutex);
- while (1) {
- int c1;
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
- if (count < c)
- c = count;
- if (c <= 0)
- break;
-
- c -= copy_from_user(tmp_buf, buf, c);
- if (!c) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- cli();
- c1 = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
- if (c1 < c)
- c = c1;
- memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
- info->xmit.head = ((info->xmit.head + c) &
- (SERIAL_XMIT_SIZE-1));
- restore_flags(flags);
- buf += c;
- count -= c;
- ret += c;
- }
- mutex_unlock(&tmp_buf_mutex);
- } else {
- cli();
+ local_irq_disable();
while (count) {
c = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail,
@@ -3631,8 +3196,7 @@
count -= c;
ret += c;
}
- restore_flags(flags);
- }
+ local_irq_restore(flags);
/* enable transmitter if not running, unless the tty is stopped
* this does not need IRQ protection since if tr_running == 0
@@ -3651,7 +3215,7 @@
} /* raw_raw_write() */
static int
-rs_write(struct tty_struct * tty, int from_user,
+rs_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
#if defined(CONFIG_ETRAX_RS485)
@@ -3678,7 +3242,7 @@
}
#endif /* CONFIG_ETRAX_RS485 */
- count = rs_raw_write(tty, from_user, buf, count);
+ count = rs_raw_write(tty, buf, count);
#if defined(CONFIG_ETRAX_RS485)
if (info->rs485.enabled)
@@ -3746,10 +3310,9 @@
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
info->xmit.head = info->xmit.tail = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
tty_wakeup(tty);
}
@@ -3767,7 +3330,7 @@
{
struct e100_serial *info = (struct e100_serial *)tty->driver_data;
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->uses_dma_out) {
/* Put the DMA on hold and disable the channel */
*info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold);
@@ -3784,7 +3347,7 @@
DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch));
info->x_char = ch;
e100_enable_serial_tx_ready_irq(info);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -3996,21 +3559,61 @@
}
#endif
-static int
-get_modem_info(struct e100_serial * info, unsigned int *value)
+static void
+rs_break(struct tty_struct *tty, int break_state)
{
- unsigned int result;
- /* Polarity isn't verified */
-#if 0 /*def SERIAL_DEBUG_IO */
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned long flags;
- printk("get_modem_info: RTS: %i DTR: %i CD: %i RI: %i DSR: %i CTS: %i\n",
- E100_RTS_GET(info),
- E100_DTR_GET(info),
- E100_CD_GET(info),
- E100_RI_GET(info),
- E100_DSR_GET(info),
- E100_CTS_GET(info));
-#endif
+ if (!info->port)
+ return;
+
+ local_irq_save(flags);
+ if (break_state == -1) {
+ /* Go to manual mode and set the txd pin to 0 */
+ /* Clear bit 7 (txd) and 6 (tr_enable) */
+ info->tx_ctrl &= 0x3F;
+ } else {
+ /* Set bit 7 (txd) and 6 (tr_enable) */
+ info->tx_ctrl |= (0x80 | 0x40);
+ }
+ info->port[REG_TR_CTRL] = info->tx_ctrl;
+ local_irq_restore(flags);
+}
+
+static int
+rs_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+
+ if (clear & TIOCM_RTS)
+ e100_rts(info, 0);
+ if (clear & TIOCM_DTR)
+ e100_dtr(info, 0);
+ /* Handle FEMALE behaviour */
+ if (clear & TIOCM_RI)
+ e100_ri_out(info, 0);
+ if (clear & TIOCM_CD)
+ e100_cd_out(info, 0);
+
+ if (set & TIOCM_RTS)
+ e100_rts(info, 1);
+ if (set & TIOCM_DTR)
+ e100_dtr(info, 1);
+ /* Handle FEMALE behaviour */
+ if (set & TIOCM_RI)
+ e100_ri_out(info, 1);
+ if (set & TIOCM_CD)
+ e100_cd_out(info, 1);
+ return 0;
+}
+
+static int
+rs_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+ unsigned int result;
result =
(!E100_RTS_GET(info) ? TIOCM_RTS : 0)
@@ -4021,96 +3624,21 @@
| (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
#ifdef SERIAL_DEBUG_IO
- printk("e100ser: modem state: %i 0x%08X\n", result, result);
+ printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n",
+ info->line, result, result);
{
char s[100];
get_control_state_str(result, s);
- printk("state: %s\n", s);
+ printk(KERN_DEBUG "state: %s\n", s);
}
#endif
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
- return 0;
+ return result;
+
}
static int
-set_modem_info(struct e100_serial * info, unsigned int cmd,
- unsigned int *value)
-{
- unsigned int arg;
-
- if (copy_from_user(&arg, value, sizeof(int)))
- return -EFAULT;
-
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS) {
- e100_rts(info, 1);
- }
- if (arg & TIOCM_DTR) {
- e100_dtr(info, 1);
- }
- /* Handle FEMALE behaviour */
- if (arg & TIOCM_RI) {
- e100_ri_out(info, 1);
- }
- if (arg & TIOCM_CD) {
- e100_cd_out(info, 1);
- }
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS) {
- e100_rts(info, 0);
- }
- if (arg & TIOCM_DTR) {
- e100_dtr(info, 0);
- }
- /* Handle FEMALE behaviour */
- if (arg & TIOCM_RI) {
- e100_ri_out(info, 0);
- }
- if (arg & TIOCM_CD) {
- e100_cd_out(info, 0);
- }
- break;
- case TIOCMSET:
- e100_rts(info, arg & TIOCM_RTS);
- e100_dtr(info, arg & TIOCM_DTR);
- /* Handle FEMALE behaviour */
- e100_ri_out(info, arg & TIOCM_RI);
- e100_cd_out(info, arg & TIOCM_CD);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-
-static void
-rs_break(struct tty_struct *tty, int break_state)
-{
- struct e100_serial * info = (struct e100_serial *)tty->driver_data;
- unsigned long flags;
-
- if (!info->port)
- return;
-
- save_flags(flags);
- cli();
- if (break_state == -1) {
- /* Go to manual mode and set the txd pin to 0 */
- info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */
- } else {
- info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */
- }
- info->port[REG_TR_CTRL] = info->tx_ctrl;
- restore_flags(flags);
-}
-
-static int
rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
@@ -4124,49 +3652,45 @@
}
switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
- case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
- case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
+ case TIOCGSERIAL:
+ return get_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSSERIAL:
+ return set_serial_info(info,
+ (struct serial_struct *) arg);
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
- case TIOCSERGSTRUCT:
- if (copy_to_user((struct e100_serial *) arg,
- info, sizeof(struct e100_serial)))
- return -EFAULT;
- return 0;
+ case TIOCSERGSTRUCT:
+ if (copy_to_user((struct e100_serial *) arg,
+ info, sizeof(struct e100_serial)))
+ return -EFAULT;
+ return 0;
#if defined(CONFIG_ETRAX_RS485)
- case TIOCSERSETRS485:
- {
- struct rs485_control rs485ctrl;
- if (copy_from_user(&rs485ctrl, (struct rs485_control*)arg, sizeof(rs485ctrl)))
- return -EFAULT;
+ case TIOCSERSETRS485:
+ {
+ struct rs485_control rs485ctrl;
+ if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg,
+ sizeof(rs485ctrl)))
+ return -EFAULT;
- return e100_enable_rs485(tty, &rs485ctrl);
- }
+ return e100_enable_rs485(tty, &rs485ctrl);
+ }
- case TIOCSERWRRS485:
- {
- struct rs485_write rs485wr;
- if (copy_from_user(&rs485wr, (struct rs485_write*)arg, sizeof(rs485wr)))
- return -EFAULT;
+ case TIOCSERWRRS485:
+ {
+ struct rs485_write rs485wr;
+ if (copy_from_user(&rs485wr, (struct rs485_write *)arg,
+ sizeof(rs485wr)))
+ return -EFAULT;
- return e100_write_rs485(tty, 1, rs485wr.outc, rs485wr.outc_size);
- }
+ return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size);
+ }
#endif
- default:
- return -ENOIOCTLCMD;
+ default:
+ return -ENOIOCTLCMD;
}
return 0;
}
@@ -4191,46 +3715,6 @@
}
-/* In debugport.c - register a console write function that uses the normal
- * serial driver
- */
-typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len);
-
-extern debugport_write_function debug_write_function;
-
-static int rs_debug_write_function(int i, const char *buf, unsigned int len)
-{
- int cnt;
- int written = 0;
- struct tty_struct *tty;
- static int recurse_cnt = 0;
-
- tty = rs_table[i].tty;
- if (tty) {
- unsigned long flags;
- if (recurse_cnt > 5) /* We skip this debug output */
- return 1;
-
- local_irq_save(flags);
- recurse_cnt++;
- local_irq_restore(flags);
- do {
- cnt = rs_write(tty, 0, buf + written, len);
- if (cnt >= 0) {
- written += cnt;
- buf += cnt;
- len -= cnt;
- } else
- len = cnt;
- } while(len > 0);
- local_irq_save(flags);
- recurse_cnt--;
- local_irq_restore(flags);
- return 1;
- }
- return 0;
-}
-
/*
* ------------------------------------------------------------
* rs_close()
@@ -4252,11 +3736,10 @@
/* interrupts are disabled for this entire function */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (tty_hung_up_p(filp)) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -4283,7 +3766,7 @@
info->count = 0;
}
if (info->count) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
info->flags |= ASYNC_CLOSING;
@@ -4337,7 +3820,7 @@
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
+ local_irq_restore(flags);
/* port closed */
@@ -4359,6 +3842,28 @@
#endif
}
#endif
+
+ /*
+ * Release any allocated DMA irq's.
+ */
+ if (info->dma_in_enabled) {
+ free_irq(info->dma_in_irq_nbr, info);
+ cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
+ info->uses_dma_in = 0;
+#ifdef SERIAL_DEBUG_OPEN
+ printk(KERN_DEBUG "DMA irq '%s' freed\n",
+ info->dma_in_irq_description);
+#endif
+ }
+ if (info->dma_out_enabled) {
+ free_irq(info->dma_out_irq_nbr, info);
+ cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
+ info->uses_dma_out = 0;
+#ifdef SERIAL_DEBUG_OPEN
+ printk(KERN_DEBUG "DMA irq '%s' freed\n",
+ info->dma_out_irq_description);
+#endif
+ }
}
/*
@@ -4433,8 +3938,8 @@
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
+ wait_event_interruptible(info->close_wait,
+ !(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
@@ -4472,21 +3977,19 @@
printk("block_til_ready before block: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!tty_hung_up_p(filp)) {
extra_count++;
info->count--;
}
- restore_flags(flags);
+ local_irq_restore(flags);
info->blocked_open++;
while (1) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* assert RTS and DTR */
e100_rts(info, 1);
e100_dtr(info, 1);
- restore_flags(flags);
+ local_irq_restore(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
@@ -4528,6 +4031,19 @@
return 0;
}
+static void
+deinit_port(struct e100_serial *info)
+{
+ if (info->dma_out_enabled) {
+ cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description);
+ free_irq(info->dma_out_irq_nbr, info);
+ }
+ if (info->dma_in_enabled) {
+ cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description);
+ free_irq(info->dma_in_irq_nbr, info);
+ }
+}
+
/*
* This routine is called whenever a serial port is opened.
* It performs the serial-specific initialization for the tty structure.
@@ -4538,9 +4054,9 @@
struct e100_serial *info;
int retval, line;
unsigned long page;
+ int allocated_resources = 0;
/* find which port we want to open */
-
line = tty->index;
if (line < 0 || line >= NR_PORTS)
@@ -4580,8 +4096,8 @@
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
+ wait_event_interruptible(info->close_wait,
+ !(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
@@ -4591,12 +4107,85 @@
}
/*
+ * If DMA is enabled try to allocate the irq's.
+ */
+ if (info->count == 1) {
+ allocated_resources = 1;
+ if (info->dma_in_enabled) {
+ if (request_irq(info->dma_in_irq_nbr,
+ rec_interrupt,
+ info->dma_in_irq_flags,
+ info->dma_in_irq_description,
+ info)) {
+ printk(KERN_WARNING "DMA irq '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_in_irq_description);
+ /* Make sure we never try to use DMA in */
+ /* for the port again. */
+ info->dma_in_enabled = 0;
+ } else if (cris_request_dma(info->dma_in_nbr,
+ info->dma_in_irq_description,
+ DMA_VERBOSE_ON_ERROR,
+ info->dma_owner)) {
+ free_irq(info->dma_in_irq_nbr, info);
+ printk(KERN_WARNING "DMA '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_in_irq_description);
+ /* Make sure we never try to use DMA in */
+ /* for the port again. */
+ info->dma_in_enabled = 0;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ else
+ printk(KERN_DEBUG "DMA irq '%s' allocated\n",
+ info->dma_in_irq_description);
+#endif
+ }
+ if (info->dma_out_enabled) {
+ if (request_irq(info->dma_out_irq_nbr,
+ tr_interrupt,
+ info->dma_out_irq_flags,
+ info->dma_out_irq_description,
+ info)) {
+ printk(KERN_WARNING "DMA irq '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_out_irq_description);
+ /* Make sure we never try to use DMA out */
+ /* for the port again. */
+ info->dma_out_enabled = 0;
+ } else if (cris_request_dma(info->dma_out_nbr,
+ info->dma_out_irq_description,
+ DMA_VERBOSE_ON_ERROR,
+ info->dma_owner)) {
+ free_irq(info->dma_out_irq_nbr, info);
+ printk(KERN_WARNING "DMA '%s' busy; "
+ "falling back to non-DMA mode\n",
+ info->dma_out_irq_description);
+ /* Make sure we never try to use DMA out */
+ /* for the port again. */
+ info->dma_out_enabled = 0;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ else
+ printk(KERN_DEBUG "DMA irq '%s' allocated\n",
+ info->dma_out_irq_description);
+#endif
+ }
+ }
+
+ /*
* Start up the serial port
*/
retval = startup(info);
- if (retval)
+ if (retval) {
+ if (allocated_resources)
+ deinit_port(info);
+
+ /* FIXME Decrease count info->count here too? */
return retval;
+ }
+
retval = block_til_ready(tty, filp, info);
if (retval) {
@@ -4604,6 +4193,9 @@
printk("rs_open returning after block_til_ready with %d\n",
retval);
#endif
+ if (allocated_resources)
+ deinit_port(info);
+
return retval;
}
@@ -4793,6 +4385,8 @@
.send_xchar = rs_send_xchar,
.wait_until_sent = rs_wait_until_sent,
.read_proc = rs_read_proc,
+ .tiocmget = rs_tiocmget,
+ .tiocmset = rs_tiocmset
};
static int __init
@@ -4810,9 +4404,27 @@
/* Setup the timed flush handler system */
#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER)
- init_timer(&flush_timer);
- flush_timer.function = timed_flush_handler;
- mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS);
+ setup_timer(&flush_timer, timed_flush_handler, 0);
+ mod_timer(&flush_timer, jiffies + 5);
+#endif
+
+#if defined(CONFIG_ETRAX_RS485)
+#if defined(CONFIG_ETRAX_RS485_ON_PA)
+ if (cris_io_interface_allocate_pins(if_ser0, 'a', rs485_pa_bit,
+ rs485_pa_bit)) {
+ printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
+ "RS485 pin\n");
+ return -EBUSY;
+ }
+#endif
+#if defined(CONFIG_ETRAX_RS485_ON_PORT_G)
+ if (cris_io_interface_allocate_pins(if_ser0, 'g', rs485_pa_bit,
+ rs485_port_g_bit)) {
+ printk(KERN_CRIT "ETRAX100LX serial: Could not allocate "
+ "RS485 pin\n");
+ return -EBUSY;
+ }
+#endif
#endif
/* Initialize the tty_driver structure */
@@ -4839,6 +4451,16 @@
/* do some initializing for the separate ports */
for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
+ if (info->enabled) {
+ if (cris_request_io_interface(info->io_if,
+ info->io_if_description)) {
+ printk(KERN_CRIT "ETRAX100LX async serial: "
+ "Could not allocate IO pins for "
+ "%s, port %d\n",
+ info->io_if_description, i);
+ info->enabled = 0;
+ }
+ }
info->uses_dma_in = 0;
info->uses_dma_out = 0;
info->line = i;
@@ -4872,7 +4494,7 @@
info->rs485.delay_rts_before_send = 0;
info->rs485.enabled = 0;
#endif
- INIT_WORK(&info->work, do_softint, info);
+ INIT_WORK(&info->work, do_softint);
if (info->enabled) {
printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
@@ -4890,64 +4512,17 @@
#endif
#ifndef CONFIG_SVINTO_SIM
+#ifndef CONFIG_ETRAX_KGDB
/* Not needed in simulator. May only complicate stuff. */
/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
- if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial ", NULL))
- panic("irq8");
+ if (request_irq(SERIAL_IRQ_NBR, ser_interrupt,
+ IRQF_SHARED | IRQF_DISABLED, "serial ", driver))
+ panic("%s: Failed to request irq8", __FUNCTION__);
-#ifdef CONFIG_ETRAX_SERIAL_PORT0
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT
- if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 0 dma tr", NULL))
- panic("irq22");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN
- if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 0 dma rec", NULL))
- panic("irq23");
-#endif
-#endif
-
-#ifdef CONFIG_ETRAX_SERIAL_PORT1
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT
- if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 1 dma tr", NULL))
- panic("irq24");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN
- if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 1 dma rec", NULL))
- panic("irq25");
-#endif
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2
- /* DMA Shared with par0 (and SCSI0 and ATA) */
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT
- if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma tr", NULL))
- panic("irq18");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN
- if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma rec", NULL))
- panic("irq19");
-#endif
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3
- /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT
- if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma tr", NULL))
- panic("irq20");
-#endif
-#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN
- if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma rec", NULL))
- panic("irq21");
-#endif
-#endif
-
-#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST
- if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, IRQF_SHARED | IRQF_DISABLED,
- "fast serial dma timeout", NULL)) {
- printk(KERN_CRIT "err: timer1 irq\n");
- }
#endif
#endif /* CONFIG_SVINTO_SIM */
- debug_write_function = rs_debug_write_function;
+
return 0;
}
diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h
new file mode 100644
index 0000000..ccd0f32
--- /dev/null
+++ b/drivers/serial/crisv10.h
@@ -0,0 +1,146 @@
+/*
+ * serial.h: Arch-dep definitions for the Etrax100 serial driver.
+ *
+ * Copyright (C) 1998-2007 Axis Communications AB
+ */
+
+#ifndef _ETRAX_SERIAL_H
+#define _ETRAX_SERIAL_H
+
+#include <linux/circ_buf.h>
+#include <asm/termios.h>
+#include <asm/dma.h>
+#include <asm/arch/io_interface_mux.h>
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ *
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+#define SERIAL_RECV_DESCRIPTORS 8
+
+struct etrax_recv_buffer {
+ struct etrax_recv_buffer *next;
+ unsigned short length;
+ unsigned char error;
+ unsigned char pad;
+
+ unsigned char buffer[0];
+};
+
+struct e100_serial {
+ int baud;
+ volatile u8 *port; /* R_SERIALx_CTRL */
+ u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */
+
+ /* Output registers */
+ volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
+ volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */
+ volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */
+ const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */
+
+ /* Input registers */
+ volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */
+ volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */
+ volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */
+ volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */
+
+ int flags; /* defined in tty.h */
+
+ u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
+ u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
+ u8 iseteop; /* bit number for R_SET_EOP for the input dma */
+ int enabled; /* Set to 1 if the port is enabled in HW config */
+
+ u8 dma_out_enabled; /* Set to 1 if DMA should be used */
+ u8 dma_in_enabled; /* Set to 1 if DMA should be used */
+
+ /* end of fields defined in rs_table[] in .c-file */
+ int dma_owner;
+ unsigned int dma_in_nbr;
+ unsigned int dma_out_nbr;
+ unsigned int dma_in_irq_nbr;
+ unsigned int dma_out_irq_nbr;
+ unsigned long dma_in_irq_flags;
+ unsigned long dma_out_irq_flags;
+ char *dma_in_irq_description;
+ char *dma_out_irq_description;
+
+ enum cris_io_interface io_if;
+ char *io_if_description;
+
+ u8 uses_dma_in; /* Set to 1 if DMA is used */
+ u8 uses_dma_out; /* Set to 1 if DMA is used */
+ u8 forced_eop; /* a fifo eop has been forced */
+ int baud_base; /* For special baudrates */
+ int custom_divisor; /* For special baudrates */
+ struct etrax_dma_descr tr_descr;
+ struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS];
+ int cur_rec_descr;
+
+ volatile int tr_running; /* 1 if output is running */
+
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int line;
+ int type; /* PORT_ETRAX */
+ int count; /* # of fd on device */
+ int blocked_open; /* # of blocked opens */
+ struct circ_buf xmit;
+ struct etrax_recv_buffer *first_recv_buffer;
+ struct etrax_recv_buffer *last_recv_buffer;
+ unsigned int recv_cnt;
+ unsigned int max_recv_cnt;
+
+ struct work_struct work;
+ struct async_icount icount; /* error-statistics etc.*/
+ struct ktermios normal_termios;
+ struct ktermios callout_termios;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ unsigned long char_time_usec; /* The time for 1 char, in usecs */
+ unsigned long flush_time_usec; /* How often we should flush */
+ unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */
+ unsigned long last_tx_active; /* Last tx time in jiffies */
+ unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */
+ unsigned long last_rx_active; /* Last rx time in jiffies */
+
+ int break_detected_cnt;
+ int errorcode;
+
+#ifdef CONFIG_ETRAX_RS485
+ struct rs485_control rs485; /* RS-485 support */
+#endif
+};
+
+/* this PORT is not in the standard serial.h. it's not actually used for
+ * anything since we only have one type of async serial-port anyway in this
+ * system.
+ */
+
+#define PORT_ETRAX 1
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP 0
+
+#endif /* __KERNEL__ */
+
+#endif /* !_ETRAX_SERIAL_H */
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 89769ce..b31f443 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -457,10 +457,11 @@
EXPORT_SYMBOL_GPL(spi_register_master);
-static int __unregister(struct device *dev, void *unused)
+static int __unregister(struct device *dev, void *master_dev)
{
/* note: before about 2.6.14-rc1 this would corrupt memory: */
- spi_unregister_device(to_spi_device(dev));
+ if (dev != master_dev)
+ spi_unregister_device(to_spi_device(dev));
return 0;
}
@@ -478,7 +479,8 @@
{
int dummy;
- dummy = device_for_each_child(master->dev.parent, NULL, __unregister);
+ dummy = device_for_each_child(master->dev.parent, &master->dev,
+ __unregister);
device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
index cc5094f..363ac8e 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi_txx9.c
@@ -24,6 +24,7 @@
#include <linux/spi/spi.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/io.h>
#include <asm/gpio.h>
@@ -74,7 +75,6 @@
struct list_head queue;
wait_queue_head_t waitq;
void __iomem *membase;
- int irq;
int baseclk;
struct clk *clk;
u32 max_speed_hz, min_speed_hz;
@@ -350,12 +350,12 @@
struct resource *res;
int ret = -ENODEV;
u32 mcr;
+ int irq;
master = spi_alloc_master(&dev->dev, sizeof(*c));
if (!master)
return ret;
c = spi_master_get_devdata(master);
- c->irq = -1;
platform_set_drvdata(dev, master);
INIT_WORK(&c->work, txx9spi_work);
@@ -381,32 +381,36 @@
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!res)
- goto exit;
- c->membase = ioremap(res->start, res->end - res->start + 1);
+ goto exit_busy;
+ if (!devm_request_mem_region(&dev->dev,
+ res->start, res->end - res->start + 1,
+ "spi_txx9"))
+ goto exit_busy;
+ c->membase = devm_ioremap(&dev->dev,
+ res->start, res->end - res->start + 1);
if (!c->membase)
- goto exit;
+ goto exit_busy;
/* enter config mode */
mcr = txx9spi_rd(c, TXx9_SPMCR);
mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
- c->irq = platform_get_irq(dev, 0);
- if (c->irq < 0)
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0)
+ goto exit_busy;
+ ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0,
+ "spi_txx9", c);
+ if (ret)
goto exit;
- ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c);
- if (ret) {
- c->irq = -1;
- goto exit;
- }
c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id);
if (!c->workqueue)
- goto exit;
+ goto exit_busy;
c->last_chipselect = -1;
dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
- (unsigned long long)res->start, c->irq,
+ (unsigned long long)res->start, irq,
(c->baseclk + 500000) / 1000000);
master->bus_num = dev->id;
@@ -418,13 +422,11 @@
if (ret)
goto exit;
return 0;
+exit_busy:
+ ret = -EBUSY;
exit:
if (c->workqueue)
destroy_workqueue(c->workqueue);
- if (c->irq >= 0)
- free_irq(c->irq, c);
- if (c->membase)
- iounmap(c->membase);
if (c->clk) {
clk_disable(c->clk);
clk_put(c->clk);
@@ -442,8 +444,6 @@
spi_unregister_master(master);
platform_set_drvdata(dev, NULL);
destroy_workqueue(c->workqueue);
- free_irq(c->irq, c);
- iounmap(c->membase);
clk_disable(c->clk);
clk_put(c->clk);
spi_master_put(master);
diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c
index 6da58ca..455991f 100644
--- a/drivers/spi/tle62x0.c
+++ b/drivers/spi/tle62x0.c
@@ -107,8 +107,11 @@
mutex_lock(&st->lock);
ret = tle62x0_read(st);
-
dev_dbg(dev, "tle62x0_read() returned %d\n", ret);
+ if (ret < 0) {
+ mutex_unlock(&st->lock);
+ return ret;
+ }
for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) {
fault <<= 8;
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index c12a741..85a2054 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -440,6 +440,7 @@
break;
case SSB_BUSTYPE_PCMCIA:
#ifdef CONFIG_SSB_PCMCIAHOST
+ sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
dev->parent = &bus->host_pcmcia->dev;
#endif
break;
@@ -1147,7 +1148,10 @@
return err;
}
-subsys_initcall(ssb_modinit);
+/* ssb must be initialized after PCI but before the ssb drivers.
+ * That means we must use some initcall between subsys_initcall
+ * and device_initcall. */
+fs_initcall(ssb_modinit);
static void __exit ssb_modexit(void)
{
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index b6abee8..bb44a76 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -63,17 +63,17 @@
err = pcmcia_access_configuration_register(pdev, ®);
if (err != CS_SUCCESS)
goto error;
- read_addr |= (reg.Value & 0xF) << 12;
+ read_addr |= ((u32)(reg.Value & 0x0F)) << 12;
reg.Offset = 0x30;
err = pcmcia_access_configuration_register(pdev, ®);
if (err != CS_SUCCESS)
goto error;
- read_addr |= reg.Value << 16;
+ read_addr |= ((u32)reg.Value) << 16;
reg.Offset = 0x32;
err = pcmcia_access_configuration_register(pdev, ®);
if (err != CS_SUCCESS)
goto error;
- read_addr |= reg.Value << 24;
+ read_addr |= ((u32)reg.Value) << 24;
cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
if (cur_core == coreidx)
@@ -152,28 +152,29 @@
goto out_unlock;
}
-/* These are the main device register access functions.
- * do_select_core is inline to have the likely hotpath inline.
- * All unlikely codepaths are out-of-line. */
-static inline int do_select_core(struct ssb_bus *bus,
- struct ssb_device *dev,
- u16 *offset)
+static int select_core_and_segment(struct ssb_device *dev,
+ u16 *offset)
{
+ struct ssb_bus *bus = dev->bus;
int err;
- u8 need_seg = (*offset >= 0x800) ? 1 : 0;
+ u8 need_segment;
+
+ if (*offset >= 0x800) {
+ *offset -= 0x800;
+ need_segment = 1;
+ } else
+ need_segment = 0;
if (unlikely(dev != bus->mapped_device)) {
err = ssb_pcmcia_switch_core(bus, dev);
if (unlikely(err))
return err;
}
- if (unlikely(need_seg != bus->mapped_pcmcia_seg)) {
- err = ssb_pcmcia_switch_segment(bus, need_seg);
+ if (unlikely(need_segment != bus->mapped_pcmcia_seg)) {
+ err = ssb_pcmcia_switch_segment(bus, need_segment);
if (unlikely(err))
return err;
}
- if (need_seg == 1)
- *offset -= 0x800;
return 0;
}
@@ -181,32 +182,31 @@
static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
{
struct ssb_bus *bus = dev->bus;
- u16 x;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return 0xFFFF;
- x = readw(bus->mmio + offset);
- return x;
+ return readw(bus->mmio + offset);
}
static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
{
struct ssb_bus *bus = dev->bus;
- u32 x;
+ u32 lo, hi;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return 0xFFFFFFFF;
- x = readl(bus->mmio + offset);
+ lo = readw(bus->mmio + offset);
+ hi = readw(bus->mmio + offset + 2);
- return x;
+ return (lo | (hi << 16));
}
static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
{
struct ssb_bus *bus = dev->bus;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return;
writew(value, bus->mmio + offset);
}
@@ -215,12 +215,12 @@
{
struct ssb_bus *bus = dev->bus;
- if (unlikely(do_select_core(bus, dev, &offset)))
+ if (unlikely(select_core_and_segment(dev, &offset)))
return;
- readw(bus->mmio + offset);
- writew(value >> 16, bus->mmio + offset + 2);
- readw(bus->mmio + offset);
- writew(value, bus->mmio + offset);
+ writeb((value & 0xFF000000) >> 24, bus->mmio + offset + 3);
+ writeb((value & 0x00FF0000) >> 16, bus->mmio + offset + 2);
+ writeb((value & 0x0000FF00) >> 8, bus->mmio + offset + 1);
+ writeb((value & 0x000000FF) >> 0, bus->mmio + offset + 0);
}
/* Not "static", as it's used in main.c */
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 6bfdba6..1f7ab15 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1215,20 +1215,18 @@
static int keyspan_open (struct usb_serial_port *port, struct file *filp)
{
- struct keyspan_port_private *p_priv;
- struct keyspan_serial_private *s_priv;
- struct usb_serial *serial = port->serial;
+ struct keyspan_port_private *p_priv;
+ struct keyspan_serial_private *s_priv;
+ struct usb_serial *serial = port->serial;
const struct keyspan_device_details *d_details;
int i, err;
- int baud_rate, device_port;
struct urb *urb;
- unsigned int cflag;
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
-
- dbg("%s - port%d.", __FUNCTION__, port->number);
+
+ dbg("%s - port%d.", __FUNCTION__, port->number);
/* Set some sane defaults */
p_priv->rts_state = 1;
@@ -1249,7 +1247,7 @@
urb->dev = serial->dev;
/* make sure endpoint data toggle is synchronized with the device */
-
+
usb_clear_halt(urb->dev, urb->pipe);
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
@@ -1265,30 +1263,6 @@
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
}
- /* get the terminal config for the setup message now so we don't
- * need to send 2 of them */
-
- cflag = port->tty->termios->c_cflag;
- device_port = port->number - port->serial->minor;
-
- /* Baud rate calculation takes baud rate as an integer
- so other rates can be generated if desired. */
- baud_rate = tty_get_baud_rate(port->tty);
- /* If no match or invalid, leave as default */
- if (baud_rate >= 0
- && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
- NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
- p_priv->baud = baud_rate;
- }
-
- /* set CTS/RTS handshake etc. */
- p_priv->cflag = cflag;
- p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
-
- keyspan_send_setup(port, 1);
- //mdelay(100);
- //keyspan_set_termios(port, NULL);
-
return (0);
}
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cc4b60f..7d86e9e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -503,7 +503,7 @@
config FB_CT65550
bool "Chips 65550 display support"
- depends on (FB = y) && PPC32
+ depends on (FB = y) && PPC32 && PCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index b9b572b..2e552d5 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -183,8 +183,8 @@
.vmode = FB_VMODE_NONINTERLACED,
};
-struct fb_videomode *default_mode = &default_mode_CRT;
-struct fb_var_screeninfo *default_var = &default_var_CRT;
+struct fb_videomode *default_mode __initdata = &default_mode_CRT;
+struct fb_var_screeninfo *default_var __initdata = &default_var_CRT;
static int flat_panel_enabled = 0;
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index 6c227f9..ca13c48 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -33,7 +33,7 @@
#define MSR_LX_GLD_CONFIG 0x48002001
#define MSR_LX_GLCP_DOTPLL 0x4c000015
-#define MSR_LX_DF_PADSEL 0x48000011
+#define MSR_LX_DF_PADSEL 0x48002011
#define MSR_LX_DC_SPARE 0x80000011
#define MSR_LX_DF_GLCONFIG 0x48002001
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index b3463dd..75836aa 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -727,7 +727,7 @@
static int ps3fb_get_vblank(struct fb_vblank *vblank)
{
- memset(vblank, 0, sizeof(&vblank));
+ memset(vblank, 0, sizeof(*vblank));
vblank->flags = FB_VBLANK_HAVE_VSYNC;
return 0;
}
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index a5333c1..b829dc7 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -540,7 +540,7 @@
int ret = 0;
u8 revision;
- dbg("probe called: device is %p\n", dev);
+ dbg("probe called: device is %p\n", pdev);
printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
@@ -753,8 +753,11 @@
static int __init
s1d13xxxfb_init(void)
{
+
+#ifndef MODULE
if (fb_get_options("s1d13xxxfb", NULL))
return -ENODEV;
+#endif
return platform_driver_register(&s1d13xxxfb_driver);
}
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index bc7d236..37bd24b 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1248,7 +1248,6 @@
if(found_mode) {
ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
ivideo->sisfb_mode_idx, ivideo->currentvbflags);
- ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
} else {
ivideo->sisfb_mode_idx = -1;
}
@@ -1260,6 +1259,8 @@
return -EINVAL;
}
+ ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
+
if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
ivideo->refresh_rate = 60;
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index b983d26..d1d6c0f 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -926,8 +926,10 @@
int start, struct fb_info *info)
{
struct uvesafb_ktask *task;
+#ifdef CONFIG_X86
struct uvesafb_par *par = info->par;
int i = par->mode_idx;
+#endif
int err = 0;
/*
@@ -1103,11 +1105,11 @@
static int uvesafb_blank(int blank, struct fb_info *info)
{
- struct uvesafb_par *par = info->par;
struct uvesafb_ktask *task;
int err = 1;
-
#ifdef CONFIG_X86
+ struct uvesafb_par *par = info->par;
+
if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
int loop = 10000;
u8 seq = 0, crtc17 = 0;
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 0e4baca..1dc04b6 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -53,7 +53,7 @@
unsigned int num_added;
/* Last used index we've seen. */
- unsigned int last_used_idx;
+ u16 last_used_idx;
/* How to notify other side. FIXME: commonalize hcalls! */
void (*notify)(struct virtqueue *vq);
@@ -277,11 +277,17 @@
struct vring_virtqueue *vq;
unsigned int i;
+ /* We assume num is a power of 2. */
+ if (num & (num - 1)) {
+ dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
+ return NULL;
+ }
+
vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL);
if (!vq)
return NULL;
- vring_init(&vq->vring, num, pages);
+ vring_init(&vq->vring, num, pages, PAGE_SIZE);
vq->vq.callback = callback;
vq->vq.vdev = vdev;
vq->vq.vq_ops = &vring_vq_ops;
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 299e274..b63b5e04 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -233,7 +233,7 @@
{
int count, err;
- memset(st, 0, sizeof(st));
+ memset(st, 0, sizeof(*st));
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
diff --git a/fs/Kconfig b/fs/Kconfig
index c75c954..429a002 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -2007,7 +2007,7 @@
config CIFS_UPCALL
bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
depends on CIFS_EXPERIMENTAL
- depends on CONNECTOR
+ depends on KEYS
help
Enables an upcall mechanism for CIFS which will be used to contact
userspace helper utilities to provide SPNEGO packaged Kerberos
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 130f6c6..ac7a8b1 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -14,8 +14,6 @@
unsigned long si_blocks;
unsigned long si_freeb;
unsigned long si_freei;
- unsigned long si_lf_ioff;
- unsigned long si_lf_sblk;
unsigned long si_lf_eblk;
unsigned long si_lasti;
unsigned long * si_imap;
@@ -39,7 +37,7 @@
static inline struct bfs_inode_info *BFS_I(struct inode *inode)
{
- return list_entry(inode, struct bfs_inode_info, vfs_inode);
+ return container_of(inode, struct bfs_inode_info, vfs_inode);
}
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 097f149..1fd056d 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -21,29 +21,32 @@
#define dprintf(x...)
#endif
-static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino);
-static struct buffer_head * bfs_find_entry(struct inode * dir,
- const unsigned char * name, int namelen, struct bfs_dirent ** res_dir);
+static int bfs_add_entry(struct inode *dir, const unsigned char *name,
+ int namelen, int ino);
+static struct buffer_head *bfs_find_entry(struct inode *dir,
+ const unsigned char *name, int namelen,
+ struct bfs_dirent **res_dir);
-static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
+static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir)
{
- struct inode * dir = f->f_path.dentry->d_inode;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ struct inode *dir = f->f_path.dentry->d_inode;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
unsigned int offset;
int block;
lock_kernel();
- if (f->f_pos & (BFS_DIRENT_SIZE-1)) {
- printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos,
- dir->i_sb->s_id, dir->i_ino);
+ if (f->f_pos & (BFS_DIRENT_SIZE - 1)) {
+ printf("Bad f_pos=%08lx for %s:%08lx\n",
+ (unsigned long)f->f_pos,
+ dir->i_sb->s_id, dir->i_ino);
unlock_kernel();
return -EBADF;
}
while (f->f_pos < dir->i_size) {
- offset = f->f_pos & (BFS_BSIZE-1);
+ offset = f->f_pos & (BFS_BSIZE - 1);
block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS);
bh = sb_bread(dir->i_sb, block);
if (!bh) {
@@ -54,7 +57,9 @@
de = (struct bfs_dirent *)(bh->b_data + offset);
if (de->ino) {
int size = strnlen(de->name, BFS_NAMELEN);
- if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) {
+ if (filldir(dirent, de->name, size, f->f_pos,
+ le16_to_cpu(de->ino),
+ DT_UNKNOWN) < 0) {
brelse(bh);
unlock_kernel();
return 0;
@@ -62,7 +67,7 @@
}
offset += BFS_DIRENT_SIZE;
f->f_pos += BFS_DIRENT_SIZE;
- } while (offset < BFS_BSIZE && f->f_pos < dir->i_size);
+ } while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size));
brelse(bh);
}
@@ -78,13 +83,13 @@
extern void dump_imap(const char *, struct super_block *);
-static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
- struct nameidata *nd)
+static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
int err;
- struct inode * inode;
- struct super_block * s = dir->i_sb;
- struct bfs_sb_info * info = BFS_SB(s);
+ struct inode *inode;
+ struct super_block *s = dir->i_sb;
+ struct bfs_sb_info *info = BFS_SB(s);
unsigned long ino;
inode = new_inode(s);
@@ -97,7 +102,7 @@
iput(inode);
return -ENOSPC;
}
- set_bit(ino, info->si_imap);
+ set_bit(ino, info->si_imap);
info->si_freei--;
inode->i_uid = current->fsuid;
inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
@@ -113,9 +118,10 @@
BFS_I(inode)->i_eblock = 0;
insert_inode_hash(inode);
mark_inode_dirty(inode);
- dump_imap("create",s);
+ dump_imap("create", s);
- err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);
+ err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len,
+ inode->i_ino);
if (err) {
inode_dec_link_count(inode);
iput(inode);
@@ -127,11 +133,12 @@
return 0;
}
-static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
{
- struct inode * inode = NULL;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ struct inode *inode = NULL;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
if (dentry->d_name.len > BFS_NAMELEN)
return ERR_PTR(-ENAMETOOLONG);
@@ -152,13 +159,15 @@
return NULL;
}
-static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new)
+static int bfs_link(struct dentry *old, struct inode *dir,
+ struct dentry *new)
{
- struct inode * inode = old->d_inode;
+ struct inode *inode = old->d_inode;
int err;
lock_kernel();
- err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino);
+ err = bfs_add_entry(dir, new->d_name.name, new->d_name.len,
+ inode->i_ino);
if (err) {
unlock_kernel();
return err;
@@ -172,23 +181,23 @@
return 0;
}
-
-static int bfs_unlink(struct inode * dir, struct dentry * dentry)
+static int bfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error = -ENOENT;
- struct inode * inode;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ struct inode *inode;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
inode = dentry->d_inode;
lock_kernel();
bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
- if (!bh || le16_to_cpu(de->ino) != inode->i_ino)
+ if (!bh || (le16_to_cpu(de->ino) != inode->i_ino))
goto out_brelse;
if (!inode->i_nlink) {
- printf("unlinking non-existent file %s:%lu (nlink=%d)\n", inode->i_sb->s_id,
- inode->i_ino, inode->i_nlink);
+ printf("unlinking non-existent file %s:%lu (nlink=%d)\n",
+ inode->i_sb->s_id, inode->i_ino,
+ inode->i_nlink);
inode->i_nlink = 1;
}
de->ino = 0;
@@ -205,12 +214,12 @@
return error;
}
-static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
- struct inode * new_dir, struct dentry * new_dentry)
+static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
- struct inode * old_inode, * new_inode;
- struct buffer_head * old_bh, * new_bh;
- struct bfs_dirent * old_de, * new_de;
+ struct inode *old_inode, *new_inode;
+ struct buffer_head *old_bh, *new_bh;
+ struct bfs_dirent *old_de, *new_de;
int error = -ENOENT;
old_bh = new_bh = NULL;
@@ -223,7 +232,7 @@
old_dentry->d_name.name,
old_dentry->d_name.len, &old_de);
- if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino)
+ if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino))
goto end_rename;
error = -EPERM;
@@ -239,7 +248,8 @@
if (!new_bh) {
error = bfs_add_entry(new_dir,
new_dentry->d_name.name,
- new_dentry->d_name.len, old_inode->i_ino);
+ new_dentry->d_name.len,
+ old_inode->i_ino);
if (error)
goto end_rename;
}
@@ -268,11 +278,12 @@
.rename = bfs_rename,
};
-static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino)
+static int bfs_add_entry(struct inode *dir, const unsigned char *name,
+ int namelen, int ino)
{
- struct buffer_head * bh;
- struct bfs_dirent * de;
- int block, sblock, eblock, off, eoff;
+ struct buffer_head *bh;
+ struct bfs_dirent *de;
+ int block, sblock, eblock, off, pos;
int i;
dprintf("name=%s, namelen=%d\n", name, namelen);
@@ -284,27 +295,24 @@
sblock = BFS_I(dir)->i_sblock;
eblock = BFS_I(dir)->i_eblock;
- eoff = dir->i_size % BFS_BSIZE;
- for (block=sblock; block<=eblock; block++) {
+ for (block = sblock; block <= eblock; block++) {
bh = sb_bread(dir->i_sb, block);
- if(!bh)
+ if (!bh)
return -ENOSPC;
- for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) {
+ for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) {
de = (struct bfs_dirent *)(bh->b_data + off);
- if (block==eblock && off>=eoff) {
- /* Do not read/interpret the garbage in the end of eblock. */
- de->ino = 0;
- }
if (!de->ino) {
- if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) {
+ pos = (block - sblock) * BFS_BSIZE + off;
+ if (pos >= dir->i_size) {
dir->i_size += BFS_DIRENT_SIZE;
dir->i_ctime = CURRENT_TIME_SEC;
}
dir->i_mtime = CURRENT_TIME_SEC;
mark_inode_dirty(dir);
de->ino = cpu_to_le16((u16)ino);
- for (i=0; i<BFS_NAMELEN; i++)
- de->name[i] = (i < namelen) ? name[i] : 0;
+ for (i = 0; i < BFS_NAMELEN; i++)
+ de->name[i] =
+ (i < namelen) ? name[i] : 0;
mark_buffer_dirty(bh);
brelse(bh);
return 0;
@@ -315,25 +323,26 @@
return -ENOSPC;
}
-static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer)
+static inline int bfs_namecmp(int len, const unsigned char *name,
+ const char *buffer)
{
- if (len < BFS_NAMELEN && buffer[len])
+ if ((len < BFS_NAMELEN) && buffer[len])
return 0;
return !memcmp(name, buffer, len);
}
-static struct buffer_head * bfs_find_entry(struct inode * dir,
- const unsigned char * name, int namelen, struct bfs_dirent ** res_dir)
+static struct buffer_head *bfs_find_entry(struct inode *dir,
+ const unsigned char *name, int namelen,
+ struct bfs_dirent **res_dir)
{
- unsigned long block, offset;
- struct buffer_head * bh;
- struct bfs_dirent * de;
+ unsigned long block = 0, offset = 0;
+ struct buffer_head *bh = NULL;
+ struct bfs_dirent *de;
*res_dir = NULL;
if (namelen > BFS_NAMELEN)
return NULL;
- bh = NULL;
- block = offset = 0;
+
while (block * BFS_BSIZE + offset < dir->i_size) {
if (!bh) {
bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block);
@@ -344,7 +353,8 @@
}
de = (struct bfs_dirent *)(bh->b_data + offset);
offset += BFS_DIRENT_SIZE;
- if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) {
+ if (le16_to_cpu(de->ino) &&
+ bfs_namecmp(namelen, name, de->name)) {
*res_dir = de;
return bh;
}
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 911b4cc..b11e63e 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -2,6 +2,11 @@
* fs/bfs/file.c
* BFS file operations.
* Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
+ *
+ * Make the file block allocation algorithm understand the size
+ * of the underlying block device.
+ * Copyright (C) 2007 Dmitri Vorobiev <dmitri.vorobiev@gmail.com>
+ *
*/
#include <linux/fs.h>
@@ -27,7 +32,8 @@
.splice_read = generic_file_splice_read,
};
-static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
+static int bfs_move_block(unsigned long from, unsigned long to,
+ struct super_block *sb)
{
struct buffer_head *bh, *new;
@@ -43,21 +49,22 @@
}
static int bfs_move_blocks(struct super_block *sb, unsigned long start,
- unsigned long end, unsigned long where)
+ unsigned long end, unsigned long where)
{
unsigned long i;
dprintf("%08lx-%08lx->%08lx\n", start, end, where);
for (i = start; i <= end; i++)
if(bfs_move_block(i, where + i, sb)) {
- dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
+ dprintf("failed to move block %08lx -> %08lx\n", i,
+ where + i);
return -EIO;
}
return 0;
}
-static int bfs_get_block(struct inode * inode, sector_t block,
- struct buffer_head * bh_result, int create)
+static int bfs_get_block(struct inode *inode, sector_t block,
+ struct buffer_head *bh_result, int create)
{
unsigned long phys;
int err;
@@ -66,9 +73,6 @@
struct bfs_inode_info *bi = BFS_I(inode);
struct buffer_head *sbh = info->si_sbh;
- if (block > info->si_blocks)
- return -EIO;
-
phys = bi->i_sblock + block;
if (!create) {
if (phys <= bi->i_eblock) {
@@ -79,21 +83,29 @@
return 0;
}
- /* if the file is not empty and the requested block is within the range
- of blocks allocated for this file, we can grant it */
- if (inode->i_size && phys <= bi->i_eblock) {
+ /*
+ * If the file is not empty and the requested block is within the
+ * range of blocks allocated for this file, we can grant it.
+ */
+ if (bi->i_sblock && (phys <= bi->i_eblock)) {
dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n",
create, (unsigned long)block, phys);
map_bh(bh_result, sb, phys);
return 0;
}
- /* the rest has to be protected against itself */
+ /* The file will be extended, so let's see if there is enough space. */
+ if (phys >= info->si_blocks)
+ return -ENOSPC;
+
+ /* The rest has to be protected against itself. */
lock_kernel();
- /* if the last data block for this file is the last allocated
- block, we can extend the file trivially, without moving it
- anywhere */
+ /*
+ * If the last data block for this file is the last allocated
+ * block, we can extend the file trivially, without moving it
+ * anywhere.
+ */
if (bi->i_eblock == info->si_lf_eblk) {
dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n",
create, (unsigned long)block, phys);
@@ -106,13 +118,19 @@
goto out;
}
- /* Ok, we have to move this entire file to the next free block */
+ /* Ok, we have to move this entire file to the next free block. */
phys = info->si_lf_eblk + 1;
- if (bi->i_sblock) { /* if data starts on block 0 then there is no data */
+ if (phys + block >= info->si_blocks) {
+ err = -ENOSPC;
+ goto out;
+ }
+
+ if (bi->i_sblock) {
err = bfs_move_blocks(inode->i_sb, bi->i_sblock,
- bi->i_eblock, phys);
+ bi->i_eblock, phys);
if (err) {
- dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
+ dprintf("failed to move ino=%08lx -> fs corruption\n",
+ inode->i_ino);
goto out;
}
} else
@@ -124,8 +142,10 @@
phys += block;
info->si_lf_eblk = bi->i_eblock = phys;
- /* this assumes nothing can write the inode back while we are here
- * and thus update inode->i_blocks! (XXX)*/
+ /*
+ * This assumes nothing can write the inode back while we are here
+ * and thus update inode->i_blocks! (XXX)
+ */
info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks;
mark_inode_dirty(inode);
mark_buffer_dirty(sbh);
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 7bd9c2b..294c41b 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -30,25 +30,26 @@
#define dprintf(x...)
#endif
-void dump_imap(const char *prefix, struct super_block * s);
+void dump_imap(const char *prefix, struct super_block *s);
-static void bfs_read_inode(struct inode * inode)
+static void bfs_read_inode(struct inode *inode)
{
unsigned long ino = inode->i_ino;
- struct bfs_inode * di;
- struct buffer_head * bh;
+ struct bfs_inode *di;
+ struct buffer_head *bh;
int block, off;
- if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
+ if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) {
printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
make_bad_inode(inode);
return;
}
- block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(inode->i_sb, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
+ printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id,
+ ino);
make_bad_inode(inode);
return;
}
@@ -56,7 +57,7 @@
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
- inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
+ inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
inode->i_mode |= S_IFDIR;
inode->i_op = &bfs_dir_inops;
@@ -70,48 +71,48 @@
BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);
BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock);
+ BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino);
inode->i_uid = le32_to_cpu(di->i_uid);
inode->i_gid = le32_to_cpu(di->i_gid);
inode->i_nlink = le32_to_cpu(di->i_nlink);
inode->i_size = BFS_FILESIZE(di);
inode->i_blocks = BFS_FILEBLOCKS(di);
- if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
inode->i_atime.tv_sec = le32_to_cpu(di->i_atime);
inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime);
inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime);
inode->i_atime.tv_nsec = 0;
inode->i_mtime.tv_nsec = 0;
inode->i_ctime.tv_nsec = 0;
- BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */
brelse(bh);
}
-static int bfs_write_inode(struct inode * inode, int unused)
+static int bfs_write_inode(struct inode *inode, int unused)
{
unsigned int ino = (u16)inode->i_ino;
unsigned long i_sblock;
- struct bfs_inode * di;
- struct buffer_head * bh;
+ struct bfs_inode *di;
+ struct buffer_head *bh;
int block, off;
dprintf("ino=%08x\n", ino);
- if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
+ if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) {
printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino);
return -EIO;
}
lock_kernel();
- block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(inode->i_sb, block);
if (!bh) {
- printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino);
+ printf("Unable to read inode %s:%08x\n",
+ inode->i_sb->s_id, ino);
unlock_kernel();
return -EIO;
}
- off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+ off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
if (ino == BFS_ROOT_INO)
@@ -133,27 +134,26 @@
di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
mark_buffer_dirty(bh);
- dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off);
brelse(bh);
unlock_kernel();
return 0;
}
-static void bfs_delete_inode(struct inode * inode)
+static void bfs_delete_inode(struct inode *inode)
{
unsigned long ino = inode->i_ino;
- struct bfs_inode * di;
- struct buffer_head * bh;
+ struct bfs_inode *di;
+ struct buffer_head *bh;
int block, off;
- struct super_block * s = inode->i_sb;
- struct bfs_sb_info * info = BFS_SB(s);
- struct bfs_inode_info * bi = BFS_I(inode);
+ struct super_block *s = inode->i_sb;
+ struct bfs_sb_info *info = BFS_SB(s);
+ struct bfs_inode_info *bi = BFS_I(inode);
dprintf("ino=%08lx\n", ino);
truncate_inode_pages(&inode->i_data, 0);
- if (ino < BFS_ROOT_INO || ino > info->si_lasti) {
+ if ((ino < BFS_ROOT_INO) || (ino > info->si_lasti)) {
printf("invalid ino=%08lx\n", ino);
return;
}
@@ -162,31 +162,35 @@
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
lock_kernel();
mark_inode_dirty(inode);
- block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+
+ block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
bh = sb_bread(s, block);
if (!bh) {
- printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
+ printf("Unable to read inode %s:%08lx\n",
+ inode->i_sb->s_id, ino);
unlock_kernel();
return;
}
- off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
- di = (struct bfs_inode *) bh->b_data + off;
+ off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
+ di = (struct bfs_inode *)bh->b_data + off;
+ memset((void *)di, 0, sizeof(struct bfs_inode));
+ mark_buffer_dirty(bh);
+ brelse(bh);
+
if (bi->i_dsk_ino) {
- info->si_freeb += 1 + bi->i_eblock - bi->i_sblock;
+ info->si_freeb += BFS_FILEBLOCKS(bi);
info->si_freei++;
clear_bit(ino, info->si_imap);
dump_imap("delete_inode", s);
}
- di->i_ino = 0;
- di->i_sblock = 0;
- mark_buffer_dirty(bh);
- brelse(bh);
- /* if this was the last file, make the previous
- block "last files last block" even if there is no real file there,
- saves us 1 gap */
- if (info->si_lf_eblk == BFS_I(inode)->i_eblock) {
- info->si_lf_eblk = BFS_I(inode)->i_sblock - 1;
+ /*
+ * If this was the last file, make the previous block
+ * "last block of the last file" even if there is no
+ * real file there, saves us 1 gap.
+ */
+ if (info->si_lf_eblk == bi->i_eblock) {
+ info->si_lf_eblk = bi->i_sblock - 1;
mark_buffer_dirty(info->si_sbh);
}
unlock_kernel();
@@ -228,7 +232,7 @@
unlock_kernel();
}
-static struct kmem_cache * bfs_inode_cachep;
+static struct kmem_cache *bfs_inode_cachep;
static struct inode *bfs_alloc_inode(struct super_block *sb)
{
@@ -279,7 +283,7 @@
.statfs = bfs_statfs,
};
-void dump_imap(const char *prefix, struct super_block * s)
+void dump_imap(const char *prefix, struct super_block *s)
{
#ifdef DEBUG
int i;
@@ -287,25 +291,26 @@
if (!tmpbuf)
return;
- for (i=BFS_SB(s)->si_lasti; i>=0; i--) {
- if (i > PAGE_SIZE-100) break;
+ for (i = BFS_SB(s)->si_lasti; i >= 0; i--) {
+ if (i > PAGE_SIZE - 100) break;
if (test_bit(i, BFS_SB(s)->si_imap))
strcat(tmpbuf, "1");
else
strcat(tmpbuf, "0");
}
- printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf);
+ printf("BFS-fs: %s: lasti=%08lx <%s>\n",
+ prefix, BFS_SB(s)->si_lasti, tmpbuf);
free_page((unsigned long)tmpbuf);
#endif
}
static int bfs_fill_super(struct super_block *s, void *data, int silent)
{
- struct buffer_head * bh;
- struct bfs_super_block * bfs_sb;
- struct inode * inode;
+ struct buffer_head *bh;
+ struct bfs_super_block *bfs_sb;
+ struct inode *inode;
unsigned i, imap_len;
- struct bfs_sb_info * info;
+ struct bfs_sb_info *info;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
@@ -329,14 +334,14 @@
s->s_magic = BFS_MAGIC;
info->si_sbh = bh;
- info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode)
- + BFS_ROOT_INO - 1;
-
- imap_len = info->si_lasti/8 + 1;
+ info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
+ sizeof(struct bfs_inode)
+ + BFS_ROOT_INO - 1;
+ imap_len = (info->si_lasti / 8) + 1;
info->si_imap = kzalloc(imap_len, GFP_KERNEL);
if (!info->si_imap)
goto out;
- for (i=0; i<BFS_ROOT_INO; i++)
+ for (i = 0; i < BFS_ROOT_INO; i++)
set_bit(i, info->si_imap);
s->s_op = &bfs_sops;
@@ -352,16 +357,15 @@
goto out;
}
- info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
- info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start))>>BFS_BSIZE_BITS;
+ info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
+ info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1
+ - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS;
info->si_freei = 0;
info->si_lf_eblk = 0;
- info->si_lf_sblk = 0;
- info->si_lf_ioff = 0;
bh = NULL;
- for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) {
+ for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) {
struct bfs_inode *di;
- int block = (i - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+ int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
unsigned long sblock, eblock;
@@ -384,11 +388,8 @@
sblock = le32_to_cpu(di->i_sblock);
eblock = le32_to_cpu(di->i_eblock);
- if (eblock > info->si_lf_eblk) {
+ if (eblock > info->si_lf_eblk)
info->si_lf_eblk = eblock;
- info->si_lf_sblk = sblock;
- info->si_lf_ioff = BFS_INO2OFF(i);
- }
}
brelse(bh);
if (!(s->s_flags & MS_RDONLY)) {
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 3d41916..64dd222 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,7 @@
+Version 1.52
+------------
+Fix oops on second mount to server when null auth is used.
+
Version 1.51
------------
Fix memory leak in statfs when mounted to very old servers (e.g.
@@ -12,7 +16,12 @@
cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
bigendian architectures. Fix possible memory corruption when
EAGAIN returned on kern_recvmsg. Return better error if server
-requires packet signing but client has disabled it.
+requires packet signing but client has disabled it. When mounted
+with cifsacl mount option - mode bits are approximated based
+on the contents of the ACL of the file or directory. When cifs
+mount helper is missing convert make sure that UNC name
+has backslash (not forward slash) between ip address of server
+and the share name.
Version 1.50
------------
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index ff6ba8d..45e42fb 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,9 @@
#
obj-$(CONFIG_CIFS) += cifs.o
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifsacl.o
+cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
+ link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
+ md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \
+ readdir.o ioctl.o sess.o export.o cifsacl.o
+
+cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 2a01f3e..bcda2c6 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -77,8 +77,12 @@
#define SPNEGO_OID_LEN 7
#define NTLMSSP_OID_LEN 10
+#define KRB5_OID_LEN 7
+#define MSKRB5_OID_LEN 7
static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
+static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
+static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
/*
* ASN.1 context.
@@ -457,6 +461,7 @@
unsigned long *oid = NULL;
unsigned int cls, con, tag, oidlen, rc;
int use_ntlmssp = FALSE;
+ int use_kerberos = FALSE;
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
@@ -545,18 +550,28 @@
return 0;
}
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
- rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
- if (rc) {
+ if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
+
cFYI(1,
("OID len = %d oid = 0x%lx 0x%lx "
"0x%lx 0x%lx",
oidlen, *oid, *(oid + 1),
*(oid + 2), *(oid + 3)));
- rc = compare_oid(oid, oidlen,
- NTLMSSP_OID, NTLMSSP_OID_LEN);
- kfree(oid);
- if (rc)
+
+ if (compare_oid(oid, oidlen,
+ MSKRB5_OID,
+ MSKRB5_OID_LEN))
+ use_kerberos = TRUE;
+ else if (compare_oid(oid, oidlen,
+ KRB5_OID,
+ KRB5_OID_LEN))
+ use_kerberos = TRUE;
+ else if (compare_oid(oid, oidlen,
+ NTLMSSP_OID,
+ NTLMSSP_OID_LEN))
use_ntlmssp = TRUE;
+
+ kfree(oid);
}
} else {
cFYI(1, ("Should be an oid what is going on?"));
@@ -609,12 +624,10 @@
ctx.pointer)); /* is this UTF-8 or ASCII? */
}
- /* if (use_kerberos)
- *secType = Kerberos
- else */
- if (use_ntlmssp) {
+ if (use_kerberos)
+ *secType = Kerberos;
+ else if (use_ntlmssp)
*secType = NTLMSSP;
- }
return 1;
}
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
new file mode 100644
index 0000000..ad54a3a
--- /dev/null
+++ b/fs/cifs/cifs_spnego.c
@@ -0,0 +1,128 @@
+/*
+ * fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS
+ *
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Author(s): Jeff Layton (jlayton@redhat.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/list.h>
+#include <linux/string.h>
+#include <keys/user-type.h>
+#include <linux/key-type.h>
+#include "cifsglob.h"
+#include "cifs_spnego.h"
+#include "cifs_debug.h"
+
+/* create a new cifs key */
+static int
+cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen)
+{
+ char *payload;
+ int ret;
+
+ ret = -ENOMEM;
+ payload = kmalloc(datalen, GFP_KERNEL);
+ if (!payload)
+ goto error;
+
+ /* attach the data */
+ memcpy(payload, data, datalen);
+ rcu_assign_pointer(key->payload.data, payload);
+ ret = 0;
+
+error:
+ return ret;
+}
+
+static void
+cifs_spnego_key_destroy(struct key *key)
+{
+ kfree(key->payload.data);
+}
+
+
+/*
+ * keytype for CIFS spnego keys
+ */
+struct key_type cifs_spnego_key_type = {
+ .name = "cifs.spnego",
+ .instantiate = cifs_spnego_key_instantiate,
+ .match = user_match,
+ .destroy = cifs_spnego_key_destroy,
+ .describe = user_describe,
+};
+
+/* get a key struct with a SPNEGO security blob, suitable for session setup */
+struct key *
+cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname)
+{
+ struct TCP_Server_Info *server = sesInfo->server;
+ char *description, *dp;
+ size_t desc_len;
+ struct key *spnego_key;
+
+
+ /* version + ;ip{4|6}= + address + ;host=hostname +
+ ;sec= + ;uid= + NULL */
+ desc_len = 4 + 5 + 32 + 1 + 5 + strlen(hostname) +
+ strlen(";sec=krb5") + 7 + sizeof(uid_t)*2 + 1;
+ spnego_key = ERR_PTR(-ENOMEM);
+ description = kzalloc(desc_len, GFP_KERNEL);
+ if (description == NULL)
+ goto out;
+
+ dp = description;
+ /* start with version and hostname portion of UNC string */
+ spnego_key = ERR_PTR(-EINVAL);
+ sprintf(dp, "0x%2.2x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION,
+ hostname);
+ dp = description + strlen(description);
+
+ /* add the server address */
+ if (server->addr.sockAddr.sin_family == AF_INET)
+ sprintf(dp, "ip4=" NIPQUAD_FMT,
+ NIPQUAD(server->addr.sockAddr.sin_addr));
+ else if (server->addr.sockAddr.sin_family == AF_INET6)
+ sprintf(dp, "ip6=" NIP6_SEQFMT,
+ NIP6(server->addr.sockAddr6.sin6_addr));
+ else
+ goto out;
+
+ dp = description + strlen(description);
+
+ /* for now, only sec=krb5 is valid */
+ if (server->secType == Kerberos)
+ sprintf(dp, ";sec=krb5");
+ else
+ goto out;
+
+ dp = description + strlen(description);
+ sprintf(dp, ";uid=0x%x", sesInfo->linux_uid);
+
+ cFYI(1, ("key description = %s", description));
+ spnego_key = request_key(&cifs_spnego_key_type, description, "");
+
+ if (cifsFYI && !IS_ERR(spnego_key)) {
+ struct cifs_spnego_msg *msg = spnego_key->payload.data;
+ cifs_dump_mem("SPNEGO reply blob:", msg->data,
+ msg->secblob_len + msg->sesskey_len);
+ }
+
+out:
+ kfree(description);
+ return spnego_key;
+}
diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h
new file mode 100644
index 0000000..f443f3b
--- /dev/null
+++ b/fs/cifs/cifs_spnego.h
@@ -0,0 +1,46 @@
+/*
+ * fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS
+ *
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Author(s): Jeff Layton (jlayton@redhat.com)
+ * Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _CIFS_SPNEGO_H
+#define _CIFS_SPNEGO_H
+
+#define CIFS_SPNEGO_UPCALL_VERSION 1
+
+/*
+ * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
+ * The flags field is for future use. The request-key callout should set
+ * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob
+ * and stuff it in the data field.
+ */
+struct cifs_spnego_msg {
+ uint32_t version;
+ uint32_t flags;
+ uint32_t sesskey_len;
+ uint32_t secblob_len;
+ uint8_t data[1];
+};
+
+#ifdef __KERNEL__
+extern struct key_type cifs_spnego_key_type;
+#endif /* KERNEL */
+
+#endif /* _CIFS_SPNEGO_H */
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index e8e5635..dabbce0 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -38,13 +38,13 @@
{{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
- {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"}
-};
+ {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} }
+;
/* security id for everyone */
-static const struct cifs_sid sid_everyone =
- {1, 1, {0, 0, 0, 0, 0, 0}, {} };
+static const struct cifs_sid sid_everyone = {
+ 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
/* group users */
static const struct cifs_sid sid_user =
{1, 2 , {0, 0, 0, 0, 0, 5}, {} };
@@ -97,7 +97,7 @@
/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
the same returns 1, if they do not match returns 0 */
-int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
+int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
{
int i;
int num_subauth, num_sat, num_saw;
@@ -129,66 +129,142 @@
return (1); /* sids compare/match */
}
+/*
+ change posix mode to reflect permissions
+ pmode is the existing mode (we only want to overwrite part of this
+ bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
+*/
+static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode,
+ umode_t *pbits_to_set)
+{
+ /* the order of ACEs is important. The canonical order is to begin with
+ DENY entries followed by ALLOW, otherwise an allow entry could be
+ encountered first, making the subsequent deny entry like "dead code"
+ which would be superflous since Windows stops when a match is made
+ for the operation you are trying to perform for your user */
-static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
+ /* For deny ACEs we change the mask so that subsequent allow access
+ control entries do not turn on the bits we are denying */
+ if (type == ACCESS_DENIED) {
+ if (ace_flags & GENERIC_ALL) {
+ *pbits_to_set &= ~S_IRWXUGO;
+ }
+ if ((ace_flags & GENERIC_WRITE) ||
+ ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
+ *pbits_to_set &= ~S_IWUGO;
+ if ((ace_flags & GENERIC_READ) ||
+ ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
+ *pbits_to_set &= ~S_IRUGO;
+ if ((ace_flags & GENERIC_EXECUTE) ||
+ ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
+ *pbits_to_set &= ~S_IXUGO;
+ return;
+ } else if (type != ACCESS_ALLOWED) {
+ cERROR(1, ("unknown access control type %d", type));
+ return;
+ }
+ /* else ACCESS_ALLOWED type */
+
+ if (ace_flags & GENERIC_ALL) {
+ *pmode |= (S_IRWXUGO & (*pbits_to_set));
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("all perms"));
+#endif
+ return;
+ }
+ if ((ace_flags & GENERIC_WRITE) ||
+ ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
+ *pmode |= (S_IWUGO & (*pbits_to_set));
+ if ((ace_flags & GENERIC_READ) ||
+ ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
+ *pmode |= (S_IRUGO & (*pbits_to_set));
+ if ((ace_flags & GENERIC_EXECUTE) ||
+ ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
+ *pmode |= (S_IXUGO & (*pbits_to_set));
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode));
+#endif
+ return;
+}
+
+/*
+ Generate access flags to reflect permissions mode is the existing mode.
+ This function is called for every ACE in the DACL whose SID matches
+ with either owner or group or everyone.
+*/
+
+static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
+ __u32 *pace_flags)
+{
+ /* reset access mask */
+ *pace_flags = 0x0;
+
+ /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
+ mode &= bits_to_use;
+
+ /* check for R/W/X UGO since we do not know whose flags
+ is this but we have cleared all the bits sans RWX for
+ either user or group or other as per bits_to_use */
+ if (mode & S_IRUGO)
+ *pace_flags |= SET_FILE_READ_RIGHTS;
+ if (mode & S_IWUGO)
+ *pace_flags |= SET_FILE_WRITE_RIGHTS;
+ if (mode & S_IXUGO)
+ *pace_flags |= SET_FILE_EXEC_RIGHTS;
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags));
+#endif
+ return;
+}
+
+
+#ifdef CONFIG_CIFS_DEBUG2
+static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
{
int num_subauth;
/* validate that we do not go past end of acl */
- /* XXX this if statement can be removed
- if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
+ if (le16_to_cpu(pace->size) < 16) {
+ cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size)));
+ return;
+ }
+
+ if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
cERROR(1, ("ACL too small to parse ACE"));
return;
- } */
+ }
- num_subauth = pace->num_subauth;
+ num_subauth = pace->sid.num_subauth;
if (num_subauth) {
-#ifdef CONFIG_CIFS_DEBUG2
int i;
- cFYI(1, ("ACE revision %d num_subauth %d",
- pace->revision, pace->num_subauth));
+ cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
+ pace->sid.revision, pace->sid.num_subauth, pace->type,
+ pace->flags, pace->size));
for (i = 0; i < num_subauth; ++i) {
cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
- le32_to_cpu(pace->sub_auth[i])));
+ le32_to_cpu(pace->sid.sub_auth[i])));
}
/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */
-
- cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1])));
-#endif
}
return;
}
-
-static void parse_ntace(struct cifs_ntace *pntace, char *end_of_acl)
-{
- /* validate that we do not go past end of acl */
- if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) {
- cERROR(1, ("ACL too small to parse NT ACE"));
- return;
- }
-
-#ifdef CONFIG_CIFS_DEBUG2
- cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x",
- pntace->type, pntace->flags, pntace->size,
- pntace->access_req));
#endif
- return;
-}
-
static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid)
+ struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
+ struct inode *inode)
{
int i;
int num_aces = 0;
int acl_size;
char *acl_base;
- struct cifs_ntace **ppntace;
struct cifs_ace **ppace;
/* BB need to add parm so we can store the SID BB */
@@ -205,50 +281,63 @@
le32_to_cpu(pdacl->num_aces)));
#endif
+ /* reset rwx permissions for user/group/other.
+ Also, if num_aces is 0 i.e. DACL has no ACEs,
+ user/group/other have no permissions */
+ inode->i_mode &= ~(S_IRWXUGO);
+
+ if (!pdacl) {
+ /* no DACL in the security descriptor, set
+ all the permissions for user/group/other */
+ inode->i_mode |= S_IRWXUGO;
+ return;
+ }
acl_base = (char *)pdacl;
acl_size = sizeof(struct cifs_acl);
num_aces = le32_to_cpu(pdacl->num_aces);
if (num_aces > 0) {
- ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *),
- GFP_KERNEL);
+ umode_t user_mask = S_IRWXU;
+ umode_t group_mask = S_IRWXG;
+ umode_t other_mask = S_IRWXO;
+
ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
GFP_KERNEL);
/* cifscred->cecount = pdacl->num_aces;
- cifscred->ntaces = kmalloc(num_aces *
- sizeof(struct cifs_ntace *), GFP_KERNEL);
cifscred->aces = kmalloc(num_aces *
sizeof(struct cifs_ace *), GFP_KERNEL);*/
for (i = 0; i < num_aces; ++i) {
- ppntace[i] = (struct cifs_ntace *)
- (acl_base + acl_size);
- ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] +
- sizeof(struct cifs_ntace));
+ ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
+#ifdef CONFIG_CIFS_DEBUG2
+ dump_ace(ppace[i], end_of_acl);
+#endif
+ if (compare_sids(&(ppace[i]->sid), pownersid))
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &(inode->i_mode),
+ &user_mask);
+ if (compare_sids(&(ppace[i]->sid), pgrpsid))
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &(inode->i_mode),
+ &group_mask);
+ if (compare_sids(&(ppace[i]->sid), &sid_everyone))
+ access_flags_to_mode(ppace[i]->access_req,
+ ppace[i]->type,
+ &(inode->i_mode),
+ &other_mask);
- parse_ntace(ppntace[i], end_of_acl);
- if (end_of_acl < ((char *)ppace[i] +
- (le16_to_cpu(ppntace[i]->size) -
- sizeof(struct cifs_ntace)))) {
- cERROR(1, ("ACL too small to parse ACE"));
- break;
- } else
- parse_ace(ppace[i], end_of_acl);
-
-/* memcpy((void *)(&(cifscred->ntaces[i])),
- (void *)ppntace[i],
- sizeof(struct cifs_ntace));
- memcpy((void *)(&(cifscred->aces[i])),
+/* memcpy((void *)(&(cifscred->aces[i])),
(void *)ppace[i],
sizeof(struct cifs_ace)); */
- acl_base = (char *)ppntace[i];
- acl_size = le16_to_cpu(ppntace[i]->size);
+ acl_base = (char *)ppace[i];
+ acl_size = le16_to_cpu(ppace[i]->size);
}
kfree(ppace);
- kfree(ppntace);
}
return;
@@ -257,20 +346,20 @@
static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
{
-
/* BB need to add parm so we can store the SID BB */
- /* validate that we do not go past end of acl */
- if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) {
- cERROR(1, ("ACL too small to parse SID"));
+ /* validate that we do not go past end of ACL - sid must be at least 8
+ bytes long (assuming no sub-auths - e.g. the null SID */
+ if (end_of_acl < (char *)psid + 8) {
+ cERROR(1, ("ACL too small to parse SID %p", psid));
return -EINVAL;
}
if (psid->num_subauth) {
#ifdef CONFIG_CIFS_DEBUG2
int i;
- cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
- psid->revision, psid->num_subauth, psid->sub_auth[0]));
+ cFYI(1, ("SID revision %d num_auth %d",
+ psid->revision, psid->num_subauth));
for (i = 0; i < psid->num_subauth; i++) {
cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
@@ -289,27 +378,32 @@
/* Convert CIFS ACL to POSIX form */
-int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
+static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
+ struct inode *inode)
{
int rc;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
char *end_of_acl = ((char *)pntsd) + acl_len;
+ __u32 dacloffset;
+
+ if ((inode == NULL) || (pntsd == NULL))
+ return -EIO;
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
- dacl_ptr = (struct cifs_acl *)((char *)pntsd +
- le32_to_cpu(pntsd->dacloffset));
+ dacloffset = le32_to_cpu(pntsd->dacloffset);
+ dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
"sacloffset 0x%x dacloffset 0x%x",
pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
le32_to_cpu(pntsd->gsidoffset),
- le32_to_cpu(pntsd->sacloffset),
- le32_to_cpu(pntsd->dacloffset)));
+ le32_to_cpu(pntsd->sacloffset), dacloffset));
#endif
+/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
rc = parse_sid(owner_sid_ptr, end_of_acl);
if (rc)
return rc;
@@ -318,16 +412,120 @@
if (rc)
return rc;
- parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr);
+ if (dacloffset)
+ parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
+ group_sid_ptr, inode);
+ else
+ cFYI(1, ("no ACL")); /* BB grant all or default perms? */
/* cifscred->uid = owner_sid_ptr->rid;
cifscred->gid = group_sid_ptr->rid;
memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
- sizeof (struct cifs_sid));
+ sizeof(struct cifs_sid));
memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
- sizeof (struct cifs_sid)); */
+ sizeof(struct cifs_sid)); */
return (0);
}
+
+
+/* Retrieve an ACL from the server */
+static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
+ const char *path)
+{
+ struct cifsFileInfo *open_file;
+ int unlock_file = FALSE;
+ int xid;
+ int rc = -EIO;
+ __u16 fid;
+ struct super_block *sb;
+ struct cifs_sb_info *cifs_sb;
+ struct cifs_ntsd *pntsd = NULL;
+
+ cFYI(1, ("get mode from ACL for %s", path));
+
+ if (inode == NULL)
+ return NULL;
+
+ xid = GetXid();
+ open_file = find_readable_file(CIFS_I(inode));
+ sb = inode->i_sb;
+ if (sb == NULL) {
+ FreeXid(xid);
+ return NULL;
+ }
+ cifs_sb = CIFS_SB(sb);
+
+ if (open_file) {
+ unlock_file = TRUE;
+ fid = open_file->netfid;
+ } else {
+ int oplock = FALSE;
+ /* open file */
+ rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
+ READ_CONTROL, 0, &fid, &oplock, NULL,
+ cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (rc != 0) {
+ cERROR(1, ("Unable to open file to get ACL"));
+ FreeXid(xid);
+ return NULL;
+ }
+ }
+
+ rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+ cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
+ if (unlock_file == TRUE)
+ atomic_dec(&open_file->wrtPending);
+ else
+ CIFSSMBClose(xid, cifs_sb->tcon, fid);
+
+ FreeXid(xid);
+ return pntsd;
+}
+
+/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
+void acl_to_uid_mode(struct inode *inode, const char *path)
+{
+ struct cifs_ntsd *pntsd = NULL;
+ u32 acllen = 0;
+ int rc = 0;
+
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("converting ACL to mode for %s", path));
+#endif
+ pntsd = get_cifs_acl(&acllen, inode, path);
+
+ /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
+ if (pntsd)
+ rc = parse_sec_desc(pntsd, acllen, inode);
+ if (rc)
+ cFYI(1, ("parse sec desc failed rc = %d", rc));
+
+ kfree(pntsd);
+ return;
+}
+
+/* Convert mode bits to an ACL so we can update the ACL on the server */
+int mode_to_acl(struct inode *inode, const char *path)
+{
+ int rc = 0;
+ __u32 acllen = 0;
+ struct cifs_ntsd *pntsd = NULL;
+
+ cFYI(1, ("set ACL from mode for %s", path));
+
+ /* Get the security descriptor */
+ pntsd = get_cifs_acl(&acllen, inode, path);
+
+ /* Add/Modify the three ACEs for owner, group, everyone
+ while retaining the other ACEs */
+
+ /* Set the security descriptor */
+
+
+ kfree(pntsd);
+ return rc;
+}
#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 420f878..93a7c34 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -35,6 +35,9 @@
#define UBITSHIFT 6
#define GBITSHIFT 3
+#define ACCESS_ALLOWED 0
+#define ACCESS_DENIED 1
+
struct cifs_ntsd {
__le16 revision; /* revision level */
__le16 type;
@@ -48,7 +51,7 @@
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[6];
- __le32 sub_auth[5]; /* sub_auth[num_subauth] */ /* BB FIXME endianness BB */
+ __le32 sub_auth[5]; /* sub_auth[num_subauth] */
} __attribute__((packed));
struct cifs_acl {
@@ -57,18 +60,12 @@
__le32 num_aces;
} __attribute__((packed));
-struct cifs_ntace { /* first part of ACE which contains perms */
+struct cifs_ace {
__u8 type;
__u8 flags;
__le16 size;
__le32 access_req;
-} __attribute__((packed));
-
-struct cifs_ace { /* last part of ACE which includes user info */
- __u8 revision; /* revision level */
- __u8 num_subauth;
- __u8 authority[6];
- __le32 sub_auth[5];
+ struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
} __attribute__((packed));
struct cifs_wksid {
@@ -79,7 +76,7 @@
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern int match_sid(struct cifs_sid *);
-extern int compare_sids(struct cifs_sid *, struct cifs_sid *);
+extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 632070b..4ff8939 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -99,15 +99,16 @@
MD5Init(&context);
MD5Update(&context, (char *)&key->data, key->len);
for (i = 0; i < n_vec; i++) {
+ if (iov[i].iov_len == 0)
+ continue;
if (iov[i].iov_base == NULL) {
cERROR(1, ("null iovec entry"));
return -EIO;
- } else if (iov[i].iov_len == 0)
- break; /* bail out if we are sent nothing to sign */
+ }
/* The first entry includes a length field (which does not get
signed that occupies the first 4 bytes before the header */
if (i == 0) {
- if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
+ if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
break; /* nothing to sign or corrupt header */
MD5Update(&context, iov[0].iov_base+4,
iov[0].iov_len-4);
@@ -122,7 +123,7 @@
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
- __u32 * pexpected_response_sequence_number)
+ __u32 *pexpected_response_sequence_number)
{
int rc = 0;
char smb_signature[20];
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index a6fbea5..416dc9f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -43,6 +43,8 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
#include <linux/mm.h>
+#include <linux/key-type.h>
+#include "cifs_spnego.h"
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
#ifdef CONFIG_CIFS_QUOTA
@@ -1005,12 +1007,16 @@
rc = register_filesystem(&cifs_fs_type);
if (rc)
goto out_destroy_request_bufs;
-
+#ifdef CONFIG_CIFS_UPCALL
+ rc = register_key_type(&cifs_spnego_key_type);
+ if (rc)
+ goto out_unregister_filesystem;
+#endif
oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
if (IS_ERR(oplockThread)) {
rc = PTR_ERR(oplockThread);
cERROR(1, ("error %d create oplock thread", rc));
- goto out_unregister_filesystem;
+ goto out_unregister_key_type;
}
dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
@@ -1024,7 +1030,11 @@
out_stop_oplock_thread:
kthread_stop(oplockThread);
+ out_unregister_key_type:
+#ifdef CONFIG_CIFS_UPCALL
+ unregister_key_type(&cifs_spnego_key_type);
out_unregister_filesystem:
+#endif
unregister_filesystem(&cifs_fs_type);
out_destroy_request_bufs:
cifs_destroy_request_bufs();
@@ -1046,6 +1056,9 @@
#ifdef CONFIG_PROC_FS
cifs_proc_clean();
#endif
+#ifdef CONFIG_CIFS_UPCALL
+ unregister_key_type(&cifs_spnego_key_type);
+#endif
unregister_filesystem(&cifs_fs_type);
cifs_destroy_inodecache();
cifs_destroy_mids();
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 5574ba3..2a21dc6 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -106,5 +106,5 @@
extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
-#define CIFS_VERSION "1.51"
+#define CIFS_VERSION "1.52"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index c41ff74..dbe6b84 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -220,6 +220,23 @@
| FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
+#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
+ | FILE_READ_EA | FILE_WRITE_EA \
+ | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
+ | FILE_READ_ATTRIBUTES \
+ | FILE_WRITE_ATTRIBUTES \
+ | DELETE | READ_CONTROL | WRITE_DAC \
+ | WRITE_OWNER | SYNCHRONIZE)
+
/*
* Invalid readdir handle
@@ -1211,6 +1228,29 @@
__le32 AclFlags;
} __attribute__((packed)) QUERY_SEC_DESC_REQ;
+
+typedef struct smb_com_transaction_ssec_req {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* no setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 3 = SET_SECURITY_DESC */
+ __le16 ByteCount; /* bcc = 3 + 8 */
+ __u8 Pad[3];
+ __u16 Fid;
+ __u16 Reserved2;
+ __le32 AclFlags;
+} __attribute__((packed)) SET_SEC_DESC_REQ;
+
typedef struct smb_com_transaction_change_notify_req {
struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1a88366..dd1d7c2 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -61,6 +61,9 @@
extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
+#endif
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
@@ -73,6 +76,8 @@
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifsSesInfo *ses,
void **request_buf);
+extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo,
+ const char *hostname);
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
const int stage,
const struct nls_table *nls_cp);
@@ -92,6 +97,8 @@
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb, int xid);
+extern void acl_to_uid_mode(struct inode *inode, const char *search_path);
+extern int mode_to_acl(struct inode *inode, const char *path);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *);
@@ -311,7 +318,6 @@
#ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */
-extern int parse_sec_desc(struct cifs_ntsd *, int);
extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon,
const char *fromName,
@@ -336,8 +342,7 @@
const void *ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
- __u16 fid, char *acl_inf, const int buflen,
- const int acl_type /* ACCESS vs. DEFAULT */);
+ __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen, const int acl_type,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index f0d9a48..59d7b7c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -647,8 +647,7 @@
count - 16,
&server->secType);
if (rc == 1) {
- /* BB Need to fill struct for sessetup here */
- rc = -EOPNOTSUPP;
+ rc = 0;
} else {
rc = -EINVAL;
}
@@ -2486,6 +2485,7 @@
return rc;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
/* Initialize NT TRANSACT SMB into small smb request buffer.
This assumes that all NT TRANSACTS that we init here have
total parm and data under about 400 bytes (to fit in small cifs
@@ -2494,7 +2494,7 @@
MaxSetupCount (size of returned setup area) and
MaxParameterCount (returned parms size) must be set by caller */
static int
-smb_init_ntransact(const __u16 sub_command, const int setup_count,
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
const int parm_len, struct cifsTconInfo *tcon,
void **ret_buf)
{
@@ -2525,12 +2525,15 @@
static int
validate_ntransact(char *buf, char **ppparm, char **ppdata,
- int *pdatalen, int *pparmlen)
+ __u32 *pparmlen, __u32 *pdatalen)
{
char *end_of_smb;
__u32 data_count, data_offset, parm_count, parm_offset;
struct smb_com_ntransact_rsp *pSMBr;
+ *pdatalen = 0;
+ *pparmlen = 0;
+
if (buf == NULL)
return -EINVAL;
@@ -2567,8 +2570,11 @@
cFYI(1, ("parm count and data count larger than SMB"));
return -EINVAL;
}
+ *pdatalen = data_count;
+ *pparmlen = parm_count;
return 0;
}
+#endif /* CIFS_EXPERIMENTAL */
int
CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3067,8 +3073,7 @@
/* Get Security Descriptor (by handle) from remote server for a file or dir */
int
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
- /* BB fix up return info */ char *acl_inf, const int buflen,
- const int acl_type)
+ struct cifs_ntsd **acl_inf, __u32 *pbuflen)
{
int rc = 0;
int buf_type = 0;
@@ -3077,7 +3082,10 @@
cFYI(1, ("GetCifsACL"));
- rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
+ *pbuflen = 0;
+ *acl_inf = NULL;
+
+ rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
8 /* parm len */, tcon, (void **) &pSMB);
if (rc)
return rc;
@@ -3099,34 +3107,52 @@
if (rc) {
cFYI(1, ("Send error in QuerySecDesc = %d", rc));
} else { /* decode response */
- struct cifs_ntsd *psec_desc;
__le32 * parm;
- int parm_len;
- int data_len;
- int acl_len;
+ __u32 parm_len;
+ __u32 acl_len;
struct smb_com_ntransact_rsp *pSMBr;
+ char *pdata;
/* validate_nttransact */
rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
- (char **)&psec_desc,
- &parm_len, &data_len);
+ &pdata, &parm_len, pbuflen);
if (rc)
goto qsec_out;
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
- cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
+ cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
rc = -EIO; /* bad smb */
+ *pbuflen = 0;
goto qsec_out;
}
/* BB check that data area is minimum length and as big as acl_len */
acl_len = le32_to_cpu(*parm);
- /* BB check if (acl_len > bufsize) */
+ if (acl_len != *pbuflen) {
+ cERROR(1, ("acl length %d does not match %d",
+ acl_len, *pbuflen));
+ if (*pbuflen > acl_len)
+ *pbuflen = acl_len;
+ }
- parse_sec_desc(psec_desc, acl_len);
+ /* check if buffer is big enough for the acl
+ header followed by the smallest SID */
+ if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
+ (*pbuflen >= 64 * 1024)) {
+ cERROR(1, ("bad acl length %d", *pbuflen));
+ rc = -EINVAL;
+ *pbuflen = 0;
+ } else {
+ *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
+ if (*acl_inf == NULL) {
+ *pbuflen = 0;
+ rc = -ENOMEM;
+ }
+ memcpy(*acl_inf, pdata, *pbuflen);
+ }
}
qsec_out:
if (buf_type == CIFS_SMALL_BUFFER)
@@ -3381,7 +3407,7 @@
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
data_offset,
- sizeof (FILE_UNIX_BASIC_INFO));
+ sizeof(FILE_UNIX_BASIC_INFO));
}
}
cifs_buf_release(pSMB);
@@ -3649,7 +3675,7 @@
pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
pSMB->SearchHandle = searchHandle; /* always kept as le */
pSMB->SearchCount =
- cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
+ cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
pSMB->ResumeKey = psrch_inf->resume_key;
pSMB->SearchFlags =
@@ -4331,7 +4357,7 @@
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
+ if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
rc = -EIO; /* bad smb */
else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 19ee11f..c52a76f 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -160,7 +160,7 @@
if (server->ssocket) {
cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
server->ssocket->flags));
- server->ssocket->ops->shutdown(server->ssocket, SEND_SHUTDOWN);
+ kernel_sock_shutdown(server->ssocket, SHUT_WR);
cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
server->ssocket->state,
server->ssocket->flags));
@@ -793,7 +793,7 @@
vol->linux_gid = current->gid;
vol->dir_mode = S_IRWXUGO;
/* 2767 perms indicate mandatory locking support */
- vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
+ vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = TRUE;
@@ -1790,7 +1790,7 @@
if (volume_info.nullauth) {
cFYI(1, ("null user"));
- volume_info.username = NULL;
+ volume_info.username = "";
} else if (volume_info.username) {
/* BB fixme parse for domain name here */
cFYI(1, ("Username: %s", volume_info.username));
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 793404b..37dc97a 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -593,7 +593,7 @@
* case take precedence. If a is not a negative dentry, this
* should have no side effects
*/
- memcpy((unsigned char *)a->name, b->name, a->len);
+ memcpy(a->name, b->name, a->len);
return 0;
}
return 1;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 1e7e4c0..68ad4ca 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1026,6 +1026,37 @@
return total_written;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
+{
+ struct cifsFileInfo *open_file = NULL;
+
+ read_lock(&GlobalSMBSeslock);
+ /* we could simply get the first_list_entry since write-only entries
+ are always at the end of the list but since the first entry might
+ have a close pending, we go through the whole list */
+ list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
+ if (open_file->closePend)
+ continue;
+ if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_RDONLY))) {
+ if (!open_file->invalidHandle) {
+ /* found a good file */
+ /* lock it so it will not be closed on us */
+ atomic_inc(&open_file->wrtPending);
+ read_unlock(&GlobalSMBSeslock);
+ return open_file;
+ } /* else might as well continue, and look for
+ another, or simply have the caller reopen it
+ again rather than trying to fix this handle */
+ } else /* write only file */
+ break; /* write only files are last so must be done */
+ }
+ read_unlock(&GlobalSMBSeslock);
+ return NULL;
+}
+#endif
+
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *open_file;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 5e8b388..7d907e8 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -289,7 +289,7 @@
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
-static int get_sfu_uid_mode(struct inode *inode,
+static int get_sfu_mode(struct inode *inode,
const unsigned char *path,
struct cifs_sb_info *cifs_sb, int xid)
{
@@ -527,11 +527,16 @@
/* BB fill in uid and gid here? with help from winbind?
or retrieve from NTFS stream extended attribute */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ /* fill in 0777 bits from ACL */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+ cFYI(1, ("Getting mode bits from ACL"));
+ acl_to_uid_mode(inode, search_path);
+ }
+#endif
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
- /* fill in uid, gid, mode from server ACL */
- /* BB FIXME this should also take into account the
- * default uid specified on mount if present */
- get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
+ /* fill in remaining high mode bits e.g. SUID, VTX */
+ get_sfu_mode(inode, search_path, cifs_sb, xid);
} else if (atomic_read(&cifsInfo->inUse) == 0) {
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c
index e5c3e12..f13f96d 100644
--- a/fs/cifs/md5.c
+++ b/fs/cifs/md5.c
@@ -276,8 +276,8 @@
}
/* start out by storing key in pads */
- memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
- memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+ memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
+ memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
memcpy(ctx->k_ipad, key, key_len);
memcpy(ctx->k_opad, key, key_len);
@@ -307,8 +307,8 @@
}
/* start out by storing key in pads */
- memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
- memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+ memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
+ memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
memcpy(ctx->k_ipad, key, key_len);
memcpy(ctx->k_opad, key, key_len);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 51ec681..15546c2 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -73,7 +73,7 @@
{
struct cifsSesInfo *ret_buf;
- ret_buf = kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL);
+ ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
if (ret_buf) {
write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount);
@@ -109,7 +109,7 @@
tconInfoAlloc(void)
{
struct cifsTconInfo *ret_buf;
- ret_buf = kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL);
+ ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
if (ret_buf) {
write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount);
@@ -298,7 +298,7 @@
memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
buffer->smb_buf_length =
- (2 * word_count) + sizeof (struct smb_hdr) -
+ (2 * word_count) + sizeof(struct smb_hdr) -
4 /* RFC 1001 length field does not count */ +
2 /* for bcc field itself */ ;
/* Note that this is the only network field that has to be converted
@@ -422,8 +422,8 @@
__u32 clc_len; /* calculated length */
cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
- if (length < 2 + sizeof (struct smb_hdr)) {
- if ((length >= sizeof (struct smb_hdr) - 1)
+ if (length < 2 + sizeof(struct smb_hdr)) {
+ if ((length >= sizeof(struct smb_hdr) - 1)
&& (smb->Status.CifsError != 0)) {
smb->WordCount = 0;
/* some error cases do not return wct and bcc */
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index f06359c..646e1f0 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -132,6 +132,34 @@
{0, 0}
};
+
+/* if the mount helper is missing we need to reverse the 1st slash
+ from '/' to backslash in order to format the UNC properly for
+ ip address parsing and for tree connect (unless the user
+ remembered to put the UNC name in properly). Fortunately we do
+ not have to call this twice (we check for IPv4 addresses
+ first, so it is already converted by the time we
+ try IPv6 addresses */
+static int canonicalize_unc(char *cp)
+{
+ int i;
+
+ for (i = 0; i <= 46 /* INET6_ADDRSTRLEN */ ; i++) {
+ if (cp[i] == 0)
+ break;
+ if (cp[i] == '\\')
+ break;
+ if (cp[i] == '/') {
+#ifdef CONFIG_CIFS_DEBUG2
+ cFYI(1, ("change slash to backslash in malformed UNC"));
+#endif
+ cp[i] = '\\';
+ return 1;
+ }
+ }
+ return 0;
+}
+
/* Convert string containing dotted ip address to binary form */
/* returns 0 if invalid address */
@@ -141,11 +169,13 @@
int ret = 0;
/* calculate length by finding first slash or NULL */
- /* BB Should we convert '/' slash to '\' here since it seems already
- * done before this */
- if ( address_family == AF_INET ) {
- ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
- } else if ( address_family == AF_INET6 ) {
+ if (address_family == AF_INET) {
+ ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL);
+ if (ret == 0) {
+ if (canonicalize_unc(cp))
+ ret = in4_pton(cp, -1, dst, '\\', NULL);
+ }
+ } else if (address_family == AF_INET6) {
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
}
#ifdef CONFIG_CIFS_DEBUG2
@@ -740,7 +770,7 @@
static void
-ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
+ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
{
int i;
if (ntstatus == 0) {
@@ -793,8 +823,8 @@
if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */
for (i = 0;
i <
- sizeof (mapping_table_ERRDOS) /
- sizeof (struct smb_to_posix_error); i++) {
+ sizeof(mapping_table_ERRDOS) /
+ sizeof(struct smb_to_posix_error); i++) {
if (mapping_table_ERRDOS[i].smb_err == 0)
break;
else if (mapping_table_ERRDOS[i].smb_err ==
@@ -807,8 +837,8 @@
} else if (smberrclass == ERRSRV) { /* server class of error codes */
for (i = 0;
i <
- sizeof (mapping_table_ERRSRV) /
- sizeof (struct smb_to_posix_error); i++) {
+ sizeof(mapping_table_ERRSRV) /
+ sizeof(struct smb_to_posix_error); i++) {
if (mapping_table_ERRSRV[i].smb_err == 0)
break;
else if (mapping_table_ERRSRV[i].smb_err ==
@@ -837,14 +867,14 @@
unsigned int
smbCalcSize(struct smb_hdr *ptr)
{
- return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+ return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
2 /* size of the bcc field */ + BCC(ptr));
}
unsigned int
smbCalcSize_LE(struct smb_hdr *ptr)
{
- return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+ return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 3746580..0f22def 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -171,7 +171,13 @@
/* Linux can not store file creation time unfortunately so ignore it */
cifsInfo->cifsAttrs = attr;
- cifsInfo->time = jiffies;
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+ /* get more accurate mode via ACL - so force inode refresh */
+ cifsInfo->time = 0;
+ } else
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+ cifsInfo->time = jiffies;
/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
/* 2767 perms - indicate mandatory locking */
@@ -495,7 +501,7 @@
static int cifs_unicode_bytelen(char *str)
{
int len;
- __le16 * ustr = (__le16 *)str;
+ __le16 *ustr = (__le16 *)str;
for (len = 0; len <= PATH_MAX; len++) {
if (ustr[len] == 0)
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 90542a3..58bbfd9 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -80,7 +80,7 @@
/* Routines for Windows NT MD4 Hash functions. */
static int
-_my_wcslen(__u16 * str)
+_my_wcslen(__u16 *str)
{
int len = 0;
while (*str++ != 0)
@@ -96,7 +96,7 @@
*/
static int
-_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
+_my_mbstowcs(__u16 *dst, const unsigned char *src, int len)
{ /* BB not a very good conversion routine - change/fix */
int i;
__u16 val;
@@ -125,9 +125,9 @@
/* Password cannot be longer than 128 characters */
if (passwd) {
len = strlen((char *) passwd);
- if (len > 128) {
+ if (len > 128)
len = 128;
- }
+
/* Password must be converted to NT unicode */
_my_mbstowcs(wpwd, passwd, len);
} else
@@ -135,7 +135,7 @@
wpwd[len] = 0; /* Ensure string is null terminated */
/* Calculate length in bytes */
- len = _my_wcslen(wpwd) * sizeof (__u16);
+ len = _my_wcslen(wpwd) * sizeof(__u16);
mdfour(p16, (unsigned char *) wpwd, len);
memset(wpwd, 0, 129 * 2);
@@ -167,7 +167,7 @@
E_P16((unsigned char *) passwd, (unsigned char *) p16);
/* clear out local copy of user's password (just being paranoid). */
- memset(passwd, '\0', sizeof (passwd));
+ memset(passwd, '\0', sizeof(passwd));
}
#endif
@@ -189,8 +189,10 @@
return;
dom_u = user_u + 1024;
- /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
- push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
+ /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2,
+ STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+ push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2,
+ STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
/* BB user and domain may need to be uppercased */
user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 369e838..54e8ef9 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -265,7 +265,9 @@
else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
__u16 fid;
int oplock = FALSE;
- if (experimEnabled)
+ struct cifs_ntsd *pacl = NULL;
+ __u32 buflen = 0;
+ if (experimEnabled)
rc = CIFSSMBOpen(xid, pTcon, full_path,
FILE_OPEN, GENERIC_READ, 0, &fid,
&oplock, NULL, cifs_sb->local_nls,
@@ -273,10 +275,9 @@
CIFS_MOUNT_MAP_SPECIAL_CHR);
/* else rc is EOPNOTSUPP from above */
- if(rc == 0) {
- rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
- ea_value, buf_size,
- ACL_TYPE_ACCESS);
+ if (rc == 0) {
+ rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl,
+ &buflen);
CIFSSMBClose(xid, pTcon, fid);
}
}
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 2150edf..6b7474a 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -87,7 +87,7 @@
loff_t offset;
int rc;
- offset = ((((off_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
+ offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT)
+ offset_in_page);
virt = kmap(page_for_lower);
rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size);
diff --git a/fs/exec.c b/fs/exec.c
index 2c942e2..4ccaaa4 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1692,7 +1692,10 @@
if (!binfmt || !binfmt->core_dump)
goto fail;
down_write(&mm->mmap_sem);
- if (!get_dumpable(mm)) {
+ /*
+ * If another thread got here first, or we are not dumpable, bail out.
+ */
+ if (mm->core_waiters || !get_dumpable(mm)) {
up_write(&mm->mmap_sem);
goto fail;
}
@@ -1706,7 +1709,6 @@
flag = O_EXCL; /* Stop rewrite attacks */
current->fsuid = 0; /* Dump root private */
}
- set_dumpable(mm, 0);
retval = coredump_wait(exit_code);
if (retval < 0)
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 18a42de..377ad17 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -69,14 +69,6 @@
return desc + offset;
}
-static inline int
-block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
-{
- return ext2_test_bit ((block -
- le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block)) %
- EXT2_BLOCKS_PER_GROUP(sb), map);
-}
-
/*
* Read the bitmap for a given block_group, reading into the specified
* slot in the superblock's bitmap cache.
@@ -86,51 +78,20 @@
static struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group)
{
- int i;
struct ext2_group_desc * desc;
struct buffer_head * bh = NULL;
- unsigned int bitmap_blk;
-
+
desc = ext2_get_group_desc (sb, block_group, NULL);
if (!desc)
- return NULL;
- bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
- bh = sb_bread(sb, bitmap_blk);
+ goto error_out;
+ bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
if (!bh)
- ext2_error (sb, __FUNCTION__,
+ ext2_error (sb, "read_block_bitmap",
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %u",
block_group, le32_to_cpu(desc->bg_block_bitmap));
-
- /* check whether block bitmap block number is set */
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- /* check whether the inode bitmap block number is set */
- bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- /* check whether the inode table block number is set */
- bitmap_blk = le32_to_cpu(desc->bg_inode_table);
- for (i = 0; i < EXT2_SB(sb)->s_itb_per_group; i++, bitmap_blk++) {
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- }
-
- return bh;
-
error_out:
- brelse(bh);
- ext2_error(sb, __FUNCTION__,
- "Invalid block bitmap - "
- "block_group = %d, block = %u",
- block_group, bitmap_blk);
- return NULL;
+ return bh;
}
static void release_blocks(struct super_block *sb, int count)
@@ -1461,7 +1422,6 @@
#endif
}
-
static inline int test_root(int a, int b)
{
int num = b;
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index c2324d5..320b2cb 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -47,6 +47,11 @@
flags &= ~EXT2_DIRSYNC_FL;
mutex_lock(&inode->i_mutex);
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+ return -EPERM;
+ }
oldflags = ei->i_flags;
/*
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 7a87d15..a8ba7e8 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -80,14 +80,6 @@
return desc + offset;
}
-static inline int
-block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map)
-{
- return ext3_test_bit ((block -
- le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
- EXT3_BLOCKS_PER_GROUP(sb), map);
-}
-
/**
* read_block_bitmap()
* @sb: super block
@@ -101,51 +93,20 @@
static struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group)
{
- int i;
struct ext3_group_desc * desc;
struct buffer_head * bh = NULL;
- ext3_fsblk_t bitmap_blk;
desc = ext3_get_group_desc (sb, block_group, NULL);
if (!desc)
- return NULL;
- bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
- bh = sb_bread(sb, bitmap_blk);
+ goto error_out;
+ bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
if (!bh)
- ext3_error (sb, __FUNCTION__,
+ ext3_error (sb, "read_block_bitmap",
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %u",
block_group, le32_to_cpu(desc->bg_block_bitmap));
-
- /* check whether block bitmap block number is set */
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- /* check whether the inode bitmap block number is set */
- bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- /* check whether the inode table block number is set */
- bitmap_blk = le32_to_cpu(desc->bg_inode_table);
- for (i = 0; i < EXT3_SB(sb)->s_itb_per_group; i++, bitmap_blk++) {
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- }
-
- return bh;
-
error_out:
- brelse(bh);
- ext3_error(sb, __FUNCTION__,
- "Invalid block bitmap - "
- "block_group = %d, block = %lu",
- block_group, bitmap_blk);
- return NULL;
+ return bh;
}
/*
* The reservation window structure operations
@@ -1772,7 +1733,6 @@
#endif
}
-
static inline int test_root(int a, int b)
{
int num = b;
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index c8e4ee3..8ca3bfd 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -67,7 +67,7 @@
unsigned long offset)
{
const char * error_msg = NULL;
- const int rlen = le16_to_cpu(de->rec_len);
+ const int rlen = ext3_rec_len_from_disk(de->rec_len);
if (rlen < EXT3_DIR_REC_LEN(1))
error_msg = "rec_len is smaller than minimal";
@@ -173,10 +173,10 @@
* least that it is non-zero. A
* failure will be detected in the
* dirent test below. */
- if (le16_to_cpu(de->rec_len) <
+ if (ext3_rec_len_from_disk(de->rec_len) <
EXT3_DIR_REC_LEN(1))
break;
- i += le16_to_cpu(de->rec_len);
+ i += ext3_rec_len_from_disk(de->rec_len);
}
offset = i;
filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
@@ -197,7 +197,7 @@
ret = stored;
goto out;
}
- offset += le16_to_cpu(de->rec_len);
+ offset += ext3_rec_len_from_disk(de->rec_len);
if (le32_to_cpu(de->inode)) {
/* We might block in the next section
* if the data destination is
@@ -219,7 +219,7 @@
goto revalidate;
stored ++;
}
- filp->f_pos += le16_to_cpu(de->rec_len);
+ filp->f_pos += ext3_rec_len_from_disk(de->rec_len);
}
offset = 0;
brelse (bh);
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 4a2a02c..023a070 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -51,6 +51,11 @@
flags &= ~EXT3_DIRSYNC_FL;
mutex_lock(&inode->i_mutex);
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+ return -EPERM;
+ }
oldflags = ei->i_flags;
/* The JOURNAL_DATA flag is modifiable only by root */
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index ec8170a..4ab6f76 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -177,6 +177,16 @@
struct inode *inode);
/*
+ * p is at least 6 bytes before the end of page
+ */
+static inline struct ext3_dir_entry_2 *
+ext3_next_entry(struct ext3_dir_entry_2 *p)
+{
+ return (struct ext3_dir_entry_2 *)((char *)p +
+ ext3_rec_len_from_disk(p->rec_len));
+}
+
+/*
* Future: use high four bits of block for coalesce-on-delete flags
* Mask them off for now.
*/
@@ -280,7 +290,7 @@
space += EXT3_DIR_REC_LEN(de->name_len);
names++;
}
- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
}
printk("(%i)\n", names);
return (struct stats) { names, space, 1 };
@@ -547,14 +557,6 @@
/*
- * p is at least 6 bytes before the end of page
- */
-static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p)
-{
- return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len));
-}
-
-/*
* This function fills a red-black tree with information from a
* directory block. It returns the number directory entries loaded
* into the tree. If there is an error it is returned in err.
@@ -720,7 +722,7 @@
cond_resched();
}
/* XXX: do we need to check rec_len == 0 case? -Chris */
- de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
}
return count;
}
@@ -822,7 +824,7 @@
return 1;
}
/* prevent looping on a bad block */
- de_len = le16_to_cpu(de->rec_len);
+ de_len = ext3_rec_len_from_disk(de->rec_len);
if (de_len <= 0)
return -1;
offset += de_len;
@@ -1130,7 +1132,7 @@
rec_len = EXT3_DIR_REC_LEN(de->name_len);
memcpy (to, de, rec_len);
((struct ext3_dir_entry_2 *) to)->rec_len =
- cpu_to_le16(rec_len);
+ ext3_rec_len_to_disk(rec_len);
de->inode = 0;
map++;
to += rec_len;
@@ -1149,13 +1151,12 @@
prev = to = de;
while ((char*)de < base + size) {
- next = (struct ext3_dir_entry_2 *) ((char *) de +
- le16_to_cpu(de->rec_len));
+ next = ext3_next_entry(de);
if (de->inode && de->name_len) {
rec_len = EXT3_DIR_REC_LEN(de->name_len);
if (de > to)
memmove(to, de, rec_len);
- to->rec_len = cpu_to_le16(rec_len);
+ to->rec_len = ext3_rec_len_to_disk(rec_len);
prev = to;
to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len);
}
@@ -1229,8 +1230,8 @@
/* Fancy dance to stay within two buffers */
de2 = dx_move_dirents(data1, data2, map + split, count - split);
de = dx_pack_dirents(data1,blocksize);
- de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
- de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+ de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de);
+ de2->rec_len = ext3_rec_len_to_disk(data2 + blocksize - (char *) de2);
dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
@@ -1300,7 +1301,7 @@
return -EEXIST;
}
nlen = EXT3_DIR_REC_LEN(de->name_len);
- rlen = le16_to_cpu(de->rec_len);
+ rlen = ext3_rec_len_from_disk(de->rec_len);
if ((de->inode? rlen - nlen: rlen) >= reclen)
break;
de = (struct ext3_dir_entry_2 *)((char *)de + rlen);
@@ -1319,11 +1320,11 @@
/* By now the buffer is marked for journaling */
nlen = EXT3_DIR_REC_LEN(de->name_len);
- rlen = le16_to_cpu(de->rec_len);
+ rlen = ext3_rec_len_from_disk(de->rec_len);
if (de->inode) {
struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen);
- de1->rec_len = cpu_to_le16(rlen - nlen);
- de->rec_len = cpu_to_le16(nlen);
+ de1->rec_len = ext3_rec_len_to_disk(rlen - nlen);
+ de->rec_len = ext3_rec_len_to_disk(nlen);
de = de1;
}
de->file_type = EXT3_FT_UNKNOWN;
@@ -1400,17 +1401,18 @@
/* The 0th block becomes the root, move the dirents out */
fde = &root->dotdot;
- de = (struct ext3_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len));
+ de = (struct ext3_dir_entry_2 *)((char *)fde +
+ ext3_rec_len_from_disk(fde->rec_len));
len = ((char *) root) + blocksize - (char *) de;
memcpy (data1, de, len);
de = (struct ext3_dir_entry_2 *) data1;
top = data1 + len;
- while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top)
+ while ((char *)(de2 = ext3_next_entry(de)) < top)
de = de2;
- de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+ de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de);
/* Initialize the root; the dot dirents already exist */
de = (struct ext3_dir_entry_2 *) (&root->dotdot);
- de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
+ de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2));
memset (&root->info, 0, sizeof(root->info));
root->info.info_length = sizeof(root->info);
root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
@@ -1490,7 +1492,7 @@
return retval;
de = (struct ext3_dir_entry_2 *) bh->b_data;
de->inode = 0;
- de->rec_len = cpu_to_le16(blocksize);
+ de->rec_len = ext3_rec_len_to_disk(blocksize);
return add_dirent_to_buf(handle, dentry, inode, de, bh);
}
@@ -1553,7 +1555,7 @@
goto cleanup;
node2 = (struct dx_node *)(bh2->b_data);
entries2 = node2->entries;
- node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+ node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize);
node2->fake.inode = 0;
BUFFER_TRACE(frame->bh, "get_write_access");
err = ext3_journal_get_write_access(handle, frame->bh);
@@ -1651,9 +1653,9 @@
BUFFER_TRACE(bh, "get_write_access");
ext3_journal_get_write_access(handle, bh);
if (pde)
- pde->rec_len =
- cpu_to_le16(le16_to_cpu(pde->rec_len) +
- le16_to_cpu(de->rec_len));
+ pde->rec_len = ext3_rec_len_to_disk(
+ ext3_rec_len_from_disk(pde->rec_len) +
+ ext3_rec_len_from_disk(de->rec_len));
else
de->inode = 0;
dir->i_version++;
@@ -1661,10 +1663,9 @@
ext3_journal_dirty_metadata(handle, bh);
return 0;
}
- i += le16_to_cpu(de->rec_len);
+ i += ext3_rec_len_from_disk(de->rec_len);
pde = de;
- de = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
}
return -ENOENT;
}
@@ -1798,13 +1799,13 @@
de = (struct ext3_dir_entry_2 *) dir_block->b_data;
de->inode = cpu_to_le32(inode->i_ino);
de->name_len = 1;
- de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
+ de->rec_len = ext3_rec_len_to_disk(EXT3_DIR_REC_LEN(de->name_len));
strcpy (de->name, ".");
ext3_set_de_type(dir->i_sb, de, S_IFDIR);
- de = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ de = ext3_next_entry(de);
de->inode = cpu_to_le32(dir->i_ino);
- de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+ de->rec_len = ext3_rec_len_to_disk(inode->i_sb->s_blocksize -
+ EXT3_DIR_REC_LEN(1));
de->name_len = 2;
strcpy (de->name, "..");
ext3_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -1856,8 +1857,7 @@
return 1;
}
de = (struct ext3_dir_entry_2 *) bh->b_data;
- de1 = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ de1 = ext3_next_entry(de);
if (le32_to_cpu(de->inode) != inode->i_ino ||
!le32_to_cpu(de1->inode) ||
strcmp (".", de->name) ||
@@ -1868,9 +1868,9 @@
brelse (bh);
return 1;
}
- offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
- de = (struct ext3_dir_entry_2 *)
- ((char *) de1 + le16_to_cpu(de1->rec_len));
+ offset = ext3_rec_len_from_disk(de->rec_len) +
+ ext3_rec_len_from_disk(de1->rec_len);
+ de = ext3_next_entry(de1);
while (offset < inode->i_size ) {
if (!bh ||
(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
@@ -1899,9 +1899,8 @@
brelse (bh);
return 0;
}
- offset += le16_to_cpu(de->rec_len);
- de = (struct ext3_dir_entry_2 *)
- ((char *) de + le16_to_cpu(de->rec_len));
+ offset += ext3_rec_len_from_disk(de->rec_len);
+ de = ext3_next_entry(de);
}
brelse (bh);
return 1;
@@ -2255,8 +2254,7 @@
}
#define PARENT_INO(buffer) \
- ((struct ext3_dir_entry_2 *) ((char *) buffer + \
- le16_to_cpu(((struct ext3_dir_entry_2 *) buffer)->rec_len)))->inode
+ (ext3_next_entry((struct ext3_dir_entry_2 *)(buffer))->inode)
/*
* Anybody can rename anything with this: the permission checks are left to the
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index e906b65..71ee95e 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -189,15 +189,6 @@
return desc;
}
-static inline int
-block_in_use(ext4_fsblk_t block, struct super_block *sb, unsigned char *map)
-{
- ext4_grpblk_t offset;
-
- ext4_get_group_no_and_offset(sb, block, NULL, &offset);
- return ext4_test_bit (offset, map);
-}
-
/**
* read_block_bitmap()
* @sb: super block
@@ -211,7 +202,6 @@
struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group)
{
- int i;
struct ext4_group_desc * desc;
struct buffer_head * bh = NULL;
ext4_fsblk_t bitmap_blk;
@@ -239,38 +229,7 @@
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %llu",
block_group, bitmap_blk);
-
- /* check whether block bitmap block number is set */
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
-
- /* check whether the inode bitmap block number is set */
- bitmap_blk = ext4_inode_bitmap(sb, desc);
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- /* check whether the inode table block number is set */
- bitmap_blk = ext4_inode_table(sb, desc);
- for (i = 0; i < EXT4_SB(sb)->s_itb_per_group; i++, bitmap_blk++) {
- if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
- /* bad block bitmap */
- goto error_out;
- }
- }
-
return bh;
-
-error_out:
- brelse(bh);
- ext4_error(sb, __FUNCTION__,
- "Invalid block bitmap - "
- "block_group = %d, block = %llu",
- block_group, bitmap_blk);
- return NULL;
-
}
/*
* The reservation window structure operations
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index c04c7cc..e7f894b 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -51,6 +51,11 @@
flags &= ~EXT4_DIRSYNC_FL;
mutex_lock(&inode->i_mutex);
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode)) {
+ mutex_unlock(&inode->i_mutex);
+ return -EPERM;
+ }
oldflags = ei->i_flags;
/* The JOURNAL_DATA flag is modifiable only by root */
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 0fcdba9..535b373 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -55,9 +55,10 @@
if (!ff->reserved_req) {
kfree(ff);
ff = NULL;
+ } else {
+ INIT_LIST_HEAD(&ff->write_entry);
+ atomic_set(&ff->count, 0);
}
- INIT_LIST_HEAD(&ff->write_entry);
- atomic_set(&ff->count, 0);
}
return ff;
}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 12aca8e..09ee07f 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -364,7 +364,6 @@
++next;
truncate_huge_page(page);
unlock_page(page);
- hugetlb_put_quota(mapping);
freed++;
}
huge_pagevec_release(&pvec);
@@ -859,15 +858,15 @@
return -ENOMEM;
}
-int hugetlb_get_quota(struct address_space *mapping)
+int hugetlb_get_quota(struct address_space *mapping, long delta)
{
int ret = 0;
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);
if (sbinfo->free_blocks > -1) {
spin_lock(&sbinfo->stat_lock);
- if (sbinfo->free_blocks > 0)
- sbinfo->free_blocks--;
+ if (sbinfo->free_blocks - delta >= 0)
+ sbinfo->free_blocks -= delta;
else
ret = -ENOMEM;
spin_unlock(&sbinfo->stat_lock);
@@ -876,13 +875,13 @@
return ret;
}
-void hugetlb_put_quota(struct address_space *mapping)
+void hugetlb_put_quota(struct address_space *mapping, long delta)
{
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);
if (sbinfo->free_blocks > -1) {
spin_lock(&sbinfo->stat_lock);
- sbinfo->free_blocks++;
+ sbinfo->free_blocks += delta;
spin_unlock(&sbinfo->stat_lock);
}
}
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
index 3c8663b..dfda12a 100644
--- a/fs/jfs/ioctl.c
+++ b/fs/jfs/ioctl.c
@@ -79,6 +79,9 @@
if (!S_ISDIR(inode->i_mode))
flags &= ~JFS_DIRSYNC_FL;
+ /* Is it quota file? Do not allow user to mess with it */
+ if (IS_NOQUOTA(inode))
+ return -EPERM;
jfs_get_inode_flags(jfs_inode);
oldflags = jfs_inode->mode2;
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index b617428..0e5fa11 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -41,7 +41,7 @@
fh = fh_copy(&resp->fh, &argp->fh);
if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
- RETURN_STATUS(nfserr_inval);
+ RETURN_STATUS(nfserr);
if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
RETURN_STATUS(nfserr_inval);
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 3e3f2de..b647f2f 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -37,7 +37,7 @@
fh = fh_copy(&resp->fh, &argp->fh);
if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
- RETURN_STATUS(nfserr_inval);
+ RETURN_STATUS(nfserr);
if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
RETURN_STATUS(nfserr_inval);
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 4f712e9..468f17a 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -95,6 +95,22 @@
return 0;
}
+static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
+ struct svc_export *exp)
+{
+ /* Check if the request originated from a secure port. */
+ if (!rqstp->rq_secure && EX_SECURE(exp)) {
+ char buf[RPC_MAX_ADDRBUFLEN];
+ dprintk(KERN_WARNING
+ "nfsd: request from insecure port %s!\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
+ return nfserr_perm;
+ }
+
+ /* Set user creds for this exportpoint */
+ return nfserrno(nfsd_setuser(rqstp, exp));
+}
+
/*
* Perform sanity checks on the dentry in a client's file handle.
*
@@ -167,18 +183,7 @@
goto out;
}
- /* Check if the request originated from a secure port. */
- error = nfserr_perm;
- if (!rqstp->rq_secure && EX_SECURE(exp)) {
- char buf[RPC_MAX_ADDRBUFLEN];
- printk(KERN_WARNING
- "nfsd: request from insecure port %s!\n",
- svc_print_addr(rqstp, buf, sizeof(buf)));
- goto out;
- }
-
- /* Set user creds for this exportpoint */
- error = nfserrno(nfsd_setuser(rqstp, exp));
+ error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
goto out;
@@ -227,18 +232,22 @@
fhp->fh_export = exp;
nfsd_nr_verified++;
} else {
- /* just rechecking permissions
- * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
+ /*
+ * just rechecking permissions
+ * (e.g. nfsproc_create calls fh_verify, then nfsd_create
+ * does as well)
*/
dprintk("nfsd: fh_verify - just checking\n");
dentry = fhp->fh_dentry;
exp = fhp->fh_export;
- /* Set user creds for this exportpoint; necessary even
+ /*
+ * Set user creds for this exportpoint; necessary even
* in the "just checking" case because this may be a
* filehandle that was created by fh_compose, and that
* is about to be used in another nfsv4 compound
- * operation */
- error = nfserrno(nfsd_setuser(rqstp, exp));
+ * operation.
+ */
+ error = nfsd_setuser_and_check_port(rqstp, exp);
if (error)
goto out;
}
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 685c180..d84bd15 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -58,6 +58,7 @@
#include <linux/slab.h>
#include <linux/idr.h>
#include <linux/kref.h>
+#include <linux/net.h>
#include <net/tcp.h>
#include <asm/uaccess.h>
@@ -616,8 +617,7 @@
del_timer_sync(&sc->sc_idle_timeout);
o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
sc_put(sc);
- sc->sc_sock->ops->shutdown(sc->sc_sock,
- RCV_SHUTDOWN|SEND_SHUTDOWN);
+ kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR);
}
/* not fatal so failed connects before the other guy has our
diff --git a/fs/open.c b/fs/open.c
index 3b69c53..4932b4d1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1061,7 +1061,7 @@
prevent_tail_call(ret);
return ret;
}
-EXPORT_SYMBOL_GPL(sys_open);
+EXPORT_UNUSED_SYMBOL_GPL(sys_open); /* To be deleted for 2.6.25 */
asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
int mode)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index aeaf0d0..a17c2685 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2328,21 +2328,18 @@
void proc_flush_task(struct task_struct *task)
{
- int i, leader;
- struct pid *pid, *tgid;
+ int i;
+ struct pid *pid, *tgid = NULL;
struct upid *upid;
- leader = thread_group_leader(task);
- proc_flush_task_mnt(proc_mnt, task->pid, leader ? task->tgid : 0);
pid = task_pid(task);
- if (pid->level == 0)
- return;
+ if (thread_group_leader(task))
+ tgid = task_tgid(task);
- tgid = task_tgid(task);
- for (i = 1; i <= pid->level; i++) {
+ for (i = 0; i <= pid->level; i++) {
upid = &pid->numbers[i];
proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr,
- leader ? 0 : tgid->numbers[i].nr);
+ tgid ? tgid->numbers[i].nr : 0);
}
upid = &pid->numbers[pid->level];
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 1bdb624..a9806bc 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -561,28 +561,33 @@
static void proc_kill_inodes(struct proc_dir_entry *de)
{
struct list_head *p;
- struct super_block *sb = proc_mnt->mnt_sb;
+ struct super_block *sb;
/*
* Actually it's a partial revoke().
*/
- file_list_lock();
- list_for_each(p, &sb->s_files) {
- struct file * filp = list_entry(p, struct file, f_u.fu_list);
- struct dentry * dentry = filp->f_path.dentry;
- struct inode * inode;
- const struct file_operations *fops;
+ spin_lock(&sb_lock);
+ list_for_each_entry(sb, &proc_fs_type.fs_supers, s_instances) {
+ file_list_lock();
+ list_for_each(p, &sb->s_files) {
+ struct file *filp = list_entry(p, struct file,
+ f_u.fu_list);
+ struct dentry *dentry = filp->f_path.dentry;
+ struct inode *inode;
+ const struct file_operations *fops;
- if (dentry->d_op != &proc_dentry_operations)
- continue;
- inode = dentry->d_inode;
- if (PDE(inode) != de)
- continue;
- fops = filp->f_op;
- filp->f_op = NULL;
- fops_put(fops);
+ if (dentry->d_op != &proc_dentry_operations)
+ continue;
+ inode = dentry->d_inode;
+ if (PDE(inode) != de)
+ continue;
+ fops = filp->f_op;
+ filp->f_op = NULL;
+ fops_put(fops);
+ }
+ file_list_unlock();
}
- file_list_unlock();
+ spin_unlock(&sb_lock);
}
static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent,
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 1820eb2..1b2b6c6 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -78,3 +78,5 @@
{
return PROC_I(inode)->fd;
}
+
+extern struct file_system_type proc_fs_type;
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 153554c..131f9c6 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -178,7 +178,7 @@
kfree(net->proc_net_root);
}
-static struct pernet_operations proc_net_ns_ops = {
+static struct pernet_operations __net_initdata proc_net_ns_ops = {
.init = proc_net_ns_init,
.exit = proc_net_ns_exit,
};
diff --git a/fs/proc/root.c b/fs/proc/root.c
index ec9cb3b..1f86bb8 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -98,7 +98,7 @@
put_pid_ns(ns);
}
-static struct file_system_type proc_fs_type = {
+struct file_system_type proc_fs_type = {
.name = "proc",
.get_sb = proc_get_sb,
.kill_sb = proc_kill_sb,
diff --git a/fs/read_write.c b/fs/read_write.c
index 124693e..ea1f94c 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -370,7 +370,7 @@
return ret;
}
-EXPORT_SYMBOL_GPL(sys_read);
+EXPORT_UNUSED_SYMBOL_GPL(sys_read); /* to be deleted for 2.6.25 */
asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
{
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index c438a8f..e0f0f09 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -57,6 +57,9 @@
if (get_user(flags, (int __user *)arg))
return -EFAULT;
+ /* Is it quota file? Do not allow user to mess with it. */
+ if (IS_NOQUOTA(inode))
+ return -EPERM;
if (((flags ^ REISERFS_I(inode)->
i_attrs) & (REISERFS_IMMUTABLE_FL |
REISERFS_APPEND_FL))
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index ca41567..d2db241 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -1458,9 +1458,6 @@
}
bh = next;
} while (bh != head);
- if (PAGE_SIZE == bh->b_size) {
- cancel_dirty_page(page, PAGE_CACHE_SIZE);
- }
}
}
}
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index f5d14ce..efbe29a 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -234,7 +234,7 @@
VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n",
(long)dentry->d_inode->i_size,
- dentry->d_inode->i_flags, dentry->d_inode->i_atime);
+ dentry->d_inode->i_flags, dentry->d_inode->i_atime.tv_sec);
status = generic_file_aio_read(iocb, iov, nr_segs, pos);
out:
@@ -269,7 +269,7 @@
struct dentry *dentry = file->f_path.dentry;
ssize_t status;
- VERBOSE("file %s/%s, pos=%Ld, count=%d\n",
+ VERBOSE("file %s/%s, pos=%Ld, count=%lu\n",
DENTRY_PATH(dentry), *ppos, count);
status = smb_revalidate_inode(dentry);
@@ -363,7 +363,8 @@
result = generic_file_aio_write(iocb, iov, nr_segs, pos);
VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
(long) file->f_pos, (long) dentry->d_inode->i_size,
- dentry->d_inode->i_mtime, dentry->d_inode->i_atime);
+ dentry->d_inode->i_mtime.tv_sec,
+ dentry->d_inode->i_atime.tv_sec);
}
out:
return result;
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index ab51775..9416ead 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -536,7 +536,7 @@
/* Allocate the global temp buffer and some superblock helper structs */
/* FIXME: move these to the smb_sb_info struct */
- VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) +
+ VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) +
sizeof(struct smb_mount_data_kernel));
mem = kmalloc(sizeof(struct smb_ops) +
sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index feac460..d517a27 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -2593,7 +2593,7 @@
fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
fattr->f_mtime.tv_nsec = 0;
VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n",
- mask, date, time, fattr->f_mtime);
+ mask, date, time, fattr->f_mtime.tv_sec);
fattr->f_size = DVAL(req->rq_data, 12);
/* ULONG allocation size */
fattr->attr = WVAL(req->rq_data, 20);
diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c
index 283c572..fae8e85 100644
--- a/fs/smbfs/smbiod.c
+++ b/fs/smbfs/smbiod.c
@@ -227,7 +227,7 @@
printk(KERN_ERR "smb_retry: signal failed [%d]\n", result);
goto out;
}
- VERBOSE("signalled pid %d\n", pid);
+ VERBOSE("signalled pid %d\n", pid_nr(pid));
/* FIXME: The retried requests should perhaps get a "time boost". */
diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h
index 0b51a87..2949a94 100644
--- a/include/asm-cris/atomic.h
+++ b/include/asm-cris/atomic.h
@@ -3,6 +3,8 @@
#ifndef __ASM_CRIS_ATOMIC__
#define __ASM_CRIS_ATOMIC__
+#include <linux/compiler.h>
+
#include <asm/system.h>
#include <asm/arch/atomic.h>
diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h
index 180dbf2..c6c5be6 100644
--- a/include/asm-cris/checksum.h
+++ b/include/asm-cris/checksum.h
@@ -62,7 +62,7 @@
* returns a 16-bit checksum, already complemented
*/
-static inline __sum16 int csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
unsigned short len,
unsigned short proto,
__wsum sum)
diff --git a/include/asm-cris/ethernet.h b/include/asm-cris/ethernet.h
index 30da58a..4d58652 100644
--- a/include/asm-cris/ethernet.h
+++ b/include/asm-cris/ethernet.h
@@ -15,4 +15,7 @@
#define SET_ETH_DUPLEX_AUTO SIOCDEVPRIVATE+3 /* Auto neg duplex */
#define SET_ETH_DUPLEX_HALF SIOCDEVPRIVATE+4 /* Full duplex */
#define SET_ETH_DUPLEX_FULL SIOCDEVPRIVATE+5 /* Half duplex */
+#define SET_ETH_ENABLE_LEDS SIOCDEVPRIVATE+6 /* Enable net LEDs */
+#define SET_ETH_DISABLE_LEDS SIOCDEVPRIVATE+7 /* Disable net LEDs */
+#define SET_ETH_AUTONEG SIOCDEVPRIVATE+8
#endif /* _CRIS_ETHERNET_H */
diff --git a/include/asm-cris/fasttimer.h b/include/asm-cris/fasttimer.h
index a3a7713..8f8a8d6 100644
--- a/include/asm-cris/fasttimer.h
+++ b/include/asm-cris/fasttimer.h
@@ -1,9 +1,8 @@
-/* $Id: fasttimer.h,v 1.3 2004/05/14 10:19:19 starvik Exp $
+/*
* linux/include/asm-cris/fasttimer.h
*
* Fast timers for ETRAX100LX
- * This may be useful in other OS than Linux so use 2 space indentation...
- * Copyright (C) 2000, 2002 Axis Communications AB
+ * Copyright (C) 2000-2007 Axis Communications AB
*/
#include <linux/time.h> /* struct timeval */
#include <linux/timex.h>
@@ -12,11 +11,16 @@
typedef void fast_timer_function_type(unsigned long);
+struct fasttime_t {
+ unsigned long tv_jiff; /* jiffies */
+ unsigned long tv_usec; /* microseconds */
+};
+
struct fast_timer{ /* Close to timer_list */
struct fast_timer *next;
struct fast_timer *prev;
- struct timeval tv_set;
- struct timeval tv_expires;
+ struct fasttime_t tv_set;
+ struct fasttime_t tv_expires;
unsigned long delay_us;
fast_timer_function_type *function;
unsigned long data;
@@ -38,6 +42,6 @@
void schedule_usleep(unsigned long us);
-void fast_timer_init(void);
+int fast_timer_init(void);
#endif
diff --git a/include/asm-cris/hardirq.h b/include/asm-cris/hardirq.h
index 1c13dd3..74178ad 100644
--- a/include/asm-cris/hardirq.h
+++ b/include/asm-cris/hardirq.h
@@ -1,6 +1,7 @@
#ifndef __ASM_HARDIRQ_H
#define __ASM_HARDIRQ_H
+#include <asm/irq.h>
#include <linux/threads.h>
#include <linux/cache.h>
diff --git a/include/asm-cris/posix_types.h b/include/asm-cris/posix_types.h
index 92000d0..3a5e4c4 100644
--- a/include/asm-cris/posix_types.h
+++ b/include/asm-cris/posix_types.h
@@ -52,7 +52,6 @@
} __kernel_fsid_t;
#ifdef __KERNEL__
-#include <linux/bitops.h>
#undef __FD_SET
#define __FD_SET(fd,fdsetp) set_bit(fd, (void *)(fdsetp))
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index 71c1b36..66e1a74 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -171,6 +171,19 @@
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
+
+/* Unsupported rates, but needed to avoid compile error. */
+#define B500000 0010005
+#define B576000 0010006
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
+
/* etrax supports these additional three baud rates */
#define B921600 0010005
#define B1843200 0010006
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h
index fde39f6..784668a 100644
--- a/include/asm-cris/thread_info.h
+++ b/include/asm-cris/thread_info.h
@@ -32,6 +32,7 @@
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */
+ __u32 tls; /* TLS for this thread */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead
@@ -79,14 +80,18 @@
* - other flags in MSW
*/
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
-#define TIF_SIGPENDING 1 /* signal pending */
-#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
+#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
diff --git a/include/asm-cris/tlb.h b/include/asm-cris/tlb.h
index 6cc26de..7724246 100644
--- a/include/asm-cris/tlb.h
+++ b/include/asm-cris/tlb.h
@@ -1,6 +1,8 @@
#ifndef _CRIS_TLB_H
#define _CRIS_TLB_H
+#include <linux/pagemap.h>
+
#include <asm/arch/tlb.h>
/*
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 7c90fa9..6f2d924 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -255,6 +255,7 @@
#define __NR_io_submit 248
#define __NR_io_cancel 249
#define __NR_fadvise64 250
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
#define __NR_exit_group 252
#define __NR_lookup_dcookie 253
#define __NR_epoll_create 254
@@ -292,10 +293,46 @@
#define __NR_add_key 286
#define __NR_request_key 287
#define __NR_keyctl 288
+#define __NR_ioprio_set 289
+#define __NR_ioprio_get 290
+#define __NR_inotify_init 291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch 293
+#define __NR_migrate_pages 294
+#define __NR_openat 295
+#define __NR_mkdirat 296
+#define __NR_mknodat 297
+#define __NR_fchownat 298
+#define __NR_futimesat 299
+#define __NR_fstatat64 300
+#define __NR_unlinkat 301
+#define __NR_renameat 302
+#define __NR_linkat 303
+#define __NR_symlinkat 304
+#define __NR_readlinkat 305
+#define __NR_fchmodat 306
+#define __NR_faccessat 307
+#define __NR_pselect6 308
+#define __NR_ppoll 309
+#define __NR_unshare 310
+#define __NR_set_robust_list 311
+#define __NR_get_robust_list 312
+#define __NR_splice 313
+#define __NR_sync_file_range 314
+#define __NR_tee 315
+#define __NR_vmsplice 316
+#define __NR_move_pages 317
+#define __NR_getcpu 318
+#define __NR_epoll_pwait 319
+#define __NR_utimensat 320
+#define __NR_signalfd 321
+#define __NR_timerfd 322
+#define __NR_eventfd 323
+#define __NR_fallocate 324
#ifdef __KERNEL__
-#define NR_syscalls 289
+#define NR_syscalls 325
#include <asm/arch/unistd.h>
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 9d74338..4525c78 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -138,6 +138,7 @@
#define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000)
#define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000)
#define CPU_FTR_SPE ASM_CONST(0x0000000002000000)
+#define CPU_FTR_NEED_PAIRED_STWCX ASM_CONST(0x0000000004000000)
/*
* Add the 64-bit processor unique features in the top half of the word;
@@ -261,25 +262,25 @@
#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | \
- CPU_FTR_USE_TB | \
+ CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | \
- CPU_FTR_USE_TB | \
+ CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \
CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | \
- CPU_FTR_USE_TB | \
+ CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
@@ -289,31 +290,32 @@
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE | \
+ CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7447 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7447A (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_7448 (CPU_FTR_COMMON | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_PPC_LE)
+ CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
#define CPU_FTRS_82XX (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
#define CPU_FTRS_G2_LE (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | \
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index e7b4c0d..5c91081 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -44,13 +44,13 @@
static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long vmaddr)
{
- _tlbie(vmaddr, vma->vm_mm->context.id);
+ _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
}
static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
unsigned long vmaddr)
{
- _tlbie(vmaddr, vma->vm_mm->context.id);
+ _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0);
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
index aa82b88..3ebafba 100644
--- a/include/asm-um/pgtable-3level.h
+++ b/include/asm-um/pgtable-3level.h
@@ -71,7 +71,7 @@
static inline void pud_clear (pud_t *pud)
{
- set_pud(pud, __pud(0));
+ set_pud(pud, __pud(_PAGE_NEWPAGE));
}
#define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK)
diff --git a/include/asm-x86/i387_64.h b/include/asm-x86/i387_64.h
index 0217b74..3a4ffba 100644
--- a/include/asm-x86/i387_64.h
+++ b/include/asm-x86/i387_64.h
@@ -203,6 +203,11 @@
*/
static inline int restore_i387(struct _fpstate __user *buf)
{
+ set_used_math();
+ if (!(task_thread_info(current)->status & TS_USEDFPU)) {
+ clts();
+ task_thread_info(current)->status |= TS_USEDFPU;
+ }
return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
}
diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h
index 213c973..51ddb25 100644
--- a/include/asm-x86/ptrace.h
+++ b/include/asm-x86/ptrace.h
@@ -60,7 +60,7 @@
#define instruction_pointer(regs) ((regs)->eip)
#define frame_pointer(regs) ((regs)->ebp)
-#define stack_pointer(regs) ((regs)->esp)
+#define stack_pointer(regs) ((unsigned long)(regs))
#define regs_return_value(regs) ((regs)->eax)
extern unsigned long profile_pc(struct pt_regs *regs);
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index 0b9bfbd..d62fcee 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -13,12 +13,6 @@
/* */
-#ifdef CONFIG_CGROUP_CPUACCT
-SUBSYS(cpuacct)
-#endif
-
-/* */
-
#ifdef CONFIG_CGROUP_DEBUG
SUBSYS(debug)
#endif
diff --git a/include/linux/cpu_acct.h b/include/linux/cpu_acct.h
deleted file mode 100644
index 6b5fd8a..0000000
--- a/include/linux/cpu_acct.h
+++ /dev/null
@@ -1,14 +0,0 @@
-
-#ifndef _LINUX_CPU_ACCT_H
-#define _LINUX_CPU_ACCT_H
-
-#include <linux/cgroup.h>
-#include <asm/cputime.h>
-
-#ifdef CONFIG_CGROUP_CPUACCT
-extern void cpuacct_charge(struct task_struct *, cputime_t cputime);
-#else
-static void inline cpuacct_charge(struct task_struct *p, cputime_t cputime) {}
-#endif
-
-#endif
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 6413445..241c01c 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -656,6 +656,26 @@
#define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
#define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
~EXT3_DIR_ROUND)
+#define EXT3_MAX_REC_LEN ((1<<16)-1)
+
+static inline unsigned ext3_rec_len_from_disk(__le16 dlen)
+{
+ unsigned len = le16_to_cpu(dlen);
+
+ if (len == EXT3_MAX_REC_LEN)
+ return 1 << 16;
+ return len;
+}
+
+static inline __le16 ext3_rec_len_to_disk(unsigned len)
+{
+ if (len == (1 << 16))
+ return cpu_to_le16(EXT3_MAX_REC_LEN);
+ else if (len > (1 << 16))
+ BUG();
+ return cpu_to_le16(len);
+}
+
/*
* Hash Tree Directory indexing
* (c) Daniel Phillips, 2001
diff --git a/include/linux/f75375s.h b/include/linux/f75375s.h
new file mode 100644
index 0000000..e99e225
--- /dev/null
+++ b/include/linux/f75375s.h
@@ -0,0 +1,21 @@
+/*
+ * f75375s.h - platform data structure for f75375s sensor
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007, Riku Voipio <riku.voipio@iki.fi>
+ */
+
+#ifndef __LINUX_F75375S_H
+#define __LINUX_F75375S_H
+
+/* We want to set fans spinning on systems where there is no
+ * BIOS to do that for us */
+struct f75375s_platform_data {
+ u8 pwm[2];
+ u8 pwm_enable[2];
+};
+
+#endif /* __LINUX_F75375S_H */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index ea0f50b..2496879 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -19,7 +19,7 @@
int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
-int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int);
+int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int, int);
void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
void __unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long);
int hugetlb_prefault(struct address_space *, struct vm_area_struct *);
@@ -106,7 +106,7 @@
return 0;
}
-#define follow_hugetlb_page(m,v,p,vs,a,b,i) ({ BUG(); 0; })
+#define follow_hugetlb_page(m,v,p,vs,a,b,i,w) ({ BUG(); 0; })
#define follow_huge_addr(mm, addr, write) ERR_PTR(-EINVAL)
#define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; })
#define hugetlb_prefault(mapping, vma) ({ BUG(); 0; })
@@ -165,8 +165,10 @@
extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_file_setup(const char *name, size_t);
-int hugetlb_get_quota(struct address_space *mapping);
-void hugetlb_put_quota(struct address_space *mapping);
+int hugetlb_get_quota(struct address_space *mapping, long delta);
+void hugetlb_put_quota(struct address_space *mapping, long delta);
+
+#define BLOCKS_PER_HUGEPAGE (HPAGE_SIZE / 512)
static inline int is_file_hugepages(struct file *file)
{
diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
index 580b3f4..2f4e957 100644
--- a/include/linux/mc146818rtc.h
+++ b/include/linux/mc146818rtc.h
@@ -109,8 +109,11 @@
#ifndef ARCH_RTC_LOCATION /* Override by <asm/mc146818rtc.h>? */
#define RTC_IO_EXTENT 0x8
+#define RTC_IO_EXTENT_USED 0x2
#define RTC_IOMAPPED 1 /* Default to I/O mapping. */
+#else
+#define RTC_IO_EXTENT_USED RTC_IO_EXTENT
#endif /* ARCH_RTC_LOCATION */
#endif /* _MC146818RTC_H */
diff --git a/include/linux/net.h b/include/linux/net.h
index dd79cdb..596131e 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -95,6 +95,12 @@
#endif /* ARCH_HAS_SOCKET_TYPES */
+enum sock_shutdown_cmd {
+ SHUT_RD = 0,
+ SHUT_WR = 1,
+ SHUT_RDWR = 2,
+};
+
/**
* struct socket - general BSD socket
* @state: socket state (%SS_CONNECTED, etc)
@@ -223,6 +229,8 @@
extern int kernel_sendpage(struct socket *sock, struct page *page, int offset,
size_t size, int flags);
extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
+extern int kernel_sock_shutdown(struct socket *sock,
+ enum sock_shutdown_cmd how);
#ifndef CONFIG_SMP
#define SOCKOPS_WRAPPED(name) name
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index fbe1964..1ee009e 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2276,6 +2276,9 @@
#define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582
#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590
#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
+#define PCI_DEVICE_ID_INTEL_5000_ERR 0x25F0
+#define PCI_DEVICE_ID_INTEL_5000_FBD0 0x25F5
+#define PCI_DEVICE_ID_INTEL_5000_FBD1 0x25F6
#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770
#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772
#define PCI_DEVICE_ID_INTEL_3000_HB 0x2778
@@ -2329,6 +2332,7 @@
#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b
+#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f
#define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff
#define PCI_DEVICE_ID_INTEL_TOLAPAI_0 0x5031
#define PCI_DEVICE_ID_INTEL_TOLAPAI_1 0x5032
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 0135c76..1689e28 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -29,6 +29,7 @@
extern struct pid_namespace init_pid_ns;
+#ifdef CONFIG_PID_NS
static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
{
if (ns != &init_pid_ns)
@@ -45,6 +46,28 @@
kref_put(&ns->kref, free_pid_ns);
}
+#else /* !CONFIG_PID_NS */
+#include <linux/err.h>
+
+static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
+{
+ return ns;
+}
+
+static inline struct pid_namespace *
+copy_pid_ns(unsigned long flags, struct pid_namespace *ns)
+{
+ if (flags & CLONE_NEWPID)
+ ns = ERR_PTR(-EINVAL);
+ return ns;
+}
+
+static inline void put_pid_ns(struct pid_namespace *ns)
+{
+}
+
+#endif /* CONFIG_PID_NS */
+
static inline struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
{
return tsk->nsproxy->pid_ns;
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 5bf6182..4e81836 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -491,9 +491,11 @@
unsigned char nduseropt_family;
unsigned char nduseropt_pad1;
unsigned short nduseropt_opts_len; /* Total length of options */
+ int nduseropt_ifindex;
__u8 nduseropt_icmp_type;
__u8 nduseropt_icmp_code;
unsigned short nduseropt_pad2;
+ unsigned int nduseropt_pad3;
/* Followed by one or more ND options */
};
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 94e4991..91140fe 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -387,7 +387,9 @@
static inline void skb_truesize_check(struct sk_buff *skb)
{
- if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len))
+ int len = sizeof(struct sk_buff) + skb->len;
+
+ if (unlikely((int)skb->truesize < len))
skb_truesize_bug(skb);
}
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index ac69e7bb..1a4ed49 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -67,7 +67,7 @@
};
/* The standard layout for the ring is a continuous chunk of memory which looks
- * like this. The used fields will be aligned to a "num+1" boundary.
+ * like this. We assume num is a power of 2.
*
* struct vring
* {
@@ -79,8 +79,8 @@
* __u16 avail_idx;
* __u16 available[num];
*
- * // Padding so a correctly-chosen num value will cache-align used_idx.
- * char pad[sizeof(struct vring_desc) - sizeof(avail_flags)];
+ * // Padding to the next page boundary.
+ * char pad[];
*
* // A ring of used descriptor heads with free-running index.
* __u16 used_flags;
@@ -88,18 +88,21 @@
* struct vring_used_elem used[num];
* };
*/
-static inline void vring_init(struct vring *vr, unsigned int num, void *p)
+static inline void vring_init(struct vring *vr, unsigned int num, void *p,
+ unsigned int pagesize)
{
vr->num = num;
vr->desc = p;
- vr->avail = p + num*sizeof(struct vring);
- vr->used = p + (num+1)*(sizeof(struct vring) + sizeof(__u16));
+ vr->avail = p + num*sizeof(struct vring_desc);
+ vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + pagesize-1)
+ & ~(pagesize - 1));
}
-static inline unsigned vring_size(unsigned int num)
+static inline unsigned vring_size(unsigned int num, unsigned int pagesize)
{
- return (num + 1) * (sizeof(struct vring_desc) + sizeof(__u16))
- + sizeof(__u32) + num * sizeof(struct vring_used_elem);
+ return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num)
+ + pagesize - 1) & ~(pagesize - 1))
+ + sizeof(__u16) * 2 + sizeof(struct vring_used_elem) * num;
}
#ifdef __KERNEL__
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 0864a77..a1c805d 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -12,7 +12,7 @@
#define UNIX_HASH_SIZE 256
-extern atomic_t unix_tot_inflight;
+extern unsigned int unix_tot_inflight;
struct unix_address {
atomic_t refcnt;
diff --git a/include/net/dst.h b/include/net/dst.h
index e9ff4a4..2f65e89 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -143,6 +143,13 @@
atomic_inc(&dst->__refcnt);
}
+static inline void dst_use(struct dst_entry *dst, unsigned long time)
+{
+ dst_hold(dst);
+ dst->__use++;
+ dst->lastuse = time;
+}
+
static inline
struct dst_entry * dst_clone(struct dst_entry * dst)
{
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 017aebd..41a301e 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -107,4 +107,7 @@
extern int fib_rules_lookup(struct fib_rules_ops *,
struct flowi *, int flags,
struct fib_lookup_arg *);
+extern int fib_default_rule_add(struct fib_rules_ops *,
+ u32 pref, u32 table,
+ u32 flags);
#endif
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index 227adcb..38d5a1e 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -13,9 +13,6 @@
struct sockaddr;
struct socket;
-extern void inet_remove_sock(struct sock *sk1);
-extern void inet_put_sock(unsigned short num,
- struct sock *sk);
extern int inet_release(struct socket *sock);
extern int inet_stream_connect(struct socket *sock,
struct sockaddr * uaddr,
@@ -30,7 +27,6 @@
struct msghdr *msg,
size_t size);
extern int inet_shutdown(struct socket *sock, int how);
-extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
extern int inet_listen(struct socket *sock, int backlog);
extern void inet_sock_destruct(struct sock *sk);
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 8461cda..469216d 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/wait.h>
+#include <linux/vmalloc.h>
#include <net/inet_connection_sock.h>
#include <net/inet_sock.h>
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index aa10a81..ad8404b 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -22,7 +22,7 @@
__be32 v4daddr; /* peer's address */
__u16 avl_height;
__u16 ip_id_count; /* IP ID for the next packet */
- struct inet_peer *unused_next, **unused_prevp;
+ struct list_head unused;
__u32 dtime; /* the time of last use of not
* referenced entries */
atomic_t refcnt;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5fcc4c1..17b6039 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -706,11 +706,16 @@
*
* @queues: number of available hardware transmit queues for
* data packets. WMM/QoS requires at least four.
+ *
+ * @rate_control_algorithm: rate control algorithm for this hardware.
+ * If unset (NULL), the default algorithm will be used. Must be
+ * set before calling ieee80211_register_hw().
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
struct wiphy *wiphy;
struct workqueue_struct *workqueue;
+ const char *rate_control_algorithm;
void *priv;
u32 flags;
unsigned int extra_tx_headroom;
@@ -936,27 +941,11 @@
* and remove_interface calls, i.e. while the interface with the
* given local_address is enabled.
*
- * @set_ieee8021x: Enable/disable IEEE 802.1X. This item requests wlan card
- * to pass unencrypted EAPOL-Key frames even when encryption is
- * configured. If the wlan card does not require such a configuration,
- * this function pointer can be set to NULL.
- *
- * @set_port_auth: Set port authorization state (IEEE 802.1X PAE) to be
- * authorized (@authorized=1) or unauthorized (=0). This function can be
- * used if the wlan hardware or low-level driver implements PAE.
- * mac80211 will filter frames based on authorization state in any case,
- * so this function pointer can be NULL if low-level driver does not
- * require event notification about port state changes.
- *
* @hw_scan: Ask the hardware to service the scan request, no need to start
* the scan state machine in stack.
*
* @get_stats: return low-level statistics
*
- * @set_privacy_invoked: For devices that generate their own beacons and probe
- * response or association responses this updates the state of privacy_invoked
- * returns 0 for success or an error number.
- *
* @get_sequence_counter: For devices that have internal sequence counters this
* callback allows mac80211 to access the current value of a counter.
* This callback seems not well-defined, tell us if you need it.
@@ -1029,14 +1018,9 @@
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_address, const u8 *address,
struct ieee80211_key_conf *key);
- int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x);
- int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr,
- int authorized);
int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
int (*get_stats)(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
- int (*set_privacy_invoked)(struct ieee80211_hw *hw,
- int privacy_invoked);
int (*get_sequence_counter)(struct ieee80211_hw *hw,
u8* addr, u8 keyidx, u8 txrx,
u32* iv32, u16* iv16);
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 1fd449a..5dd6d90 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -119,9 +119,11 @@
#ifdef CONFIG_NET_NS
#define __net_init
#define __net_exit
+#define __net_initdata
#else
#define __net_init __init
#define __net_exit __exit_refok
+#define __net_initdata __initdata
#endif
struct pernet_operations {
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index b873336..c1f7976 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -103,6 +103,7 @@
SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */
SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */
+ SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */
SCTP_CMD_LAST
} sctp_verb_t;
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index da8354e..f30b537 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -186,6 +186,8 @@
SCTP_IERROR_AUTH_BAD_HMAC,
SCTP_IERROR_AUTH_BAD_KEYID,
SCTP_IERROR_PROTO_VIOLATION,
+ SCTP_IERROR_ERROR,
+ SCTP_IERROR_ABORT,
} sctp_ierror_t;
@@ -407,6 +409,7 @@
SCTP_RTXR_T3_RTX,
SCTP_RTXR_FAST_RTX,
SCTP_RTXR_PMTUD,
+ SCTP_RTXR_T1_RTX,
} sctp_retransmit_reason_t;
/* Reasons to lower cwnd. */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 93eb708..34318a3 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -65,7 +65,6 @@
#ifdef TEST_FRAME
-#undef CONFIG_PROC_FS
#undef CONFIG_SCTP_DBG_OBJCNT
#undef CONFIG_SYSCTL
#endif /* TEST_FRAME */
@@ -267,6 +266,7 @@
SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS,
SCTP_MIB_DELAY_SACK_EXPIREDS,
SCTP_MIB_AUTOCLOSE_EXPIREDS,
+ SCTP_MIB_T1_RETRANSMITS,
SCTP_MIB_T3_RETRANSMITS,
SCTP_MIB_PMTUD_RETRANSMITS,
SCTP_MIB_FAST_RETRANSMITS,
@@ -664,6 +664,9 @@
return (h & (sctp_assoc_hashsize-1));
}
+#define sctp_for_each_hentry(epb, node, head) \
+ hlist_for_each_entry(epb, node, head, node)
+
/* Is a socket of this style? */
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ef892e0..eb3113c 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -100,20 +100,19 @@
struct sctp_bind_bucket {
unsigned short port;
unsigned short fastreuse;
- struct sctp_bind_bucket *next;
- struct sctp_bind_bucket **pprev;
+ struct hlist_node node;
struct hlist_head owner;
};
struct sctp_bind_hashbucket {
spinlock_t lock;
- struct sctp_bind_bucket *chain;
+ struct hlist_head chain;
};
/* Used for hashing all associations. */
struct sctp_hashbucket {
rwlock_t lock;
- struct sctp_ep_common *chain;
+ struct hlist_head chain;
} __attribute__((__aligned__(8)));
@@ -212,6 +211,7 @@
/* Flag to indicate if addip is enabled. */
int addip_enable;
+ int addip_noauth_enable;
/* Flag to indicate if PR-SCTP is enabled. */
int prsctp_enable;
@@ -249,6 +249,7 @@
#define sctp_local_addr_list (sctp_globals.local_addr_list)
#define sctp_local_addr_lock (sctp_globals.addr_list_lock)
#define sctp_addip_enable (sctp_globals.addip_enable)
+#define sctp_addip_noauth (sctp_globals.addip_noauth_enable)
#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
#define sctp_auth_enable (sctp_globals.auth_enable)
@@ -873,10 +874,11 @@
* address list derived from the INIT or INIT ACK chunk, a
* number of data elements needs to be maintained including:
*/
- __u32 rtt; /* This is the most recent RTT. */
-
/* RTO : The current retransmission timeout value. */
unsigned long rto;
+ unsigned long last_rto;
+
+ __u32 rtt; /* This is the most recent RTT. */
/* RTTVAR : The current RTT variation. */
__u32 rttvar;
@@ -1184,9 +1186,7 @@
int flags);
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
__u8 use_as_src, gfp_t gfp);
-int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
- void fastcall (*rcu_call)(struct rcu_head *,
- void (*func)(struct rcu_head *)));
+int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
struct sctp_sock *);
union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
@@ -1229,8 +1229,7 @@
struct sctp_ep_common {
/* Fields to help us manage our entries in the hash tables. */
- struct sctp_ep_common *next;
- struct sctp_ep_common **pprev;
+ struct hlist_node node;
int hashent;
/* Runtime type information. What kind of endpoint is this? */
@@ -1541,7 +1540,6 @@
__u8 asconf_capable; /* Does peer support ADDIP? */
__u8 prsctp_capable; /* Can peer do PR-SCTP? */
__u8 auth_capable; /* Is peer doing SCTP-AUTH? */
- __u8 addip_capable; /* Can peer do ADD-IP */
__u32 adaptation_ind; /* Adaptation Code point. */
diff --git a/include/net/sock.h b/include/net/sock.h
index 5504fb9..567e468 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1235,14 +1235,16 @@
gfp_t gfp)
{
struct sk_buff *skb;
- int hdr_len;
- hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header);
- skb = alloc_skb_fclone(size + hdr_len, gfp);
+ skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp);
if (skb) {
skb->truesize += mem;
if (sk_stream_wmem_schedule(sk, skb->truesize)) {
- skb_reserve(skb, hdr_len);
+ /*
+ * Make sure that we have exactly size bytes
+ * available to the caller, no more, no less.
+ */
+ skb_reserve(skb, skb_tailroom(skb) - size);
return skb;
}
__kfree_skb(skb);
diff --git a/init/Kconfig b/init/Kconfig
index 8b88d0b..c5b354b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -215,6 +215,18 @@
vservers, to use user namespaces to provide different
user info for different servers. If unsure, say N.
+config PID_NS
+ bool "PID Namespaces (EXPERIMENTAL)"
+ default n
+ depends on EXPERIMENTAL
+ help
+ Suport process id namespaces. This allows having multiple
+ process with the same pid as long as they are in different
+ pid namespaces. This is a building block of containers.
+
+ Unless you want to work with an experimental feature
+ say N here.
+
config AUDIT
bool "Auditing support"
depends on NET
@@ -301,13 +313,6 @@
for instance virtual servers and checkpoint/restart
jobs.
-config CGROUP_CPUACCT
- bool "Simple CPU accounting cgroup subsystem"
- depends on CGROUPS
- help
- Provides a simple Resource Controller for monitoring the
- total CPU consumed by the tasks in a cgroup
-
config CPUSETS
bool "Cpuset support"
depends on SMP && CGROUPS
diff --git a/kernel/Makefile b/kernel/Makefile
index f60afe7..dfa9695 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -40,7 +40,6 @@
obj-$(CONFIG_CGROUPS) += cgroup.o
obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o
obj-$(CONFIG_CPUSETS) += cpuset.o
-obj-$(CONFIG_CGROUP_CPUACCT) += cpu_acct.o
obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 3fe21e1..1a3c239 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1,6 +1,4 @@
/*
- * kernel/cgroup.c
- *
* Generic process-grouping system.
*
* Based originally on the cpuset system, extracted by Paul Menage
@@ -2200,7 +2198,8 @@
{
struct cgroup_subsys_state *css;
struct list_head *l;
- printk(KERN_ERR "Initializing cgroup subsys %s\n", ss->name);
+
+ printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
/* Create the top cgroup state for this subsystem */
ss->root = &rootnode;
@@ -2273,7 +2272,7 @@
BUG_ON(!ss->create);
BUG_ON(!ss->destroy);
if (ss->subsys_id != i) {
- printk(KERN_ERR "Subsys %s id == %d\n",
+ printk(KERN_ERR "cgroup: Subsys %s id == %d\n",
ss->name, ss->subsys_id);
BUG();
}
@@ -2605,7 +2604,7 @@
dentry = lookup_one_len(nodename, parent->dentry, strlen(nodename));
if (IS_ERR(dentry)) {
printk(KERN_INFO
- "Couldn't allocate dentry for %s: %ld\n", nodename,
+ "cgroup: Couldn't allocate dentry for %s: %ld\n", nodename,
PTR_ERR(dentry));
ret = PTR_ERR(dentry);
goto out_release;
diff --git a/kernel/cpu_acct.c b/kernel/cpu_acct.c
deleted file mode 100644
index 731e47e..0000000
--- a/kernel/cpu_acct.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * kernel/cpu_acct.c - CPU accounting cgroup subsystem
- *
- * Copyright (C) Google Inc, 2006
- *
- * Developed by Paul Menage (menage@google.com) and Balbir Singh
- * (balbir@in.ibm.com)
- *
- */
-
-/*
- * Example cgroup subsystem for reporting total CPU usage of tasks in a
- * cgroup, along with percentage load over a time interval
- */
-
-#include <linux/module.h>
-#include <linux/cgroup.h>
-#include <linux/fs.h>
-#include <linux/rcupdate.h>
-
-#include <asm/div64.h>
-
-struct cpuacct {
- struct cgroup_subsys_state css;
- spinlock_t lock;
- /* total time used by this class */
- cputime64_t time;
-
- /* time when next load calculation occurs */
- u64 next_interval_check;
-
- /* time used in current period */
- cputime64_t current_interval_time;
-
- /* time used in last period */
- cputime64_t last_interval_time;
-};
-
-struct cgroup_subsys cpuacct_subsys;
-
-static inline struct cpuacct *cgroup_ca(struct cgroup *cont)
-{
- return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id),
- struct cpuacct, css);
-}
-
-static inline struct cpuacct *task_ca(struct task_struct *task)
-{
- return container_of(task_subsys_state(task, cpuacct_subsys_id),
- struct cpuacct, css);
-}
-
-#define INTERVAL (HZ * 10)
-
-static inline u64 next_interval_boundary(u64 now)
-{
- /* calculate the next interval boundary beyond the
- * current time */
- do_div(now, INTERVAL);
- return (now + 1) * INTERVAL;
-}
-
-static struct cgroup_subsys_state *cpuacct_create(
- struct cgroup_subsys *ss, struct cgroup *cont)
-{
- struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
-
- if (!ca)
- return ERR_PTR(-ENOMEM);
- spin_lock_init(&ca->lock);
- ca->next_interval_check = next_interval_boundary(get_jiffies_64());
- return &ca->css;
-}
-
-static void cpuacct_destroy(struct cgroup_subsys *ss,
- struct cgroup *cont)
-{
- kfree(cgroup_ca(cont));
-}
-
-/* Lazily update the load calculation if necessary. Called with ca locked */
-static void cpuusage_update(struct cpuacct *ca)
-{
- u64 now = get_jiffies_64();
-
- /* If we're not due for an update, return */
- if (ca->next_interval_check > now)
- return;
-
- if (ca->next_interval_check <= (now - INTERVAL)) {
- /* If it's been more than an interval since the last
- * check, then catch up - the last interval must have
- * been zero load */
- ca->last_interval_time = 0;
- ca->next_interval_check = next_interval_boundary(now);
- } else {
- /* If a steal takes the last interval time negative,
- * then we just ignore it */
- if ((s64)ca->current_interval_time > 0)
- ca->last_interval_time = ca->current_interval_time;
- else
- ca->last_interval_time = 0;
- ca->next_interval_check += INTERVAL;
- }
- ca->current_interval_time = 0;
-}
-
-static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft)
-{
- struct cpuacct *ca = cgroup_ca(cont);
- u64 time;
-
- spin_lock_irq(&ca->lock);
- cpuusage_update(ca);
- time = cputime64_to_jiffies64(ca->time);
- spin_unlock_irq(&ca->lock);
-
- /* Convert 64-bit jiffies to seconds */
- time *= 1000;
- do_div(time, HZ);
- return time;
-}
-
-static u64 load_read(struct cgroup *cont, struct cftype *cft)
-{
- struct cpuacct *ca = cgroup_ca(cont);
- u64 time;
-
- /* Find the time used in the previous interval */
- spin_lock_irq(&ca->lock);
- cpuusage_update(ca);
- time = cputime64_to_jiffies64(ca->last_interval_time);
- spin_unlock_irq(&ca->lock);
-
- /* Convert time to a percentage, to give the load in the
- * previous period */
- time *= 100;
- do_div(time, INTERVAL);
-
- return time;
-}
-
-static struct cftype files[] = {
- {
- .name = "usage",
- .read_uint = cpuusage_read,
- },
- {
- .name = "load",
- .read_uint = load_read,
- }
-};
-
-static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont)
-{
- return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
-}
-
-void cpuacct_charge(struct task_struct *task, cputime_t cputime)
-{
-
- struct cpuacct *ca;
- unsigned long flags;
-
- if (!cpuacct_subsys.active)
- return;
- rcu_read_lock();
- ca = task_ca(task);
- if (ca) {
- spin_lock_irqsave(&ca->lock, flags);
- cpuusage_update(ca);
- ca->time = cputime64_add(ca->time, cputime);
- ca->current_interval_time =
- cputime64_add(ca->current_interval_time, cputime);
- spin_unlock_irqrestore(&ca->lock, flags);
- }
- rcu_read_unlock();
-}
-
-struct cgroup_subsys cpuacct_subsys = {
- .name = "cpuacct",
- .create = cpuacct_create,
- .destroy = cpuacct_destroy,
- .populate = cpuacct_populate,
- .subsys_id = cpuacct_subsys_id,
-};
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index e391cbb..dc335ad 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -178,9 +178,11 @@
*/
if (desc->chip->ack)
desc->chip->ack(irq);
- action_ret = handle_IRQ_event(irq, desc->action);
- if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ if (likely(!(desc->status & IRQ_DISABLED))) {
+ action_ret = handle_IRQ_event(irq, desc->action);
+ if (!noirqdebug)
+ note_interrupt(irq, desc, action_ret);
+ }
desc->chip->end(irq);
return 1;
}
diff --git a/kernel/marker.c b/kernel/marker.c
index ccb48d9..5323cfa 100644
--- a/kernel/marker.c
+++ b/kernel/marker.c
@@ -28,7 +28,7 @@
extern struct marker __stop___markers[];
/*
- * module_mutex nests inside markers_mutex. Markers mutex protects the builtin
+ * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
* and module markers, the hash table and deferred_sync.
*/
static DEFINE_MUTEX(markers_mutex);
@@ -257,7 +257,6 @@
* @refcount: number of references left to the given probe_module (out)
*
* Updates the probe callback corresponding to a range of markers.
- * Must be called with markers_mutex held.
*/
void marker_update_probe_range(struct marker *begin,
struct marker *end, struct module *probe_module,
@@ -266,6 +265,7 @@
struct marker *iter;
struct marker_entry *mark_entry;
+ mutex_lock(&markers_mutex);
for (iter = begin; iter < end; iter++) {
mark_entry = get_marker(iter->name);
if (mark_entry && mark_entry->refcount) {
@@ -281,6 +281,7 @@
disable_marker(iter);
}
}
+ mutex_unlock(&markers_mutex);
}
/*
@@ -293,7 +294,6 @@
{
int refcount = 0;
- mutex_lock(&markers_mutex);
/* Core kernel markers */
marker_update_probe_range(__start___markers,
__stop___markers, probe_module, &refcount);
@@ -303,7 +303,6 @@
synchronize_sched();
deferred_sync = 0;
}
- mutex_unlock(&markers_mutex);
}
/**
@@ -320,7 +319,7 @@
marker_probe_func *probe, void *private)
{
struct marker_entry *entry;
- int ret = 0, need_update = 0;
+ int ret = 0;
mutex_lock(&markers_mutex);
entry = get_marker(name);
@@ -335,11 +334,11 @@
ret = add_marker(name, format, probe, private);
if (ret)
goto end;
- need_update = 1;
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(NULL);
+ return ret;
end:
mutex_unlock(&markers_mutex);
- if (need_update)
- marker_update_probes(NULL);
return ret;
}
EXPORT_SYMBOL_GPL(marker_probe_register);
@@ -355,7 +354,6 @@
struct module *probe_module;
struct marker_entry *entry;
void *private;
- int need_update = 0;
mutex_lock(&markers_mutex);
entry = get_marker(name);
@@ -368,11 +366,11 @@
probe_module = __module_text_address((unsigned long)entry->probe);
private = remove_marker(name);
deferred_sync = 1;
- need_update = 1;
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(probe_module);
+ return private;
end:
mutex_unlock(&markers_mutex);
- if (need_update)
- marker_update_probes(probe_module);
return private;
}
EXPORT_SYMBOL_GPL(marker_probe_unregister);
@@ -392,7 +390,6 @@
struct marker_entry *entry;
int found = 0;
unsigned int i;
- int need_update = 0;
mutex_lock(&markers_mutex);
for (i = 0; i < MARKER_TABLE_SIZE; i++) {
@@ -414,11 +411,11 @@
probe_module = __module_text_address((unsigned long)entry->probe);
private = remove_marker(entry->name);
deferred_sync = 1;
- need_update = 1;
+ mutex_unlock(&markers_mutex);
+ marker_update_probes(probe_module);
+ return private;
end:
mutex_unlock(&markers_mutex);
- if (need_update)
- marker_update_probes(probe_module);
return private;
}
EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
@@ -434,7 +431,7 @@
int marker_arm(const char *name)
{
struct marker_entry *entry;
- int ret = 0, need_update = 0;
+ int ret = 0;
mutex_lock(&markers_mutex);
entry = get_marker(name);
@@ -447,11 +444,9 @@
*/
if (entry->refcount++)
goto end;
- need_update = 1;
end:
mutex_unlock(&markers_mutex);
- if (need_update)
- marker_update_probes(NULL);
+ marker_update_probes(NULL);
return ret;
}
EXPORT_SYMBOL_GPL(marker_arm);
@@ -467,7 +462,7 @@
int marker_disarm(const char *name)
{
struct marker_entry *entry;
- int ret = 0, need_update = 0;
+ int ret = 0;
mutex_lock(&markers_mutex);
entry = get_marker(name);
@@ -486,11 +481,9 @@
ret = -EPERM;
goto end;
}
- need_update = 1;
end:
mutex_unlock(&markers_mutex);
- if (need_update)
- marker_update_probes(NULL);
+ marker_update_probes(NULL);
return ret;
}
EXPORT_SYMBOL_GPL(marker_disarm);
diff --git a/kernel/params.c b/kernel/params.c
index 16f269e..2a4c514 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -592,19 +592,16 @@
for (i=0; i < __stop___param - __start___param; i++) {
char *dot;
- size_t kplen;
+ size_t max_name_len;
kp = &__start___param[i];
- kplen = strlen(kp->name);
+ max_name_len =
+ min_t(size_t, MAX_KBUILD_MODNAME, strlen(kp->name));
- /* We do not handle args without periods. */
- if (kplen > MAX_KBUILD_MODNAME) {
- DEBUGP("kernel parameter name is too long: %s\n", kp->name);
- continue;
- }
- dot = memchr(kp->name, '.', kplen);
+ dot = memchr(kp->name, '.', max_name_len);
if (!dot) {
- DEBUGP("couldn't find period in %s\n", kp->name);
+ DEBUGP("couldn't find period in first %d characters "
+ "of %s\n", MAX_KBUILD_MODNAME, kp->name);
continue;
}
name_len = dot - kp->name;
diff --git a/kernel/pid.c b/kernel/pid.c
index d1db36b..f815455 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -537,6 +537,7 @@
return NULL;
}
+#ifdef CONFIG_PID_NS
static struct pid_namespace *create_pid_namespace(int level)
{
struct pid_namespace *ns;
@@ -621,6 +622,7 @@
if (parent != NULL)
put_pid_ns(parent);
}
+#endif /* CONFIG_PID_NS */
void zap_pid_ns_processes(struct pid_namespace *pid_ns)
{
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 8b15f77..05b6479 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -456,7 +456,17 @@
int error;
unsigned int flags;
- mutex_lock(&pm_mutex);
+ /*
+ * name_to_dev_t() below takes a sysfs buffer mutex when sysfs
+ * is configured into the kernel. Since the regular hibernate
+ * trigger path is via sysfs which takes a buffer mutex before
+ * calling hibernate functions (which take pm_mutex) this can
+ * cause lockdep to complain about a possible ABBA deadlock
+ * which cannot happen since we're in the boot code here and
+ * sysfs can't be invoked yet. Therefore, we use a subclass
+ * here to avoid lockdep complaining.
+ */
+ mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING);
if (!swsusp_resume_device) {
if (!strlen(resume_file)) {
mutex_unlock(&pm_mutex);
diff --git a/kernel/resource.c b/kernel/resource.c
index a358142..2eb553d 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -277,7 +277,7 @@
int ret = -1;
res.start = (u64) start_pfn << PAGE_SHIFT;
res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
- res.flags = IORESOURCE_MEM;
+ res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
orig_end = res.end;
while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) {
pfn = (unsigned long)(res.start >> PAGE_SHIFT);
diff --git a/kernel/sched.c b/kernel/sched.c
index b18f231..4fb3532 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -52,7 +52,6 @@
#include <linux/cpu.h>
#include <linux/cpuset.h>
#include <linux/percpu.h>
-#include <linux/cpu_acct.h>
#include <linux/kthread.h>
#include <linux/seq_file.h>
#include <linux/sysctl.h>
@@ -3338,13 +3337,9 @@
{
struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
cputime64_t tmp;
- struct rq *rq = this_rq();
p->utime = cputime_add(p->utime, cputime);
- if (p != rq->idle)
- cpuacct_charge(p, cputime);
-
/* Add user time to cpustat. */
tmp = cputime_to_cputime64(cputime);
if (TASK_NICE(p) > 0)
@@ -3408,10 +3403,9 @@
cpustat->irq = cputime64_add(cpustat->irq, tmp);
else if (softirq_count())
cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
- else if (p != rq->idle) {
+ else if (p != rq->idle)
cpustat->system = cputime64_add(cpustat->system, tmp);
- cpuacct_charge(p, cputime);
- } else if (atomic_read(&rq->nr_iowait) > 0)
+ else if (atomic_read(&rq->nr_iowait) > 0)
cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
else
cpustat->idle = cputime64_add(cpustat->idle, tmp);
@@ -3447,10 +3441,8 @@
cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
else
cpustat->idle = cputime64_add(cpustat->idle, tmp);
- } else {
+ } else
cpustat->steal = cputime64_add(cpustat->steal, tmp);
- cpuacct_charge(p, -tmp);
- }
}
/*
diff --git a/kernel/signal.c b/kernel/signal.c
index 909a0cc..afa4f78 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -55,7 +55,7 @@
* signal handler may change by the time it is
* unblocked.
*/
- if (sigismember(&t->blocked, sig))
+ if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
return 0;
/* Is it explicitly or implicitly ignored? */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 3a1744f..0deed82 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2620,6 +2620,10 @@
int name[CTL_MAXNAME];
int i;
+ /* Check args->nlen. */
+ if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
+ return -ENOTDIR;
+
/* Read in the sysctl name for better debug message logging */
for (i = 0; i < args->nlen; i++)
if (get_user(name[i], args->name + i))
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index 5a2f2b2..4abc6d2 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -738,7 +738,7 @@
{ NET_ROSE, "rose", trans_net_rose_table },
{ NET_IPV6, "ipv6", trans_net_ipv6_table },
{ NET_X25, "x25", trans_net_x25_table },
- { NET_TR, "tr", trans_net_tr_table },
+ { NET_TR, "token-ring", trans_net_tr_table },
{ NET_DECNET, "decnet", trans_net_decnet_table },
/* NET_ECONET not used */
{ NET_SCTP, "sctp", trans_net_sctp_table },
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 354e74b..07e86a8 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -398,31 +398,31 @@
fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]);
file = fget_light(fd, &fput_needed);
- if (file) {
- size = nla_total_size(sizeof(struct cgroupstats));
+ if (!file)
+ return 0;
- rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb,
- size);
- if (rc < 0)
- goto err;
+ size = nla_total_size(sizeof(struct cgroupstats));
- na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
- sizeof(struct cgroupstats));
- stats = nla_data(na);
- memset(stats, 0, sizeof(*stats));
+ rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb,
+ size);
+ if (rc < 0)
+ goto err;
- rc = cgroupstats_build(stats, file->f_dentry);
- if (rc < 0)
- goto err;
+ na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
+ sizeof(struct cgroupstats));
+ stats = nla_data(na);
+ memset(stats, 0, sizeof(*stats));
- fput_light(file, fput_needed);
- return send_reply(rep_skb, info->snd_pid);
+ rc = cgroupstats_build(stats, file->f_dentry);
+ if (rc < 0) {
+ nlmsg_free(rep_skb);
+ goto err;
}
+ rc = send_reply(rep_skb, info->snd_pid);
+
err:
- if (file)
- fput_light(file, fput_needed);
- nlmsg_free(rep_skb);
+ fput_light(file, fput_needed);
return rc;
}
diff --git a/lib/Makefile b/lib/Makefile
index 3a0983b..b6793ed 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,7 +4,7 @@
lib-y := ctype.o string.o vsprintf.o cmdline.o \
rbtree.o radix-tree.o dump_stack.o \
- idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \
+ idr.o int_sqrt.o extable.o prio_tree.o \
sha1.o irq_regs.o reciprocal_div.o argv_split.o \
proportions.o prio_heap.o
@@ -14,7 +14,7 @@
lib-y += kobject.o kref.o klist.o
obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
- bust_spinlocks.o hexdump.o kasprintf.o
+ bust_spinlocks.o hexdump.o kasprintf.o bitmap.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 8b809ec..6121b57 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -116,7 +116,9 @@
static void free_huge_page(struct page *page)
{
int nid = page_to_nid(page);
+ struct address_space *mapping;
+ mapping = (struct address_space *) page_private(page);
BUG_ON(page_count(page));
INIT_LIST_HEAD(&page->lru);
@@ -129,6 +131,9 @@
enqueue_huge_page(page);
}
spin_unlock(&hugetlb_lock);
+ if (mapping)
+ hugetlb_put_quota(mapping, 1);
+ set_page_private(page, 0);
}
/*
@@ -323,7 +328,7 @@
* allocated to satisfy the reservation must be explicitly freed if they were
* never used.
*/
-void return_unused_surplus_pages(unsigned long unused_resv_pages)
+static void return_unused_surplus_pages(unsigned long unused_resv_pages)
{
static int nid = -1;
struct page *page;
@@ -353,35 +358,50 @@
}
}
+
+static struct page *alloc_huge_page_shared(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ struct page *page;
+
+ spin_lock(&hugetlb_lock);
+ page = dequeue_huge_page(vma, addr);
+ spin_unlock(&hugetlb_lock);
+ return page ? page : ERR_PTR(-VM_FAULT_OOM);
+}
+
+static struct page *alloc_huge_page_private(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ struct page *page = NULL;
+
+ if (hugetlb_get_quota(vma->vm_file->f_mapping, 1))
+ return ERR_PTR(-VM_FAULT_SIGBUS);
+
+ spin_lock(&hugetlb_lock);
+ if (free_huge_pages > resv_huge_pages)
+ page = dequeue_huge_page(vma, addr);
+ spin_unlock(&hugetlb_lock);
+ if (!page)
+ page = alloc_buddy_huge_page(vma, addr);
+ return page ? page : ERR_PTR(-VM_FAULT_OOM);
+}
+
static struct page *alloc_huge_page(struct vm_area_struct *vma,
unsigned long addr)
{
- struct page *page = NULL;
- int use_reserved_page = vma->vm_flags & VM_MAYSHARE;
+ struct page *page;
+ struct address_space *mapping = vma->vm_file->f_mapping;
- spin_lock(&hugetlb_lock);
- if (!use_reserved_page && (free_huge_pages <= resv_huge_pages))
- goto fail;
+ if (vma->vm_flags & VM_MAYSHARE)
+ page = alloc_huge_page_shared(vma, addr);
+ else
+ page = alloc_huge_page_private(vma, addr);
- page = dequeue_huge_page(vma, addr);
- if (!page)
- goto fail;
-
- spin_unlock(&hugetlb_lock);
- set_page_refcounted(page);
- return page;
-
-fail:
- spin_unlock(&hugetlb_lock);
-
- /*
- * Private mappings do not use reserved huge pages so the allocation
- * may have failed due to an undersized hugetlb pool. Try to grab a
- * surplus huge page from the buddy allocator.
- */
- if (!use_reserved_page)
- page = alloc_buddy_huge_page(vma, addr);
-
+ if (!IS_ERR(page)) {
+ set_page_refcounted(page);
+ set_page_private(page, (unsigned long) mapping);
+ }
return page;
}
@@ -726,9 +746,9 @@
page_cache_get(old_page);
new_page = alloc_huge_page(vma, address);
- if (!new_page) {
+ if (IS_ERR(new_page)) {
page_cache_release(old_page);
- return VM_FAULT_OOM;
+ return -PTR_ERR(new_page);
}
spin_unlock(&mm->page_table_lock);
@@ -772,27 +792,28 @@
size = i_size_read(mapping->host) >> HPAGE_SHIFT;
if (idx >= size)
goto out;
- if (hugetlb_get_quota(mapping))
- goto out;
page = alloc_huge_page(vma, address);
- if (!page) {
- hugetlb_put_quota(mapping);
- ret = VM_FAULT_OOM;
+ if (IS_ERR(page)) {
+ ret = -PTR_ERR(page);
goto out;
}
clear_huge_page(page, address);
if (vma->vm_flags & VM_SHARED) {
int err;
+ struct inode *inode = mapping->host;
err = add_to_page_cache(page, mapping, idx, GFP_KERNEL);
if (err) {
put_page(page);
- hugetlb_put_quota(mapping);
if (err == -EEXIST)
goto retry;
goto out;
}
+
+ spin_lock(&inode->i_lock);
+ inode->i_blocks += BLOCKS_PER_HUGEPAGE;
+ spin_unlock(&inode->i_lock);
} else
lock_page(page);
}
@@ -822,7 +843,6 @@
backout:
spin_unlock(&mm->page_table_lock);
- hugetlb_put_quota(mapping);
unlock_page(page);
put_page(page);
goto out;
@@ -868,7 +888,8 @@
int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
struct page **pages, struct vm_area_struct **vmas,
- unsigned long *position, int *length, int i)
+ unsigned long *position, int *length, int i,
+ int write)
{
unsigned long pfn_offset;
unsigned long vaddr = *position;
@@ -890,7 +911,7 @@
int ret;
spin_unlock(&mm->page_table_lock);
- ret = hugetlb_fault(mm, vma, vaddr, 0);
+ ret = hugetlb_fault(mm, vma, vaddr, write);
spin_lock(&mm->page_table_lock);
if (!(ret & VM_FAULT_ERROR))
continue;
@@ -1132,6 +1153,8 @@
if (chg < 0)
return chg;
+ if (hugetlb_get_quota(inode->i_mapping, chg))
+ return -ENOSPC;
ret = hugetlb_acct_memory(chg);
if (ret < 0)
return ret;
@@ -1142,5 +1165,11 @@
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
{
long chg = region_truncate(&inode->i_mapping->private_list, offset);
- hugetlb_acct_memory(freed - chg);
+
+ spin_lock(&inode->i_lock);
+ inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed;
+ spin_unlock(&inode->i_lock);
+
+ hugetlb_put_quota(inode->i_mapping, (chg - freed));
+ hugetlb_acct_memory(-(chg - freed));
}
diff --git a/mm/memory.c b/mm/memory.c
index 9791e47..4bf0b6d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1036,7 +1036,7 @@
if (is_vm_hugetlb_page(vma)) {
i = follow_hugetlb_page(mm, vma, pages, vmas,
- &start, &len, i);
+ &start, &len, i, write);
continue;
}
@@ -2084,9 +2084,9 @@
count_vm_event(PGMAJFAULT);
}
- delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
mark_page_accessed(page);
lock_page(page);
+ delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
/*
* Back out if somebody else already faulted in this pte.
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 3a47871..9512a54 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -39,7 +39,7 @@
res->name = "System RAM";
res->start = start;
res->end = start + size - 1;
- res->flags = IORESOURCE_MEM;
+ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
if (request_resource(&iomem_resource, res) < 0) {
printk("System RAM resource %llx - %llx cannot be added\n",
(unsigned long long)res->start, (unsigned long long)res->end);
@@ -574,8 +574,8 @@
/* Ok, all of our target is islaoted.
We cannot do rollback at this point. */
offline_isolated_pages(start_pfn, end_pfn);
- /* reset pagetype flags */
- start_isolate_page_range(start_pfn, end_pfn);
+ /* reset pagetype flags and makes migrate type to be MOVABLE */
+ undo_isolate_page_range(start_pfn, end_pfn);
/* removal success */
zone->present_pages -= offlined_pages;
zone->zone_pgdat->node_present_pages -= offlined_pages;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index c1592a9..83c69f8 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -722,12 +722,29 @@
}
+/*
+ * Allocate a new page for page migration based on vma policy.
+ * Start assuming that page is mapped by vma pointed to by @private.
+ * Search forward from there, if not. N.B., this assumes that the
+ * list of pages handed to migrate_pages()--which is how we get here--
+ * is in virtual address order.
+ */
static struct page *new_vma_page(struct page *page, unsigned long private, int **x)
{
struct vm_area_struct *vma = (struct vm_area_struct *)private;
+ unsigned long uninitialized_var(address);
- return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
- page_address_in_vma(page, vma));
+ while (vma) {
+ address = page_address_in_vma(page, vma);
+ if (address != -EFAULT)
+ break;
+ vma = vma->vm_next;
+ }
+
+ /*
+ * if !vma, alloc_page_vma() will use task or system default policy
+ */
+ return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
}
#else
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 838a5e3..81a91e6 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -355,8 +355,8 @@
*/
static void balance_dirty_pages(struct address_space *mapping)
{
- long bdi_nr_reclaimable;
- long bdi_nr_writeback;
+ long nr_reclaimable, bdi_nr_reclaimable;
+ long nr_writeback, bdi_nr_writeback;
long background_thresh;
long dirty_thresh;
long bdi_thresh;
@@ -376,11 +376,26 @@
get_dirty_limits(&background_thresh, &dirty_thresh,
&bdi_thresh, bdi);
+
+ nr_reclaimable = global_page_state(NR_FILE_DIRTY) +
+ global_page_state(NR_UNSTABLE_NFS);
+ nr_writeback = global_page_state(NR_WRITEBACK);
+
bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE);
bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK);
+
if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh)
break;
+ /*
+ * Throttle it only when the background writeback cannot
+ * catch-up. This avoids (excessively) small writeouts
+ * when the bdi limits are ramping up.
+ */
+ if (nr_reclaimable + nr_writeback <
+ (background_thresh + dirty_thresh) / 2)
+ break;
+
if (!bdi->dirty_exceeded)
bdi->dirty_exceeded = 1;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index da69d83..12376ae 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -749,23 +749,6 @@
return move_freepages(zone, start_page, end_page, migratetype);
}
-/* Return the page with the lowest PFN in the list */
-static struct page *min_page(struct list_head *list)
-{
- unsigned long min_pfn = -1UL;
- struct page *min_page = NULL, *page;;
-
- list_for_each_entry(page, list, lru) {
- unsigned long pfn = page_to_pfn(page);
- if (pfn < min_pfn) {
- min_pfn = pfn;
- min_page = page;
- }
- }
-
- return min_page;
-}
-
/* Remove an element from the buddy allocator from the fallback list */
static struct page *__rmqueue_fallback(struct zone *zone, int order,
int start_migratetype)
@@ -789,11 +772,8 @@
if (list_empty(&area->free_list[migratetype]))
continue;
- /* Bias kernel allocations towards low pfns */
page = list_entry(area->free_list[migratetype].next,
struct page, lru);
- if (unlikely(start_migratetype != MIGRATE_MOVABLE))
- page = min_page(&area->free_list[migratetype]);
area->nr_free--;
/*
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index 8f92a29..3444b58 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -55,7 +55,7 @@
return 0;
undo:
for (pfn = start_pfn;
- pfn <= undo_pfn;
+ pfn < undo_pfn;
pfn += pageblock_nr_pages)
unset_migratetype_isolate(pfn_to_page(pfn));
@@ -76,7 +76,7 @@
pfn < end_pfn;
pfn += pageblock_nr_pages) {
page = __first_valid_page(pfn, pageblock_nr_pages);
- if (!page || get_pageblock_flags(page) != MIGRATE_ISOLATE)
+ if (!page || get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
continue;
unset_migratetype_isolate(page);
}
@@ -126,7 +126,7 @@
*/
for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
page = __first_valid_page(pfn, pageblock_nr_pages);
- if (page && get_pageblock_flags(page) != MIGRATE_ISOLATE)
+ if (page && get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
break;
}
if (pfn < end_pfn)
diff --git a/mm/rmap.c b/mm/rmap.c
index 8990f90..dc3be5f 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -183,7 +183,9 @@
}
/*
- * At what user virtual address is page expected in vma?
+ * At what user virtual address is page expected in @vma?
+ * Returns virtual address or -EFAULT if page's index/offset is not
+ * within the range mapped the @vma.
*/
static inline unsigned long
vma_address(struct page *page, struct vm_area_struct *vma)
@@ -193,8 +195,7 @@
address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
if (unlikely(address < vma->vm_start || address >= vma->vm_end)) {
- /* page should be within any vma from prio_tree_next */
- BUG_ON(!PageAnon(page));
+ /* page should be within @vma mapping range */
return -EFAULT;
}
return address;
diff --git a/mm/slab.c b/mm/slab.c
index cfa6be4..c31cd36 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1043,7 +1043,7 @@
}
ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d);
if (!ac_ptr[i]) {
- for (i--; i <= 0; i--)
+ for (i--; i >= 0; i--)
kfree(ac_ptr[i]);
kfree(ac_ptr);
return NULL;
diff --git a/mm/slub.c b/mm/slub.c
index 84f59fd..9acb413 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1080,7 +1080,6 @@
struct page *page;
struct kmem_cache_node *n;
void *start;
- void *end;
void *last;
void *p;
@@ -1101,7 +1100,6 @@
SetSlabDebug(page);
start = page_address(page);
- end = start + s->objects * s->size;
if (unlikely(s->flags & SLAB_POISON))
memset(start, POISON_INUSE, PAGE_SIZE << s->order);
diff --git a/mm/util.c b/mm/util.c
index 5f64026..8f18683 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -95,8 +95,8 @@
return (void *)p;
ret = kmalloc_track_caller(new_size, flags);
- if (ret) {
- memcpy(ret, p, min(new_size, ks));
+ if (ret && p) {
+ memcpy(ret, p, ks);
kfree(p);
}
return ret;
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 4651bf1..e8d846f 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -803,7 +803,7 @@
sysctl_stat_interval);
}
-static void __devinit start_cpu_timer(int cpu)
+static void __cpuinit start_cpu_timer(int cpu)
{
struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 1037748c..6567213 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -376,6 +376,7 @@
new_dev->init = vlan_dev_init;
new_dev->open = vlan_dev_open;
new_dev->stop = vlan_dev_stop;
+ new_dev->set_mac_address = vlan_set_mac_address;
new_dev->set_multicast_list = vlan_dev_set_multicast_list;
new_dev->change_rx_flags = vlan_change_rx_flags;
new_dev->destructor = free_netdev;
@@ -636,6 +637,10 @@
if (!vlandev)
continue;
+ flgs = vlandev->flags;
+ if (!(flgs & IFF_UP))
+ continue;
+
vlan_sync_address(dev, vlandev);
}
break;
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index cf4a80d..2cd139307 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -60,6 +60,7 @@
int vlan_dev_change_mtu(struct net_device *dev, int new_mtu);
int vlan_dev_open(struct net_device* dev);
int vlan_dev_stop(struct net_device* dev);
+int vlan_set_mac_address(struct net_device *dev, void *p);
int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
void vlan_dev_set_ingress_priority(const struct net_device *dev,
u32 skb_prio, short vlan_prio);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 1a1740a..7a36878 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -665,6 +665,32 @@
return 0;
}
+int vlan_set_mac_address(struct net_device *dev, void *p)
+{
+ struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+ struct sockaddr *addr = p;
+ int err;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ if (!(dev->flags & IFF_UP))
+ goto out;
+
+ if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) {
+ err = dev_unicast_add(real_dev, addr->sa_data, ETH_ALEN);
+ if (err < 0)
+ return err;
+ }
+
+ if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
+ dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN);
+
+out:
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ return 0;
+}
+
int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index da22f90..c1757c7 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -766,6 +766,9 @@
if (!nf_bridge)
return NF_ACCEPT;
+ if (!(nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT)))
+ return NF_ACCEPT;
+
if (!realoutdev)
return NF_DROP;
diff --git a/net/core/dev.c b/net/core/dev.c
index be6ceda..86d6261 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1171,6 +1171,8 @@
nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
}
}
+
+ raw_notifier_chain_unregister(&netdev_chain, nb);
goto unlock;
}
@@ -2688,7 +2690,7 @@
proc_net_remove(net, "dev");
}
-static struct pernet_operations dev_proc_ops = {
+static struct pernet_operations __net_initdata dev_proc_ops = {
.init = dev_proc_net_init,
.exit = dev_proc_net_exit,
};
@@ -4330,7 +4332,6 @@
static int __net_init netdev_init(struct net *net)
{
INIT_LIST_HEAD(&net->dev_base_head);
- rwlock_init(&dev_base_lock);
net->dev_name_head = netdev_create_hash();
if (net->dev_name_head == NULL)
@@ -4354,7 +4355,7 @@
kfree(net->dev_index_head);
}
-static struct pernet_operations netdev_net_ops = {
+static struct pernet_operations __net_initdata netdev_net_ops = {
.init = netdev_init,
.exit = netdev_exit,
};
@@ -4385,7 +4386,7 @@
rtnl_unlock();
}
-static struct pernet_operations default_device_ops = {
+static struct pernet_operations __net_initdata default_device_ops = {
.exit = default_device_exit,
};
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index ae35405..69fff16 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -168,13 +168,13 @@
da = from->mc_list;
while (da != NULL) {
next = da->next;
- if (!da->da_synced)
- continue;
- __dev_addr_delete(&to->mc_list, &to->mc_count,
- da->da_addr, da->da_addrlen, 0);
- da->da_synced = 0;
- __dev_addr_delete(&from->mc_list, &from->mc_count,
- da->da_addr, da->da_addrlen, 0);
+ if (da->da_synced) {
+ __dev_addr_delete(&to->mc_list, &to->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ da->da_synced = 0;
+ __dev_addr_delete(&from->mc_list, &from->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ }
da = next;
}
__dev_set_rx_mode(to);
@@ -285,7 +285,7 @@
proc_net_remove(net, "dev_mcast");
}
-static struct pernet_operations dev_mc_net_ops = {
+static struct pernet_operations __net_initdata dev_mc_net_ops = {
.init = dev_mc_net_init,
.exit = dev_mc_net_exit,
};
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 13de6f5..848132b 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -18,6 +18,28 @@
static LIST_HEAD(rules_ops);
static DEFINE_SPINLOCK(rules_mod_lock);
+int fib_default_rule_add(struct fib_rules_ops *ops,
+ u32 pref, u32 table, u32 flags)
+{
+ struct fib_rule *r;
+
+ r = kzalloc(ops->rule_size, GFP_KERNEL);
+ if (r == NULL)
+ return -ENOMEM;
+
+ atomic_set(&r->refcnt, 1);
+ r->action = FR_ACT_TO_TBL;
+ r->pref = pref;
+ r->table = table;
+ r->flags = flags;
+
+ /* The lock is not required here, the list in unreacheable
+ * at the moment this function is called */
+ list_add_tail(&r->list, &ops->rules_list);
+ return 0;
+}
+EXPORT_SYMBOL(fib_default_rule_add);
+
static void notify_rule_change(int event, struct fib_rule *rule,
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
u32 pid);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 3f6d37d..383252b 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -188,6 +188,7 @@
pure_initcall(net_ns_init);
+#ifdef CONFIG_NET_NS
static int register_pernet_operations(struct list_head *list,
struct pernet_operations *ops)
{
@@ -228,6 +229,23 @@
ops->exit(net);
}
+#else
+
+static int register_pernet_operations(struct list_head *list,
+ struct pernet_operations *ops)
+{
+ if (ops->init == NULL)
+ return 0;
+ return ops->init(&init_net);
+}
+
+static void unregister_pernet_operations(struct pernet_operations *ops)
+{
+ if (ops->exit)
+ ops->exit(&init_net);
+}
+#endif
+
/**
* register_pernet_subsys - register a network namespace subsystem
* @ops: pernet operations structure for the subsystem
diff --git a/net/core/sock.c b/net/core/sock.c
index 8fc2f84..c519b43 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2097,7 +2097,3 @@
EXPORT_SYMBOL(sock_i_uid);
EXPORT_SYMBOL(sock_i_ino);
EXPORT_SYMBOL(sysctl_optmem_max);
-#ifdef CONFIG_SYSCTL
-EXPORT_SYMBOL(sysctl_rmem_max);
-EXPORT_SYMBOL(sysctl_wmem_max);
-#endif
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 97eee5e..66663e5 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -293,9 +293,7 @@
dn_rt_hash_table[hash].chain);
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
- rth->u.dst.__use++;
- dst_hold(&rth->u.dst);
- rth->u.dst.lastuse = now;
+ dst_use(&rth->u.dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
dnrt_drop(rt);
@@ -308,9 +306,7 @@
rcu_assign_pointer(rt->u.dst.dn_next, dn_rt_hash_table[hash].chain);
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
- dst_hold(&rt->u.dst);
- rt->u.dst.__use++;
- rt->u.dst.lastuse = now;
+ dst_use(&rt->u.dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
*rp = rt;
return 0;
@@ -1182,9 +1178,7 @@
(flp->mark == rt->fl.mark) &&
(rt->fl.iif == 0) &&
(rt->fl.oif == flp->oif)) {
- rt->u.dst.lastuse = jiffies;
- dst_hold(&rt->u.dst);
- rt->u.dst.__use++;
+ dst_use(&rt->u.dst, jiffies);
rcu_read_unlock_bh();
*pprt = &rt->u.dst;
return 0;
@@ -1456,9 +1450,7 @@
(rt->fl.oif == 0) &&
(rt->fl.mark == skb->mark) &&
(rt->fl.iif == cb->iif)) {
- rt->u.dst.lastuse = jiffies;
- dst_hold(&rt->u.dst);
- rt->u.dst.__use++;
+ dst_use(&rt->u.dst, jiffies);
rcu_read_unlock();
skb->dst = (struct dst_entry *)rt;
return 0;
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index ddd3f04..ffebea0 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -48,15 +48,6 @@
u8 flags;
};
-static struct dn_fib_rule default_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7fff,
- .table = RT_TABLE_MAIN,
- .action = FR_ACT_TO_TBL,
- },
-};
-
int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
{
@@ -262,8 +253,8 @@
void __init dn_fib_rules_init(void)
{
- list_add_tail(&default_rule.common.list,
- &dn_fib_rules_ops.rules_list);
+ BUG_ON(fib_default_rule_add(&dn_fib_rules_ops, 0x7fff,
+ RT_TABLE_MAIN, 0));
fib_rules_register(&dn_fib_rules_ops);
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index ac36767..e01b59a 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -470,7 +470,7 @@
{
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
struct iw_mlme *mlme = (struct iw_mlme *)extra;
- u16 reason = cpu_to_le16(mlme->reason_code);
+ u16 reason = mlme->reason_code;
struct ieee80211softmac_network *net;
int err = -EINVAL;
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index f16839c..a0ada3a 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -49,33 +49,6 @@
#endif
};
-static struct fib4_rule default_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7FFF,
- .table = RT_TABLE_DEFAULT,
- .action = FR_ACT_TO_TBL,
- },
-};
-
-static struct fib4_rule main_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7FFE,
- .table = RT_TABLE_MAIN,
- .action = FR_ACT_TO_TBL,
- },
-};
-
-static struct fib4_rule local_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .table = RT_TABLE_LOCAL,
- .action = FR_ACT_TO_TBL,
- .flags = FIB_RULE_PERMANENT,
- },
-};
-
#ifdef CONFIG_NET_CLS_ROUTE
u32 fib_rules_tclass(struct fib_result *res)
{
@@ -319,11 +292,27 @@
.owner = THIS_MODULE,
};
+static int __init fib_default_rules_init(void)
+{
+ int err;
+
+ err = fib_default_rule_add(&fib4_rules_ops, 0,
+ RT_TABLE_LOCAL, FIB_RULE_PERMANENT);
+ if (err < 0)
+ return err;
+ err = fib_default_rule_add(&fib4_rules_ops, 0x7FFE,
+ RT_TABLE_MAIN, 0);
+ if (err < 0)
+ return err;
+ err = fib_default_rule_add(&fib4_rules_ops, 0x7FFF,
+ RT_TABLE_DEFAULT, 0);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
void __init fib4_rules_init(void)
{
- list_add_tail(&local_rule.common.list, &fib4_rules_ops.rules_list);
- list_add_tail(&main_rule.common.list, &fib4_rules_ops.rules_list);
- list_add_tail(&default_rule.common.list, &fib4_rules_ops.rules_list);
-
+ BUG_ON(fib_default_rules_init());
fib_rules_register(&fib4_rules_ops);
}
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 771031d..af99519 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -61,7 +61,7 @@
* 4. Global variable peer_total is modified under the pool lock.
* 5. struct inet_peer fields modification:
* avl_left, avl_right, avl_parent, avl_height: pool lock
- * unused_next, unused_prevp: unused node list lock
+ * unused: unused node list lock
* refcnt: atomically against modifications on other CPU;
* usually under some other lock to prevent node disappearing
* dtime: unused node list lock
@@ -94,8 +94,7 @@
int inet_peer_gc_mintime __read_mostly = 10 * HZ;
int inet_peer_gc_maxtime __read_mostly = 120 * HZ;
-static struct inet_peer *inet_peer_unused_head;
-static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
+static LIST_HEAD(unused_peers);
static DEFINE_SPINLOCK(inet_peer_unused_lock);
static void peer_check_expire(unsigned long dummy);
@@ -138,15 +137,7 @@
static void unlink_from_unused(struct inet_peer *p)
{
spin_lock_bh(&inet_peer_unused_lock);
- if (p->unused_prevp != NULL) {
- /* On unused list. */
- *p->unused_prevp = p->unused_next;
- if (p->unused_next != NULL)
- p->unused_next->unused_prevp = p->unused_prevp;
- else
- inet_peer_unused_tailp = p->unused_prevp;
- p->unused_prevp = NULL; /* mark it as removed */
- }
+ list_del_init(&p->unused);
spin_unlock_bh(&inet_peer_unused_lock);
}
@@ -337,24 +328,24 @@
/* May be called with local BH enabled. */
static int cleanup_once(unsigned long ttl)
{
- struct inet_peer *p;
+ struct inet_peer *p = NULL;
/* Remove the first entry from the list of unused nodes. */
spin_lock_bh(&inet_peer_unused_lock);
- p = inet_peer_unused_head;
- if (p != NULL) {
- __u32 delta = (__u32)jiffies - p->dtime;
+ if (!list_empty(&unused_peers)) {
+ __u32 delta;
+
+ p = list_first_entry(&unused_peers, struct inet_peer, unused);
+ delta = (__u32)jiffies - p->dtime;
+
if (delta < ttl) {
/* Do not prune fresh entries. */
spin_unlock_bh(&inet_peer_unused_lock);
return -1;
}
- inet_peer_unused_head = p->unused_next;
- if (p->unused_next != NULL)
- p->unused_next->unused_prevp = p->unused_prevp;
- else
- inet_peer_unused_tailp = p->unused_prevp;
- p->unused_prevp = NULL; /* mark as not on the list */
+
+ list_del_init(&p->unused);
+
/* Grab an extra reference to prevent node disappearing
* before unlink_from_pool() call. */
atomic_inc(&p->refcnt);
@@ -412,7 +403,7 @@
/* Link the node. */
link_to_pool(n);
- n->unused_prevp = NULL; /* not on the list */
+ INIT_LIST_HEAD(&n->unused);
peer_total++;
write_unlock_bh(&peer_pool_lock);
@@ -467,10 +458,7 @@
{
spin_lock_bh(&inet_peer_unused_lock);
if (atomic_dec_and_test(&p->refcnt)) {
- p->unused_prevp = inet_peer_unused_tailp;
- p->unused_next = NULL;
- *inet_peer_unused_tailp = p;
- inet_peer_unused_tailp = &p->unused_next;
+ list_add_tail(&p->unused, &unused_peers);
p->dtime = (__u32)jiffies;
}
spin_unlock_bh(&inet_peer_unused_lock);
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index b7eeae6..0a9f3c3 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -441,7 +441,6 @@
} else
return NULL;
}
-EXPORT_SYMBOL(ip_vs_try_bind_dest);
/*
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 3c4d22a..b64cf45 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -604,7 +604,6 @@
ip_vs_service_put(svc);
return dest;
}
-EXPORT_SYMBOL(ip_vs_find_dest);
/*
* Lookup dest by {svc,addr,port} in the destination trash.
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 56e93f6..70e7997 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -681,7 +681,7 @@
if (!nat)
return 0;
- memset(nat, 0, sizeof(nat));
+ memset(nat, 0, sizeof(*nat));
i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
return 0;
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 21b12de..1bff9ed 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -578,6 +578,9 @@
i = (i + 1) & rt_hash_mask;
rthp = &rt_hash_table[i].chain;
+ if (need_resched())
+ cond_resched();
+
if (*rthp == NULL)
continue;
spin_lock_bh(rt_hash_lock_addr(i));
@@ -851,9 +854,7 @@
*/
rcu_assign_pointer(rt_hash_table[hash].chain, rth);
- rth->u.dst.__use++;
- dst_hold(&rth->u.dst);
- rth->u.dst.lastuse = now;
+ dst_use(&rth->u.dst, now);
spin_unlock_bh(rt_hash_lock_addr(hash));
rt_drop(rt);
@@ -1813,11 +1814,6 @@
goto martian_destination;
err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
- if (err == -ENOBUFS)
- goto e_nobufs;
- if (err == -EINVAL)
- goto e_inval;
-
done:
in_dev_put(in_dev);
if (free_res)
@@ -1935,9 +1931,7 @@
rth->fl.oif == 0 &&
rth->fl.mark == skb->mark &&
rth->fl.fl4_tos == tos) {
- rth->u.dst.lastuse = jiffies;
- dst_hold(&rth->u.dst);
- rth->u.dst.__use++;
+ dst_use(&rth->u.dst, jiffies);
RT_CACHE_STAT_INC(in_hit);
rcu_read_unlock();
skb->dst = (struct dst_entry*)rth;
@@ -2331,9 +2325,7 @@
rth->fl.mark == flp->mark &&
!((rth->fl.fl4_tos ^ flp->fl4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK))) {
- rth->u.dst.lastuse = jiffies;
- dst_hold(&rth->u.dst);
- rth->u.dst.__use++;
+ dst_use(&rth->u.dst, jiffies);
RT_CACHE_STAT_INC(out_hit);
rcu_read_unlock_bh();
*rp = rth;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ca9590f..0f0c1c9 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1269,6 +1269,9 @@
if (before(TCP_SKB_CB(ack_skb)->ack_seq, prior_snd_una - tp->max_window))
return 0;
+ if (!tp->packets_out)
+ goto out;
+
/* SACK fastpath:
* if the only SACK change is the increase of the end_seq of
* the first block then only apply that SACK block
@@ -1400,11 +1403,9 @@
/* DSACK info lost if out-of-mem, try SACK still */
if (in_sack <= 0)
in_sack = tcp_match_skb_to_sack(sk, skb, start_seq, end_seq);
- if (in_sack < 0)
+ if (unlikely(in_sack < 0))
break;
- fack_count += tcp_skb_pcount(skb);
-
sacked = TCP_SKB_CB(skb)->sacked;
/* Account D-SACK for retransmitted packet. */
@@ -1419,19 +1420,17 @@
if ((dup_sack && in_sack) &&
(sacked&TCPCB_SACKED_ACKED))
reord = min(fack_count, reord);
- } else {
- /* If it was in a hole, we detected reordering. */
- if (fack_count < prior_fackets &&
- !(sacked&TCPCB_SACKED_ACKED))
- reord = min(fack_count, reord);
}
/* Nothing to do; acked frame is about to be dropped. */
+ fack_count += tcp_skb_pcount(skb);
continue;
}
- if (!in_sack)
+ if (!in_sack) {
+ fack_count += tcp_skb_pcount(skb);
continue;
+ }
if (!(sacked&TCPCB_SACKED_ACKED)) {
if (sacked & TCPCB_SACKED_RETRANS) {
@@ -1448,12 +1447,17 @@
tp->retransmit_skb_hint = NULL;
}
} else {
- /* New sack for not retransmitted frame,
- * which was in hole. It is reordering.
- */
- if (!(sacked & TCPCB_RETRANS) &&
- fack_count < prior_fackets)
- reord = min(fack_count, reord);
+ if (!(sacked & TCPCB_RETRANS)) {
+ /* New sack for not retransmitted frame,
+ * which was in hole. It is reordering.
+ */
+ if (fack_count < prior_fackets)
+ reord = min(fack_count, reord);
+
+ /* SACK enhanced F-RTO (RFC4138; Appendix B) */
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark))
+ flag |= FLAG_ONLY_ORIG_SACKED;
+ }
if (sacked & TCPCB_LOST) {
TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
@@ -1462,24 +1466,13 @@
/* clear lost hint */
tp->retransmit_skb_hint = NULL;
}
- /* SACK enhanced F-RTO detection.
- * Set flag if and only if non-rexmitted
- * segments below frto_highmark are
- * SACKed (RFC4138; Appendix B).
- * Clearing correct due to in-order walk
- */
- if (after(end_seq, tp->frto_highmark)) {
- flag &= ~FLAG_ONLY_ORIG_SACKED;
- } else {
- if (!(sacked & TCPCB_RETRANS))
- flag |= FLAG_ONLY_ORIG_SACKED;
- }
}
TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
flag |= FLAG_DATA_SACKED;
tp->sacked_out += tcp_skb_pcount(skb);
+ fack_count += tcp_skb_pcount(skb);
if (fack_count > tp->fackets_out)
tp->fackets_out = fack_count;
@@ -1490,6 +1483,8 @@
} else {
if (dup_sack && (sacked&TCPCB_RETRANS))
reord = min(fack_count, reord);
+
+ fack_count += tcp_skb_pcount(skb);
}
/* D-SACK. We can detect redundant retransmission
@@ -1504,6 +1499,12 @@
tp->retransmit_skb_hint = NULL;
}
}
+
+ /* SACK enhanced FRTO (RFC4138, Appendix B): Clearing correct
+ * due to in-order walk
+ */
+ if (after(end_seq, tp->frto_highmark))
+ flag &= ~FLAG_ONLY_ORIG_SACKED;
}
if (tp->retrans_out &&
@@ -1515,7 +1516,9 @@
if ((reord < tp->fackets_out) && icsk->icsk_ca_state != TCP_CA_Loss &&
(!tp->frto_highmark || after(tp->snd_una, tp->frto_highmark)))
- tcp_update_reordering(sk, ((tp->fackets_out + 1) - reord), 0);
+ tcp_update_reordering(sk, tp->fackets_out - reord, 0);
+
+out:
#if FASTRETRANS_DEBUG > 0
BUG_TRAP((int)tp->sacked_out >= 0);
@@ -1671,6 +1674,9 @@
}
tcp_verify_left_out(tp);
+ /* Too bad if TCP was application limited */
+ tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp) + 1);
+
/* Earlier loss recovery underway (see RFC4138; Appendix B).
* The last condition is necessary at least in tp->frto_counter case.
*/
@@ -1703,6 +1709,8 @@
tcp_for_write_queue(skb, sk) {
if (skb == tcp_send_head(sk))
break;
+
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
/*
* Count the retransmission made on RTO correctly (only when
* waiting for the first ACK and did not get it)...
@@ -1716,7 +1724,7 @@
} else {
if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS)
tp->undo_marker = 0;
- TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS);
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
}
/* Don't lost mark skbs that were fwd transmitted after RTO */
@@ -2630,7 +2638,8 @@
* is before the ack sequence we can discard it as it's confirmed to have
* arrived at the other end.
*/
-static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p)
+static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p,
+ int prior_fackets)
{
struct tcp_sock *tp = tcp_sk(sk);
const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -2639,6 +2648,8 @@
int fully_acked = 1;
int flag = 0;
int prior_packets = tp->packets_out;
+ u32 cnt = 0;
+ u32 reord = tp->packets_out;
s32 seq_rtt = -1;
ktime_t last_ackt = net_invalid_timestamp();
@@ -2679,10 +2690,14 @@
if ((flag & FLAG_DATA_ACKED) ||
(packets_acked > 1))
flag |= FLAG_NONHEAD_RETRANS_ACKED;
- } else if (seq_rtt < 0) {
- seq_rtt = now - scb->when;
- if (fully_acked)
- last_ackt = skb->tstamp;
+ } else {
+ if (seq_rtt < 0) {
+ seq_rtt = now - scb->when;
+ if (fully_acked)
+ last_ackt = skb->tstamp;
+ }
+ if (!(sacked & TCPCB_SACKED_ACKED))
+ reord = min(cnt, reord);
}
if (sacked & TCPCB_SACKED_ACKED)
@@ -2693,12 +2708,16 @@
if ((sacked & TCPCB_URG) && tp->urg_mode &&
!before(end_seq, tp->snd_up))
tp->urg_mode = 0;
- } else if (seq_rtt < 0) {
- seq_rtt = now - scb->when;
- if (fully_acked)
- last_ackt = skb->tstamp;
+ } else {
+ if (seq_rtt < 0) {
+ seq_rtt = now - scb->when;
+ if (fully_acked)
+ last_ackt = skb->tstamp;
+ }
+ reord = min(cnt, reord);
}
tp->packets_out -= packets_acked;
+ cnt += packets_acked;
/* Initial outgoing SYN's get put onto the write_queue
* just like anything else we transmit. It is not
@@ -2730,13 +2749,18 @@
tcp_ack_update_rtt(sk, flag, seq_rtt);
tcp_rearm_rto(sk);
+ if (tcp_is_reno(tp)) {
+ tcp_remove_reno_sacks(sk, pkts_acked);
+ } else {
+ /* Non-retransmitted hole got filled? That's reordering */
+ if (reord < prior_fackets)
+ tcp_update_reordering(sk, tp->fackets_out - reord, 0);
+ }
+
tp->fackets_out -= min(pkts_acked, tp->fackets_out);
/* hint's skb might be NULL but we don't need to care */
tp->fastpath_cnt_hint -= min_t(u32, pkts_acked,
tp->fastpath_cnt_hint);
- if (tcp_is_reno(tp))
- tcp_remove_reno_sacks(sk, pkts_acked);
-
if (ca_ops->pkts_acked) {
s32 rtt_us = -1;
@@ -3019,6 +3043,7 @@
u32 ack_seq = TCP_SKB_CB(skb)->seq;
u32 ack = TCP_SKB_CB(skb)->ack_seq;
u32 prior_in_flight;
+ u32 prior_fackets;
s32 seq_rtt;
int prior_packets;
int frto_cwnd = 0;
@@ -3043,6 +3068,8 @@
tp->bytes_acked += min(ack - prior_snd_una, tp->mss_cache);
}
+ prior_fackets = tp->fackets_out;
+
if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
/* Window is constant, pure forward advance.
* No more checks are required.
@@ -3084,13 +3111,13 @@
prior_in_flight = tcp_packets_in_flight(tp);
/* See if we can take anything off of the retransmit queue. */
- flag |= tcp_clean_rtx_queue(sk, &seq_rtt);
+ flag |= tcp_clean_rtx_queue(sk, &seq_rtt, prior_fackets);
+ if (tp->frto_counter)
+ frto_cwnd = tcp_process_frto(sk, flag);
/* Guarantee sacktag reordering detection against wrap-arounds */
if (before(tp->frto_highmark, tp->snd_una))
tp->frto_highmark = 0;
- if (tp->frto_counter)
- frto_cwnd = tcp_process_frto(sk, flag);
if (tcp_ack_is_dubious(sk, flag)) {
/* Advance CWND, if state allows this. */
diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c
index a794a8c..978b3fd 100644
--- a/net/ipv4/tunnel4.c
+++ b/net/ipv4/tunnel4.c
@@ -17,6 +17,11 @@
static struct xfrm_tunnel *tunnel64_handlers;
static DEFINE_MUTEX(tunnel4_mutex);
+static inline struct xfrm_tunnel **fam_handlers(unsigned short family)
+{
+ return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
+}
+
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
{
struct xfrm_tunnel **pprev;
@@ -25,8 +30,7 @@
mutex_lock(&tunnel4_mutex);
- for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
- *pprev; pprev = &(*pprev)->next) {
+ for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) {
if ((*pprev)->priority > priority)
break;
if ((*pprev)->priority == priority)
@@ -53,8 +57,7 @@
mutex_lock(&tunnel4_mutex);
- for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
- *pprev; pprev = &(*pprev)->next) {
+ for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) {
if (*pprev == handler) {
*pprev = handler->next;
ret = 0;
@@ -118,6 +121,17 @@
break;
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static void tunnel64_err(struct sk_buff *skb, u32 info)
+{
+ struct xfrm_tunnel *handler;
+
+ for (handler = tunnel64_handlers; handler; handler = handler->next)
+ if (!handler->err_handler(skb, info))
+ break;
+}
+#endif
+
static struct net_protocol tunnel4_protocol = {
.handler = tunnel4_rcv,
.err_handler = tunnel4_err,
@@ -127,7 +141,7 @@
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct net_protocol tunnel64_protocol = {
.handler = tunnel64_rcv,
- .err_handler = tunnel4_err,
+ .err_handler = tunnel64_err,
.no_policy = 1,
};
#endif
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 706622a..428c6b0 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -31,25 +31,6 @@
static struct fib_rules_ops fib6_rules_ops;
-static struct fib6_rule main_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0x7FFE,
- .action = FR_ACT_TO_TBL,
- .table = RT6_TABLE_MAIN,
- },
-};
-
-static struct fib6_rule local_rule = {
- .common = {
- .refcnt = ATOMIC_INIT(2),
- .pref = 0,
- .action = FR_ACT_TO_TBL,
- .table = RT6_TABLE_LOCAL,
- .flags = FIB_RULE_PERMANENT,
- },
-};
-
struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
pol_lookup_t lookup)
{
@@ -270,11 +251,23 @@
.owner = THIS_MODULE,
};
+static int __init fib6_default_rules_init(void)
+{
+ int err;
+
+ err = fib_default_rule_add(&fib6_rules_ops, 0,
+ RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
+ if (err < 0)
+ return err;
+ err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
void __init fib6_rules_init(void)
{
- list_add_tail(&local_rule.common.list, &fib6_rules_ops.rules_list);
- list_add_tail(&main_rule.common.list, &fib6_rules_ops.rules_list);
-
+ BUG_ON(fib6_default_rules_init());
fib_rules_register(&fib6_rules_ops);
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 36f7dbf..67997a7 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1037,6 +1037,7 @@
ndmsg = nlmsg_data(nlh);
ndmsg->nduseropt_family = AF_INET6;
+ ndmsg->nduseropt_ifindex = ra->dev->ifindex;
ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type;
ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code;
ndmsg->nduseropt_opts_len = opt->nd_opt_len << 3;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 973a97a..6ecb5e6 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -544,12 +544,8 @@
rt = rt6_device_match(rt, fl->oif, flags);
BACKTRACK(&fl->fl6_src);
out:
- dst_hold(&rt->u.dst);
+ dst_use(&rt->u.dst, jiffies);
read_unlock_bh(&table->tb6_lock);
-
- rt->u.dst.lastuse = jiffies;
- rt->u.dst.__use++;
-
return rt;
}
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index a195a66..c76a952 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -92,11 +92,6 @@
extern struct ipx_route *ipxrtr_lookup(__be32 net);
extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
-#undef IPX_REFCNT_DEBUG
-#ifdef IPX_REFCNT_DEBUG
-atomic_t ipx_sock_nr;
-#endif
-
struct ipx_interface *ipx_interfaces_head(void)
{
struct ipx_interface *rc = NULL;
@@ -151,14 +146,7 @@
{
ipx_remove_socket(sk);
skb_queue_purge(&sk->sk_receive_queue);
-#ifdef IPX_REFCNT_DEBUG
- atomic_dec(&ipx_sock_nr);
- printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk,
- atomic_read(&ipx_sock_nr));
- if (atomic_read(&sk->sk_refcnt) != 1)
- printk(KERN_DEBUG "Destruction sock ipx %p delayed, cnt=%d\n",
- sk, atomic_read(&sk->sk_refcnt));
-#endif
+ sk_refcnt_debug_dec(sk);
sock_put(sk);
}
@@ -1384,11 +1372,8 @@
sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto);
if (!sk)
goto out;
-#ifdef IPX_REFCNT_DEBUG
- atomic_inc(&ipx_sock_nr);
- printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,
- atomic_read(&ipx_sock_nr));
-#endif
+
+ sk_refcnt_debug_inc(sk);
sock_init_data(sock, sk);
sk->sk_no_check = 1; /* Checksum off by default */
sock->ops = &ipx_dgram_ops;
@@ -1409,6 +1394,7 @@
sock_set_flag(sk, SOCK_DEAD);
sock->sk = NULL;
+ sk_refcnt_debug_release(sk);
ipx_destroy_socket(sk);
out:
return 0;
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 6fffb38..ce176e6 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -13,6 +13,18 @@
This option enables the hardware independent IEEE 802.11
networking stack.
+config MAC80211_RCSIMPLE
+ bool "'simple' rate control algorithm" if EMBEDDED
+ default y
+ depends on MAC80211
+ help
+ This option allows you to turn off the 'simple' rate
+ control algorithm in mac80211. If you do turn it off,
+ you absolutely need another rate control algorithm.
+
+ Say Y unless you know you will have another algorithm
+ available.
+
config MAC80211_LEDS
bool "Enable LED triggers"
depends on MAC80211 && LEDS_TRIGGERS
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 219cd9f..1e6237b 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -1,8 +1,9 @@
-obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o
+obj-$(CONFIG_MAC80211) += mac80211.o
mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
mac80211-objs-$(CONFIG_NET_SCHED) += wme.o
+mac80211-objs-$(CONFIG_MAC80211_RCSIMPLE) += rc80211_simple.o
mac80211-objs := \
ieee80211.o \
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index f484ca7..e0ee65a 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -1072,7 +1072,8 @@
ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
- result = ieee80211_init_rate_ctrl_alg(local, NULL);
+ result = ieee80211_init_rate_ctrl_alg(local,
+ hw->rate_control_algorithm);
if (result < 0) {
printk(KERN_DEBUG "%s: Failed to initialize rate control "
"algorithm\n", wiphy_name(local->hw.wiphy));
@@ -1233,8 +1234,17 @@
BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+#ifdef CONFIG_MAC80211_RCSIMPLE
+ ret = ieee80211_rate_control_register(&mac80211_rcsimple);
+ if (ret)
+ return ret;
+#endif
+
ret = ieee80211_wme_register();
if (ret) {
+#ifdef CONFIG_MAC80211_RCSIMPLE
+ ieee80211_rate_control_unregister(&mac80211_rcsimple);
+#endif
printk(KERN_DEBUG "ieee80211_init: failed to "
"initialize WME (err=%d)\n", ret);
return ret;
@@ -1248,6 +1258,10 @@
static void __exit ieee80211_exit(void)
{
+#ifdef CONFIG_MAC80211_RCSIMPLE
+ ieee80211_rate_control_unregister(&mac80211_rcsimple);
+#endif
+
ieee80211_wme_unregister();
ieee80211_debugfs_netdev_exit();
}
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h
deleted file mode 100644
index c15295d..0000000
--- a/net/mac80211/ieee80211_common.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * IEEE 802.11 driver (80211.o) -- hostapd interface
- * Copyright 2002-2004, Instant802 Networks, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef IEEE80211_COMMON_H
-#define IEEE80211_COMMON_H
-
-#include <linux/types.h>
-
-/*
- * This is common header information with user space. It is used on all
- * frames sent to wlan#ap interface.
- */
-
-#define IEEE80211_FI_VERSION 0x80211001
-
-struct ieee80211_frame_info {
- __be32 version;
- __be32 length;
- __be64 mactime;
- __be64 hosttime;
- __be32 phytype;
- __be32 channel;
- __be32 datarate;
- __be32 antenna;
- __be32 priority;
- __be32 ssi_type;
- __be32 ssi_signal;
- __be32 ssi_noise;
- __be32 preamble;
- __be32 encoding;
-
- /* Note: this structure is otherwise identical to capture format used
- * in linux-wlan-ng, but this additional field is used to provide meta
- * data about the frame to hostapd. This was the easiest method for
- * providing this information, but this might change in the future. */
- __be32 msg_type;
-} __attribute__ ((packed));
-
-
-enum ieee80211_msg_type {
- ieee80211_msg_normal = 0,
- ieee80211_msg_tx_callback_ack = 1,
- ieee80211_msg_tx_callback_fail = 2,
- /* hole at 3, was ieee80211_msg_passive_scan but unused */
- /* hole at 4, was ieee80211_msg_wep_frame_unknown_key but now unused */
- ieee80211_msg_michael_mic_failure = 5,
- /* hole at 6, was monitor but never sent to userspace */
- ieee80211_msg_sta_not_assoc = 7,
- /* 8 was ieee80211_msg_set_aid_for_sta */
- /* 9 was ieee80211_msg_key_threshold_notification */
- /* 11 was ieee80211_msg_radar */
-};
-
-struct ieee80211_msg_key_notification {
- int tx_rx_count;
- char ifname[IFNAMSIZ];
- u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast keys */
-};
-
-
-enum ieee80211_phytype {
- ieee80211_phytype_fhss_dot11_97 = 1,
- ieee80211_phytype_dsss_dot11_97 = 2,
- ieee80211_phytype_irbaseband = 3,
- ieee80211_phytype_dsss_dot11_b = 4,
- ieee80211_phytype_pbcc_dot11_b = 5,
- ieee80211_phytype_ofdm_dot11_g = 6,
- ieee80211_phytype_pbcc_dot11_g = 7,
- ieee80211_phytype_ofdm_dot11_a = 8,
-};
-
-enum ieee80211_ssi_type {
- ieee80211_ssi_none = 0,
- ieee80211_ssi_norm = 1, /* normalized, 0-1000 */
- ieee80211_ssi_dbm = 2,
- ieee80211_ssi_raw = 3, /* raw SSI */
-};
-
-struct ieee80211_radar_info {
- int channel;
- int radar;
- int radar_type;
-};
-
-#endif /* IEEE80211_COMMON_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4b4ed2a..b4e32ab 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -230,6 +230,7 @@
#define IEEE80211_STA_AUTO_SSID_SEL BIT(10)
#define IEEE80211_STA_AUTO_BSSID_SEL BIT(11)
#define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
+#define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
struct ieee80211_if_sta {
enum {
IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
@@ -259,7 +260,6 @@
unsigned long request;
struct sk_buff_head skb_queue;
- int key_management_enabled;
unsigned long last_probe;
#define IEEE80211_AUTH_ALG_OPEN BIT(0)
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 6caa3ec..7027eed 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -917,7 +917,6 @@
struct iw_request_info *info,
struct iw_param *data, char *extra)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
int ret = 0;
@@ -927,18 +926,21 @@
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_WPA_ENABLED:
case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- break;
case IW_AUTH_KEY_MGMT:
+ break;
+ case IW_AUTH_PRIVACY_INVOKED:
if (sdata->type != IEEE80211_IF_TYPE_STA)
ret = -EINVAL;
else {
+ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
/*
- * Key management was set by wpa_supplicant,
- * we only need this to associate to a network
- * that has privacy enabled regardless of not
- * having a key.
+ * Privacy invoked by wpa_supplicant, store the
+ * value and allow associating to a protected
+ * network without having a key up front.
*/
- sdata->u.sta.key_management_enabled = !!data->value;
+ if (data->value)
+ sdata->u.sta.flags |=
+ IEEE80211_STA_PRIVACY_INVOKED;
}
break;
case IW_AUTH_80211_AUTH_ALG:
@@ -948,11 +950,6 @@
else
ret = -EOPNOTSUPP;
break;
- case IW_AUTH_PRIVACY_INVOKED:
- if (local->ops->set_privacy_invoked)
- ret = local->ops->set_privacy_invoked(
- local_to_hw(local), data->value);
- break;
default:
ret = -EOPNOTSUPP;
break;
diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c
index 93abb8f..7254bd6 100644
--- a/net/mac80211/ieee80211_rate.c
+++ b/net/mac80211/ieee80211_rate.c
@@ -25,13 +25,25 @@
{
struct rate_control_alg *alg;
+ if (!ops->name)
+ return -EINVAL;
+
+ mutex_lock(&rate_ctrl_mutex);
+ list_for_each_entry(alg, &rate_ctrl_algs, list) {
+ if (!strcmp(alg->ops->name, ops->name)) {
+ /* don't register an algorithm twice */
+ WARN_ON(1);
+ return -EALREADY;
+ }
+ }
+
alg = kzalloc(sizeof(*alg), GFP_KERNEL);
if (alg == NULL) {
+ mutex_unlock(&rate_ctrl_mutex);
return -ENOMEM;
}
alg->ops = ops;
- mutex_lock(&rate_ctrl_mutex);
list_add_tail(&alg->list, &rate_ctrl_algs);
mutex_unlock(&rate_ctrl_mutex);
@@ -61,9 +73,12 @@
struct rate_control_alg *alg;
struct rate_control_ops *ops = NULL;
+ if (!name)
+ return NULL;
+
mutex_lock(&rate_ctrl_mutex);
list_for_each_entry(alg, &rate_ctrl_algs, list) {
- if (!name || !strcmp(alg->ops->name, name))
+ if (!strcmp(alg->ops->name, name))
if (try_module_get(alg->ops->module)) {
ops = alg->ops;
break;
@@ -80,9 +95,12 @@
{
struct rate_control_ops *ops;
+ if (!name)
+ name = "simple";
+
ops = ieee80211_try_rate_control_ops_get(name);
if (!ops) {
- request_module("rc80211_%s", name ? name : "default");
+ request_module("rc80211_%s", name);
ops = ieee80211_try_rate_control_ops_get(name);
}
return ops;
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
index 7cd1eba..2368813 100644
--- a/net/mac80211/ieee80211_rate.h
+++ b/net/mac80211/ieee80211_rate.h
@@ -65,6 +65,9 @@
struct kref kref;
};
+/* default 'simple' algorithm */
+extern struct rate_control_ops mac80211_rcsimple;
+
int ieee80211_rate_control_register(struct rate_control_ops *ops);
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index fda0e06..2079e98 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -704,10 +704,11 @@
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *bss;
- int res = 0;
+ int bss_privacy;
+ int wep_privacy;
+ int privacy_invoked;
- if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL) ||
- ifsta->key_management_enabled)
+ if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
return 0;
bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
@@ -715,13 +716,16 @@
if (!bss)
return 0;
- if (ieee80211_sta_wep_configured(dev) !=
- !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
- res = 1;
+ bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
+ wep_privacy = !!ieee80211_sta_wep_configured(dev);
+ privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
ieee80211_rx_bss_put(dev, bss);
- return res;
+ if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
+ return 0;
+
+ return 1;
}
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 314b8de..da72737 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -7,7 +7,6 @@
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/types.h>
@@ -29,8 +28,6 @@
#define RATE_CONTROL_INTERVAL (HZ / 20)
#define RATE_CONTROL_MIN_TX 10
-MODULE_ALIAS("rc80211_default");
-
static void rate_control_rate_inc(struct ieee80211_local *local,
struct sta_info *sta)
{
@@ -394,8 +391,7 @@
}
#endif
-static struct rate_control_ops rate_control_simple = {
- .module = THIS_MODULE,
+struct rate_control_ops mac80211_rcsimple = {
.name = "simple",
.tx_status = rate_control_simple_tx_status,
.get_rate = rate_control_simple_get_rate,
@@ -410,22 +406,3 @@
.remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
#endif
};
-
-
-static int __init rate_control_simple_init(void)
-{
- return ieee80211_rate_control_register(&rate_control_simple);
-}
-
-
-static void __exit rate_control_simple_exit(void)
-{
- ieee80211_rate_control_unregister(&rate_control_simple);
-}
-
-
-subsys_initcall(rate_control_simple_init);
-module_exit(rate_control_simple_exit);
-
-MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
-MODULE_LICENSE("GPL");
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ece7776..428a9fc 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -509,9 +509,11 @@
rx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
} else {
+#ifdef CONFIG_MAC80211_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: RX protected frame,"
" but have no key\n", rx->dev->name);
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index a84a233..9bf0e1c 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -314,9 +314,11 @@
if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
+#ifdef CONFIG_MAC80211_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
"failed\n", rx->dev->name);
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
} else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 6695efb..20cec1c 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -323,9 +323,12 @@
&rx->u.rx.tkip_iv32,
&rx->u.rx.tkip_iv16);
if (res != TKIP_DECRYPT_OK || wpa_test) {
- printk(KERN_DEBUG "%s: TKIP decrypt failed for RX frame from "
- "%s (res=%d)\n",
- rx->dev->name, print_mac(mac, rx->sta->addr), res);
+#ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: TKIP decrypt failed for RX "
+ "frame from %s (res=%d)\n", rx->dev->name,
+ print_mac(mac, rx->sta->addr), res);
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
@@ -594,9 +597,12 @@
skb->data + hdrlen + CCMP_HDR_LEN, data_len,
skb->data + skb->len - CCMP_MIC_LEN,
skb->data + hdrlen + CCMP_HDR_LEN)) {
- printk(KERN_DEBUG "%s: CCMP decrypt failed for RX "
- "frame from %s\n", rx->dev->name,
- print_mac(mac, rx->sta->addr));
+#ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: CCMP decrypt failed "
+ "for RX frame from %s\n", rx->dev->name,
+ print_mac(mac, rx->sta->addr));
+#endif /* CONFIG_MAC80211_DEBUG */
return TXRX_DROP;
}
}
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index 2dfac32..87bc144 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -60,6 +60,41 @@
}
EXPORT_SYMBOL(nf_unregister_sockopt);
+static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf,
+ int val, int get)
+{
+ struct nf_sockopt_ops *ops;
+
+ if (sk->sk_net != &init_net)
+ return ERR_PTR(-ENOPROTOOPT);
+
+ if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
+ return ERR_PTR(-EINTR);
+
+ list_for_each_entry(ops, &nf_sockopts, list) {
+ if (ops->pf == pf) {
+ if (!try_module_get(ops->owner))
+ goto out_nosup;
+
+ if (get) {
+ if (val >= ops->get_optmin &&
+ val < ops->get_optmax)
+ goto out;
+ } else {
+ if (val >= ops->set_optmin &&
+ val < ops->set_optmax)
+ goto out;
+ }
+ module_put(ops->owner);
+ }
+ }
+out_nosup:
+ ops = ERR_PTR(-ENOPROTOOPT);
+out:
+ mutex_unlock(&nf_sockopt_mutex);
+ return ops;
+}
+
/* Call get/setsockopt() */
static int nf_sockopt(struct sock *sk, int pf, int val,
char __user *opt, int *len, int get)
@@ -67,39 +102,15 @@
struct nf_sockopt_ops *ops;
int ret;
- if (sk->sk_net != &init_net)
- return -ENOPROTOOPT;
+ ops = nf_sockopt_find(sk, pf, val, get);
+ if (IS_ERR(ops))
+ return PTR_ERR(ops);
- if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
- return -EINTR;
+ if (get)
+ ret = ops->get(sk, val, opt, len);
+ else
+ ret = ops->set(sk, val, opt, *len);
- list_for_each_entry(ops, &nf_sockopts, list) {
- if (ops->pf == pf) {
- if (!try_module_get(ops->owner))
- goto out_nosup;
- if (get) {
- if (val >= ops->get_optmin
- && val < ops->get_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- ret = ops->get(sk, val, opt, len);
- goto out;
- }
- } else {
- if (val >= ops->set_optmin
- && val < ops->set_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- ret = ops->set(sk, val, opt, *len);
- goto out;
- }
- }
- module_put(ops->owner);
- }
- }
- out_nosup:
- mutex_unlock(&nf_sockopt_mutex);
- return -ENOPROTOOPT;
-
- out:
module_put(ops->owner);
return ret;
}
@@ -124,51 +135,22 @@
struct nf_sockopt_ops *ops;
int ret;
- if (sk->sk_net != &init_net)
- return -ENOPROTOOPT;
+ ops = nf_sockopt_find(sk, pf, val, get);
+ if (IS_ERR(ops))
+ return PTR_ERR(ops);
-
- if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
- return -EINTR;
-
- list_for_each_entry(ops, &nf_sockopts, list) {
- if (ops->pf == pf) {
- if (!try_module_get(ops->owner))
- goto out_nosup;
-
- if (get) {
- if (val >= ops->get_optmin
- && val < ops->get_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- if (ops->compat_get)
- ret = ops->compat_get(sk,
- val, opt, len);
- else
- ret = ops->get(sk,
- val, opt, len);
- goto out;
- }
- } else {
- if (val >= ops->set_optmin
- && val < ops->set_optmax) {
- mutex_unlock(&nf_sockopt_mutex);
- if (ops->compat_set)
- ret = ops->compat_set(sk,
- val, opt, *len);
- else
- ret = ops->set(sk,
- val, opt, *len);
- goto out;
- }
- }
- module_put(ops->owner);
- }
+ if (get) {
+ if (ops->compat_get)
+ ret = ops->compat_get(sk, val, opt, len);
+ else
+ ret = ops->get(sk, val, ops, len);
+ } else {
+ if (ops->compat_set)
+ ret = ops->compat_set(sk, val, ops, *len);
+ else
+ ret = ops->set(sk, val, ops, *len);
}
- out_nosup:
- mutex_unlock(&nf_sockopt_mutex);
- return -ENOPROTOOPT;
- out:
module_put(ops->owner);
return ret;
}
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index ff44f86..f9c55dc 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -170,7 +170,7 @@
if (skb->tstamp.tv64 == 0)
__net_timestamp((struct sk_buff *)skb);
- stamp = skb->tstamp.tv64;
+ stamp = ktime_to_ns(skb->tstamp);
do_div(stamp, NSEC_PER_SEC);
if (info->flags & XT_TIME_LOCAL_TZ)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 415c972..de3988b 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1888,7 +1888,7 @@
#endif
}
-static struct pernet_operations netlink_net_ops = {
+static struct pernet_operations __net_initdata netlink_net_ops = {
.init = netlink_net_init,
.exit = netlink_net_exit,
};
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 4cb2dfb..8a7807d 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -139,9 +139,6 @@
static HLIST_HEAD(packet_sklist);
static DEFINE_RWLOCK(packet_sklist_lock);
-static atomic_t packet_socks_nr;
-
-
/* Private packet socket structures. */
struct packet_mclist
@@ -236,10 +233,7 @@
return;
}
- atomic_dec(&packet_socks_nr);
-#ifdef PACKET_REFCNT_DEBUG
- printk(KERN_DEBUG "PACKET socket %p is free, %d are alive\n", sk, atomic_read(&packet_socks_nr));
-#endif
+ sk_refcnt_debug_dec(sk);
}
@@ -515,7 +509,7 @@
sll->sll_hatype = dev->type;
sll->sll_protocol = skb->protocol;
sll->sll_pkttype = skb->pkt_type;
- if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST)
+ if (unlikely(po->origdev))
sll->sll_ifindex = orig_dev->ifindex;
else
sll->sll_ifindex = dev->ifindex;
@@ -661,7 +655,7 @@
sll->sll_hatype = dev->type;
sll->sll_protocol = skb->protocol;
sll->sll_pkttype = skb->pkt_type;
- if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST)
+ if (unlikely(po->origdev))
sll->sll_ifindex = orig_dev->ifindex;
else
sll->sll_ifindex = dev->ifindex;
@@ -849,6 +843,7 @@
/* Purge queues */
skb_queue_purge(&sk->sk_receive_queue);
+ sk_refcnt_debug_release(sk);
sock_put(sk);
return 0;
@@ -886,20 +881,14 @@
if (protocol == 0)
goto out_unlock;
- if (dev) {
- if (dev->flags&IFF_UP) {
- dev_add_pack(&po->prot_hook);
- sock_hold(sk);
- po->running = 1;
- } else {
- sk->sk_err = ENETDOWN;
- if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_error_report(sk);
- }
- } else {
+ if (!dev || (dev->flags & IFF_UP)) {
dev_add_pack(&po->prot_hook);
sock_hold(sk);
po->running = 1;
+ } else {
+ sk->sk_err = ENETDOWN;
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_error_report(sk);
}
out_unlock:
@@ -1010,7 +999,7 @@
po->num = proto;
sk->sk_destruct = packet_sock_destruct;
- atomic_inc(&packet_socks_nr);
+ sk_refcnt_debug_inc(sk);
/*
* Attach a protocol block
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
index 51d151c..73d60a3 100644
--- a/net/rfkill/rfkill.c
+++ b/net/rfkill/rfkill.c
@@ -27,6 +27,10 @@
#include <linux/mutex.h>
#include <linux/rfkill.h>
+/* Get declaration of rfkill_switch_all() to shut up sparse. */
+#include "rfkill-input.h"
+
+
MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("RF switch support");
@@ -276,21 +280,17 @@
static int rfkill_add_switch(struct rfkill *rfkill)
{
- int retval;
+ int error;
- retval = mutex_lock_interruptible(&rfkill_mutex);
- if (retval)
- return retval;
+ mutex_lock(&rfkill_mutex);
- retval = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]);
- if (retval)
- goto out;
+ error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]);
+ if (!error)
+ list_add_tail(&rfkill->node, &rfkill_list);
- list_add_tail(&rfkill->node, &rfkill_list);
-
- out:
mutex_unlock(&rfkill_mutex);
- return retval;
+
+ return error;
}
static void rfkill_remove_switch(struct rfkill *rfkill)
@@ -387,20 +387,23 @@
if (!rfkill->toggle_radio)
return -EINVAL;
+ if (rfkill->type >= RFKILL_TYPE_MAX)
+ return -EINVAL;
+
+ snprintf(dev->bus_id, sizeof(dev->bus_id),
+ "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1);
+
+ rfkill_led_trigger_register(rfkill);
error = rfkill_add_switch(rfkill);
if (error)
return error;
- snprintf(dev->bus_id, sizeof(dev->bus_id),
- "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1);
-
error = device_add(dev);
if (error) {
rfkill_remove_switch(rfkill);
return error;
}
- rfkill_led_trigger_register(rfkill);
return 0;
}
@@ -416,9 +419,9 @@
*/
void rfkill_unregister(struct rfkill *rfkill)
{
- rfkill_led_trigger_unregister(rfkill);
device_del(&rfkill->dev);
rfkill_remove_switch(rfkill);
+ rfkill_led_trigger_unregister(rfkill);
put_device(&rfkill->dev);
}
EXPORT_SYMBOL(rfkill_unregister);
@@ -448,5 +451,5 @@
class_unregister(&rfkill_class);
}
-module_init(rfkill_init);
+subsys_initcall(rfkill_init);
module_exit(rfkill_exit);
diff --git a/net/rxrpc/ar-local.c b/net/rxrpc/ar-local.c
index fe03f71..f3a2bd7 100644
--- a/net/rxrpc/ar-local.c
+++ b/net/rxrpc/ar-local.c
@@ -114,7 +114,7 @@
return 0;
error:
- local->socket->ops->shutdown(local->socket, 2);
+ kernel_sock_shutdown(local->socket, SHUT_RDWR);
local->socket->sk->sk_user_data = NULL;
sock_release(local->socket);
local->socket = NULL;
@@ -267,7 +267,7 @@
/* finish cleaning up the local descriptor */
rxrpc_purge_queue(&local->accept_queue);
rxrpc_purge_queue(&local->reject_queue);
- local->socket->ops->shutdown(local->socket, 2);
+ kernel_sock_shutdown(local->socket, SHUT_RDWR);
sock_release(local->socket);
up_read(&rxrpc_local_sem);
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 5317102..c390082 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -613,17 +613,7 @@
memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
n->ht_up = ht;
n->handle = handle;
-{
- u8 i = 0;
- u32 mask = ntohl(s->hmask);
- if (mask) {
- while (!(mask & 1)) {
- i++;
- mask>>=1;
- }
- }
- n->fshift = i;
-}
+ n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
#ifdef CONFIG_CLS_U32_MARK
if (tb[TCA_U32_MARK-1]) {
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index fa1a6f4..e595e65 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -134,7 +134,7 @@
{
struct Qdisc *q = dev->qdisc;
struct sk_buff *skb;
- int ret;
+ int ret = NETDEV_TX_BUSY;
/* Dequeue packet */
if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
@@ -145,7 +145,8 @@
spin_unlock(&dev->queue_lock);
HARD_TX_LOCK(dev, smp_processor_id());
- ret = dev_hard_start_xmit(skb, dev);
+ if (!netif_subqueue_stopped(dev, skb))
+ ret = dev_hard_start_xmit(skb, dev);
HARD_TX_UNLOCK(dev);
spin_lock(&dev->queue_lock);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 03158e36..013e3d3 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -262,10 +262,14 @@
*/
asoc->peer.sack_needed = 1;
- /* Assume that the peer recongizes ASCONF until reported otherwise
- * via an ERROR chunk.
+ /* Assume that the peer will tell us if he recognizes ASCONF
+ * as part of INIT exchange.
+ * The sctp_addip_noauth option is there for backward compatibilty
+ * and will revert old behavior.
*/
- asoc->peer.asconf_capable = 1;
+ asoc->peer.asconf_capable = 0;
+ if (sctp_addip_noauth)
+ asoc->peer.asconf_capable = 1;
/* Create an input queue. */
sctp_inq_init(&asoc->base.inqueue);
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index dfffa94..cae95af 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -180,9 +180,7 @@
/* Delete an address from the bind address list in the SCTP_bind_addr
* structure.
*/
-int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
- void fastcall (*rcu_call)(struct rcu_head *head,
- void (*func)(struct rcu_head *head)))
+int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
{
struct sctp_sockaddr_entry *addr, *temp;
@@ -198,15 +196,10 @@
}
}
- /* Call the rcu callback provided in the args. This function is
- * called by both BH packet processing and user side socket option
- * processing, but it works on different lists in those 2 contexts.
- * Each context provides it's own callback, whether call_rcu_bh()
- * or call_rcu(), to make sure that we wait for an appropriate time.
- */
if (addr && !addr->valid) {
- rcu_call(&addr->rcu, sctp_local_addr_free);
+ call_rcu(&addr->rcu, sctp_local_addr_free);
SCTP_DBG_OBJCNT_DEC(addr);
+ return 0;
}
return -EINVAL;
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 2d2d81e..de6f505 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -328,24 +328,35 @@
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
+ struct sctp_association *asoc = NULL;
+ struct sctp_transport *t = NULL;
+ struct sctp_hashbucket *head;
+ struct sctp_ep_common *epb;
+ struct hlist_node *node;
+ int hash;
int rport;
- struct sctp_association *asoc;
- struct list_head *pos;
-
- rport = ntohs(paddr->v4.sin_port);
-
- list_for_each(pos, &ep->asocs) {
- asoc = list_entry(pos, struct sctp_association, asocs);
- if (rport == asoc->peer.port) {
- *transport = sctp_assoc_lookup_paddr(asoc, paddr);
-
- if (*transport)
- return asoc;
- }
- }
*transport = NULL;
- return NULL;
+ rport = ntohs(paddr->v4.sin_port);
+
+ hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
+ head = &sctp_assoc_hashtable[hash];
+ read_lock(&head->lock);
+ sctp_for_each_hentry(epb, node, &head->chain) {
+ asoc = sctp_assoc(epb);
+ if (asoc->ep != ep || rport != asoc->peer.port)
+ goto next;
+
+ t = sctp_assoc_lookup_paddr(asoc, paddr);
+ if (t) {
+ *transport = t;
+ break;
+ }
+next:
+ asoc = NULL;
+ }
+ read_unlock(&head->lock);
+ return asoc;
}
/* Lookup association on an endpoint based on a peer address. BH-safe. */
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 86503e7..91ae463 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -656,7 +656,6 @@
/* Insert endpoint into the hash table. */
static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
- struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
@@ -666,12 +665,7 @@
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- epp = &head->chain;
- epb->next = *epp;
- if (epb->next)
- (*epp)->pprev = &epb->next;
- *epp = epb;
- epb->pprev = epp;
+ hlist_add_head(&epb->node, &head->chain);
sctp_write_unlock(&head->lock);
}
@@ -691,19 +685,15 @@
epb = &ep->base;
+ if (hlist_unhashed(&epb->node))
+ return;
+
epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
-
- if (epb->pprev) {
- if (epb->next)
- epb->next->pprev = epb->pprev;
- *epb->pprev = epb->next;
- epb->pprev = NULL;
- }
-
+ __hlist_del(&epb->node);
sctp_write_unlock(&head->lock);
}
@@ -721,12 +711,13 @@
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
+ struct hlist_node *node;
int hash;
hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
head = &sctp_ep_hashtable[hash];
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
if (sctp_endpoint_is_match(ep, laddr))
goto hit;
@@ -744,7 +735,6 @@
/* Insert association into the hash table. */
static void __sctp_hash_established(struct sctp_association *asoc)
{
- struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
struct sctp_hashbucket *head;
@@ -756,12 +746,7 @@
head = &sctp_assoc_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- epp = &head->chain;
- epb->next = *epp;
- if (epb->next)
- (*epp)->pprev = &epb->next;
- *epp = epb;
- epb->pprev = epp;
+ hlist_add_head(&epb->node, &head->chain);
sctp_write_unlock(&head->lock);
}
@@ -790,14 +775,7 @@
head = &sctp_assoc_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
-
- if (epb->pprev) {
- if (epb->next)
- epb->next->pprev = epb->pprev;
- *epb->pprev = epb->next;
- epb->pprev = NULL;
- }
-
+ __hlist_del(&epb->node);
sctp_write_unlock(&head->lock);
}
@@ -822,6 +800,7 @@
struct sctp_ep_common *epb;
struct sctp_association *asoc;
struct sctp_transport *transport;
+ struct hlist_node *node;
int hash;
/* Optimize here for direct hit, only listening connections can
@@ -830,7 +809,7 @@
hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
head = &sctp_assoc_hashtable[hash];
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
asoc = sctp_assoc(epb);
transport = sctp_assoc_is_match(asoc, local, peer);
if (transport)
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index f10fe7f..cf4b7eb 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -90,6 +90,10 @@
void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
{
/* Directly call the packet handling routine. */
+ if (chunk->rcvr->dead) {
+ sctp_chunk_free(chunk);
+ return;
+ }
/* We are now calling this either from the soft interrupt
* or from the backlog processing.
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 28f4fe7..fa76f23 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -382,7 +382,7 @@
/* Mark all the eligible packets on a transport for retransmission. */
void sctp_retransmit_mark(struct sctp_outq *q,
struct sctp_transport *transport,
- __u8 fast_retransmit)
+ __u8 reason)
{
struct list_head *lchunk, *ltemp;
struct sctp_chunk *chunk;
@@ -412,20 +412,20 @@
continue;
}
- /* If we are doing retransmission due to a fast retransmit,
- * only the chunk's that are marked for fast retransmit
- * should be added to the retransmit queue. If we are doing
- * retransmission due to a timeout or pmtu discovery, only the
- * chunks that are not yet acked should be added to the
- * retransmit queue.
+ /* If we are doing retransmission due to a timeout or pmtu
+ * discovery, only the chunks that are not yet acked should
+ * be added to the retransmit queue.
*/
- if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||
- (!fast_retransmit && !chunk->tsn_gap_acked)) {
+ if ((reason == SCTP_RTXR_FAST_RTX &&
+ (chunk->fast_retransmit > 0)) ||
+ (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) {
/* If this chunk was sent less then 1 rto ago, do not
* retransmit this chunk, but give the peer time
- * to acknowlege it.
+ * to acknowlege it. Do this only when
+ * retransmitting due to T3 timeout.
*/
- if ((jiffies - chunk->sent_at) < transport->rto)
+ if (reason == SCTP_RTXR_T3_RTX &&
+ (jiffies - chunk->sent_at) < transport->last_rto)
continue;
/* RFC 2960 6.2.1 Processing a Received SACK
@@ -467,10 +467,10 @@
}
}
- SCTP_DEBUG_PRINTK("%s: transport: %p, fast_retransmit: %d, "
+ SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, "
"cwnd: %d, ssthresh: %d, flight_size: %d, "
"pba: %d\n", __FUNCTION__,
- transport, fast_retransmit,
+ transport, reason,
transport->cwnd, transport->ssthresh,
transport->flight_size,
transport->partial_bytes_acked);
@@ -484,7 +484,6 @@
sctp_retransmit_reason_t reason)
{
int error = 0;
- __u8 fast_retransmit = 0;
switch(reason) {
case SCTP_RTXR_T3_RTX:
@@ -499,16 +498,18 @@
case SCTP_RTXR_FAST_RTX:
SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
- fast_retransmit = 1;
break;
case SCTP_RTXR_PMTUD:
SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
break;
+ case SCTP_RTXR_T1_RTX:
+ SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
+ break;
default:
BUG();
}
- sctp_retransmit_mark(q, transport, fast_retransmit);
+ sctp_retransmit_mark(q, transport, reason);
/* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination,
* the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by
@@ -641,7 +642,8 @@
/* If we are here due to a retransmit timeout or a fast
* retransmit and if there are any chunks left in the retransmit
- * queue that could not fit in the PMTU sized packet, they need * to be marked as ineligible for a subsequent fast retransmit.
+ * queue that could not fit in the PMTU sized packet, they need
+ * to be marked as ineligible for a subsequent fast retransmit.
*/
if (rtx_timeout && !lchunk) {
list_for_each(lchunk1, lqueue) {
@@ -660,10 +662,9 @@
int sctp_outq_uncork(struct sctp_outq *q)
{
int error = 0;
- if (q->cork) {
+ if (q->cork)
q->cork = 0;
- error = sctp_outq_flush(q, 0);
- }
+ error = sctp_outq_flush(q, 0);
return error;
}
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index e4cd841..2499732 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -225,6 +225,7 @@
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
struct sock *sk;
+ struct hlist_node *node;
int hash = *(loff_t *)v;
if (hash >= sctp_ep_hashsize)
@@ -233,7 +234,7 @@
head = &sctp_ep_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
ep = sctp_ep(epb);
sk = epb->sk;
seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
@@ -328,6 +329,7 @@
struct sctp_ep_common *epb;
struct sctp_association *assoc;
struct sock *sk;
+ struct hlist_node *node;
int hash = *(loff_t *)v;
if (hash >= sctp_assoc_hashsize)
@@ -336,7 +338,7 @@
head = &sctp_assoc_hashtable[hash];
sctp_local_bh_disable();
read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
+ sctp_for_each_hentry(epb, node, &head->chain) {
assoc = sctp_assoc(epb);
sk = epb->sk;
seq_printf(seq,
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 40c1a47..d50f610 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1137,7 +1137,7 @@
}
for (i = 0; i < sctp_assoc_hashsize; i++) {
rwlock_init(&sctp_assoc_hashtable[i].lock);
- sctp_assoc_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain);
}
/* Allocate and initialize the endpoint hash table. */
@@ -1151,7 +1151,7 @@
}
for (i = 0; i < sctp_ep_hashsize; i++) {
rwlock_init(&sctp_ep_hashtable[i].lock);
- sctp_ep_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
}
/* Allocate and initialize the SCTP port hash table. */
@@ -1170,7 +1170,7 @@
}
for (i = 0; i < sctp_port_hashsize; i++) {
spin_lock_init(&sctp_port_hashtable[i].lock);
- sctp_port_hashtable[i].chain = NULL;
+ INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
}
printk(KERN_INFO "SCTP: Hash tables configured "
@@ -1179,6 +1179,7 @@
/* Disable ADDIP by default. */
sctp_addip_enable = 0;
+ sctp_addip_noauth = 0;
/* Enable PR-SCTP by default. */
sctp_prsctp_enable = 1;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index c377e4e..5a9783c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1788,9 +1788,14 @@
sizeof(sctp_paramhdr_t);
+ /* This is a fatal error. Any accumulated non-fatal errors are
+ * not reported.
+ */
+ if (*errp)
+ sctp_chunk_free(*errp);
+
/* Create an error chunk and fill it in with our payload. */
- if (!*errp)
- *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
+ *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
@@ -1813,9 +1818,15 @@
{
__u16 len = ntohs(param.p->length);
- /* Make an ERROR chunk. */
- if (!*errp)
- *errp = sctp_make_op_error_space(asoc, chunk, len);
+ /* Processing of the HOST_NAME parameter will generate an
+ * ABORT. If we've accumulated any non-fatal errors, they
+ * would be unrecognized parameters and we should not include
+ * them in the ABORT.
+ */
+ if (*errp)
+ sctp_chunk_free(*errp);
+
+ *errp = sctp_make_op_error_space(asoc, chunk, len);
if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
@@ -1847,7 +1858,7 @@
break;
case SCTP_CID_ASCONF:
case SCTP_CID_ASCONF_ACK:
- asoc->peer.addip_capable = 1;
+ asoc->peer.asconf_capable = 1;
break;
default:
break;
@@ -1862,56 +1873,40 @@
* taken if the processing endpoint does not recognize the
* Parameter Type.
*
- * 00 - Stop processing this SCTP chunk and discard it,
- * do not process any further chunks within it.
+ * 00 - Stop processing this parameter; do not process any further
+ * parameters within this chunk
*
- * 01 - Stop processing this SCTP chunk and discard it,
- * do not process any further chunks within it, and report
- * the unrecognized parameter in an 'Unrecognized
- * Parameter Type' (in either an ERROR or in the INIT ACK).
+ * 01 - Stop processing this parameter, do not process any further
+ * parameters within this chunk, and report the unrecognized
+ * parameter in an 'Unrecognized Parameter' ERROR chunk.
*
* 10 - Skip this parameter and continue processing.
*
* 11 - Skip this parameter and continue processing but
* report the unrecognized parameter in an
- * 'Unrecognized Parameter Type' (in either an ERROR or in
- * the INIT ACK).
+ * 'Unrecognized Parameter' ERROR chunk.
*
* Return value:
- * 0 - discard the chunk
- * 1 - continue with the chunk
+ * SCTP_IERROR_NO_ERROR - continue with the chunk
+ * SCTP_IERROR_ERROR - stop and report an error.
+ * SCTP_IERROR_NOMEME - out of memory.
*/
-static int sctp_process_unk_param(const struct sctp_association *asoc,
- union sctp_params param,
- struct sctp_chunk *chunk,
- struct sctp_chunk **errp)
+static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
+ union sctp_params param,
+ struct sctp_chunk *chunk,
+ struct sctp_chunk **errp)
{
- int retval = 1;
+ int retval = SCTP_IERROR_NO_ERROR;
switch (param.p->type & SCTP_PARAM_ACTION_MASK) {
case SCTP_PARAM_ACTION_DISCARD:
- retval = 0;
- break;
- case SCTP_PARAM_ACTION_DISCARD_ERR:
- retval = 0;
- /* Make an ERROR chunk, preparing enough room for
- * returning multiple unknown parameters.
- */
- if (NULL == *errp)
- *errp = sctp_make_op_error_space(asoc, chunk,
- ntohs(chunk->chunk_hdr->length));
-
- if (*errp) {
- sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
- WORD_ROUND(ntohs(param.p->length)));
- sctp_addto_chunk(*errp,
- WORD_ROUND(ntohs(param.p->length)),
- param.v);
- }
-
+ retval = SCTP_IERROR_ERROR;
break;
case SCTP_PARAM_ACTION_SKIP:
break;
+ case SCTP_PARAM_ACTION_DISCARD_ERR:
+ retval = SCTP_IERROR_ERROR;
+ /* Fall through */
case SCTP_PARAM_ACTION_SKIP_ERR:
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
@@ -1932,9 +1927,8 @@
* to the peer and the association won't be
* established.
*/
- retval = 0;
+ retval = SCTP_IERROR_NOMEM;
}
-
break;
default:
break;
@@ -1943,18 +1937,20 @@
return retval;
}
-/* Find unrecognized parameters in the chunk.
+/* Verify variable length parameters
* Return values:
- * 0 - discard the chunk
- * 1 - continue with the chunk
+ * SCTP_IERROR_ABORT - trigger an ABORT
+ * SCTP_IERROR_NOMEM - out of memory (abort)
+ * SCTP_IERROR_ERROR - stop processing, trigger an ERROR
+ * SCTP_IERROR_NO_ERROR - continue with the chunk
*/
-static int sctp_verify_param(const struct sctp_association *asoc,
- union sctp_params param,
- sctp_cid_t cid,
- struct sctp_chunk *chunk,
- struct sctp_chunk **err_chunk)
+static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
+ union sctp_params param,
+ sctp_cid_t cid,
+ struct sctp_chunk *chunk,
+ struct sctp_chunk **err_chunk)
{
- int retval = 1;
+ int retval = SCTP_IERROR_NO_ERROR;
/* FIXME - This routine is not looking at each parameter per the
* chunk type, i.e., unrecognized parameters should be further
@@ -1976,7 +1972,9 @@
case SCTP_PARAM_HOST_NAME_ADDRESS:
/* Tell the peer, we won't support this param. */
- return sctp_process_hn_param(asoc, param, chunk, err_chunk);
+ sctp_process_hn_param(asoc, param, chunk, err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ break;
case SCTP_PARAM_FWD_TSN_SUPPORT:
if (sctp_prsctp_enable)
@@ -1993,9 +1991,11 @@
* cause 'Protocol Violation'.
*/
if (SCTP_AUTH_RANDOM_LENGTH !=
- ntohs(param.p->length) - sizeof(sctp_paramhdr_t))
- return sctp_process_inv_paramlength(asoc, param.p,
+ ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) {
+ sctp_process_inv_paramlength(asoc, param.p,
chunk, err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ }
break;
case SCTP_PARAM_CHUNKS:
@@ -2007,9 +2007,11 @@
* INIT-ACK chunk if the sender wants to receive authenticated
* chunks. Its maximum length is 260 bytes.
*/
- if (260 < ntohs(param.p->length))
- return sctp_process_inv_paramlength(asoc, param.p,
- chunk, err_chunk);
+ if (260 < ntohs(param.p->length)) {
+ sctp_process_inv_paramlength(asoc, param.p,
+ chunk, err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ }
break;
case SCTP_PARAM_HMAC_ALGO:
@@ -2020,8 +2022,7 @@
default:
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
ntohs(param.p->type), cid);
- return sctp_process_unk_param(asoc, param, chunk, err_chunk);
-
+ retval = sctp_process_unk_param(asoc, param, chunk, err_chunk);
break;
}
return retval;
@@ -2036,6 +2037,7 @@
{
union sctp_params param;
int has_cookie = 0;
+ int result;
/* Verify stream values are non-zero. */
if ((0 == peer_init->init_hdr.num_outbound_streams) ||
@@ -2043,8 +2045,7 @@
(0 == peer_init->init_hdr.init_tag) ||
(SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {
- sctp_process_inv_mandatory(asoc, chunk, errp);
- return 0;
+ return sctp_process_inv_mandatory(asoc, chunk, errp);
}
/* Check for missing mandatory parameters. */
@@ -2062,29 +2063,29 @@
* VIOLATION error. We build the ERROR chunk here and let the normal
* error handling code build and send the packet.
*/
- if (param.v != (void*)chunk->chunk_end) {
- sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
- return 0;
- }
+ if (param.v != (void*)chunk->chunk_end)
+ return sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
/* The only missing mandatory param possible today is
* the state cookie for an INIT-ACK chunk.
*/
- if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) {
- sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
- chunk, errp);
- return 0;
- }
+ if ((SCTP_CID_INIT_ACK == cid) && !has_cookie)
+ return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
+ chunk, errp);
- /* Find unrecognized parameters. */
-
+ /* Verify all the variable length parameters */
sctp_walk_params(param, peer_init, init_hdr.params) {
- if (!sctp_verify_param(asoc, param, cid, chunk, errp)) {
- if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type)
+ result = sctp_verify_param(asoc, param, cid, chunk, errp);
+ switch (result) {
+ case SCTP_IERROR_ABORT:
+ case SCTP_IERROR_NOMEM:
return 0;
- else
+ case SCTP_IERROR_ERROR:
return 1;
+ case SCTP_IERROR_NO_ERROR:
+ default:
+ break;
}
} /* for (loop through all parameters) */
@@ -2137,11 +2138,14 @@
/* If the peer claims support for ADD-IP without support
* for AUTH, disable support for ADD-IP.
+ * Do this only if backward compatible mode is turned off.
*/
- if (asoc->peer.addip_capable && !asoc->peer.auth_capable) {
+ if (!sctp_addip_noauth &&
+ (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) {
asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP |
SCTP_PARAM_DEL_IP |
SCTP_PARAM_SET_PRIMARY);
+ asoc->peer.asconf_capable = 0;
}
/* Walk list of transports, removing transports in the UNKNOWN state. */
@@ -2848,10 +2852,11 @@
__be16 err_code;
int length = 0;
- int chunk_len = asconf->skb->len;
+ int chunk_len;
__u32 serial;
int all_param_pass = 1;
+ chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
hdr = (sctp_addiphdr_t *)asconf->skb->data;
serial = ntohl(hdr->serial);
@@ -2952,13 +2957,17 @@
/* This is always done in BH context with a socket lock
* held, so the list can not change.
*/
+ local_bh_disable();
list_for_each_entry(saddr, &bp->address_list, list) {
if (sctp_cmp_addr_exact(&saddr->a, &addr))
saddr->use_as_src = 1;
}
+ local_bh_enable();
break;
case SCTP_PARAM_DEL_IP:
- retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh);
+ local_bh_disable();
+ retval = sctp_del_bind_addr(bp, &addr);
+ local_bh_enable();
list_for_each(pos, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport,
transports);
@@ -2990,7 +2999,7 @@
sctp_addip_param_t *asconf_ack_param;
sctp_errhdr_t *err_param;
int length;
- int asconf_ack_len = asconf_ack->skb->len;
+ int asconf_ack_len;
__be16 err_code;
if (no_err)
@@ -2998,6 +3007,9 @@
else
err_code = SCTP_ERROR_REQ_REFUSED;
+ asconf_ack_len = ntohs(asconf_ack->chunk_hdr->length) -
+ sizeof(sctp_chunkhdr_t);
+
/* Skip the addiphdr from the asconf_ack chunk and store a pointer to
* the first asconf_ack parameter.
*/
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index bbdc938..78d1a8a 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -453,6 +453,7 @@
* maximum value discussed in rule C7 above (RTO.max) may be
* used to provide an upper bound to this doubling operation.
*/
+ transport->last_rto = transport->rto;
transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
}
@@ -1267,6 +1268,12 @@
sctp_ootb_pkt_free(packet);
break;
+ case SCTP_CMD_T1_RETRAN:
+ /* Mark a transport for retransmission. */
+ sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
+ SCTP_RTXR_T1_RTX);
+ break;
+
case SCTP_CMD_RETRAN:
/* Mark a transport for retransmission. */
sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
@@ -1393,7 +1400,8 @@
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport,
transports);
- sctp_retransmit_mark(&asoc->outqueue, t, 0);
+ sctp_retransmit_mark(&asoc->outqueue, t,
+ SCTP_RTXR_T1_RTX);
}
sctp_add_cmd_sf(commands,
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f01b408..5ebbe80 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2305,7 +2305,7 @@
/* If we've sent any data bundled with COOKIE-ECHO we will need to
* resend
*/
- sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN,
+ sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
SCTP_TRANSPORT(asoc->peer.primary_path));
/* Cast away the const modifier, as we want to just
@@ -4064,11 +4064,6 @@
struct sctp_chunk *chunk = arg;
struct sctp_chunk *abort = NULL;
- /* Make the abort chunk. */
- abort = sctp_make_abort_violation(asoc, chunk, payload, paylen);
- if (!abort)
- goto nomem;
-
/* SCTP-AUTH, Section 6.3:
* It should be noted that if the receiver wants to tear
* down an association in an authenticated way only, the
@@ -4083,6 +4078,11 @@
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
goto discard;
+ /* Make the abort chunk. */
+ abort = sctp_make_abort_violation(asoc, chunk, payload, paylen);
+ if (!abort)
+ goto nomem;
+
if (asoc) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index a7ecf31..ff8bc95 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -660,7 +660,7 @@
* socket routing and failover schemes. Refer to comments in
* sctp_do_bind(). -daisy
*/
- retval = sctp_del_bind_addr(bp, sa_addr, call_rcu);
+ retval = sctp_del_bind_addr(bp, sa_addr);
addr_buf += af->sockaddr_len;
err_bindx_rem:
@@ -5307,6 +5307,7 @@
{
struct sctp_bind_hashbucket *head; /* hash list */
struct sctp_bind_bucket *pp; /* hash list port iterator */
+ struct hlist_node *node;
unsigned short snum;
int ret;
@@ -5331,7 +5332,7 @@
index = sctp_phashfn(rover);
head = &sctp_port_hashtable[index];
sctp_spin_lock(&head->lock);
- for (pp = head->chain; pp; pp = pp->next)
+ sctp_for_each_hentry(pp, node, &head->chain)
if (pp->port == rover)
goto next;
break;
@@ -5358,7 +5359,7 @@
*/
head = &sctp_port_hashtable[sctp_phashfn(snum)];
sctp_spin_lock(&head->lock);
- for (pp = head->chain; pp; pp = pp->next) {
+ sctp_for_each_hentry(pp, node, &head->chain) {
if (pp->port == snum)
goto pp_found;
}
@@ -5702,10 +5703,7 @@
pp->port = snum;
pp->fastreuse = 0;
INIT_HLIST_HEAD(&pp->owner);
- if ((pp->next = head->chain) != NULL)
- pp->next->pprev = &pp->next;
- head->chain = pp;
- pp->pprev = &head->chain;
+ hlist_add_head(&pp->node, &head->chain);
}
return pp;
}
@@ -5714,9 +5712,7 @@
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
{
if (pp && hlist_empty(&pp->owner)) {
- if (pp->next)
- pp->next->pprev = pp->pprev;
- *(pp->pprev) = pp->next;
+ __hlist_del(&pp->node);
kmem_cache_free(sctp_bucket_cachep, pp);
SCTP_DBG_OBJCNT_DEC(bind_bucket);
}
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 0669778..da4f157 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -263,6 +263,15 @@
.proc_handler = &proc_dointvec,
.strategy = &sysctl_intvec
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "addip_noauth_enable",
+ .data = &sctp_addip_noauth,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ .strategy = &sysctl_intvec
+ },
{ .ctl_name = 0 }
};
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 5f467c9..d55ce83 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -74,8 +74,8 @@
* given destination transport address, set RTO to the protocol
* parameter 'RTO.Initial'.
*/
+ peer->last_rto = peer->rto = msecs_to_jiffies(sctp_rto_initial);
peer->rtt = 0;
- peer->rto = msecs_to_jiffies(sctp_rto_initial);
peer->rttvar = 0;
peer->srtt = 0;
peer->rto_pending = 0;
@@ -385,6 +385,7 @@
tp->rto = tp->asoc->rto_max;
tp->rtt = rtt;
+ tp->last_rto = tp->rto;
/* Reset rto_pending so that a new RTT measurement is started when a
* new data chunk is sent.
@@ -578,7 +579,7 @@
*/
t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
t->ssthresh = asoc->peer.i.a_rwnd;
- t->rto = asoc->rto_initial;
+ t->last_rto = t->rto = asoc->rto_initial;
t->rtt = 0;
t->srtt = 0;
t->rttvar = 0;
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 4be92d0..4908041 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -862,7 +862,7 @@
continue;
/* see if this ssn has been marked by skipping */
- if (!SSN_lt(cssn, sctp_ssn_peek(in, csid)))
+ if (!SSN_lte(cssn, sctp_ssn_peek(in, csid)))
break;
__skb_unlink(pos, &ulpq->lobby);
diff --git a/net/socket.c b/net/socket.c
index 5d879fd..74784df 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2319,6 +2319,11 @@
return err;
}
+int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
+{
+ return sock->ops->shutdown(sock, how);
+}
+
/* ABI emulation layers need these two */
EXPORT_SYMBOL(move_addr_to_kernel);
EXPORT_SYMBOL(move_addr_to_user);
@@ -2345,3 +2350,4 @@
EXPORT_SYMBOL(kernel_setsockopt);
EXPORT_SYMBOL(kernel_sendpage);
EXPORT_SYMBOL(kernel_sock_ioctl);
+EXPORT_SYMBOL(kernel_sock_shutdown);
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index dc55cc97..1afeb3e 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -320,9 +320,9 @@
xprt->slot = kcalloc(xprt->max_reqs,
sizeof(struct rpc_rqst), GFP_KERNEL);
if (xprt->slot == NULL) {
- kfree(xprt);
dprintk("RPC: %s: couldn't allocate %d slots\n",
__func__, xprt->max_reqs);
+ kfree(xprt);
return ERR_PTR(-ENOMEM);
}
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 515e7a6..e835da8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -457,7 +457,7 @@
* What the above comment does talk about? --ANK(980817)
*/
- if (atomic_read(&unix_tot_inflight))
+ if (unix_tot_inflight)
unix_gc(); /* Garbage collect fds */
return 0;
@@ -599,15 +599,14 @@
struct sock *sk = NULL;
struct unix_sock *u;
- if (atomic_read(&unix_nr_socks) >= 2*get_max_files())
+ atomic_inc(&unix_nr_socks);
+ if (atomic_read(&unix_nr_socks) > 2 * get_max_files())
goto out;
sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto);
if (!sk)
goto out;
- atomic_inc(&unix_nr_socks);
-
sock_init_data(sock,sk);
lockdep_set_class(&sk->sk_receive_queue.lock,
&af_unix_sk_receive_queue_lock_key);
@@ -625,6 +624,8 @@
init_waitqueue_head(&u->peer_wait);
unix_insert_socket(unix_sockets_unbound, sk);
out:
+ if (sk == NULL)
+ atomic_dec(&unix_nr_socks);
return sk;
}
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 406b643..ebdff3d 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -92,7 +92,7 @@
static LIST_HEAD(gc_candidates);
static DEFINE_SPINLOCK(unix_gc_lock);
-atomic_t unix_tot_inflight = ATOMIC_INIT(0);
+unsigned int unix_tot_inflight;
static struct sock *unix_get_socket(struct file *filp)
@@ -133,7 +133,7 @@
} else {
BUG_ON(list_empty(&u->link));
}
- atomic_inc(&unix_tot_inflight);
+ unix_tot_inflight++;
spin_unlock(&unix_gc_lock);
}
}
@@ -147,7 +147,7 @@
BUG_ON(list_empty(&u->link));
if (atomic_dec_and_test(&u->inflight))
list_del_init(&u->link);
- atomic_dec(&unix_tot_inflight);
+ unix_tot_inflight--;
spin_unlock(&unix_gc_lock);
}
}
@@ -161,7 +161,7 @@
for (skb = sock_queue_head(sk)->next, next = skb->next; \
skb != sock_queue_head(sk); skb = next, next = skb->next)
-static void scan_inflight(struct sock *x, void (*func)(struct sock *),
+static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
struct sk_buff_head *hitlist)
{
struct sk_buff *skb;
@@ -185,9 +185,9 @@
* if it indeed does so
*/
struct sock *sk = unix_get_socket(*fp++);
- if(sk) {
+ if (sk) {
hit = true;
- func(sk);
+ func(unix_sk(sk));
}
}
if (hit && hitlist != NULL) {
@@ -199,7 +199,7 @@
spin_unlock(&x->sk_receive_queue.lock);
}
-static void scan_children(struct sock *x, void (*func)(struct sock *),
+static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
struct sk_buff_head *hitlist)
{
if (x->sk_state != TCP_LISTEN)
@@ -235,20 +235,18 @@
}
}
-static void dec_inflight(struct sock *sk)
+static void dec_inflight(struct unix_sock *usk)
{
- atomic_dec(&unix_sk(sk)->inflight);
+ atomic_dec(&usk->inflight);
}
-static void inc_inflight(struct sock *sk)
+static void inc_inflight(struct unix_sock *usk)
{
- atomic_inc(&unix_sk(sk)->inflight);
+ atomic_inc(&usk->inflight);
}
-static void inc_inflight_move_tail(struct sock *sk)
+static void inc_inflight_move_tail(struct unix_sock *u)
{
- struct unix_sock *u = unix_sk(sk);
-
atomic_inc(&u->inflight);
/*
* If this is still a candidate, move it to the end of the
diff --git a/samples/markers/marker-example.c b/samples/markers/marker-example.c
index e787c6d..05e438f 100644
--- a/samples/markers/marker-example.c
+++ b/samples/markers/marker-example.c
@@ -19,7 +19,8 @@
{
int i;
- trace_mark(subsystem_event, "%d %s", 123, "example string");
+ trace_mark(subsystem_event, "integer %d string %s", 123,
+ "example string");
for (i = 0; i < 10; i++)
trace_mark(subsystem_eventb, MARK_NOARGS);
return -EPERM;
diff --git a/samples/markers/probe-example.c b/samples/markers/probe-example.c
index 238b2e3..a367975 100644
--- a/samples/markers/probe-example.c
+++ b/samples/markers/probe-example.c
@@ -53,7 +53,7 @@
static struct probe_data probe_array[] =
{
{ .name = "subsystem_event",
- .format = "%d %s",
+ .format = "integer %d string %s",
.probe_func = probe_subsystem_event },
{ .name = "subsystem_eventb",
.format = MARK_NOARGS,
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 5959412..1ad6f7f 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -4,12 +4,7 @@
PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config
-# If a arch/$(SRCARCH)/Kconfig.$(ARCH) file exist use it
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/Kconfig.$(ARCH)),)
- Kconfig := arch/$(SRCARCH)/Kconfig.$(ARCH)
-else
- Kconfig := arch/$(SRCARCH)/Kconfig
-endif
+Kconfig := arch/$(SRCARCH)/Kconfig
xconfig: $(obj)/qconf
$< $(Kconfig)
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index a38787a..c6bee85 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -591,6 +591,7 @@
conf_read_simple(name, S_DEF_USER);
else if (!stat("all.config", &tmpstat))
conf_read_simple("all.config", S_DEF_USER);
+ conf_set_env_sym("K64BIT", "64BIT", S_DEF_USER);
break;
default:
break;
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index b2913e9..e4fa3f3 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -83,6 +83,95 @@
return name;
}
+static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
+{
+ char *p2;
+
+ switch (sym->type) {
+ case S_TRISTATE:
+ if (p[0] == 'm') {
+ sym->def[def].tri = mod;
+ sym->flags |= def_flags;
+ break;
+ }
+ case S_BOOLEAN:
+ if (p[0] == 'y') {
+ sym->def[def].tri = yes;
+ sym->flags |= def_flags;
+ break;
+ }
+ if (p[0] == 'n') {
+ sym->def[def].tri = no;
+ sym->flags |= def_flags;
+ break;
+ }
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ break;
+ case S_OTHER:
+ if (*p != '"') {
+ for (p2 = p; *p2 && !isspace(*p2); p2++)
+ ;
+ sym->type = S_STRING;
+ goto done;
+ }
+ case S_STRING:
+ if (*p++ != '"')
+ break;
+ for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+ if (*p2 == '"') {
+ *p2 = 0;
+ break;
+ }
+ memmove(p2, p2 + 1, strlen(p2));
+ }
+ if (!p2) {
+ conf_warning("invalid string found");
+ return 1;
+ }
+ case S_INT:
+ case S_HEX:
+ done:
+ if (sym_string_valid(sym, p)) {
+ sym->def[def].val = strdup(p);
+ sym->flags |= def_flags;
+ } else {
+ conf_warning("symbol value '%s' invalid for %s", p, sym->name);
+ return 1;
+ }
+ break;
+ default:
+ ;
+ }
+ return 0;
+}
+
+/* Read an environment variable and assign the value to the symbol */
+int conf_set_env_sym(const char *env, const char *symname, int def)
+{
+ struct symbol *sym;
+ char *p;
+ int def_flags;
+
+ p = getenv(env);
+ if (p) {
+ char warning[200];
+ sprintf(warning, "Environment variable (%s = \"%s\")", env, p);
+ conf_filename = warning;
+ def_flags = SYMBOL_DEF << def;
+ if (def == S_DEF_USER) {
+ sym = sym_find(symname);
+ if (!sym)
+ return 1;
+ } else {
+ sym = sym_lookup(symname, 0);
+ if (sym->type == S_UNKNOWN)
+ sym->type = S_OTHER;
+ }
+ conf_set_sym_val(sym, def, def_flags, p);
+ }
+ return 0;
+}
+
int conf_read_simple(const char *name, int def)
{
FILE *in = NULL;
@@ -213,61 +302,8 @@
conf_warning("trying to reassign symbol %s", sym->name);
break;
}
- switch (sym->type) {
- case S_TRISTATE:
- if (p[0] == 'm') {
- sym->def[def].tri = mod;
- sym->flags |= def_flags;
- break;
- }
- case S_BOOLEAN:
- if (p[0] == 'y') {
- sym->def[def].tri = yes;
- sym->flags |= def_flags;
- break;
- }
- if (p[0] == 'n') {
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- }
- conf_warning("symbol value '%s' invalid for %s", p, sym->name);
- break;
- case S_OTHER:
- if (*p != '"') {
- for (p2 = p; *p2 && !isspace(*p2); p2++)
- ;
- sym->type = S_STRING;
- goto done;
- }
- case S_STRING:
- if (*p++ != '"')
- break;
- for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
- if (*p2 == '"') {
- *p2 = 0;
- break;
- }
- memmove(p2, p2 + 1, strlen(p2));
- }
- if (!p2) {
- conf_warning("invalid string found");
- continue;
- }
- case S_INT:
- case S_HEX:
- done:
- if (sym_string_valid(sym, p)) {
- sym->def[def].val = strdup(p);
- sym->flags |= def_flags;
- } else {
- conf_warning("symbol value '%s' invalid for %s", p, sym->name);
- continue;
- }
- break;
- default:
- ;
- }
+ if (conf_set_sym_val(sym, def, def_flags, p))
+ continue;
break;
case '\r':
case '\n':
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 4d09f6d..dca294e 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -1,6 +1,7 @@
/* confdata.c */
P(conf_parse,void,(const char *name));
+P(conf_set_env_sym,int,(const char *envname, const char *symname, int def));
P(conf_read,int,(const char *name));
P(conf_read_simple,int,(const char *name, int));
P(conf_write,int,(const char *name));
diff --git a/security/commoncap.c b/security/commoncap.c
index bf67871..302e8d0 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -526,6 +526,10 @@
if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
return 0;
+ /* sigcont is permitted within same session */
+ if (sig == SIGCONT && (task_session_nr(current) == task_session_nr(p)))
+ return 0;
+
if (secid)
/*
* Signal sent as a particular user.