Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[CIPSO]: Fix several unaligned kernel accesses in the CIPSO engine.
[NetLabel]: consolidate the struct socket/sock handling to just struct sock
[IPV4]: Do not remove idev when addresses are cleared
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index d91125a..0958e97 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -340,8 +340,32 @@
point out some special detail about the sign-off.
+13) When to use Acked-by:
-13) The canonical patch format
+The Signed-off-by: tag indicates that the signer was involved in the
+development of the patch, or that he/she was in the patch's delivery path.
+
+If a person was not directly involved in the preparation or handling of a
+patch but wishes to signify and record their approval of it then they can
+arrange to have an Acked-by: line added to the patch's changelog.
+
+Acked-by: is often used by the maintainer of the affected code when that
+maintainer neither contributed to nor forwarded the patch.
+
+Acked-by: is not as formal as Signed-off-by:. It is a record that the acker
+has at least reviewed the patch and has indicated acceptance. Hence patch
+mergers will sometimes manually convert an acker's "yep, looks good to me"
+into an Acked-by:.
+
+Acked-by: does not necessarily indicate acknowledgement of the entire patch.
+For example, if a patch affects multiple subsystems and has an Acked-by: from
+one subsystem maintainer then this usually indicates acknowledgement of just
+the part which affects that maintainer's code. Judgement should be used here.
+ When in doubt people should refer to the original discussion in the mailing
+list archives.
+
+
+14) The canonical patch format
The canonical patch subject line is:
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt
index 2a63d56..05851e9 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/atomic_ops.txt
@@ -149,7 +149,7 @@
void smp_mb__before_atomic_dec(void);
void smp_mb__after_atomic_dec(void);
void smp_mb__before_atomic_inc(void);
- void smp_mb__after_atomic_dec(void);
+ void smp_mb__after_atomic_inc(void);
For example, smp_mb__before_atomic_dec() can be used like so:
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 19c4a6e..2a97320 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -96,6 +96,46 @@
calls to clk_get(&pdev->dev, clock_name) return them as needed.
+Legacy Drivers: Device Probing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some drivers are not fully converted to the driver model, because they take
+on a non-driver role: the driver registers its platform device, rather than
+leaving that for system infrastructure. Such drivers can't be hotplugged
+or coldplugged, since those mechanisms require device creation to be in a
+different system component than the driver.
+
+The only "good" reason for this is to handle older system designs which, like
+original IBM PCs, rely on error-prone "probe-the-hardware" models for hardware
+configuration. Newer systems have largely abandoned that model, in favor of
+bus-level support for dynamic configuration (PCI, USB), or device tables
+provided by the boot firmware (e.g. PNPACPI on x86). There are too many
+conflicting options about what might be where, and even educated guesses by
+an operating system will be wrong often enough to make trouble.
+
+This style of driver is discouraged. If you're updating such a driver,
+please try to move the device enumeration to a more appropriate location,
+outside the driver. This will usually be cleanup, since such drivers
+tend to already have "normal" modes, such as ones using device nodes that
+were created by PNP or by platform device setup.
+
+None the less, there are some APIs to support such legacy drivers. Avoid
+using these calls except with such hotplug-deficient drivers.
+
+ struct platform_device *platform_device_alloc(
+ char *name, unsigned id);
+
+You can use platform_device_alloc() to dynamically allocate a device, which
+you will then initialize with resources and platform_device_register().
+A better solution is usually:
+
+ struct platform_device *platform_device_register_simple(
+ char *name, unsigned id,
+ struct resource *res, unsigned nres);
+
+You can use platform_device_register_simple() as a one-step call to allocate
+and register a device.
+
+
Device Naming and Driver Binding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The platform_device.dev.bus_id is the canonical name for the devices.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 49ae1ea..7d3f205 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -104,6 +104,7 @@
What: remove EXPORT_SYMBOL(kernel_thread)
When: August 2006
Files: arch/*/kernel/*_ksyms.c
+Funcs: kernel_thread
Why: kernel_thread is a low-level implementation detail. Drivers should
use the <linux/kthread.h> API instead which shields them from
implementation details and provides a higherlevel interface that
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 6dd0508..145e440 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -94,10 +94,10 @@
Note that trying to mount a tmpfs with an mpol option will fail if the
running kernel does not support NUMA; and will fail if its nodelist
-specifies a node >= MAX_NUMNODES. If your system relies on that tmpfs
-being mounted, but from time to time runs a kernel built without NUMA
-capability (perhaps a safe recovery kernel), or configured to support
-fewer nodes, then it is advisable to omit the mpol option from automatic
+specifies a node which is not online. If your system relies on that
+tmpfs being mounted, but from time to time runs a kernel built without
+NUMA capability (perhaps a safe recovery kernel), or with fewer nodes
+online, then it is advisable to omit the mpol option from automatic
mount options. It can be added later, when the tmpfs is already mounted
on MountPoint, by 'mount -o remount,mpol=Policy:NodeList MountPoint'.
@@ -121,4 +121,4 @@
Author:
Christoph Rohland <cr@sap.com>, 1.12.01
Updated:
- Hugh Dickins <hugh@veritas.com>, 19 February 2006
+ Hugh Dickins <hugh@veritas.com>, 4 June 2007
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index e9cc8bb..c3480aa 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -1,7 +1,7 @@
request_firmware() hotplug interface:
------------------------------------
- Copyright (C) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ Copyright (C) 2003 Manuel Estrada Sainz
Why:
---
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index 87feccd..6865cbe 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -1,7 +1,7 @@
/*
* firmware_sample_driver.c -
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* Sample code on how to use request_firmware() from drivers.
*
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index 9e1b0e4..4994f1f 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -1,7 +1,7 @@
/*
* firmware_sample_firmware_class.c -
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* NOTE: This is just a probe of concept, if you think that your driver would
* be well served by this mechanism please contact me first.
@@ -19,7 +19,7 @@
#include <linux/firmware.h>
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
MODULE_LICENSE("GPL");
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index e06b6e3..153d84d 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -32,6 +32,8 @@
- info on the COPS LocalTalk Linux driver
cs89x0.txt
- the Crystal LAN (CS8900/20-based) Ethernet ISA adapter driver
+cxacru.txt
+ - Conexant AccessRunner USB ADSL Modem
de4x5.txt
- the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
decnet.txt
diff --git a/Documentation/networking/cxacru.txt b/Documentation/networking/cxacru.txt
new file mode 100644
index 0000000..b074681
--- /dev/null
+++ b/Documentation/networking/cxacru.txt
@@ -0,0 +1,84 @@
+Firmware is required for this device: http://accessrunner.sourceforge.net/
+
+While it is capable of managing/maintaining the ADSL connection without the
+module loaded, the device will sometimes stop responding after unloading the
+driver and it is necessary to unplug/remove power to the device to fix this.
+
+Detected devices will appear as ATM devices named "cxacru". In /sys/class/atm/
+these are directories named cxacruN where N is the device number. A symlink
+named device points to the USB interface device's directory which contains
+several sysfs attribute files for retrieving device statistics:
+
+* adsl_controller_version
+
+* adsl_headend
+* adsl_headend_environment
+ Information about the remote headend.
+
+* downstream_attenuation (dB)
+* downstream_bits_per_frame
+* downstream_rate (kbps)
+* downstream_snr_margin (dB)
+ Downstream stats.
+
+* upstream_attenuation (dB)
+* upstream_bits_per_frame
+* upstream_rate (kbps)
+* upstream_snr_margin (dB)
+* transmitter_power (dBm/Hz)
+ Upstream stats.
+
+* downstream_crc_errors
+* downstream_fec_errors
+* downstream_hec_errors
+* upstream_crc_errors
+* upstream_fec_errors
+* upstream_hec_errors
+ Error counts.
+
+* line_startable
+ Indicates that ADSL support on the device
+ is/can be enabled, see adsl_start.
+
+* line_status
+ "initialising"
+ "down"
+ "attempting to activate"
+ "training"
+ "channel analysis"
+ "exchange"
+ "waiting"
+ "up"
+
+ Changes between "down" and "attempting to activate"
+ if there is no signal.
+
+* link_status
+ "not connected"
+ "connected"
+ "lost"
+
+* mac_address
+
+* modulation
+ "ANSI T1.413"
+ "ITU-T G.992.1 (G.DMT)"
+ "ITU-T G.992.2 (G.LITE)"
+
+* startup_attempts
+ Count of total attempts to initialise ADSL.
+
+To enable/disable ADSL, the following can be written to the adsl_state file:
+ "start"
+ "stop
+ "restart" (stops, waits 1.5s, then starts)
+ "poll" (used to resume status polling if it was disabled due to failure)
+
+Changes in adsl/line state are reported via kernel log messages:
+ [4942145.150704] ATM dev 0: ADSL state: running
+ [4942243.663766] ATM dev 0: ADSL line: down
+ [4942249.665075] ATM dev 0: ADSL line: attempting to activate
+ [4942253.654954] ATM dev 0: ADSL line: training
+ [4942255.666387] ATM dev 0: ADSL line: channel analysis
+ [4942259.656262] ATM dev 0: ADSL line: exchange
+ [2635357.696901] ATM dev 0: ADSL line: up (8128 kb/s down | 832 kb/s up)
diff --git a/MAINTAINERS b/MAINTAINERS
index f3b5a39..4c715a7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -782,11 +782,6 @@
L: linux-kernel@vger.kernel.org
S: Maintained
-BERKSHIRE PRODUCTS PC WATCHDOG DRIVER
-P: Kenji Hollis
-W: http://ftp.bitgate.com/pcwd/
-S: Maintained
-
BFS FILE SYSTEM
P: Tigran A. Aivazian
M: tigran@aivazian.fsnet.co.uk
@@ -3025,7 +3020,7 @@
REISERFS FILE SYSTEM
P: Hans Reiser
M: reiserfs-dev@namesys.com
-L: reiserfs-list@namesys.com
+L: reiserfs-devel@vger.kernel.org
W: http://www.namesys.com
S: Supported
@@ -3904,10 +3899,6 @@
UCLINUX FOR NEC V850
P: Miles Bader
-M: uclinux-v850@lsi.nec.co.jp
-W: http://www.ic.nec.co.jp/micro/uclinux/eng/
-W: http://www.ee.nec.de/uclinux/
-S: Supported
UCLINUX FOR RENESAS H8/300
P: Yoshinori Sato
@@ -3916,10 +3907,10 @@
S: Supported
UFS FILESYSTEM
-P: Evgeniy Dushistov
-M: dushistov@mail.ru
-L: linux-kernel@vger.kernel.org
-S: Maintained
+P: Evgeniy Dushistov
+M: dushistov@mail.ru
+L: linux-kernel@vger.kernel.org
+S: Maintained
USB DIAMOND RIO500 DRIVER
P: Cesar Miquel
diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
index ddf8fa3..1853524 100644
--- a/arch/i386/math-emu/fpu_entry.c
+++ b/arch/i386/math-emu/fpu_entry.c
@@ -754,7 +754,7 @@
return -1;
if ( offset )
if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
- return -1
+ return -1;
RE_ENTRANT_CHECK_ON;
return 1;
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index 92e5807..fb66ead 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -62,10 +62,13 @@
/***************************************************************************/
+static int ticks_per_intr;
+
void coldfire_timer_init(irq_handler_t handler)
{
__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
- __raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
+ ticks_per_intr = (MCF_BUSCLK / 16) / HZ;
+ __raw_writetrr(ticks_per_intr - 1, TA(MCFTIMER_TRR));
__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
@@ -81,11 +84,10 @@
unsigned long coldfire_timer_offset(void)
{
- unsigned long trr, tcn, offset;
+ unsigned long tcn, offset;
tcn = __raw_readw(TA(MCFTIMER_TCN));
- trr = __raw_readtrr(TA(MCFTIMER_TRR));
- offset = (tcn * (1000000 / HZ)) / trr;
+ offset = ((tcn + 1) * (1000000 / HZ)) / ticks_per_intr;
/* Check if we just wrapped the counters and maybe missed a tick */
if ((offset < (1000000 / HZ / 2)) && mcf_timerirqpending(1))
diff --git a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c
index 85053b2..7a97c74 100644
--- a/arch/ppc/syslib/qspan_pci.c
+++ b/arch/ppc/syslib/qspan_pci.c
@@ -365,13 +365,13 @@
}
void __init
-m8xx_pcibios_fixup(void))
+m8xx_pcibios_fixup(void)
{
/* Lots to do here, all board and configuration specific. */
}
void __init
-m8xx_setup_pci_ptrs(void))
+m8xx_setup_pci_ptrs(void)
{
set_config_access_method(qspan);
diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
index fb51660..3334f99 100644
--- a/arch/sh64/kernel/pci_sh5.c
+++ b/arch/sh64/kernel/pci_sh5.c
@@ -521,10 +521,10 @@
bus->resource[0]->start = PCIBIOS_MIN_IO;
bus->resource[1]->start = PCIBIOS_MIN_MEM;
#else
- bus->resource[0]->end = 0
- bus->resource[1]->end = 0
- bus->resource[0]->start =0
- bus->resource[1]->start = 0;
+ bus->resource[0]->end = 0;
+ bus->resource[1]->end = 0;
+ bus->resource[0]->start =0;
+ bus->resource[1]->start = 0;
#endif
/* Turn off downstream PF memory address range by default */
bus->resource[2]->start = 1024*1024;
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 16cc46a..6676b93 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -343,6 +343,15 @@
if (model && !strcmp(model, "SUNW,simba"))
return 1;
+
+ /* Treat PCI busses lacking ranges property just like
+ * simba.
+ */
+ if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
+ if (!of_find_property(np, "ranges", NULL))
+ return 1;
+ }
+
return 0;
}
@@ -549,8 +558,6 @@
static int __init use_1to1_mapping(struct device_node *pp)
{
- const char *model;
-
/* If this is on the PMU bus, don't try to translate it even
* if a ranges property exists.
*/
@@ -567,9 +574,11 @@
if (!strcmp(pp->name, "dma"))
return 0;
- /* Similarly for Simba PCI bridges. */
- model = of_get_property(pp, "model", NULL);
- if (model && !strcmp(model, "SUNW,simba"))
+ /* Similarly for all PCI bridges, if we get this far
+ * it lacks a ranges property, and this will include
+ * cases like Simba.
+ */
+ if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex"))
return 0;
return 1;
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 38a32bc..81f4a5e 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -522,6 +522,89 @@
res->end += root->start;
}
+/* For PCI bus devices which lack a 'ranges' property we interrogate
+ * the config space values to set the resources, just like the generic
+ * Linux PCI probing code does.
+ */
+static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
+ struct pci_bus *bus,
+ struct pci_pbm_info *pbm)
+{
+ struct resource *res;
+ u8 io_base_lo, io_limit_lo;
+ u16 mem_base_lo, mem_limit_lo;
+ unsigned long base, limit;
+
+ pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
+ pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
+ base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
+ limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
+
+ if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+ u16 io_base_hi, io_limit_hi;
+
+ pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
+ pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
+ base |= (io_base_hi << 16);
+ limit |= (io_limit_hi << 16);
+ }
+
+ res = bus->resource[0];
+ if (base <= limit) {
+ res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
+ if (!res->start)
+ res->start = base;
+ if (!res->end)
+ res->end = limit + 0xfff;
+ pci_resource_adjust(res, &pbm->io_space);
+ }
+
+ pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
+ pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
+ base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
+ limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+
+ res = bus->resource[1];
+ if (base <= limit) {
+ res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+ IORESOURCE_MEM);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
+ }
+
+ pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
+ pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
+ base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+ limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+
+ if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+ u32 mem_base_hi, mem_limit_hi;
+
+ pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
+ pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
+
+ /*
+ * Some bridges set the base > limit by default, and some
+ * (broken) BIOSes do not initialize them. If we find
+ * this, just assume they are not being used.
+ */
+ if (mem_base_hi <= mem_limit_hi) {
+ base |= ((long) mem_base_hi) << 32;
+ limit |= ((long) mem_limit_hi) << 32;
+ }
+ }
+
+ res = bus->resource[2];
+ if (base <= limit) {
+ res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+ IORESOURCE_MEM | IORESOURCE_PREFETCH);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
+ }
+}
+
/* Cook up fake bus resources for SUNW,simba PCI bridges which lack
* a proper 'ranges' property.
*/
@@ -581,13 +664,8 @@
simba = 0;
if (ranges == NULL) {
const char *model = of_get_property(node, "model", NULL);
- if (model && !strcmp(model, "SUNW,simba")) {
+ if (model && !strcmp(model, "SUNW,simba"))
simba = 1;
- } else {
- printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
- node->full_name);
- return;
- }
}
bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
@@ -611,7 +689,10 @@
}
if (simba) {
apb_fake_ranges(dev, bus, pbm);
- goto simba_cont;
+ goto after_ranges;
+ } else if (ranges == NULL) {
+ pci_cfg_fake_ranges(dev, bus, pbm);
+ goto after_ranges;
}
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
@@ -650,7 +731,7 @@
*/
pci_resource_adjust(res, root);
}
-simba_cont:
+after_ranges:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
if (ofpci_verbose)
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index d00f51a..6fa7616 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -24,6 +24,7 @@
#include <linux/syscalls.h>
#include <linux/percpu.h>
#include <linux/init.h>
+#include <linux/rwsem.h>
#include <net/compat.h>
#include <asm/oplib.h>
@@ -58,7 +59,6 @@
#include <asm/ns87303.h>
#include <asm/timer.h>
#include <asm/cpudata.h>
-#include <asm/rwsem.h>
struct poll {
int fd;
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c504312..e6ff302 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -278,6 +278,7 @@
config KERNEL_STACK_ORDER
int "Kernel stack size order"
default 1 if 64BIT
+ range 1 10 if 64BIT
default 0 if !64BIT
help
This option determines the size of UML kernel stacks. They will
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index ced9910..4bd40bb 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/list.h"
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 9115392..4739dd5 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -1,3 +1,4 @@
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/console.h>
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 70509dd..2e09f16 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -20,6 +20,7 @@
#define MAJOR_NR UBD_MAJOR
#define UBD_SHIFT 4
+#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/blkdev.h"
#include "linux/hdreg.h"
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 8b7f2cd..c716b5a 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,8 +1,9 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
+#include "linux/kernel.h"
#include "linux/init.h"
#include "linux/ctype.h"
#include "linux/proc_fs.h"
@@ -24,11 +25,14 @@
val = uml_exitcode;
len = sprintf(page, "%d\n", val);
len -= off;
- if(len <= off+count) *eof = 1;
+ if(len <= off+count)
+ *eof = 1;
*start = page + off;
- if(len > count) len = count;
- if(len < 0) len = 0;
- return(len);
+ if(len > count)
+ len = count;
+ if(len < 0)
+ len = 0;
+ return len;
}
static int write_proc_exitcode(struct file *file, const char __user *buffer,
@@ -38,12 +42,14 @@
int tmp;
if(copy_from_user(buf, buffer, count))
- return(-EFAULT);
+ return -EFAULT;
+
tmp = simple_strtol(buf, &end, 0);
if((*end != '\0') && !isspace(*end))
- return(-EINVAL);
+ return -EINVAL;
+
uml_exitcode = tmp;
- return(count);
+ return count;
}
static int make_proc_exitcode(void)
@@ -54,24 +60,13 @@
if(ent == NULL){
printk(KERN_WARNING "make_proc_exitcode : Failed to register "
"/proc/exitcode\n");
- return(0);
+ return 0;
}
ent->read_proc = read_proc_exitcode;
ent->write_proc = write_proc_exitcode;
-
- return(0);
+
+ return 0;
}
__initcall(make_proc_exitcode);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index cb29fb9..aac1c0b 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -465,13 +465,14 @@
unsigned __kprobes long oops_begin(void)
{
- int cpu = smp_processor_id();
+ int cpu;
unsigned long flags;
oops_enter();
/* racy, but better than risking deadlock. */
local_irq_save(flags);
+ cpu = smp_processor_id();
if (!spin_trylock(&die_lock)) {
if (cpu == die_owner)
/* nested oops. should stop eventually */;
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 1ad5111..efb6e84 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -79,6 +79,8 @@
if (unlikely(i % MAX_ORDER_NR_PAGES == 0)) {
touch_nmi_watchdog();
}
+ if (!pfn_valid(pgdat->node_start_pfn + i))
+ continue;
page = pfn_to_page(pgdat->node_start_pfn + i);
total++;
if (PageReserved(page))
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 2b924a6..6dc0b01 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -784,9 +784,12 @@
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
break;
/*FALLTHROUGH*/
+ case ATA_PROT_NODATA:
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ break;
+ /*FALLTHROUGH*/
case ATA_PROT_ATAPI_DMA:
case ATA_PROT_DMA:
- case ATA_PROT_NODATA:
pdc_packet_start(qc);
return 0;
@@ -800,7 +803,7 @@
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_tf_load(ap, tf);
}
@@ -808,7 +811,7 @@
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_exec_command(ap, tf);
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 20c4ea6..8c506db 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -369,36 +369,6 @@
return class_name;
}
-static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
- char *buffer, int buffer_size,
- int *cur_len,
- struct class_device *class_dev)
-{
- struct device *dev = class_dev->dev;
- char *path;
-
- if (!dev)
- return 0;
-
- /* add device, backing this class device (deprecated) */
- path = kobject_get_path(&dev->kobj, GFP_KERNEL);
-
- add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
- cur_len, "PHYSDEVPATH=%s", path);
- kfree(path);
-
- if (dev->bus)
- add_uevent_var(envp, num_envp, cur_index,
- buffer, buffer_size, cur_len,
- "PHYSDEVBUS=%s", dev->bus->name);
-
- if (dev->driver)
- add_uevent_var(envp, num_envp, cur_index,
- buffer, buffer_size, cur_len,
- "PHYSDEVDRIVER=%s", dev->driver->name);
- return 0;
-}
-
static int make_deprecated_class_device_links(struct class_device *class_dev)
{
char *class_name;
@@ -430,11 +400,6 @@
kfree(class_name);
}
#else
-static inline int deprecated_class_uevent(char **envp, int num_envp,
- int *cur_index, char *buffer,
- int buffer_size, int *cur_len,
- struct class_device *class_dev)
-{ return 0; }
static inline int make_deprecated_class_device_links(struct class_device *cd)
{ return 0; }
static void remove_deprecated_class_device_links(struct class_device *cd)
@@ -445,15 +410,13 @@
int num_envp, char *buffer, int buffer_size)
{
struct class_device *class_dev = to_class_dev(kobj);
+ struct device *dev = class_dev->dev;
int i = 0;
int length = 0;
int retval = 0;
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
- deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
- &length, class_dev);
-
if (MAJOR(class_dev->devt)) {
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
@@ -464,6 +427,26 @@
"MINOR=%u", MINOR(class_dev->devt));
}
+ if (dev) {
+ const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+ if (path) {
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVPATH=%s", path);
+ kfree(path);
+ }
+
+ if (dev->bus)
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
+
+ if (dev->driver)
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
+ }
+
/* terminate, set to next free slot, shrink available space */
envp[i] = NULL;
envp = &envp[i];
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b78fc1e..dd40d78 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -180,10 +180,12 @@
const char *path;
path = kobject_get_path(&parent->kobj, GFP_KERNEL);
- add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVPATH=%s", path);
- kfree(path);
+ if (path) {
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVPATH=%s", path);
+ kfree(path);
+ }
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 92428e5..b0088b0 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -207,19 +207,6 @@
return driver_probe_device(drv, dev);
}
-static int device_probe_drivers(void *data)
-{
- struct device *dev = data;
- int ret = 0;
-
- if (dev->bus) {
- down(&dev->sem);
- ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
- up(&dev->sem);
- }
- return ret;
-}
-
/**
* device_attach - try to attach device to a driver.
* @dev: device.
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 97ab5bd..89a5f4a 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1,7 +1,7 @@
/*
* firmware_class.c - Multi purpose firmware loading support
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* Please see Documentation/firmware_class/ for more information.
*
@@ -23,7 +23,7 @@
#define to_dev(obj) container_of(obj, struct device, kobj)
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL");
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5526ead..0ed5470 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1354,7 +1354,7 @@
*/
static int max_loop;
module_param(max_loop, int, 0);
-MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand");
+MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
@@ -1394,16 +1394,11 @@
EXPORT_SYMBOL(loop_register_transfer);
EXPORT_SYMBOL(loop_unregister_transfer);
-static struct loop_device *loop_init_one(int i)
+static struct loop_device *loop_alloc(int i)
{
struct loop_device *lo;
struct gendisk *disk;
- list_for_each_entry(lo, &loop_devices, lo_list) {
- if (lo->lo_number == i)
- return lo;
- }
-
lo = kzalloc(sizeof(*lo), GFP_KERNEL);
if (!lo)
goto out;
@@ -1427,8 +1422,6 @@
disk->private_data = lo;
disk->queue = lo->lo_queue;
sprintf(disk->disk_name, "loop%d", i);
- add_disk(disk);
- list_add_tail(&lo->lo_list, &loop_devices);
return lo;
out_free_queue:
@@ -1439,15 +1432,37 @@
return NULL;
}
-static void loop_del_one(struct loop_device *lo)
+static void loop_free(struct loop_device *lo)
{
- del_gendisk(lo->lo_disk);
blk_cleanup_queue(lo->lo_queue);
put_disk(lo->lo_disk);
list_del(&lo->lo_list);
kfree(lo);
}
+static struct loop_device *loop_init_one(int i)
+{
+ struct loop_device *lo;
+
+ list_for_each_entry(lo, &loop_devices, lo_list) {
+ if (lo->lo_number == i)
+ return lo;
+ }
+
+ lo = loop_alloc(i);
+ if (lo) {
+ add_disk(lo->lo_disk);
+ list_add_tail(&lo->lo_list, &loop_devices);
+ }
+ return lo;
+}
+
+static void loop_del_one(struct loop_device *lo)
+{
+ del_gendisk(lo->lo_disk);
+ loop_free(lo);
+}
+
static struct kobject *loop_probe(dev_t dev, int *part, void *data)
{
struct loop_device *lo;
@@ -1464,28 +1479,77 @@
static int __init loop_init(void)
{
- if (register_blkdev(LOOP_MAJOR, "loop"))
- return -EIO;
- blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS,
- THIS_MODULE, loop_probe, NULL, NULL);
+ int i, nr;
+ unsigned long range;
+ struct loop_device *lo, *next;
+
+ /*
+ * loop module now has a feature to instantiate underlying device
+ * structure on-demand, provided that there is an access dev node.
+ * However, this will not work well with user space tool that doesn't
+ * know about such "feature". In order to not break any existing
+ * tool, we do the following:
+ *
+ * (1) if max_loop is specified, create that many upfront, and this
+ * also becomes a hard limit.
+ * (2) if max_loop is not specified, create 8 loop device on module
+ * load, user can further extend loop device by create dev node
+ * themselves and have kernel automatically instantiate actual
+ * device on-demand.
+ */
+ if (max_loop > 1UL << MINORBITS)
+ return -EINVAL;
if (max_loop) {
- printk(KERN_INFO "loop: the max_loop option is obsolete "
- "and will be removed in March 2008\n");
-
+ nr = max_loop;
+ range = max_loop;
+ } else {
+ nr = 8;
+ range = 1UL << MINORBITS;
}
+
+ if (register_blkdev(LOOP_MAJOR, "loop"))
+ return -EIO;
+
+ for (i = 0; i < nr; i++) {
+ lo = loop_alloc(i);
+ if (!lo)
+ goto Enomem;
+ list_add_tail(&lo->lo_list, &loop_devices);
+ }
+
+ /* point of no return */
+
+ list_for_each_entry(lo, &loop_devices, lo_list)
+ add_disk(lo->lo_disk);
+
+ blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
+ THIS_MODULE, loop_probe, NULL, NULL);
+
printk(KERN_INFO "loop: module loaded\n");
return 0;
+
+Enomem:
+ printk(KERN_INFO "loop: out of memory\n");
+
+ list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+ loop_free(lo);
+
+ unregister_blkdev(LOOP_MAJOR, "loop");
+ return -ENOMEM;
}
static void __exit loop_exit(void)
{
+ unsigned long range;
struct loop_device *lo, *next;
+ range = max_loop ? max_loop : 1UL << MINORBITS;
+
list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
loop_del_one(lo);
- blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS);
+ blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
if (unregister_blkdev(LOOP_MAJOR, "loop"))
printk(KERN_WARNING "loop: cannot unregister blkdev\n");
}
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index f574962..4310cc8 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -1053,11 +1053,11 @@
if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
xwarn("cleanup() unregister_blkdev() failed\n");
}
- blk_cleanup_queue(mcdx_queue);
#if !MCDX_QUIET
else
xinfo("cleanup() succeeded\n");
#endif
+ blk_cleanup_queue(mcdx_queue);
}
#ifdef MODULE
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index e45113a..45bf2a2 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -2172,11 +2172,12 @@
}
status = inb(ioaddr + ECH_PNLSTATUS);
if ((status & ECH_PNLIDMASK) != nxtid)
- goto err_fr;
+ break;
panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
if (!panelp) {
printk("STALLION: failed to allocate memory "
"(size=%Zd)\n", sizeof(struct stlpanel));
+ retval = -ENOMEM;
goto err_fr;
}
panelp->magic = STL_PANELMAGIC;
@@ -2223,8 +2224,10 @@
brdp->nrports += panelp->nrports;
brdp->panels[panelnr++] = panelp;
if ((brdp->brdtype != BRD_ECHPCI) &&
- (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
+ (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
+ retval = -EINVAL;
goto err_fr;
+ }
}
brdp->nrpanels = panelnr;
@@ -2371,6 +2374,7 @@
dev_err(&pdev->dev, "too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
mutex_unlock(&stl_brdslock);
+ retval = -ENODEV;
goto err_fr;
}
brdp->brdnr = (unsigned int)brdnr;
@@ -4710,6 +4714,29 @@
spin_lock_init(&stallion_lock);
spin_lock_init(&brd_lock);
+ stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+ if (!stl_serial) {
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ stl_serial->owner = THIS_MODULE;
+ stl_serial->driver_name = stl_drvname;
+ stl_serial->name = "ttyE";
+ stl_serial->major = STL_SERIALMAJOR;
+ stl_serial->minor_start = 0;
+ stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+ stl_serial->subtype = SERIAL_TYPE_NORMAL;
+ stl_serial->init_termios = stl_deftermios;
+ stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(stl_serial, &stl_ops);
+
+ retval = tty_register_driver(stl_serial);
+ if (retval) {
+ printk("STALLION: failed to register serial driver\n");
+ goto err_frtty;
+ }
+
/*
* Find any dynamically supported boards. That is via module load
* line options.
@@ -4739,13 +4766,9 @@
/* this has to be _after_ isa finding because of locking */
retval = pci_register_driver(&stl_pcidriver);
- if (retval && stl_nrbrds == 0)
- goto err;
-
- stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
- if (!stl_serial) {
- retval = -ENOMEM;
- goto err_pcidr;
+ if (retval && stl_nrbrds == 0) {
+ printk(KERN_ERR "STALLION: can't register pci driver\n");
+ goto err_unrtty;
}
/*
@@ -4756,43 +4779,18 @@
printk("STALLION: failed to register serial board device\n");
stallion_class = class_create(THIS_MODULE, "staliomem");
- if (IS_ERR(stallion_class)) {
- retval = PTR_ERR(stallion_class);
- goto err_reg;
- }
+ if (IS_ERR(stallion_class))
+ printk("STALLION: failed to create class\n");
for (i = 0; i < 4; i++)
class_device_create(stallion_class, NULL,
MKDEV(STL_SIOMEMMAJOR, i), NULL,
"staliomem%d", i);
- stl_serial->owner = THIS_MODULE;
- stl_serial->driver_name = stl_drvname;
- stl_serial->name = "ttyE";
- stl_serial->major = STL_SERIALMAJOR;
- stl_serial->minor_start = 0;
- stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
- stl_serial->subtype = SERIAL_TYPE_NORMAL;
- stl_serial->init_termios = stl_deftermios;
- stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- tty_set_operations(stl_serial, &stl_ops);
-
- retval = tty_register_driver(stl_serial);
- if (retval) {
- printk("STALLION: failed to register serial driver\n");
- goto err_clsdev;
- }
-
return 0;
-err_clsdev:
- for (i = 0; i < 4; i++)
- class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
- class_destroy(stallion_class);
-err_reg:
- unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+err_unrtty:
+ tty_unregister_driver(stl_serial);
+err_frtty:
put_tty_driver(stl_serial);
-err_pcidr:
- pci_unregister_driver(&stl_pcidriver);
- stl_free_isabrds();
err:
return retval;
}
@@ -4821,8 +4819,6 @@
tty_unregister_device(stl_serial,
brdp->brdnr * STL_MAXPORTS + j);
}
- tty_unregister_driver(stl_serial);
- put_tty_driver(stl_serial);
for (i = 0; i < 4; i++)
class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
@@ -4834,6 +4830,9 @@
pci_unregister_driver(&stl_pcidriver);
stl_free_isabrds();
+
+ tty_unregister_driver(stl_serial);
+ put_tty_driver(stl_serial);
}
module_init(stallion_module_init);
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
index 46fc21a..d36a4c0 100644
--- a/drivers/isdn/hardware/eicon/divasfunc.c
+++ b/drivers/isdn/hardware/eicon/divasfunc.c
@@ -195,7 +195,7 @@
/*
* disconnect from didd
*/
-static void DIVA_EXIT_FUNCTION disconnect_didd(void)
+static void disconnect_didd(void)
{
IDI_SYNC_REQ req;
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 3524e3f..61de78a 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -2182,7 +2182,7 @@
.init_info = kgdbhook_init_info,
.rx_char = kgdbhook_rx_char,
.cflags = B38400 | CS8 | CLOCAL,
-}
+};
void __init zs_kgdb_hook(int tty_num)
{
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 30b7bfb..8bcf7fe 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -476,8 +476,6 @@
add_timer(&timer);
wait_for_completion(done);
status = urb->status;
- if (status == -ECONNRESET)
- status = -ETIMEDOUT;
del_timer_sync(&timer);
if (actual_length)
@@ -629,10 +627,22 @@
return 0;
}
+static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance,
+ struct atm_dev *atm_dev)
+{
+ struct usb_interface *intf = usbatm_instance->usb_intf;
+
+ #define CXACRU_DEVICE_REMOVE_FILE(_name) \
+ device_remove_file(&intf->dev, &dev_attr_##_name);
+ CXACRU_ALL_FILES(REMOVE);
+ #undef CXACRU_DEVICE_REMOVE_FILE
+}
+
static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
{
struct cxacru_data *instance = usbatm_instance->driver_data;
+ struct usb_interface *intf = usbatm_instance->usb_intf;
/*
struct atm_dev *atm_dev = usbatm_instance->atm_dev;
*/
@@ -649,14 +659,18 @@
return ret;
}
+ #define CXACRU_DEVICE_CREATE_FILE(_name) \
+ ret = device_create_file(&intf->dev, &dev_attr_##_name); \
+ if (unlikely(ret)) \
+ goto fail_sysfs;
+ CXACRU_ALL_FILES(CREATE);
+ #undef CXACRU_DEVICE_CREATE_FILE
+
/* start ADSL */
mutex_lock(&instance->adsl_state_serialize);
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
- if (ret < 0) {
+ if (ret < 0)
atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
- mutex_unlock(&instance->adsl_state_serialize);
- return ret;
- }
/* Start status polling */
mutex_lock(&instance->poll_state_serialize);
@@ -680,6 +694,11 @@
if (start_polling)
cxacru_poll_status(&instance->poll_work.work);
return 0;
+
+fail_sysfs:
+ usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret);
+ cxacru_remove_device_files(usbatm_instance, atm_dev);
+ return ret;
}
static void cxacru_poll_status(struct work_struct *work)
@@ -1065,13 +1084,6 @@
goto fail;
}
- #define CXACRU_DEVICE_CREATE_FILE(_name) \
- ret = device_create_file(&intf->dev, &dev_attr_##_name); \
- if (unlikely(ret)) \
- goto fail_sysfs;
- CXACRU_ALL_FILES(CREATE);
- #undef CXACRU_DEVICE_CREATE_FILE
-
usb_fill_int_urb(instance->rcv_urb,
usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
instance->rcv_buf, PAGE_SIZE,
@@ -1092,14 +1104,6 @@
return 0;
- fail_sysfs:
- dbg("cxacru_bind: device_create_file failed (%d)\n", ret);
-
- #define CXACRU_DEVICE_REMOVE_FILE(_name) \
- device_remove_file(&intf->dev, &dev_attr_##_name);
- CXACRU_ALL_FILES(REMOVE);
- #undef CXACRU_DEVICE_REVOVE_FILE
-
fail:
free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf);
@@ -1146,11 +1150,6 @@
free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf);
- #define CXACRU_DEVICE_REMOVE_FILE(_name) \
- device_remove_file(&intf->dev, &dev_attr_##_name);
- CXACRU_ALL_FILES(REMOVE);
- #undef CXACRU_DEVICE_REVOVE_FILE
-
kfree(instance);
usbatm_instance->driver_data = NULL;
@@ -1231,6 +1230,7 @@
.heavy_init = cxacru_heavy_init,
.unbind = cxacru_unbind,
.atm_start = cxacru_atm_start,
+ .atm_stop = cxacru_remove_device_files,
.bulk_in = CXACRU_EP_DATA,
.bulk_out = CXACRU_EP_DATA,
.rx_padding = 3,
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 7b1edfe..6778f9a 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -347,10 +347,8 @@
if (usblp->bidir && usblp->used && !usblp->sleeping) {
usblp->readcount = 0;
usblp->readurb->dev = usblp->dev;
- if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
- usblp->used = 0;
+ if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
return -EIO;
- }
}
return 0;
@@ -412,6 +410,7 @@
usblp->readurb->status = 0;
if (handle_bidir(usblp) < 0) {
+ usblp->used = 0;
file->private_data = NULL;
retval = -EIO;
}
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f493fb1..346fc03 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -40,21 +40,25 @@
config USB_DEVICE_CLASS
bool "USB device class-devices (DEPRECATED)"
depends on USB
- default n
+ default y
---help---
Userspace access to USB devices is granted by device-nodes exported
directly from the usbdev in sysfs. Old versions of the driver
core and udev needed additional class devices to export device nodes.
These additional devices are difficult to handle in userspace, if
- information about USB interfaces must be available. One device contains
- the device node, the other device contains the interface data. Both
- devices are at the same level in sysfs (siblings) and one can't access
- the other. The device node created directly by the usbdev is the parent
- device of the interface and therefore easily accessible from the interface
- event.
+ information about USB interfaces must be available. One device
+ contains the device node, the other device contains the interface
+ data. Both devices are at the same level in sysfs (siblings) and one
+ can't access the other. The device node created directly by the
+ usb device is the parent device of the interface and therefore
+ easily accessible from the interface event.
- This option provides backward compatibility if needed.
+ This option provides backward compatibility for libusb device
+ nodes (lsusb) when usbfs is not used, and the following udev rule
+ doesn't exist:
+ SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \
+ NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
config USB_DYNAMIC_MINORS
bool "Dynamic USB minor allocation (EXPERIMENTAL)"
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 2d4fd53..dd34823 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -1,4 +1,5 @@
#include <linux/usb.h>
+#include <linux/usb/ch9.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -49,7 +50,7 @@
unsigned char *buffer0 = buffer;
struct usb_endpoint_descriptor *d;
struct usb_host_endpoint *endpoint;
- int n, i;
+ int n, i, j;
d = (struct usb_endpoint_descriptor *) buffer;
buffer += d->bLength;
@@ -84,6 +85,45 @@
memcpy(&endpoint->desc, d, n);
INIT_LIST_HEAD(&endpoint->urb_list);
+ /* If the bInterval value is outside the legal range,
+ * set it to a default value: 32 ms */
+ i = 0; /* i = min, j = max, n = default */
+ j = 255;
+ if (usb_endpoint_xfer_int(d)) {
+ i = 1;
+ switch (to_usb_device(ddev)->speed) {
+ case USB_SPEED_HIGH:
+ n = 9; /* 32 ms = 2^(9-1) uframes */
+ j = 16;
+ break;
+ default: /* USB_SPEED_FULL or _LOW */
+ /* For low-speed, 10 ms is the official minimum.
+ * But some "overclocked" devices might want faster
+ * polling so we'll allow it. */
+ n = 32;
+ break;
+ }
+ } else if (usb_endpoint_xfer_isoc(d)) {
+ i = 1;
+ j = 16;
+ switch (to_usb_device(ddev)->speed) {
+ case USB_SPEED_HIGH:
+ n = 9; /* 32 ms = 2^(9-1) uframes */
+ break;
+ default: /* USB_SPEED_FULL */
+ n = 6; /* 32 ms = 2^(6-1) frames */
+ break;
+ }
+ }
+ if (d->bInterval < i || d->bInterval > j) {
+ dev_warn(ddev, "config %d interface %d altsetting %d "
+ "endpoint 0x%X has an invalid bInterval %d, "
+ "changing to %d\n",
+ cfgno, inum, asnum,
+ d->bEndpointAddress, d->bInterval, n);
+ endpoint->desc.bInterval = n;
+ }
+
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
endpoint->extra = buffer;
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index f28af06..6042364 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -132,7 +132,7 @@
* where it's an output parameter representing the full speed limit.
* the usb spec fixes high speed bulk maxpacket at 512 bytes.
*/
- max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize);
+ max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* INT: limit 64 bytes full speed, 1024 high speed */
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 188c74a..46d0e52 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1369,12 +1369,12 @@
hs = !hs;
if (hs) {
dev->req->buf = dev->hs_config;
- len = le16_to_cpup (&dev->hs_config->wTotalLength);
+ len = le16_to_cpu(dev->hs_config->wTotalLength);
} else
#endif
{
dev->req->buf = dev->config;
- len = le16_to_cpup (&dev->config->wTotalLength);
+ len = le16_to_cpu(dev->config->wTotalLength);
}
((u8 *)dev->req->buf) [1] = type;
return len;
@@ -1885,7 +1885,7 @@
/* full or low speed config */
dev->config = (void *) kbuf;
- total = le16_to_cpup (&dev->config->wTotalLength);
+ total = le16_to_cpu(dev->config->wTotalLength);
if (!is_valid_config (dev->config) || total >= length)
goto fail;
kbuf += total;
@@ -1894,7 +1894,7 @@
/* optional high speed config */
if (kbuf [1] == USB_DT_CONFIG) {
dev->hs_config = (void *) kbuf;
- total = le16_to_cpup (&dev->hs_config->wTotalLength);
+ total = le16_to_cpu(dev->hs_config->wTotalLength);
if (!is_valid_config (dev->hs_config) || total >= length)
goto fail;
kbuf += total;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 52779c5..d975ecf 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2440,9 +2440,9 @@
tmp = 0;
-#define w_value le16_to_cpup (&u.r.wValue)
-#define w_index le16_to_cpup (&u.r.wIndex)
-#define w_length le16_to_cpup (&u.r.wLength)
+#define w_value le16_to_cpu(u.r.wValue)
+#define w_index le16_to_cpu(u.r.wIndex)
+#define w_length le16_to_cpu(u.r.wLength)
/* ack the irq */
writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index b394e63..c4975a6 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1651,9 +1651,9 @@
UDC_EP_NUM_REG = 0;
} while (UDC_IRQ_SRC_REG & UDC_SETUP);
-#define w_value le16_to_cpup (&u.r.wValue)
-#define w_index le16_to_cpup (&u.r.wIndex)
-#define w_length le16_to_cpup (&u.r.wLength)
+#define w_value le16_to_cpu(u.r.wValue)
+#define w_index le16_to_cpu(u.r.wIndex)
+#define w_length le16_to_cpu(u.r.wLength)
/* Delegate almost all control requests to the gadget driver,
* except for a handful of ch9 status/feature requests that
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 6ec8cf1..708657c 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -186,10 +186,14 @@
DEBUG("query OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
DEBUG ("%03d: %08x %08x %08x %08x\n", i,
- le32_to_cpup((__le32 *)&buf[i]),
- le32_to_cpup((__le32 *)&buf[i + 4]),
- le32_to_cpup((__le32 *)&buf[i + 8]),
- le32_to_cpup((__le32 *)&buf[i + 12]));
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 4])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 8])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 12])));
}
}
@@ -665,7 +669,7 @@
break;
case OID_PNP_QUERY_POWER:
DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
- le32_to_cpup((__le32 *) buf) - 1);
+ le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
/* only suspend is a real power state, and
* it can't be entered by OID_PNP_SET_POWER...
*/
@@ -704,10 +708,14 @@
DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
DEBUG ("%03d: %08x %08x %08x %08x\n", i,
- le32_to_cpup((__le32 *)&buf[i]),
- le32_to_cpup((__le32 *)&buf[i + 4]),
- le32_to_cpup((__le32 *)&buf[i + 8]),
- le32_to_cpup((__le32 *)&buf[i + 12]));
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 4])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 8])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 12])));
}
}
@@ -721,7 +729,8 @@
* PROMISCUOUS, DIRECTED,
* MULTICAST, ALL_MULTICAST, BROADCAST
*/
- *params->filter = (u16) le32_to_cpup((__le32 *)buf);
+ *params->filter = (u16) le32_to_cpu(get_unaligned(
+ (__le32 *)buf));
DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
__FUNCTION__, *params->filter);
@@ -771,7 +780,7 @@
* resuming, Windows forces a reset, and then SET_POWER D0.
* FIXME ... then things go batty; Windows wedges itself.
*/
- i = le32_to_cpup((__force __le32 *)buf);
+ i = le32_to_cpu(get_unaligned((__le32 *)buf));
DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
switch (i) {
case NdisDeviceStateD0:
@@ -1058,8 +1067,8 @@
return -ENOMEM;
tmp = (__le32 *) buf;
- MsgType = le32_to_cpup(tmp++);
- MsgLength = le32_to_cpup(tmp++);
+ MsgType = le32_to_cpu(get_unaligned(tmp++));
+ MsgLength = le32_to_cpu(get_unaligned(tmp++));
if (configNr >= RNDIS_MAX_CONFIGS)
return -ENOTSUPP;
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 216c9c9..bb9cc59 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -417,6 +417,8 @@
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ goto done;
/* undocumented erratum seen on at least rev D */
if ((ohci->flags & OHCI_QUIRK_AMD756)
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index d230ee7..54979c2 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1179,8 +1179,8 @@
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
-/* These are virtual windows driver CDs, which the zd1211rw driver automatically
- * converts into a WLAN devices. */
+/* These are virtual windows driver CDs, which the zd1211rw driver
+ * automatically converts into WLAN devices. */
UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
"ZyXEL",
"G-220F USB-WLAN Install",
@@ -1193,6 +1193,14 @@
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE ),
+/* SanDisk that has a second LUN for a driver ISO, reported by
+ * Ben Collins <bcollins@ubuntu.com> */
+UNUSUAL_DEV( 0x0781, 0x5406, 0x0000, 0xffff,
+ "SanDisk",
+ "U3 Cruzer Micro driver ISO",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI",
@@ -1271,6 +1279,15 @@
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Edward Chapman (taken from linux-usb mailing list)
+ Netac OnlyDisk Mini U2CV2 512MB USB 2.0 Flash Drive */
+UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999,
+ "Netac",
+ "USB Flash Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+
/* Patch by Stephan Walter <stephan.walter@epfl.ch>
* I don't know why, but it works... */
UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 7b0265d..861141b 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -558,7 +558,7 @@
if (!realdatastart)
realdatastart = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process data, errno %d\n",
- (int)-datapos);
+ (int)-realdatastart);
do_munmap(current->mm, textpos, text_len);
ret = realdatastart;
goto err;
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index a461f76..dc77fed 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -9,6 +9,9 @@
* to achieve effects such as fast scrolling by changing the origin.
*/
+#ifndef _LINUX_CONSOLE_STRUCT_H
+#define _LINUX_CONSOLE_STRUCT_H
+
#include <linux/wait.h>
#include <linux/vt.h>
#include <linux/workqueue.h>
@@ -130,3 +133,5 @@
#define CUR_DEFAULT CUR_UNDERLINE
#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
+
+#endif /* _LINUX_CONSOLE_STRUCT_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 45353d7..7a48525 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -218,10 +218,14 @@
DUMP_PREFIX_ADDRESS,
DUMP_PREFIX_OFFSET
};
-extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
- size_t linebuflen);
-extern void print_hex_dump(const char *level, int prefix_type,
- void *buf, size_t len);
+extern void hex_dump_to_buffer(const void *buf, size_t len,
+ int rowsize, int groupsize,
+ char *linebuf, size_t linebuflen, bool ascii);
+extern void print_hex_dump(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize, int groupsize,
+ void *buf, size_t len, bool ascii);
+extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ void *buf, size_t len);
#define hex_asc(x) "0123456789abcdef"[x]
#ifdef DEBUG
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d58e74b..693f0e6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1162,6 +1162,7 @@
/* Not implemented yet, only for 486*/
#define PF_STARTING 0x00000002 /* being created */
#define PF_EXITING 0x00000004 /* getting shut down */
+#define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */
#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */
#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */
#define PF_DUMPCORE 0x00000200 /* dumped core */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 0764c82..a0ad374 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -70,11 +70,8 @@
*/
static inline int kmalloc_index(size_t size)
{
- /*
- * We should return 0 if size == 0 but we use the smallest object
- * here for SLAB legacy reasons.
- */
- WARN_ON_ONCE(size == 0);
+ if (!size)
+ return 0;
if (size > KMALLOC_MAX_SIZE)
return -1;
@@ -153,13 +150,25 @@
#define SLUB_DMA 0
#endif
+
+/*
+ * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
+ *
+ * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
+ *
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
+ * Both make kfree a no-op.
+ */
+#define ZERO_SIZE_PTR ((void *)16)
+
+
static inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_alloc(s, flags);
} else
@@ -172,7 +181,7 @@
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_zalloc(s, flags);
} else
@@ -188,7 +197,7 @@
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_alloc_node(s, flags, node);
} else
diff --git a/kernel/exit.c b/kernel/exit.c
index 5b888c2..5c8ecba 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -892,13 +892,29 @@
if (unlikely(tsk->flags & PF_EXITING)) {
printk(KERN_ALERT
"Fixing recursive fault but reboot is needed!\n");
+ /*
+ * We can do this unlocked here. The futex code uses
+ * this flag just to verify whether the pi state
+ * cleanup has been done or not. In the worst case it
+ * loops once more. We pretend that the cleanup was
+ * done as there is no way to return. Either the
+ * OWNER_DIED bit is set by now or we push the blocked
+ * task into the wait for ever nirwana as well.
+ */
+ tsk->flags |= PF_EXITPIDONE;
if (tsk->io_context)
exit_io_context();
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
}
+ /*
+ * tsk->flags are checked in the futex code to protect against
+ * an exiting task cleaning up the robust pi futexes.
+ */
+ spin_lock_irq(&tsk->pi_lock);
tsk->flags |= PF_EXITING;
+ spin_unlock_irq(&tsk->pi_lock);
if (unlikely(in_atomic()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
@@ -912,7 +928,7 @@
}
group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) {
- hrtimer_cancel(&tsk->signal->real_timer);
+ hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
}
acct_collect(code, group_dead);
@@ -965,6 +981,12 @@
* Make sure we are holding no locks:
*/
debug_check_no_locks_held(tsk);
+ /*
+ * We can do this unlocked here. The futex code uses this flag
+ * just to verify whether the pi state cleanup has been done
+ * or not. In the worst case it loops once more.
+ */
+ tsk->flags |= PF_EXITPIDONE;
if (tsk->io_context)
exit_io_context();
diff --git a/kernel/futex.c b/kernel/futex.c
index b7ce15c..3b7f771 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -430,10 +430,6 @@
p = NULL;
goto out_unlock;
}
- if (p->exit_state != 0) {
- p = NULL;
- goto out_unlock;
- }
get_task_struct(p);
out_unlock:
rcu_read_unlock();
@@ -502,7 +498,7 @@
struct futex_q *this, *next;
struct plist_head *head;
struct task_struct *p;
- pid_t pid;
+ pid_t pid = uval & FUTEX_TID_MASK;
head = &hb->chain;
@@ -520,6 +516,8 @@
return -EINVAL;
WARN_ON(!atomic_read(&pi_state->refcount));
+ WARN_ON(pid && pi_state->owner &&
+ pi_state->owner->pid != pid);
atomic_inc(&pi_state->refcount);
*ps = pi_state;
@@ -530,15 +528,33 @@
/*
* We are the first waiter - try to look up the real owner and attach
- * the new pi_state to it, but bail out when the owner died bit is set
- * and TID = 0:
+ * the new pi_state to it, but bail out when TID = 0
*/
- pid = uval & FUTEX_TID_MASK;
- if (!pid && (uval & FUTEX_OWNER_DIED))
+ if (!pid)
return -ESRCH;
p = futex_find_get_task(pid);
- if (!p)
- return -ESRCH;
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ /*
+ * We need to look at the task state flags to figure out,
+ * whether the task is exiting. To protect against the do_exit
+ * change of the task flags, we do this protected by
+ * p->pi_lock:
+ */
+ spin_lock_irq(&p->pi_lock);
+ if (unlikely(p->flags & PF_EXITING)) {
+ /*
+ * The task is on the way out. When PF_EXITPIDONE is
+ * set, we know that the task has finished the
+ * cleanup:
+ */
+ int ret = (p->flags & PF_EXITPIDONE) ? -ESRCH : -EAGAIN;
+
+ spin_unlock_irq(&p->pi_lock);
+ put_task_struct(p);
+ return ret;
+ }
pi_state = alloc_pi_state();
@@ -551,7 +567,6 @@
/* Store the key for possible exit cleanups: */
pi_state->key = *key;
- spin_lock_irq(&p->pi_lock);
WARN_ON(!list_empty(&pi_state->list));
list_add(&pi_state->list, &p->pi_state_list);
pi_state->owner = p;
@@ -618,6 +633,8 @@
* preserve the owner died bit.)
*/
if (!(uval & FUTEX_OWNER_DIED)) {
+ int ret = 0;
+
newval = FUTEX_WAITERS | new_owner->pid;
/* Keep the FUTEX_WAITER_REQUEUED flag if it was set */
newval |= (uval & FUTEX_WAITER_REQUEUED);
@@ -625,10 +642,15 @@
pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
pagefault_enable();
+
if (curval == -EFAULT)
- return -EFAULT;
+ ret = -EFAULT;
if (curval != uval)
- return -EINVAL;
+ ret = -EINVAL;
+ if (ret) {
+ spin_unlock(&pi_state->pi_mutex.wait_lock);
+ return ret;
+ }
}
spin_lock_irq(&pi_state->owner->pi_lock);
@@ -1174,7 +1196,7 @@
#ifdef CONFIG_DEBUG_PI_LIST
this->list.plist.lock = &hb2->lock;
#endif
- }
+ }
this->key = key2;
get_futex_key_refs(&key2);
drop_count++;
@@ -1326,12 +1348,10 @@
/*
* Fixup the pi_state owner with current.
*
- * The cur->mm semaphore must be held, it is released at return of this
- * function.
+ * Must be called with hash bucket lock held and mm->sem held for non
+ * private futexes.
*/
-static int fixup_pi_state_owner(u32 __user *uaddr, struct rw_semaphore *fshared,
- struct futex_q *q,
- struct futex_hash_bucket *hb,
+static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
struct task_struct *curr)
{
u32 newtid = curr->pid | FUTEX_WAITERS;
@@ -1355,23 +1375,24 @@
list_add(&pi_state->list, &curr->pi_state_list);
spin_unlock_irq(&curr->pi_lock);
- /* Unqueue and drop the lock */
- unqueue_me_pi(q);
- if (fshared)
- up_read(fshared);
/*
* We own it, so we have to replace the pending owner
* TID. This must be atomic as we have preserve the
* owner died bit here.
*/
- ret = get_user(uval, uaddr);
+ ret = get_futex_value_locked(&uval, uaddr);
+
while (!ret) {
newval = (uval & FUTEX_OWNER_DIED) | newtid;
newval |= (uval & FUTEX_WAITER_REQUEUED);
+
+ pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr,
uval, newval);
+ pagefault_enable();
+
if (curval == -EFAULT)
- ret = -EFAULT;
+ ret = -EFAULT;
if (curval == uval)
break;
uval = curval;
@@ -1553,10 +1574,7 @@
*/
uaddr = q.pi_state->key.uaddr;
- /* mmap_sem and hash_bucket lock are unlocked at
- return of this function */
- ret = fixup_pi_state_owner(uaddr, fshared,
- &q, hb, curr);
+ ret = fixup_pi_state_owner(uaddr, &q, curr);
} else {
/*
* Catch the rare case, where the lock was released
@@ -1567,12 +1585,13 @@
if (rt_mutex_trylock(&q.pi_state->pi_mutex))
ret = 0;
}
- /* Unqueue and drop the lock */
- unqueue_me_pi(&q);
- if (fshared)
- up_read(fshared);
}
+ /* Unqueue and drop the lock */
+ unqueue_me_pi(&q);
+ if (fshared)
+ up_read(fshared);
+
debug_rt_mutex_free_waiter(&q.waiter);
return ret;
@@ -1688,7 +1707,7 @@
struct futex_hash_bucket *hb;
u32 uval, newval, curval;
struct futex_q q;
- int ret, lock_held, attempt = 0;
+ int ret, lock_taken, ownerdied = 0, attempt = 0;
if (refill_pi_state_cache())
return -ENOMEM;
@@ -1709,10 +1728,11 @@
if (unlikely(ret != 0))
goto out_release_sem;
+ retry_unlocked:
hb = queue_lock(&q, -1, NULL);
retry_locked:
- lock_held = 0;
+ ret = lock_taken = 0;
/*
* To avoid races, we attempt to take the lock here again
@@ -1728,43 +1748,44 @@
if (unlikely(curval == -EFAULT))
goto uaddr_faulted;
- /* We own the lock already */
+ /*
+ * Detect deadlocks. In case of REQUEUE_PI this is a valid
+ * situation and we return success to user space.
+ */
if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) {
- if (!detect && 0)
- force_sig(SIGKILL, current);
- /*
- * Normally, this check is done in user space.
- * In case of requeue, the owner may attempt to lock this futex,
- * even if the ownership has already been given by the previous
- * waker.
- * In the usual case, this is a case of deadlock, but not in case
- * of REQUEUE_PI.
- */
if (!(curval & FUTEX_WAITER_REQUEUED))
ret = -EDEADLK;
goto out_unlock_release_sem;
}
/*
- * Surprise - we got the lock. Just return
- * to userspace:
+ * Surprise - we got the lock. Just return to userspace:
*/
if (unlikely(!curval))
goto out_unlock_release_sem;
uval = curval;
+
/*
- * In case of a requeue, check if there already is an owner
- * If not, just take the futex.
+ * Set the WAITERS flag, so the owner will know it has someone
+ * to wake at next unlock
*/
- if ((curval & FUTEX_WAITER_REQUEUED) && !(curval & FUTEX_TID_MASK)) {
- /* set current as futex owner */
- newval = curval | current->pid;
- lock_held = 1;
- } else
- /* Set the WAITERS flag, so the owner will know it has someone
- to wake at next unlock */
- newval = curval | FUTEX_WAITERS;
+ newval = curval | FUTEX_WAITERS;
+
+ /*
+ * There are two cases, where a futex might have no owner (the
+ * owner TID is 0): OWNER_DIED or REQUEUE. We take over the
+ * futex in this case. We also do an unconditional take over,
+ * when the owner of the futex died.
+ *
+ * This is safe as we are protected by the hash bucket lock !
+ */
+ if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
+ /* Keep the OWNER_DIED and REQUEUE bits */
+ newval = (curval & ~FUTEX_TID_MASK) | current->pid;
+ ownerdied = 0;
+ lock_taken = 1;
+ }
pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
@@ -1775,8 +1796,13 @@
if (unlikely(curval != uval))
goto retry_locked;
- if (lock_held) {
- set_pi_futex_owner(hb, &q.key, curr);
+ /*
+ * We took the lock due to requeue or owner died take over.
+ */
+ if (unlikely(lock_taken)) {
+ /* For requeue we need to fixup the pi_futex */
+ if (curval & FUTEX_WAITER_REQUEUED)
+ set_pi_futex_owner(hb, &q.key, curr);
goto out_unlock_release_sem;
}
@@ -1787,34 +1813,40 @@
ret = lookup_pi_state(uval, hb, &q.key, &q.pi_state);
if (unlikely(ret)) {
- /*
- * There were no waiters and the owner task lookup
- * failed. When the OWNER_DIED bit is set, then we
- * know that this is a robust futex and we actually
- * take the lock. This is safe as we are protected by
- * the hash bucket lock. We also set the waiters bit
- * unconditionally here, to simplify glibc handling of
- * multiple tasks racing to acquire the lock and
- * cleanup the problems which were left by the dead
- * owner.
- */
- if (curval & FUTEX_OWNER_DIED) {
- uval = newval;
- newval = current->pid |
- FUTEX_OWNER_DIED | FUTEX_WAITERS;
+ switch (ret) {
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr,
- uval, newval);
- pagefault_enable();
+ case -EAGAIN:
+ /*
+ * Task is exiting and we just wait for the
+ * exit to complete.
+ */
+ queue_unlock(&q, hb);
+ if (fshared)
+ up_read(fshared);
+ cond_resched();
+ goto retry;
- if (unlikely(curval == -EFAULT))
+ case -ESRCH:
+ /*
+ * No owner found for this futex. Check if the
+ * OWNER_DIED bit is set to figure out whether
+ * this is a robust futex or not.
+ */
+ if (get_futex_value_locked(&curval, uaddr))
goto uaddr_faulted;
- if (unlikely(curval != uval))
+
+ /*
+ * We simply start over in case of a robust
+ * futex. The code above will take the futex
+ * and return happy.
+ */
+ if (curval & FUTEX_OWNER_DIED) {
+ ownerdied = 1;
goto retry_locked;
- ret = 0;
+ }
+ default:
+ goto out_unlock_release_sem;
}
- goto out_unlock_release_sem;
}
/*
@@ -1845,31 +1877,42 @@
down_read(fshared);
spin_lock(q.lock_ptr);
- /*
- * Got the lock. We might not be the anticipated owner if we
- * did a lock-steal - fix up the PI-state in that case.
- */
- if (!ret && q.pi_state->owner != curr)
- /* mmap_sem is unlocked at return of this function */
- ret = fixup_pi_state_owner(uaddr, fshared, &q, hb, curr);
- else {
+ if (!ret) {
+ /*
+ * Got the lock. We might not be the anticipated owner
+ * if we did a lock-steal - fix up the PI-state in
+ * that case:
+ */
+ if (q.pi_state->owner != curr)
+ ret = fixup_pi_state_owner(uaddr, &q, curr);
+ } else {
/*
* Catch the rare case, where the lock was released
- * when we were on the way back before we locked
- * the hash bucket.
+ * when we were on the way back before we locked the
+ * hash bucket.
*/
- if (ret && q.pi_state->owner == curr) {
- if (rt_mutex_trylock(&q.pi_state->pi_mutex))
- ret = 0;
+ if (q.pi_state->owner == curr &&
+ rt_mutex_trylock(&q.pi_state->pi_mutex)) {
+ ret = 0;
+ } else {
+ /*
+ * Paranoia check. If we did not take the lock
+ * in the trylock above, then we should not be
+ * the owner of the rtmutex, neither the real
+ * nor the pending one:
+ */
+ if (rt_mutex_owner(&q.pi_state->pi_mutex) == curr)
+ printk(KERN_ERR "futex_lock_pi: ret = %d "
+ "pi-mutex: %p pi-state %p\n", ret,
+ q.pi_state->pi_mutex.owner,
+ q.pi_state->owner);
}
- /* Unqueue and drop the lock */
- unqueue_me_pi(&q);
- if (fshared)
- up_read(fshared);
}
- if (!detect && ret == -EDEADLK && 0)
- force_sig(SIGKILL, current);
+ /* Unqueue and drop the lock */
+ unqueue_me_pi(&q);
+ if (fshared)
+ up_read(fshared);
return ret != -EINTR ? ret : -ERESTARTNOINTR;
@@ -1887,16 +1930,19 @@
* non-atomically. Therefore, if get_user below is not
* enough, we need to handle the fault ourselves, while
* still holding the mmap_sem.
+ *
+ * ... and hb->lock. :-) --ANK
*/
+ queue_unlock(&q, hb);
+
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, fshared,
attempt);
if (ret)
- goto out_unlock_release_sem;
- goto retry_locked;
+ goto out_release_sem;
+ goto retry_unlocked;
}
- queue_unlock(&q, hb);
if (fshared)
up_read(fshared);
@@ -1940,9 +1986,9 @@
goto out;
hb = hash_futex(&key);
+retry_unlocked:
spin_lock(&hb->lock);
-retry_locked:
/*
* To avoid races, try to do the TID -> 0 atomic transition
* again. If it succeeds then we can return without waking
@@ -2005,16 +2051,19 @@
* non-atomically. Therefore, if get_user below is not
* enough, we need to handle the fault ourselves, while
* still holding the mmap_sem.
+ *
+ * ... and hb->lock. --ANK
*/
+ spin_unlock(&hb->lock);
+
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, fshared,
attempt);
if (ret)
- goto out_unlock;
- goto retry_locked;
+ goto out;
+ goto retry_unlocked;
}
- spin_unlock(&hb->lock);
if (fshared)
up_read(fshared);
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 12879f6..a6fbb41 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -189,6 +189,19 @@
if (!waiter || !waiter->task)
goto out_unlock_pi;
+ /*
+ * Check the orig_waiter state. After we dropped the locks,
+ * the previous owner of the lock might have released the lock
+ * and made us the pending owner:
+ */
+ if (orig_waiter && !orig_waiter->task)
+ goto out_unlock_pi;
+
+ /*
+ * Drop out, when the task has no waiters. Note,
+ * top_waiter can be NULL, when we are in the deboosting
+ * mode!
+ */
if (top_waiter && (!task_has_pi_waiters(task) ||
top_waiter != task_top_pi_waiter(task)))
goto out_unlock_pi;
@@ -636,9 +649,16 @@
* all over without going into schedule to try
* to get the lock now:
*/
- if (unlikely(!waiter.task))
+ if (unlikely(!waiter.task)) {
+ /*
+ * Reset the return value. We might
+ * have returned with -EDEADLK and the
+ * owner released the lock while we
+ * were walking the pi chain.
+ */
+ ret = 0;
continue;
-
+ }
if (unlikely(ret))
break;
}
diff --git a/lib/hexdump.c b/lib/hexdump.c
index e6da5b7..473f5ae 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -16,42 +16,98 @@
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
* @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @linebuf: where to put the converted data
* @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
*
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
- * 16 bytes of input data converted to hex + ASCII output.
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
*
* Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
* to a hex + ASCII dump at the supplied memory location.
* The converted output is always NUL-terminated.
*
* E.g.:
- * hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf));
+ * hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ * linebuf, sizeof(linebuf), 1);
*
* example output buffer:
- * 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
*/
-void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
- size_t linebuflen)
+void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
+ int groupsize, char *linebuf, size_t linebuflen,
+ bool ascii)
{
const u8 *ptr = buf;
u8 ch;
int j, lx = 0;
+ int ascii_column;
- for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) {
- if (j && !(j % 4))
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ if (!len)
+ goto nil;
+ if (len > rowsize) /* limit to one line at a time */
+ len = rowsize;
+ if ((len % groupsize) != 0) /* no mixed size output */
+ groupsize = 1;
+
+ switch (groupsize) {
+ case 8: {
+ const u64 *ptr8 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%16.16llx ", (unsigned long long)*(ptr8 + j));
+ ascii_column = 17 * ngroups + 2;
+ break;
+ }
+
+ case 4: {
+ const u32 *ptr4 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%8.8x ", *(ptr4 + j));
+ ascii_column = 9 * ngroups + 2;
+ break;
+ }
+
+ case 2: {
+ const u16 *ptr2 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%4.4x ", *(ptr2 + j));
+ ascii_column = 5 * ngroups + 2;
+ break;
+ }
+
+ default:
+ for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen;
+ j++) {
+ ch = ptr[j];
+ linebuf[lx++] = hex_asc(ch >> 4);
+ linebuf[lx++] = hex_asc(ch & 0x0f);
linebuf[lx++] = ' ';
- ch = ptr[j];
- linebuf[lx++] = hex_asc(ch >> 4);
- linebuf[lx++] = hex_asc(ch & 0x0f);
+ }
+ ascii_column = 3 * rowsize + 2;
+ break;
}
- if ((lx + 2) < linebuflen) {
+ if (!ascii)
+ goto nil;
+
+ while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
linebuf[lx++] = ' ';
- linebuf[lx++] = ' ';
- }
- for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++)
+ for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++)
linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
+nil:
linebuf[lx++] = '\0';
}
EXPORT_SYMBOL(hex_dump_to_buffer);
@@ -59,46 +115,83 @@
/**
* print_hex_dump - print a text hex dump to syslog for a binary blob of data
* @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
* @prefix_type: controls whether prefix of an offset, address, or none
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @buf: data blob to dump
* @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
*
* Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
* to the kernel log at the specified kernel log level, with an optional
* leading prefix.
*
- * E.g.:
- * print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
+ * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
*
- * Example output using %DUMP_PREFIX_OFFSET:
- * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
- * Example output using %DUMP_PREFIX_ADDRESS:
- * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrstuvwxyz{|}~.
+ * E.g.:
+ * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
+ * 16, 1, frame->data, frame->len, 1);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
*/
-void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
+void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
+ int rowsize, int groupsize,
+ void *buf, size_t len, bool ascii)
{
u8 *ptr = buf;
int i, linelen, remaining = len;
- unsigned char linebuf[100];
+ unsigned char linebuf[200];
- for (i = 0; i < len; i += 16) {
- linelen = min(remaining, 16);
- remaining -= 16;
- hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf));
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ for (i = 0; i < len; i += rowsize) {
+ linelen = min(remaining, rowsize);
+ remaining -= rowsize;
+ hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
+ linebuf, sizeof(linebuf), ascii);
switch (prefix_type) {
case DUMP_PREFIX_ADDRESS:
- printk("%s%*p: %s\n", level,
+ printk("%s%s%*p: %s\n", level, prefix_str,
(int)(2 * sizeof(void *)), ptr + i, linebuf);
break;
case DUMP_PREFIX_OFFSET:
- printk("%s%.8x: %s\n", level, i, linebuf);
+ printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
break;
default:
- printk("%s%s\n", level, linebuf);
+ printk("%s%s%s\n", level, prefix_str, linebuf);
break;
}
}
}
EXPORT_SYMBOL(print_hex_dump);
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), with log level of KERN_DEBUG,
+ * rowsize of 16, groupsize of 1, and ASCII output included.
+ */
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ void *buf, size_t len)
+{
+ print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
+ buf, len, 1);
+}
+EXPORT_SYMBOL(print_hex_dump_bytes);
diff --git a/lib/kobject.c b/lib/kobject.c
index fc5f3f6..ac15206 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -202,14 +202,14 @@
/* be noisy on error issues */
if (error == -EEXIST)
- printk("kobject_add failed for %s with -EEXIST, "
- "don't try to register things with the "
- "same name in the same directory.\n",
+ printk(KERN_ERR "kobject_add failed for %s with "
+ "-EEXIST, don't try to register things with "
+ "the same name in the same directory.\n",
kobject_name(kobj));
else
- printk("kobject_add failed for %s (%d)\n",
+ printk(KERN_ERR "kobject_add failed for %s (%d)\n",
kobject_name(kobj), error);
- dump_stack();
+ dump_stack();
}
return error;
diff --git a/mm/shmem.c b/mm/shmem.c
index e537317..b6aae2b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -967,6 +967,8 @@
*nodelist++ = '\0';
if (nodelist_parse(nodelist, *policy_nodes))
goto out;
+ if (!nodes_subset(*policy_nodes, node_online_map))
+ goto out;
}
if (!strcmp(value, "default")) {
*policy = MPOL_DEFAULT;
diff --git a/mm/slab.c b/mm/slab.c
index 2e71a32..6d65cf4 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3539,7 +3539,7 @@
check_irq_off();
objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
- if (use_alien_caches && cache_free_alien(cachep, objp))
+ if (cache_free_alien(cachep, objp))
return;
if (likely(ac->avail < ac->limit)) {
diff --git a/mm/slub.c b/mm/slub.c
index 51663a3..c9ab688 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2241,7 +2241,7 @@
if (s)
return slab_alloc(s, flags, -1, __builtin_return_address(0));
- return NULL;
+ return ZERO_SIZE_PTR;
}
EXPORT_SYMBOL(__kmalloc);
@@ -2252,16 +2252,20 @@
if (s)
return slab_alloc(s, flags, node, __builtin_return_address(0));
- return NULL;
+ return ZERO_SIZE_PTR;
}
EXPORT_SYMBOL(__kmalloc_node);
#endif
size_t ksize(const void *object)
{
- struct page *page = get_object_page(object);
+ struct page *page;
struct kmem_cache *s;
+ if (object == ZERO_SIZE_PTR)
+ return 0;
+
+ page = get_object_page(object);
BUG_ON(!page);
s = page->slab;
BUG_ON(!s);
@@ -2293,7 +2297,13 @@
struct kmem_cache *s;
struct page *page;
- if (!x)
+ /*
+ * This has to be an unsigned comparison. According to Linus
+ * some gcc version treat a pointer as a signed entity. Then
+ * this comparison would be true for all "negative" pointers
+ * (which would cover the whole upper half of the address space).
+ */
+ if ((unsigned long)x <= (unsigned long)ZERO_SIZE_PTR)
return;
page = virt_to_head_page(x);
@@ -2398,12 +2408,12 @@
void *ret;
size_t ks;
- if (unlikely(!p))
+ if (unlikely(!p || p == ZERO_SIZE_PTR))
return kmalloc(new_size, flags);
if (unlikely(!new_size)) {
kfree(p);
- return NULL;
+ return ZERO_SIZE_PTR;
}
ks = ksize(p);
@@ -2652,7 +2662,7 @@
struct kmem_cache *s = get_slab(size, gfpflags);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return slab_alloc(s, gfpflags, -1, caller);
}
@@ -2663,7 +2673,7 @@
struct kmem_cache *s = get_slab(size, gfpflags);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return slab_alloc(s, gfpflags, node, caller);
}
diff --git a/mm/sparse.c b/mm/sparse.c
index 545e4d3..e03b39f 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -240,6 +240,27 @@
return NULL;
}
+/*
+ * Allocate the accumulated non-linear sections, allocate a mem_map
+ * for each and record the physical to section mapping.
+ */
+void __init sparse_init(void)
+{
+ unsigned long pnum;
+ struct page *map;
+
+ for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+ if (!valid_section_nr(pnum))
+ continue;
+
+ map = sparse_early_mem_map_alloc(pnum);
+ if (!map)
+ continue;
+ sparse_init_one_section(__nr_to_section(pnum), pnum, map);
+ }
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
{
struct page *page, *ret;
@@ -280,27 +301,6 @@
}
/*
- * Allocate the accumulated non-linear sections, allocate a mem_map
- * for each and record the physical to section mapping.
- */
-void __init sparse_init(void)
-{
- unsigned long pnum;
- struct page *map;
-
- for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
- if (!valid_section_nr(pnum))
- continue;
-
- map = sparse_early_mem_map_alloc(pnum);
- if (!map)
- continue;
- sparse_init_one_section(__nr_to_section(pnum), pnum, map);
- }
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-/*
* returns the number of sections whose mem_maps were properly
* set. If this is <=0, then that means that the passed-in
* map was not consumed and must be freed.
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index e216d49..aea90d3 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1,14 +1,15 @@
#!/usr/bin/perl -w
# (c) 2001, Dave Jones. <davej@codemonkey.org.uk> (the file handling bit)
-# (c) 2005, Joel Scohpp <jschopp@austin.ibm.com> (the ugly bit)
+# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
# (c) 2007, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite, etc)
# Licensed under the terms of the GNU GPL License version 2
use strict;
my $P = $0;
+$P =~ s@.*/@@g;
-my $V = '0.01';
+my $V = '0.04';
use Getopt::Long qw(:config no_auto_abbrev);
@@ -26,7 +27,7 @@
my $exit = 0;
if ($#ARGV < 0) {
- print "usage: patchstylecheckemail.pl [options] patchfile\n";
+ print "usage: $P [options] patchfile\n";
print "version: $V\n";
print "options: -q => quiet\n";
print " --no-tree => run without a kernel tree\n";
@@ -38,7 +39,8 @@
exit(2);
}
-my @deprecated = ();
+my @dep_includes = ();
+my @dep_functions = ();
my $removal = 'Documentation/feature-removal-schedule.txt';
if ($tree && -f $removal) {
open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
@@ -46,22 +48,27 @@
if (/^Files:\s+(.*\S)/) {
for my $file (split(/[, ]+/, $1)) {
if ($file =~ m@include/(.*)@) {
- push(@deprecated, $1);
+ push(@dep_includes, $1);
}
}
+
+ } elsif (/^Funcs:\s+(.*\S)/) {
+ for my $func (split(/[, ]+/, $1)) {
+ push(@dep_functions, $func);
+ }
}
}
}
-my @lines = ();
+my @rawlines = ();
while (<>) {
chomp;
- push(@lines, $_);
+ push(@rawlines, $_);
if (eof(ARGV)) {
- if (!process($ARGV, @lines)) {
+ if (!process($ARGV, @rawlines)) {
$exit = 1;
}
- @lines = ();
+ @rawlines = ();
}
}
@@ -99,6 +106,130 @@
return $res;
}
+sub line_stats {
+ my ($line) = @_;
+
+ # Drop the diff line leader and expand tabs
+ $line =~ s/^.//;
+ $line = expand_tabs($line);
+
+ # Pick the indent from the front of the line.
+ my ($white) = ($line =~ /^(\s*)/);
+
+ return (length($line), length($white));
+}
+
+sub sanitise_line {
+ my ($line) = @_;
+
+ my $res = '';
+ my $l = '';
+
+ my $quote = '';
+
+ foreach my $c (split(//, $line)) {
+ if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
+ if ($quote eq '') {
+ $quote = $c;
+ $res .= $c;
+ $l = $c;
+ next;
+ } elsif ($quote eq $c) {
+ $quote = '';
+ }
+ }
+ if ($quote && $c ne "\t") {
+ $res .= "X";
+ } else {
+ $res .= $c;
+ }
+
+ $l = $c;
+ }
+
+ return $res;
+}
+
+sub ctx_block_get {
+ my ($linenr, $remain, $outer) = @_;
+ my $line;
+ my $start = $linenr - 1;
+ my $blk = '';
+ my @o;
+ my @c;
+ my @res = ();
+
+ for ($line = $start; $remain > 0; $line++) {
+ next if ($rawlines[$line] =~ /^-/);
+ $remain--;
+
+ $blk .= $rawlines[$line];
+
+ @o = ($blk =~ /\{/g);
+ @c = ($blk =~ /\}/g);
+
+ if (!$outer || (scalar(@o) - scalar(@c)) == 1) {
+ push(@res, $rawlines[$line]);
+ }
+
+ last if (scalar(@o) == scalar(@c));
+ }
+
+ return @res;
+}
+sub ctx_block_outer {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 1);
+}
+sub ctx_block {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 0);
+}
+
+sub ctx_locate_comment {
+ my ($first_line, $end_line) = @_;
+
+ # Catch a comment on the end of the line itself.
+ my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
+ return $current_comment if (defined $current_comment);
+
+ # Look through the context and try and figure out if there is a
+ # comment.
+ my $in_comment = 0;
+ $current_comment = '';
+ for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
+ my $line = $rawlines[$linenr - 1];
+ #warn " $line\n";
+ if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
+ $in_comment = 1;
+ }
+ if ($line =~ m@/\*@) {
+ $in_comment = 1;
+ }
+ if (!$in_comment && $current_comment ne '') {
+ $current_comment = '';
+ }
+ $current_comment .= $line . "\n" if ($in_comment);
+ if ($line =~ m@\*/@) {
+ $in_comment = 0;
+ }
+ }
+
+ chomp($current_comment);
+ return($current_comment);
+}
+sub ctx_has_comment {
+ my ($first_line, $end_line) = @_;
+ my $cmt = ctx_locate_comment($first_line, $end_line);
+
+ ##print "LINE: $rawlines[$end_line - 1 ]\n";
+ ##print "CMMT: $cmt\n";
+
+ return ($cmt ne '');
+}
+
sub cat_vet {
my ($vet) = @_;
@@ -116,7 +247,7 @@
my $prevline="";
my $stashline="";
- my $lineforcounting='';
+ my $length;
my $indent;
my $previndent=0;
my $stashindent=0;
@@ -139,13 +270,14 @@
#extract the filename as it passes
if ($line=~/^\+\+\+\s+(\S+)/) {
$realfile=$1;
+ $realfile =~ s@^[^/]*/@@;
$in_comment = 0;
next;
}
#extract the line range in the file after the patch is applied
if ($line=~/^\@\@ -\d+,\d+ \+(\d+)(,(\d+))? \@\@/) {
$is_patch = 1;
- $first_line = 1;
+ $first_line = $linenr + 1;
$in_comment = 0;
$realline=$1-1;
if (defined $2) {
@@ -156,10 +288,11 @@
next;
}
-#track the line number as we move through the hunk
- if ($line=~/^[ \+]/) {
+# track the line number as we move through the hunk, note that
+# new versions of GNU diff omit the leading space on completely
+# blank context lines so we need to count that too.
+ if ($line =~ /^( |\+|$)/) {
$realline++;
- $realcnt-- if ($realcnt != 0);
# track any sort of multi-line comment. Obviously if
# the added text or context do not include the whole
@@ -168,7 +301,7 @@
# Guestimate if this is a continuing comment. If this
# is the start of a diff block and this line starts
# ' *' then it is very likely a comment.
- if ($first_line and $line =~ m@^.\s*\*@) {
+ if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
$in_comment = 1;
}
if ($line =~ m@/\*@) {
@@ -178,23 +311,20 @@
$in_comment = 0;
}
- $lineforcounting = $line;
- $lineforcounting =~ s/^\+//;
- $lineforcounting = expand_tabs($lineforcounting);
-
- my ($white) = ($lineforcounting =~ /^(\s*)/);
- $indent = length($white);
+ # Measure the line length and indent.
+ ($length, $indent) = line_stats($line);
# Track the previous line.
($prevline, $stashline) = ($stashline, $line);
($previndent, $stashindent) = ($stashindent, $indent);
- $first_line = 0;
}
+ $realcnt-- if ($realcnt != 0);
#make up the handle for any error we report on this line
- $here = "PATCH: $ARGV:$linenr:";
- $here .= "\nFILE: $realfile:$realline:" if ($realcnt != 0);
+ $here = "#$linenr: ";
+ $here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
+ my $hereline = "$here\n$line\n";
my $herecurr = "$here\n$line\n\n";
my $hereprev = "$here\n$prevline\n$line\n\n";
@@ -203,6 +333,8 @@
$signoff++;
} elsif ($line =~ /^\s*signed-off-by:/i) {
+ # This is a signoff, if ugly, so do not double report.
+ $signoff++;
if (!($line =~ /^\s*Signed-off-by:/)) {
print "use Signed-off-by:\n";
print "$herecurr";
@@ -215,21 +347,28 @@
}
}
-#ignore lines not being added
- if ($line=~/^[^\+]/) {next;}
+# Check for wrappage within a valid hunk of the file
+ if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
+ print "patch seems to be corrupt (line wrapped?) [$realcnt]\n";
+ print "$herecurr";
+ $clean = 0;
+ }
-# check we are in a valid source file *.[hcsS] if not then ignore this hunk
- next if ($realfile !~ /\.[hcsS]$/);
+#ignore lines being removed
+ if ($line=~/^-/) {next;}
+
+# check we are in a valid source file if not then ignore this hunk
+ next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
#trailing whitespace
- if ($line=~/\S\s+$/) {
+ if ($line=~/\+.*\S\s+$/) {
my $herevet = "$here\n" . cat_vet($line) . "\n\n";
print "trailing whitespace\n";
print "$herevet";
$clean = 0;
}
#80 column limit
- if (!($prevline=~/\/\*\*/) && length($lineforcounting) > 80) {
+ if ($line =~ /^\+/ && !($prevline=~/\/\*\*/) && $length > 80) {
print "line over 80 characters\n";
print "$herecurr";
$clean = 0;
@@ -253,19 +392,59 @@
#
next if ($in_comment);
-# no C99 // comments
- if ($line =~ m@//@ and !($line =~ m@\".*//.*\"@)) {
- print "do not use C99 // comments\n";
- print "$herecurr";
- $clean = 0;
- }
-
# Remove comments from the line before processing.
$line =~ s@/\*.*\*/@@g;
$line =~ s@/\*.*@@;
$line =~ s@.*\*/@@;
+
+ #
+ # Checks which may be anchored in the context.
+ #
+
+ # Check for switch () and associated case and default
+ # statements should be at the same indent.
+ if ($line=~/\bswitch\s*\(.*\)/) {
+ my $err = '';
+ my $sep = '';
+ my @ctx = ctx_block_outer($linenr, $realcnt);
+ shift(@ctx);
+ for my $ctx (@ctx) {
+ my ($clen, $cindent) = line_stats($ctx);
+ if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
+ $indent != $cindent) {
+ $err .= "$sep$ctx\n";
+ $sep = '';
+ } else {
+ $sep = "[...]\n";
+ }
+ }
+ if ($err ne '') {
+ print "switch and case should be at the same indent\n";
+ print "$here\n$line\n$err\n";
+ $clean = 0;
+ }
+ }
+
+#ignore lines not being added
+ if ($line=~/^[^\+]/) {next;}
+
+ #
+ # Checks which are anchored on the added line.
+ #
+
+# no C99 // comments
+ if ($line =~ m{//}) {
+ print "do not use C99 // comments\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ # Remove C99 comments.
$line =~ s@//.*@@;
+ # Standardise the strings and chars within the input
+ # to simplify matching.
+ $line = sanitise_line($line);
+
#EXPORT_SYMBOL should immediately follow its function closing }.
if (($line =~ /EXPORT_SYMBOL.*\(.*\)/) ||
($line =~ /EXPORT_UNUSED_SYMBOL.*\(.*\)/)) {
@@ -293,8 +472,28 @@
}
# * goes on variable not on type
- if ($line=~/[A-Za-z\d_]+\* [A-Za-z\d_]+/) {
- print "\"foo* bar\" should be \"foo *bar\"\n";
+ my $type = '(?:char|short|int|long|unsigned|float|double|' .
+ 'struct\s+[A-Za-z\d_]+|' .
+ 'union\s+[A-Za-z\d_]+)';
+
+ if ($line =~ m{[A-Za-z\d_]+(\*+) [A-Za-z\d_]+}) {
+ print "\"foo$1 bar\" should be \"foo $1bar\"\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ if ($line =~ m{$type (\*) [A-Za-z\d_]+} ||
+ $line =~ m{[A-Za-z\d_]+ (\*\*+) [A-Za-z\d_]+}) {
+ print "\"foo $1 bar\" should be \"foo $1bar\"\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ if ($line =~ m{\([A-Za-z\d_\s]+[A-Za-z\d_](\*+)\)}) {
+ print "\"(foo$1)\" should be \"(foo $1)\"\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ if ($line =~ m{\([A-Za-z\d_\s]+[A-Za-z\d_]\s+(\*+)\s+\)}) {
+ print "\"(foo $1 )\" should be \"(foo $1)\"\n";
print "$herecurr";
$clean = 0;
}
@@ -306,11 +505,29 @@
# $clean = 0;
# }
-# printk should use KERN_* levels
+# printk should use KERN_* levels. Note that follow on printk's on the
+# same line do not need a level, so we use the current block context
+# to try and find and validate the current printk. In summary the current
+# printk includes all preceeding printk's which have no newline on the end.
+# we assume the first bad printk is the one to report.
if ($line =~ /\bprintk\((?!KERN_)/) {
- print "printk() should include KERN_ facility level\n";
- print "$herecurr";
- $clean = 0;
+ my $ok = 0;
+ for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
+ #print "CHECK<$lines[$ln - 1]\n";
+ # we have a preceeding printk if it ends
+ # with "\n" ignore it, else it is to blame
+ if ($lines[$ln - 1] =~ m{\bprintk\(}) {
+ if ($rawlines[$ln - 1] !~ m{\\n"}) {
+ $ok = 1;
+ }
+ last;
+ }
+ }
+ if ($ok == 0) {
+ print "printk() should include KERN_ facility level\n";
+ print "$herecurr";
+ $clean = 0;
+ }
}
#function brace can't be on same line, except for #defines of do while, or if closed on same line
@@ -320,86 +537,91 @@
print "$herecurr";
$clean = 0;
}
+ # Note we expand the line with the leading + as the real
+ # line will be displayed with the leading + and the tabs
+ # will therefore also expand that way.
my $opline = $line;
- $opline =~ s/^.//;
+ $opline = expand_tabs($opline);
+ $opline =~ s/^./ /;
if (!($line=~/\#\s*include/)) {
# Check operator spacing.
my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline);
+ my $off = 0;
for (my $n = 0; $n < $#elements; $n += 2) {
- # $wN says we have white-space before or after
- # $sN says we have a separator before or after
- # $oN says we have another operator before or after
- my $w1 = $elements[$n] =~ /\s$/;
- my $s1 = $elements[$n] =~ /(\[|\(|\s)$/;
- my $o1 = $elements[$n] eq '';
+ $off += length($elements[$n]);
+
+ my $a = '';
+ $a = 'V' if ($elements[$n] ne '');
+ $a = 'W' if ($elements[$n] =~ /\s$/);
+ $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
+ $a = 'O' if ($elements[$n] eq '');
+ $a = 'E' if ($elements[$n] eq '' && $n == 0);
+
my $op = $elements[$n + 1];
- my $w2 = 1;
- my $s2 = 1;
- my $o2 = 0;
- # If we have something after the operator handle it.
+
+ my $c = '';
if (defined $elements[$n + 2]) {
- $w2 = $elements[$n + 2] =~ /^\s/;
- $s2 = $elements[$n + 2] =~ /^(\s|\)|\]|;)/;
- $o2 = $elements[$n + 2] eq '';
+ $c = 'V' if ($elements[$n + 2] ne '');
+ $c = 'W' if ($elements[$n + 2] =~ /^\s/);
+ $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
+ $c = 'O' if ($elements[$n + 2] eq '');
+ } else {
+ $c = 'E';
}
- # Generate the context.
- my $at = "here: ";
- for (my $m = $n; $m >= 0; $m--) {
- if ($elements[$m] ne '') {
- $at .= $elements[$m];
- last;
- }
+ # Pick up the preceeding and succeeding characters.
+ my $ca = substr($opline, $off - 1, 1);
+ my $cc = '';
+ if (length($opline) > ($off + length($elements[$n]))) {
+ $cc = substr($opline, $off + 1 + length($elements[$n]), 1);
}
- $at .= $op;
- for (my $m = $n + 2; defined $elements[$m]; $m++) {
- if ($elements[$m] ne '') {
- $at .= $elements[$m];
- last;
- }
- }
+
+ my $ctx = "${a}x${c}";
+
+ my $at = "(ctx:$ctx)";
+
+ my $ptr = (" " x $off) . "^";
+ my $hereptr = "$hereline$ptr\n\n";
##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
- # Skip things apparently in quotes.
- next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
# We need ; as an operator. // is a comment.
if ($op eq ';' or $op eq '//') {
# -> should have no spaces
} elsif ($op eq '->') {
- if ($s1 or $s2) {
+ if ($ctx =~ /Wx.|.xW/) {
print "no spaces around that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# , must have a space on the right.
} elsif ($op eq ',') {
- if (!$s2) {
+ if ($ctx !~ /.xW|.xE/) {
print "need space after that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# unary ! and unary ~ are allowed no space on the right
} elsif ($op eq '!' or $op eq '~') {
- if (!$s1 && !$o1) {
+ if ($ctx !~ /[WOEB]x./) {
print "need space before that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
- if ($s2) {
+ if ($ctx =~ /.xW/) {
print "no space after that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# unary ++ and unary -- are allowed no space on one side.
} elsif ($op eq '++' or $op eq '--') {
- if (($s1 && $s2) || ((!$s1 && !$o1) && (!$s2 && !$o2))) {
+ if ($ctx !~ /[WOB]x[^W]|[^W]x[WOB]/) {
print "need space one side of that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
@@ -415,15 +637,28 @@
#
# - is the same
#
- # * is the same only adding:
+ } elsif ($op eq '&' or $op eq '-') {
+ if ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]/) {
+ print "need space before that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # * is the same as & only adding:
# type:
# (foo *)
# (foo **)
#
- } elsif ($op eq '&' or $op eq '-' or $op eq '*') {
- if ($w2 and !$w1) {
+ } elsif ($op eq '*') {
+ if ($ca eq '*') {
+ if ($cc =~ /\s/) {
+ print "no space after that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+ } elsif ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB/) {
print "need space before that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
@@ -431,18 +666,19 @@
} elsif ($op eq '<<' or $op eq '>>' or $op eq '+' or $op eq '/' or
$op eq '^' or $op eq '|')
{
- if ($s1 != $s2) {
+ if ($ctx !~ /VxV|WxW|VxE|WxE/) {
print "need consistent spacing around '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
# All the others need spaces both sides.
- } elsif (!$s1 or !$s2) {
+ } elsif ($ctx !~ /[EW]x[WE]/) {
print "need spaces around that '$op' $at\n";
- print "$herecurr";
+ print "$hereptr";
$clean = 0;
}
+ $off += length($elements[$n + 1]);
}
}
@@ -454,7 +690,7 @@
}
#goto labels aren't indented, allow a single space however
- if ($line=~/^.\s+[A-Za-z\d_]+:/ and
+ if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
!($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
print "labels should not be indented\n";
print "$herecurr";
@@ -462,15 +698,16 @@
}
# Need a space before open parenthesis after if, while etc
- if ($line=~/(if|while|for|switch)\(/) {
+ if ($line=~/\b(if|while|for|switch)\(/) {
print "need a space before the open parenthesis\n";
print "$herecurr";
$clean = 0;
}
# Check for illegal assignment in if conditional.
- if ($line=~/(if|while)\s*\(.*[^<>!=]=[^=].*\)/) {
- print "do not use assignment in if condition\n";
+ if ($line=~/\b(if|while)\s*\(.*[^<>!=]=[^=].*\)/) {
+ #next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
+ print "do not use assignment in condition\n";
print "$herecurr";
$clean = 0;
}
@@ -484,17 +721,6 @@
$clean = 0;
}
- # Check for switch () {<nl>case, these must be at the
- # same indent. We will only catch the first one, as our
- # context is very small but people tend to be consistent
- # so we will catch them out more often than not.
- if ($prevline=~/\s*switch\s*\(.*\)/ and $line=~/\s*case\s+/
- and $previndent != $indent) {
- print "switch and case should be at the same indent\n";
- print "$hereprev";
- $clean = 0;
- }
-
#studly caps, commented out until figure out how to distinguish between use of existing and adding new
# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
# print "No studly caps, use _\n";
@@ -520,11 +746,11 @@
}
#if/while/etc brace do not go on next line, unless #defining a do while loop, or if that brace on the next line is for something else
- if ($prevline=~/(if|while|for|switch)\s*\(/) {
+ if ($prevline=~/\b(if|while|for|switch)\s*\(/) {
my @opened = $prevline=~/\(/g;
my @closed = $prevline=~/\)/g;
my $nr_line = $linenr;
- my $remaining = $realcnt;
+ my $remaining = $realcnt - 1;
my $next_line = $line;
my $extra_lines = 0;
my $display_segment = $prevline;
@@ -540,10 +766,10 @@
@closed = $prevline=~/\)/g;
}
- if (($prevline=~/(if|while|for|switch)\s*\(.*\)\s*$/) and ($next_line=~/{/) and
- !($next_line=~/(if|while|for)/) and !($next_line=~/\#define.*do.*while/)) {
+ if (($prevline=~/\b(if|while|for|switch)\s*\(.*\)\s*$/) and ($next_line=~/{/) and
+ !($next_line=~/\b(if|while|for)/) and !($next_line=~/\#define.*do.*while/)) {
print "That { should be on the previous line\n";
- print "$display_segment\n$next_line\n\n";
+ print "$here\n$display_segment\n$next_line\n\n";
$clean = 0;
}
}
@@ -558,7 +784,7 @@
}
# don't include deprecated include files
- for my $inc (@deprecated) {
+ for my $inc (@dep_includes) {
if ($line =~ m@\#\s*include\s*\<$inc>@) {
print "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n";
print "$herecurr";
@@ -566,9 +792,56 @@
}
}
-# don't use kernel_thread()
- if ($line =~ /\bkernel_thread\b/) {
- print "Don't use kernel_thread(), use kthread(): see Documentation/feature-removal-schedule.txt\n";
+# don't use deprecated functions
+ for my $func (@dep_functions) {
+ if ($line =~ /\b$func\b/) {
+ print "Don't use $func(): see Documentation/feature-removal-schedule.txt\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+# no volatiles please
+ if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
+ print "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# warn about #if 0
+ if ($line =~ /^.#\s*if\s+0\b/) {
+ print "#if 0 -- if this code redundant remove it\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# warn about #ifdefs in C files
+# if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+# print "#ifdef in C files should be avoided\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+# check for spinlock_t definitions without a comment.
+ if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
+ my $which = $1;
+ if (!ctx_has_comment($first_line, $linenr)) {
+ print "$1 definition without comment\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+# check for memory barriers without a comment.
+ if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
+ if (!ctx_has_comment($first_line, $linenr)) {
+ print "memory barrier without comment\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+# check of hardware specific defines
+ if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@) {
+ print "architecture specific defines should be avoided\n";
print "$herecurr";
$clean = 0;
}