Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754904Ab2JNRPN (ORCPT ); Sun, 14 Oct 2012 13:15:13 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:48106 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754732Ab2JNRPJ (ORCPT ); Sun, 14 Oct 2012 13:15:09 -0400 Message-ID: <1350234882.26833.15.camel@deadeye.wl.decadent.org.uk> Subject: Re: [ 000/147] 3.2.32-stable review From: Ben Hutchings To: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk Date: Sun, 14 Oct 2012 18:14:42 +0100 In-Reply-To: <20121014143533.742627615@decadent.org.uk> References: <20121014143533.742627615@decadent.org.uk> Content-Type: multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature"; boundary="=-UP35LHFiwNqpaaZIDlSp" X-Mailer: Evolution 3.4.3-1 Mime-Version: 1.0 X-SA-Exim-Connect-IP: 77.75.106.1 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 213148 Lines: 6642 --=-UP35LHFiwNqpaaZIDlSp Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable diff --git a/Documentation/virtual/lguest/lguest.c b/Documentation/virtual/= lguest/lguest.c index c095d79..288dba6 100644 --- a/Documentation/virtual/lguest/lguest.c +++ b/Documentation/virtual/lguest/lguest.c @@ -1299,6 +1299,7 @@ static struct device *new_device(const char *name, u1= 6 type) dev->feature_len =3D 0; dev->num_vq =3D 0; dev->running =3D false; + dev->next =3D NULL; =20 /* * Append to device list. Prepending to a single-linked list is diff --git a/Makefile b/Makefile index fd9c414..9203135 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION =3D 3 PATCHLEVEL =3D 2 -SUBLEVEL =3D 31 -EXTRAVERSION =3D +SUBLEVEL =3D 32 +EXTRAVERSION =3D -rc1 NAME =3D Saber-toothed Squirrel =20 # *DOCUMENTATION* diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_= 32k.c index a6cbb71..04e703a 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -82,22 +82,29 @@ static void notrace omap_update_sched_clock(void) * nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles; static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK(read_persistent_clock_lock); + void read_persistent_clock(struct timespec *ts) { unsigned long long nsecs; - cycles_t delta; - struct timespec *tsp =3D &persistent_ts; + cycles_t last_cycles; + unsigned long flags; + + spin_lock_irqsave(&read_persistent_clock_lock, flags); =20 last_cycles =3D cycles; cycles =3D timer_32k_base ? __raw_readl(timer_32k_base) : 0; - delta =3D cycles - last_cycles; =20 - nsecs =3D clocksource_cyc2ns(delta, persistent_mult, persistent_shift); + nsecs =3D clocksource_cyc2ns(cycles - last_cycles, + persistent_mult, persistent_shift); + + timespec_add_ns(&persistent_ts, nsecs); + + *ts =3D persistent_ts; =20 - timespec_add_ns(tsp, nsecs); - *ts =3D *tsp; + spin_unlock_irqrestore(&read_persistent_clock_lock, flags); } =20 int __init omap_init_clocksource_32k(void) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 0be3186..aaf7444 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -224,7 +224,7 @@ KBUILD_CPPFLAGS +=3D -D"DATAOFFSET=3D$(if $(dataoffset-= y),$(dataoffset-y),0)" LDFLAGS +=3D -m $(ld-emul) =20 ifdef CONFIG_MIPS -CHECKFLAGS +=3D $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \ +CHECKFLAGS +=3D $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ sed -e "s/^\#define /-D'/" -e "s/ /'=3D'/" -e "s/$$/'/") ifdef CONFIG_64BIT diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 1a96618..ce7dd99 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -102,7 +102,7 @@ obj-$(CONFIG_MIPS_MACHINE) +=3D mips_machine.o =20 obj-$(CONFIG_OF) +=3D prom.o =20 -CFLAGS_cpu-bugs64.o =3D $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -= o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI";= fi) +CFLAGS_cpu-bugs64.o =3D $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -= o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"= ; fi) =20 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) +=3D 8250-platform.o =20 diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile index 7120282..3eb4a52 100644 --- a/arch/mn10300/Makefile +++ b/arch/mn10300/Makefile @@ -26,7 +26,7 @@ CHECKFLAGS +=3D PROCESSOR :=3D unset UNIT :=3D unset =20 -KBUILD_CFLAGS +=3D -mam33 -mmem-funcs -DCPU=3DAM33 +KBUILD_CFLAGS +=3D -mam33 -DCPU=3DAM33 $(call cc-option,-mmem-funcs,) KBUILD_AFLAGS +=3D -mam33 -DCPU=3DAM33 =20 ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y) diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/pla= tforms/pseries/eeh_driver.c index 1b6cb10..a0a4e8a 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,41 @@ static inline const char * pcid_name (struct pci_dev *pd= ev) return ""; } =20 +/** + * eeh_pcid_get - Get the PCI device driver + * @pdev: PCI device + * + * The function is used to retrieve the PCI device driver for + * the indicated PCI device. Besides, we will increase the reference + * of the PCI device driver to prevent that being unloaded on + * the fly. Otherwise, kernel crash would be seen. + */ +static inline struct pci_driver *eeh_pcid_get(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return NULL; + + if (!try_module_get(pdev->driver->driver.owner)) + return NULL; + + return pdev->driver; +} + +/** + * eeh_pcid_put - Dereference on the PCI device driver + * @pdev: PCI device + * + * The function is called to do dereference on the PCI device + * driver of the indicated PCI device. + */ +static inline void eeh_pcid_put(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return; + + module_put(pdev->driver->driver.owner); +} + #if 0 static void print_device_node_tree(struct pci_dn *pdn, int dent) { @@ -109,18 +145,20 @@ static void eeh_enable_irq(struct pci_dev *dev) static int eeh_report_error(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res =3D userdata; - struct pci_driver *driver =3D dev->driver; + struct pci_driver *driver; =20 dev->error_state =3D pci_channel_io_frozen; =20 - if (!driver) - return 0; + driver =3D eeh_pcid_get(dev); + if (!driver) return 0; =20 eeh_disable_irq(dev); =20 if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } =20 rc =3D driver->err_handler->error_detected (dev, pci_channel_io_frozen); =20 @@ -128,6 +166,7 @@ static int eeh_report_error(struct pci_dev *dev, void *= userdata) if (rc =3D=3D PCI_ERS_RESULT_NEED_RESET) *res =3D rc; if (*res =3D=3D PCI_ERS_RESULT_NONE) *res =3D rc; =20 + eeh_pcid_put(dev); return 0; } =20 @@ -142,12 +181,15 @@ static int eeh_report_error(struct pci_dev *dev, void= *userdata) static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res =3D userdata; - struct pci_driver *driver =3D dev->driver; + struct pci_driver *driver; =20 - if (!driver || - !driver->err_handler || - !driver->err_handler->mmio_enabled) + driver =3D eeh_pcid_get(dev); + if (!driver) return 0; + if (!driver->err_handler || + !driver->err_handler->mmio_enabled) { + eeh_pcid_put(dev); return 0; + } =20 rc =3D driver->err_handler->mmio_enabled (dev); =20 @@ -155,6 +197,7 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev,= void *userdata) if (rc =3D=3D PCI_ERS_RESULT_NEED_RESET) *res =3D rc; if (*res =3D=3D PCI_ERS_RESULT_NONE) *res =3D rc; =20 + eeh_pcid_put(dev); return 0; } =20 @@ -165,18 +208,20 @@ static int eeh_report_mmio_enabled(struct pci_dev *de= v, void *userdata) static int eeh_report_reset(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res =3D userdata; - struct pci_driver *driver =3D dev->driver; - - if (!driver) - return 0; + struct pci_driver *driver; =20 dev->error_state =3D pci_channel_io_normal; =20 + driver =3D eeh_pcid_get(dev); + if (!driver) return 0; + eeh_enable_irq(dev); =20 if (!driver->err_handler || - !driver->err_handler->slot_reset) + !driver->err_handler->slot_reset) { + eeh_pcid_put(dev); return 0; + } =20 rc =3D driver->err_handler->slot_reset(dev); if ((*res =3D=3D PCI_ERS_RESULT_NONE) || @@ -184,6 +229,7 @@ static int eeh_report_reset(struct pci_dev *dev, void *= userdata) if (*res =3D=3D PCI_ERS_RESULT_DISCONNECT && rc =3D=3D PCI_ERS_RESULT_NEED_RESET) *res =3D rc; =20 + eeh_pcid_put(dev); return 0; } =20 @@ -193,21 +239,24 @@ static int eeh_report_reset(struct pci_dev *dev, void= *userdata) =20 static int eeh_report_resume(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver =3D dev->driver; + struct pci_driver *driver; =20 dev->error_state =3D pci_channel_io_normal; =20 - if (!driver) - return 0; + driver =3D eeh_pcid_get(dev); + if (!driver) return 0; =20 eeh_enable_irq(dev); =20 if (!driver->err_handler || - !driver->err_handler->resume) + !driver->err_handler->resume) { + eeh_pcid_put(dev); return 0; + } =20 driver->err_handler->resume(dev); =20 + eeh_pcid_put(dev); return 0; } =20 @@ -220,21 +269,24 @@ static int eeh_report_resume(struct pci_dev *dev, voi= d *userdata) =20 static int eeh_report_failure(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver =3D dev->driver; + struct pci_driver *driver; =20 dev->error_state =3D pci_channel_io_perm_failure; =20 - if (!driver) - return 0; + driver =3D eeh_pcid_get(dev); + if (!driver) return 0; =20 eeh_disable_irq(dev); =20 if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } =20 driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); =20 + eeh_pcid_put(dev); return 0; } =20 diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.= h index 18601c8..884507e 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -146,8 +146,7 @@ static inline unsigned long pmd_pfn(pmd_t pmd) =20 static inline int pmd_large(pmd_t pte) { - return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) =3D=3D - (_PAGE_PSE | _PAGE_PRESENT); + return pmd_flags(pte) & _PAGE_PSE; } =20 #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -415,7 +414,13 @@ static inline int pte_hidden(pte_t pte) =20 static inline int pmd_present(pmd_t pmd) { - return pmd_flags(pmd) & _PAGE_PRESENT; + /* + * Checking for _PAGE_PSE is needed too because + * split_huge_page will temporarily clear the present bit (but + * the _PAGE_PSE flag will remain set at all times while the + * _PAGE_PRESENT bit is clear). + */ + return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE); } =20 static inline int pmd_none(pmd_t pmd) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 37718f0..4d320b2 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -731,6 +731,7 @@ void __init efi_enter_virtual_mode(void) * * Call EFI services through wrapper functions. */ + efi.runtime_version =3D efi_systab.fw_revision; efi.get_time =3D virt_efi_get_time; efi.set_time =3D virt_efi_set_time; efi.get_wakeup_time =3D virt_efi_get_wakeup_time; diff --git a/block/blk-core.c b/block/blk-core.c index 49d9e91..c76dfb2 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -580,7 +580,7 @@ blk_init_allocated_queue(struct request_queue *q, reque= st_fn_proc *rfn, q->request_fn =3D rfn; q->prep_rq_fn =3D NULL; q->unprep_rq_fn =3D NULL; - q->queue_flags =3D QUEUE_FLAG_DEFAULT; + q->queue_flags |=3D QUEUE_FLAG_DEFAULT; =20 /* Override internal queue lock with supplied lock pointer */ if (lock) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9ecec98..5016de5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -950,8 +950,6 @@ static int __init acpi_bus_init(void) status =3D acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ =20 - acpi_bus_osc_support(); - status =3D acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); @@ -959,6 +957,12 @@ static int __init acpi_bus_init(void) } =20 /* + * _OSC method may exist in module level code, + * so it must be run after ACPI_FULL_INITIALIZATION + */ + acpi_bus_osc_support(); + + /* * _PDC control method may load dynamic SSDT tables, * and we need to install the table handler before that. */ diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6f95d98..1f90dab 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -108,7 +108,7 @@ static struct usb_device_id btusb_table[] =3D { { USB_DEVICE(0x413c, 0x8197) }, =20 /* Foxconn - Hon Hai */ - { USB_DEVICE(0x0489, 0xe033) }, + { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, =20 /*Broadcom devices with vendor specific id */ { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index eedd547..5936691 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count= ) tmp[tpk_curr + 1] =3D '\0'; printk(KERN_INFO "%s%s", tpk_tag, tmp); tpk_curr =3D 0; - if (buf[i + 1] =3D=3D '\n') + if ((i + 1) < count && buf[i + 1] =3D=3D '\n') i++; break; case '\n': diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index b48967b..5991114 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -564,8 +564,8 @@ void dmaengine_get(void) list_del_rcu(&device->global_node); break; } else if (err) - pr_err("dmaengine: failed to get %s: (%d)\n", - dma_chan_name(chan), err); + pr_debug("%s: failed to get %s: (%d)\n", + __func__, dma_chan_name(chan), err); } } =20 diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 4799393..b97d4f0 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -471,8 +471,8 @@ static int ioctl_get_info(struct client *client, union = ioctl_arg *arg) client->bus_reset_closure =3D a->bus_reset_closure; if (a->bus_reset !=3D 0) { fill_bus_reset_event(&bus_reset, client); - ret =3D copy_to_user(u64_to_uptr(a->bus_reset), - &bus_reset, sizeof(bus_reset)); + /* unaligned size of bus_reset is 36 bytes */ + ret =3D copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36); } if (ret =3D=3D 0 && list_empty(&client->link)) list_add_tail(&client->link, &client->device->client_list); diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 0535c21..3e60e8d 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -435,12 +435,23 @@ efivar_attr_read(struct efivar_entry *entry, char *bu= f) if (status !=3D EFI_SUCCESS) return -EIO; =20 - if (var->Attributes & 0x1) + if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) str +=3D sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); - if (var->Attributes & 0x2) + if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) str +=3D sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); - if (var->Attributes & 0x4) + if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) str +=3D sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) + str +=3D sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); + if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) + str +=3D sprintf(str, + "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) + str +=3D sprintf(str, + "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) + str +=3D sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); return str - buf; } =20 diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_ge= m.c index e48e01e..33e1555 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1543,16 +1543,19 @@ i915_gem_object_move_to_active(struct drm_i915_gem_= object *obj, list_move_tail(&obj->ring_list, &ring->active_list); =20 obj->last_rendering_seqno =3D seqno; - if (obj->fenced_gpu_access) { - struct drm_i915_fence_reg *reg; - - BUG_ON(obj->fence_reg =3D=3D I915_FENCE_REG_NONE); =20 + if (obj->fenced_gpu_access) { obj->last_fenced_seqno =3D seqno; obj->last_fenced_ring =3D ring; =20 - reg =3D &dev_priv->fence_regs[obj->fence_reg]; - list_move_tail(®->lru_list, &dev_priv->mm.fence_list); + /* Bump MRU to take account of the delayed flush */ + if (obj->fence_reg !=3D I915_FENCE_REG_NONE) { + struct drm_i915_fence_reg *reg; + + reg =3D &dev_priv->fence_regs[obj->fence_reg]; + list_move_tail(®->lru_list, + &dev_priv->mm.fence_list); + } } } =20 @@ -1561,6 +1564,7 @@ i915_gem_object_move_off_active(struct drm_i915_gem_o= bject *obj) { list_del_init(&obj->ring_list); obj->last_rendering_seqno =3D 0; + obj->last_fenced_seqno =3D 0; } =20 static void @@ -1589,6 +1593,7 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_= object *obj) BUG_ON(!list_empty(&obj->gpu_write_list)); BUG_ON(!obj->active); obj->ring =3D NULL; + obj->last_fenced_ring =3D NULL; =20 i915_gem_object_move_off_active(obj); obj->fenced_gpu_access =3D false; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i= 915/i915_gem_execbuffer.c index a6c2f7a..1202198 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -574,7 +574,8 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *r= ing, if (ret) break; } - obj->pending_fenced_gpu_access =3D need_fence; + obj->pending_fenced_gpu_access =3D + !!(entry->flags & EXEC_OBJECT_NEEDS_FENCE); } =20 entry->offset =3D obj->gtt_offset; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/= i915_gem_tiling.c index 31d334d..861223b 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -107,10 +107,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) */ swizzle_x =3D I915_BIT_6_SWIZZLE_NONE; swizzle_y =3D I915_BIT_6_SWIZZLE_NONE; - } else if (IS_MOBILE(dev)) { + } else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) { uint32_t dcc; =20 - /* On mobile 9xx chipsets, channel interleave by the CPU is + /* On 9xx chipsets, channel interleave by the CPU is * determined by DCC. For single-channel, neither the CPU * nor the GPU do swizzling. For dual channel interleaved, * the GPU's interleave is bit 9 and 10 for X tiled, and bit diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_ir= q.c index c8b5bc1..2812d7b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -530,6 +530,12 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_GSE_IVB) intel_opregion_gse_intr(dev); =20 + if (de_iir & DE_PIPEA_VBLANK_IVB) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK_IVB) + drm_handle_vblank(dev, 1); + if (de_iir & DE_PLANEA_FLIP_DONE_IVB) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -540,12 +546,6 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } =20 - if (de_iir & DE_PIPEA_VBLANK_IVB) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK_IVB) - drm_handle_vblank(dev, 1); - /* check event from PCH */ if (de_iir & DE_PCH_EVENT_IVB) { if (pch_iir & SDE_HOTPLUG_MASK_CPT) @@ -622,6 +622,12 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_GSE) intel_opregion_gse_intr(dev); =20 + if (de_iir & DE_PIPEA_VBLANK) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK) + drm_handle_vblank(dev, 1); + if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -632,12 +638,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } =20 - if (de_iir & DE_PIPEA_VBLANK) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK) - drm_handle_vblank(dev, 1); - /* check event from PCH */ if (de_iir & DE_PCH_EVENT) { if (pch_iir & hotplug_mask) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_re= g.h index 4a5e662..a294a32 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -401,6 +401,9 @@ # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 11) =20 +#define GEN6_GT_MODE 0x20d0 +#define GEN6_GT_MODE_HI (1 << 9) + #define GFX_MODE 0x02520 #define GFX_MODE_GEN7 0x0229c #define GFX_RUN_LIST_ENABLE (1<<15) @@ -1557,6 +1560,10 @@ =20 /* Video Data Island Packet control */ #define VIDEO_DIP_DATA 0x61178 +/* Read the description of VIDEO_DIP_DATA (before Haswel) or VIDEO_DIP_ECC + * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to eac= h byte + * of the infoframe structure specified by CEA-861. */ +#define VIDEO_DIP_DATA_SIZE 32 #define VIDEO_DIP_CTL 0x61170 #define VIDEO_DIP_ENABLE (1 << 31) #define VIDEO_DIP_PORT_B (1 << 29) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/in= tel_display.c index 6c3fb44..adac0dd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2850,13 +2850,34 @@ static void intel_clear_scanline_wait(struct drm_de= vice *dev) I915_WRITE_CTL(ring, tmp); } =20 +static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) +{ + struct drm_device *dev =3D crtc->dev; + struct drm_i915_private *dev_priv =3D dev->dev_private; + unsigned long flags; + bool pending; + + if (atomic_read(&dev_priv->mm.wedged)) + return false; + + spin_lock_irqsave(&dev->event_lock, flags); + pending =3D to_intel_crtc(crtc)->unpin_work !=3D NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + + return pending; +} + static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { struct drm_device *dev =3D crtc->dev; + struct drm_i915_private *dev_priv =3D dev->dev_private; =20 if (crtc->fb =3D=3D NULL) return; =20 + wait_event(dev_priv->pending_flip_queue, + !intel_crtc_has_pending_flip(crtc)); + mutex_lock(&dev->struct_mutex); intel_finish_fb(crtc->fb); mutex_unlock(&dev->struct_mutex); @@ -5027,7 +5048,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, /* default to 8bpc */ pipeconf &=3D ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); if (is_dp) { - if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { pipeconf |=3D PIPECONF_BPP_6 | PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP; @@ -5495,7 +5516,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *cr= tc, /* determine panel color depth */ temp =3D I915_READ(PIPECONF(pipe)); temp &=3D ~PIPE_BPC_MASK; - dither =3D intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode); + dither =3D intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, adjusted_mode); switch (pipe_bpp) { case 18: temp |=3D PIPE_6BPC; @@ -6952,9 +6973,8 @@ static void do_intel_finish_page_flip(struct drm_devi= ce *dev, =20 atomic_clear_mask(1 << intel_crtc->plane, &obj->pending_flip.counter); - if (atomic_read(&obj->pending_flip) =3D=3D 0) - wake_up(&dev_priv->pending_flip_queue); =20 + wake_up(&dev_priv->pending_flip_queue); schedule_work(&work->work); =20 trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); @@ -7193,7 +7213,7 @@ static int intel_gen7_queue_flip(struct drm_device *d= ev, default: WARN_ONCE(1, "unknown plane in flip command\n"); ret =3D -ENODEV; - goto err; + goto err_unpin; } =20 ret =3D intel_ring_begin(ring, 4); @@ -8278,6 +8298,11 @@ static void gen6_init_clock_gating(struct drm_device= *dev) DISPPLANE_TRICKLE_FEED_DISABLE); intel_flush_display_plane(dev_priv, pipe); } + + /* The default value should be 0x200 according to docs, but the two + * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */ + I915_WRITE(GEN6_GT_MODE, 0xffff << 16); + I915_WRITE(GEN6_GT_MODE, GEN6_GT_MODE_HI << 16 | GEN6_GT_MODE_HI); } =20 static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_p= riv) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel= _hdmi.c index c2a64f4..497da2a 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -138,14 +138,20 @@ static void i9xx_write_infoframe(struct drm_encoder *= encoder, =20 I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags); =20 + mmiowb(); for (i =3D 0; i < len; i +=3D 4) { I915_WRITE(VIDEO_DIP_DATA, *data); data++; } + /* Write every possible data byte to force correct ECC calculation. */ + for (; i < VIDEO_DIP_DATA_SIZE; i +=3D 4) + I915_WRITE(VIDEO_DIP_DATA, 0); + mmiowb(); =20 flags |=3D intel_infoframe_flags(frame); =20 I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags); + POSTING_READ(VIDEO_DIP_CTL); } =20 static void ironlake_write_infoframe(struct drm_encoder *encoder, @@ -168,14 +174,20 @@ static void ironlake_write_infoframe(struct drm_encod= er *encoder, =20 I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); =20 + mmiowb(); for (i =3D 0; i < len; i +=3D 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + /* Write every possible data byte to force correct ECC calculation. */ + for (; i < VIDEO_DIP_DATA_SIZE; i +=3D 4) + I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); + mmiowb(); =20 flags |=3D intel_infoframe_flags(frame); =20 I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); + POSTING_READ(reg); } static void intel_set_infoframe(struct drm_encoder *encoder, struct dip_infoframe *frame) @@ -546,10 +558,13 @@ void intel_hdmi_init(struct drm_device *dev, int sdvo= x_reg) if (!HAS_PCH_SPLIT(dev)) { intel_hdmi->write_infoframe =3D i9xx_write_infoframe; I915_WRITE(VIDEO_DIP_CTL, 0); + POSTING_READ(VIDEO_DIP_CTL); } else { intel_hdmi->write_infoframe =3D ironlake_write_infoframe; - for_each_pipe(i) + for_each_pipe(i) { I915_WRITE(TVIDEO_DIP_CTL(i), 0); + POSTING_READ(TVIDEO_DIP_CTL(i)); + } } =20 drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/ev= ergreen.c index fc0633c..b61f490 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -37,6 +37,16 @@ #define EVERGREEN_PFP_UCODE_SIZE 1120 #define EVERGREEN_PM4_UCODE_SIZE 1376 =20 +static const u32 crtc_offsets[6] =3D +{ + EVERGREEN_CRTC0_REGISTER_OFFSET, + EVERGREEN_CRTC1_REGISTER_OFFSET, + EVERGREEN_CRTC2_REGISTER_OFFSET, + EVERGREEN_CRTC3_REGISTER_OFFSET, + EVERGREEN_CRTC4_REGISTER_OFFSET, + EVERGREEN_CRTC5_REGISTER_OFFSET +}; + static void evergreen_gpu_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); void evergreen_pcie_gen2_enable(struct radeon_device *rdev); @@ -66,6 +76,27 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_d= evice *rdev) } } =20 +void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) +{ + int i; + + if (crtc >=3D rdev->num_crtc) + return; + + if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_= MASTER_EN) { + for (i =3D 0; i < rdev->usec_timeout; i++) { + if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CR= TC_V_BLANK)) + break; + udelay(1); + } + for (i =3D 0; i < rdev->usec_timeout; i++) { + if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC= _V_BLANK) + break; + udelay(1); + } + } +} + void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) { /* enable the pflip int */ @@ -1065,116 +1096,88 @@ void evergreen_agp_enable(struct radeon_device *rd= ev) =20 void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_sav= e *save) { + u32 crtc_enabled, tmp, frame_count, blackout; + int i, j; + save->vga_render_control =3D RREG32(VGA_RENDER_CONTROL); save->vga_hdp_control =3D RREG32(VGA_HDP_CONTROL); =20 - /* Stop all video */ + /* disable VGA render */ WREG32(VGA_RENDER_CONTROL, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (rdev->num_crtc >=3D 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - } - if (rdev->num_crtc >=3D 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); - } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >=3D 4) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >=3D 6) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >=3D 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >=3D 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + /* blank the display controllers */ + for (i =3D 0; i < rdev->num_crtc; i++) { + crtc_enabled =3D RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVER= GREEN_CRTC_MASTER_EN; + if (crtc_enabled) { + save->crtc_enabled[i] =3D true; + tmp =3D RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { + dce4_wait_for_vblank(rdev, i); + tmp |=3D EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + } + /* wait for the next frame */ + frame_count =3D radeon_get_vblank_counter(rdev, i); + for (j =3D 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) !=3D frame_count) + break; + udelay(1); + } + } } =20 - WREG32(D1VGA_CONTROL, 0); - WREG32(D2VGA_CONTROL, 0); - if (rdev->num_crtc >=3D 4) { - WREG32(EVERGREEN_D3VGA_CONTROL, 0); - WREG32(EVERGREEN_D4VGA_CONTROL, 0); - } - if (rdev->num_crtc >=3D 6) { - WREG32(EVERGREEN_D5VGA_CONTROL, 0); - WREG32(EVERGREEN_D6VGA_CONTROL, 0); + evergreen_mc_wait_for_idle(rdev); + + blackout =3D RREG32(MC_SHARED_BLACKOUT_CNTL); + if ((blackout & BLACKOUT_MODE_MASK) !=3D 1) { + /* Block CPU access */ + WREG32(BIF_FB_EN, 0); + /* blackout the MC */ + blackout &=3D ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); } } =20 void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_s= ave *save) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGI= STER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_RE= GISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_= OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTE= R_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGI= STER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_RE= GISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_= OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTE= R_OFFSET, - (u32)rdev->mc.vram_start); - - if (rdev->num_crtc >=3D 4) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REG= ISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_R= EGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER= _OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGIST= ER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REG= ISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_R= EGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER= _OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGIST= ER_OFFSET, - (u32)rdev->mc.vram_start); - } - if (rdev->num_crtc >=3D 6) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REG= ISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_R= EGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER= _OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGIST= ER_OFFSET, - (u32)rdev->mc.vram_start); + u32 tmp, frame_count; + int i, j; =20 - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REG= ISTER_OFFSET, + /* update crtc base addresses */ + for (i =3D 0; i < rdev->num_crtc; i++) { + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_R= EGISTER_OFFSET, + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER= _OFFSET, + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGIST= ER_OFFSET, + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], (u32)rdev->mc.vram_start); } - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vra= m_start)); WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); - /* Unlock host access */ + + /* unblackout the MC */ + tmp =3D RREG32(MC_SHARED_BLACKOUT_CNTL); + tmp &=3D ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); + /* allow CPU access */ + WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); + + for (i =3D 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled) { + tmp =3D RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + tmp &=3D ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + /* wait for the next frame */ + frame_count =3D radeon_get_vblank_counter(rdev, i); + for (j =3D 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) !=3D frame_count) + break; + udelay(1); + } + } + } + /* Unlock vga access */ WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); WREG32(VGA_RENDER_CONTROL, save->vga_render_control); diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeo= n/evergreen_reg.h index 7d7f215..e022776 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -210,7 +210,10 @@ #define EVERGREEN_CRTC_CONTROL 0x6e70 # define EVERGREEN_CRTC_MASTER_EN (1 << 0) # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) +#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 +# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) #define EVERGREEN_CRTC_STATUS 0x6e8c +# define EVERGREEN_CRTC_V_BLANK (1 << 0) #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 #define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/e= vergreend.h index 6ecd23f..fe44a95 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,10 @@ =20 #define CONFIG_MEMSIZE 0x5428 =20 +#define BIF_FB_EN 0x5490 +#define FB_READ_EN (1 << 0) +#define FB_WRITE_EN (1 << 1) + #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -194,6 +198,9 @@ #define NOOFCHAN_MASK 0x00003000 #define MC_SHARED_CHREMAP 0x2008 =20 +#define MC_SHARED_BLACKOUT_CNTL 0x20ac +#define BLACKOUT_MODE_MASK 0x00000007 + #define MC_ARB_RAMCFG 0x2760 #define NOOFBANK_SHIFT 0 #define NOOFBANK_MASK 0x00000003 diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/= radeon_asic.h index 5ce9402..5aa6670 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -386,6 +386,7 @@ void r700_cp_fini(struct radeon_device *rdev); struct evergreen_mc_save { u32 vga_render_control; u32 vga_hdp_control; + bool crtc_enabled[RADEON_MAX_CRTCS]; }; =20 void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/rade= on/radeon_irq_kms.c index baa019e..4f9496e 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -143,6 +143,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev) (rdev->pdev->subsystem_device =3D=3D 0x01fd)) return true; =20 + /* Gateway RS690 only seems to work with MSIs. */ + if ((rdev->pdev->device =3D=3D 0x791f) && + (rdev->pdev->subsystem_vendor =3D=3D 0x107b) && + (rdev->pdev->subsystem_device =3D=3D 0x0185)) + return true; + + /* try and enable MSIs by default on all RS690s */ + if (rdev->family =3D=3D CHIP_RS690) + return true; + /* RV515 seems to have MSI issues where it loses * MSI rearms occasionally. This leads to lockups and freezes. * disable it by default. diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/ra= deon_pm.c index 78a665b..ebd6c51 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -553,7 +553,9 @@ void radeon_pm_suspend(struct radeon_device *rdev) void radeon_pm_resume(struct radeon_device *rdev) { /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >=3D CHIP_BARTS) && + (rdev->family <=3D CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); @@ -608,7 +610,9 @@ int radeon_pm_init(struct radeon_device *rdev) radeon_pm_print_states(rdev); radeon_pm_init_profile(rdev); /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >=3D CHIP_BARTS) && + (rdev->family <=3D CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband= /ulp/ipoib/ipoib_main.c index fe2fdbb..1740b82 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -148,7 +148,7 @@ static int ipoib_stop(struct net_device *dev) =20 netif_stop_queue(dev); =20 - ipoib_ib_dev_down(dev, 0); + ipoib_ib_dev_down(dev, 1); ipoib_ib_dev_stop(dev, 0); =20 if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infin= iband/ulp/ipoib/ipoib_multicast.c index e5069b4..80799c0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -190,7 +190,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *= mcast, =20 mcast->mcmember =3D *mcmember; =20 - /* Set the cached Q_Key before we attach if it's the broadcast group */ + /* Set the multicast MTU and cached Q_Key before we attach if it's + * the broadcast group. + */ if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4, sizeof (union ib_gid))) { spin_lock_irq(&priv->lock); @@ -198,10 +200,17 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast= *mcast, spin_unlock_irq(&priv->lock); return -EAGAIN; } + priv->mcast_mtu =3D IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcm= ember.mtu)); priv->qkey =3D be32_to_cpu(priv->broadcast->mcmember.qkey); spin_unlock_irq(&priv->lock); priv->tx_wr.wr.ud.remote_qkey =3D priv->qkey; set_qkey =3D 1; + + if (!ipoib_cm_admin_enabled(dev)) { + rtnl_lock(); + dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); + rtnl_unlock(); + } } =20 if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { @@ -590,14 +599,6 @@ void ipoib_mcast_join_task(struct work_struct *work) return; } =20 - priv->mcast_mtu =3D IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcme= mber.mtu)); - - if (!ipoib_cm_admin_enabled(dev)) { - rtnl_lock(); - dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); - rtnl_unlock(); - } - ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n"); =20 clear_bit(IPOIB_MCAST_RUN, &priv->flags); diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/s= rp/ib_srp.c index c76b051..4ec049d 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -620,9 +620,9 @@ static void srp_reset_req(struct srp_target_port *targe= t, struct srp_request *re struct scsi_cmnd *scmnd =3D srp_claim_req(target, req, NULL); =20 if (scmnd) { + srp_free_req(target, req, scmnd, 0); scmnd->result =3D DID_RESET << 16; scmnd->scsi_done(scmnd); - srp_free_req(target, req, scmnd, 0); } } =20 @@ -1669,6 +1669,7 @@ static int srp_abort(struct scsi_cmnd *scmnd) SRP_TSK_ABORT_TASK); srp_free_req(target, req, scmnd, 0); scmnd->result =3D DID_ABORT << 16; + scmnd->scsi_done(scmnd); =20 return SUCCESS; } diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptic= s.c index 96532bc..7be5fd9 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -53,14 +53,19 @@ #define ABS_POS_BITS 13 =20 /* - * Any position values from the hardware above the following limits are - * treated as "wrapped around negative" values that have been truncated to - * the 13-bit reporting range of the hardware. These are just reasonable - * guesses and can be adjusted if hardware is found that operates outside - * of these parameters. + * These values should represent the absolute maximum value that will + * be reported for a positive position value. Some Synaptics firmware + * uses this value to indicate a finger near the edge of the touchpad + * whose precise position cannot be determined. + * + * At least one touchpad is known to report positions in excess of this + * value which are actually negative values truncated to the 13-bit + * reporting range. These values have never been observed to be lower + * than 8184 (i.e. -8), so we treat all values greater than 8176 as + * negative and any other value as positive. */ -#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2) -#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2) +#define X_MAX_POSITIVE 8176 +#define Y_MAX_POSITIVE 8176 =20 /* * Synaptics touchpads report the y coordinate from bottom to top, which i= s @@ -561,11 +566,21 @@ static int synaptics_parse_hw_state(const unsigned ch= ar buf[], hw->right =3D (buf[0] & 0x02) ? 1 : 0; } =20 - /* Convert wrap-around values to negative */ + /* + * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE + * is used by some firmware to indicate a finger at the edge of + * the touchpad whose precise position cannot be determined, so + * convert these values to the maximum axis value. + */ if (hw->x > X_MAX_POSITIVE) hw->x -=3D 1 << ABS_POS_BITS; + else if (hw->x =3D=3D X_MAX_POSITIVE) + hw->x =3D XMAX; + if (hw->y > Y_MAX_POSITIVE) hw->y -=3D 1 << ABS_POS_BITS; + else if (hw->y =3D=3D Y_MAX_POSITIVE) + hw->y =3D YMAX; =20 return 0; } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index ccf347f..b9062c0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -563,7 +563,9 @@ static void domain_update_iommu_coherency(struct dmar_d= omain *domain) { int i; =20 - domain->iommu_coherency =3D 1; + i =3D find_first_bit(&domain->iommu_bmp, g_num_of_iommus); + + domain->iommu_coherency =3D i < g_num_of_iommus ? 1 : 0; =20 for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { if (!ecap_coherent(g_iommus[i]->ecap)) { diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 0e49c99..c06992e 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1473,6 +1473,7 @@ static int ite_probe(struct pnp_dev *pdev, const stru= ct pnp_device_id rdev =3D rc_allocate_device(); if (!rdev) goto failure; + itdev->rdev =3D rdev; =20 ret =3D -ENODEV; =20 @@ -1604,7 +1605,6 @@ static int ite_probe(struct pnp_dev *pdev, const stru= ct pnp_device_id if (ret) goto failure; =20 - itdev->rdev =3D rdev; ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); =20 return 0; diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspc= a/pac7302.c index 1c44f78..6ddc769 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -1197,6 +1197,8 @@ static const struct usb_device_id device_table[] =3D = { {USB_DEVICE(0x093a, 0x2629), .driver_info =3D FL_VFLIP}, {USB_DEVICE(0x093a, 0x262a)}, {USB_DEVICE(0x093a, 0x262c)}, + {USB_DEVICE(0x145f, 0x013c)}, + {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */ {} }; MODULE_DEVICE_TABLE(usb, device_table); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index d5fe43d..bc27065 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2188,9 +2188,7 @@ static int omap_hsmmc_suspend(struct device *dev) } else { host->suspended =3D 0; if (host->pdata->resume) { - ret =3D host->pdata->resume(&pdev->dev, - host->slot_id); - if (ret) + if (host->pdata->resume(&pdev->dev, host->slot_id)) dev_dbg(mmc_dev(host->mmc), "Unmask interrupt failed\n"); } diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 0d33ff0..06af9e4 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -601,7 +601,7 @@ static int __devexit sdhci_s3c_remove(struct platform_d= evice *pdev) =20 sdhci_remove_host(host, 1); =20 - for (ptr =3D 0; ptr < 3; ptr++) { + for (ptr =3D 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index d5505f3..559d30d 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1003,6 +1003,10 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_= id) host->sd_error =3D true; dev_dbg(&host->pd->dev, "int err state =3D %08x\n", state); } + if (host->state =3D=3D STATE_IDLE) { + dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state); + return IRQ_HANDLED; + } if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) complete(&host->intr_wait); else diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-= nvram.c index e5bfd0e..0598d52 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -43,7 +43,8 @@ struct map_info autcpu12_sram_map =3D { =20 static int __init init_autcpu12_sram (void) { - int err, save0, save1; + map_word tmp, save0, save1; + int err; =20 autcpu12_sram_map.virt =3D ioremap(0x12000000, SZ_128K); if (!autcpu12_sram_map.virt) { @@ -51,7 +52,7 @@ static int __init init_autcpu12_sram (void) err =3D -EIO; goto out; } - simple_map_init(&autcpu_sram_map); + simple_map_init(&autcpu12_sram_map); =20 /* * Check for 32K/128K @@ -61,20 +62,22 @@ static int __init init_autcpu12_sram (void) * Read and check result on ofs 0x0 * Restore contents */ - save0 =3D map_read32(&autcpu12_sram_map,0); - save1 =3D map_read32(&autcpu12_sram_map,0x10000); - map_write32(&autcpu12_sram_map,~save0,0x10000); + save0 =3D map_read(&autcpu12_sram_map, 0); + save1 =3D map_read(&autcpu12_sram_map, 0x10000); + tmp.x[0] =3D ~save0.x[0]; + map_write(&autcpu12_sram_map, tmp, 0x10000); /* if we find this pattern on 0x0, we have 32K size * restore contents and exit */ - if ( map_read32(&autcpu12_sram_map,0) !=3D save0) { - map_write32(&autcpu12_sram_map,save0,0x0); + tmp =3D map_read(&autcpu12_sram_map, 0); + if (!map_word_equal(&autcpu12_sram_map, tmp, save0)) { + map_write(&autcpu12_sram_map, save0, 0x0); goto map; } /* We have a 128K found, restore 0x10000 and set size * to 128K */ - map_write32(&autcpu12_sram_map,save1,0x10000); + map_write(&autcpu12_sram_map, save1, 0x10000); autcpu12_sram_map.size =3D SZ_128K; =20 map: diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index a0bd2de..198da0a 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -748,6 +748,8 @@ static const char *default_mtd_part_types[] =3D { * partition parsers, specified in @types. However, if @types is %NULL, th= en * the default list of parsers is used. The default list contains only the * "cmdlinepart" and "ofpart" parsers ATM. + * Note: If there are more then one parser in @types, the kernel only take= s the + * partitions parsed out by the first parser. * * This function may return: * o a negative error code in case of failure @@ -772,11 +774,12 @@ int parse_mtd_partitions(struct mtd_info *master, con= st char **types, if (!parser) continue; ret =3D (*parser->parse_fn)(master, pparts, data); + put_partition_parser(parser); if (ret > 0) { printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); + break; } - put_partition_parser(parser); } return ret; } diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index f024375..532da04 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -390,7 +390,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t = *buf, /* Read the mirror version, if available */ if (md && (md->options & NAND_BBT_VERSION)) { scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, - mtd->writesize, td); + mtd->writesize, md); md->version[0] =3D buf[bbt_get_ver_offs(mtd, md)]; pr_info("Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 83e8e1b..ade0da0 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -2355,6 +2355,7 @@ static int __init ns_init_module(void) uint64_t new_size =3D (uint64_t)nsmtd->erasesize << overridesize; if (new_size >> overridesize !=3D nsmtd->erasesize) { NS_ERR("overridesize is too big\n"); + retval =3D -EINVAL; goto err_exit; } /* N.B. This relies on nand_scan not doing anything with the size before= we change it */ diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index f745f00..297c965 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1132,7 +1132,8 @@ static int omap_nand_remove(struct platform_device *p= dev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); - kfree(&info->mtd); + release_mem_region(info->phys_base, NAND_IO_SIZE); + kfree(info); return 0; } =20 diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 6c3fb5a..1f9c363 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -816,6 +816,11 @@ static int autoresize(struct ubi_device *ubi, int vol_= id) struct ubi_volume *vol =3D ubi->volumes[vol_id]; int err, old_reserved_pebs =3D vol->reserved_pebs; =20 + if (ubi->ro_mode) { + ubi_warn("skip auto-resize because of R/O mode"); + return 0; + } + /* * Clear the auto-resize flag in the volume in-memory copy of the * volume table, and 'ubi_resize_volume()' will propagate this change diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index b99318e..b2b62de 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -997,7 +997,7 @@ static int process_eb(struct ubi_device *ubi, struct ub= i_scan_info *si, return err; goto adjust_mean_ec; case UBI_IO_FF: - if (ec_err) + if (ec_err || bitflips) err =3D add_to_list(si, pnum, ec, 1, &si->erase); else err =3D add_to_list(si, pnum, ec, 0, &si->free); diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mp= c5xxx_can.c index 5fedc33..d8f2b5b 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -181,7 +181,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platf= orm_device *ofdev, =20 if (!clock_name || !strcmp(clock_name, "sys")) { sys_clk =3D clk_get(&ofdev->dev, "sys_clk"); - if (!sys_clk) { + if (IS_ERR(sys_clk)) { dev_err(&ofdev->dev, "couldn't get sys_clk\n"); goto exit_unmap; } @@ -204,7 +204,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platf= orm_device *ofdev, =20 if (clocksrc < 0) { ref_clk =3D clk_get(&ofdev->dev, "ref_clk"); - if (!ref_clk) { + if (IS_ERR(ref_clk)) { dev_err(&ofdev->dev, "couldn't get ref_clk\n"); goto exit_unmap; } diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/et= hernet/intel/e1000/e1000_main.c index 0549261..c5f6b0e 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -4720,8 +4720,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, boo= l *enable_wake) =20 netif_device_detach(netdev); =20 - mutex_lock(&adapter->mutex); - if (netif_running(netdev)) { WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); e1000_down(adapter); @@ -4729,10 +4727,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bo= ol *enable_wake) =20 #ifdef CONFIG_PM retval =3D pci_save_state(pdev); - if (retval) { - mutex_unlock(&adapter->mutex); + if (retval) return retval; - } #endif =20 status =3D er32(STATUS); @@ -4789,8 +4785,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, boo= l *enable_wake) if (netif_running(netdev)) e1000_free_irq(adapter); =20 - mutex_unlock(&adapter->mutex); - pci_disable_device(pdev); =20 return 0; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/re= altek/r8169.c index ed1be8a..4b43bc5 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -327,6 +327,8 @@ enum rtl_registers { Config0 =3D 0x51, Config1 =3D 0x52, Config2 =3D 0x53, +#define PME_SIGNAL (1 << 5) /* 8168c and later */ + Config3 =3D 0x54, Config4 =3D 0x55, Config5 =3D 0x56, @@ -1360,7 +1362,6 @@ static void __rtl8169_set_wol(struct rtl8169_private = *tp, u32 wolopts) u16 reg; u8 mask; } cfg[] =3D { - { WAKE_ANY, Config1, PMEnable }, { WAKE_PHY, Config3, LinkUp }, { WAKE_MAGIC, Config3, MagicPacket }, { WAKE_UCAST, Config5, UWF }, @@ -1368,16 +1369,32 @@ static void __rtl8169_set_wol(struct rtl8169_privat= e *tp, u32 wolopts) { WAKE_MCAST, Config5, MWF }, { WAKE_ANY, Config5, LanWake } }; + u8 options; =20 RTL_W8(Cfg9346, Cfg9346_Unlock); =20 for (i =3D 0; i < ARRAY_SIZE(cfg); i++) { - u8 options =3D RTL_R8(cfg[i].reg) & ~cfg[i].mask; + options =3D RTL_R8(cfg[i].reg) & ~cfg[i].mask; if (wolopts & cfg[i].opt) options |=3D cfg[i].mask; RTL_W8(cfg[i].reg, options); } =20 + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17: + options =3D RTL_R8(Config1) & ~PMEnable; + if (wolopts) + options |=3D PMEnable; + RTL_W8(Config1, options); + break; + default: + options =3D RTL_R8(Config2) & ~PME_SIGNAL; + if (wolopts) + options |=3D PME_SIGNAL; + RTL_W8(Config2, options); + break; + } + RTL_W8(Cfg9346, Cfg9346_Lock); } =20 diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 7145714..c0f097b 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -79,6 +79,7 @@ static int rionet_capable =3D 1; * on system trade-offs. */ static struct rio_dev **rionet_active; +static int nact; /* total number of active rionet peers */ =20 #define is_rionet_capable(src_ops, dst_ops) \ ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ @@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struc= t net_device *ndev) struct ethhdr *eth =3D (struct ethhdr *)skb->data; u16 destid; unsigned long flags; + int add_num =3D 1; =20 local_irq_save(flags); if (!spin_trylock(&rnet->tx_lock)) { @@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_buff *skb, stru= ct net_device *ndev) return NETDEV_TX_LOCKED; } =20 - if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) { + if (is_multicast_ether_addr(eth->h_dest)) + add_num =3D nact; + + if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { netif_stop_queue(ndev); spin_unlock_irqrestore(&rnet->tx_lock, flags); printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", @@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_buff *skb, str= uct net_device *ndev) } =20 if (is_multicast_ether_addr(eth->h_dest)) { + int count =3D 0; for (i =3D 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); i++) - if (rionet_active[i]) + if (rionet_active[i]) { rionet_queue_tx_msg(skb, ndev, rionet_active[i]); + if (count) + atomic_inc(&skb->users); + count++; + } } else if (RIONET_MAC_MATCH(eth->h_dest)) { destid =3D RIONET_GET_DESTID(eth->h_dest); if (rionet_active[destid]) @@ -220,14 +230,17 @@ static void rionet_dbell_event(struct rio_mport *mpor= t, void *dev_id, u16 sid, u if (info =3D=3D RIONET_DOORBELL_JOIN) { if (!rionet_active[sid]) { list_for_each_entry(peer, &rionet_peers, node) { - if (peer->rdev->destid =3D=3D sid) + if (peer->rdev->destid =3D=3D sid) { rionet_active[sid] =3D peer->rdev; + nact++; + } } rio_mport_send_doorbell(mport, sid, RIONET_DOORBELL_JOIN); } } else if (info =3D=3D RIONET_DOORBELL_LEAVE) { rionet_active[sid] =3D NULL; + nact--; } else { if (netif_msg_intr(rnet)) printk(KERN_WARNING "%s: unhandled doorbell\n", @@ -524,6 +537,7 @@ static int rionet_probe(struct rio_dev *rdev, const str= uct rio_device_id *id) =20 rc =3D rionet_setup_netdev(rdev->net->hport, ndev); rionet_check =3D 1; + nact =3D 0; } =20 /* diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/at= h/ath9k/pci.c index 1883d39..f7e17a0 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -122,8 +122,9 @@ static void ath_pci_aspm_init(struct ath_common *common= ) if (!parent) return; =20 - if (ah->btcoex_hw.scheme !=3D ATH_BTCOEX_CFG_NONE) { - /* Bluetooth coexistance requires disabling ASPM. */ + if ((ah->btcoex_hw.scheme !=3D ATH_BTCOEX_CFG_NONE) && + (AR_SREV_9285(ah))) { + /* Bluetooth coexistance requires disabling ASPM for AR9285. */ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); aspm &=3D ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index dfee1b3..9005380 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -658,8 +658,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, str= uct pci_dev *dev, int max, =20 /* Check if setup is sensible at all */ if (!pass && - (primary !=3D bus->number || secondary <=3D bus->number)) { - dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); + (primary !=3D bus->number || secondary <=3D bus->number || + secondary > subordinate)) { + dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), rec= onfiguring\n", + secondary, subordinate); broken =3D 1; } =20 diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 0860181..4f1b10b 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -519,6 +519,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter= *adapter, u64 wwpn, =20 rwlock_init(&port->unit_list_lock); INIT_LIST_HEAD(&port->unit_list); + atomic_set(&port->units, 0); =20 INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 96f13ad8..79a6afe 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -39,17 +39,23 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter) spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); } =20 -static int zfcp_ccw_activate(struct ccw_device *cdev) - +/** + * zfcp_ccw_activate - activate adapter and wait for it to finish + * @cdev: pointer to belonging ccw device + * @clear: Status flags to clear. + * @tag: s390dbf trace record tag + */ +static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag= ) { struct zfcp_adapter *adapter =3D zfcp_ccw_adapter_by_cdev(cdev); =20 if (!adapter) return 0; =20 + zfcp_erp_clear_adapter_status(adapter, clear); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ccresu2"); + tag); zfcp_erp_wait(adapter); flush_work(&adapter->scan_work); =20 @@ -164,26 +170,29 @@ static int zfcp_ccw_set_online(struct ccw_device *cde= v) BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); adapter->req_no =3D 0; =20 - zfcp_ccw_activate(cdev); + zfcp_ccw_activate(cdev, 0, "ccsonl1"); zfcp_ccw_adapter_put(adapter); return 0; } =20 /** - * zfcp_ccw_set_offline - set_offline function of zfcp driver + * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish * @cdev: pointer to belonging ccw device + * @set: Status flags to set. + * @tag: s390dbf trace record tag * * This function gets called by the common i/o layer and sets an adapter * into state offline. */ -static int zfcp_ccw_set_offline(struct ccw_device *cdev) +static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *t= ag) { struct zfcp_adapter *adapter =3D zfcp_ccw_adapter_by_cdev(cdev); =20 if (!adapter) return 0; =20 - zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); + zfcp_erp_set_adapter_status(adapter, set); + zfcp_erp_adapter_shutdown(adapter, 0, tag); zfcp_erp_wait(adapter); =20 zfcp_ccw_adapter_put(adapter); @@ -191,6 +200,18 @@ static int zfcp_ccw_set_offline(struct ccw_device *cde= v) } =20 /** + * zfcp_ccw_set_offline - set_offline function of zfcp driver + * @cdev: pointer to belonging ccw device + * + * This function gets called by the common i/o layer and sets an adapter + * into state offline. + */ +static int zfcp_ccw_set_offline(struct ccw_device *cdev) +{ + return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1"); +} + +/** * zfcp_ccw_notify - ccw notify function * @cdev: pointer to belonging ccw device * @event: indicates if adapter was detached or attached @@ -207,6 +228,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, in= t event) =20 switch (event) { case CIO_GONE: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccnigo1", adapter); + break; + } dev_warn(&cdev->dev, "The FCP device has been detached\n"); zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); break; @@ -216,6 +242,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, in= t event) zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); break; case CIO_OPER: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccniop1", adapter); + break; + } dev_info(&cdev->dev, "The FCP device is operational again\n"); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); @@ -251,6 +282,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) zfcp_ccw_adapter_put(adapter); } =20 +static int zfcp_ccw_suspend(struct ccw_device *cdev) +{ + zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1"); + return 0; +} + +static int zfcp_ccw_thaw(struct ccw_device *cdev) +{ + /* trace records for thaw and final shutdown during suspend + can only be found in system dump until the end of suspend + but not after resume because it's based on the memory image + right after the very first suspend (freeze) callback */ + zfcp_ccw_activate(cdev, 0, "ccthaw1"); + return 0; +} + +static int zfcp_ccw_resume(struct ccw_device *cdev) +{ + zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1"); + return 0; +} + struct ccw_driver zfcp_ccw_driver =3D { .driver =3D { .owner =3D THIS_MODULE, @@ -263,7 +316,7 @@ struct ccw_driver zfcp_ccw_driver =3D { .set_offline =3D zfcp_ccw_set_offline, .notify =3D zfcp_ccw_notify, .shutdown =3D zfcp_ccw_shutdown, - .freeze =3D zfcp_ccw_set_offline, - .thaw =3D zfcp_ccw_activate, - .restore =3D zfcp_ccw_activate, + .freeze =3D zfcp_ccw_suspend, + .thaw =3D zfcp_ccw_thaw, + .restore =3D zfcp_ccw_resume, }; diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index fab2c25..8ed63aa 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapt= er *adapter) } read_unlock_irqrestore(&adapter->port_list_lock, flags); =20 - shost_for_each_device(sdev, port->adapter->scsi_host) { + shost_for_each_device(sdev, adapter->scsi_host) { zfcp_sdev =3D sdev_to_zfcp(sdev); status =3D atomic_read(&zfcp_sdev->status); if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a9a816e..79b9848 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter,= u64 req_id, u16 scount, length =3D min((u16)sizeof(struct qdio_buffer), (u16)ZFCP_DBF_PAY_MAX_REC); =20 - while ((char *)pl[payload->counter] && payload->counter < scount) { + while (payload->counter < scount && (char *)pl[payload->counter]) { memcpy(payload->data, (char *)pl[payload->counter], length); debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); payload->counter++; @@ -200,6 +200,26 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter= , u64 req_id, u16 scount, spin_unlock_irqrestore(&dbf->pay_lock, flags); } =20 +/** + * zfcp_dbf_hba_basic - trace event for basic adapter events + * @adapter: pointer to struct zfcp_adapter + */ +void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter) +{ + struct zfcp_dbf *dbf =3D adapter->dbf; + struct zfcp_dbf_hba *rec =3D &dbf->hba_buf; + unsigned long flags; + + spin_lock_irqsave(&dbf->hba_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id =3D ZFCP_DBF_HBA_BASIC; + + debug_event(dbf->hba, 1, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->hba_lock, flags); +} + static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, struct zfcp_adapter *adapter, struct zfcp_port *port, diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 714f087..3ac7a4b 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id { ZFCP_DBF_HBA_RES =3D 1, ZFCP_DBF_HBA_USS =3D 2, ZFCP_DBF_HBA_BIT =3D 3, + ZFCP_DBF_HBA_BASIC =3D 4, }; =20 /** diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index ed5d921..f172b84 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -77,6 +77,7 @@ struct zfcp_reqlist; #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 +#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 @@ -204,6 +205,7 @@ struct zfcp_port { struct zfcp_adapter *adapter; /* adapter used to access port */ struct list_head unit_list; /* head of logical unit list */ rwlock_t unit_list_lock; /* unit list lock */ + atomic_t units; /* zfcp_unit count */ atomic_t status; /* status of this remote port */ u64 wwnn; /* WWNN if known */ u64 wwpn; /* WWPN */ diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 2302e1c..ef9e502 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -54,6 +54,7 @@ extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_= req *); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **)= ; +extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); @@ -158,6 +159,7 @@ extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd = *, int); extern struct attribute_group zfcp_sysfs_unit_attrs; extern struct attribute_group zfcp_sysfs_adapter_attrs; extern struct attribute_group zfcp_sysfs_port_attrs; +extern struct mutex zfcp_sysfs_port_units_mutex; extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; extern struct device_attribute *zfcp_sysfs_shost_attrs[]; =20 diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e9a787e..8c849f0 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fs= f_req *req) return; } =20 - zfcp_dbf_hba_fsf_uss("fssrh_2", req); + zfcp_dbf_hba_fsf_uss("fssrh_4", req); =20 switch (sr_buf->status_type) { case FSF_STATUS_READ_PORT_CLOSED: @@ -771,12 +771,14 @@ out: static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev =3D req->data; - struct zfcp_scsi_dev *zfcp_sdev =3D sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; union fsf_status_qual *fsq =3D &req->qtcb->header.fsf_status_qual; =20 if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; =20 + zfcp_sdev =3D sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: if (fsq->word[0] =3D=3D fsq->word[1]) { @@ -885,7 +887,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_re= q *req) =20 switch (header->fsf_status) { case FSF_GOOD: - zfcp_dbf_san_res("fsscth1", req); + zfcp_dbf_san_res("fsscth2", req); ct->status =3D 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -1739,13 +1741,15 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_f= sf_req *req) { struct zfcp_adapter *adapter =3D req->adapter; struct scsi_device *sdev =3D req->data; - struct zfcp_scsi_dev *zfcp_sdev =3D sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header =3D &req->qtcb->header; struct fsf_qtcb_bottom_support *bottom =3D &req->qtcb->bottom.support; =20 if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; =20 + zfcp_sdev =3D sdev_to_zfcp(sdev); + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_COMMON_ACCESS_BOXED | ZFCP_STATUS_LUN_SHARED | @@ -1856,11 +1860,13 @@ out: static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev =3D req->data; - struct zfcp_scsi_dev *zfcp_sdev =3D sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; =20 if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; =20 + zfcp_sdev =3D sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); @@ -1950,7 +1956,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *r= eq, struct scsi_cmnd *scsi) { struct fsf_qual_latency_info *lat_in; struct latency_cont *lat =3D NULL; - struct zfcp_scsi_dev *zfcp_sdev =3D sdev_to_zfcp(scsi->device); + struct zfcp_scsi_dev *zfcp_sdev; struct zfcp_blk_drv_data blktrc; int ticks =3D req->adapter->timer_ticks; =20 @@ -1965,6 +1971,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *r= eq, struct scsi_cmnd *scsi) =20 if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA && !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { + zfcp_sdev =3D sdev_to_zfcp(scsi->device); blktrc.flags |=3D ZFCP_BLK_LAT_VALID; blktrc.channel_lat =3D lat_in->channel_lat * ticks; blktrc.fabric_lat =3D lat_in->fabric_lat * ticks; @@ -2002,12 +2009,14 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp= _fsf_req *req) { struct scsi_cmnd *scmnd =3D req->data; struct scsi_device *sdev =3D scmnd->device; - struct zfcp_scsi_dev *zfcp_sdev =3D sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header =3D &req->qtcb->header; =20 if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) return; =20 + zfcp_sdev =3D sdev_to_zfcp(sdev); + switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index e14da57..e76d003 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct ccw_device *cde= v, unsigned int qdio_err, { struct zfcp_qdio *qdio =3D (struct zfcp_qdio *) parm; struct zfcp_adapter *adapter =3D qdio->adapter; - struct qdio_buffer_element *sbale; int sbal_no, sbal_idx; - void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; - u64 req_id; - u8 scount; =20 if (unlikely(qdio_err)) { - memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); if (zfcp_adapter_multi_buffer_active(adapter)) { + void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; + struct qdio_buffer_element *sbale; + u64 req_id; + u8 scount; + + memset(pl, 0, + ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); sbale =3D qdio->res_q[idx]->element; req_id =3D (u64) sbale->addr; - scount =3D sbale->scount + 1; /* incl. signaling SBAL */ + scount =3D min(sbale->scount + 1, + ZFCP_QDIO_MAX_SBALS_PER_REQ + 1); + /* incl. signaling SBAL */ =20 for (sbal_no =3D 0; sbal_no < scount; sbal_no++) { sbal_idx =3D (idx + sbal_no) % diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.= c index cdc4ff7..9e62210 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct devi= ce *dev, static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, zfcp_sysfs_port_rescan_store); =20 +DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); + static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_store(struct dev= ice *dev, else retval =3D 0; =20 + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) > 0) { + retval =3D -EBUSY; + mutex_unlock(&zfcp_sysfs_port_units_mutex); + goto out; + } + /* port is about to be removed, so no more unit_add */ + atomic_set(&port->units, -1); + mutex_unlock(&zfcp_sysfs_port_units_mutex); + write_lock_irq(&adapter->port_list_lock); list_del(&port->list); write_unlock_irq(&adapter->port_list_lock); @@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct devic= e *dev, { struct zfcp_port *port =3D container_of(dev, struct zfcp_port, dev); u64 fcp_lun; + int retval; =20 if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) return -EINVAL; =20 - if (zfcp_unit_add(port, fcp_lun)) - return -EINVAL; + retval =3D zfcp_unit_add(port, fcp_lun); + if (retval) + return retval; =20 return count; } diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 20796eb..4e6a535 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev) { struct zfcp_unit *unit =3D container_of(dev, struct zfcp_unit, dev); =20 - put_device(&unit->port->dev); + atomic_dec(&unit->port->units); kfree(unit); } =20 @@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev) int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) { struct zfcp_unit *unit; + int retval =3D 0; + + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) =3D=3D -1) { + /* port is already gone */ + retval =3D -ENODEV; + goto out; + } =20 unit =3D zfcp_unit_find(port, fcp_lun); if (unit) { put_device(&unit->dev); - return -EEXIST; + retval =3D -EEXIST; + goto out; } =20 unit =3D kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); - if (!unit) - return -ENOMEM; + if (!unit) { + retval =3D -ENOMEM; + goto out; + } =20 unit->port =3D port; unit->fcp_lun =3D fcp_lun; @@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun= ) if (dev_set_name(&unit->dev, "0x%016llx", (unsigned long long) fcp_lun)) { kfree(unit); - return -ENOMEM; + retval =3D -ENOMEM; + goto out; } =20 - get_device(&port->dev); - if (device_register(&unit->dev)) { put_device(&unit->dev); - return -ENOMEM; + retval =3D -ENOMEM; + goto out; } =20 if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { device_unregister(&unit->dev); - return -EINVAL; + retval =3D -EINVAL; + goto out; } =20 + atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */ + write_lock_irq(&port->unit_list_lock); list_add_tail(&unit->list, &port->unit_list); write_unlock_irq(&port->unit_list_lock); =20 zfcp_unit_scsi_scan(unit); =20 - return 0; +out: + mutex_unlock(&zfcp_sysfs_port_units_mutex); + return retval; } =20 /** diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 7e6eca4..59fc5a1 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1174,7 +1174,16 @@ wait_io1: outw(val, tmport); outb(2, 0x80); TCM_SYNC: - udelay(0x800); + /* + * The funny division into multiple delays is to accomodate + * arches like ARM where udelay() multiplies its argument by + * a large number to initialize a loop counter. To avoid + * overflow, the maximum supported udelay is 2000 microseconds. + * + * XXX it would be more polite to find a way to use msleep() + */ + mdelay(2); + udelay(48); if ((inb(tmport) & 0x80) =3D=3D 0x00) { /* bsy ? */ outw(0, tmport--); outb(0, tmport); diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/devi= ce_handler/scsi_dh_alua.c index 4ef0212..e5a4423 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -578,8 +578,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct a= lua_dh_data *h) h->state =3D TPGS_STATE_STANDBY; break; case TPGS_STATE_OFFLINE: - case TPGS_STATE_UNAVAILABLE: - /* Path unusable for unavailable/offline */ + /* Path unusable */ err =3D SCSI_DH_DEV_OFFLINED; break; default: diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index be9aad8..22523aa 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -532,12 +532,42 @@ static void set_performant_mode(struct ctlr_info *h, = struct CommandList *c) c->busaddr |=3D 1 | (h->blockFetchTable[c->Header.SGList] << 1); } =20 +static int is_firmware_flash_cmd(u8 *cdb) +{ + return cdb[0] =3D=3D BMIC_WRITE && cdb[6] =3D=3D BMIC_FLASH_FIRMWARE; +} + +/* + * During firmware flash, the heartbeat register may not update as frequen= tly + * as it should. So we dial down lockup detection during firmware flash. = and + * dial it back up when firmware flash completes. + */ +#define HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH (240 * HZ) +#define HEARTBEAT_SAMPLE_INTERVAL (30 * HZ) +static void dial_down_lockup_detection_during_fw_flash(struct ctlr_info *h= , + struct CommandList *c) +{ + if (!is_firmware_flash_cmd(c->Request.CDB)) + return; + atomic_inc(&h->firmware_flash_in_progress); + h->heartbeat_sample_interval =3D HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH; +} + +static void dial_up_lockup_detection_on_fw_flash_complete(struct ctlr_info= *h, + struct CommandList *c) +{ + if (is_firmware_flash_cmd(c->Request.CDB) && + atomic_dec_and_test(&h->firmware_flash_in_progress)) + h->heartbeat_sample_interval =3D HEARTBEAT_SAMPLE_INTERVAL; +} + static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) { unsigned long flags; =20 set_performant_mode(h, c); + dial_down_lockup_detection_during_fw_flash(h, c); spin_lock_irqsave(&h->lock, flags); addQ(&h->reqQ, c); h->Qdepth++; @@ -2926,7 +2956,7 @@ static void fill_cmd(struct CommandList *c, u8 cmd, s= truct ctlr_info *h, c->Request.Timeout =3D 0; /* Don't time out */ memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); c->Request.CDB[0] =3D cmd; - c->Request.CDB[1] =3D 0x03; /* Reset target above */ + c->Request.CDB[1] =3D HPSA_RESET_TYPE_LUN; /* If bytes 4-7 are zero, it means reset the */ /* LunID device */ c->Request.CDB[4] =3D 0x00; @@ -3032,6 +3062,7 @@ static inline int bad_tag(struct ctlr_info *h, u32 ta= g_index, static inline void finish_cmd(struct CommandList *c, u32 raw_tag) { removeQ(c); + dial_up_lockup_detection_on_fw_flash_complete(c->h, c); if (likely(c->cmd_type =3D=3D CMD_SCSI)) complete_scsi_command(c); else if (c->cmd_type =3D=3D CMD_IOCTL_PEND) @@ -4172,9 +4203,6 @@ static void controller_lockup_detected(struct ctlr_in= fo *h) spin_unlock_irqrestore(&h->lock, flags); } =20 -#define HEARTBEAT_SAMPLE_INTERVAL (10 * HZ) -#define HEARTBEAT_CHECK_MINIMUM_INTERVAL (HEARTBEAT_SAMPLE_INTERVAL / 2) - static void detect_controller_lockup(struct ctlr_info *h) { u64 now; @@ -4185,7 +4213,7 @@ static void detect_controller_lockup(struct ctlr_info= *h) now =3D get_jiffies_64(); /* If we've received an interrupt recently, we're ok. */ if (time_after64(h->last_intr_timestamp + - (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now)) + (h->heartbeat_sample_interval), now)) return; =20 /* @@ -4194,7 +4222,7 @@ static void detect_controller_lockup(struct ctlr_info= *h) * otherwise don't care about signals in this thread. */ if (time_after64(h->last_heartbeat_timestamp + - (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now)) + (h->heartbeat_sample_interval), now)) return; =20 /* If heartbeat has not changed since we last looked, we're not ok. */ @@ -4236,6 +4264,7 @@ static void add_ctlr_to_lockup_detector_list(struct c= tlr_info *h) { unsigned long flags; =20 + h->heartbeat_sample_interval =3D HEARTBEAT_SAMPLE_INTERVAL; spin_lock_irqsave(&lockup_detector_lock, flags); list_add_tail(&h->lockup_list, &hpsa_ctlr_list); spin_unlock_irqrestore(&lockup_detector_lock, flags); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 91edafb..c721509 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -124,6 +124,8 @@ struct ctlr_info { u64 last_intr_timestamp; u32 last_heartbeat; u64 last_heartbeat_timestamp; + u32 heartbeat_sample_interval; + atomic_t firmware_flash_in_progress; u32 lockup_detected; struct list_head lockup_list; }; diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 3fd4715..e4ea0a3 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -163,6 +163,7 @@ struct SenseSubsystem_info { #define BMIC_WRITE 0x27 #define BMIC_CACHE_FLUSH 0xc2 #define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */ +#define BMIC_FLASH_FIRMWARE 0xF7 =20 /* Command List Structure */ union SCSI3Addr { diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvs= csi.c index 3d391dc..36aca4b 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1547,6 +1547,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_ho= st_data *hostdata, =20 host_config =3D &evt_struct->iu.mad.host_config; =20 + /* The transport length field is only 16-bit */ + length =3D min(0xffff, length); + /* Set up a lun reset SRP command */ memset(host_config, 0x00, sizeof(*host_config)); host_config->common.type =3D VIOSRP_HOST_CONFIG_TYPE; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 83d08b6..5c8b0dc 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -469,7 +469,6 @@ static int __devinit isci_pci_probe(struct pci_dev *pde= v, const struct pci_devic if (sci_oem_parameters_validate(&orom->ctrl[i])) { dev_warn(&pdev->dev, "[%d]: invalid oem parameters detected, falling back to firmware\n", = i); - devm_kfree(&pdev->dev, orom); orom =3D NULL; break; } diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.= c index b5f4341..7cd637d 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -104,7 +104,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pd= ev) =20 if (i >=3D len) { dev_err(&pdev->dev, "oprom parse error\n"); - devm_kfree(&pdev->dev, rom); rom =3D NULL; } pci_unmap_biosrom(oprom); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index bb7c482..08d48a3 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1023,33 +1023,31 @@ static void __scsi_remove_target(struct scsi_target= *starget) void scsi_remove_target(struct device *dev) { struct Scsi_Host *shost =3D dev_to_shost(dev->parent); - struct scsi_target *starget, *found; + struct scsi_target *starget, *last =3D NULL; unsigned long flags; =20 - restart: - found =3D NULL; + /* remove targets being careful to lookup next entry before + * deleting the last + */ spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state =3D=3D STARGET_DEL) continue; if (starget->dev.parent =3D=3D dev || &starget->dev =3D=3D dev) { - found =3D starget; - found->reap_ref++; - break; + /* assuming new targets arrive at the end */ + starget->reap_ref++; + spin_unlock_irqrestore(shost->host_lock, flags); + if (last) + scsi_target_reap(last); + last =3D starget; + __scsi_remove_target(starget); + spin_lock_irqsave(shost->host_lock, flags); } } spin_unlock_irqrestore(shost->host_lock, flags); =20 - if (found) { - __scsi_remove_target(found); - scsi_target_reap(found); - /* in the case where @dev has multiple starget children, - * continue removing. - * - * FIXME: does such a case exist? - */ - goto restart; - } + if (last) + scsi_target_reap(last); } EXPORT_SYMBOL(scsi_remove_target); =20 diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/= comedi_fops.c index 4ad2c0e..9465bce 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -843,7 +843,7 @@ static int parse_insn(struct comedi_device *dev, struct= comedi_insn *insn, ret =3D -EAGAIN; break; } - ret =3D s->async->inttrig(dev, s, insn->data[0]); + ret =3D s->async->inttrig(dev, s, data[0]); if (ret >=3D 0) ret =3D 1; break; @@ -1088,7 +1088,6 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } =20 - kfree(async->cmd.chanlist); async->cmd =3D user_cmd; async->cmd.data =3D NULL; /* load channel/gain list */ @@ -1833,6 +1832,8 @@ void do_become_nonbusy(struct comedi_device *dev, str= uct comedi_subdevice *s) if (async) { comedi_reset_async_buf(async); async->inttrig =3D NULL; + kfree(async->cmd.chanlist); + async->cmd.chanlist =3D NULL; } else { printk(KERN_ERR "BUG: (?) do_become_nonbusy called with async=3D0\n"); diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/com= edi/drivers/jr3_pci.c index 8d98cf4..c8b7eed 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -913,7 +913,7 @@ static int jr3_pci_attach(struct comedi_device *dev, } =20 /* Reset DSP card */ - devpriv->iobase->channel[0].reset =3D 0; + writel(0, &devpriv->iobase->channel[0].reset); =20 result =3D comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware)= ; printk("Firmare load %d\n", result); diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi= /drivers/s626.c index 23fc64b..c72128f 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2370,7 +2370,7 @@ static int s626_enc_insn_config(struct comedi_device = *dev, /* (data=3D=3DNULL) ? (Preloadvalue=3D0) : (Preloadvalue=3Ddata[0]); */ =20 k->SetMode(dev, k, Setup, TRUE); - Preload(dev, k, *(insn->data)); + Preload(dev, k, data[0]); k->PulseIndex(dev, k); SetLatchSource(dev, k, valueSrclatch); k->SetEnable(dev, k, (uint16_t) (enab !=3D 0)); diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speak= up/speakup_soft.c index 42cdafe..b5130c8 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -40,7 +40,7 @@ static int softsynth_is_alive(struct spk_synth *synth); static unsigned char get_index(void); =20 static struct miscdevice synth_device; -static int initialized; +static int init_pos; static int misc_registered; =20 static struct var_t vars[] =3D { @@ -194,7 +194,7 @@ static int softsynth_close(struct inode *inode, struct = file *fp) unsigned long flags; spk_lock(flags); synth_soft.alive =3D 0; - initialized =3D 0; + init_pos =3D 0; spk_unlock(flags); /* Make sure we let applications go before leaving */ speakup_start_ttys(); @@ -239,13 +239,8 @@ static ssize_t softsynth_read(struct file *fp, char *b= uf, size_t count, ch =3D '\x18'; } else if (synth_buffer_empty()) { break; - } else if (!initialized) { - if (*init) { - ch =3D *init; - init++; - } else { - initialized =3D 1; - } + } else if (init[init_pos]) { + ch =3D init[init_pos++]; } else { ch =3D synth_buffer_getc(); } diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/isc= si_target.c index 2ff1255..f35cb10 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3204,7 +3204,6 @@ static int iscsit_build_sendtargets_response(struct i= scsi_cmd *cmd) len +=3D 1; =20 if ((len + payload_len) > buffer_len) { - spin_unlock(&tiqn->tiqn_tpg_lock); end_of_buf =3D 1; goto eob; } @@ -3357,6 +3356,7 @@ static int iscsit_send_reject( hdr->opcode =3D ISCSI_OP_REJECT; hdr->flags |=3D ISCSI_FLAG_CMD_FINAL; hton24(hdr->dlength, ISCSI_HDR_LEN); + hdr->ffffffff =3D 0xffffffff; cmd->stat_sn =3D conn->stat_sn++; hdr->statsn =3D cpu_to_be32(cmd->stat_sn); hdr->exp_cmdsn =3D cpu_to_be32(conn->sess->exp_cmd_sn); diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscs= i/iscsi_target_core.h index 0f68197..dae283f 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -25,10 +25,10 @@ #define NA_DATAOUT_TIMEOUT_RETRIES 5 #define NA_DATAOUT_TIMEOUT_RETRIES_MAX 15 #define NA_DATAOUT_TIMEOUT_RETRIES_MIN 1 -#define NA_NOPIN_TIMEOUT 5 +#define NA_NOPIN_TIMEOUT 15 #define NA_NOPIN_TIMEOUT_MAX 60 #define NA_NOPIN_TIMEOUT_MIN 3 -#define NA_NOPIN_RESPONSE_TIMEOUT 5 +#define NA_NOPIN_RESPONSE_TIMEOUT 30 #define NA_NOPIN_RESPONSE_TIMEOUT_MAX 60 #define NA_NOPIN_RESPONSE_TIMEOUT_MIN 3 #define NA_RANDOM_DATAIN_PDU_OFFSETS 0 diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi= /iscsi_target_tpg.c index d4cf2cd..309f14c 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -674,6 +674,12 @@ int iscsit_ta_generate_node_acls( pr_debug("iSCSI_TPG[%hu] - Generate Initiator Portal Group ACLs: %s\n", tpg->tpgt, (a->generate_node_acls) ? "Enabled" : "Disabled"); =20 + if (flag =3D=3D 1 && a->cache_dynamic_acls =3D=3D 0) { + pr_debug("Explicitly setting cache_dynamic_acls=3D1 when " + "generate_node_acls=3D1\n"); + a->cache_dynamic_acls =3D 1; + } + return 0; } =20 @@ -713,6 +719,12 @@ int iscsit_ta_cache_dynamic_acls( return -EINVAL; } =20 + if (a->generate_node_acls =3D=3D 1 && flag =3D=3D 0) { + pr_debug("Skipping cache_dynamic_acls=3D0 when" + " generate_node_acls=3D1\n"); + return 0; + } + a->cache_dynamic_acls =3D flag; pr_debug("iSCSI_TPG[%hu] - Cache Dynamic Initiator Portal Group" " ACLs %s\n", tpg->tpgt, (a->cache_dynamic_acls) ? diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_= core_configfs.c index 93d4f6a..0b01bfc 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3123,6 +3123,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!target_cg->default_groups) { pr_err("Unable to allocate target_cg->default_groups\n"); + ret =3D -ENOMEM; goto out_global; } =20 @@ -3138,6 +3139,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!hba_cg->default_groups) { pr_err("Unable to allocate hba_cg->default_groups\n"); + ret =3D -ENOMEM; goto out_global; } config_group_init_type_name(&alua_group, @@ -3153,6 +3155,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!alua_cg->default_groups) { pr_err("Unable to allocate alua_cg->default_groups\n"); + ret =3D -ENOMEM; goto out_global; } =20 @@ -3164,14 +3167,17 @@ static int __init target_core_init_configfs(void) * Add core/alua/lu_gps/default_lu_gp */ lu_gp =3D core_alua_allocate_lu_gp("default_lu_gp", 1); - if (IS_ERR(lu_gp)) + if (IS_ERR(lu_gp)) { + ret =3D -ENOMEM; goto out_global; + } =20 lu_gp_cg =3D &alua_lu_gps_group; lu_gp_cg->default_groups =3D kzalloc(sizeof(struct config_group) * 2, GFP_KERNEL); if (!lu_gp_cg->default_groups) { pr_err("Unable to allocate lu_gp_cg->default_groups\n"); + ret =3D -ENOMEM; goto out_global; } =20 diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core= _file.c index 455a251..cafa477 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -139,6 +139,19 @@ static struct se_device *fd_create_virtdevice( * of pure timestamp updates. */ flags =3D O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; + /* + * Optionally allow fd_buffered_io=3D1 to be enabled for people + * who want use the fs buffer cache as an WriteCache mechanism. + * + * This means that in event of a hard failure, there is a risk + * of silent data-loss if the SCSI client has *not* performed a + * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE + * to write-out the entire device cache. + */ + if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { + pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n"); + flags &=3D ~O_DSYNC; + } =20 file =3D filp_open(dev_p, flags, 0600); if (IS_ERR(file)) { @@ -206,6 +219,12 @@ static struct se_device *fd_create_virtdevice( if (!dev) goto fail; =20 + if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { + pr_debug("FILEIO: Forcing setting of emulate_write_cache=3D1" + " with FDBD_HAS_BUFFERED_IO_WCE\n"); + dev->se_sub_dev->se_dev_attrib.emulate_write_cache =3D 1; + } + fd_dev->fd_dev_id =3D fd_host->fd_host_dev_id_count++; fd_dev->fd_queue_depth =3D dev->queue_depth; =20 @@ -450,6 +469,7 @@ enum { static match_table_t tokens =3D { {Opt_fd_dev_name, "fd_dev_name=3D%s"}, {Opt_fd_dev_size, "fd_dev_size=3D%s"}, + {Opt_fd_buffered_io, "fd_buffered_io=3D%d"}, {Opt_err, NULL} }; =20 @@ -461,7 +481,7 @@ static ssize_t fd_set_configfs_dev_params( struct fd_dev *fd_dev =3D se_dev->se_dev_su_ptr; char *orig, *ptr, *arg_p, *opts; substring_t args[MAX_OPT_ARGS]; - int ret =3D 0, token; + int ret =3D 0, arg, token; =20 opts =3D kstrdup(page, GFP_KERNEL); if (!opts) @@ -505,6 +525,19 @@ static ssize_t fd_set_configfs_dev_params( " bytes\n", fd_dev->fd_dev_size); fd_dev->fbd_flags |=3D FBDF_HAS_SIZE; break; + case Opt_fd_buffered_io: + match_int(args, &arg); + if (arg !=3D 1) { + pr_err("bogus fd_buffered_io=3D%d value\n", arg); + ret =3D -EINVAL; + goto out; + } + + pr_debug("FILEIO: Using buffered I/O" + " operations for struct fd_dev\n"); + + fd_dev->fbd_flags |=3D FDBD_HAS_BUFFERED_IO_WCE; + break; default: break; } @@ -536,8 +569,10 @@ static ssize_t fd_show_configfs_dev_params( ssize_t bl =3D 0; =20 bl =3D sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); - bl +=3D sprintf(b + bl, " File: %s Size: %llu Mode: O_DSYNC\n", - fd_dev->fd_dev_name, fd_dev->fd_dev_size); + bl +=3D sprintf(b + bl, " File: %s Size: %llu Mode: %s\n", + fd_dev->fd_dev_name, fd_dev->fd_dev_size, + (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ? + "Buffered-WCE" : "O_DSYNC"); return bl; } =20 diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core= _file.h index 53ece69..6b1b6a9 100644 --- a/drivers/target/target_core_file.h +++ b/drivers/target/target_core_file.h @@ -18,6 +18,7 @@ struct fd_request { =20 #define FBDF_HAS_PATH 0x01 #define FBDF_HAS_SIZE 0x02 +#define FDBD_HAS_BUFFERED_IO_WCE 0x04 =20 struct fd_dev { u32 fbd_flags; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index fc7bbba..d190269 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -108,7 +108,7 @@ struct gsm_mux_net { */ =20 struct gsm_msg { - struct gsm_msg *next; + struct list_head list; u8 addr; /* DLCI address + flags */ u8 ctrl; /* Control byte + flags */ unsigned int len; /* Length of data block (can be zero) */ @@ -245,8 +245,7 @@ struct gsm_mux { unsigned int tx_bytes; /* TX data outstanding */ #define TX_THRESH_HI 8192 #define TX_THRESH_LO 2048 - struct gsm_msg *tx_head; /* Pending data packets */ - struct gsm_msg *tx_tail; + struct list_head tx_list; /* Pending data packets */ =20 /* Control messages */ struct timer_list t2_timer; /* Retransmit timer for commands */ @@ -663,7 +662,7 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux *g= sm, u8 addr, int len, m->len =3D len; m->addr =3D addr; m->ctrl =3D ctrl; - m->next =3D NULL; + INIT_LIST_HEAD(&m->list); return m; } =20 @@ -673,22 +672,21 @@ static struct gsm_msg *gsm_data_alloc(struct gsm_mux = *gsm, u8 addr, int len, * * The tty device has called us to indicate that room has appeared in * the transmit queue. Ram more data into the pipe if we have any + * If we have been flow-stopped by a CMD_FCOFF, then we can only + * send messages on DLCI0 until CMD_FCON * * FIXME: lock against link layer control transmissions */ =20 static void gsm_data_kick(struct gsm_mux *gsm) { - struct gsm_msg *msg =3D gsm->tx_head; + struct gsm_msg *msg, *nmsg; int len; int skip_sof =3D 0; =20 - /* FIXME: We need to apply this solely to data messages */ - if (gsm->constipated) - return; - - while (gsm->tx_head !=3D NULL) { - msg =3D gsm->tx_head; + list_for_each_entry_safe(msg, nmsg, &gsm->tx_list, list) { + if (gsm->constipated && msg->addr) + continue; if (gsm->encoding !=3D 0) { gsm->txframe[0] =3D GSM1_SOF; len =3D gsm_stuff_frame(msg->data, @@ -711,14 +709,13 @@ static void gsm_data_kick(struct gsm_mux *gsm) len - skip_sof) < 0) break; /* FIXME: Can eliminate one SOF in many more cases */ - gsm->tx_head =3D msg->next; - if (gsm->tx_head =3D=3D NULL) - gsm->tx_tail =3D NULL; gsm->tx_bytes -=3D msg->len; - kfree(msg); /* For a burst of frames skip the extra SOF within the burst */ skip_sof =3D 1; + + list_del(&msg->list); + kfree(msg); } } =20 @@ -768,11 +765,7 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, st= ruct gsm_msg *msg) msg->data =3D dp; =20 /* Add to the actual output queue */ - if (gsm->tx_tail) - gsm->tx_tail->next =3D msg; - else - gsm->tx_head =3D msg; - gsm->tx_tail =3D msg; + list_add_tail(&msg->list, &gsm->tx_list); gsm->tx_bytes +=3D msg->len; gsm_data_kick(gsm); } @@ -875,7 +868,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *= gsm, =20 /* dlci->skb is locked by tx_lock */ if (dlci->skb =3D=3D NULL) { - dlci->skb =3D skb_dequeue(&dlci->skb_list); + dlci->skb =3D skb_dequeue_tail(&dlci->skb_list); if (dlci->skb =3D=3D NULL) return 0; first =3D 1; @@ -886,7 +879,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *= gsm, if (len > gsm->mtu) { if (dlci->adaption =3D=3D 3) { /* Over long frame, bin it */ - kfree_skb(dlci->skb); + dev_kfree_skb_any(dlci->skb); dlci->skb =3D NULL; return 0; } @@ -899,8 +892,11 @@ static int gsm_dlci_data_output_framed(struct gsm_mux = *gsm, =20 /* FIXME: need a timer or something to kick this so it can't get stuck with no work outstanding and no buffer free */ - if (msg =3D=3D NULL) + if (msg =3D=3D NULL) { + skb_queue_tail(&dlci->skb_list, dlci->skb); + dlci->skb =3D NULL; return -ENOMEM; + } dp =3D msg->data; =20 if (dlci->adaption =3D=3D 4) { /* Interruptible framed (Packetised Data) = */ @@ -912,7 +908,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *= gsm, skb_pull(dlci->skb, len); __gsm_data_queue(dlci, msg); if (last) { - kfree_skb(dlci->skb); + dev_kfree_skb_any(dlci->skb); dlci->skb =3D NULL; } return size; @@ -971,16 +967,22 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) static void gsm_dlci_data_kick(struct gsm_dlci *dlci) { unsigned long flags; + int sweep; + + if (dlci->constipated)=20 + return; =20 spin_lock_irqsave(&dlci->gsm->tx_lock, flags); /* If we have nothing running then we need to fire up */ + sweep =3D (dlci->gsm->tx_bytes < TX_THRESH_LO); if (dlci->gsm->tx_bytes =3D=3D 0) { if (dlci->net) gsm_dlci_data_output_framed(dlci->gsm, dlci); else gsm_dlci_data_output(dlci->gsm, dlci); - } else if (dlci->gsm->tx_bytes < TX_THRESH_LO) - gsm_dlci_data_sweep(dlci->gsm); + } + if (sweep) + gsm_dlci_data_sweep(dlci->gsm); spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } =20 @@ -1027,6 +1029,7 @@ static void gsm_process_modem(struct tty_struct *tty,= struct gsm_dlci *dlci, { int mlines =3D 0; u8 brk =3D 0; + int fc; =20 /* The modem status command can either contain one octet (v.24 signals) or two octets (v.24 signals + break signals). The length field will @@ -1038,19 +1041,21 @@ static void gsm_process_modem(struct tty_struct *tt= y, struct gsm_dlci *dlci, else { brk =3D modem & 0x7f; modem =3D (modem >> 7) & 0x7f; - }; + } =20 /* Flow control/ready to communicate */ - if (modem & MDM_FC) { + fc =3D (modem & MDM_FC) || !(modem & MDM_RTR); + if (fc && !dlci->constipated) { /* Need to throttle our output on this device */ dlci->constipated =3D 1; - } - if (modem & MDM_RTC) { - mlines |=3D TIOCM_DSR | TIOCM_DTR; + } else if (!fc && dlci->constipated) { dlci->constipated =3D 0; gsm_dlci_data_kick(dlci); } + /* Map modem bits */ + if (modem & MDM_RTC) + mlines |=3D TIOCM_DSR | TIOCM_DTR; if (modem & MDM_RTR) mlines |=3D TIOCM_RTS | TIOCM_CTS; if (modem & MDM_IC) @@ -1190,6 +1195,8 @@ static void gsm_control_message(struct gsm_mux *gsm, = unsigned int command, u8 *data, int clen) { u8 buf[1]; + unsigned long flags; + switch (command) { case CMD_CLD: { struct gsm_dlci *dlci =3D gsm->dlci[0]; @@ -1206,16 +1213,18 @@ static void gsm_control_message(struct gsm_mux *gsm= , unsigned int command, gsm_control_reply(gsm, CMD_TEST, data, clen); break; case CMD_FCON: - /* Modem wants us to STFU */ - gsm->constipated =3D 1; - gsm_control_reply(gsm, CMD_FCON, NULL, 0); - break; - case CMD_FCOFF: /* Modem can accept data again */ gsm->constipated =3D 0; - gsm_control_reply(gsm, CMD_FCOFF, NULL, 0); + gsm_control_reply(gsm, CMD_FCON, NULL, 0); /* Kick the link in case it is idling */ + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); + spin_unlock_irqrestore(&gsm->tx_lock, flags); + break; + case CMD_FCOFF: + /* Modem wants us to STFU */ + gsm->constipated =3D 1; + gsm_control_reply(gsm, CMD_FCOFF, NULL, 0); break; case CMD_MSC: /* Out of band modem line change indicator for a DLCI */ @@ -1668,7 +1677,7 @@ static void gsm_dlci_free(struct kref *ref) dlci->gsm->dlci[dlci->addr] =3D NULL; kfifo_free(dlci->fifo); while ((dlci->skb =3D skb_dequeue(&dlci->skb_list))) - kfree_skb(dlci->skb); + dev_kfree_skb(dlci->skb); kfree(dlci); } =20 @@ -2007,7 +2016,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) { int i; struct gsm_dlci *dlci =3D gsm->dlci[0]; - struct gsm_msg *txq; + struct gsm_msg *txq, *ntxq; struct gsm_control *gc; =20 gsm->dead =3D 1; @@ -2042,11 +2051,9 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) if (gsm->dlci[i]) gsm_dlci_release(gsm->dlci[i]); /* Now wipe the queues */ - for (txq =3D gsm->tx_head; txq !=3D NULL; txq =3D gsm->tx_head) { - gsm->tx_head =3D txq->next; + list_for_each_entry_safe(txq, ntxq, &gsm->tx_list, list) kfree(txq); - } - gsm->tx_tail =3D NULL; + INIT_LIST_HEAD(&gsm->tx_list); } EXPORT_SYMBOL_GPL(gsm_cleanup_mux); =20 @@ -2157,6 +2164,7 @@ struct gsm_mux *gsm_alloc_mux(void) } spin_lock_init(&gsm->lock); kref_init(&gsm->ref); + INIT_LIST_HEAD(&gsm->tx_list); =20 gsm->t1 =3D T1; gsm->t2 =3D T2; @@ -2273,7 +2281,7 @@ static void gsmld_receive_buf(struct tty_struct *tty,= const unsigned char *cp, gsm->error(gsm, *dp, flags); break; default: - WARN_ONCE("%s: unknown flag %d\n", + WARN_ONCE(1, "%s: unknown flag %d\n", tty_name(tty, buf), flags); break; } @@ -2377,12 +2385,12 @@ static void gsmld_write_wakeup(struct tty_struct *t= ty) =20 /* Queue poll */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); if (gsm->tx_bytes < TX_THRESH_LO) { - spin_lock_irqsave(&gsm->tx_lock, flags); gsm_dlci_data_sweep(gsm); - spin_unlock_irqrestore(&gsm->tx_lock, flags); } + spin_unlock_irqrestore(&gsm->tx_lock, flags); } =20 /** @@ -2889,6 +2897,10 @@ static int gsmtty_open(struct tty_struct *tty, struc= t file *filp) gsm =3D gsm_mux[mux]; if (gsm->dead) return -EL2HLT; + /* If DLCI 0 is not yet fully open return an error. This is ok from a loc= king + perspective as we don't have to worry about this if DLCI0 is lost */ + if (gsm->dlci[0] && gsm->dlci[0]->state !=3D DLCI_OPEN)=20 + return -EL2NSYNC; dlci =3D gsm->dlci[line]; if (dlci =3D=3D NULL) dlci =3D gsm_dlci_alloc(gsm, line); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 39d6ab6..8481aae 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1728,7 +1728,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, str= uct file *file, =20 do_it_again: =20 - BUG_ON(!tty->read_buf); + if (WARN_ON(!tty->read_buf)) + return -EAGAIN; =20 c =3D job_control(tty, file); if (c < 0) diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 482d51e..e7d82c1 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c @@ -1118,6 +1118,8 @@ pci_xr17c154_setup(struct serial_private *priv, #define PCI_SUBDEVICE_ID_OCTPRO422 0x0208 #define PCI_SUBDEVICE_ID_POCTAL232 0x0308 #define PCI_SUBDEVICE_ID_POCTAL422 0x0408 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 #define PCI_VENDOR_ID_ADVANTECH 0x13fe #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 #define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 @@ -3168,8 +3170,11 @@ static struct pci_device_id serial_pci_tbl[] =3D { * For now just used the hex ID 0x950a. */ { PCI_VENDOR_ID_OXSEMI, 0x950a, - PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0, - pbn_b0_2_115200 }, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00, + 0, 0, pbn_b0_2_115200 }, + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30, + 0, 0, pbn_b0_2_115200 }, { PCI_VENDOR_ID_OXSEMI, 0x950a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_1130000 }, diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl01= 1.c index 6da8cf8..fe9f111 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1627,13 +1627,26 @@ pl011_set_termios(struct uart_port *port, struct kt= ermios *termios, old_cr &=3D ~ST_UART011_CR_OVSFACT; } =20 + /* + * Workaround for the ST Micro oversampling variants to + * increase the bitrate slightly, by lowering the divisor, + * to avoid delayed sampling of start bit at high speeds, + * else we see data corruption. + */ + if (uap->vendor->oversampling) { + if ((baud >=3D 3000000) && (baud < 3250000) && (quot > 1)) + quot -=3D 1; + else if ((baud > 3250000) && (quot > 2)) + quot -=3D 2; + } /* Set baud rate */ writew(quot & 0x3f, port->membase + UART011_FBRD); writew(quot >> 6, port->membase + UART011_IBRD); =20 /* * ----------v----------v----------v----------v----- - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L + * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER + * UART011_FBRD & UART011_IBRD. * ----------^----------^----------^----------^----- */ writew(lcr_h, port->membase + uap->lcrh_rx); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index a40ab98..4cddbfc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1680,6 +1680,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev =3D to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; + struct xhci_cd *cur_cd, *next_cd; unsigned long flags; int size; int i, j, num_ports; @@ -1701,6 +1702,11 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring =3D NULL; xhci_dbg(xhci, "Freed command ring\n"); + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } =20 for (i =3D 1; i < MAX_HC_SLOTS; ++i) xhci_free_virt_device(xhci, i); @@ -2246,6 +2252,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring =3D xhci_ring_alloc(xhci, 1, true, false, flags); if (!xhci->cmd_ring) goto fail; + INIT_LIST_HEAD(&xhci->cancel_cmd_list); xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index bddcbfc..4ed7572 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -99,6 +99,7 @@ static void xhci_pci_quirks(struct device *dev, struct xh= ci_hcd *xhci) * PPT chipsets. */ xhci->quirks |=3D XHCI_SPURIOUS_REBOOT; + xhci->quirks |=3D XHCI_AVOID_BEI; } if (pdev->vendor =3D=3D PCI_VENDOR_ID_ETRON && pdev->device =3D=3D PCI_DEVICE_ID_ASROCK_P67) { diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c7c530c..950aef8 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -309,12 +309,123 @@ static int room_on_ring(struct xhci_hcd *xhci, struc= t xhci_ring *ring, /* Ring the host controller doorbell after placing a command on the ring *= / void xhci_ring_cmd_db(struct xhci_hcd *xhci) { + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) + return; + xhci_dbg(xhci, "// Ding dong!\n"); xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ xhci_readl(xhci, &xhci->dba->doorbell[0]); } =20 +static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) +{ + u64 temp_64; + int ret; + + xhci_dbg(xhci, "Abort command ring\n"); + + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) { + xhci_dbg(xhci, "The command ring isn't running, " + "Have the command ring been stopped?\n"); + return 0; + } + + temp_64 =3D xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + if (!(temp_64 & CMD_RING_RUNNING)) { + xhci_dbg(xhci, "Command ring had been stopped\n"); + return 0; + } + xhci->cmd_ring_state =3D CMD_RING_STATE_ABORTED; + xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, + &xhci->op_regs->cmd_ring); + + /* Section 4.6.1.2 of xHCI 1.0 spec says software should + * time the completion od all xHCI commands, including + * the Command Abort operation. If software doesn't see + * CRR negated in a timely manner (e.g. longer than 5 + * seconds), then it should assume that the there are + * larger problems with the xHC and assert HCRST. + */ + ret =3D handshake(xhci, &xhci->op_regs->cmd_ring, + CMD_RING_RUNNING, 0, 5 * 1000 * 1000); + if (ret < 0) { + xhci_err(xhci, "Stopped the command ring failed, " + "maybe the host is dead\n"); + xhci->xhc_state |=3D XHCI_STATE_DYING; + xhci_quiesce(xhci); + xhci_halt(xhci); + return -ESHUTDOWN; + } + + return 0; +} + +static int xhci_queue_cd(struct xhci_hcd *xhci, + struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cd; + cd =3D kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC); + if (!cd) + return -ENOMEM; + INIT_LIST_HEAD(&cd->cancel_cmd_list); + + cd->command =3D command; + cd->cmd_trb =3D cmd_trb; + list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list); + + return 0; +} + +/* + * Cancel the command which has issue. + * + * Some commands may hang due to waiting for acknowledgement from + * usb device. It is outside of the xHC's ability to control and + * will cause the command ring is blocked. When it occurs software + * should intervene to recover the command ring. + * See Section 4.6.1.1 and 4.6.1.2 + */ +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + int retval =3D 0; + unsigned long flags; + + spin_lock_irqsave(&xhci->lock, flags); + + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_warn(xhci, "Abort the command ring," + " but the xHCI is dead.\n"); + retval =3D -ESHUTDOWN; + goto fail; + } + + /* queue the cmd desriptor to cancel_cmd_list */ + retval =3D xhci_queue_cd(xhci, command, cmd_trb); + if (retval) { + xhci_warn(xhci, "Queuing command descriptor failed.\n"); + goto fail; + } + + /* abort command ring */ + retval =3D xhci_abort_cmd_ring(xhci); + if (retval) { + xhci_err(xhci, "Abort command ring failed\n"); + if (unlikely(retval =3D=3D -ESHUTDOWN)) { + spin_unlock_irqrestore(&xhci->lock, flags); + usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); + xhci_dbg(xhci, "xHCI host controller is dead.\n"); + return retval; + } + } + +fail: + spin_unlock_irqrestore(&xhci->lock, flags); + return retval; +} + void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, @@ -1043,6 +1154,20 @@ static void handle_reset_ep_completion(struct xhci_h= cd *xhci, } } =20 +/* Complete the command and detele it from the devcie's command queue. + */ +static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, + struct xhci_command *command, u32 status) +{ + command->status =3D status; + list_del(&command->cmd_list); + if (command->completion) + complete(command->completion); + else + xhci_free_command(xhci, command); +} + + /* Check to see if a command in the device's command queue matches this on= e. * Signal the completion or free the command, and return 1. Return 0 if t= he * completed command isn't at the head of the command list. @@ -1061,15 +1186,144 @@ static int handle_cmd_in_cmd_wait_list(struct xhci= _hcd *xhci, if (xhci->cmd_ring->dequeue !=3D command->command_trb) return 0; =20 - command->status =3D GET_COMP_CODE(le32_to_cpu(event->status)); - list_del(&command->cmd_list); - if (command->completion) - complete(command->completion); - else - xhci_free_command(xhci, command); + xhci_complete_cmd_in_cmd_wait_list(xhci, command, + GET_COMP_CODE(le32_to_cpu(event->status))); return 1; } =20 +/* + * Finding the command trb need to be cancelled and modifying it to + * NO OP command. And if the command is in device's command wait + * list, finishing and freeing it. + * + * If we can't find the command trb, we think it had already been + * executed. + */ +static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd= ) +{ + struct xhci_segment *cur_seg; + union xhci_trb *cmd_trb; + u32 cycle_state; + + if (xhci->cmd_ring->dequeue =3D=3D xhci->cmd_ring->enqueue) + return; + + /* find the current segment of command ring */ + cur_seg =3D find_trb_seg(xhci->cmd_ring->first_seg, + xhci->cmd_ring->dequeue, &cycle_state); + + /* find the command trb matched by cd from command ring */ + for (cmd_trb =3D xhci->cmd_ring->dequeue; + cmd_trb !=3D xhci->cmd_ring->enqueue; + next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) { + /* If the trb is link trb, continue */ + if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3])) + continue; + + if (cur_cd->cmd_trb =3D=3D cmd_trb) { + + /* If the command in device's command list, we should + * finish it and free the command structure. + */ + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + + /* get cycle state from the origin command trb */ + cycle_state =3D le32_to_cpu(cmd_trb->generic.field[3]) + & TRB_CYCLE; + + /* modify the command trb to NO OP command */ + cmd_trb->generic.field[0] =3D 0; + cmd_trb->generic.field[1] =3D 0; + cmd_trb->generic.field[2] =3D 0; + cmd_trb->generic.field[3] =3D cpu_to_le32( + TRB_TYPE(TRB_CMD_NOOP) | cycle_state); + break; + } + } +} + +static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + xhci_cmd_to_noop(xhci, cur_cd); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } +} + +/* + * traversing the cancel_cmd_list. If the command descriptor according + * to cmd_trb is found, the function free it and return 1, otherwise + * return 0. + */ +static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return 0; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + if (cur_cd->cmd_trb =3D=3D cmd_trb) { + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + return 1; + } + } + + return 0; +} + +/* + * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the + * trb pointed by the command ring dequeue pointer is the trb we want to + * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will + * traverse the cancel_cmd_list to trun the all of the commands according + * to command descriptor to NO-OP trb. + */ +static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, + int cmd_trb_comp_code) +{ + int cur_trb_is_good =3D 0; + + /* Searching the cmd trb pointed by the command ring dequeue + * pointer in command descriptor list. If it is found, free it. + */ + cur_trb_is_good =3D xhci_search_cmd_trb_in_cd_list(xhci, + xhci->cmd_ring->dequeue); + + if (cmd_trb_comp_code =3D=3D COMP_CMD_ABORT) + xhci->cmd_ring_state =3D CMD_RING_STATE_STOPPED; + else if (cmd_trb_comp_code =3D=3D COMP_CMD_STOP) { + /* traversing the cancel_cmd_list and canceling + * the command according to command descriptor + */ + xhci_cancel_cmd_in_cd_list(xhci); + + xhci->cmd_ring_state =3D CMD_RING_STATE_RUNNING; + /* + * ring command ring doorbell again to restart the + * command ring + */ + if (xhci->cmd_ring->dequeue !=3D xhci->cmd_ring->enqueue) + xhci_ring_cmd_db(xhci); + } + return cur_trb_is_good; +} + static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { @@ -1095,6 +1349,22 @@ static void handle_cmd_completion(struct xhci_hcd *x= hci, xhci->error_bitmask |=3D 1 << 5; return; } + + if ((GET_COMP_CODE(le32_to_cpu(event->status)) =3D=3D COMP_CMD_ABORT) || + (GET_COMP_CODE(le32_to_cpu(event->status)) =3D=3D COMP_CMD_STOP)) { + /* If the return value is 0, we think the trb pointed by + * command ring dequeue pointer is a good trb. The good + * trb means we don't want to cancel the trb, but it have + * been stopped by host. So we should handle it normally. + * Otherwise, driver should invoke inc_deq() and return. + */ + if (handle_stopped_cmd_ring(xhci, + GET_COMP_CODE(le32_to_cpu(event->status)))) { + inc_deq(xhci, xhci->cmd_ring, false); + return; + } + } + switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): @@ -3356,7 +3626,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, = gfp_t mem_flags, } else { td->last_trb =3D ep_ring->enqueue; field |=3D TRB_IOC; - if (xhci->hci_version =3D=3D 0x100) { + if (xhci->hci_version =3D=3D 0x100 && + !(xhci->quirks & + XHCI_AVOID_BEI)) { /* Set BEI bit except for the last td */ if (i < num_tds - 1) field |=3D TRB_BEI; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 09872ee..f5c0f38 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit o= n a link TRB"); * handshake done). There are two failure modes: "usec" have passed (maj= or * hardware flakeout), or the register reads as all-ones (hardware removed= ). */ -static int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; @@ -105,8 +105,12 @@ int xhci_halt(struct xhci_hcd *xhci) =20 ret =3D handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (!ret) + if (!ret) { xhci->xhc_state |=3D XHCI_STATE_HALTED; + xhci->cmd_ring_state =3D CMD_RING_STATE_STOPPED; + } else + xhci_warn(xhci, "Host not halted after %u microseconds.\n", + XHCI_MAX_HALT_USEC); return ret; } =20 @@ -459,6 +463,8 @@ static bool compliance_mode_recovery_timer_quirk_check(= void) =20 dmi_product_name =3D dmi_get_system_info(DMI_PRODUCT_NAME); dmi_sys_vendor =3D dmi_get_system_info(DMI_SYS_VENDOR); + if (!dmi_product_name || !dmi_sys_vendor) + return false; =20 if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) return false; @@ -570,6 +576,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci) return -ENODEV; } xhci->shared_hcd->state =3D HC_STATE_RUNNING; + xhci->cmd_ring_state =3D CMD_RING_STATE_RUNNING; =20 if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); @@ -874,7 +881,7 @@ int xhci_suspend(struct xhci_hcd *xhci) command &=3D ~CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_HALT, STS_HALT, 100*100)) { + STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) { xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; @@ -2506,6 +2513,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *x= hci, struct completion *cmd_completion; u32 *cmd_status; struct xhci_virt_device *virt_dev; + union xhci_trb *cmd_trb; =20 spin_lock_irqsave(&xhci->lock, flags); virt_dev =3D xhci->devs[udev->slot_id]; @@ -2551,6 +2559,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *x= hci, } init_completion(cmd_completion); =20 + cmd_trb =3D xhci->cmd_ring->dequeue; if (!ctx_change) ret =3D xhci_queue_configure_endpoint(xhci, in_ctx->dma, udev->slot_id, must_succeed); @@ -2572,14 +2581,17 @@ static int xhci_configure_endpoint(struct xhci_hcd = *xhci, /* Wait for the configure endpoint command to complete */ timeleft =3D wait_for_completion_interruptible_timeout( cmd_completion, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <=3D 0) { xhci_warn(xhci, "%s while waiting for %s command\n", timeleft =3D=3D 0 ? "Timeout" : "Signal", ctx_change =3D=3D 0 ? "configure endpoint" : "evaluate context"); - /* FIXME cancel the configure endpoint command */ + /* cancel the configure endpoint command */ + ret =3D xhci_cancel_cmd(xhci, command, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } =20 @@ -3528,8 +3540,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_d= evice *udev) unsigned long flags; int timeleft; int ret; + union xhci_trb *cmd_trb; =20 spin_lock_irqsave(&xhci->lock, flags); + cmd_trb =3D xhci->cmd_ring->dequeue; ret =3D xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); @@ -3541,12 +3555,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_= device *udev) =20 /* XXX: how much time for xHC slot assignment? */ timeleft =3D wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <=3D 0) { xhci_warn(xhci, "%s while waiting for a slot\n", timeleft =3D=3D 0 ? "Timeout" : "Signal"); - /* FIXME cancel the enable slot request */ - return 0; + /* cancel the enable slot request */ + return xhci_cancel_cmd(xhci, NULL, cmd_trb); } =20 if (!xhci->slot_id) { @@ -3607,6 +3621,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct u= sb_device *udev) struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u64 temp_64; + union xhci_trb *cmd_trb; =20 if (!udev->slot_id) { xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); @@ -3645,6 +3660,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct u= sb_device *udev) xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); =20 spin_lock_irqsave(&xhci->lock, flags); + cmd_trb =3D xhci->cmd_ring->dequeue; ret =3D xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret) { @@ -3657,7 +3673,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct u= sb_device *udev) =20 /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */ timeleft =3D wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); /* FIXME: From section 4.3.4: "Software shall be responsible for timing * the SetAddress() "recovery interval" required by USB and aborting the * command on a timeout. @@ -3665,7 +3681,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct = usb_device *udev) if (timeleft <=3D 0) { xhci_warn(xhci, "%s while waiting for address device command\n", timeleft =3D=3D 0 ? "Timeout" : "Signal"); - /* FIXME cancel the address device command */ + /* cancel the address device command */ + ret =3D xhci_cancel_cmd(xhci, NULL, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } =20 diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 44d518a..cc368c2 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1255,6 +1255,16 @@ struct xhci_td { union xhci_trb *last_trb; }; =20 +/* xHCI command default timeout value */ +#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ) + +/* command descriptor */ +struct xhci_cd { + struct list_head cancel_cmd_list; + struct xhci_command *command; + union xhci_trb *cmd_trb; +}; + struct xhci_dequeue_state { struct xhci_segment *new_deq_seg; union xhci_trb *new_deq_ptr; @@ -1402,6 +1412,11 @@ struct xhci_hcd { /* data structures */ struct xhci_device_context_array *dcbaa; struct xhci_ring *cmd_ring; + unsigned int cmd_ring_state; +#define CMD_RING_STATE_RUNNING (1 << 0) +#define CMD_RING_STATE_ABORTED (1 << 1) +#define CMD_RING_STATE_STOPPED (1 << 2) + struct list_head cancel_cmd_list; unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; @@ -1473,6 +1488,7 @@ struct xhci_hcd { #define XHCI_TRUST_TX_LENGTH (1 << 10) #define XHCI_SPURIOUS_REBOOT (1 << 13) #define XHCI_COMP_MODE_QUIRK (1 << 14) +#define XHCI_AVOID_BEI (1 << 15) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ @@ -1666,6 +1682,8 @@ static inline void xhci_unregister_pci(void) {} =20 /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, + u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_reset(struct xhci_hcd *xhci); @@ -1756,6 +1774,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci= , unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); void xhci_stop_endpoint_command_watchdog(unsigned long arg); +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb); void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); =20 diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 7324bea..e29a664 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -584,6 +584,8 @@ static struct usb_device_id id_table_combined [] =3D { { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), + .driver_info =3D (kernel_ulong_t)&ftdi_jtag_quirk }, /* * ELV devices: */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_si= o_ids.h index 06f6fd2..7b5eb74 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -517,6 +517,11 @@ */ #define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */ =20 +/* + * TIAO product ids (FTDI_VID) + * http://www.tiaowiki.com/w/Main_Page + */ +#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Ada= pter */ =20 =20 /********************************/ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c068b4d..3fd4e6f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -870,7 +870,8 @@ static const struct usb_device_id option_ids[] =3D { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) = }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) = }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) = }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) = }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), + .driver_info =3D (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) = }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) = }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) = }, diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index a348198..87271e3 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,8 +36,6 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 -#define PANTECH_PRODUCT_UML190_VZW 0x3716 -#define PANTECH_PRODUCT_UML290_VZW 0x3718 =20 /* CMOTECH devices */ #define CMOTECH_VENDOR_ID 0x16d8 @@ -68,11 +66,9 @@ static struct usb_device_id id_table[] =3D { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xf= f, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX,= 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, = 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML1= 90_VZW, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML1= 90_VZW, 0xff, 0xfe, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML2= 90_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML2= 90_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML2= 90_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) },= /* NMEA */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) },= /* WMC */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) },= /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index f55ae23..790fa63 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -392,10 +392,12 @@ static struct vfsmount *autofs4_d_automount(struct pa= th *path) ino->flags |=3D AUTOFS_INF_PENDING; spin_unlock(&sbi->fs_lock); status =3D autofs4_mount_wait(dentry); - if (status) - return ERR_PTR(status); spin_lock(&sbi->fs_lock); ino->flags &=3D ~AUTOFS_INF_PENDING; + if (status) { + spin_unlock(&sbi->fs_lock); + return ERR_PTR(status); + } } done: if (!(ino->flags & AUTOFS_INF_EXPIRING)) { diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6ff96c6..8dd615c 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1668,30 +1668,19 @@ static int elf_note_info_init(struct elf_note_info = *info) return 0; info->psinfo =3D kmalloc(sizeof(*info->psinfo), GFP_KERNEL); if (!info->psinfo) - goto notes_free; + return 0; info->prstatus =3D kmalloc(sizeof(*info->prstatus), GFP_KERNEL); if (!info->prstatus) - goto psinfo_free; + return 0; info->fpu =3D kmalloc(sizeof(*info->fpu), GFP_KERNEL); if (!info->fpu) - goto prstatus_free; + return 0; #ifdef ELF_CORE_COPY_XFPREGS info->xfpu =3D kmalloc(sizeof(*info->xfpu), GFP_KERNEL); if (!info->xfpu) - goto fpu_free; + return 0; #endif return 1; -#ifdef ELF_CORE_COPY_XFPREGS - fpu_free: - kfree(info->fpu); -#endif - prstatus_free: - kfree(info->prstatus); - psinfo_free: - kfree(info->psinfo); - notes_free: - kfree(info->notes); - return 0; } =20 static int fill_note_info(struct elfhdr *elf, int phdrs, diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index a9f29b1..2262a77 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -559,6 +559,8 @@ struct ecryptfs_open_req { struct inode *ecryptfs_get_inode(struct inode *lower_inode, struct super_block *sb); void ecryptfs_i_size_init(const char *page_virt, struct inode *inode); +int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode); int ecryptfs_decode_and_decrypt_filename(char **decrypted_name, size_t *decrypted_name_size, struct dentry *ecryptfs_dentry, diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index d3f95f9..841f24f 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -139,29 +139,50 @@ out: return rc; } =20 -static void ecryptfs_vma_close(struct vm_area_struct *vma) -{ - filemap_write_and_wait(vma->vm_file->f_mapping); -} - -static const struct vm_operations_struct ecryptfs_file_vm_ops =3D { - .close =3D ecryptfs_vma_close, - .fault =3D filemap_fault, -}; +struct kmem_cache *ecryptfs_file_info_cache; =20 -static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vm= a) +static int read_or_initialize_metadata(struct dentry *dentry) { + struct inode *inode =3D dentry->d_inode; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_crypt_stat *crypt_stat; int rc; =20 - rc =3D generic_file_mmap(file, vma); + crypt_stat =3D &ecryptfs_inode_to_private(inode)->crypt_stat; + mount_crypt_stat =3D &ecryptfs_superblock_to_private( + inode->i_sb)->mount_crypt_stat; + mutex_lock(&crypt_stat->cs_mutex); + + if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED && + crypt_stat->flags & ECRYPTFS_KEY_VALID) { + rc =3D 0; + goto out; + } + + rc =3D ecryptfs_read_metadata(dentry); if (!rc) - vma->vm_ops =3D &ecryptfs_file_vm_ops; + goto out; + + if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) { + crypt_stat->flags &=3D ~(ECRYPTFS_I_SIZE_INITIALIZED + | ECRYPTFS_ENCRYPTED); + rc =3D 0; + goto out; + } + + if (!(mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) && + !i_size_read(ecryptfs_inode_to_lower(inode))) { + rc =3D ecryptfs_initialize_file(dentry, inode); + if (!rc) + goto out; + } =20 + rc =3D -EIO; +out: + mutex_unlock(&crypt_stat->cs_mutex); return rc; } =20 -struct kmem_cache *ecryptfs_file_info_cache; - /** * ecryptfs_open * @inode: inode speciying file to open @@ -237,32 +258,9 @@ static int ecryptfs_open(struct inode *inode, struct f= ile *file) rc =3D 0; goto out; } - mutex_lock(&crypt_stat->cs_mutex); - if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) - || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { - rc =3D ecryptfs_read_metadata(ecryptfs_dentry); - if (rc) { - ecryptfs_printk(KERN_DEBUG, - "Valid headers not found\n"); - if (!(mount_crypt_stat->flags - & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { - rc =3D -EIO; - printk(KERN_WARNING "Either the lower file " - "is not in a valid eCryptfs format, " - "or the key could not be retrieved. " - "Plaintext passthrough mode is not " - "enabled; returning -EIO\n"); - mutex_unlock(&crypt_stat->cs_mutex); - goto out_put; - } - rc =3D 0; - crypt_stat->flags &=3D ~(ECRYPTFS_I_SIZE_INITIALIZED - | ECRYPTFS_ENCRYPTED); - mutex_unlock(&crypt_stat->cs_mutex); - goto out; - } - } - mutex_unlock(&crypt_stat->cs_mutex); + rc =3D read_or_initialize_metadata(ecryptfs_dentry); + if (rc) + goto out_put; ecryptfs_printk(KERN_DEBUG, "inode w/ addr =3D [0x%p], i_ino =3D " "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino, (unsigned long long)i_size_read(inode)); @@ -278,8 +276,14 @@ out: =20 static int ecryptfs_flush(struct file *file, fl_owner_t td) { - return file->f_mode & FMODE_WRITE - ? filemap_write_and_wait(file->f_mapping) : 0; + struct file *lower_file =3D ecryptfs_file_to_lower(file); + + if (lower_file->f_op && lower_file->f_op->flush) { + filemap_write_and_wait(file->f_mapping); + return lower_file->f_op->flush(lower_file, td); + } + + return 0; } =20 static int ecryptfs_release(struct inode *inode, struct file *file) @@ -293,15 +297,7 @@ static int ecryptfs_release(struct inode *inode, struc= t file *file) static int ecryptfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) { - int rc =3D 0; - - rc =3D generic_file_fsync(file, start, end, datasync); - if (rc) - goto out; - rc =3D vfs_fsync_range(ecryptfs_file_to_lower(file), start, end, - datasync); -out: - return rc; + return vfs_fsync(ecryptfs_file_to_lower(file), datasync); } =20 static int ecryptfs_fasync(int fd, struct file *file, int flag) @@ -370,7 +366,7 @@ const struct file_operations ecryptfs_main_fops =3D { #ifdef CONFIG_COMPAT .compat_ioctl =3D ecryptfs_compat_ioctl, #endif - .mmap =3D ecryptfs_file_mmap, + .mmap =3D generic_file_mmap, .open =3D ecryptfs_open, .flush =3D ecryptfs_flush, .release =3D ecryptfs_release, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 7c7556b..a9be90d 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -161,6 +161,31 @@ ecryptfs_create_underlying_file(struct inode *lower_di= r_inode, return vfs_create(lower_dir_inode, lower_dentry, mode, NULL); } =20 +static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry, + struct inode *inode) +{ + struct dentry *lower_dentry =3D ecryptfs_dentry_to_lower(dentry); + struct inode *lower_dir_inode =3D ecryptfs_inode_to_lower(dir); + struct dentry *lower_dir_dentry; + int rc; + + dget(lower_dentry); + lower_dir_dentry =3D lock_parent(lower_dentry); + rc =3D vfs_unlink(lower_dir_inode, lower_dentry); + if (rc) { + printk(KERN_ERR "Error in vfs_unlink; rc =3D [%d]\n", rc); + goto out_unlock; + } + fsstack_copy_attr_times(dir, lower_dir_inode); + set_nlink(inode, ecryptfs_inode_to_lower(inode)->i_nlink); + inode->i_ctime =3D dir->i_ctime; + d_drop(dentry); +out_unlock: + unlock_dir(lower_dir_dentry); + dput(lower_dentry); + return rc; +} + /** * ecryptfs_do_create * @directory_inode: inode of the new file's dentry's parent in ecryptfs @@ -201,8 +226,10 @@ ecryptfs_do_create(struct inode *directory_inode, } inode =3D __ecryptfs_get_inode(lower_dentry->d_inode, directory_inode->i_sb); - if (IS_ERR(inode)) + if (IS_ERR(inode)) { + vfs_unlink(lower_dir_dentry->d_inode, lower_dentry); goto out_lock; + } fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode); out_lock: @@ -219,8 +246,8 @@ out: * * Returns zero on success */ -static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, - struct inode *ecryptfs_inode) +int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry, + struct inode *ecryptfs_inode) { struct ecryptfs_crypt_stat *crypt_stat =3D &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; @@ -284,7 +311,9 @@ ecryptfs_create(struct inode *directory_inode, struct d= entry *ecryptfs_dentry, * that this on disk file is prepared to be an ecryptfs file */ rc =3D ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode); if (rc) { - drop_nlink(ecryptfs_inode); + ecryptfs_do_unlink(directory_inode, ecryptfs_dentry, + ecryptfs_inode); + make_bad_inode(ecryptfs_inode); unlock_new_inode(ecryptfs_inode); iput(ecryptfs_inode); goto out; @@ -496,27 +525,7 @@ out_lock: =20 static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) { - int rc =3D 0; - struct dentry *lower_dentry =3D ecryptfs_dentry_to_lower(dentry); - struct inode *lower_dir_inode =3D ecryptfs_inode_to_lower(dir); - struct dentry *lower_dir_dentry; - - dget(lower_dentry); - lower_dir_dentry =3D lock_parent(lower_dentry); - rc =3D vfs_unlink(lower_dir_inode, lower_dentry); - if (rc) { - printk(KERN_ERR "Error in vfs_unlink; rc =3D [%d]\n", rc); - goto out_unlock; - } - fsstack_copy_attr_times(dir, lower_dir_inode); - set_nlink(dentry->d_inode, - ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink); - dentry->d_inode->i_ctime =3D dir->i_ctime; - d_drop(dentry); -out_unlock: - unlock_dir(lower_dir_dentry); - dput(lower_dentry); - return rc; + return ecryptfs_do_unlink(dir, dentry, dentry->d_inode); } =20 static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, @@ -1026,12 +1035,6 @@ static int ecryptfs_setattr(struct dentry *dentry, s= truct iattr *ia) goto out; } =20 - if (S_ISREG(inode->i_mode)) { - rc =3D filemap_write_and_wait(inode->i_mapping); - if (rc) - goto out; - fsstack_copy_attr_all(inode, lower_inode); - } memcpy(&lower_ia, ia, sizeof(lower_ia)); if (ia->ia_valid & ATTR_FILE) lower_ia.ia_file =3D ecryptfs_file_to_lower(ia->ia_file); diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index b4a6bef..1cfef9f 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode) inode_info =3D ecryptfs_inode_to_private(inode); if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count, &inode_info->lower_file_mutex)) { + filemap_write_and_wait(inode->i_mapping); fput(inode_info->lower_file); inode_info->lower_file =3D NULL; mutex_unlock(&inode_info->lower_file_mutex); diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 6a44148..93a998a 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -62,18 +62,6 @@ static int ecryptfs_writepage(struct page *page, struct = writeback_control *wbc) { int rc; =20 - /* - * Refuse to write the page out if we are called from reclaim context - * since our writepage() path may potentially allocate memory when - * calling into the lower fs vfs_write() which may in turn invoke - * us again. - */ - if (current->flags & PF_MEMALLOC) { - redirty_page_for_writepage(wbc, page); - rc =3D 0; - goto out; - } - rc =3D ecryptfs_encrypt_page(page); if (rc) { ecryptfs_printk(KERN_WARNING, "Error encrypting " @@ -498,7 +486,6 @@ static int ecryptfs_write_end(struct file *file, struct ecryptfs_crypt_stat *crypt_stat =3D &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; int rc; - int need_unlock_page =3D 1; =20 ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" "(page w/ index =3D [0x%.16lx], to =3D [%d])\n", index, to); @@ -519,26 +506,26 @@ static int ecryptfs_write_end(struct file *file, "zeros in page with index =3D [0x%.16lx]\n", index); goto out; } - set_page_dirty(page); - unlock_page(page); - need_unlock_page =3D 0; + rc =3D ecryptfs_encrypt_page(page); + if (rc) { + ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " + "index [0x%.16lx])\n", index); + goto out; + } if (pos + copied > i_size_read(ecryptfs_inode)) { i_size_write(ecryptfs_inode, pos + copied); ecryptfs_printk(KERN_DEBUG, "Expanded file size to " "[0x%.16llx]\n", (unsigned long long)i_size_read(ecryptfs_inode)); - balance_dirty_pages_ratelimited(mapping); - rc =3D ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); - if (rc) { - printk(KERN_ERR "Error writing inode size to metadata; " - "rc =3D [%d]\n", rc); - goto out; - } } - rc =3D copied; + rc =3D ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); + if (rc) + printk(KERN_ERR "Error writing inode size to metadata; " + "rc =3D [%d]\n", rc); + else + rc =3D copied; out: - if (need_unlock_page) - unlock_page(page); + unlock_page(page); page_cache_release(page); return rc; } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8b01f9f..bac2330 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2382,6 +2382,16 @@ static int ext4_nonda_switch(struct super_block *sb) free_blocks =3D EXT4_C2B(sbi, percpu_counter_read_positive(&sbi->s_freeclusters_counter)); dirty_blocks =3D percpu_counter_read_positive(&sbi->s_dirtyclusters_count= er); + /* + * Start pushing delalloc when 1/2 of free blocks are dirty. + */ + if (dirty_blocks && (free_blocks < 2 * dirty_blocks) && + !writeback_in_progress(sb->s_bdi) && + down_read_trylock(&sb->s_umount)) { + writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); + up_read(&sb->s_umount); + } + if (2 * free_blocks < 3 * dirty_blocks || free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { /* @@ -2390,13 +2400,6 @@ static int ext4_nonda_switch(struct super_block *sb) */ return 1; } - /* - * Even if we don't switch but are nearing capacity, - * start pushing delalloc when 1/2 of free blocks are dirty. - */ - if (free_blocks < 2 * dirty_blocks) - writeback_inodes_sb_if_idle(sb, WB_REASON_FS_FREE_SPACE); - return 0; } =20 @@ -4004,6 +4007,7 @@ static int ext4_do_update_inode(handle_t *handle, struct ext4_inode_info *ei =3D EXT4_I(inode); struct buffer_head *bh =3D iloc->bh; int err =3D 0, rc, block; + int need_datasync =3D 0; =20 /* For fields not not tracking in the in-memory inode, * initialise them to zero for new inodes. */ @@ -4052,7 +4056,10 @@ static int ext4_do_update_inode(handle_t *handle, raw_inode->i_file_acl_high =3D cpu_to_le16(ei->i_file_acl >> 32); raw_inode->i_file_acl_lo =3D cpu_to_le32(ei->i_file_acl); - ext4_isize_set(raw_inode, ei->i_disksize); + if (ei->i_disksize !=3D ext4_isize(raw_inode)) { + ext4_isize_set(raw_inode, ei->i_disksize); + need_datasync =3D 1; + } if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb =3D inode->i_sb; if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, @@ -4105,7 +4112,7 @@ static int ext4_do_update_inode(handle_t *handle, err =3D rc; ext4_clear_inode_state(inode, EXT4_STATE_NEW); =20 - ext4_update_inode_fsync_trans(handle, inode, 0); + ext4_update_inode_fsync_trans(handle, inode, need_datasync); out_brelse: brelse(bh); ext4_std_error(inode->i_sb, err); diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index c5826c6..e2016f3 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -141,55 +141,21 @@ mext_next_extent(struct inode *inode, struct ext4_ext= _path *path, } =20 /** - * mext_check_null_inode - NULL check for two inodes - * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. - */ -static int -mext_check_null_inode(struct inode *inode1, struct inode *inode2, - const char *function, unsigned int line) -{ - int ret =3D 0; - - if (inode1 =3D=3D NULL) { - __ext4_error(inode2->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 NULL inode2 %lu", inode2->i_ino); - ret =3D -EIO; - } else if (inode2 =3D=3D NULL) { - __ext4_error(inode1->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 %lu inode2 NULL", inode1->i_ino); - ret =3D -EIO; - } - return ret; -} - -/** * double_down_write_data_sem - Acquire two inodes' write lock of i_data_s= em * - * @orig_inode: original inode structure - * @donor_inode: donor inode structure - * Acquire write lock of i_data_sem of the two inodes (orig and donor) by - * i_ino order. + * Acquire write lock of i_data_sem of the two inodes */ static void -double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_i= node) +double_down_write_data_sem(struct inode *first, struct inode *second) { - struct inode *first =3D orig_inode, *second =3D donor_inode; + if (first < second) { + down_write(&EXT4_I(first)->i_data_sem); + down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); + } else { + down_write(&EXT4_I(second)->i_data_sem); + down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING); =20 - /* - * Use the inode number to provide the stable locking order instead - * of its address, because the C language doesn't guarantee you can - * compare pointers that don't come from the same array. - */ - if (donor_inode->i_ino < orig_inode->i_ino) { - first =3D donor_inode; - second =3D orig_inode; } - - down_write(&EXT4_I(first)->i_data_sem); - down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); } =20 /** @@ -969,14 +935,6 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } =20 - /* Files should be in the same ext4 FS */ - if (orig_inode->i_sb !=3D donor_inode->i_sb) { - ext4_debug("ext4 move extent: The argument files " - "should be in same FS [ino:orig %lu, donor %lu]\n", - orig_inode->i_ino, donor_inode->i_ino); - return -EINVAL; - } - /* Ext4 move extent supports only extent based file */ if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) { ext4_debug("ext4 move extent: orig file is not extents " @@ -1072,35 +1030,19 @@ mext_check_arguments(struct inode *orig_inode, * @inode1: the inode structure * @inode2: the inode structure * - * Lock two inodes' i_mutex by i_ino order. - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. + * Lock two inodes' i_mutex */ -static int +static void mext_inode_double_lock(struct inode *inode1, struct inode *inode2) { - int ret =3D 0; - - BUG_ON(inode1 =3D=3D NULL && inode2 =3D=3D NULL); - - ret =3D mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1 =3D=3D inode2) { - mutex_lock(&inode1->i_mutex); - goto out; - } - - if (inode1->i_ino < inode2->i_ino) { + BUG_ON(inode1 =3D=3D inode2); + if (inode1 < inode2) { mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); } else { mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); } - -out: - return ret; } =20 /** @@ -1109,28 +1051,13 @@ out: * @inode1: the inode that is released first * @inode2: the inode that is released second * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. */ =20 -static int +static void mext_inode_double_unlock(struct inode *inode1, struct inode *inode2) { - int ret =3D 0; - - BUG_ON(inode1 =3D=3D NULL && inode2 =3D=3D NULL); - - ret =3D mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1) - mutex_unlock(&inode1->i_mutex); - - if (inode2 && inode2 !=3D inode1) - mutex_unlock(&inode2->i_mutex); - -out: - return ret; + mutex_unlock(&inode1->i_mutex); + mutex_unlock(&inode2->i_mutex); } =20 /** @@ -1187,16 +1114,23 @@ ext4_move_extents(struct file *o_filp, struct file = *d_filp, ext4_lblk_t block_end, seq_start, add_blocks, file_end, seq_blocks =3D 0; ext4_lblk_t rest_blocks; pgoff_t orig_page_offset =3D 0, seq_end_page; - int ret1, ret2, depth, last_extent =3D 0; + int ret, depth, last_extent =3D 0; int blocks_per_page =3D PAGE_CACHE_SIZE >> orig_inode->i_blkbits; int data_offset_in_page; int block_len_in_page; int uninit; =20 - /* orig and donor should be different file */ - if (orig_inode->i_ino =3D=3D donor_inode->i_ino) { + if (orig_inode->i_sb !=3D donor_inode->i_sb) { + ext4_debug("ext4 move extent: The argument files " + "should be in same FS [ino:orig %lu, donor %lu]\n", + orig_inode->i_ino, donor_inode->i_ino); + return -EINVAL; + } + + /* orig and donor should be different inodes */ + if (orig_inode =3D=3D donor_inode) { ext4_debug("ext4 move extent: The argument files should not " - "be same file [ino:orig %lu, donor %lu]\n", + "be same inode [ino:orig %lu, donor %lu]\n", orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } @@ -1208,18 +1142,21 @@ ext4_move_extents(struct file *o_filp, struct file = *d_filp, orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } - + /* TODO: This is non obvious task to swap blocks for inodes with full + jornaling enabled */ + if (ext4_should_journal_data(orig_inode) || + ext4_should_journal_data(donor_inode)) { + return -EINVAL; + } /* Protect orig and donor inodes against a truncate */ - ret1 =3D mext_inode_double_lock(orig_inode, donor_inode); - if (ret1 < 0) - return ret1; + mext_inode_double_lock(orig_inode, donor_inode); =20 /* Protect extent tree against block allocations via delalloc */ double_down_write_data_sem(orig_inode, donor_inode); /* Check the filesystem environment whether move_extent can be done */ - ret1 =3D mext_check_arguments(orig_inode, donor_inode, orig_start, + ret =3D mext_check_arguments(orig_inode, donor_inode, orig_start, donor_start, &len); - if (ret1) + if (ret) goto out; =20 file_end =3D (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits; @@ -1227,13 +1164,13 @@ ext4_move_extents(struct file *o_filp, struct file = *d_filp, if (file_end < block_end) len -=3D block_end - file_end; =20 - ret1 =3D get_ext_path(orig_inode, block_start, &orig_path); - if (ret1) + ret =3D get_ext_path(orig_inode, block_start, &orig_path); + if (ret) goto out; =20 /* Get path structure to check the hole */ - ret1 =3D get_ext_path(orig_inode, block_start, &holecheck_path); - if (ret1) + ret =3D get_ext_path(orig_inode, block_start, &holecheck_path); + if (ret) goto out; =20 depth =3D ext_depth(orig_inode); @@ -1252,13 +1189,13 @@ ext4_move_extents(struct file *o_filp, struct file = *d_filp, last_extent =3D mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 =3D last_extent; + ret =3D last_extent; goto out; } last_extent =3D mext_next_extent(orig_inode, orig_path, &ext_dummy); if (last_extent < 0) { - ret1 =3D last_extent; + ret =3D last_extent; goto out; } seq_start =3D le32_to_cpu(ext_cur->ee_block); @@ -1272,7 +1209,7 @@ ext4_move_extents(struct file *o_filp, struct file *d= _filp, if (le32_to_cpu(ext_cur->ee_block) > block_end) { ext4_debug("ext4 move extent: The specified range of file " "may be the hole\n"); - ret1 =3D -EINVAL; + ret =3D -EINVAL; goto out; } =20 @@ -1292,7 +1229,7 @@ ext4_move_extents(struct file *o_filp, struct file *d= _filp, last_extent =3D mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 =3D last_extent; + ret =3D last_extent; break; } add_blocks =3D ext4_ext_get_actual_len(ext_cur); @@ -1349,18 +1286,18 @@ ext4_move_extents(struct file *o_filp, struct file = *d_filp, orig_page_offset, data_offset_in_page, block_len_in_page, uninit, - &ret1); + &ret); =20 /* Count how many blocks we have exchanged */ *moved_len +=3D block_len_in_page; - if (ret1 < 0) + if (ret < 0) break; if (*moved_len > len) { EXT4_ERROR_INODE(orig_inode, "We replaced blocks too much! " "sum of replaced: %llu requested: %llu", *moved_len, len); - ret1 =3D -EIO; + ret =3D -EIO; break; } =20 @@ -1374,22 +1311,22 @@ ext4_move_extents(struct file *o_filp, struct file = *d_filp, } =20 double_down_write_data_sem(orig_inode, donor_inode); - if (ret1 < 0) + if (ret < 0) break; =20 /* Decrease buffer counter */ if (holecheck_path) ext4_ext_drop_refs(holecheck_path); - ret1 =3D get_ext_path(orig_inode, seq_start, &holecheck_path); - if (ret1) + ret =3D get_ext_path(orig_inode, seq_start, &holecheck_path); + if (ret) break; depth =3D holecheck_path->p_depth; =20 /* Decrease buffer counter */ if (orig_path) ext4_ext_drop_refs(orig_path); - ret1 =3D get_ext_path(orig_inode, seq_start, &orig_path); - if (ret1) + ret =3D get_ext_path(orig_inode, seq_start, &orig_path); + if (ret) break; =20 ext_cur =3D holecheck_path[depth].p_ext; @@ -1412,12 +1349,7 @@ out: kfree(holecheck_path); } double_up_write_data_sem(orig_inode, donor_inode); - ret2 =3D mext_inode_double_unlock(orig_inode, donor_inode); - - if (ret1) - return ret1; - else if (ret2) - return ret2; + mext_inode_double_unlock(orig_inode, donor_inode); =20 - return 0; + return ret; } diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 4dd0890..88f97e5 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1801,9 +1801,7 @@ retry: err =3D PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); -#ifdef CONFIG_EXT4_FS_XATTR inode->i_op =3D &ext4_special_inode_operations; -#endif err =3D ext4_add_nondir(handle, dentry, inode); } ext4_journal_stop(handle); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 54f5786..13bfa07 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -63,6 +63,7 @@ int writeback_in_progress(struct backing_dev_info *bdi) { return test_bit(BDI_writeback_running, &bdi->state); } +EXPORT_SYMBOL(writeback_in_progress); =20 static inline struct backing_dev_info *inode_to_bdi(struct inode *inode) { diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index b09e51d..464cd76 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1032,11 +1032,11 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, ops.datbuf =3D NULL; =20 ret =3D c->mtd->read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen !=3D ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen !=3D ops.ooblen) { printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd" " bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret =3D -EIO; return ret; } @@ -1075,11 +1075,11 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_in= fo *c, ops.datbuf =3D NULL; =20 ret =3D c->mtd->read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen !=3D ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen !=3D ops.ooblen) { printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd" " bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret =3D -EIO; return ret; } diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 23d7451..df753a1 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -40,6 +40,7 @@ struct nsm_args { u32 proc; =20 char *mon_name; + char *nodename; }; =20 struct nsm_res { @@ -93,6 +94,7 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc= , struct nsm_res *res) .vers =3D 3, .proc =3D NLMPROC_NSM_NOTIFY, .mon_name =3D nsm->sm_mon_name, + .nodename =3D utsname()->nodename, }; struct rpc_message msg =3D { .rpc_argp =3D &args, @@ -429,7 +431,7 @@ static void encode_my_id(struct xdr_stream *xdr, const = struct nsm_args *argp) { __be32 *p; =20 - encode_nsm_string(xdr, utsname()->nodename); + encode_nsm_string(xdr, argp->nodename); p =3D xdr_reserve_space(xdr, 4 + 4 + 4); *p++ =3D cpu_to_be32(argp->prog); *p++ =3D cpu_to_be32(argp->vers); diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklay= out.c index d774309..1aaa0ee 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -164,25 +164,39 @@ static struct bio *bl_alloc_init_bio(int npg, sector_= t isect, return bio; } =20 -static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, +static struct bio *do_add_page_to_bio(struct bio *bio, int npg, int rw, sector_t isect, struct page *page, struct pnfs_block_extent *be, void (*end_io)(struct bio *, int err), - struct parallel_io *par) + struct parallel_io *par, + unsigned int offset, int len) { + isect =3D isect + (offset >> SECTOR_SHIFT); + dprintk("%s: npg %d rw %d isect %llu offset %u len %d\n", __func__, + npg, rw, (unsigned long long)isect, offset, len); retry: if (!bio) { bio =3D bl_alloc_init_bio(npg, isect, be, end_io, par); if (!bio) return ERR_PTR(-ENOMEM); } - if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { + if (bio_add_page(bio, page, len, offset) < len) { bio =3D bl_submit_bio(rw, bio); goto retry; } return bio; } =20 +static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, + sector_t isect, struct page *page, + struct pnfs_block_extent *be, + void (*end_io)(struct bio *, int err), + struct parallel_io *par) +{ + return do_add_page_to_bio(bio, npg, rw, isect, page, be, + end_io, par, 0, PAGE_CACHE_SIZE); +} + /* This is basically copied from mpage_end_io_read */ static void bl_end_io_read(struct bio *bio, int err) { @@ -446,6 +460,106 @@ map_block(struct buffer_head *bh, sector_t isect, str= uct pnfs_block_extent *be) return; } =20 +static void +bl_read_single_end_io(struct bio *bio, int error) +{ + struct bio_vec *bvec =3D bio->bi_io_vec + bio->bi_vcnt - 1; + struct page *page =3D bvec->bv_page; + + /* Only one page in bvec */ + unlock_page(page); +} + +static int +bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int offset, unsigned int len) +{ + struct bio *bio; + struct page *shadow_page; + sector_t isect; + char *kaddr, *kshadow_addr; + int ret =3D 0; + + dprintk("%s: offset %u len %u\n", __func__, offset, len); + + shadow_page =3D alloc_page(GFP_NOFS | __GFP_HIGHMEM); + if (shadow_page =3D=3D NULL) + return -ENOMEM; + + bio =3D bio_alloc(GFP_NOIO, 1); + if (bio =3D=3D NULL) + return -ENOMEM; + + isect =3D (page->index << PAGE_CACHE_SECTOR_SHIFT) + + (offset / SECTOR_SIZE); + + bio->bi_sector =3D isect - be->be_f_offset + be->be_v_offset; + bio->bi_bdev =3D be->be_mdev; + bio->bi_end_io =3D bl_read_single_end_io; + + lock_page(shadow_page); + if (bio_add_page(bio, shadow_page, + SECTOR_SIZE, round_down(offset, SECTOR_SIZE)) =3D=3D 0) { + unlock_page(shadow_page); + bio_put(bio); + return -EIO; + } + + submit_bio(READ, bio); + wait_on_page_locked(shadow_page); + if (unlikely(!test_bit(BIO_UPTODATE, &bio->bi_flags))) { + ret =3D -EIO; + } else { + kaddr =3D kmap_atomic(page); + kshadow_addr =3D kmap_atomic(shadow_page); + memcpy(kaddr + offset, kshadow_addr + offset, len); + kunmap_atomic(kshadow_addr); + kunmap_atomic(kaddr); + } + __free_page(shadow_page); + bio_put(bio); + + return ret; +} + +static int +bl_read_partial_page_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int dirty_offset, unsigned int dirty_len, + bool full_page) +{ + int ret =3D 0; + unsigned int start, end; + + if (full_page) { + start =3D 0; + end =3D PAGE_CACHE_SIZE; + } else { + start =3D round_down(dirty_offset, SECTOR_SIZE); + end =3D round_up(dirty_offset + dirty_len, SECTOR_SIZE); + } + + dprintk("%s: offset %u len %d\n", __func__, dirty_offset, dirty_len); + if (!be) { + zero_user_segments(page, start, dirty_offset, + dirty_offset + dirty_len, end); + if (start =3D=3D 0 && end =3D=3D PAGE_CACHE_SIZE && + trylock_page(page)) { + SetPageUptodate(page); + unlock_page(page); + } + return ret; + } + + if (start !=3D dirty_offset) + ret =3D bl_do_readpage_sync(page, be, start, dirty_offset - start); + + if (!ret && (dirty_offset + dirty_len < end)) + ret =3D bl_do_readpage_sync(page, be, dirty_offset + dirty_len, + end - dirty_offset - dirty_len); + + return ret; +} + /* Given an unmapped page, zero it or read in page for COW, page is locked * by caller. */ @@ -479,7 +593,6 @@ init_page_for_write(struct page *page, struct pnfs_bloc= k_extent *cow_read) SetPageUptodate(page); =20 cleanup: - bl_put_extent(cow_read); if (bh) free_buffer_head(bh); if (ret) { @@ -501,6 +614,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int syn= c) struct parallel_io *par; loff_t offset =3D wdata->args.offset; size_t count =3D wdata->args.count; + unsigned int pg_offset, pg_len, saved_len; struct page **pages =3D wdata->args.pages; struct page *page; pgoff_t index; @@ -615,10 +729,11 @@ next_page: if (!extent_length) { /* We've used up the previous extent */ bl_put_extent(be); + bl_put_extent(cow_read); bio =3D bl_submit_bio(WRITE, bio); /* Get the next one */ be =3D bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), - isect, NULL); + isect, &cow_read); if (!be || !is_writable(be, isect)) { wdata->pnfs_error =3D -EINVAL; goto out; @@ -626,7 +741,26 @@ next_page: extent_length =3D be->be_length - (isect - be->be_f_offset); } - if (be->be_state =3D=3D PNFS_BLOCK_INVALID_DATA) { + + dprintk("%s offset %lld count %Zu\n", __func__, offset, count); + pg_offset =3D offset & ~PAGE_CACHE_MASK; + if (pg_offset + count > PAGE_CACHE_SIZE) + pg_len =3D PAGE_CACHE_SIZE - pg_offset; + else + pg_len =3D count; + + saved_len =3D pg_len; + if (be->be_state =3D=3D PNFS_BLOCK_INVALID_DATA && + !bl_is_sector_init(be->be_inval, isect)) { + ret =3D bl_read_partial_page_sync(pages[i], cow_read, + pg_offset, pg_len, true); + if (ret) { + dprintk("%s bl_read_partial_page_sync fail %d\n", + __func__, ret); + wdata->pnfs_error =3D ret; + goto out; + } + ret =3D bl_mark_sectors_init(be->be_inval, isect, PAGE_CACHE_SECTORS, NULL); @@ -636,15 +770,35 @@ next_page: wdata->pnfs_error =3D ret; goto out; } + + /* Expand to full page write */ + pg_offset =3D 0; + pg_len =3D PAGE_CACHE_SIZE; + } else if ((pg_offset & (SECTOR_SIZE - 1)) || + (pg_len & (SECTOR_SIZE - 1))){ + /* ahh, nasty case. We have to do sync full sector + * read-modify-write cycles. + */ + unsigned int saved_offset =3D pg_offset; + ret =3D bl_read_partial_page_sync(pages[i], be, pg_offset, + pg_len, false); + pg_offset =3D round_down(pg_offset, SECTOR_SIZE); + pg_len =3D round_up(saved_offset + pg_len, SECTOR_SIZE) + - pg_offset; } - bio =3D bl_add_page_to_bio(bio, wdata->npages - i, WRITE, + + + bio =3D do_add_page_to_bio(bio, wdata->npages - i, WRITE, isect, pages[i], be, - bl_end_io_write, par); + bl_end_io_write, par, + pg_offset, pg_len); if (IS_ERR(bio)) { wdata->pnfs_error =3D PTR_ERR(bio); bio =3D NULL; goto out; } + offset +=3D saved_len; + count -=3D saved_len; isect +=3D PAGE_CACHE_SECTORS; last_isect =3D isect; extent_length -=3D PAGE_CACHE_SECTORS; @@ -662,12 +816,10 @@ next_page: } =20 write_done: - wdata->res.count =3D (last_isect << SECTOR_SHIFT) - (offset); - if (count < wdata->res.count) { - wdata->res.count =3D count; - } + wdata->res.count =3D wdata->args.count; out: bl_put_extent(be); + bl_put_extent(cow_read); bl_submit_bio(WRITE, bio); put_parallel(par); return PNFS_ATTEMPTED; diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklay= out.h index 42acf7e..519a9de 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h @@ -40,6 +40,7 @@ =20 #define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT) #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT) +#define SECTOR_SIZE (1 << SECTOR_SHIFT) =20 struct block_mount_id { spinlock_t bm_lock; /* protects list */ diff --git a/fs/udf/super.c b/fs/udf/super.c index 516b7f0..f66439e 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1289,6 +1289,7 @@ static int udf_load_logicalvol(struct super_block *sb= , sector_t block, udf_err(sb, "error loading logical volume descriptor: " "Partition table too long (%u > %lu)\n", table_len, sb->s_blocksize - sizeof(*lvd)); + ret =3D 1; goto out_bh; } =20 @@ -1333,8 +1334,10 @@ static int udf_load_logicalvol(struct super_block *s= b, sector_t block, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { if (udf_load_sparable_map(sb, map, - (struct sparablePartitionMap *)gpm) < 0) + (struct sparablePartitionMap *)gpm) < 0) { + ret =3D 1; goto out_bh; + } } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) { diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 7978eec..3e8f2f7 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -188,7 +188,7 @@ struct sp_node { =20 struct shared_policy { struct rb_root root; - spinlock_t lock; + struct mutex mutex; }; =20 void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *m= pol); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 67cc215..1874c5e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1823,7 +1823,6 @@ #define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 #define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 -#define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL 0x2530 =20 #define PCI_VENDOR_ID_RADISYS 0x1331 =20 diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index e5a7b9a..416dcb0 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -1353,7 +1353,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb) struct nf_conn *ct =3D nf_ct_get(skb, &ctinfo); =20 if (!ct || !nf_ct_is_untracked(ct)) { - nf_reset(skb); + nf_conntrack_put(skb->nfct); skb->nfct =3D &nf_ct_untracked_get()->ct_general; skb->nfctinfo =3D IP_CT_NEW; nf_conntrack_get(skb->nfct); diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 6b76d81..a122196 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -292,7 +292,9 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp) static int cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp) { - return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp); + return *rdp->nxttail[RCU_DONE_TAIL + + ACCESS_ONCE(rsp->completed) !=3D rdp->completed] && + !rcu_gp_in_progress(rsp); } =20 /* diff --git a/kernel/sched_stoptask.c b/kernel/sched_stoptask.c index 8b44e7f..85e9da2 100644 --- a/kernel/sched_stoptask.c +++ b/kernel/sched_stoptask.c @@ -25,8 +25,10 @@ static struct task_struct *pick_next_task_stop(struct rq= *rq) { struct task_struct *stop =3D rq->stop; =20 - if (stop && stop->on_rq) + if (stop && stop->on_rq) { + stop->se.exec_start =3D rq->clock_task; return stop; + } =20 return NULL; } @@ -50,6 +52,21 @@ static void yield_task_stop(struct rq *rq) =20 static void put_prev_task_stop(struct rq *rq, struct task_struct *prev) { + struct task_struct *curr =3D rq->curr; + u64 delta_exec; + + delta_exec =3D rq->clock_task - curr->se.exec_start; + if (unlikely((s64)delta_exec < 0)) + delta_exec =3D 0; + + schedstat_set(curr->se.statistics.exec_max, + max(curr->se.statistics.exec_max, delta_exec)); + + curr->se.sum_exec_runtime +=3D delta_exec; + account_group_exec_runtime(curr, delta_exec); + + curr->se.exec_start =3D rq->clock_task; + cpuacct_charge(curr, delta_exec); } =20 static void task_tick_stop(struct rq *rq, struct task_struct *curr, int qu= eued) @@ -58,6 +75,9 @@ static void task_tick_stop(struct rq *rq, struct task_str= uct *curr, int queued) =20 static void set_curr_task_stop(struct rq *rq) { + struct task_struct *stop =3D rq->stop; + + stop->se.exec_start =3D rq->clock_task; } =20 static void switched_to_stop(struct rq *rq, struct task_struct *p) diff --git a/kernel/sys.c b/kernel/sys.c index 481611f..c504302 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -365,6 +365,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier); void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); + disable_nonboot_cpus(); if (!cmd) printk(KERN_EMERG "Restarting system.\n"); else diff --git a/kernel/workqueue.c b/kernel/workqueue.c index b413138..43a19c5 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1726,10 +1726,9 @@ static void move_linked_works(struct work_struct *wo= rk, struct list_head *head, *nextp =3D n; } =20 -static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) +static void cwq_activate_delayed_work(struct work_struct *work) { - struct work_struct *work =3D list_first_entry(&cwq->delayed_works, - struct work_struct, entry); + struct cpu_workqueue_struct *cwq =3D get_work_cwq(work); struct list_head *pos =3D gcwq_determine_ins_pos(cwq->gcwq, cwq); =20 trace_workqueue_activate_work(work); @@ -1738,6 +1737,14 @@ static void cwq_activate_first_delayed(struct cpu_wo= rkqueue_struct *cwq) cwq->nr_active++; } =20 +static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) +{ + struct work_struct *work =3D list_first_entry(&cwq->delayed_works, + struct work_struct, entry); + + cwq_activate_delayed_work(work); +} + /** * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight * @cwq: cwq of interest @@ -1869,7 +1876,9 @@ __acquires(&gcwq->lock) =20 spin_unlock_irq(&gcwq->lock); =20 + smp_wmb(); /* paired with test_and_set_bit(PENDING) */ work_clear_pending(work); + lock_map_acquire_read(&cwq->wq->lockdep_map); lock_map_acquire(&lockdep_map); trace_workqueue_execute_start(work); @@ -2626,6 +2635,18 @@ static int try_to_grab_pending(struct work_struct *w= ork) smp_rmb(); if (gcwq =3D=3D get_work_gcwq(work)) { debug_work_deactivate(work); + + /* + * A delayed work item cannot be grabbed directly + * because it might have linked NO_COLOR work items + * which, if left on the delayed_list, will confuse + * cwq->nr_active management later on and cause + * stall. Make sure the work item is activated + * before grabbing. + */ + if (*work_data_bits(work) & WORK_STRUCT_DELAYED) + cwq_activate_delayed_work(work); + list_del_init(&work->entry); cwq_dec_nr_in_flight(get_work_cwq(work), get_work_color(work), diff --git a/lib/gcd.c b/lib/gcd.c index f879033..433d89b 100644 --- a/lib/gcd.c +++ b/lib/gcd.c @@ -9,6 +9,9 @@ unsigned long gcd(unsigned long a, unsigned long b) =20 if (a < b) swap(a, b); + + if (!b) + return a; while ((r =3D a % b) !=3D 0) { a =3D b; b =3D r; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 0f897b8..d6c0fdf 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2429,8 +2429,8 @@ static int unmap_ref_private(struct mm_struct *mm, st= ruct vm_area_struct *vma, * from page cache lookup which is in HPAGE_SIZE units. */ address =3D address & huge_page_mask(h); - pgoff =3D ((address - vma->vm_start) >> PAGE_SHIFT) - + (vma->vm_pgoff >> PAGE_SHIFT); + pgoff =3D ((address - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff; mapping =3D vma->vm_file->f_dentry->d_inode->i_mapping; =20 /* diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 11b8d47..4c82c21 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -607,24 +607,39 @@ check_range(struct mm_struct *mm, unsigned long start= , unsigned long end, return first; } =20 -/* Apply policy to a single VMA */ -static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new) +/* + * Apply policy to a single VMA + * This must be called with the mmap_sem held for writing. + */ +static int vma_replace_policy(struct vm_area_struct *vma, + struct mempolicy *pol) { - int err =3D 0; - struct mempolicy *old =3D vma->vm_policy; + int err; + struct mempolicy *old; + struct mempolicy *new; =20 pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", vma->vm_start, vma->vm_end, vma->vm_pgoff, vma->vm_ops, vma->vm_file, vma->vm_ops ? vma->vm_ops->set_policy : NULL); =20 - if (vma->vm_ops && vma->vm_ops->set_policy) + new =3D mpol_dup(pol); + if (IS_ERR(new)) + return PTR_ERR(new); + + if (vma->vm_ops && vma->vm_ops->set_policy) { err =3D vma->vm_ops->set_policy(vma, new); - if (!err) { - mpol_get(new); - vma->vm_policy =3D new; - mpol_put(old); + if (err) + goto err_out; } + + old =3D vma->vm_policy; + vma->vm_policy =3D new; /* protected by mmap_sem */ + mpol_put(old); + + return 0; + err_out: + mpol_put(new); return err; } =20 @@ -675,7 +690,7 @@ static int mbind_range(struct mm_struct *mm, unsigned l= ong start, if (err) goto out; } - err =3D policy_vma(vma, new_pol); + err =3D vma_replace_policy(vma, new_pol); if (err) goto out; } @@ -1507,8 +1522,18 @@ struct mempolicy *get_vma_policy(struct task_struct = *task, addr); if (vpol) pol =3D vpol; - } else if (vma->vm_policy) + } else if (vma->vm_policy) { pol =3D vma->vm_policy; + + /* + * shmem_alloc_page() passes MPOL_F_SHARED policy with + * a pseudo vma whose vma->vm_ops=3DNULL. Take a reference + * count on these policies which will be dropped by + * mpol_cond_put() later + */ + if (mpol_needs_cond_ref(pol)) + mpol_get(pol); + } } if (!pol) pol =3D &default_policy; @@ -2032,7 +2057,7 @@ int __mpol_equal(struct mempolicy *a, struct mempolic= y *b) */ =20 /* lookup first element intersecting start-end */ -/* Caller holds sp->lock */ +/* Caller holds sp->mutex */ static struct sp_node * sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end= ) { @@ -2096,36 +2121,50 @@ mpol_shared_policy_lookup(struct shared_policy *sp,= unsigned long idx) =20 if (!sp->root.rb_node) return NULL; - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); sn =3D sp_lookup(sp, idx, idx+1); if (sn) { mpol_get(sn->policy); pol =3D sn->policy; } - spin_unlock(&sp->lock); + mutex_unlock(&sp->mutex); return pol; } =20 +static void sp_free(struct sp_node *n) +{ + mpol_put(n->policy); + kmem_cache_free(sn_cache, n); +} + static void sp_delete(struct shared_policy *sp, struct sp_node *n) { pr_debug("deleting %lx-l%lx\n", n->start, n->end); rb_erase(&n->nd, &sp->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_free(n); } =20 static struct sp_node *sp_alloc(unsigned long start, unsigned long end, struct mempolicy *pol) { - struct sp_node *n =3D kmem_cache_alloc(sn_cache, GFP_KERNEL); + struct sp_node *n; + struct mempolicy *newpol; =20 + n =3D kmem_cache_alloc(sn_cache, GFP_KERNEL); if (!n) return NULL; + + newpol =3D mpol_dup(pol); + if (IS_ERR(newpol)) { + kmem_cache_free(sn_cache, n); + return NULL; + } + newpol->flags |=3D MPOL_F_SHARED; + n->start =3D start; n->end =3D end; - mpol_get(pol); - pol->flags |=3D MPOL_F_SHARED; /* for unref */ - n->policy =3D pol; + n->policy =3D newpol; + return n; } =20 @@ -2133,10 +2172,10 @@ static struct sp_node *sp_alloc(unsigned long start= , unsigned long end, static int shared_policy_replace(struct shared_policy *sp, unsigned long s= tart, unsigned long end, struct sp_node *new) { - struct sp_node *n, *new2 =3D NULL; + struct sp_node *n; + int ret =3D 0; =20 -restart: - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); n =3D sp_lookup(sp, start, end); /* Take care of old policies in the same range. */ while (n && n->start < end) { @@ -2149,16 +2188,14 @@ restart: } else { /* Old policy spanning whole new range. */ if (n->end > end) { + struct sp_node *new2; + new2 =3D sp_alloc(end, n->end, n->policy); if (!new2) { - spin_unlock(&sp->lock); - new2 =3D sp_alloc(end, n->end, n->policy); - if (!new2) - return -ENOMEM; - goto restart; + ret =3D -ENOMEM; + goto out; } n->end =3D start; sp_insert(sp, new2); - new2 =3D NULL; break; } else n->end =3D start; @@ -2169,12 +2206,9 @@ restart: } if (new) sp_insert(sp, new); - spin_unlock(&sp->lock); - if (new2) { - mpol_put(new2->policy); - kmem_cache_free(sn_cache, new2); - } - return 0; +out: + mutex_unlock(&sp->mutex); + return ret; } =20 /** @@ -2192,7 +2226,7 @@ void mpol_shared_policy_init(struct shared_policy *sp= , struct mempolicy *mpol) int ret; =20 sp->root =3D RB_ROOT; /* empty tree =3D=3D default mempolicy */ - spin_lock_init(&sp->lock); + mutex_init(&sp->mutex); =20 if (mpol) { struct vm_area_struct pvma; @@ -2246,7 +2280,7 @@ int mpol_set_shared_policy(struct shared_policy *info= , } err =3D shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new)= ; if (err && new) - kmem_cache_free(sn_cache, new); + sp_free(new); return err; } =20 @@ -2258,16 +2292,14 @@ void mpol_free_shared_policy(struct shared_policy *= p) =20 if (!p->root.rb_node) return; - spin_lock(&p->lock); + mutex_lock(&p->mutex); next =3D rb_first(&p->root); while (next) { n =3D rb_entry(next, struct sp_node, nd); next =3D rb_next(&n->nd); - rb_erase(&n->nd, &p->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_delete(p, n); } - spin_unlock(&p->lock); + mutex_unlock(&p->mutex); } =20 /* assumes fs =3D=3D KERNEL_DS */ diff --git a/mm/slab.c b/mm/slab.c index cd3ab93..4c3b671 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1669,9 +1669,6 @@ void __init kmem_cache_init_late(void) =20 g_cpucache_up =3D LATE; =20 - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); - /* 6) resize the head arrays to their final sizes */ mutex_lock(&cache_chain_mutex); list_for_each_entry(cachep, &cache_chain, next) @@ -1679,6 +1676,9 @@ void __init kmem_cache_init_late(void) BUG(); mutex_unlock(&cache_chain_mutex); =20 + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); + /* Done! */ g_cpucache_up =3D FULL; =20 diff --git a/mm/truncate.c b/mm/truncate.c index 632b15e..00fb58a 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -394,11 +394,12 @@ invalidate_complete_page2(struct address_space *mappi= ng, struct page *page) if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL)) return 0; =20 + clear_page_mlock(page); + spin_lock_irq(&mapping->tree_lock); if (PageDirty(page)) goto failed; =20 - clear_page_mlock(page); BUG_ON(page_has_private(page)); __delete_from_page_cache(page); spin_unlock_irq(&mapping->tree_lock); diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netf= ilter/nf_conntrack_l3proto_ipv4.c index de9da21..d7d63f4 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -84,6 +84,14 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, u= nsigned int nhoff, *dataoff =3D nhoff + (iph->ihl << 2); *protonum =3D iph->protocol; =20 + /* Check bogus IP headers */ + if (*dataoff > skb->len) { + pr_debug("nf_conntrack_ipv4: bogus IPv4 packet: " + "nhoff %u, ihl %u, skblen %u\n", + nhoff, iph->ihl << 2, skb->len); + return -NF_ACCEPT; + } + return NF_ACCEPT; } =20 diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_si= p.c index 78844d9..6609a84 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, uns= igned int dataoff, if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, hdr, NULL, &matchoff, &matchlen, &addr, &port) > 0) { - unsigned int matchend, poff, plen, buflen, n; + unsigned int olen, matchend, poff, plen, buflen, n; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; =20 /* We're only interested in headers related to this @@ -163,11 +163,12 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, u= nsigned int dataoff, goto next; } =20 + olen =3D *datalen; if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; =20 - matchend =3D matchoff + matchlen; + matchend =3D matchoff + matchlen + *datalen - olen; =20 /* The maddr=3D parameter (RFC 2361) specifies where to send * the reply. */ @@ -501,7 +502,10 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *s= kb, unsigned int dataoff, ret =3D nf_ct_expect_related(rtcp_exp); if (ret =3D=3D 0) break; - else if (ret !=3D -EBUSY) { + else if (ret =3D=3D -EBUSY) { + nf_ct_unexpect_related(rtp_exp); + continue; + } else if (ret < 0) { nf_ct_unexpect_related(rtp_exp); port =3D 0; break; diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntra= ck_expect.c index 340c80d..7918eb7 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -366,23 +366,6 @@ static void evict_oldest_expect(struct nf_conn *master= , } } =20 -static inline int refresh_timer(struct nf_conntrack_expect *i) -{ - struct nf_conn_help *master_help =3D nfct_help(i->master); - const struct nf_conntrack_expect_policy *p; - - if (!del_timer(&i->timeout)) - return 0; - - p =3D &rcu_dereference_protected( - master_help->helper, - lockdep_is_held(&nf_conntrack_lock) - )->expect_policy[i->class]; - i->timeout.expires =3D jiffies + p->timeout * HZ; - add_timer(&i->timeout); - return 1; -} - static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) { const struct nf_conntrack_expect_policy *p; @@ -390,7 +373,7 @@ static inline int __nf_ct_expect_check(struct nf_conntr= ack_expect *expect) struct nf_conn *master =3D expect->master; struct nf_conn_help *master_help =3D nfct_help(master); struct net *net =3D nf_ct_exp_net(expect); - struct hlist_node *n; + struct hlist_node *n, *next; unsigned int h; int ret =3D 1; =20 @@ -401,12 +384,12 @@ static inline int __nf_ct_expect_check(struct nf_conn= track_expect *expect) goto out; } h =3D nf_ct_expect_dst_hash(&expect->tuple); - hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { + hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) { if (expect_matches(i, expect)) { - /* Refresh timer: if it's dying, ignore.. */ - if (refresh_timer(i)) { - ret =3D 0; - goto out; + if (del_timer(&i->timeout)) { + nf_ct_unlink_expect(i); + nf_ct_expect_put(i); + break; } } else if (expect_clash(i, expect)) { ret =3D -EBUSY; diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index dfd52ba..8f3f280 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -389,8 +389,7 @@ static void htable_put(struct xt_hashlimit_htable *hinf= o) #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) =20 /* Precision saver. */ -static inline u_int32_t -user2credits(u_int32_t user) +static u32 user2credits(u32 user) { /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) @@ -400,7 +399,7 @@ user2credits(u_int32_t user) return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE; } =20 -static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long n= ow) +static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) { dh->rateinfo.credit +=3D (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY; if (dh->rateinfo.credit > dh->rateinfo.credit_cap) @@ -531,8 +530,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_actio= n_param *par) dh->rateinfo.prev =3D jiffies; dh->rateinfo.credit =3D user2credits(hinfo->cfg.avg * hinfo->cfg.burst); - dh->rateinfo.credit_cap =3D user2credits(hinfo->cfg.avg * - hinfo->cfg.burst); + dh->rateinfo.credit_cap =3D dh->rateinfo.credit; dh->rateinfo.cost =3D user2credits(hinfo->cfg.avg); } else { /* update expiration timeout */ diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 32b7a57..a4c1e45 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -88,8 +88,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_para= m *par) } =20 /* Precision saver. */ -static u_int32_t -user2credits(u_int32_t user) +static u32 user2credits(u32 user) { /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) @@ -118,12 +117,12 @@ static int limit_mt_check(const struct xt_mtchk_param= *par) =20 /* For SMP, we only want to use one set of state. */ r->master =3D priv; + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * + 128. */ + priv->prev =3D jiffies; + priv->credit =3D user2credits(r->avg * r->burst); /* Credits full. */ if (r->cost =3D=3D 0) { - /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * - 128. */ - priv->prev =3D jiffies; - priv->credit =3D user2credits(r->avg * r->burst); /* Credits full. */ - r->credit_cap =3D user2credits(r->avg * r->burst); /* Credits full. */ + r->credit_cap =3D priv->credit; /* Credits full. */ r->cost =3D user2credits(r->avg); } return 0; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c5391af..10a385b 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1028,6 +1028,16 @@ static void xs_udp_data_ready(struct sock *sk, int l= en) read_unlock_bh(&sk->sk_callback_lock); } =20 +/* + * Helper function to force a TCP close if the server is sending + * junk and/or it has put us in CLOSE_WAIT + */ +static void xs_tcp_force_close(struct rpc_xprt *xprt) +{ + set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); + xprt_force_disconnect(xprt); +} + static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_s= kb_reader *desc) { struct sock_xprt *transport =3D container_of(xprt, struct sock_xprt, xprt= ); @@ -1054,7 +1064,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xpr= t *xprt, struct xdr_skb_rea /* Sanity check of the record length */ if (unlikely(transport->tcp_reclen < 8)) { dprintk("RPC: invalid TCP record fragment length\n"); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); return; } dprintk("RPC: reading TCP record fragment of length %d\n", @@ -1135,7 +1145,7 @@ static inline void xs_tcp_read_calldir(struct sock_xp= rt *transport, break; default: dprintk("RPC: invalid request message type\n"); - xprt_force_disconnect(&transport->xprt); + xs_tcp_force_close(&transport->xprt); } xs_tcp_check_fraghdr(transport); } @@ -1458,6 +1468,8 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_x= prt *xprt) static void xs_sock_mark_closed(struct rpc_xprt *xprt) { smp_mb__before_clear_bit(); + clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); + clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); @@ -1515,8 +1527,8 @@ static void xs_tcp_state_change(struct sock *sk) break; case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ - xprt_force_disconnect(xprt); xprt->connect_cookie++; + xs_tcp_force_close(xprt); case TCP_CLOSING: /* * If the server closed down the connection, make sure that @@ -2159,8 +2171,7 @@ static void xs_tcp_setup_socket(struct work_struct *w= ork) /* We're probably in TIME_WAIT. Get rid of existing socket, * and retry */ - set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); break; case -ECONNREFUSED: case -ECONNRESET: diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index d897278..978416d 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -98,24 +98,24 @@ try-run =3D $(shell set -e; \ # Usage: cflags-y +=3D $(call as-option,-Wa$(comma)-isa=3Dfoo,) =20 as-option =3D $(call try-run,\ - $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)= ) + $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2= )) =20 # as-instr # Usage: cflags-y +=3D $(call as-instr,instr,option1,option2) =20 as-instr =3D $(call try-run,\ - /bin/echo -e "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,= $(2),$(3)) + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" = -,$(2),$(3)) =20 # cc-option # Usage: cflags-y +=3D $(call cc-option,-march=3Dwinchip-c6,-march=3Di586) =20 cc-option =3D $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP= ",$(1),$(2)) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TM= P",$(1),$(2)) =20 # cc-option-yn # Usage: flag :=3D $(call cc-option-yn,-march=3Dwinchip-c6) cc-option-yn =3D $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP= ",y,n) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TM= P",y,n) =20 # cc-option-align # Prefix align with either -falign or -malign @@ -125,7 +125,7 @@ cc-option-align =3D $(subst -functions=3D0,,\ # cc-disable-warning # Usage: cflags-y +=3D $(call cc-disable-warning,unused-but-set-variable) cc-disable-warning =3D $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/nul= l -o "$$TMP",-Wno-$(strip $(1))) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/nu= ll -o "$$TMP",-Wno-$(strip $(1))) =20 # cc-version # Usage gcc-ver :=3D $(call cc-version) @@ -143,7 +143,7 @@ cc-ifversion =3D $(shell [ $(call cc-version, $(CC)) $(= 1) $(2) ] && echo $(3)) # cc-ldoption # Usage: ldflags +=3D $(call cc-ldoption, -Wl$(comma)--hash-style=3Dboth) cc-ldoption =3D $(call try-run,\ - $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) =20 # ld-option # Usage: LDFLAGS +=3D $(call ld-option, -X) @@ -209,7 +209,7 @@ endif # >$< substitution to preserve $ when reloading .cmd file # note: when using inline perl scripts [perl -e '...$$t=3D1;...'] # in $(cmd_xxx) double $$ your perl vars -make-cmd =3D $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) +make-cmd =3D $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,= $(cmd_$(1)))))) =20 # Find any prerequisites that is newer than target or that does not exist. # PHONY targets skipped in both cases. diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index 6bf8e87..c3f69ae 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst @@ -42,7 +42,7 @@ quiet_cmd_install =3D INSTALL $(subst $(srctree)/,,$@) $(installed-fw-dirs): $(call cmd,mkdir) =20 -$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(di= r %) +$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH= )/%) $(call cmd,install) =20 PHONY +=3D __fw_install __fw_modinst FORCE diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh index debecb5..7f2126d 100644 --- a/scripts/gcc-version.sh +++ b/scripts/gcc-version.sh @@ -22,10 +22,10 @@ if [ ${#compiler} -eq 0 ]; then exit 1 fi =20 -MAJOR=3D$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) -MINOR=3D$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) +MAJOR=3D$(echo __GNUC__ | $compiler -E -x c - | tail -n 1) +MINOR=3D$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1) if [ "x$with_patchlevel" !=3D "x" ] ; then - PATCHLEVEL=3D$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1) + PATCHLEVEL=3D$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1= ) printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL else printf "%02d%02d\\n" $MAJOR $MINOR diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32= -has-stack-protector.sh index 29493dc..12dbd0b 100644 --- a/scripts/gcc-x86_32-has-stack-protector.sh +++ b/scripts/gcc-x86_32-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh =20 -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack= -protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstac= k-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64= -has-stack-protector.sh index afaec61..973e8c1 100644 --- a/scripts/gcc-x86_64-has-stack-protector.sh +++ b/scripts/gcc-x86_64-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh =20 -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmode= l=3Dkernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmod= el=3Dkernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh index fa59cbf..854d9c7 100755 --- a/scripts/kconfig/check.sh +++ b/scripts/kconfig/check.sh @@ -1,6 +1,6 @@ #!/bin/sh # Needed for systems without gettext -$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +$* -x c -o /dev/null - > /dev/null 2>&1 << EOF #include int main() { diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/l= xdialog/check-lxdialog.sh index 82cc3a8..50df490 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15 =20 # Check if we can link to ncurses check() { - $cc -xc - -o $tmp 2>/dev/null <<'EOF' + $cc -x c - -o $tmp 2>/dev/null <<'EOF' #include CURSES_LOC main() {} EOF diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streaml= ine_config.pl index bccf07dd..3346f42 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -463,6 +463,8 @@ while() { if (defined($configs{$1})) { if ($localyesconfig) { $setconfigs{$1} =3D 'y'; + print "$1=3Dy\n"; + next; } else { $setconfigs{$1} =3D $2; } diff --git a/scripts/package/buildtar b/scripts/package/buildtar index 8a7b155..d0d748e 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -109,7 +109,7 @@ esac if tar --owner=3Droot --group=3Droot --help >/dev/null 2>&1; then opts=3D"--owner=3Droot --group=3Droot" fi - tar cf - . $opts | ${compress} > "${tarball}${file_ext}" + tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}" ) =20 echo "Tarball successfully created in ${tarball}${file_ext}" diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index d83bafc..193ce81 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -119,6 +119,7 @@ struct loopback_pcm { unsigned int period_size_frac; unsigned long last_jiffies; struct timer_list timer; + spinlock_t timer_lock; }; =20 static struct platform_device *devices[SNDRV_CARDS]; @@ -169,6 +170,7 @@ static void loopback_timer_start(struct loopback_pcm *d= pcm) unsigned long tick; unsigned int rate_shift =3D get_rate_shift(dpcm); =20 + spin_lock(&dpcm->timer_lock); if (rate_shift !=3D dpcm->pcm_rate_shift) { dpcm->pcm_rate_shift =3D rate_shift; dpcm->period_size_frac =3D frac_pos(dpcm, dpcm->pcm_period_size); @@ -181,12 +183,15 @@ static void loopback_timer_start(struct loopback_pcm = *dpcm) tick =3D (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; dpcm->timer.expires =3D jiffies + tick; add_timer(&dpcm->timer); + spin_unlock(&dpcm->timer_lock); } =20 static inline void loopback_timer_stop(struct loopback_pcm *dpcm) { + spin_lock(&dpcm->timer_lock); del_timer(&dpcm->timer); dpcm->timer.expires =3D 0; + spin_unlock(&dpcm->timer_lock); } =20 #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) @@ -659,6 +664,7 @@ static int loopback_open(struct snd_pcm_substream *subs= tream) dpcm->substream =3D substream; setup_timer(&dpcm->timer, loopback_timer_function, (unsigned long)dpcm); + spin_lock_init(&dpcm->timer_lock); =20 cable =3D loopback->cables[substream->number][dev]; if (!cable) { diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.= c index 402f330..94f0c4a 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -139,6 +139,7 @@ struct conexant_spec { unsigned int asus:1; unsigned int pin_eapd_ctrls:1; unsigned int single_adc_amp:1; + unsigned int fixup_stereo_dmic:1; =20 unsigned int adc_switching:1; =20 @@ -4113,9 +4114,9 @@ static int cx_auto_init(struct hda_codec *codec) =20 static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *bas= ename, const char *dir, int cidx, - hda_nid_t nid, int hda_dir, int amp_idx) + hda_nid_t nid, int hda_dir, int amp_idx, int chs) { - static char name[32]; + static char name[44]; static struct snd_kcontrol_new knew[] =3D { HDA_CODEC_VOLUME(name, 0, 0, 0), HDA_CODEC_MUTE(name, 0, 0, 0), @@ -4125,7 +4126,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *c= odec, const char *basename, =20 for (i =3D 0; i < 2; i++) { struct snd_kcontrol *kctl; - knew[i].private_value =3D HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx, + knew[i].private_value =3D HDA_COMPOSE_AMP_VAL(nid, chs, amp_idx, hda_dir); knew[i].subdevice =3D HDA_SUBDEV_AMP_FLAG; knew[i].index =3D cidx; @@ -4144,7 +4145,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *c= odec, const char *basename, } =20 #define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \ - cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0) + cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0, 3) =20 #define cx_auto_add_pb_volume(codec, nid, str, idx) \ cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) @@ -4214,6 +4215,36 @@ static int cx_auto_build_output_controls(struct hda_= codec *codec) return 0; } =20 +/* Returns zero if this is a normal stereo channel, and non-zero if it sho= uld + be split in two independent channels. + dest_label must be at least 44 characters. */ +static int cx_auto_get_rightch_label(struct hda_codec *codec, const char *= label, + char *dest_label, int nid) +{ + struct conexant_spec *spec =3D codec->spec; + int i; + + if (!spec->fixup_stereo_dmic) + return 0; + + for (i =3D 0; i < AUTO_CFG_MAX_INS; i++) { + int def_conf; + if (spec->autocfg.inputs[i].pin !=3D nid) + continue; + + if (spec->autocfg.inputs[i].type !=3D AUTO_PIN_MIC) + return 0; + def_conf =3D snd_hda_codec_get_pincfg(codec, nid); + if (snd_hda_get_input_pin_attr(def_conf) !=3D INPUT_PIN_ATTR_INT) + return 0; + + /* Finally found the inverted internal mic! */ + snprintf(dest_label, 44, "Inverted %s", label); + return 1; + } + return 0; +} + static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t n= id, const char *label, const char *pfx, int cidx) @@ -4222,14 +4253,25 @@ static int cx_auto_add_capture_volume(struct hda_co= dec *codec, hda_nid_t nid, int i; =20 for (i =3D 0; i < spec->num_adc_nids; i++) { + char rightch_label[44]; hda_nid_t adc_nid =3D spec->adc_nids[i]; int idx =3D get_input_connection(codec, adc_nid, nid); if (idx < 0) continue; if (spec->single_adc_amp) idx =3D 0; + + if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) { + /* Make two independent kcontrols for left and right */ + int err =3D cx_auto_add_volume_idx(codec, label, pfx, + cidx, adc_nid, HDA_INPUT, idx, 1); + if (err < 0) + return err; + return cx_auto_add_volume_idx(codec, rightch_label, pfx, + cidx, adc_nid, HDA_INPUT, idx, 2); + } return cx_auto_add_volume_idx(codec, label, pfx, - cidx, adc_nid, HDA_INPUT, idx); + cidx, adc_nid, HDA_INPUT, idx, 3); } return 0; } @@ -4242,9 +4284,19 @@ static int cx_auto_add_boost_volume(struct hda_codec= *codec, int idx, int i, con; =20 nid =3D spec->imux_info[idx].pin; - if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) + if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { + char rightch_label[44]; + if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) { + int err =3D cx_auto_add_volume_idx(codec, label, " Boost", + cidx, nid, HDA_INPUT, 0, 1); + if (err < 0) + return err; + return cx_auto_add_volume_idx(codec, rightch_label, " Boost", + cidx, nid, HDA_INPUT, 0, 2); + } return cx_auto_add_volume(codec, label, " Boost", cidx, nid, HDA_INPUT); + } con =3D __select_input_connection(codec, spec->imux_info[idx].adc, nid, &mux, false, 0); if (con < 0) @@ -4398,23 +4450,31 @@ static void apply_pincfg(struct hda_codec *codec, c= onst struct cxt_pincfg *cfg) =20 } =20 -static void apply_pin_fixup(struct hda_codec *codec, +enum { + CXT_PINCFG_LENOVO_X200, + CXT_PINCFG_LENOVO_TP410, + CXT_FIXUP_STEREO_DMIC, +}; + +static void apply_fixup(struct hda_codec *codec, const struct snd_pci_quirk *quirk, const struct cxt_pincfg **table) { + struct conexant_spec *spec =3D codec->spec; + quirk =3D snd_pci_quirk_lookup(codec->bus->pci, quirk); - if (quirk) { + if (quirk && table[quirk->value]) { snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n", quirk->name); apply_pincfg(codec, table[quirk->value]); } + if (quirk->value =3D=3D CXT_FIXUP_STEREO_DMIC) { + snd_printdd(KERN_INFO "hda_codec: applying internal mic workaround for %= s\n", + quirk->name); + spec->fixup_stereo_dmic =3D 1; + } } =20 -enum { - CXT_PINCFG_LENOVO_X200, - CXT_PINCFG_LENOVO_TP410, -}; - /* ThinkPad X200 & co with cxt5051 */ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] =3D { { 0x16, 0x042140ff }, /* HP (seq# overridden) */ @@ -4434,6 +4494,7 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_tp41= 0[] =3D { static const struct cxt_pincfg *cxt_pincfg_tbl[] =3D { [CXT_PINCFG_LENOVO_X200] =3D cxt_pincfg_lenovo_x200, [CXT_PINCFG_LENOVO_TP410] =3D cxt_pincfg_lenovo_tp410, + [CXT_FIXUP_STEREO_DMIC] =3D NULL, }; =20 static const struct snd_pci_quirk cxt5051_fixups[] =3D { @@ -4447,6 +4508,9 @@ static const struct snd_pci_quirk cxt5066_fixups[] = =3D { SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMI= C), + SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), {} }; =20 @@ -4486,10 +4550,10 @@ static int patch_conexant_auto(struct hda_codec *co= dec) break; case 0x14f15051: add_cx5051_fake_mutes(codec); - apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); + apply_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); break; default: - apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); + apply_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); break; } =20 diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 323d4d9..0961d88 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -348,7 +348,7 @@ int main(void) fd =3D socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); - exit(-1); + exit(EXIT_FAILURE); } addr.nl_family =3D AF_NETLINK; addr.nl_pad =3D 0; @@ -360,7 +360,7 @@ int main(void) if (error < 0) { syslog(LOG_ERR, "bind failed; error:%d", error); close(fd); - exit(-1); + exit(EXIT_FAILURE); } sock_opt =3D addr.nl_groups; setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); @@ -378,7 +378,7 @@ int main(void) if (len < 0) { syslog(LOG_ERR, "netlink_send failed; error:%d", len); close(fd); - exit(-1); + exit(EXIT_FAILURE); } =20 pfd.fd =3D fd; @@ -497,7 +497,7 @@ int main(void) len =3D netlink_send(fd, incoming_cn_msg); if (len < 0) { syslog(LOG_ERR, "net_link send failed; error:%d", len); - exit(-1); + exit(EXIT_FAILURE); } } =20 diff --git a/tools/perf/Makefile b/tools/perf/Makefile index b98e307..e45d2b1 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -56,7 +56,7 @@ ifeq ($(ARCH),x86_64) ARCH :=3D x86 IS_X86_64 :=3D 0 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) - IS_X86_64 :=3D $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + IS_X86_64 :=3D $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) endif ifeq (${IS_X86_64}, 1) RAW_ARCH :=3D x86_64 diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index e8a03ac..7db8da5 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -100,7 +100,7 @@ GMO_FILES =3D ${shell for HLANG in ${LANGUAGES}; do ech= o po/$$HLANG.gmo; done;} export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS =20 # check if compiler option is supported -cc-supports =3D ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev= /null 2>&1; then echo "$(1)"; fi;} +cc-supports =3D ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /de= v/null 2>&1; then echo "$(1)"; fi;} =20 # use '-Os' optimization if available, else use -O2 OPTIMIZATION :=3D $(call cc-supports,-Os,-O2) --=-UP35LHFiwNqpaaZIDlSp Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIVAwUAUHrzA+e/yOyVhhEJAQqIeQ//XHfyYzbwa+Inz3NogvLXYSik9CefwzRM 4emxuBcJ4A3ewHTdQUuj9rk87uAn/RHRvncfup5SfL9AGbqm2XAItIuw/7A1zoYC RT4L9soiD9mR/tGIGcUm59OfRIA/Wdl79F5R4hqCG944iq7DeW7qwzjP5Qh6VDor c3VHiJl4FRO1WijaUR9Bv1zbQyqY8ucU4dLEWLZq7qTZFZIHn+y0S8BXchH9dd4e DSRk4uyFO6tOLYlRIxJHIBPxdRv3NwoCEzvNyzi8iREElaxV9YTl4NrkQMMaPFc3 dFn0/C/xKb9IZZOhyUC4HxZNA2HK8rR/2VZBlwDfLTmszMIaD/xZbHv45IihCVR0 t9IOqf0fHA28WjGYslu7TZXv0LzJ06gE7n0nvHOAlbjTuHe0CcLq/DsybtQefPmb 9/e3jp7FyO8SIsvTx6VWMqpqeIFXTPqp1rrGP5a1EgZhlfdTHKc2mhhe4FhEjIie yGm2ay5z1YsOK6U1Eh86IFyvs/F8SHfqukGNUy2COVSrWcp1yTyxh+6EAnxILtfU rppJMhG8iZtDdTU/BVx+RS7eIvBRiArWhzRpIPeXa5IU+N+Kd9S8ojDypG/L2AtI kqsgwfHEUygLT3381BxhKgXJMgVJXRUQdQLd7Sfv1mm6PjJGelNjvHcK3M+nN2cL NjT/nLOtfns= =/LKT -----END PGP SIGNATURE----- --=-UP35LHFiwNqpaaZIDlSp-- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/