From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org,
Andrew Morton <akpm@linux-foundation.org>,
torvalds@linux-foundation.org, stable@kernel.org
Subject: Re: Linux 2.6.27.21
Date: Sat, 2 May 2009 13:05:28 -0700 [thread overview]
Message-ID: <20090502200528.GD7287@kroah.com> (raw)
In-Reply-To: <20090502200515.GC7287@kroah.com>
diff --git a/Makefile b/Makefile
index 0664c76..d3b7fc8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 27
-EXTRAVERSION = .21
+EXTRAVERSION = .22
NAME = Trembling Tortoise
# *DOCUMENTATION*
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 6d406c5..9696cc3 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -27,7 +27,7 @@
PPC_LONG "1b,4b,2b,4b\n" \
".previous" \
: "=&r" (oldval), "=&r" (ret) \
- : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \
+ : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
: "cr0", "memory")
static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
@@ -47,19 +47,19 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
switch (op) {
case FUTEX_OP_SET:
- __futex_atomic_op("", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_ADD:
- __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_OR:
- __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_ANDN:
- __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
case FUTEX_OP_XOR:
- __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg);
+ __futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
break;
default:
ret = -ENOSYS;
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 101ed87..ae1c5b5 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -309,6 +309,25 @@ static inline void prefetchw(const void *x)
#define HAVE_ARCH_PICK_MMAP_LAYOUT
#endif
+#ifdef CONFIG_PPC64
+static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
+{
+ unsigned long sp;
+
+ if (is_32)
+ sp = regs->gpr[1] & 0x0ffffffffUL;
+ else
+ sp = regs->gpr[1];
+
+ return sp;
+}
+#else
+static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
+{
+ return regs->gpr[1];
+}
+#endif
+
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_PROCESSOR_H */
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index a54405e..00b5078 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -26,12 +26,12 @@ int show_unhandled_signals = 0;
* Allocate space for the signal frame
*/
void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
- size_t frame_size)
+ size_t frame_size, int is_32)
{
unsigned long oldsp, newsp;
/* Default to using normal stack */
- oldsp = regs->gpr[1];
+ oldsp = get_clean_sp(regs, is_32);
/* Check for alt stack */
if ((ka->sa.sa_flags & SA_ONSTACK) &&
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h
index 28f4b9f..f77d502 100644
--- a/arch/powerpc/kernel/signal.h
+++ b/arch/powerpc/kernel/signal.h
@@ -13,7 +13,7 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
- size_t frame_size);
+ size_t frame_size, int is_32);
extern void restore_sigmask(sigset_t *set);
extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index a6a4310..9084a27 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -836,7 +836,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
/* Set up Signal Frame */
/* Put a Real Time Context onto stack */
- rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+ rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1);
addr = rt_sf;
if (unlikely(rt_sf == NULL))
goto badframe;
@@ -1170,7 +1170,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
unsigned long newsp = 0;
/* Set up Signal Frame */
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ka, regs, sizeof(*frame), 1);
if (unlikely(frame == NULL))
goto badframe;
sc = (struct sigcontext __user *) &frame->sctx;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index e4acdbd..3de15b0 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -404,7 +404,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
unsigned long newsp = 0;
long err = 0;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ka, regs, sizeof(*frame), 0);
if (unlikely(frame == NULL))
goto badframe;
diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c
index 8c3c25f..a99dbbe 100644
--- a/arch/x86/boot/memory.c
+++ b/arch/x86/boot/memory.c
@@ -27,13 +27,14 @@ static int detect_memory_e820(void)
do {
size = sizeof(struct e820entry);
- /* Important: %edx is clobbered by some BIOSes,
- so it must be either used for the error output
+ /* Important: %edx and %esi are clobbered by some BIOSes,
+ so they must be either used for the error output
or explicitly marked clobbered. */
asm("int $0x15; setc %0"
: "=d" (err), "+b" (next), "=a" (id), "+c" (size),
"=m" (*desc)
- : "D" (desc), "d" (SMAP), "a" (0xe820));
+ : "D" (desc), "d" (SMAP), "a" (0xe820)
+ : "esi");
/* BIOSes which terminate the chain with CF = 1 as opposed
to %ebx = 0 don't always report the SMAP signature on
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index cb7d3b6..26baabd 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -45,6 +45,32 @@ u64 mtrr_tom2;
static int mtrr_show;
module_param_named(show, mtrr_show, bool, 0);
+/**
+ * BIOS is expected to clear MtrrFixDramModEn bit, see for example
+ * "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
+ * Opteron Processors" (26094 Rev. 3.30 February 2006), section
+ * "13.2.1.2 SYSCFG Register": "The MtrrFixDramModEn bit should be set
+ * to 1 during BIOS initalization of the fixed MTRRs, then cleared to
+ * 0 for operation."
+ */
+static inline void k8_check_syscfg_dram_mod_en(void)
+{
+ u32 lo, hi;
+
+ if (!((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+ (boot_cpu_data.x86 >= 0x0f)))
+ return;
+
+ rdmsr(MSR_K8_SYSCFG, lo, hi);
+ if (lo & K8_MTRRFIXRANGE_DRAM_MODIFY) {
+ printk(KERN_ERR "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]"
+ " not cleared by BIOS, clearing this bit\n",
+ smp_processor_id());
+ lo &= ~K8_MTRRFIXRANGE_DRAM_MODIFY;
+ mtrr_wrmsr(MSR_K8_SYSCFG, lo, hi);
+ }
+}
+
/*
* Returns the effective MTRR type for the region
* Error returns:
@@ -178,6 +204,8 @@ get_fixed_ranges(mtrr_type * frs)
unsigned int *p = (unsigned int *) frs;
int i;
+ k8_check_syscfg_dram_mod_en();
+
rdmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
for (i = 0; i < 2; i++)
@@ -312,27 +340,10 @@ void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
}
/**
- * Enable and allow read/write of extended fixed-range MTRR bits on K8 CPUs
- * see AMD publication no. 24593, chapter 3.2.1 for more information
- */
-static inline void k8_enable_fixed_iorrs(void)
-{
- unsigned lo, hi;
-
- rdmsr(MSR_K8_SYSCFG, lo, hi);
- mtrr_wrmsr(MSR_K8_SYSCFG, lo
- | K8_MTRRFIXRANGE_DRAM_ENABLE
- | K8_MTRRFIXRANGE_DRAM_MODIFY, hi);
-}
-
-/**
* set_fixed_range - checks & updates a fixed-range MTRR if it differs from the value it should have
* @msr: MSR address of the MTTR which should be checked and updated
* @changed: pointer which indicates whether the MTRR needed to be changed
* @msrwords: pointer to the MSR values which the MSR should have
- *
- * If K8 extentions are wanted, update the K8 SYSCFG MSR also.
- * See AMD publication no. 24593, chapter 7.8.1, page 233 for more information.
*/
static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
{
@@ -341,10 +352,6 @@ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
rdmsr(msr, lo, hi);
if (lo != msrwords[0] || hi != msrwords[1]) {
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
- (boot_cpu_data.x86 >= 0x0f && boot_cpu_data.x86 <= 0x11) &&
- ((msrwords[0] | msrwords[1]) & K8_MTRR_RDMEM_WRMEM_MASK))
- k8_enable_fixed_iorrs();
mtrr_wrmsr(msr, msrwords[0], msrwords[1]);
*changed = true;
}
@@ -428,6 +435,8 @@ static int set_fixed_ranges(mtrr_type * frs)
bool changed = false;
int block=-1, range;
+ k8_check_syscfg_dram_mod_en();
+
while (fixed_range_blocks[++block].ranges)
for (range=0; range < fixed_range_blocks[block].ranges; range++)
set_fixed_range(fixed_range_blocks[block].base_msr + range,
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 8791fc5..b4b899a 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -326,6 +326,9 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return -EINVAL;
}
flags = new_flags;
+ vma->vm_page_prot = __pgprot(
+ (pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK) |
+ flags);
}
if (((vma->vm_pgoff < max_low_pfn_mapped) ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 2694998..e618cbe 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -968,9 +968,9 @@ static const struct acpi_device_id ec_device_ids[] = {
int __init acpi_ec_ecdt_probe(void)
{
- int ret;
acpi_status status;
struct acpi_table_ecdt *ecdt_ptr;
+ acpi_handle dummy;
boot_ec = make_acpi_ec();
if (!boot_ec)
@@ -996,30 +996,31 @@ int __init acpi_ec_ecdt_probe(void)
boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT;
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
- } else {
- /* This workaround is needed only on some broken machines,
- * which require early EC, but fail to provide ECDT */
- acpi_handle x;
- printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
- status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
- boot_ec, NULL);
- /* Check that acpi_get_devices actually find something */
- if (ACPI_FAILURE(status) || !boot_ec->handle)
- goto error;
- /* We really need to limit this workaround, the only ASUS,
- * which needs it, has fake EC._INI method, so use it as flag.
- * Keep boot_ec struct as it will be needed soon.
- */
- if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x)))
- return -ENODEV;
+ /* Add some basic check against completely broken table */
+ if (boot_ec->data_addr != boot_ec->command_addr)
+ goto install;
+ /* fall through */
}
-
- ret = ec_install_handlers(boot_ec);
- if (!ret) {
+ /* This workaround is needed only on some broken machines,
+ * which require early EC, but fail to provide ECDT */
+ printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
+ status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
+ boot_ec, NULL);
+ /* Check that acpi_get_devices actually find something */
+ if (ACPI_FAILURE(status) || !boot_ec->handle)
+ goto error;
+ /* We really need to limit this workaround, the only ASUS,
+ * which needs it, has fake EC._INI method, so use it as flag.
+ * Keep boot_ec struct as it will be needed soon.
+ */
+ if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &dummy)))
+ return -ENODEV;
+install:
+ if (!ec_install_handlers(boot_ec)) {
first_ec = boot_ec;
return 0;
}
- error:
+error:
kfree(boot_ec);
boot_ec = NULL;
return -ENODEV;
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 4216399..233a5fd 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -8,7 +8,7 @@
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
* Portions Copyright (C) 2003 Red Hat Inc
- * Portions Copyright (C) 2005-2007 MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2009 MontaVista Software, Inc.
*
* TODO
* Look into engine reset on timeout errors. Should not be required.
@@ -24,7 +24,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt37x"
-#define DRV_VERSION "0.6.11"
+#define DRV_VERSION "0.6.12"
struct hpt_clock {
u8 xfer_speed;
@@ -445,23 +445,6 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
}
/**
- * hpt370_bmdma_start - DMA engine begin
- * @qc: ATA command
- *
- * The 370 and 370A want us to reset the DMA engine each time we
- * use it. The 372 and later are fine.
- */
-
-static void hpt370_bmdma_start(struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
- udelay(10);
- ata_bmdma_start(qc);
-}
-
-/**
* hpt370_bmdma_end - DMA engine stop
* @qc: ATA command
*
@@ -598,7 +581,6 @@ static struct scsi_host_template hpt37x_sht = {
static struct ata_port_operations hpt370_port_ops = {
.inherits = &ata_bmdma_port_ops,
- .bmdma_start = hpt370_bmdma_start,
.bmdma_stop = hpt370_bmdma_stop,
.mode_filter = hpt370_filter,
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 118dbde..8cf3dca 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -1207,7 +1207,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
{
struct page * page;
- page = alloc_page(GFP_KERNEL | GFP_DMA32);
+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
if (page == NULL)
return NULL;
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 47b8cf2..92022aa 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -90,6 +90,7 @@ out1:
blkdev_put(bdev);
out:
mutex_unlock(&raw_mutex);
+ unlock_kernel();
return err;
}
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 2d637e0..fdcd0ab 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -101,6 +101,7 @@ struct buffer_desc {
u32 phys_addr;
u32 __reserved[4];
struct buffer_desc *next;
+ enum dma_data_direction dir;
};
struct crypt_ctl {
@@ -132,14 +133,10 @@ struct crypt_ctl {
struct ablk_ctx {
struct buffer_desc *src;
struct buffer_desc *dst;
- unsigned src_nents;
- unsigned dst_nents;
};
struct aead_ctx {
struct buffer_desc *buffer;
- unsigned short assoc_nents;
- unsigned short src_nents;
struct scatterlist ivlist;
/* used when the hmac is not on one sg entry */
u8 *hmac_virt;
@@ -312,7 +309,7 @@ static struct crypt_ctl *get_crypt_desc_emerg(void)
}
}
-static void free_buf_chain(struct buffer_desc *buf, u32 phys)
+static void free_buf_chain(struct device *dev, struct buffer_desc *buf,u32 phys)
{
while (buf) {
struct buffer_desc *buf1;
@@ -320,6 +317,7 @@ static void free_buf_chain(struct buffer_desc *buf, u32 phys)
buf1 = buf->next;
phys1 = buf->phys_next;
+ dma_unmap_single(dev, buf->phys_next, buf->buf_len, buf->dir);
dma_pool_free(buffer_pool, buf, phys);
buf = buf1;
phys = phys1;
@@ -348,7 +346,6 @@ static void one_packet(dma_addr_t phys)
struct crypt_ctl *crypt;
struct ixp_ctx *ctx;
int failed;
- enum dma_data_direction src_direction = DMA_BIDIRECTIONAL;
failed = phys & 0x1 ? -EBADMSG : 0;
phys &= ~0x3;
@@ -358,13 +355,8 @@ static void one_packet(dma_addr_t phys)
case CTL_FLAG_PERFORM_AEAD: {
struct aead_request *req = crypt->data.aead_req;
struct aead_ctx *req_ctx = aead_request_ctx(req);
- dma_unmap_sg(dev, req->assoc, req_ctx->assoc_nents,
- DMA_TO_DEVICE);
- dma_unmap_sg(dev, &req_ctx->ivlist, 1, DMA_BIDIRECTIONAL);
- dma_unmap_sg(dev, req->src, req_ctx->src_nents,
- DMA_BIDIRECTIONAL);
- free_buf_chain(req_ctx->buffer, crypt->src_buf);
+ free_buf_chain(dev, req_ctx->buffer, crypt->src_buf);
if (req_ctx->hmac_virt) {
finish_scattered_hmac(crypt);
}
@@ -374,16 +366,11 @@ static void one_packet(dma_addr_t phys)
case CTL_FLAG_PERFORM_ABLK: {
struct ablkcipher_request *req = crypt->data.ablk_req;
struct ablk_ctx *req_ctx = ablkcipher_request_ctx(req);
- int nents;
+
if (req_ctx->dst) {
- nents = req_ctx->dst_nents;
- dma_unmap_sg(dev, req->dst, nents, DMA_FROM_DEVICE);
- free_buf_chain(req_ctx->dst, crypt->dst_buf);
- src_direction = DMA_TO_DEVICE;
+ free_buf_chain(dev, req_ctx->dst, crypt->dst_buf);
}
- nents = req_ctx->src_nents;
- dma_unmap_sg(dev, req->src, nents, src_direction);
- free_buf_chain(req_ctx->src, crypt->src_buf);
+ free_buf_chain(dev, req_ctx->src, crypt->src_buf);
req->base.complete(&req->base, failed);
break;
}
@@ -748,56 +735,35 @@ static int setup_cipher(struct crypto_tfm *tfm, int encrypt,
return 0;
}
-static int count_sg(struct scatterlist *sg, int nbytes)
+static struct buffer_desc *chainup_buffers(struct device *dev,
+ struct scatterlist *sg, unsigned nbytes,
+ struct buffer_desc *buf, gfp_t flags,
+ enum dma_data_direction dir)
{
- int i;
- for (i = 0; nbytes > 0; i++, sg = sg_next(sg))
- nbytes -= sg->length;
- return i;
-}
-
-static struct buffer_desc *chainup_buffers(struct scatterlist *sg,
- unsigned nbytes, struct buffer_desc *buf, gfp_t flags)
-{
- int nents = 0;
-
- while (nbytes > 0) {
+ for (;nbytes > 0; sg = scatterwalk_sg_next(sg)) {
+ unsigned len = min(nbytes, sg->length);
struct buffer_desc *next_buf;
u32 next_buf_phys;
- unsigned len = min(nbytes, sg_dma_len(sg));
+ void *ptr;
- nents++;
nbytes -= len;
- if (!buf->phys_addr) {
- buf->phys_addr = sg_dma_address(sg);
- buf->buf_len = len;
- buf->next = NULL;
- buf->phys_next = 0;
- goto next;
- }
- /* Two consecutive chunks on one page may be handled by the old
- * buffer descriptor, increased by the length of the new one
- */
- if (sg_dma_address(sg) == buf->phys_addr + buf->buf_len) {
- buf->buf_len += len;
- goto next;
- }
+ ptr = page_address(sg_page(sg)) + sg->offset;
next_buf = dma_pool_alloc(buffer_pool, flags, &next_buf_phys);
- if (!next_buf)
- return NULL;
+ if (!next_buf) {
+ buf = NULL;
+ break;
+ }
+ sg_dma_address(sg) = dma_map_single(dev, ptr, len, dir);
buf->next = next_buf;
buf->phys_next = next_buf_phys;
-
buf = next_buf;
- buf->next = NULL;
- buf->phys_next = 0;
+
buf->phys_addr = sg_dma_address(sg);
buf->buf_len = len;
-next:
- if (nbytes > 0) {
- sg = sg_next(sg);
- }
+ buf->dir = dir;
}
+ buf->next = NULL;
+ buf->phys_next = 0;
return buf;
}
@@ -858,12 +824,12 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt)
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
struct ixp_ctx *ctx = crypto_ablkcipher_ctx(tfm);
unsigned ivsize = crypto_ablkcipher_ivsize(tfm);
- int ret = -ENOMEM;
struct ix_sa_dir *dir;
struct crypt_ctl *crypt;
- unsigned int nbytes = req->nbytes, nents;
+ unsigned int nbytes = req->nbytes;
enum dma_data_direction src_direction = DMA_BIDIRECTIONAL;
struct ablk_ctx *req_ctx = ablkcipher_request_ctx(req);
+ struct buffer_desc src_hook;
gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
GFP_KERNEL : GFP_ATOMIC;
@@ -876,7 +842,7 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt)
crypt = get_crypt_desc();
if (!crypt)
- return ret;
+ return -ENOMEM;
crypt->data.ablk_req = req;
crypt->crypto_ctx = dir->npe_ctx_phys;
@@ -889,53 +855,41 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt)
BUG_ON(ivsize && !req->info);
memcpy(crypt->iv, req->info, ivsize);
if (req->src != req->dst) {
+ struct buffer_desc dst_hook;
crypt->mode |= NPE_OP_NOT_IN_PLACE;
- nents = count_sg(req->dst, nbytes);
/* This was never tested by Intel
* for more than one dst buffer, I think. */
- BUG_ON(nents != 1);
- req_ctx->dst_nents = nents;
- dma_map_sg(dev, req->dst, nents, DMA_FROM_DEVICE);
- req_ctx->dst = dma_pool_alloc(buffer_pool, flags,&crypt->dst_buf);
- if (!req_ctx->dst)
- goto unmap_sg_dest;
- req_ctx->dst->phys_addr = 0;
- if (!chainup_buffers(req->dst, nbytes, req_ctx->dst, flags))
+ BUG_ON(req->dst->length < nbytes);
+ req_ctx->dst = NULL;
+ if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook,
+ flags, DMA_FROM_DEVICE))
goto free_buf_dest;
src_direction = DMA_TO_DEVICE;
+ req_ctx->dst = dst_hook.next;
+ crypt->dst_buf = dst_hook.phys_next;
} else {
req_ctx->dst = NULL;
- req_ctx->dst_nents = 0;
}
- nents = count_sg(req->src, nbytes);
- req_ctx->src_nents = nents;
- dma_map_sg(dev, req->src, nents, src_direction);
-
- req_ctx->src = dma_pool_alloc(buffer_pool, flags, &crypt->src_buf);
- if (!req_ctx->src)
- goto unmap_sg_src;
- req_ctx->src->phys_addr = 0;
- if (!chainup_buffers(req->src, nbytes, req_ctx->src, flags))
+ req_ctx->src = NULL;
+ if (!chainup_buffers(dev, req->src, nbytes, &src_hook,
+ flags, src_direction))
goto free_buf_src;
+ req_ctx->src = src_hook.next;
+ crypt->src_buf = src_hook.phys_next;
crypt->ctl_flags |= CTL_FLAG_PERFORM_ABLK;
qmgr_put_entry(SEND_QID, crypt_virt2phys(crypt));
BUG_ON(qmgr_stat_overflow(SEND_QID));
return -EINPROGRESS;
free_buf_src:
- free_buf_chain(req_ctx->src, crypt->src_buf);
-unmap_sg_src:
- dma_unmap_sg(dev, req->src, req_ctx->src_nents, src_direction);
+ free_buf_chain(dev, req_ctx->src, crypt->src_buf);
free_buf_dest:
if (req->src != req->dst) {
- free_buf_chain(req_ctx->dst, crypt->dst_buf);
-unmap_sg_dest:
- dma_unmap_sg(dev, req->src, req_ctx->dst_nents,
- DMA_FROM_DEVICE);
+ free_buf_chain(dev, req_ctx->dst, crypt->dst_buf);
}
crypt->ctl_flags = CTL_FLAG_UNUSED;
- return ret;
+ return -ENOMEM;
}
static int ablk_encrypt(struct ablkcipher_request *req)
@@ -983,7 +937,7 @@ static int hmac_inconsistent(struct scatterlist *sg, unsigned start,
break;
offset += sg->length;
- sg = sg_next(sg);
+ sg = scatterwalk_sg_next(sg);
}
return (start + nbytes > offset + sg->length);
}
@@ -995,11 +949,10 @@ static int aead_perform(struct aead_request *req, int encrypt,
struct ixp_ctx *ctx = crypto_aead_ctx(tfm);
unsigned ivsize = crypto_aead_ivsize(tfm);
unsigned authsize = crypto_aead_authsize(tfm);
- int ret = -ENOMEM;
struct ix_sa_dir *dir;
struct crypt_ctl *crypt;
- unsigned int cryptlen, nents;
- struct buffer_desc *buf;
+ unsigned int cryptlen;
+ struct buffer_desc *buf, src_hook;
struct aead_ctx *req_ctx = aead_request_ctx(req);
gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
GFP_KERNEL : GFP_ATOMIC;
@@ -1020,7 +973,7 @@ static int aead_perform(struct aead_request *req, int encrypt,
}
crypt = get_crypt_desc();
if (!crypt)
- return ret;
+ return -ENOMEM;
crypt->data.aead_req = req;
crypt->crypto_ctx = dir->npe_ctx_phys;
@@ -1039,31 +992,27 @@ static int aead_perform(struct aead_request *req, int encrypt,
BUG(); /* -ENOTSUP because of my lazyness */
}
- req_ctx->buffer = dma_pool_alloc(buffer_pool, flags, &crypt->src_buf);
- if (!req_ctx->buffer)
- goto out;
- req_ctx->buffer->phys_addr = 0;
/* ASSOC data */
- nents = count_sg(req->assoc, req->assoclen);
- req_ctx->assoc_nents = nents;
- dma_map_sg(dev, req->assoc, nents, DMA_TO_DEVICE);
- buf = chainup_buffers(req->assoc, req->assoclen, req_ctx->buffer,flags);
+ buf = chainup_buffers(dev, req->assoc, req->assoclen, &src_hook,
+ flags, DMA_TO_DEVICE);
+ req_ctx->buffer = src_hook.next;
+ crypt->src_buf = src_hook.phys_next;
if (!buf)
- goto unmap_sg_assoc;
+ goto out;
/* IV */
sg_init_table(&req_ctx->ivlist, 1);
sg_set_buf(&req_ctx->ivlist, iv, ivsize);
- dma_map_sg(dev, &req_ctx->ivlist, 1, DMA_BIDIRECTIONAL);
- buf = chainup_buffers(&req_ctx->ivlist, ivsize, buf, flags);
+ buf = chainup_buffers(dev, &req_ctx->ivlist, ivsize, buf, flags,
+ DMA_BIDIRECTIONAL);
if (!buf)
- goto unmap_sg_iv;
+ goto free_chain;
if (unlikely(hmac_inconsistent(req->src, cryptlen, authsize))) {
/* The 12 hmac bytes are scattered,
* we need to copy them into a safe buffer */
req_ctx->hmac_virt = dma_pool_alloc(buffer_pool, flags,
&crypt->icv_rev_aes);
if (unlikely(!req_ctx->hmac_virt))
- goto unmap_sg_iv;
+ goto free_chain;
if (!encrypt) {
scatterwalk_map_and_copy(req_ctx->hmac_virt,
req->src, cryptlen, authsize, 0);
@@ -1073,33 +1022,28 @@ static int aead_perform(struct aead_request *req, int encrypt,
req_ctx->hmac_virt = NULL;
}
/* Crypt */
- nents = count_sg(req->src, cryptlen + authsize);
- req_ctx->src_nents = nents;
- dma_map_sg(dev, req->src, nents, DMA_BIDIRECTIONAL);
- buf = chainup_buffers(req->src, cryptlen + authsize, buf, flags);
+ buf = chainup_buffers(dev, req->src, cryptlen + authsize, buf, flags,
+ DMA_BIDIRECTIONAL);
if (!buf)
- goto unmap_sg_src;
+ goto free_hmac_virt;
if (!req_ctx->hmac_virt) {
crypt->icv_rev_aes = buf->phys_addr + buf->buf_len - authsize;
}
+
crypt->ctl_flags |= CTL_FLAG_PERFORM_AEAD;
qmgr_put_entry(SEND_QID, crypt_virt2phys(crypt));
BUG_ON(qmgr_stat_overflow(SEND_QID));
return -EINPROGRESS;
-unmap_sg_src:
- dma_unmap_sg(dev, req->src, req_ctx->src_nents, DMA_BIDIRECTIONAL);
+free_hmac_virt:
if (req_ctx->hmac_virt) {
dma_pool_free(buffer_pool, req_ctx->hmac_virt,
crypt->icv_rev_aes);
}
-unmap_sg_iv:
- dma_unmap_sg(dev, &req_ctx->ivlist, 1, DMA_BIDIRECTIONAL);
-unmap_sg_assoc:
- dma_unmap_sg(dev, req->assoc, req_ctx->assoc_nents, DMA_TO_DEVICE);
- free_buf_chain(req_ctx->buffer, crypt->src_buf);
+free_chain:
+ free_buf_chain(dev, req_ctx->buffer, crypt->src_buf);
out:
crypt->ctl_flags = CTL_FLAG_UNUSED;
- return ret;
+ return -ENOMEM;
}
static int aead_setup(struct crypto_aead *tfm, unsigned int authsize)
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index c37ab17..7e443a3 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -114,6 +114,8 @@
* the register setting lists into the table indexed by the clock selected
* - set the correct hwif->ultra_mask for each individual chip
* - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
+ * - stop resetting HPT370's state machine before each DMA transfer as that has
+ * caused more harm than good
* Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
*/
@@ -134,7 +136,7 @@
#define DRV_NAME "hpt366"
/* various tuning parameters */
-#define HPT_RESET_STATE_ENGINE
+#undef HPT_RESET_STATE_ENGINE
#undef HPT_DELAY_INTERRUPT
#define HPT_SERIALIZE_IO 0
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index 3f11910..fcec2df 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -46,6 +46,9 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
#define IF_WRITEBUF 264
+/* interrupt pipe message size according to ibid. ch. 2.2 */
+#define IP_MSGSIZE 3
+
/* Values for the Gigaset 307x */
#define USB_GIGA_VENDOR_ID 0x0681
#define USB_3070_PRODUCT_ID 0x0001
@@ -110,7 +113,7 @@ struct bas_cardstate {
unsigned char *rcvbuf; /* AT reply receive buffer */
struct urb *urb_int_in; /* URB for interrupt pipe */
- unsigned char int_in_buf[3];
+ unsigned char *int_in_buf;
spinlock_t lock; /* locks all following */
int basstate; /* bitmap (BS_*) */
@@ -657,7 +660,7 @@ static void read_int_callback(struct urb *urb)
}
/* drop incomplete packets even if the missing bytes wouldn't matter */
- if (unlikely(urb->actual_length < 3)) {
+ if (unlikely(urb->actual_length < IP_MSGSIZE)) {
dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n",
urb->actual_length);
goto resubmit;
@@ -2127,6 +2130,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs)
static void gigaset_freecshw(struct cardstate *cs)
{
/* timers, URBs and rcvbuf are disposed of in disconnect */
+ kfree(cs->hw.bas->int_in_buf);
kfree(cs->hw.bas);
cs->hw.bas = NULL;
}
@@ -2232,6 +2236,12 @@ static int gigaset_probe(struct usb_interface *interface,
}
hostif = interface->cur_altsetting;
}
+ ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL);
+ if (!ucs->int_in_buf) {
+ kfree(ucs);
+ pr_err("out of memory\n");
+ return 0;
+ }
/* Reject application specific interfaces
*/
@@ -2290,7 +2300,7 @@ static int gigaset_probe(struct usb_interface *interface,
usb_fill_int_urb(ucs->urb_int_in, udev,
usb_rcvintpipe(udev,
(endpoint->bEndpointAddress) & 0x0f),
- ucs->int_in_buf, 3, read_int_callback, cs,
+ ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs,
endpoint->bInterval);
if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) {
dev_err(cs->dev, "could not submit interrupt URB: %s\n",
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 34bb0e4..1a551a8 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -282,11 +282,17 @@ static u32 dbg_level;
static struct workqueue_struct *tpacpi_wq;
+enum led_status_t {
+ TPACPI_LED_OFF = 0,
+ TPACPI_LED_ON,
+ TPACPI_LED_BLINK,
+};
+
/* Special LED class that can defer work */
struct tpacpi_led_classdev {
struct led_classdev led_classdev;
struct work_struct work;
- enum led_brightness new_brightness;
+ enum led_status_t new_state;
unsigned int led;
};
@@ -3478,7 +3484,7 @@ static void light_set_status_worker(struct work_struct *work)
container_of(work, struct tpacpi_led_classdev, work);
if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
- light_set_status((data->new_brightness != LED_OFF));
+ light_set_status((data->new_state != TPACPI_LED_OFF));
}
static void light_sysfs_set(struct led_classdev *led_cdev,
@@ -3488,7 +3494,8 @@ static void light_sysfs_set(struct led_classdev *led_cdev,
container_of(led_cdev,
struct tpacpi_led_classdev,
led_classdev);
- data->new_brightness = brightness;
+ data->new_state = (brightness != LED_OFF) ?
+ TPACPI_LED_ON : TPACPI_LED_OFF;
queue_work(tpacpi_wq, &data->work);
}
@@ -3995,12 +4002,6 @@ enum { /* For TPACPI_LED_OLD */
TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */
};
-enum led_status_t {
- TPACPI_LED_OFF = 0,
- TPACPI_LED_ON,
- TPACPI_LED_BLINK,
-};
-
static enum led_access_mode led_supported;
TPACPI_HANDLE(led, ec, "SLED", /* 570 */
@@ -4094,23 +4095,13 @@ static int led_set_status(const unsigned int led,
return rc;
}
-static void led_sysfs_set_status(unsigned int led,
- enum led_brightness brightness)
-{
- led_set_status(led,
- (brightness == LED_OFF) ?
- TPACPI_LED_OFF :
- (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ?
- TPACPI_LED_BLINK : TPACPI_LED_ON);
-}
-
static void led_set_status_worker(struct work_struct *work)
{
struct tpacpi_led_classdev *data =
container_of(work, struct tpacpi_led_classdev, work);
if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING))
- led_sysfs_set_status(data->led, data->new_brightness);
+ led_set_status(data->led, data->new_state);
}
static void led_sysfs_set(struct led_classdev *led_cdev,
@@ -4119,7 +4110,13 @@ static void led_sysfs_set(struct led_classdev *led_cdev,
struct tpacpi_led_classdev *data = container_of(led_cdev,
struct tpacpi_led_classdev, led_classdev);
- data->new_brightness = brightness;
+ if (brightness == LED_OFF)
+ data->new_state = TPACPI_LED_OFF;
+ else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK)
+ data->new_state = TPACPI_LED_ON;
+ else
+ data->new_state = TPACPI_LED_BLINK;
+
queue_work(tpacpi_wq, &data->work);
}
@@ -4137,7 +4134,7 @@ static int led_sysfs_blink_set(struct led_classdev *led_cdev,
} else if ((*delay_on != 500) || (*delay_off != 500))
return -EINVAL;
- data->new_brightness = TPACPI_LED_BLINK;
+ data->new_state = TPACPI_LED_BLINK;
queue_work(tpacpi_wq, &data->work);
return 0;
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index c3bda5c..f1521c6 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -750,7 +750,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dest_idx * sizeof(dest_desc),
DMA_BIDIRECTIONAL);
- ssb_dma_sync_single_for_device(bp->sdev, le32_to_cpu(src_desc->addr),
+ ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
RX_PKT_BUF_SZ,
DMA_FROM_DEVICE);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1b9c4dc..f9f29c9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3516,11 +3516,26 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
}
break;
case NETDEV_CHANGE:
- /*
- * TODO: is this what we get if somebody
- * sets up a hierarchical bond, then rmmod's
- * one of the slave bonding devices?
- */
+ if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) {
+ struct slave *slave;
+
+ slave = bond_get_slave_by_dev(bond, slave_dev);
+ if (slave) {
+ u16 old_speed = slave->speed;
+ u16 old_duplex = slave->duplex;
+
+ bond_update_speed_duplex(slave);
+
+ if (bond_is_lb(bond))
+ break;
+
+ if (old_speed != slave->speed)
+ bond_3ad_adapter_speed_changed(slave);
+ if (old_duplex != slave->duplex)
+ bond_3ad_adapter_duplex_changed(slave);
+ }
+ }
+
break;
case NETDEV_DOWN:
/*
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index fb730ec..0f6de5f 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -248,6 +248,12 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
return (struct bonding *)slave->dev->master->priv;
}
+static inline bool bond_is_lb(const struct bonding *bond)
+{
+ return bond->params.mode == BOND_MODE_TLB
+ || bond->params.mode == BOND_MODE_ALB;
+}
+
#define BOND_FOM_NONE 0
#define BOND_FOM_ACTIVE 1
#define BOND_FOM_FOLLOW 2
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 39c17bb..a98d31a 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -375,6 +375,22 @@ enum features {
RTL_FEATURE_GMII = (1 << 2),
};
+struct rtl8169_counters {
+ __le64 tx_packets;
+ __le64 rx_packets;
+ __le64 tx_errors;
+ __le32 rx_errors;
+ __le16 rx_missed;
+ __le16 align_errors;
+ __le32 tx_one_collision;
+ __le32 tx_multi_collision;
+ __le64 rx_unicast;
+ __le64 rx_broadcast;
+ __le32 rx_multicast;
+ __le16 tx_aborted;
+ __le16 tx_underun;
+};
+
struct rtl8169_private {
void __iomem *mmio_addr; /* memory map physical address */
struct pci_dev *pci_dev; /* Index of PCI device */
@@ -416,6 +432,7 @@ struct rtl8169_private {
unsigned features;
struct mii_if_info mii;
+ struct rtl8169_counters counters;
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -960,22 +977,6 @@ static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
"tx_underrun",
};
-struct rtl8169_counters {
- __le64 tx_packets;
- __le64 rx_packets;
- __le64 tx_errors;
- __le32 rx_errors;
- __le16 rx_missed;
- __le16 align_errors;
- __le32 tx_one_collision;
- __le32 tx_multi_collision;
- __le64 rx_unicast;
- __le64 rx_broadcast;
- __le32 rx_multicast;
- __le16 tx_aborted;
- __le16 tx_underun;
-};
-
static int rtl8169_get_sset_count(struct net_device *dev, int sset)
{
switch (sset) {
@@ -986,16 +987,21 @@ static int rtl8169_get_sset_count(struct net_device *dev, int sset)
}
}
-static void rtl8169_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
+static void rtl8169_update_counters(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
struct rtl8169_counters *counters;
dma_addr_t paddr;
u32 cmd;
+ int wait = 1000;
- ASSERT_RTNL();
+ /*
+ * Some chips are unable to dump tally counters when the receiver
+ * is disabled.
+ */
+ if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
+ return;
counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
if (!counters)
@@ -1006,31 +1012,45 @@ static void rtl8169_get_ethtool_stats(struct net_device *dev,
RTL_W32(CounterAddrLow, cmd);
RTL_W32(CounterAddrLow, cmd | CounterDump);
- while (RTL_R32(CounterAddrLow) & CounterDump) {
- if (msleep_interruptible(1))
+ while (wait--) {
+ if ((RTL_R32(CounterAddrLow) & CounterDump) == 0) {
+ /* copy updated counters */
+ memcpy(&tp->counters, counters, sizeof(*counters));
break;
+ }
+ udelay(10);
}
RTL_W32(CounterAddrLow, 0);
RTL_W32(CounterAddrHigh, 0);
- data[0] = le64_to_cpu(counters->tx_packets);
- data[1] = le64_to_cpu(counters->rx_packets);
- data[2] = le64_to_cpu(counters->tx_errors);
- data[3] = le32_to_cpu(counters->rx_errors);
- data[4] = le16_to_cpu(counters->rx_missed);
- data[5] = le16_to_cpu(counters->align_errors);
- data[6] = le32_to_cpu(counters->tx_one_collision);
- data[7] = le32_to_cpu(counters->tx_multi_collision);
- data[8] = le64_to_cpu(counters->rx_unicast);
- data[9] = le64_to_cpu(counters->rx_broadcast);
- data[10] = le32_to_cpu(counters->rx_multicast);
- data[11] = le16_to_cpu(counters->tx_aborted);
- data[12] = le16_to_cpu(counters->tx_underun);
-
pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
}
+static void rtl8169_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ ASSERT_RTNL();
+
+ rtl8169_update_counters(dev);
+
+ data[0] = le64_to_cpu(tp->counters.tx_packets);
+ data[1] = le64_to_cpu(tp->counters.rx_packets);
+ data[2] = le64_to_cpu(tp->counters.tx_errors);
+ data[3] = le32_to_cpu(tp->counters.rx_errors);
+ data[4] = le16_to_cpu(tp->counters.rx_missed);
+ data[5] = le16_to_cpu(tp->counters.align_errors);
+ data[6] = le32_to_cpu(tp->counters.tx_one_collision);
+ data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
+ data[8] = le64_to_cpu(tp->counters.rx_unicast);
+ data[9] = le64_to_cpu(tp->counters.rx_broadcast);
+ data[10] = le32_to_cpu(tp->counters.rx_multicast);
+ data[11] = le16_to_cpu(tp->counters.tx_aborted);
+ data[12] = le16_to_cpu(tp->counters.tx_underun);
+}
+
static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
switch(stringset) {
@@ -1667,8 +1687,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_res_4;
}
- /* Unneeded ? Don't mess with Mrs. Murphy. */
- rtl8169_irq_mask_and_ack(ioaddr);
+ RTL_W16(IntrMask, 0x0000);
/* Soft reset the chip. */
RTL_W8(ChipCmd, CmdReset);
@@ -1680,6 +1699,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
msleep_interruptible(1);
}
+ RTL_W16(IntrStatus, 0xffff);
+
/* Identify chip attached to board */
rtl8169_get_mac_version(tp, ioaddr);
@@ -2529,13 +2550,6 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
opts1 |= FirstFrag;
} else {
len = skb->len;
-
- if (unlikely(len < ETH_ZLEN)) {
- if (skb_padto(skb, ETH_ZLEN))
- goto err_update_stats;
- len = ETH_ZLEN;
- }
-
opts1 |= FirstFrag | LastFrag;
tp->tx_skb[entry].skb = skb;
}
@@ -2573,7 +2587,6 @@ out:
err_stop:
netif_stop_queue(dev);
ret = NETDEV_TX_BUSY;
-err_update_stats:
dev->stats.tx_dropped++;
goto out;
}
@@ -2979,6 +2992,9 @@ static int rtl8169_close(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev);
struct pci_dev *pdev = tp->pci_dev;
+ /* update counters before going down */
+ rtl8169_update_counters(dev);
+
rtl8169_down(dev);
free_irq(dev->irq, dev);
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index d1b0fba..8ccf374 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -591,8 +591,8 @@ struct ath9k_country_entry {
u8 iso[3];
};
-#define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg)
-#define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg)
+#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
+#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
#define SM(_v, _f) (((_v) << _f##_S) & _f)
#define MS(_v, _f) (((_v) & _f) >> _f##_S)
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
index 87e37bc..e50ba6d 100644
--- a/drivers/net/wireless/ath9k/core.c
+++ b/drivers/net/wireless/ath9k/core.c
@@ -1120,6 +1120,7 @@ int ath_init(u16 devid, struct ath_softc *sc)
sc->sc_cachelsz = csz << 2; /* convert to bytes */
spin_lock_init(&sc->sc_resetlock);
+ spin_lock_init(&sc->sc_serial_rw);
ah = ath9k_hw_attach(devid, sc, sc->mem, &status);
if (ah == NULL) {
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index 88f4cc3..51ef315 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -1022,6 +1022,7 @@ struct ath_softc {
spinlock_t sc_rxbuflock;
spinlock_t sc_txbuflock;
spinlock_t sc_resetlock;
+ spinlock_t sc_serial_rw;
spinlock_t node_lock;
};
@@ -1069,4 +1070,36 @@ void ath_skb_unmap_single(struct ath_softc *sc,
void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]);
enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc);
+/*
+ * Read and write, they both share the same lock. We do this to serialize
+ * reads and writes on Atheros 802.11n PCI devices only. This is required
+ * as the FIFO on these devices can only accept sanely 2 requests. After
+ * that the device goes bananas. Serializing the reads/writes prevents this
+ * from happening.
+ */
+
+static inline void ath9k_iowrite32(struct ath_hal *ah, u32 reg_offset, u32 val)
+{
+ if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) {
+ unsigned long flags;
+ spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
+ iowrite32(val, ah->ah_sc->mem + reg_offset);
+ spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
+ } else
+ iowrite32(val, ah->ah_sc->mem + reg_offset);
+}
+
+static inline unsigned int ath9k_ioread32(struct ath_hal *ah, u32 reg_offset)
+{
+ u32 val;
+ if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) {
+ unsigned long flags;
+ spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags);
+ val = ioread32(ah->ah_sc->mem + reg_offset);
+ spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags);
+ } else
+ val = ioread32(ah->ah_sc->mem + reg_offset);
+ return val;
+}
+
#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 69120b5..c40b677 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -369,6 +369,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah)
}
ah->ah_config.intr_mitigation = 0;
+
+ /*
+ * We need this for PCI devices only (Cardbus, PCI, miniPCI)
+ * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
+ * This means we use it for all AR5416 devices, and the few
+ * minor PCI AR9280 devices out there.
+ *
+ * Serialization is required because these devices do not handle
+ * well the case of two concurrent reads/writes due to the latency
+ * involved. During one read/write another read/write can be issued
+ * on another CPU while the previous read/write may still be working
+ * on our hardware, if we hit this case the hardware poops in a loop.
+ * We prevent this by serializing reads and writes.
+ *
+ * This issue is not present on PCI-Express devices or pre-AR5416
+ * devices (legacy, 802.11abg).
+ */
+ if (num_possible_cpus() > 1)
+ ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO;
}
static inline void ath9k_hw_override_ini(struct ath_hal *ah,
@@ -3294,7 +3313,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
}
if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) {
- if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) {
+ if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI ||
+ (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) {
ah->ah_config.serialize_regmode =
SER_REG_MODE_ON;
} else {
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 9dda816..4102aaa 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -51,7 +51,7 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
}
/* Extract the bitrate index out of an OFDM PLCP header. */
-static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
+static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
{
int base = aphy ? 0 : 4;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 55ac5c3..cb009f3 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1807,12 +1807,14 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
num_arrays++;
q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL);
if (q->pool == NULL)
- goto enomem;
+ return -ENOMEM;
q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
GFP_KERNEL, NULL);
- if (q->queue == ERR_PTR(-ENOMEM))
+ if (IS_ERR(q->queue)) {
+ q->queue = NULL;
goto enomem;
+ }
for (i = 0; i < max; i++) {
q->pool[i] = kzalloc(item_size, GFP_KERNEL);
@@ -1842,8 +1844,7 @@ void iscsi_pool_free(struct iscsi_pool *q)
for (i = 0; i < q->max; i++)
kfree(q->pool[i]);
- if (q->pool)
- kfree(q->pool);
+ kfree(q->pool);
kfree(q->queue);
}
EXPORT_SYMBOL_GPL(iscsi_pool_free);
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 023a4e9..abbdb31 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -641,7 +641,7 @@ next_desc:
iface = &intf->altsetting[0];
ep = &iface->endpoint[0].desc;
- if (!usb_endpoint_is_int_in(ep)) {
+ if (!ep || !usb_endpoint_is_int_in(ep)) {
rv = -EINVAL;
goto err;
}
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 3a8bb53..fd7b356 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -437,7 +437,7 @@ invalid:
DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
w_value, w_index, w_length);
- req->zero = 0;
+ req->zero = (value < w_length);
req->length = value;
value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
if (value < 0)
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 38a55af..bb3d7c3 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
}
-static u32 eth_get_link(struct net_device *net)
-{
- struct eth_dev *dev = netdev_priv(net);
- return dev->gadget->speed != USB_SPEED_UNKNOWN;
-}
-
/* REVISIT can also support:
* - WOL (by tracking suspends and issuing remote wakeup)
* - msglevel (implies updated messaging)
@@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net)
static struct ethtool_ops ops = {
.get_drvinfo = eth_get_drvinfo,
- .get_link = eth_get_link
+ .get_link = ethtool_op_get_link,
};
static void defer_kevent(struct eth_dev *dev, int flag)
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index ecc9b66..01132ac 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
token = hc32_to_cpu(ehci, qtd->hw_token);
/* always clean up qtds the hc de-activated */
+ retry_xacterr:
if ((token & QTD_STS_ACTIVE) == 0) {
/* on STALL, error, and short reads this urb must
* complete and all its qtds must be recycled.
*/
if ((token & QTD_STS_HALT) != 0) {
+
+ /* retry transaction errors until we
+ * reach the software xacterr limit
+ */
+ if ((token & QTD_STS_XACT) &&
+ QTD_CERR(token) == 0 &&
+ --qh->xacterrs > 0 &&
+ !urb->unlinked) {
+ ehci_dbg(ehci,
+ "detected XactErr len %d/%d retry %d\n",
+ qtd->length - QTD_LENGTH(token), qtd->length,
+ QH_XACTERR_MAX - qh->xacterrs);
+
+ /* reset the token in the qtd and the
+ * qh overlay (which still contains
+ * the qtd) so that we pick up from
+ * where we left off
+ */
+ token &= ~QTD_STS_HALT;
+ token |= QTD_STS_ACTIVE |
+ (EHCI_TUNE_CERR << 10);
+ qtd->hw_token = cpu_to_hc32(ehci,
+ token);
+ wmb();
+ qh->hw_token = cpu_to_hc32(ehci, token);
+ goto retry_xacterr;
+ }
stopped = 1;
/* magic dummy for some short reads; qh won't advance.
@@ -421,6 +449,9 @@ halt:
/* remove qtd; it's recycled after possible urb completion */
list_del (&qtd->qtd_list);
last = qtd;
+
+ /* reinit the xacterr counter for the next qtd */
+ qh->xacterrs = QH_XACTERR_MAX;
}
/* last urb's completion might still need calling */
@@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
head->qh_next.qh = qh;
head->hw_next = dma;
+ qh->xacterrs = QH_XACTERR_MAX;
qh->qh_state = QH_STATE_LINKED;
/* qtd completions reported later by interrupt */
}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 33459d7..c165fe4 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -500,6 +500,9 @@ struct ehci_qh {
#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */
#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */
+ u8 xacterrs; /* XactErr retry counter */
+#define QH_XACTERR_MAX 32 /* XactErr retry limit */
+
/* periodic schedule info */
u8 usecs; /* intr bandwidth */
u8 gap_uf; /* uframes split/csplit gap */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 2d78712..13b34bc 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -662,6 +662,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(DE_VID, WHT_PID) },
{ USB_DEVICE(ADI_VID, ADI_GNICE_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 80fa76e..3425122 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -890,6 +890,13 @@
#define ADI_GNICE_PID 0xF000
/*
+ * JETI SPECTROMETER SPECBOS 1201
+ * http://www.jeti.com/products/sys/scb/scb1201.php
+ */
+#define JETI_VID 0x0c6c
+#define JETI_SPC1201_PID 0x04b2
+
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_E2_READ
* wValue: 0
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index 898e67d..9466a99 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -133,19 +133,18 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
/* build the command for
* reading the ATA registers */
- scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0);
- srb->sdb.length = sizeof(regs);
- sg_init_one(&ses.sense_sgl, regs, srb->sdb.length);
- srb->sdb.table.sgl = &ses.sense_sgl;
- srb->sc_data_direction = DMA_FROM_DEVICE;
- srb->sdb.table.nents = 1;
+ scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs));
+
/* we use the same command as before, but we set
* the read taskfile bit, for not executing atacb command,
* but reading register selected in srb->cmnd[4]
*/
+ srb->cmd_len = 16;
+ srb->cmnd = ses.cmnd;
srb->cmnd[2] = 1;
usb_stor_transparent_scsi_command(srb, us);
+ memcpy(regs, srb->sense_buffer, sizeof(regs));
tmp_result = srb->result;
scsi_eh_restore_cmnd(srb, &ses);
/* we fail to get registers, report invalid command */
@@ -162,8 +161,8 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
/* XXX we should generate sk, asc, ascq from status and error
* regs
- * (see 11.1 Error translation ATA device error to SCSI error map)
- * and ata_to_sense_error from libata.
+ * (see 11.1 Error translation ATA device error to SCSI error
+ * map, and ata_to_sense_error from libata.)
*/
/* Sense data is current and format is descriptor. */
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 8daaace..5f484ae 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -135,6 +135,12 @@ static int slave_configure(struct scsi_device *sdev)
if (sdev->request_queue->max_sectors > max_sectors)
blk_queue_max_sectors(sdev->request_queue,
max_sectors);
+ } else if (sdev->type == TYPE_TAPE) {
+ /* Tapes need much higher max_sector limits, so just
+ * raise it to the maximum possible (4 GB / 512) and
+ * let the queue segment size sort out the real limit.
+ */
+ blk_queue_max_sectors(sdev->request_queue, 0x7FFFFF);
}
/* We can't put these settings in slave_alloc() because that gets
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index d21995a..4cf1617 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1241,12 +1241,14 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
-/* Reported by Rauch Wolke <rauchwolke@gmx.net> */
+/* Reported by Rauch Wolke <rauchwolke@gmx.net>
+ * and augmented by binbin <binbinsh@gmail.com> (Bugzilla #12882)
+ */
UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff,
"Simple Tech/Datafab",
"CF+SM Reader",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_RESIDUE ),
+ US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ),
/* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
* to the USB storage specification in two ways:
diff --git a/fs/buffer.c b/fs/buffer.c
index a542f97..a5d806d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -3042,7 +3042,7 @@ int sync_dirty_buffer(struct buffer_head *bh)
if (test_clear_buffer_dirty(bh)) {
get_bh(bh);
bh->b_end_io = end_buffer_write_sync;
- ret = submit_bh(WRITE_SYNC, bh);
+ ret = submit_bh(WRITE, bh);
wait_on_buffer(bh);
if (buffer_eopnotsupp(bh)) {
clear_buffer_eopnotsupp(bh);
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 088e9ae..455257e 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,4 +1,7 @@
Fix oops in cifs_dfs_ref.c when prefixpath is not reachable when using DFS.
+Fix "redzone overwritten" bug in cifs_put_tcon (CIFSTcon may allocate too
+little memory for the "nativeFileSystem" field returned by the server
+during mount).
Version 1.54
------------
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 8f0f86d..9231e0a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2348,8 +2348,10 @@ winCreateHardLinkRetry:
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
- pSMB->OldFileName[name_len] = 0; /* pad */
- pSMB->OldFileName[name_len + 1] = 0x04;
+
+ /* protocol specifies ASCII buffer format (0x04) for unicode */
+ pSMB->OldFileName[name_len] = 0x04;
+ pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
name_len2 =
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f254235..21a1abf 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3549,7 +3549,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
BCC(smb_buffer_response)) {
kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
- kzalloc(length + 2, GFP_KERNEL);
+ kzalloc(2*(length + 1), GFP_KERNEL);
if (tcon->nativeFileSystem)
cifs_strfromUCS_le(
tcon->nativeFileSystem,
diff --git a/fs/compat.c b/fs/compat.c
index a76455b..a53216d 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1353,12 +1353,17 @@ int compat_do_execve(char * filename,
{
struct linux_binprm *bprm;
struct file *file;
+ struct files_struct *displaced;
int retval;
+ retval = unshare_files(&displaced);
+ if (retval)
+ goto out_ret;
+
retval = -ENOMEM;
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
if (!bprm)
- goto out_ret;
+ goto out_files;
file = open_exec(filename);
retval = PTR_ERR(file);
@@ -1410,6 +1415,8 @@ int compat_do_execve(char * filename,
security_bprm_free(bprm);
acct_update_integrals(current);
free_bprm(bprm);
+ if (displaced)
+ put_files_struct(displaced);
return retval;
}
@@ -1430,6 +1437,9 @@ out_file:
out_kfree:
free_bprm(bprm);
+out_files:
+ if (displaced)
+ reset_files_struct(displaced);
out_ret:
return retval;
}
diff --git a/fs/dquot.c b/fs/dquot.c
index 8ec4d6c..150fc96 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -726,7 +726,7 @@ static void add_dquot_ref(struct super_block *sb, int type)
continue;
if (!dqinit_needed(inode, type))
continue;
- if (inode->i_state & (I_FREEING|I_WILL_FREE))
+ if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))
continue;
__iget(inode);
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 3e5637f..f7e66c0 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb)
spin_lock(&inode_lock);
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
- if (inode->i_state & (I_FREEING|I_WILL_FREE))
+ if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))
continue;
if (inode->i_mapping->nrpages == 0)
continue;
diff --git a/fs/exec.c b/fs/exec.c
index 5027d01..5ec0f56 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1089,9 +1089,7 @@ static int unsafe_exec(struct task_struct *p)
{
int unsafe = tracehook_unsafe_exec(p);
- if (atomic_read(&p->fs->count) > 1 ||
- atomic_read(&p->files->count) > 1 ||
- atomic_read(&p->sighand->count) > 1)
+ if (atomic_read(&p->fs->count) > 1)
unsafe |= LSM_UNSAFE_SHARE;
return unsafe;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 6caa023..6b60261 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -538,7 +538,8 @@ void generic_sync_sb_inodes(struct super_block *sb,
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
struct address_space *mapping;
- if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW))
+ if (inode->i_state &
+ (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW))
continue;
mapping = inode->i_mapping;
if (mapping->nrpages == 0)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 3f58923..a12a6b3 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -26,7 +26,6 @@
#include <linux/pagevec.h>
#include <linux/parser.h>
#include <linux/mman.h>
-#include <linux/quotaops.h>
#include <linux/slab.h>
#include <linux/dnotify.h>
#include <linux/statfs.h>
@@ -838,7 +837,7 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
bad_val:
printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",
args[0].from, p);
- return 1;
+ return -EINVAL;
}
static int
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index ec2ed15..6f7ea0a 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2089,7 +2089,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
out->f_path.dentry->d_name.len,
out->f_path.dentry->d_name.name);
- inode_double_lock(inode, pipe->inode);
+ mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
ret = ocfs2_rw_lock(inode, 1);
if (ret < 0) {
@@ -2104,12 +2104,16 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
goto out_unlock;
}
+ if (pipe->inode)
+ mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
ret = generic_file_splice_write_nolock(pipe, out, ppos, len, flags);
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
out_unlock:
ocfs2_rw_unlock(inode, 1);
out:
- inode_double_unlock(inode, pipe->inode);
+ mutex_unlock(&inode->i_mutex);
mlog_exit(ret);
return ret;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a28840b..0e910b3 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -151,15 +151,22 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
int maps_protect;
EXPORT_SYMBOL(maps_protect);
-static struct fs_struct *get_fs_struct(struct task_struct *task)
+static int get_fs_path(struct task_struct *task, struct path *path, bool root)
{
struct fs_struct *fs;
+ int result = -ENOENT;
+
task_lock(task);
fs = task->fs;
- if(fs)
- atomic_inc(&fs->count);
+ if (fs) {
+ read_lock(&fs->lock);
+ *path = root ? fs->root : fs->pwd;
+ path_get(path);
+ read_unlock(&fs->lock);
+ result = 0;
+ }
task_unlock(task);
- return fs;
+ return result;
}
static int get_nr_threads(struct task_struct *tsk)
@@ -178,42 +185,24 @@ static int get_nr_threads(struct task_struct *tsk)
static int proc_cwd_link(struct inode *inode, struct path *path)
{
struct task_struct *task = get_proc_task(inode);
- struct fs_struct *fs = NULL;
int result = -ENOENT;
if (task) {
- fs = get_fs_struct(task);
+ result = get_fs_path(task, path, 0);
put_task_struct(task);
}
- if (fs) {
- read_lock(&fs->lock);
- *path = fs->pwd;
- path_get(&fs->pwd);
- read_unlock(&fs->lock);
- result = 0;
- put_fs_struct(fs);
- }
return result;
}
static int proc_root_link(struct inode *inode, struct path *path)
{
struct task_struct *task = get_proc_task(inode);
- struct fs_struct *fs = NULL;
int result = -ENOENT;
if (task) {
- fs = get_fs_struct(task);
+ result = get_fs_path(task, path, 1);
put_task_struct(task);
}
- if (fs) {
- read_lock(&fs->lock);
- *path = fs->root;
- path_get(&fs->root);
- read_unlock(&fs->lock);
- result = 0;
- put_fs_struct(fs);
- }
return result;
}
@@ -575,7 +564,6 @@ static int mounts_open_common(struct inode *inode, struct file *file,
struct task_struct *task = get_proc_task(inode);
struct nsproxy *nsp;
struct mnt_namespace *ns = NULL;
- struct fs_struct *fs = NULL;
struct path root;
struct proc_mounts *p;
int ret = -EINVAL;
@@ -589,22 +577,16 @@ static int mounts_open_common(struct inode *inode, struct file *file,
get_mnt_ns(ns);
}
rcu_read_unlock();
- if (ns)
- fs = get_fs_struct(task);
+ if (ns && get_fs_path(task, &root, 1) == 0)
+ ret = 0;
put_task_struct(task);
}
if (!ns)
goto err;
- if (!fs)
+ if (ret)
goto err_put_ns;
- read_lock(&fs->lock);
- root = fs->root;
- path_get(&root);
- read_unlock(&fs->lock);
- put_fs_struct(fs);
-
ret = -ENOMEM;
p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
if (!p)
diff --git a/fs/splice.c b/fs/splice.c
index 6d310c7..aea1eb4 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -735,10 +735,19 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
* ->commit_write. Most of the time, these expect i_mutex to
* be held. Since this may result in an ABBA deadlock with
* pipe->inode, we have to order lock acquiry here.
+ *
+ * Outer lock must be inode->i_mutex, as pipe_wait() will
+ * release and reacquire pipe->inode->i_mutex, AND inode must
+ * never be a pipe.
*/
- inode_double_lock(inode, pipe->inode);
+ WARN_ON(S_ISFIFO(inode->i_mode));
+ mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
+ if (pipe->inode)
+ mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
ret = __splice_from_pipe(pipe, &sd, actor);
- inode_double_unlock(inode, pipe->inode);
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+ mutex_unlock(&inode->i_mutex);
return ret;
}
@@ -829,11 +838,17 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
};
ssize_t ret;
- inode_double_lock(inode, pipe->inode);
+ WARN_ON(S_ISFIFO(inode->i_mode));
+ mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
ret = file_remove_suid(out);
- if (likely(!ret))
+ if (likely(!ret)) {
+ if (pipe->inode)
+ mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
- inode_double_unlock(inode, pipe->inode);
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+ }
+ mutex_unlock(&inode->i_mutex);
if (ret > 0) {
unsigned long nr_pages;
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 28863f4..dc09ff6 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -366,7 +366,21 @@ typedef struct kernel_cap_struct {
#define CAP_FOR_EACH_U32(__capi) \
for (__capi = 0; __capi < _KERNEL_CAPABILITY_U32S; ++__capi)
+/*
+ * CAP_FS_MASK and CAP_NFSD_MASKS:
+ *
+ * The fs mask is all the privileges that fsuid==0 historically meant.
+ * At one time in the past, that included CAP_MKNOD and CAP_LINUX_IMMUTABLE.
+ *
+ * It has never meant setting security.* and trusted.* xattrs.
+ *
+ * We could also define fsmask as follows:
+ * 1. CAP_FS_MASK is the privilege to bypass all fs-related DAC permissions
+ * 2. The security.* and trusted.* xattrs are fs-related MAC permissions
+ */
+
# define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \
+ | CAP_TO_MASK(CAP_MKNOD) \
| CAP_TO_MASK(CAP_DAC_OVERRIDE) \
| CAP_TO_MASK(CAP_DAC_READ_SEARCH) \
| CAP_TO_MASK(CAP_FOWNER) \
@@ -381,11 +395,12 @@ typedef struct kernel_cap_struct {
# define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }})
# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }})
# define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
-# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } })
+# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \
+ | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \
+ CAP_FS_MASK_B1 } })
# define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \
- | CAP_TO_MASK(CAP_SYS_RESOURCE) \
- | CAP_TO_MASK(CAP_MKNOD), \
- CAP_FS_MASK_B1 } })
+ | CAP_TO_MASK(CAP_SYS_RESOURCE), \
+ CAP_FS_MASK_B1 } })
#endif /* _KERNEL_CAPABILITY_U32S != 2 */
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 450684f..f5cd050 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -234,7 +234,7 @@
#define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */
#define PCI_PM_CTRL 4 /* PM control and status register */
#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
-#define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */
+#define PCI_PM_CTRL_NO_SOFT_RESET 0x0008 /* No reset for D3hot->D0 */
#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 03e0902..09c5851 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -201,7 +201,8 @@ extern unsigned long long time_sync_thresh;
#define task_is_stopped_or_traced(task) \
((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
#define task_contributes_to_load(task) \
- ((task->state & TASK_UNINTERRUPTIBLE) != 0)
+ ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
+ (task->flags & PF_FROZEN) == 0)
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
diff --git a/kernel/exit.c b/kernel/exit.c
index 14096a1..8715136 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -938,8 +938,7 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
*/
if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
(tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
- tsk->self_exec_id != tsk->parent_exec_id) &&
- !capable(CAP_KILL))
+ tsk->self_exec_id != tsk->parent_exec_id))
tsk->exit_signal = SIGCHLD;
signal = tracehook_notify_death(tsk, &cookie, group_dead);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 75bc2cd..0920fa0 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -890,10 +890,8 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
ri->rp = rp;
ri->task = current;
- if (rp->entry_handler && rp->entry_handler(ri, regs)) {
- spin_unlock_irqrestore(&rp->lock, flags);
+ if (rp->entry_handler && rp->entry_handler(ri, regs))
return 0;
- }
arch_prepare_kretprobe(ri, regs);
diff --git a/kernel/signal.c b/kernel/signal.c
index 3d161f0..7d0a222 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1549,7 +1549,15 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)
read_lock(&tasklist_lock);
if (may_ptrace_stop()) {
do_notify_parent_cldstop(current, CLD_TRAPPED);
+ /*
+ * Don't want to allow preemption here, because
+ * sys_ptrace() needs this task to be inactive.
+ *
+ * XXX: implement read_unlock_no_resched().
+ */
+ preempt_disable();
read_unlock(&tasklist_lock);
+ preempt_enable_no_resched();
schedule();
} else {
/*
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index b5167df..e8b2b18 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -89,8 +89,8 @@ do_xip_mapping_read(struct address_space *mapping,
}
}
nr = nr - offset;
- if (nr > len)
- nr = len;
+ if (nr > len - copied)
+ nr = len - copied;
error = mapping->a_ops->get_xip_mem(mapping, index, 0,
&xip_mem, &xip_pfn);
diff --git a/mm/mmap.c b/mm/mmap.c
index ca12a93..2ae093e 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2068,6 +2068,9 @@ void exit_mmap(struct mm_struct *mm)
arch_exit_mmap(mm);
mmu_notifier_release(mm);
+ if (!mm->mmap) /* Can happen if dup_mmap() received an OOM */
+ return;
+
lru_add_drain();
flush_cache_mm(mm);
tlb = tlb_gather_mmu(mm, 1);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 63c18aa..2043c8e 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -419,7 +419,6 @@ err2:
err1:
kobject_del(&p->kobj);
err0:
- kobject_put(&p->kobj);
dev_set_promiscuity(dev, -1);
put_back:
dev_put(dev);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 03e83a6..6671485 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -372,7 +372,9 @@ static int mark_source_chains(struct xt_table_info *newinfo,
&& unconditional(&e->arp)) || visited) {
unsigned int oldpos, size;
- if (t->verdict < -NF_MAX_VERDICT - 1) {
+ if ((strcmp(t->target.u.user.name,
+ ARPT_STANDARD_TARGET) == 0) &&
+ t->verdict < -NF_MAX_VERDICT - 1) {
duprintf("mark_source_chains: bad "
"negative verdict (%i)\n",
t->verdict);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 4e7c719..b56a203 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -502,7 +502,9 @@ mark_source_chains(struct xt_table_info *newinfo,
&& unconditional(&e->ip)) || visited) {
unsigned int oldpos, size;
- if (t->verdict < -NF_MAX_VERDICT - 1) {
+ if ((strcmp(t->target.u.user.name,
+ IPT_STANDARD_TARGET) == 0) &&
+ t->verdict < -NF_MAX_VERDICT - 1) {
duprintf("mark_source_chains: bad "
"negative verdict (%i)\n",
t->verdict);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 1646a56..4494cb6 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -210,11 +210,11 @@ unique:
if (twp != NULL) {
*twp = tw;
- NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED);
+ NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED);
} else if (tw != NULL) {
/* Silly. Should hash-dance instead... */
inet_twsk_deschedule(tw, death_row);
- NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITRECYCLED);
+ NET_INC_STATS_BH(net, LINUX_MIB_TIMEWAITRECYCLED);
inet_twsk_put(tw);
}
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 7e14ccc..e55427d 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -74,8 +74,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
!idev || unlikely(idev->cnf.disable_ipv6)) {
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS);
- rcu_read_unlock();
- goto out;
+ goto drop;
}
memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
@@ -145,7 +144,6 @@ err:
drop:
rcu_read_unlock();
kfree_skb(skb);
-out:
return 0;
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 0b4557e..81751c3 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -529,7 +529,9 @@ mark_source_chains(struct xt_table_info *newinfo,
&& unconditional(&e->ipv6)) || visited) {
unsigned int oldpos, size;
- if (t->verdict < -NF_MAX_VERDICT - 1) {
+ if ((strcmp(t->target.u.user.name,
+ IP6T_STANDARD_TARGET) == 0) &&
+ t->verdict < -NF_MAX_VERDICT - 1) {
duprintf("mark_source_chains: bad "
"negative verdict (%i)\n",
t->verdict);
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6f61261..fcbc6b9 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -15,6 +15,7 @@
#include <linux/skbuff.h>
#include <linux/ipv6.h>
#include <net/ip6_checksum.h>
+#include <asm/unaligned.h>
#include <net/tcp.h>
@@ -466,7 +467,7 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
for (i = 0;
i < (opsize - TCPOLEN_SACK_BASE);
i += TCPOLEN_SACK_PERBLOCK) {
- tmp = ntohl(*((__be32 *)(ptr+i)+1));
+ tmp = get_unaligned_be32((__be32 *)(ptr+i)+1);
if (after(tmp, *sack))
*sack = tmp;
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 9f1ea4a..db9e263 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1082,7 +1082,13 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,
SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n");
- /* Build a packet */
+ /* Build a packet - the conventional user limit is 236 bytes. We can
+ do ludicrously large NetROM frames but must not overflow */
+ if (len > 65536) {
+ err = -EMSGSIZE;
+ goto out;
+ }
+
SOCK_DEBUG(sk, "NET/ROM: sendto: building packet.\n");
size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index a7f1ce1..c062361 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1120,6 +1120,10 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
/* Build a packet */
SOCK_DEBUG(sk, "ROSE: sendto: building packet.\n");
+ /* Sanity check the packet size */
+ if (len > 65535)
+ return -EMSGSIZE;
+
size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN;
if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 4c8d9f4..905fda5 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -111,7 +111,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
if (sctp_addip_enable) {
auth_chunks->chunks[0] = SCTP_CID_ASCONF;
auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK;
- auth_chunks->param_hdr.length += htons(2);
+ auth_chunks->param_hdr.length =
+ htons(sizeof(sctp_paramhdr_t) + 2);
}
}
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 9fc5b02..88d80f5 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -1037,6 +1037,12 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
sx25.sx25_addr = x25->dest_addr;
}
+ /* Sanity check the packet size */
+ if (len > 65535) {
+ rc = -EMSGSIZE;
+ goto out;
+ }
+
SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");
/* Build a packet */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 03fc6a8..f028f70 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4467,6 +4467,7 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
if (err)
return err;
err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+ if (err)
return err;
err = sel_netnode_sid(addrp, family, &node_sid);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 87d7541..b802923 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -604,6 +604,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
if (!capable(CAP_MAC_ADMIN))
rc = -EPERM;
+ if (size == 0)
+ rc = -EINVAL;
} else
rc = cap_inode_setxattr(dentry, name, value, size, flags);
@@ -1360,7 +1362,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
struct socket *sock;
int rc = 0;
- if (value == NULL || size > SMK_LABELLEN)
+ if (value == NULL || size > SMK_LABELLEN || size == 0)
return -EACCES;
sp = smk_import(value, size);
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 8c857d5..026f723 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3220,7 +3220,7 @@ static const char *ad1884_slave_vols[] = {
"Mic Playback Volume",
"CD Playback Volume",
"Internal Mic Playback Volume",
- "Docking Mic Playback Volume"
+ "Docking Mic Playback Volume",
"Beep Playback Volume",
"IEC958 Playback Volume",
NULL
next prev parent reply other threads:[~2009-05-02 20:07 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-02 20:05 Linux 2.6.27.21 Greg KH
2009-05-02 20:05 ` Greg KH [this message]
-- strict thread matches above, loose matches on Subject: below --
2009-03-23 22:10 Greg KH
2009-03-23 22:10 ` Greg KH
2009-05-08 6:45 ` Jesper Krogh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090502200528.GD7287@kroah.com \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.