]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Dec 2010 01:32:56 +0000 (17:32 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Dec 2010 01:32:56 +0000 (17:32 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6:
  [SCSI] hpsa: fix redefinition of PCI_DEVICE_ID_CISSF
  [SCSI] qla2xxx: Update version number to 8.03.05-k0.
  [SCSI] qla2xxx: Properly set the return value in qla2xxx_eh_abort function.
  [SCSI] qla2xxx: Correct issue where NPIV-config data was not being allocated for 82xx parts.
  [SCSI] qla2xxx: Change MSI initialization from using incorrect request_irq parameter.
  [SCSI] qla2xxx: Populate Command Type 6 LUN field properly.
  [SCSI] zfcp: Issue FCP command without holding SCSI host_lock
  [SCSI] zfcp: Prevent usage w/o holding a reference
  [SCSI] zfcp: No ERP escalation on gpn_ft eval
  [SCSI] zfcp: Correct false abort data assignment.
  [SCSI] zfcp: Fix common FCP request reception
  [SCSI] Eliminate error handler overload of the SCSI serial number
  [SCSI] pmcraid: disable msix and expand device config entry
  [SCSI] bsg: correct fault if queue object removed while dev_t open
  [SCSI] osd: checking NULL instead of ERR_PTR()

99 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
drivers/acpi/ac.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/hest.c
drivers/acpi/battery.c
drivers/acpi/ec.c
drivers/acpi/osl.c
drivers/acpi/power.c
drivers/acpi/processor_thermal.c
drivers/acpi/sleep.c
drivers/dma/Makefile
drivers/dma/at_hdmac.c
drivers/dma/fsldma.c
drivers/dma/fsldma.h
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/intel_mid_dma.c
drivers/dma/ioat/Makefile
drivers/dma/pch_dma.c
drivers/dma/ppc4xx/adma.c
drivers/edac/amd64_edac.c
drivers/edac/edac_core.h
drivers/edac/edac_mc.c
drivers/firewire/ohci.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/radeon/r600.c
drivers/hwmon/adm1026.c
drivers/hwmon/it87.c
drivers/hwmon/ltc4215.c
drivers/idle/intel_idle.c
drivers/infiniband/core/uverbs_cmd.c
drivers/pnp/pnpacpi/core.c
drivers/regulator/tps6586x-regulator.c
drivers/serial/kgdboc.c
drivers/video/modedb.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ioctl.h
fs/btrfs/orphan.c
fs/btrfs/super.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ceph/dir.c
fs/ceph/ioctl.h
fs/ceph/locks.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/cifs/Makefile
fs/cifs/README
fs/cifs/cifs_fs_sb.h
fs/cifs/cifsacl.c
fs/cifs/cifsacl.h
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/fuse/file.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/mount_clnt.c
fs/nfs/nfs4proc.c
fs/nfs/pagelist.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfs3xdr.c
fs/nfsd/xdr4.h
fs/xfs/xfs_rename.c
include/acpi/video.h
include/linux/acpi.h
include/linux/fs.h
include/linux/mfd/wm8994/pdata.h
include/linux/nfs_fs.h
include/linux/nfs_page.h
include/linux/video_output.h
mm/filemap.c
mm/truncate.c
mm/vmscan.c
net/sunrpc/svc_xprt.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm_hubs.c
sound/soc/soc-core.c

index a91f30890011ddf69ba9b859484966c943db7fb5..b6426f15b4ae85f5469b962806004237b9b5607e 100644 (file)
@@ -173,12 +173,13 @@ prototypes:
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*launder_page) (struct page *);
 
 locking rules:
-       All except set_page_dirty may block
+       All except set_page_dirty and freepage may block
 
                        BKL     PageLocked(page)        i_mutex
 writepage:             no      yes, unlocks (see below)
@@ -193,6 +194,7 @@ perform_write:              no      n/a                     yes
 bmap:                  no
 invalidatepage:                no      yes
 releasepage:           no      yes
+freepage:              no      yes
 direct_IO:             no
 launder_page:          no      yes
 
@@ -288,6 +290,9 @@ buffers from the page in preparation for freeing it.  It returns zero to
 indicate that the buffers are (or may be) freeable.  If ->releasepage is zero,
 the kernel assumes that the fs has no private interest in the buffers.
 
+       ->freepage() is called when the kernel is done dropping the page
+from the page cache.
+
        ->launder_page() may be called prior to releasing a page if
 it is still found to be dirty. It returns zero if the page was successfully
 cleaned, or an error value if not. Note that in order to prevent the page
index 55c28b79d8dce3afcb239f45cc1cc62c44685d3c..20899e095e7e6879580b53aa9aa0282fb4b5ce63 100644 (file)
@@ -534,6 +534,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        int (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, int);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        struct page* (*get_xip_page)(struct address_space *, sector_t,
@@ -678,6 +679,12 @@ struct address_space_operations {
         need to ensure this.  Possibly it can clear the PageUptodate
         bit if it cannot free private data yet.
 
+  freepage: freepage is called once the page is no longer visible in
+        the page cache in order to allow the cleanup of any private
+       data. Since it may be called by the memory reclaimer, it
+       should not assume that the original address_space mapping still
+       exists, and it should not block.
+
   direct_IO: called by the generic read/write routines to perform
         direct_IO - that is IO requests which bypass the page cache
         and transfer data directly between the storage and the
index ba9afeaa23acfb676021c86432fd89b45f8ba5cf..25d3aaebc10d4d86238c0af67bcb01976b6dcd65 100644 (file)
@@ -100,24 +100,7 @@ static const struct file_operations acpi_ac_fops = {
        .release = single_release,
 };
 #endif
-static int get_ac_property(struct power_supply *psy,
-                          enum power_supply_property psp,
-                          union power_supply_propval *val)
-{
-       struct acpi_ac *ac = to_acpi_ac(psy);
-       switch (psp) {
-       case POWER_SUPPLY_PROP_ONLINE:
-               val->intval = ac->state;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
 
-static enum power_supply_property ac_props[] = {
-       POWER_SUPPLY_PROP_ONLINE,
-};
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
@@ -140,6 +123,35 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
        return 0;
 }
 
+/* --------------------------------------------------------------------------
+                            sysfs I/F
+   -------------------------------------------------------------------------- */
+static int get_ac_property(struct power_supply *psy,
+                          enum power_supply_property psp,
+                          union power_supply_propval *val)
+{
+       struct acpi_ac *ac = to_acpi_ac(psy);
+
+       if (!ac)
+               return -ENODEV;
+
+       if (acpi_ac_get_state(ac))
+               return -ENODEV;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = ac->state;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static enum power_supply_property ac_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
 #ifdef CONFIG_ACPI_PROCFS_POWER
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
index 1211c03149e8c7c258fee89dd1109e1e6b901c26..5850d320404c35b9c7318eb0619ae54c7e32a30b 100644 (file)
@@ -86,7 +86,7 @@ static struct erst_erange {
  * It is used to provide exclusive accessing for ERST Error Log
  * Address Range too.
  */
-static DEFINE_SPINLOCK(erst_lock);
+static DEFINE_RAW_SPINLOCK(erst_lock);
 
 static inline int erst_errno(int command_status)
 {
@@ -421,9 +421,9 @@ ssize_t erst_get_record_count(void)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        count = __erst_get_record_count();
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return count;
 }
@@ -456,9 +456,9 @@ int erst_get_next_record_id(u64 *record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -624,17 +624,17 @@ int erst_write(const struct cper_record_header *record)
                return -EINVAL;
 
        if (erst_erange.attr & ERST_RANGE_NVRAM) {
-               if (!spin_trylock_irqsave(&erst_lock, flags))
+               if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                        return -EBUSY;
                rc = __erst_write_to_nvram(record);
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
 
        if (record->record_length > erst_erange.size)
                return -EINVAL;
 
-       if (!spin_trylock_irqsave(&erst_lock, flags))
+       if (!raw_spin_trylock_irqsave(&erst_lock, flags))
                return -EBUSY;
        memcpy(erst_erange.vaddr, record, record->record_length);
        rcd_erange = erst_erange.vaddr;
@@ -642,7 +642,7 @@ int erst_write(const struct cper_record_header *record)
        memcpy(&rcd_erange->persistence_information, "ER", 2);
 
        rc = __erst_write_to_storage(0);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
@@ -696,9 +696,9 @@ ssize_t erst_read(u64 record_id, struct cper_record_header *record,
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
        return len;
 }
 EXPORT_SYMBOL_GPL(erst_read);
@@ -719,20 +719,20 @@ ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        rc = __erst_get_next_record_id(&record_id);
        if (rc) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return rc;
        }
        /* no more record */
        if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-               spin_unlock_irqrestore(&erst_lock, flags);
+               raw_spin_unlock_irqrestore(&erst_lock, flags);
                return 0;
        }
 
        len = __erst_read(record_id, record, buflen);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return len;
 }
@@ -746,12 +746,12 @@ int erst_clear(u64 record_id)
        if (erst_disable)
                return -ENODEV;
 
-       spin_lock_irqsave(&erst_lock, flags);
+       raw_spin_lock_irqsave(&erst_lock, flags);
        if (erst_erange.attr & ERST_RANGE_NVRAM)
                rc = __erst_clear_from_nvram(record_id);
        else
                rc = __erst_clear_from_storage(record_id);
-       spin_unlock_irqrestore(&erst_lock, flags);
+       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        return rc;
 }
index 1a3508a7fe03f157c2e0144727bbeb5c244d2a46..daa7bc63f1d4bad00fd988ddcce3681fdc74f804 100644 (file)
@@ -46,9 +46,9 @@ EXPORT_SYMBOL_GPL(hest_disable);
 
 /* HEST table parsing */
 
-static struct acpi_table_hest *hest_tab;
+static struct acpi_table_hest *__read_mostly hest_tab;
 
-static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
+static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
        [ACPI_HEST_TYPE_IA32_CHECK] = -1,       /* need further calculation */
        [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1,
        [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi),
@@ -126,7 +126,7 @@ struct ghes_arr {
        unsigned int count;
 };
 
-static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
 {
        int *count = data;
 
@@ -135,7 +135,7 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
        return 0;
 }
 
-static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
+static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
 {
        struct platform_device *ghes_dev;
        struct ghes_arr *ghes_arr = data;
@@ -165,7 +165,7 @@ err:
        return rc;
 }
 
-static int hest_ghes_dev_register(unsigned int ghes_count)
+static int __init hest_ghes_dev_register(unsigned int ghes_count)
 {
        int rc, i;
        struct ghes_arr ghes_arr;
index 95649d373071ac93d14bbbb478db1ab4a8cdb801..9fb9d5ac939db1c071c4cdcaa7fba49364236e25 100644 (file)
@@ -130,6 +130,8 @@ struct acpi_battery {
        unsigned long flags;
 };
 
+static int acpi_battery_update(struct acpi_battery *battery);
+
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -184,6 +186,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
        int ret = 0;
        struct acpi_battery *battery = to_acpi_battery(psy);
 
+       if (acpi_battery_update(battery))
+               return -ENODEV;
+
        if (acpi_battery_present(battery)) {
                /* run battery update only if it is present */
                acpi_battery_get_state(battery);
index 372ff80b7b0c93f88f6f2ea9e100c0fdd2aaf6bf..302b31ed31f1ea099faa48b989114e9c99dc1485 100644 (file)
@@ -934,6 +934,9 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
        ec_flag_msi, "MSI hardware", {
        DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL},
        {
+       ec_flag_msi, "MSI hardware", {
+       DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR")}, NULL},
+       {
        ec_validate_ecdt, "ASUS hardware", {
        DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
        {},
index 966feddf6b1ba29457fde294223018ad23666e39..055d7b701fff16d18fe5de5ea243ba8ec477e3ec 100644 (file)
@@ -110,9 +110,6 @@ struct acpi_ioremap {
 static LIST_HEAD(acpi_ioremaps);
 static DEFINE_SPINLOCK(acpi_ioremap_lock);
 
-#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
-static char osi_setup_string[OSI_STRING_LENGTH_MAX];
-
 static void __init acpi_osi_setup_late(void);
 
 /*
@@ -152,8 +149,7 @@ static struct osi_linux {
        unsigned int    enable:1;
        unsigned int    dmi:1;
        unsigned int    cmdline:1;
-       unsigned int    known:1;
-} osi_linux = { 0, 0, 0, 0};
+} osi_linux = {0, 0, 0};
 
 static u32 acpi_osi_handler(acpi_string interface, u32 supported)
 {
@@ -1055,13 +1051,53 @@ static int __init acpi_os_name_setup(char *str)
 
 __setup("acpi_os_name=", acpi_os_name_setup);
 
+#define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
+#define        OSI_STRING_ENTRIES_MAX 16       /* arbitrary */
+
+struct osi_setup_entry {
+       char string[OSI_STRING_LENGTH_MAX];
+       bool enable;
+};
+
+static struct osi_setup_entry __initdata osi_setup_entries[OSI_STRING_ENTRIES_MAX];
+
+void __init acpi_osi_setup(char *str)
+{
+       struct osi_setup_entry *osi;
+       bool enable = true;
+       int i;
+
+       if (!acpi_gbl_create_osi_method)
+               return;
+
+       if (str == NULL || *str == '\0') {
+               printk(KERN_INFO PREFIX "_OSI method disabled\n");
+               acpi_gbl_create_osi_method = FALSE;
+               return;
+       }
+
+       if (*str == '!') {
+               str++;
+               enable = false;
+       }
+
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               if (!strcmp(osi->string, str)) {
+                       osi->enable = enable;
+                       break;
+               } else if (osi->string[0] == '\0') {
+                       osi->enable = enable;
+                       strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
+                       break;
+               }
+       }
+}
+
 static void __init set_osi_linux(unsigned int enable)
 {
-       if (osi_linux.enable != enable) {
+       if (osi_linux.enable != enable)
                osi_linux.enable = enable;
-               printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
-                       enable ? "Add": "Delet");
-       }
 
        if (osi_linux.enable)
                acpi_osi_setup("Linux");
@@ -1073,7 +1109,8 @@ static void __init set_osi_linux(unsigned int enable)
 
 static void __init acpi_cmdline_osi_linux(unsigned int enable)
 {
-       osi_linux.cmdline = 1;  /* cmdline set the default */
+       osi_linux.cmdline = 1;  /* cmdline set the default and override DMI */
+       osi_linux.dmi = 0;
        set_osi_linux(enable);
 
        return;
@@ -1081,15 +1118,12 @@ static void __init acpi_cmdline_osi_linux(unsigned int enable)
 
 void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
 {
-       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
-
        printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
 
        if (enable == -1)
                return;
 
-       osi_linux.known = 1;    /* DMI knows which OSI(Linux) default needed */
-
+       osi_linux.dmi = 1;      /* DMI knows that this box asks OSI(Linux) */
        set_osi_linux(enable);
 
        return;
@@ -1104,37 +1138,44 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
  */
 static void __init acpi_osi_setup_late(void)
 {
-       char *str = osi_setup_string;
+       struct osi_setup_entry *osi;
+       char *str;
+       int i;
+       acpi_status status;
 
-       if (*str == '\0')
-               return;
+       for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+               osi = &osi_setup_entries[i];
+               str = osi->string;
 
-       if (!strcmp("!Linux", str)) {
-               acpi_cmdline_osi_linux(0);      /* !enable */
-       } else if (*str == '!') {
-               if (acpi_remove_interface(++str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
-       } else if (!strcmp("Linux", str)) {
-               acpi_cmdline_osi_linux(1);      /* enable */
-       } else {
-               if (acpi_install_interface(str) == AE_OK)
-                       printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               if (*str == '\0')
+                       break;
+               if (osi->enable) {
+                       status = acpi_install_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+               } else {
+                       status = acpi_remove_interface(str);
+
+                       if (ACPI_SUCCESS(status))
+                               printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
+               }
        }
 }
 
-int __init acpi_osi_setup(char *str)
+static int __init osi_setup(char *str)
 {
-       if (str == NULL || *str == '\0') {
-               printk(KERN_INFO PREFIX "_OSI method disabled\n");
-               acpi_gbl_create_osi_method = FALSE;
-       } else {
-               strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
-       }
+       if (str && !strcmp("Linux", str))
+               acpi_cmdline_osi_linux(1);
+       else if (str && !strcmp("!Linux", str))
+               acpi_cmdline_osi_linux(0);
+       else
+               acpi_osi_setup(str);
 
        return 1;
 }
 
-__setup("acpi_osi=", acpi_osi_setup);
+__setup("acpi_osi=", osi_setup);
 
 /* enable serialization to combat AE_ALREADY_EXISTS errors */
 static int __init acpi_serialize_setup(char *str)
@@ -1530,7 +1571,7 @@ acpi_status __init acpi_os_initialize(void)
        return AE_OK;
 }
 
-acpi_status acpi_os_initialize1(void)
+acpi_status __init acpi_os_initialize1(void)
 {
        kacpid_wq = create_workqueue("kacpid");
        kacpi_notify_wq = create_workqueue("kacpi_notify");
index 67dedeed144cf82c8e13859e7222b976d0eebb2e..4c9c2fb5d98f9a14a67e8618b44dc6f2c642887b 100644 (file)
@@ -213,11 +213,13 @@ static int acpi_power_on(acpi_handle handle)
                                  resource->name));
        } else {
                result = __acpi_power_on(resource);
+               if (result)
+                       resource->ref_count--;
        }
 
        mutex_unlock(&resource->resource_lock);
 
-       return 0;
+       return result;
 }
 
 static int acpi_power_off_device(acpi_handle handle)
@@ -465,10 +467,12 @@ int acpi_power_transition(struct acpi_device *device, int state)
        struct acpi_handle_list *tl = NULL;     /* Target Resources */
        int i = 0;
 
-
        if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
                return -EINVAL;
 
+       if (device->power.state == state)
+               return 0;
+
        if ((device->power.state < ACPI_STATE_D0)
            || (device->power.state > ACPI_STATE_D3))
                return -ENODEV;
@@ -488,10 +492,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
                        goto end;
        }
 
-       if (device->power.state == state) {
-               goto end;
-       }
-
        /*
         * Then we dereference all power resources used in the current list.
         */
index fde49b9b1d99ed04eaf4192473ff7ce3bb913fd6..79cb6533289456c4f43b92dda5d7059a27345afa 100644 (file)
@@ -156,15 +156,6 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
        return 0;
 }
 
-static int acpi_thermal_cpufreq_increase(unsigned int cpu)
-{
-       return -ENODEV;
-}
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
-{
-       return -ENODEV;
-}
-
 #endif
 
 int acpi_processor_get_limit_info(struct acpi_processor *pr)
index 721d93b3ceee78c3b271f5f84ffe4fc795e435e1..febb153b5a68cf216fdd1b528ac44159e73abcba 100644 (file)
@@ -27,8 +27,6 @@
 
 static u8 sleep_states[ACPI_S_STATE_COUNT];
 
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
        union acpi_object in_arg = { ACPI_TYPE_INTEGER };
@@ -81,6 +79,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
 }
 
 #ifdef CONFIG_ACPI_SLEEP
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
 /*
  * The ACPI specification wants us to save NVS memory regions during hibernation
  * and to restore them during the subsequent resume.  Windows does that also for
@@ -427,6 +427,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
                },
        },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-NW130D",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
index a8a84f4587f20d7437af9ce12932dbf8e92a4e1b..64b21f5cd740fc5dfa1d5f09b1a944ed1f661440 100644 (file)
@@ -1,8 +1,8 @@
 ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
-       EXTRA_CFLAGS    += -DDEBUG
+       ccflags-y       += -DDEBUG
 endif
 ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
-       EXTRA_CFLAGS    += -DVERBOSE_DEBUG
+       ccflags-y       += -DVERBOSE_DEBUG
 endif
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
index a0f3e6a06e06532b3701ade73b110d823eec591f..ea0ee81cff53e266643140eb752ef3ba26289c6a 100644 (file)
@@ -722,7 +722,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        desc->lli.daddr = mem;
                        desc->lli.ctrla = ctrla
                                        | ATC_DST_WIDTH(mem_width)
-                                       | len >> mem_width;
+                                       | len >> reg_width;
                        desc->lli.ctrlb = ctrlb;
 
                        if (!first) {
index 286c3ac6bdcc236d020229ce0397ee9e78e07100..e5e172d21692d60a81fce6a9ed06e5807c57b370 100644 (file)
@@ -50,9 +50,11 @@ static void dma_init(struct fsldma_chan *chan)
                 * EIE - Error interrupt enable
                 * EOSIE - End of segments interrupt enable (basic mode)
                 * EOLNIE - End of links interrupt enable
+                * BWC - Bandwidth sharing among channels
                 */
-               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EIE
-                               | FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
+               DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+                               | FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
+                               | FSL_DMA_MR_EOSIE, 32);
                break;
        case FSL_DMA_IP_83XX:
                /* Set the channel to below modes:
index cb4d6ff5159766baf7dce594dca6fb57e3d28dd2..ba9f403c0fbe9127441e7b92bf70c59c71cbde28 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2007-2010 Freescale Semiconductor, Inc. All rights reserved.
  *
  * Author:
  *   Zhang Wei <wei.zhang@freescale.com>, Jul 2007
 #define FSL_DMA_MR_DAHE                0x00002000
 #define FSL_DMA_MR_SAHE                0x00001000
 
+/*
+ * Bandwidth/pause control determines how many bytes a given
+ * channel is allowed to transfer before the DMA engine pauses
+ * the current channel and switches to the next channel
+ */
+#define FSL_DMA_MR_BWC         0x08000000
+
 /* Special MR definition for MPC8349 */
 #define FSL_DMA_MR_EOTIE       0x00000080
 #define FSL_DMA_MR_PRC_RM      0x00000800
index f629e4961af593f0ab5d3697fce77b306ab1ed9b..e53d438142bb8747cb8f288e64d75b0ba2e18a97 100644 (file)
@@ -379,7 +379,7 @@ static int __init imxdma_probe(struct platform_device *pdev)
        return 0;
 
 err_init:
-       while (i-- >= 0) {
+       while (--i >= 0) {
                struct imxdma_channel *imxdmac = &imxdma->channel[i];
                imx_dma_free(imxdmac->imxdma_channel);
        }
index 0834323a0599595b5a7fa8db1224a85125305031..d0602dd5d1b238eedf2500cd240ef0dc092800a8 100644 (file)
@@ -951,7 +951,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
                struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
                int param;
 
-               bd->buffer_addr = sgl->dma_address;
+               bd->buffer_addr = sg->dma_address;
 
                count = sg->length;
 
@@ -1385,7 +1385,7 @@ static int __init sdma_module_init(void)
 {
        return platform_driver_probe(&sdma_driver, sdma_probe);
 }
-subsys_initcall(sdma_module_init);
+module_init(sdma_module_init);
 
 MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX SDMA driver");
index 338bc4eed1f3f55b4de66c623a135289862c783f..3109bd94bc4f403c5aba44e8ff7cb092aa23b4cd 100644 (file)
@@ -1075,7 +1075,6 @@ static int mid_setup_dma(struct pci_dev *pdev)
        if (NULL == dma->dma_pool) {
                pr_err("ERR_MDMA:pci_pool_create failed\n");
                err = -ENOMEM;
-               kfree(dma);
                goto err_dma_pool;
        }
 
@@ -1186,7 +1185,6 @@ err_engine:
        free_irq(pdev->irq, dma);
 err_irq:
        pci_pool_destroy(dma->dma_pool);
-       kfree(dma);
 err_dma_pool:
        pr_err("ERR_MDMA:setup_dma failed: %d\n", err);
        return err;
@@ -1413,7 +1411,7 @@ static const struct dev_pm_ops intel_mid_dma_pm = {
        .runtime_idle = dma_runtime_idle,
 };
 
-static struct pci_driver intel_mid_dma_pci = {
+static struct pci_driver intel_mid_dma_pci_driver = {
        .name           =       "Intel MID DMA",
        .id_table       =       intel_mid_dma_ids,
        .probe          =       intel_mid_dma_probe,
@@ -1431,13 +1429,13 @@ static int __init intel_mid_dma_init(void)
 {
        pr_debug("INFO_MDMA: LNW DMA Driver Version %s\n",
                        INTEL_MID_DMA_DRIVER_VERSION);
-       return pci_register_driver(&intel_mid_dma_pci);
+       return pci_register_driver(&intel_mid_dma_pci_driver);
 }
 fs_initcall(intel_mid_dma_init);
 
 static void __exit intel_mid_dma_exit(void)
 {
-       pci_unregister_driver(&intel_mid_dma_pci);
+       pci_unregister_driver(&intel_mid_dma_pci_driver);
 }
 module_exit(intel_mid_dma_exit);
 
index 8997d3fb9051db0020bbeb721cc5a562d780bf47..0ff7270af25b97800d64fcc6f62c350f3115f322 100644 (file)
@@ -1,2 +1,2 @@
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
-ioatdma-objs := pci.o dma.o dma_v2.o dma_v3.o dca.o
+ioatdma-y := pci.o dma.o dma_v2.o dma_v3.o dca.o
index 92b679024fedd9e033e9cbae311f7f8d7f221142..c064c89420d06080a737ea48356501aeeae869cd 100644 (file)
@@ -259,11 +259,6 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
                return;
        }
 
-       channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
-       channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
-       channel_writel(pd_chan, SIZE, desc->regs.size);
-       channel_writel(pd_chan, NEXT, desc->regs.next);
-
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> dev_addr: %x\n",
                pd_chan->chan.chan_id, desc->regs.dev_addr);
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> mem_addr: %x\n",
@@ -273,10 +268,16 @@ static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc)
        dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> next: %x\n",
                pd_chan->chan.chan_id, desc->regs.next);
 
-       if (list_empty(&desc->tx_list))
+       if (list_empty(&desc->tx_list)) {
+               channel_writel(pd_chan, DEV_ADDR, desc->regs.dev_addr);
+               channel_writel(pd_chan, MEM_ADDR, desc->regs.mem_addr);
+               channel_writel(pd_chan, SIZE, desc->regs.size);
+               channel_writel(pd_chan, NEXT, desc->regs.next);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_ONESHOT);
-       else
+       } else {
+               channel_writel(pd_chan, NEXT, desc->txd.phys);
                pdc_set_mode(&pd_chan->chan, DMA_CTL0_SG);
+       }
 
        val = dma_readl(pd, CTL2);
        val |= 1 << (DMA_CTL2_START_SHIFT_BITS + pd_chan->chan.chan_id);
index 0d58a4a4487fbbaefc167182a627c6b0b0f222b3..cef584533ee8a9ca5628b874b5d6c644a4ad05f4 100644 (file)
@@ -4449,9 +4449,8 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev,
 
        if (!request_mem_region(res.start, resource_size(&res),
                                dev_driver_string(&ofdev->dev))) {
-               dev_err(&ofdev->dev, "failed to request memory region "
-                       "(0x%016llx-0x%016llx)\n",
-                       (u64)res.start, (u64)res.end);
+               dev_err(&ofdev->dev, "failed to request memory region %pR\n",
+                       &res);
                initcode = PPC_ADMA_INIT_MEMREG;
                ret = -EBUSY;
                goto out;
index 8521401bbd751406e6f2752e10868f63c7e3b48a..eca9ba193e94a914aa64740f0b4262b8f7c99b81 100644 (file)
@@ -1572,7 +1572,7 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
        debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
                        hole_off, hole_valid, intlv_sel);
 
-       if (intlv_en ||
+       if (intlv_en &&
            (intlv_sel != ((sys_addr >> 12) & intlv_en)))
                return -EINVAL;
 
index d7ca43a828bd3fe57b3de1341d7e75d1bed84f0a..251440cd50a3b41ea47f4511365909b707ebf0e8 100644 (file)
 #define MC_PROC_NAME_MAX_LEN   7
 
 #if PAGE_SHIFT < 20
-#define PAGES_TO_MiB( pages )  ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
-#define MiB_TO_PAGES(mb)       ((mb) >> (20 - PAGE_SHIFT))
+#define PAGES_TO_MiB(pages)    ((pages) >> (20 - PAGE_SHIFT))
+#define MiB_TO_PAGES(mb)       ((mb) << (20 - PAGE_SHIFT))
 #else                          /* PAGE_SHIFT > 20 */
-#define PAGES_TO_MiB( pages )  ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#define PAGES_TO_MiB(pages)    ((pages) << (PAGE_SHIFT - 20))
 #define MiB_TO_PAGES(mb)       ((mb) >> (PAGE_SHIFT - 20))
 #endif
 
index ba6586a69ccce3b000fb22ee21512ab4673b44ac..795ea69c4d8f5fb6149c62fba8e085bd83363309 100644 (file)
@@ -586,14 +586,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
                return NULL;
        }
 
-       /* marking MCI offline */
-       mci->op_state = OP_OFFLINE;
-
        del_mc_from_global_list(mci);
        mutex_unlock(&mem_ctls_mutex);
 
-       /* flush workq processes and remove sysfs */
+       /* flush workq processes */
        edac_mc_workq_teardown(mci);
+
+       /* marking MCI offline */
+       mci->op_state = OP_OFFLINE;
+
+       /* remove from sysfs */
        edac_remove_sysfs_mci_device(mci);
 
        edac_printk(KERN_INFO, EDAC_MC,
index 84eb607d6c031b4275e834604d4c0c0729fa8502..e3c8b60bd86be8873e781bef053f466898be16c2 100644 (file)
@@ -242,6 +242,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
 
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
+#define PCI_DEVICE_ID_AGERE_FW643      0x5901
 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW        0x2380
 #define PCI_DEVICE_ID_TI_TSB12LV22     0x8009
 
@@ -253,18 +254,34 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
-       unsigned short vendor, device, flags;
+       unsigned short vendor, device, revision, flags;
 } ohci_quirks[] = {
-       {PCI_VENDOR_ID_TI,      PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER |
-                                                           QUIRK_RESET_PACKET |
-                                                           QUIRK_NO_1394A},
-       {PCI_VENDOR_ID_TI,      PCI_ANY_ID,     QUIRK_RESET_PACKET},
-       {PCI_VENDOR_ID_AL,      PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI},
-       {PCI_VENDOR_ID_NEC,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_VIA,     PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_RICOH,   PCI_ANY_ID,     QUIRK_CYCLE_TIMER},
-       {PCI_VENDOR_ID_APPLE,   PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
+       {PCI_VENDOR_ID_AL, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, PCI_ANY_ID,
+               QUIRK_BE_HEADERS},
+
+       {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
+               QUIRK_NO_MSI},
+
+       {PCI_VENDOR_ID_NEC, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER},
+
+       {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
+
+       {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_RESET_PACKET},
+
+       {PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID,
+               QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
 };
 
 /* This overrides anything that was found in ohci_quirks[]. */
@@ -2927,9 +2944,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
        }
 
        for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++)
-               if (ohci_quirks[i].vendor == dev->vendor &&
-                   (ohci_quirks[i].device == dev->device ||
-                    ohci_quirks[i].device == (unsigned short)PCI_ANY_ID)) {
+               if ((ohci_quirks[i].vendor == dev->vendor) &&
+                   (ohci_quirks[i].device == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].device == dev->device) &&
+                   (ohci_quirks[i].revision == (unsigned short)PCI_ANY_ID ||
+                    ohci_quirks[i].revision >= dev->revision)) {
                        ohci->quirks = ohci_quirks[i].flags;
                        break;
                }
index 6985cb1da72cbc232919ab2bb93a52f26304a345..2baa6708e44cd835704ea832c861b7d5fe4b6e33 100644 (file)
@@ -156,12 +156,12 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
        { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
        { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
        { DRM_MODE_CONNECTOR_Component, "Component", 0 },
-       { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 },
-       { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
-       { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
-       { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
+       { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
+       { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
+       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
+       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
        { DRM_MODE_CONNECTOR_TV, "TV", 0 },
-       { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 },
+       { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
 };
 
 static struct drm_prop_enum_list drm_encoder_enum_list[] =
index 722700d5d73ee69a6ac49d4fbd96d307f704c2bb..16d5155edad14fd63dea3b10243a71c6bd3d0ea1 100644 (file)
@@ -628,7 +628,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
        if ((seq - vblwait->request.sequence) <= (1 << 23)) {
                e->event.tv_sec = now.tv_sec;
                e->event.tv_usec = now.tv_usec;
-               drm_vblank_put(dev, e->pipe);
+               drm_vblank_put(dev, pipe);
                list_add_tail(&e->base.link, &e->base.file_priv->event_list);
                wake_up_interruptible(&e->base.file_priv->event_wait);
                trace_drm_vblank_event_delivered(current->pid, pipe,
@@ -645,7 +645,7 @@ err_unlock:
        spin_unlock_irqrestore(&dev->event_lock, flags);
        kfree(e);
 err_put:
-       drm_vblank_put(dev, e->pipe);
+       drm_vblank_put(dev, pipe);
        return ret;
 }
 
index a322d4f647bd2cbe479f6b482f1249ada5de454e..4d7a2e1bdb90e498138eea542e22884c9e36eb0d 100644 (file)
@@ -878,12 +878,15 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
        u32 tmp;
 
        /* flush hdp cache so updates hit vram */
-       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) {
+       if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
+           !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
                u32 tmp;
 
                /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
                 * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+                * This seems to cause problems on some AGP cards. Just use the old
+                * method for them.
                 */
                WREG32(HDP_DEBUG1, 0);
                tmp = readl((void __iomem *)ptr);
@@ -3485,10 +3488,12 @@ int r600_debugfs_mc_info_init(struct radeon_device *rdev)
 void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo)
 {
        /* r7xx hw bug.  write to HDP_DEBUG1 followed by fb read
-        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL
+        * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL.
+        * This seems to cause problems on some AGP cards. Just use the old
+        * method for them.
         */
        if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
-           rdev->vram_scratch.ptr) {
+           rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) {
                void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
                u32 tmp;
 
index 4bf969c0a32b5ee9cb667a4341759e651f58d569..be0fdd58aa29301fbe15f9186580d724ba769544 100644 (file)
@@ -916,27 +916,27 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        int nr = sensor_attr->index;
        struct i2c_client *client = to_i2c_client(dev);
        struct adm1026_data *data = i2c_get_clientdata(client);
-       int val, orig_div, new_div, shift;
+       int val, orig_div, new_div;
 
        val = simple_strtol(buf, NULL, 10);
        new_div = DIV_TO_REG(val);
-       if (new_div == 0) {
-               return -EINVAL;
-       }
+
        mutex_lock(&data->update_lock);
        orig_div = data->fan_div[nr];
        data->fan_div[nr] = DIV_FROM_REG(new_div);
 
        if (nr < 4) { /* 0 <= nr < 4 */
-               shift = 2 * nr;
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << shift))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[0]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[1]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[2]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[3]) << 6));
        } else { /* 3 < nr < 8 */
-               shift = 2 * (nr - 4);
                adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7,
-                       ((DIV_TO_REG(orig_div) & (~(0x03 << (2 * shift)))) |
-                       (new_div << shift)));
+                                   (DIV_TO_REG(data->fan_div[4]) << 0) |
+                                   (DIV_TO_REG(data->fan_div[5]) << 2) |
+                                   (DIV_TO_REG(data->fan_div[6]) << 4) |
+                                   (DIV_TO_REG(data->fan_div[7]) << 6));
        }
 
        if (data->fan_div[nr] != orig_div) {
index 14a5d981be7d07030a264352dbc8d8af1e158c2d..a428a92641954a640dd783f051fc9c5565c13d9b 100644 (file)
@@ -187,6 +187,7 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
 #define IT87_REG_PWM(nr)       (0x15 + (nr))
+#define IT87_REG_PWM_DUTY(nr)  (0x63 + (nr) * 8)
 
 #define IT87_REG_VIN(nr)       (0x20 + (nr))
 #define IT87_REG_TEMP(nr)      (0x29 + (nr))
@@ -251,12 +252,16 @@ struct it87_data {
        u8 fan_main_ctrl;       /* Register value */
        u8 fan_ctl;             /* Register value */
 
-       /* The following 3 arrays correspond to the same registers. The
-        * meaning of bits 6-0 depends on the value of bit 7, and we want
-        * to preserve settings on mode changes, so we have to track all
-        * values separately. */
+       /* The following 3 arrays correspond to the same registers up to
+        * the IT8720F. The meaning of bits 6-0 depends on the value of bit
+        * 7, and we want to preserve settings on mode changes, so we have
+        * to track all values separately.
+        * Starting with the IT8721F, the manual PWM duty cycles are stored
+        * in separate registers (8-bit values), so the separate tracking
+        * is no longer needed, but it is still done to keep the driver
+        * simple. */
        u8 pwm_ctrl[3];         /* Register value */
-       u8 pwm_duty[3];         /* Manual PWM value set by user (bit 6-0) */
+       u8 pwm_duty[3];         /* Manual PWM value set by user */
        u8 pwm_temp_map[3];     /* PWM to temp. chan. mapping (bits 1-0) */
 
        /* Automatic fan speed control registers */
@@ -832,7 +837,9 @@ static ssize_t set_pwm_enable(struct device *dev,
                                 data->fan_main_ctrl);
        } else {
                if (val == 1)                           /* Manual mode */
-                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       data->pwm_ctrl[nr] = data->type == it8721 ?
+                                            data->pwm_temp_map[nr] :
+                                            data->pwm_duty[nr];
                else                                    /* Automatic mode */
                        data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
                it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
@@ -858,12 +865,25 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
-       data->pwm_duty[nr] = pwm_to_reg(data, val);
-       /* If we are in manual mode, write the duty cycle immediately;
-        * otherwise, just store it for later use. */
-       if (!(data->pwm_ctrl[nr] & 0x80)) {
-               data->pwm_ctrl[nr] = data->pwm_duty[nr];
-               it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+       if (data->type == it8721) {
+               /* If we are in automatic mode, the PWM duty cycle register
+                * is read-only so we can't write the value */
+               if (data->pwm_ctrl[nr] & 0x80) {
+                       mutex_unlock(&data->update_lock);
+                       return -EBUSY;
+               }
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               it87_write_value(data, IT87_REG_PWM_DUTY(nr),
+                                data->pwm_duty[nr]);
+       } else {
+               data->pwm_duty[nr] = pwm_to_reg(data, val);
+               /* If we are in manual mode, write the duty cycle immediately;
+                * otherwise, just store it for later use. */
+               if (!(data->pwm_ctrl[nr] & 0x80)) {
+                       data->pwm_ctrl[nr] = data->pwm_duty[nr];
+                       it87_write_value(data, IT87_REG_PWM(nr),
+                                        data->pwm_ctrl[nr]);
+               }
        }
        mutex_unlock(&data->update_lock);
        return count;
@@ -1958,7 +1978,10 @@ static void __devinit it87_init_device(struct platform_device *pdev)
         *   channels to use when later setting to automatic mode later.
         *   Use a 1:1 mapping by default (we are clueless.)
         * In both cases, the value can (and should) be changed by the user
-        * prior to switching to a different mode. */
+        * prior to switching to a different mode.
+        * Note that this is no longer needed for the IT8721F and later, as
+        * these have separate registers for the temperature mapping and the
+        * manual duty cycle. */
        for (i = 0; i < 3; i++) {
                data->pwm_temp_map[i] = i;
                data->pwm_duty[i] = 0x7f;       /* Full speed */
@@ -2034,10 +2057,16 @@ static void __devinit it87_init_device(struct platform_device *pdev)
 static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
 {
        data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
-       if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+       if (data->type == it8721) {
                data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
-       else                            /* Manual mode */
-               data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+               data->pwm_duty[nr] = it87_read_value(data,
+                                                    IT87_REG_PWM_DUTY(nr));
+       } else {
+               if (data->pwm_ctrl[nr] & 0x80)  /* Automatic mode */
+                       data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+               else                            /* Manual mode */
+                       data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+       }
 
        if (has_old_autopwm(data)) {
                int i;
index 00d975eb5b83dcc86ddd8d5f5b6846c9d370f6e6..c7e6d8e81656391e7f7919d5e4c92d08a69b1700 100644 (file)
@@ -205,7 +205,6 @@ LTC4215_ALARM(curr1_max_alarm,      (1 << 2),       LTC4215_STATUS);
 
 /* Power (virtual) */
 LTC4215_POWER(power1_input);
-LTC4215_ALARM(power1_alarm,    (1 << 3),       LTC4215_STATUS);
 
 /* Input Voltage */
 LTC4215_VOLTAGE(in1_input,                     LTC4215_ADIN);
@@ -214,6 +213,7 @@ LTC4215_ALARM(in1_min_alarm,        (1 << 1),       LTC4215_STATUS);
 
 /* Output Voltage */
 LTC4215_VOLTAGE(in2_input,                     LTC4215_SOURCE);
+LTC4215_ALARM(in2_min_alarm,   (1 << 3),       LTC4215_STATUS);
 
 /* Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
@@ -223,13 +223,13 @@ static struct attribute *ltc4215_attributes[] = {
        &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
 
        &sensor_dev_attr_power1_input.dev_attr.attr,
-       &sensor_dev_attr_power1_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in1_input.dev_attr.attr,
        &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
        &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
 
        &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
 
        NULL,
 };
index 41665d2f9f93c1fa585533184468da72039fe7cf..c131d58bcb50d818e05ee0464581bceedfdbf20f 100644 (file)
@@ -273,8 +273,6 @@ static int intel_idle_probe(void)
 
        pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
 
-       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
-               lapic_timer_reliable_states = 0xFFFFFFFF;
 
        if (boot_cpu_data.x86 != 6)     /* family 6 */
                return -ENODEV;
@@ -286,8 +284,6 @@ static int intel_idle_probe(void)
        case 0x1F:      /* Core i7 and i5 Processor - Nehalem */
        case 0x2E:      /* Nehalem-EX Xeon */
        case 0x2F:      /* Westmere-EX Xeon */
-               lapic_timer_reliable_states = (1 << 1);  /* C1 */
-
        case 0x25:      /* Westmere */
        case 0x2C:      /* Westmere */
                cpuidle_state_table = nehalem_cstates;
@@ -295,7 +291,6 @@ static int intel_idle_probe(void)
 
        case 0x1C:      /* 28 - Atom Processor */
        case 0x26:      /* 38 - Lincroft Atom Processor */
-               lapic_timer_reliable_states = (1 << 1); /* C1 */
                cpuidle_state_table = atom_cstates;
                break;
 
@@ -303,10 +298,6 @@ static int intel_idle_probe(void)
        case 0x2D:      /* SNB Xeon */
                cpuidle_state_table = snb_cstates;
                break;
-#ifdef FUTURE_USE
-       case 0x17:      /* 23 - Core 2 Duo */
-               lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
-#endif
 
        default:
                pr_debug(PREFIX "does not run on family %d model %d\n",
@@ -314,6 +305,9 @@ static int intel_idle_probe(void)
                return -ENODEV;
        }
 
+       if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
+               lapic_timer_reliable_states = 0xFFFFFFFF;
+
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
 
index b342248aec059060e19f64ffd69ec28af256682a..c42699285f8eb0d67745c359afadc6e125e7815d 100644 (file)
@@ -893,68 +893,81 @@ out:
        return ret ? ret : in_len;
 }
 
+static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
+{
+       struct ib_uverbs_wc tmp;
+
+       tmp.wr_id               = wc->wr_id;
+       tmp.status              = wc->status;
+       tmp.opcode              = wc->opcode;
+       tmp.vendor_err          = wc->vendor_err;
+       tmp.byte_len            = wc->byte_len;
+       tmp.ex.imm_data         = (__u32 __force) wc->ex.imm_data;
+       tmp.qp_num              = wc->qp->qp_num;
+       tmp.src_qp              = wc->src_qp;
+       tmp.wc_flags            = wc->wc_flags;
+       tmp.pkey_index          = wc->pkey_index;
+       tmp.slid                = wc->slid;
+       tmp.sl                  = wc->sl;
+       tmp.dlid_path_bits      = wc->dlid_path_bits;
+       tmp.port_num            = wc->port_num;
+       tmp.reserved            = 0;
+
+       if (copy_to_user(dest, &tmp, sizeof tmp))
+               return -EFAULT;
+
+       return 0;
+}
+
 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                          const char __user *buf, int in_len,
                          int out_len)
 {
        struct ib_uverbs_poll_cq       cmd;
-       struct ib_uverbs_poll_cq_resp *resp;
+       struct ib_uverbs_poll_cq_resp  resp;
+       u8 __user                     *header_ptr;
+       u8 __user                     *data_ptr;
        struct ib_cq                  *cq;
-       struct ib_wc                  *wc;
-       int                            ret = 0;
-       int                            i;
-       int                            rsize;
+       struct ib_wc                   wc;
+       int                            ret;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
-       if (!wc)
-               return -ENOMEM;
-
-       rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
-       resp = kmalloc(rsize, GFP_KERNEL);
-       if (!resp) {
-               ret = -ENOMEM;
-               goto out_wc;
-       }
-
        cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
-       if (!cq) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!cq)
+               return -EINVAL;
 
-       resp->count = ib_poll_cq(cq, cmd.ne, wc);
+       /* we copy a struct ib_uverbs_poll_cq_resp to user space */
+       header_ptr = (void __user *)(unsigned long) cmd.response;
+       data_ptr = header_ptr + sizeof resp;
 
-       put_cq_read(cq);
+       memset(&resp, 0, sizeof resp);
+       while (resp.count < cmd.ne) {
+               ret = ib_poll_cq(cq, 1, &wc);
+               if (ret < 0)
+                       goto out_put;
+               if (!ret)
+                       break;
+
+               ret = copy_wc_to_user(data_ptr, &wc);
+               if (ret)
+                       goto out_put;
 
-       for (i = 0; i < resp->count; i++) {
-               resp->wc[i].wr_id          = wc[i].wr_id;
-               resp->wc[i].status         = wc[i].status;
-               resp->wc[i].opcode         = wc[i].opcode;
-               resp->wc[i].vendor_err     = wc[i].vendor_err;
-               resp->wc[i].byte_len       = wc[i].byte_len;
-               resp->wc[i].ex.imm_data    = (__u32 __force) wc[i].ex.imm_data;
-               resp->wc[i].qp_num         = wc[i].qp->qp_num;
-               resp->wc[i].src_qp         = wc[i].src_qp;
-               resp->wc[i].wc_flags       = wc[i].wc_flags;
-               resp->wc[i].pkey_index     = wc[i].pkey_index;
-               resp->wc[i].slid           = wc[i].slid;
-               resp->wc[i].sl             = wc[i].sl;
-               resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
-               resp->wc[i].port_num       = wc[i].port_num;
+               data_ptr += sizeof(struct ib_uverbs_wc);
+               ++resp.count;
        }
 
-       if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
+       if (copy_to_user(header_ptr, &resp, sizeof resp)) {
                ret = -EFAULT;
+               goto out_put;
+       }
 
-out:
-       kfree(resp);
+       ret = in_len;
 
-out_wc:
-       kfree(wc);
-       return ret ? ret : in_len;
+out_put:
+       put_cq_read(cq);
+       return ret;
 }
 
 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
index 2d73dfcecdbb4e2098e3d881a6a091a9e8ca5e62..57313f4658bc55a00a5a7d36fbb86450f8144def 100644 (file)
@@ -180,7 +180,7 @@ struct pnp_protocol pnpacpi_protocol = {
 };
 EXPORT_SYMBOL(pnpacpi_protocol);
 
-static char *pnpacpi_get_id(struct acpi_device *device)
+static char *__init pnpacpi_get_id(struct acpi_device *device)
 {
        struct acpi_hardware_id *id;
 
index 51237fbb1bbb7e15f952296a9ffcb9f668418fc9..6d20b0454a1d7284c7728e3ec0c85d7d8e22f452 100644 (file)
@@ -231,8 +231,7 @@ static int tps6586x_dvm_voltages[] = {
 };
 
 #define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits,       \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)    \
-{                                                                      \
+                          ereg0, ebit0, ereg1, ebit1)                  \
        .desc   = {                                                     \
                .name   = "REG-" #_id,                                  \
                .ops    = &tps6586x_regulator_##_ops,                   \
@@ -248,18 +247,26 @@ static int tps6586x_dvm_voltages[] = {
        .enable_bit[0]  = (ebit0),                                      \
        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
        .enable_bit[1]  = (ebit1),                                      \
-       .voltages       = tps6586x_##vdata##_voltages,                  \
-}
+       .voltages       = tps6586x_##vdata##_voltages,
+
+#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                     \
+       .go_reg = TPS6586X_##goreg,                                     \
+       .go_bit = (gobit),
 
 #define TPS6586X_LDO(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1)                        \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, 0, 0)
+                          ereg0, ebit0, ereg1, ebit1)                  \
+}
 
 #define TPS6586X_DVM(_id, vdata, vreg, shift, nbits,                   \
                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
+{                                                                      \
        TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits,     \
-                          ereg0, ebit0, ereg1, ebit1, goreg, gobit)
+                          ereg0, ebit0, ereg1, ebit1)                  \
+       TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
+}
 
 static struct tps6586x_regulator tps6586x_regulator[] = {
        TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0),
@@ -267,11 +274,11 @@ static struct tps6586x_regulator tps6586x_regulator[] = {
        TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
        TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
        TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
-       TPS6586X_LDO(LDO_8, ldo, SUPPLYV1, 5, 3, ENC, 6, END, 6),
+       TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
        TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
-       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, ENE, 7, ENE, 7),
+       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
        TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
-       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 1, END, 1),
+       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
 
        TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6),
        TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6),
@@ -290,6 +297,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        uint8_t val1, val2;
        int ret;
 
+       if (ri->enable_reg[0] == ri->enable_reg[1] &&
+           ri->enable_bit[0] == ri->enable_bit[1])
+                       return 0;
+
        ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
        if (ret)
                return ret;
@@ -298,14 +309,14 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
        if (ret)
                return ret;
 
-       if (!(val2 & ri->enable_bit[1]))
+       if (!(val2 & (1 << ri->enable_bit[1])))
                return 0;
 
        /*
         * The regulator is on, but it's enabled with the bit we don't
         * want to use, so we switch the enable bits
         */
-       if (!(val1 & ri->enable_bit[0])) {
+       if (!(val1 & (1 << ri->enable_bit[0]))) {
                ret = tps6586x_set_bits(parent, ri->enable_reg[0],
                                        1 << ri->enable_bit[0]);
                if (ret)
index 3374618300af87c16ac3ef6a674e9cb650e62f8c..25a8bc565f400b62c155dd31bb39ff08e8d85dd0 100644 (file)
@@ -90,7 +90,8 @@ static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
 
 static void kgdboc_restore_input(void)
 {
-       schedule_work(&kgdboc_restore_input_work);
+       if (likely(system_state == SYSTEM_RUNNING))
+               schedule_work(&kgdboc_restore_input_work);
 }
 
 static int kgdboc_register_kbd(char **cptr)
index 0a4dbdc1693a4462bddb82cdf5e0b9ab5ec4bed2..de450c1fb86926f39190f052d7644d56f60ccc5d 100644 (file)
@@ -855,6 +855,7 @@ const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
                        abs(cmode->yres - mode->yres);
                if (diff > d) {
                        diff = d;
+                       diff_refresh = abs(cmode->refresh - mode->refresh);
                        best = cmode;
                } else if (diff == d) {
                        d = abs(cmode->refresh - mode->refresh);
index c547cca26a266e962bbb760c0616e0846439d81d..51d2e4de34ebe58d4eb5d2c99d1fc1bb83f692f9 100644 (file)
@@ -696,6 +696,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
                                   __btree_submit_bio_done);
 }
 
+#ifdef CONFIG_MIGRATION
 static int btree_migratepage(struct address_space *mapping,
                        struct page *newpage, struct page *page)
 {
@@ -712,12 +713,9 @@ static int btree_migratepage(struct address_space *mapping,
        if (page_has_private(page) &&
            !try_to_release_page(page, GFP_KERNEL))
                return -EAGAIN;
-#ifdef CONFIG_MIGRATION
        return migrate_page(mapping, newpage, page);
-#else
-       return -ENOSYS;
-#endif
 }
+#endif
 
 static int btree_writepage(struct page *page, struct writeback_control *wbc)
 {
@@ -1009,7 +1007,10 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
        blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
        root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
                                     blocksize, generation);
-       BUG_ON(!root->node);
+       if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
+               free_extent_buffer(root->node);
+               return -EIO;
+       }
        root->commit_root = btrfs_root_node(root);
        return 0;
 }
index bcd59c7dfb574def82517a80affe6a9ddf756a92..227e5815d8382393d4adc4d0a340ee636bca9d3e 100644 (file)
@@ -429,6 +429,7 @@ err:
 
 static int cache_block_group(struct btrfs_block_group_cache *cache,
                             struct btrfs_trans_handle *trans,
+                            struct btrfs_root *root,
                             int load_cache_only)
 {
        struct btrfs_fs_info *fs_info = cache->fs_info;
@@ -442,9 +443,12 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 
        /*
         * We can't do the read from on-disk cache during a commit since we need
-        * to have the normal tree locking.
+        * to have the normal tree locking.  Also if we are currently trying to
+        * allocate blocks for the tree root we can't do the fast caching since
+        * we likely hold important locks.
         */
-       if (!trans->transaction->in_commit) {
+       if (!trans->transaction->in_commit &&
+           (root && root != root->fs_info->tree_root)) {
                spin_lock(&cache->lock);
                if (cache->cached != BTRFS_CACHE_NO) {
                        spin_unlock(&cache->lock);
@@ -2741,6 +2745,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
        struct btrfs_root *root = block_group->fs_info->tree_root;
        struct inode *inode = NULL;
        u64 alloc_hint = 0;
+       int dcs = BTRFS_DC_ERROR;
        int num_pages = 0;
        int retries = 0;
        int ret = 0;
@@ -2795,6 +2800,8 @@ again:
 
        spin_lock(&block_group->lock);
        if (block_group->cached != BTRFS_CACHE_FINISHED) {
+               /* We're not cached, don't bother trying to write stuff out */
+               dcs = BTRFS_DC_WRITTEN;
                spin_unlock(&block_group->lock);
                goto out_put;
        }
@@ -2821,6 +2828,8 @@ again:
        ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages,
                                              num_pages, num_pages,
                                              &alloc_hint);
+       if (!ret)
+               dcs = BTRFS_DC_SETUP;
        btrfs_free_reserved_data_space(inode, num_pages);
 out_put:
        iput(inode);
@@ -2828,10 +2837,7 @@ out_free:
        btrfs_release_path(root, path);
 out:
        spin_lock(&block_group->lock);
-       if (ret)
-               block_group->disk_cache_state = BTRFS_DC_ERROR;
-       else
-               block_group->disk_cache_state = BTRFS_DC_SETUP;
+       block_group->disk_cache_state = dcs;
        spin_unlock(&block_group->lock);
 
        return ret;
@@ -3037,7 +3043,13 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
 
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
 {
-       u64 num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       u64 num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
 
        if (num_devices == 1)
                flags &= ~(BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID0);
@@ -4080,7 +4092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                 * space back to the block group, otherwise we will leak space.
                 */
                if (!alloc && cache->cached == BTRFS_CACHE_NO)
-                       cache_block_group(cache, trans, 1);
+                       cache_block_group(cache, trans, NULL, 1);
 
                byte_in_group = bytenr - cache->key.objectid;
                WARN_ON(byte_in_group > cache->key.offset);
@@ -4930,11 +4942,31 @@ search:
                btrfs_get_block_group(block_group);
                search_start = block_group->key.objectid;
 
+               /*
+                * this can happen if we end up cycling through all the
+                * raid types, but we want to make sure we only allocate
+                * for the proper type.
+                */
+               if (!block_group_bits(block_group, data)) {
+                   u64 extra = BTRFS_BLOCK_GROUP_DUP |
+                               BTRFS_BLOCK_GROUP_RAID1 |
+                               BTRFS_BLOCK_GROUP_RAID10;
+
+                       /*
+                        * if they asked for extra copies and this block group
+                        * doesn't provide them, bail.  This does allow us to
+                        * fill raid0 from raid1.
+                        */
+                       if ((data & extra) && !(block_group->flags & extra))
+                               goto loop;
+               }
+
 have_block_group:
                if (unlikely(block_group->cached == BTRFS_CACHE_NO)) {
                        u64 free_percent;
 
-                       ret = cache_block_group(block_group, trans, 1);
+                       ret = cache_block_group(block_group, trans,
+                                               orig_root, 1);
                        if (block_group->cached == BTRFS_CACHE_FINISHED)
                                goto have_block_group;
 
@@ -4958,7 +4990,8 @@ have_block_group:
                        if (loop > LOOP_CACHING_NOWAIT ||
                            (loop > LOOP_FIND_IDEAL &&
                             atomic_read(&space_info->caching_threads) < 2)) {
-                               ret = cache_block_group(block_group, trans, 0);
+                               ret = cache_block_group(block_group, trans,
+                                                       orig_root, 0);
                                BUG_ON(ret);
                        }
                        found_uncached_bg = true;
@@ -5515,7 +5548,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
        u64 num_bytes = ins->offset;
 
        block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
-       cache_block_group(block_group, trans, 0);
+       cache_block_group(block_group, trans, NULL, 0);
        caching_ctl = get_caching_control(block_group);
 
        if (!caching_ctl) {
@@ -6300,9 +6333,13 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                                           NULL, NULL);
                BUG_ON(ret < 0);
                if (ret > 0) {
-                       ret = btrfs_del_orphan_item(trans, tree_root,
-                                                   root->root_key.objectid);
-                       BUG_ON(ret);
+                       /* if we fail to delete the orphan item this time
+                        * around, it'll get picked up the next time.
+                        *
+                        * The most common failure here is just -ENOENT.
+                        */
+                       btrfs_del_orphan_item(trans, tree_root,
+                                             root->root_key.objectid);
                }
        }
 
@@ -7878,7 +7915,14 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
        u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
                BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;
 
-       num_devices = root->fs_info->fs_devices->rw_devices;
+       /*
+        * we add in the count of missing devices because we want
+        * to make sure that any RAID levels on a degraded FS
+        * continue to be honored.
+        */
+       num_devices = root->fs_info->fs_devices->rw_devices +
+               root->fs_info->fs_devices->missing_devices;
+
        if (num_devices == 1) {
                stripped |= BTRFS_BLOCK_GROUP_DUP;
                stripped = flags & ~stripped;
@@ -8247,7 +8291,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                        break;
                if (ret != 0)
                        goto error;
-
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
                cache = kzalloc(sizeof(*cache), GFP_NOFS);
index c1faded5fca03a7cbcb509908cfdf3cc8362ce1f..66836d85763bbfd2dafe3821a1be30f173784fdc 100644 (file)
@@ -48,30 +48,34 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
                                         struct page **prepared_pages,
                                         struct iov_iter *i)
 {
-       size_t copied;
+       size_t copied = 0;
        int pg = 0;
        int offset = pos & (PAGE_CACHE_SIZE - 1);
+       int total_copied = 0;
 
        while (write_bytes > 0) {
                size_t count = min_t(size_t,
                                     PAGE_CACHE_SIZE - offset, write_bytes);
                struct page *page = prepared_pages[pg];
-again:
-               if (unlikely(iov_iter_fault_in_readable(i, count)))
-                       return -EFAULT;
-
-               /* Copy data from userspace to the current page */
-               copied = iov_iter_copy_from_user(page, i, offset, count);
+               /*
+                * Copy data from userspace to the current page
+                *
+                * Disable pagefault to avoid recursive lock since
+                * the pages are already locked
+                */
+               pagefault_disable();
+               copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
+               pagefault_enable();
 
                /* Flush processor's dcache for this page */
                flush_dcache_page(page);
                iov_iter_advance(i, copied);
                write_bytes -= copied;
+               total_copied += copied;
 
+               /* Return to btrfs_file_aio_write to fault page */
                if (unlikely(copied == 0)) {
-                       count = min_t(size_t, PAGE_CACHE_SIZE - offset,
-                                     iov_iter_single_seg_count(i));
-                       goto again;
+                       break;
                }
 
                if (unlikely(copied < PAGE_CACHE_SIZE - offset)) {
@@ -81,7 +85,7 @@ again:
                        offset = 0;
                }
        }
-       return 0;
+       return total_copied;
 }
 
 /*
@@ -854,6 +858,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        unsigned long last_index;
        int will_write;
        int buffered = 0;
+       int copied = 0;
+       int dirty_pages = 0;
 
        will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
                      (file->f_flags & O_DIRECT));
@@ -970,7 +976,17 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                WARN_ON(num_pages > nrptrs);
                memset(pages, 0, sizeof(struct page *) * nrptrs);
 
-               ret = btrfs_delalloc_reserve_space(inode, write_bytes);
+               /*
+                * Fault pages before locking them in prepare_pages
+                * to avoid recursive lock
+                */
+               if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               ret = btrfs_delalloc_reserve_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                if (ret)
                        goto out;
 
@@ -978,37 +994,49 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                                    pos, first_index, last_index,
                                    write_bytes);
                if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
+                       btrfs_delalloc_release_space(inode,
+                                       num_pages << PAGE_CACHE_SHIFT);
                        goto out;
                }
 
-               ret = btrfs_copy_from_user(pos, num_pages,
+               copied = btrfs_copy_from_user(pos, num_pages,
                                           write_bytes, pages, &i);
-               if (ret == 0) {
+               dirty_pages = (copied + PAGE_CACHE_SIZE - 1) >>
+                                       PAGE_CACHE_SHIFT;
+
+               if (num_pages > dirty_pages) {
+                       if (copied > 0)
+                               atomic_inc(
+                                       &BTRFS_I(inode)->outstanding_extents);
+                       btrfs_delalloc_release_space(inode,
+                                       (num_pages - dirty_pages) <<
+                                       PAGE_CACHE_SHIFT);
+               }
+
+               if (copied > 0) {
                        dirty_and_release_pages(NULL, root, file, pages,
-                                               num_pages, pos, write_bytes);
+                                               dirty_pages, pos, copied);
                }
 
                btrfs_drop_pages(pages, num_pages);
-               if (ret) {
-                       btrfs_delalloc_release_space(inode, write_bytes);
-                       goto out;
-               }
 
-               if (will_write) {
-                       filemap_fdatawrite_range(inode->i_mapping, pos,
-                                                pos + write_bytes - 1);
-               } else {
-                       balance_dirty_pages_ratelimited_nr(inode->i_mapping,
-                                                          num_pages);
-                       if (num_pages <
-                           (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
-                               btrfs_btree_balance_dirty(root, 1);
-                       btrfs_throttle(root);
+               if (copied > 0) {
+                       if (will_write) {
+                               filemap_fdatawrite_range(inode->i_mapping, pos,
+                                                        pos + copied - 1);
+                       } else {
+                               balance_dirty_pages_ratelimited_nr(
+                                                       inode->i_mapping,
+                                                       dirty_pages);
+                               if (dirty_pages <
+                               (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
+                                       btrfs_btree_balance_dirty(root, 1);
+                               btrfs_throttle(root);
+                       }
                }
 
-               pos += write_bytes;
-               num_written += write_bytes;
+               pos += copied;
+               num_written += copied;
 
                cond_resched();
        }
index 22ee0dc2e6b8a712900c68a8c44df4a453fb86f0..60d684266959bbf8f96c14873e9a1f57e069a29e 100644 (file)
@@ -290,7 +290,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
                       (unsigned long long)BTRFS_I(inode)->generation,
                       (unsigned long long)generation,
                       (unsigned long long)block_group->key.objectid);
-               goto out;
+               goto free_cache;
        }
 
        if (!num_entries)
@@ -524,6 +524,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                return 0;
        }
 
+       node = rb_first(&block_group->free_space_offset);
+       if (!node) {
+               iput(inode);
+               return 0;
+       }
+
        last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
        filemap_write_and_wait(inode->i_mapping);
        btrfs_wait_ordered_range(inode, inode->i_size &
@@ -543,10 +549,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
         */
        first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
 
-       node = rb_first(&block_group->free_space_offset);
-       if (!node)
-               goto out_free;
-
        /*
         * Lock all pages first so we can lock the extent safely.
         *
index 8039390bd6a6f7bc1d1026d917dcaeb93aa067e6..72f31ecb5c90085a2d6adfdc9b690ee038bf508f 100644 (file)
@@ -495,7 +495,7 @@ again:
                add_async_extent(async_cow, start, num_bytes,
                                 total_compressed, pages, nr_pages_ret);
 
-               if (start + num_bytes < end && start + num_bytes < actual_end) {
+               if (start + num_bytes < end) {
                        start += num_bytes;
                        pages = NULL;
                        cond_resched();
@@ -5712,9 +5712,9 @@ static void btrfs_end_dio_bio(struct bio *bio, int err)
 
        if (err) {
                printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu "
-                     "disk_bytenr %lu len %u err no %d\n",
-                     dip->inode->i_ino, bio->bi_rw, bio->bi_sector,
-                     bio->bi_size, err);
+                     "sector %#Lx len %u err no %d\n",
+                     dip->inode->i_ino, bio->bi_rw,
+                     (unsigned long long)bio->bi_sector, bio->bi_size, err);
                dip->errors = 1;
 
                /*
@@ -5934,8 +5934,7 @@ free_ordered:
         */
        if (write) {
                struct btrfs_ordered_extent *ordered;
-               ordered = btrfs_lookup_ordered_extent(inode,
-                                                     dip->logical_offset);
+               ordered = btrfs_lookup_ordered_extent(inode, file_offset);
                if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) &&
                    !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags))
                        btrfs_free_reserved_extent(root, ordered->start,
index f1c9bb4079ed8b3aaf2a01bb5211923f8e231986..f87552a1d7ea0beeb540aa59ddac3754242304cc 100644 (file)
@@ -947,23 +947,42 @@ out:
 
 static noinline int btrfs_ioctl_snap_create(struct file *file,
                                            void __user *arg, int subvol,
-                                           int async)
+                                           int v2)
 {
        struct btrfs_ioctl_vol_args *vol_args = NULL;
-       struct btrfs_ioctl_async_vol_args *async_vol_args = NULL;
+       struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL;
        char *name;
        u64 fd;
-       u64 transid = 0;
        int ret;
 
-       if (async) {
-               async_vol_args = memdup_user(arg, sizeof(*async_vol_args));
-               if (IS_ERR(async_vol_args))
-                       return PTR_ERR(async_vol_args);
+       if (v2) {
+               u64 transid = 0;
+               u64 *ptr = NULL;
 
-               name = async_vol_args->name;
-               fd = async_vol_args->fd;
-               async_vol_args->name[BTRFS_SNAPSHOT_NAME_MAX] = '\0';
+               vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2));
+               if (IS_ERR(vol_args_v2))
+                       return PTR_ERR(vol_args_v2);
+
+               if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               name = vol_args_v2->name;
+               fd = vol_args_v2->fd;
+               vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
+
+               if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC)
+                       ptr = &transid;
+
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, ptr);
+
+               if (ret == 0 && ptr &&
+                   copy_to_user(arg +
+                                offsetof(struct btrfs_ioctl_vol_args_v2,
+                                         transid), ptr, sizeof(*ptr)))
+                       ret = -EFAULT;
        } else {
                vol_args = memdup_user(arg, sizeof(*vol_args));
                if (IS_ERR(vol_args))
@@ -971,20 +990,13 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
                name = vol_args->name;
                fd = vol_args->fd;
                vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
-       }
-
-       ret = btrfs_ioctl_snap_create_transid(file, name, fd,
-                                             subvol, &transid);
 
-       if (!ret && async) {
-               if (copy_to_user(arg +
-                               offsetof(struct btrfs_ioctl_async_vol_args,
-                               transid), &transid, sizeof(transid)))
-                       return -EFAULT;
+               ret = btrfs_ioctl_snap_create_transid(file, name, fd,
+                                                     subvol, NULL);
        }
-
+out:
        kfree(vol_args);
-       kfree(async_vol_args);
+       kfree(vol_args_v2);
 
        return ret;
 }
@@ -2246,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_getversion(file, argp);
        case BTRFS_IOC_SNAP_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 0, 0);
-       case BTRFS_IOC_SNAP_CREATE_ASYNC:
+       case BTRFS_IOC_SNAP_CREATE_V2:
                return btrfs_ioctl_snap_create(file, argp, 0, 1);
        case BTRFS_IOC_SUBVOL_CREATE:
                return btrfs_ioctl_snap_create(file, argp, 1, 0);
index 17c99ebdf96049a8ad028cd6e138355df86f0c9e..c344d12c646bf7d1cbb953f8c4aba6257b6db8b9 100644 (file)
@@ -30,11 +30,15 @@ struct btrfs_ioctl_vol_args {
        char name[BTRFS_PATH_NAME_MAX + 1];
 };
 
-#define BTRFS_SNAPSHOT_NAME_MAX 4079
-struct btrfs_ioctl_async_vol_args {
+#define BTRFS_SUBVOL_CREATE_ASYNC      (1ULL << 0)
+
+#define BTRFS_SUBVOL_NAME_MAX 4039
+struct btrfs_ioctl_vol_args_v2 {
        __s64 fd;
        __u64 transid;
-       char name[BTRFS_SNAPSHOT_NAME_MAX + 1];
+       __u64 flags;
+       __u64 unused[4];
+       char name[BTRFS_SUBVOL_NAME_MAX + 1];
 };
 
 #define BTRFS_INO_LOOKUP_PATH_MAX 4080
@@ -187,6 +191,6 @@ struct btrfs_ioctl_space_args {
                                    struct btrfs_ioctl_space_args)
 #define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
 #define BTRFS_IOC_WAIT_SYNC  _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
-#define BTRFS_IOC_SNAP_CREATE_ASYNC _IOW(BTRFS_IOCTL_MAGIC, 23, \
-                                  struct btrfs_ioctl_async_vol_args)
+#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
+                                  struct btrfs_ioctl_vol_args_v2)
 #endif
index 79cba5fbc28ef8061e2d599110a3a525216a7bfd..f8be250963a09a283b8ec4ab04bcb1c3a962427e 100644 (file)
@@ -56,8 +56,12 @@ int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
                return -ENOMEM;
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-       if (ret)
+       if (ret < 0)
                goto out;
+       if (ret) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        ret = btrfs_del_item(trans, root, path);
 
index dbb51ea7a13c4b83e46c6c1f03d8d936cf75bed7..883c6fa1367eb866002d7f67d3ae2ce6497f4367 100644 (file)
@@ -685,9 +685,9 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                mutex_unlock(&root->d_inode->i_mutex);
 
                if (IS_ERR(new_root)) {
+                       dput(root);
                        deactivate_locked_super(s);
                        error = PTR_ERR(new_root);
-                       dput(root);
                        goto error_free_subvol_name;
                }
                if (!new_root->d_inode) {
index cc04dc1445d64da8694401c2cbc2fde27105b8f9..6b9884507837581ba6231bc6c4cfb85a036b82f6 100644 (file)
@@ -412,12 +412,16 @@ static noinline int device_list_add(const char *path,
 
                device->fs_devices = fs_devices;
                fs_devices->num_devices++;
-       } else if (strcmp(device->name, path)) {
+       } else if (!device->name || strcmp(device->name, path)) {
                name = kstrdup(path, GFP_NOFS);
                if (!name)
                        return -ENOMEM;
                kfree(device->name);
                device->name = name;
+               if (device->missing) {
+                       fs_devices->missing_devices--;
+                       device->missing = 0;
+               }
        }
 
        if (found_transid > fs_devices->latest_trans) {
@@ -1236,6 +1240,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 
        device->fs_devices->num_devices--;
 
+       if (device->missing)
+               root->fs_info->fs_devices->missing_devices--;
+
        next_device = list_entry(root->fs_info->fs_devices->devices.next,
                                 struct btrfs_device, dev_list);
        if (device->bdev == root->fs_info->sb->s_bdev)
@@ -3080,7 +3087,9 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
        device->devid = devid;
        device->work.func = pending_bios_fn;
        device->fs_devices = fs_devices;
+       device->missing = 1;
        fs_devices->num_devices++;
+       fs_devices->missing_devices++;
        spin_lock_init(&device->io_lock);
        INIT_LIST_HEAD(&device->dev_alloc_list);
        memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE);
@@ -3278,6 +3287,15 @@ static int read_one_dev(struct btrfs_root *root,
                        device = add_missing_dev(root, devid, dev_uuid);
                        if (!device)
                                return -ENOMEM;
+               } else if (!device->missing) {
+                       /*
+                        * this happens when a device that was properly setup
+                        * in the device info lists suddenly goes bad.
+                        * device->bdev is NULL, and so we have to set
+                        * device->missing to one here
+                        */
+                       root->fs_info->fs_devices->missing_devices++;
+                       device->missing = 1;
                }
        }
 
index 2b638b6e4eeae7cb9428490a897c1e10a9aaad1f..2740db49eb04d7a8de03d18e5935a97ff43ef9db 100644 (file)
@@ -44,6 +44,7 @@ struct btrfs_device {
 
        int writeable;
        int in_fs_metadata;
+       int missing;
 
        spinlock_t io_lock;
 
@@ -93,6 +94,7 @@ struct btrfs_fs_devices {
        u64 num_devices;
        u64 open_devices;
        u64 rw_devices;
+       u64 missing_devices;
        u64 total_rw_bytes;
        struct block_device *latest_bdev;
 
index 7d447af84ec4861acee8cd82bcecf80a892132b1..158c700fdca5e4f62763377a8374217d6371b68b 100644 (file)
@@ -114,8 +114,8 @@ static int __dcache_readdir(struct file *filp,
        spin_lock(&dcache_lock);
 
        /* start at beginning? */
-       if (filp->f_pos == 2 || (last &&
-                                filp->f_pos < ceph_dentry(last)->offset)) {
+       if (filp->f_pos == 2 || last == NULL ||
+           filp->f_pos < ceph_dentry(last)->offset) {
                if (list_empty(&parent->d_subdirs))
                        goto out_unlock;
                p = parent->d_subdirs.prev;
index a6ce54e94eb5ab435670093cd6ad789e72cc627b..52e8fd74d450b9e2895eb7c29d80e38b77eb0807 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
-#define CEPH_IOCTL_MAGIC 0x98
+#define CEPH_IOCTL_MAGIC 0x97
 
 /* just use u64 to align sanely on all archs */
 struct ceph_ioctl_layout {
index 40abde93c345d054279fd51cbca998525c4931c7..476b329867d41cf2cec7b3e2ad51e5f3885d9d7a 100644 (file)
  * Implement fcntl and flock locking functions.
  */
 static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
-                            u64 pid, u64 pid_ns,
-                            int cmd, u64 start, u64 length, u8 wait)
+                            int cmd, u8 wait, struct file_lock *fl)
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct ceph_mds_client *mdsc =
                ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_mds_request *req;
        int err;
+       u64 length = 0;
 
        req = ceph_mdsc_create_request(mdsc, operation, USE_AUTH_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
        req->r_inode = igrab(inode);
 
+       /* mds requires start and length rather than start and end */
+       if (LLONG_MAX == fl->fl_end)
+               length = 0;
+       else
+               length = fl->fl_end - fl->fl_start + 1;
+
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
             "length: %llu, wait: %d, type`: %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd);
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type);
+
 
        req->r_args.filelock_change.rule = lock_type;
        req->r_args.filelock_change.type = cmd;
-       req->r_args.filelock_change.pid = cpu_to_le64(pid);
+       req->r_args.filelock_change.pid = cpu_to_le64((u64)fl->fl_pid);
        /* This should be adjusted, but I'm not sure if
           namespaces actually get id numbers*/
        req->r_args.filelock_change.pid_namespace =
-               cpu_to_le64((u64)pid_ns);
-       req->r_args.filelock_change.start = cpu_to_le64(start);
+               cpu_to_le64((u64)(unsigned long)fl->fl_nspid);
+       req->r_args.filelock_change.start = cpu_to_le64(fl->fl_start);
        req->r_args.filelock_change.length = cpu_to_le64(length);
        req->r_args.filelock_change.wait = wait;
 
        err = ceph_mdsc_do_request(mdsc, inode, req);
+
+       if ( operation == CEPH_MDS_OP_GETFILELOCK){
+               fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid);
+               if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_RDLCK;
+               else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type)
+                       fl->fl_type = F_WRLCK;
+               else
+                       fl->fl_type = F_UNLCK;
+
+               fl->fl_start = le64_to_cpu(req->r_reply_info.filelock_reply->start);
+               length = le64_to_cpu(req->r_reply_info.filelock_reply->start) +
+                                                le64_to_cpu(req->r_reply_info.filelock_reply->length);
+               if (length >= 1)
+                       fl->fl_end = length -1;
+               else
+                       fl->fl_end = 0;
+
+       }
        ceph_mdsc_put_request(req);
        dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
-            "length: %llu, wait: %d, type`: %d err code %d", (int)lock_type,
-            (int)operation, pid, start, length, wait, cmd, err);
+            "length: %llu, wait: %d, type`: %d, err code %d", (int)lock_type,
+            (int)operation, (u64)fl->fl_pid, fl->fl_start,
+            length, wait, fl->fl_type, err);
        return err;
 }
 
@@ -54,7 +82,6 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
  */
 int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 0;
@@ -76,29 +103,20 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
 
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
-
-       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                               (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+       err = ceph_lock_message(CEPH_LOCK_FCNTL, op, file, lock_cmd, wait, fl);
        if (!err) {
-               dout("mds locked, locking locally");
-               err = posix_lock_file(file, fl, NULL);
-               if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
-                       /* undo! This should only happen if the kernel detects
-                        * local deadlock. */
-                       ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
-                                         (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
-                       dout("got %d on posix_lock_file, undid lock", err);
+               if ( op != CEPH_MDS_OP_GETFILELOCK ){
+                       dout("mds locked, locking locally");
+                       err = posix_lock_file(file, fl, NULL);
+                       if (err && (CEPH_MDS_OP_SETFILELOCK == op)) {
+                               /* undo! This should only happen if the kernel detects
+                                * local deadlock. */
+                               ceph_lock_message(CEPH_LOCK_FCNTL, op, file,
+                                                 CEPH_LOCK_UNLOCK, 0, fl);
+                               dout("got %d on posix_lock_file, undid lock", err);
+                       }
                }
+
        } else {
                dout("mds returned error code %d", err);
        }
@@ -107,7 +125,6 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
 
 int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
 {
-       u64 length;
        u8 lock_cmd;
        int err;
        u8 wait = 1;
@@ -127,26 +144,15 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
                lock_cmd = CEPH_LOCK_EXCL;
        else
                lock_cmd = CEPH_LOCK_UNLOCK;
-       /* mds requires start and length rather than start and end */
-       if (LLONG_MAX == fl->fl_end)
-               length = 0;
-       else
-               length = fl->fl_end - fl->fl_start + 1;
 
        err = ceph_lock_message(CEPH_LOCK_FLOCK, CEPH_MDS_OP_SETFILELOCK,
-                               file, (u64)fl->fl_pid,
-                               (u64)(unsigned long)fl->fl_nspid,
-                               lock_cmd, fl->fl_start,
-                               length, wait);
+                               file, lock_cmd, wait, fl);
        if (!err) {
                err = flock_lock_file_wait(file, fl);
                if (err) {
                        ceph_lock_message(CEPH_LOCK_FLOCK,
                                          CEPH_MDS_OP_SETFILELOCK,
-                                         file, (u64)fl->fl_pid,
-                                         (u64)(unsigned long)fl->fl_nspid,
-                                         CEPH_LOCK_UNLOCK, fl->fl_start,
-                                         length, 0);
+                                         file, CEPH_LOCK_UNLOCK, 0, fl);
                        dout("got %d on flock_lock_file_wait, undid lock", err);
                }
        } else {
index 098b185084791730ba0143111126bc066fdb9afb..38800eaa81d066bd8f06a401d082ecd3bb3f6fea 100644 (file)
@@ -201,6 +201,38 @@ out_bad:
        return err;
 }
 
+/*
+ * parse fcntl F_GETLK results
+ */
+static int parse_reply_info_filelock(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (*p + sizeof(*info->filelock_reply) > end)
+               goto bad;
+
+       info->filelock_reply = *p;
+       *p += sizeof(*info->filelock_reply);
+
+       if (unlikely(*p != end))
+               goto bad;
+       return 0;
+
+bad:
+       return -EIO;
+}
+
+/*
+ * parse extra results
+ */
+static int parse_reply_info_extra(void **p, void *end,
+                struct ceph_mds_reply_info_parsed *info)
+{
+       if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
+               return parse_reply_info_filelock(p, end, info);
+       else
+               return parse_reply_info_dir(p, end, info);
+}
+
 /*
  * parse entire mds reply
  */
@@ -223,10 +255,10 @@ static int parse_reply_info(struct ceph_msg *msg,
                        goto out_bad;
        }
 
-       /* dir content */
+       /* extra */
        ceph_decode_32_safe(&p, end, len, bad);
        if (len > 0) {
-               err = parse_reply_info_dir(&p, p+len, info);
+               err = parse_reply_info_extra(&p, p+len, info);
                if (err < 0)
                        goto out_bad;
        }
@@ -2074,7 +2106,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
 
        mutex_lock(&session->s_mutex);
        if (err < 0) {
-               pr_err("mdsc_handle_reply got corrupt reply mds%d\n", mds);
+               pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid);
                ceph_msg_dump(msg);
                goto out_err;
        }
@@ -2094,7 +2126,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        mutex_lock(&req->r_fill_mutex);
        err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
        if (err == 0) {
-               if (result == 0 && rinfo->dir_nr)
+               if (result == 0 && req->r_op != CEPH_MDS_OP_GETFILELOCK &&
+                   rinfo->dir_nr)
                        ceph_readdir_prepopulate(req, req->r_session);
                ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
        }
index 9341fd4f14320060a395c37f81b4a67b01c020d7..aabe563b54db308af80ee9fff18dd81610a9cf94 100644 (file)
@@ -42,26 +42,37 @@ struct ceph_mds_reply_info_in {
 };
 
 /*
- * parsed info about an mds reply, including information about the
- * target inode and/or its parent directory and dentry, and directory
- * contents (for readdir results).
+ * parsed info about an mds reply, including information about
+ * either: 1) the target inode and/or its parent directory and dentry,
+ * and directory contents (for readdir results), or
+ * 2) the file range lock info (for fcntl F_GETLK results).
  */
 struct ceph_mds_reply_info_parsed {
        struct ceph_mds_reply_head    *head;
 
+       /* trace */
        struct ceph_mds_reply_info_in diri, targeti;
        struct ceph_mds_reply_dirfrag *dirfrag;
        char                          *dname;
        u32                           dname_len;
        struct ceph_mds_reply_lease   *dlease;
 
-       struct ceph_mds_reply_dirfrag *dir_dir;
-       int                           dir_nr;
-       char                          **dir_dname;
-       u32                           *dir_dname_len;
-       struct ceph_mds_reply_lease   **dir_dlease;
-       struct ceph_mds_reply_info_in *dir_in;
-       u8                            dir_complete, dir_end;
+       /* extra */
+       union {
+               /* for fcntl F_GETLK results */
+               struct ceph_filelock *filelock_reply;
+
+               /* for readdir results */
+               struct {
+                       struct ceph_mds_reply_dirfrag *dir_dir;
+                       int                           dir_nr;
+                       char                          **dir_dname;
+                       u32                           *dir_dname_len;
+                       struct ceph_mds_reply_lease   **dir_dlease;
+                       struct ceph_mds_reply_info_in *dir_in;
+                       u8                            dir_complete, dir_end;
+               };
+       };
 
        /* encoded blob describing snapshot contexts for certain
           operations (e.g., open) */
index adefa60a9bdc10108ec9c802e4cbe1ea26f3f6e0..43b19dd391912476c395ffbabaaabbacc28d0146 100644 (file)
@@ -6,7 +6,9 @@ obj-$(CONFIG_CIFS) += cifs.o
 cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
          link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \
          md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \
-         readdir.o ioctl.o sess.o export.o cifsacl.o
+         readdir.o ioctl.o sess.o export.o
+
+cifs-$(CONFIG_CIFS_ACL) += cifsacl.o
 
 cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
 
index ee68d1036544d591930af8119d5e7450634adfff..46af99ab3614d545675e41e788686b39fd51204b 100644 (file)
@@ -337,6 +337,15 @@ A partial list of the supported mount options follows:
   wsize                default write size (default 57344)
                maximum wsize currently allowed by CIFS is 57344 (fourteen
                4096 byte pages)
+  actimeo=n    attribute cache timeout in seconds (default 1 second).
+               After this timeout, the cifs client requests fresh attribute
+               information from the server. This option allows to tune the
+               attribute cache timeout to suit the workload needs. Shorter
+               timeouts mean better the cache coherency, but increased number
+               of calls to the server. Longer timeouts mean reduced number
+               of calls to the server at the expense of less stricter cache
+               coherency checks (i.e. incorrect attribute cache for a short
+               period of time).
   rw           mount the network share read-write (note that the
                server may still consider the share read-only)
   ro           mount network share read-only
index e9a393c9c2ca4ddb8ec3d75cfcf0766234ec1789..7852cd6770517a8a5da7877fb788a834a0534c86 100644 (file)
@@ -48,6 +48,7 @@ struct cifs_sb_info {
        struct nls_table *local_nls;
        unsigned int rsize;
        unsigned int wsize;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        atomic_t active;
        uid_t   mnt_uid;
        gid_t   mnt_gid;
index c6ebea088ac7c2bf6d01d3ac02910f0164a4b4b3..a437ec391a015fb7c05725543d6c118eadefc466 100644 (file)
@@ -30,8 +30,6 @@
 #include "cifs_debug.h"
 
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
        {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
        {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
@@ -774,4 +772,3 @@ int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
 
        return rc;
 }
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
index 6c8096cf51557764aa10af6c28d108d3e93ce6e7..c4ae7d0365631f5d01db610ef3153502f2531c9d 100644 (file)
@@ -74,11 +74,7 @@ struct cifs_wksid {
        char sidname[SIDNAMELENGTH];
 } __attribute__((packed));
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-
 extern int match_sid(struct cifs_sid *);
 extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
 
-#endif /*  CONFIG_CIFS_EXPERIMENTAL */
-
 #endif /* _CIFSACL_H */
index 76c8a906a63eee2369123f0ea1f433ad58692b1e..3936aa7f2c2285cfb59857f8fe1925528920543a 100644 (file)
@@ -463,6 +463,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 
        seq_printf(s, ",rsize=%d", cifs_sb->rsize);
        seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+       /* convert actimeo and display it in seconds */
+               seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
 
        return 0;
 }
@@ -935,7 +937,6 @@ init_cifs(void)
        GlobalCurrentXid = 0;
        GlobalTotalActiveXid = 0;
        GlobalMaxActiveXid = 0;
-       memset(Local_System_Name, 0, 15);
        spin_lock_init(&cifs_tcp_ses_lock);
        spin_lock_init(&cifs_file_list_lock);
        spin_lock_init(&GlobalMid_Lock);
index b577bf0a1bb3622491ed0a885ca30b9e7684d24e..7136c0c3e2f961ec2c57d882163a1ffbc0e50ef1 100644 (file)
 
 #define CIFS_MIN_RCV_POOL 4
 
+/*
+ * default attribute cache timeout (jiffies)
+ */
+#define CIFS_DEF_ACTIMEO (1 * HZ)
+
+/*
+ * max attribute cache timeout (jiffies) - 2^30
+ */
+#define CIFS_MAX_ACTIMEO (1 << 30)
+
 /*
  * MAX_REQ is the maximum number of requests that WE will send
  * on one socket concurrently. It also matches the most common
@@ -746,8 +756,6 @@ GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN spinlock_t GlobalMid_Lock;  /* protects above & list operations */
                                          /* on midQ entries */
-GLOBAL_EXTERN char Local_System_Name[15];
-
 /*
  *  Global counters, updated atomically
  */
index db961dc4fd3d30b4bbdf15924c1e58fded05b10e..e6d1481b16c1403cbe1c7fcae04e11abcc3f91f9 100644 (file)
@@ -54,7 +54,8 @@ do {                                                          \
             __func__, curr_xid, (int)rc);                      \
 } while (0)
 extern char *build_path_from_dentry(struct dentry *);
-extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
+extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                                       struct cifsTconInfo *tcon);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern char *cifs_compose_mount_options(const char *sb_mountdata,
                const char *fullpath, const struct dfs_info3_param *ref,
@@ -79,9 +80,7 @@ extern bool is_valid_oplock_break(struct smb_hdr *smb,
                                  struct TCP_Server_Info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
-#endif
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
index 2f2632b6df5a1efd960bf44502d280e0e9499908..67acfb3acad271a51be1a1446d4f9828119e6b39 100644 (file)
@@ -2478,95 +2478,6 @@ querySymLinkRetry:
 }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-/* Initialize NT TRANSACT SMB into small smb request buffer.
-   This assumes that all NT TRANSACTS that we init here have
-   total parm and data under about 400 bytes (to fit in small cifs
-   buffer size), which is the case so far, it easily fits. NB:
-       Setup words themselves and ByteCount
-       MaxSetupCount (size of returned setup area) and
-       MaxParameterCount (returned parms size) must be set by caller */
-static int
-smb_init_nttransact(const __u16 sub_command, const int setup_count,
-                  const int parm_len, struct cifsTconInfo *tcon,
-                  void **ret_buf)
-{
-       int rc;
-       __u32 temp_offset;
-       struct smb_com_ntransact_req *pSMB;
-
-       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
-                               (void **)&pSMB);
-       if (rc)
-               return rc;
-       *ret_buf = (void *)pSMB;
-       pSMB->Reserved = 0;
-       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
-       pSMB->TotalDataCount  = 0;
-       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
-                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->DataCount  = pSMB->TotalDataCount;
-       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
-                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
-       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
-       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
-       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
-       pSMB->SubCommand = cpu_to_le16(sub_command);
-       return 0;
-}
-
-static int
-validate_ntransact(char *buf, char **ppparm, char **ppdata,
-                  __u32 *pparmlen, __u32 *pdatalen)
-{
-       char *end_of_smb;
-       __u32 data_count, data_offset, parm_count, parm_offset;
-       struct smb_com_ntransact_rsp *pSMBr;
-
-       *pdatalen = 0;
-       *pparmlen = 0;
-
-       if (buf == NULL)
-               return -EINVAL;
-
-       pSMBr = (struct smb_com_ntransact_rsp *)buf;
-
-       /* ByteCount was converted from little endian in SendReceive */
-       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
-                       (char *)&pSMBr->ByteCount;
-
-       data_offset = le32_to_cpu(pSMBr->DataOffset);
-       data_count = le32_to_cpu(pSMBr->DataCount);
-       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
-       parm_count = le32_to_cpu(pSMBr->ParameterCount);
-
-       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
-       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
-
-       /* should we also check that parm and data areas do not overlap? */
-       if (*ppparm > end_of_smb) {
-               cFYI(1, "parms start after end of smb");
-               return -EINVAL;
-       } else if (parm_count + *ppparm > end_of_smb) {
-               cFYI(1, "parm end after end of smb");
-               return -EINVAL;
-       } else if (*ppdata > end_of_smb) {
-               cFYI(1, "data starts after end of smb");
-               return -EINVAL;
-       } else if (data_count + *ppdata > end_of_smb) {
-               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
-                       *ppdata, data_count, (data_count + *ppdata),
-                       end_of_smb, pSMBr);
-               return -EINVAL;
-       } else if (parm_count + data_count > pSMBr->ByteCount) {
-               cFYI(1, "parm count and data count larger than SMB");
-               return -EINVAL;
-       }
-       *pdatalen = data_count;
-       *pparmlen = parm_count;
-       return 0;
-}
-
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName,
@@ -3056,7 +2967,97 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
+/*
+ * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
+ * all NT TRANSACTS that we init here have total parm and data under about 400
+ * bytes (to fit in small cifs buffer size), which is the case so far, it
+ * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
+ * returned setup area) and MaxParameterCount (returned parms size) must be set
+ * by caller
+ */
+static int
+smb_init_nttransact(const __u16 sub_command, const int setup_count,
+                  const int parm_len, struct cifsTconInfo *tcon,
+                  void **ret_buf)
+{
+       int rc;
+       __u32 temp_offset;
+       struct smb_com_ntransact_req *pSMB;
+
+       rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+                               (void **)&pSMB);
+       if (rc)
+               return rc;
+       *ret_buf = (void *)pSMB;
+       pSMB->Reserved = 0;
+       pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+       pSMB->TotalDataCount  = 0;
+       pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->DataCount  = pSMB->TotalDataCount;
+       temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+                       (setup_count * 2) - 4 /* for rfc1001 length itself */;
+       pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+       pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+       pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+       pSMB->SubCommand = cpu_to_le16(sub_command);
+       return 0;
+}
+
+static int
+validate_ntransact(char *buf, char **ppparm, char **ppdata,
+                  __u32 *pparmlen, __u32 *pdatalen)
+{
+       char *end_of_smb;
+       __u32 data_count, data_offset, parm_count, parm_offset;
+       struct smb_com_ntransact_rsp *pSMBr;
+
+       *pdatalen = 0;
+       *pparmlen = 0;
+
+       if (buf == NULL)
+               return -EINVAL;
+
+       pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+       /* ByteCount was converted from little endian in SendReceive */
+       end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
+                       (char *)&pSMBr->ByteCount;
+
+       data_offset = le32_to_cpu(pSMBr->DataOffset);
+       data_count = le32_to_cpu(pSMBr->DataCount);
+       parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+       parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+       *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+       *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+       /* should we also check that parm and data areas do not overlap? */
+       if (*ppparm > end_of_smb) {
+               cFYI(1, "parms start after end of smb");
+               return -EINVAL;
+       } else if (parm_count + *ppparm > end_of_smb) {
+               cFYI(1, "parm end after end of smb");
+               return -EINVAL;
+       } else if (*ppdata > end_of_smb) {
+               cFYI(1, "data starts after end of smb");
+               return -EINVAL;
+       } else if (data_count + *ppdata > end_of_smb) {
+               cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
+                       *ppdata, data_count, (data_count + *ppdata),
+                       end_of_smb, pSMBr);
+               return -EINVAL;
+       } else if (parm_count + data_count > pSMBr->ByteCount) {
+               cFYI(1, "parm count and data count larger than SMB");
+               return -EINVAL;
+       }
+       *pdatalen = data_count;
+       *pparmlen = parm_count;
+       return 0;
+}
+
 /* Get Security Descriptor (by handle) from remote server for a file or dir */
 int
 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
@@ -3214,7 +3215,7 @@ setCifsAclRetry:
        return (rc);
 }
 
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
+#endif /* CONFIG_CIFS_ACL */
 
 /* Legacy Query Path Information call for lookup to old servers such
    as Win9x/WinME */
index 32fa4d9b5dbc11537dfc09653215a9540668e109..cc1a8604a790b46767e066a59ef897f314144163 100644 (file)
@@ -105,6 +105,7 @@ struct smb_vol {
        unsigned int wsize;
        bool sockopt_tcp_nodelay:1;
        unsigned short int port;
+       unsigned long actimeo; /* attribute cache timeout (jiffies) */
        char *prepath;
        struct sockaddr_storage srcaddr; /* allow binding to a local IP */
        struct nls_table *local_nls;
@@ -806,23 +807,20 @@ cifs_parse_mount_options(char *options, const char *devname,
        short int override_gid = -1;
        bool uid_specified = false;
        bool gid_specified = false;
+       char *nodename = utsname()->nodename;
 
        separator[0] = ',';
        separator[1] = 0;
 
-       if (Local_System_Name[0] != 0)
-               memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
-       else {
-               char *nodename = utsname()->nodename;
-               int n = strnlen(nodename, 15);
-               memset(vol->source_rfc1001_name, 0x20, 15);
-               for (i = 0; i < n; i++) {
-                       /* does not have to be perfect mapping since field is
-                       informational, only used for servers that do not support
-                       port 445 and it can be overridden at mount time */
-                       vol->source_rfc1001_name[i] = toupper(nodename[i]);
-               }
-       }
+       /*
+        * does not have to be perfect mapping since field is
+        * informational, only used for servers that do not support
+        * port 445 and it can be overridden at mount time
+        */
+       memset(vol->source_rfc1001_name, 0x20, 15);
+       for (i = 0; i < strnlen(nodename, 15); i++)
+               vol->source_rfc1001_name[i] = toupper(nodename[i]);
+
        vol->source_rfc1001_name[15] = 0;
        /* null target name indicates to use *SMBSERVR default called name
           if we end up sending RFC1001 session initialize */
@@ -840,6 +838,8 @@ cifs_parse_mount_options(char *options, const char *devname,
        /* default to using server inode numbers where available */
        vol->server_ino = 1;
 
+       vol->actimeo = CIFS_DEF_ACTIMEO;
+
        if (!options)
                return 1;
 
@@ -1214,6 +1214,16 @@ cifs_parse_mount_options(char *options, const char *devname,
                                        printk(KERN_WARNING "CIFS: server net"
                                        "biosname longer than 15 truncated.\n");
                        }
+               } else if (strnicmp(data, "actimeo", 7) == 0) {
+                       if (value && *value) {
+                               vol->actimeo = HZ * simple_strtoul(value,
+                                                                  &value, 0);
+                               if (vol->actimeo > CIFS_MAX_ACTIMEO) {
+                                       cERROR(1, "CIFS: attribute cache"
+                                                       "timeout too large");
+                                       return 1;
+                               }
+                       }
                } else if (strnicmp(data, "credentials", 4) == 0) {
                        /* ignore */
                } else if (strnicmp(data, "version", 3) == 0) {
@@ -2571,6 +2581,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
        cFYI(1, "file mode: 0x%x  dir mode: 0x%x",
                cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
 
+       cifs_sb->actimeo = pvolume_info->actimeo;
+
        if (pvolume_info->noperm)
                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
        if (pvolume_info->setuids)
@@ -2821,13 +2833,13 @@ remote_path_check:
        /* check if a whole path (including prepath) is not remote */
        if (!rc && cifs_sb->prepathlen && tcon) {
                /* build_path_to_root works only when we have a valid tcon */
-               full_path = cifs_build_path_to_root(cifs_sb);
+               full_path = cifs_build_path_to_root(cifs_sb, tcon);
                if (full_path == NULL) {
                        rc = -ENOMEM;
                        goto mount_fail_check;
                }
                rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
-               if (rc != -EREMOTE) {
+               if (rc != 0 && rc != -EREMOTE) {
                        kfree(full_path);
                        goto mount_fail_check;
                }
index b857ce5db7755143affed1224c778d34ddc77b99..5a28660ca2b5e619955c05d74d9d84b95a994a4b 100644 (file)
@@ -1108,7 +1108,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
        return total_written;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
 {
@@ -1142,7 +1141,6 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
        spin_unlock(&cifs_file_list_lock);
        return NULL;
 }
-#endif
 
 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
index 28cb6e735943f935d3ed9408f34152ba35f100b7..589f3e3f6e0023b1f8b09f1e030119896117c94f 100644 (file)
@@ -686,7 +686,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        cFYI(1, "cifs_sfu_type failed: %d", tmprc);
        }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
        /* fill in 0777 bits from ACL */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path,
@@ -697,7 +697,7 @@ int cifs_get_inode_info(struct inode **pinode,
                        goto cgii_exit;
                }
        }
-#endif
+#endif /* CONFIG_CIFS_ACL */
 
        /* fill in remaining high mode bits e.g. SUID, VTX */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
@@ -728,12 +728,12 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
-char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
+char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
+                               struct cifsTconInfo *tcon)
 {
        int pplen = cifs_sb->prepathlen;
        int dfsplen;
        char *full_path = NULL;
-       struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
        /* if no prefix path, simply set path to the root of share to "" */
        if (pplen == 0) {
@@ -875,7 +875,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
        char *full_path;
        struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
-       full_path = cifs_build_path_to_root(cifs_sb);
+       full_path = cifs_build_path_to_root(cifs_sb, tcon);
        if (full_path == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -1653,6 +1653,7 @@ static bool
 cifs_inode_needs_reval(struct inode *inode)
 {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
        if (cifs_i->clientCanCacheRead)
                return false;
@@ -1663,12 +1664,12 @@ cifs_inode_needs_reval(struct inode *inode)
        if (cifs_i->time == 0)
                return true;
 
-       /* FIXME: the actimeo should be tunable */
-       if (time_after_eq(jiffies, cifs_i->time + HZ))
+       if (!time_in_range(jiffies, cifs_i->time,
+                               cifs_i->time + cifs_sb->actimeo))
                return true;
 
        /* hardlinked files w/ noserverino get "special" treatment */
-       if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
            S_ISREG(inode->i_mode) && inode->i_nlink != 1)
                return true;
 
@@ -2121,7 +2122,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
        if (attrs->ia_valid & ATTR_MODE) {
                rc = 0;
-#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef CONFIG_CIFS_ACL
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                        rc = mode_to_cifs_acl(inode, full_path, mode);
                        if (rc) {
@@ -2130,7 +2131,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                                goto cifs_setattr_exit;
                        }
                } else
-#endif
+#endif /* CONFIG_CIFS_ACL */
                if (((mode & S_IWUGO) == 0) &&
                    (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
 
index 32d300e8f20eb4a6676b8da50187a4b04146fcb8..a73eb9f4bdaf3608c2bf6f5dc124b5fabdd4445b 100644 (file)
@@ -759,18 +759,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
        rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
                     ino, fattr.cf_dtype);
 
-       /*
-        * we can not return filldir errors to the caller since they are
-        * "normal" when the stat blocksize is too small - we return remapped
-        * error instead
-        *
-        * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
-        * case already. Why should we be clobbering other errors from it?
-        */
-       if (rc) {
-               cFYI(1, "filldir rc = %d", rc);
-               rc = -EOVERFLOW;
-       }
        dput(tmp_dentry);
        return rc;
 }
index 9242d294fe90d382fb7a40f1220923baea71c97e..8b984a2cebbda185af01a6d4d5f8c31c89fc6fbe 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/compat.h>
 
 static const struct file_operations fuse_direct_io_file_operations;
 
@@ -1627,6 +1628,58 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
        return 0;
 }
 
+/*
+ * CUSE servers compiled on 32bit broke on 64bit kernels because the
+ * ABI was defined to be 'struct iovec' which is different on 32bit
+ * and 64bit.  Fortunately we can determine which structure the server
+ * used from the size of the reply.
+ */
+static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src,
+                                size_t transferred, unsigned count,
+                                bool is_compat)
+{
+#ifdef CONFIG_COMPAT
+       if (count * sizeof(struct compat_iovec) == transferred) {
+               struct compat_iovec *ciov = src;
+               unsigned i;
+
+               /*
+                * With this interface a 32bit server cannot support
+                * non-compat (i.e. ones coming from 64bit apps) ioctl
+                * requests
+                */
+               if (!is_compat)
+                       return -EINVAL;
+
+               for (i = 0; i < count; i++) {
+                       dst[i].iov_base = compat_ptr(ciov[i].iov_base);
+                       dst[i].iov_len = ciov[i].iov_len;
+               }
+               return 0;
+       }
+#endif
+
+       if (count * sizeof(struct iovec) != transferred)
+               return -EIO;
+
+       memcpy(dst, src, transferred);
+       return 0;
+}
+
+/* Make sure iov_length() won't overflow */
+static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
+{
+       size_t n;
+       u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
+
+       for (n = 0; n < count; n++) {
+               if (iov->iov_len > (size_t) max)
+                       return -ENOMEM;
+               max -= iov->iov_len;
+       }
+       return 0;
+}
+
 /*
  * For ioctls, there is no generic way to determine how much memory
  * needs to be read and/or written.  Furthermore, ioctls are allowed
@@ -1808,18 +1861,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
                        goto out;
 
-               err = -EIO;
-               if ((in_iovs + out_iovs) * sizeof(struct iovec) != transferred)
-                       goto out;
-
-               /* okay, copy in iovs and retry */
                vaddr = kmap_atomic(pages[0], KM_USER0);
-               memcpy(page_address(iov_page), vaddr, transferred);
+               err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr,
+                                           transferred, in_iovs + out_iovs,
+                                           (flags & FUSE_IOCTL_COMPAT) != 0);
                kunmap_atomic(vaddr, KM_USER0);
+               if (err)
+                       goto out;
 
                in_iov = page_address(iov_page);
                out_iov = in_iov + in_iovs;
 
+               err = fuse_verify_ioctl_iov(in_iov, in_iovs);
+               if (err)
+                       goto out;
+
+               err = fuse_verify_ioctl_iov(out_iov, out_iovs);
+               if (err)
+                       goto out;
+
                goto retry;
        }
 
index f0a384e2ae633a1dc2de619d102d5935ff32a273..996dd8989a9135203cab110f57e7c1f8df49e200 100644 (file)
@@ -57,7 +57,7 @@ static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
-static int nfs_readdir_clear_array(struct page*, gfp_t);
+static void nfs_readdir_clear_array(struct page*);
 
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
@@ -83,8 +83,8 @@ const struct inode_operations nfs_dir_inode_operations = {
        .setattr        = nfs_setattr,
 };
 
-const struct address_space_operations nfs_dir_addr_space_ops = {
-       .releasepage = nfs_readdir_clear_array,
+const struct address_space_operations nfs_dir_aops = {
+       .freepage = nfs_readdir_clear_array,
 };
 
 #ifdef CONFIG_NFS_V3
@@ -178,6 +178,7 @@ typedef struct {
        struct page     *page;
        unsigned long   page_index;
        u64             *dir_cookie;
+       u64             last_cookie;
        loff_t          current_index;
        decode_dirent_t decode;
 
@@ -213,17 +214,15 @@ void nfs_readdir_release_array(struct page *page)
  * we are freeing strings created by nfs_add_to_readdir_array()
  */
 static
-int nfs_readdir_clear_array(struct page *page, gfp_t mask)
+void nfs_readdir_clear_array(struct page *page)
 {
-       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       struct nfs_cache_array *array;
        int i;
 
-       if (IS_ERR(array))
-               return PTR_ERR(array);
+       array = kmap_atomic(page, KM_USER0);
        for (i = 0; i < array->size; i++)
                kfree(array->array[i].string.name);
-       nfs_readdir_release_array(page);
-       return 0;
+       kunmap_atomic(array, KM_USER0);
 }
 
 /*
@@ -272,7 +271,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
                goto out;
        array->last_cookie = entry->cookie;
        array->size++;
-       if (entry->eof == 1)
+       if (entry->eof != 0)
                array->eof_index = array->size;
 out:
        nfs_readdir_release_array(page);
@@ -312,15 +311,14 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
        for (i = 0; i < array->size; i++) {
                if (array->array[i].cookie == *desc->dir_cookie) {
                        desc->cache_entry_index = i;
-                       status = 0;
-                       goto out;
+                       return 0;
                }
        }
-       if (i == array->eof_index) {
-               desc->eof = 1;
+       if (array->eof_index >= 0) {
                status = -EBADCOOKIE;
+               if (*desc->dir_cookie == array->last_cookie)
+                       desc->eof = 1;
        }
-out:
        return status;
 }
 
@@ -328,10 +326,7 @@ static
 int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
 {
        struct nfs_cache_array *array;
-       int status = -EBADCOOKIE;
-
-       if (desc->dir_cookie == NULL)
-               goto out;
+       int status;
 
        array = nfs_readdir_get_array(desc->page);
        if (IS_ERR(array)) {
@@ -344,6 +339,10 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
        else
                status = nfs_readdir_search_for_cookie(array, desc);
 
+       if (status == -EAGAIN) {
+               desc->last_cookie = array->last_cookie;
+               desc->page_index++;
+       }
        nfs_readdir_release_array(desc->page);
 out:
        return status;
@@ -490,7 +489,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
 
                count++;
 
-               if (desc->plus == 1)
+               if (desc->plus != 0)
                        nfs_prime_dcache(desc->file->f_path.dentry, entry);
 
                status = nfs_readdir_add_to_array(entry, page);
@@ -498,7 +497,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
        } while (!entry->eof);
 
-       if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) {
+       if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
                array = nfs_readdir_get_array(page);
                if (!IS_ERR(array)) {
                        array->eof_index = array->size;
@@ -563,7 +562,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
        unsigned int array_size = ARRAY_SIZE(pages);
 
        entry.prev_cookie = 0;
-       entry.cookie = *desc->dir_cookie;
+       entry.cookie = desc->last_cookie;
        entry.eof = 0;
        entry.fh = nfs_alloc_fhandle();
        entry.fattr = nfs_alloc_fattr();
@@ -636,6 +635,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 static
 void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
+       if (!desc->page->mapping)
+               nfs_readdir_clear_array(desc->page);
        page_cache_release(desc->page);
        desc->page = NULL;
 }
@@ -660,9 +661,8 @@ int find_cache_page(nfs_readdir_descriptor_t *desc)
                return PTR_ERR(desc->page);
 
        res = nfs_readdir_search_array(desc);
-       if (res == 0)
-               return 0;
-       cache_page_release(desc);
+       if (res != 0)
+               cache_page_release(desc);
        return res;
 }
 
@@ -672,22 +672,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
        int res;
 
-       if (desc->page_index == 0)
+       if (desc->page_index == 0) {
                desc->current_index = 0;
-       while (1) {
-               res = find_cache_page(desc);
-               if (res != -EAGAIN)
-                       break;
-               desc->page_index++;
+               desc->last_cookie = 0;
        }
+       do {
+               res = find_cache_page(desc);
+       } while (res == -EAGAIN);
        return res;
 }
 
-static inline unsigned int dt_type(struct inode *inode)
-{
-       return (inode->i_mode >> 12) & 15;
-}
-
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -717,13 +711,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                        break;
                }
                file->f_pos++;
-               desc->cache_entry_index = i;
                if (i < (array->size-1))
                        *desc->dir_cookie = array->array[i+1].cookie;
                else
                        *desc->dir_cookie = array->last_cookie;
        }
-       if (i == array->eof_index)
+       if (array->eof_index >= 0)
                desc->eof = 1;
 
        nfs_readdir_release_array(desc->page);
@@ -764,6 +757,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        }
 
        desc->page_index = 0;
+       desc->last_cookie = *desc->dir_cookie;
        desc->page = page;
 
        status = nfs_readdir_xdr_to_array(desc, page, inode);
@@ -791,7 +785,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
-       int res = -ENOMEM;
+       int res;
 
        dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -816,7 +810,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        if (res < 0)
                goto out;
 
-       while (desc->eof != 1) {
+       do {
                res = readdir_search_pagecache(desc);
 
                if (res == -EBADCOOKIE) {
@@ -844,7 +838,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                res = nfs_do_filldir(desc, dirent, filldir);
                if (res < 0)
                        break;
-       }
+       } while (!desc->eof);
 out:
        nfs_unblock_sillyrename(dentry);
        if (res > 0)
index 60677f9f13110d1a98774595de819fddf2c0ccdf..7bf029ef4084c6e7f02e05e355382168e85e2cb8 100644 (file)
@@ -693,6 +693,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
+       unsigned int saved_type = fl->fl_type;
 
        /* Try local locking first */
        posix_test_lock(filp, fl);
@@ -700,6 +701,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
                /* found a conflict */
                goto out;
        }
+       fl->fl_type = saved_type;
 
        if (nfs_have_delegation(inode, FMODE_READ))
                goto out_noconflict;
index 314f57164602eda0762c0a226db44aa19be461f5..e67e31c734163c6fe6c0eef0d338a2b87ae55763 100644 (file)
@@ -289,6 +289,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                } else if (S_ISDIR(inode->i_mode)) {
                        inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
                        inode->i_fop = &nfs_dir_operations;
+                       inode->i_data.a_ops = &nfs_dir_aops;
                        if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
                                set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        /* Deal with crossing mountpoints */
index eceafe74f4737ea5fbcea90b8ac19749737667b9..4f981f1f668925cba6bebe6ed4cf485da6a56dbb 100644 (file)
@@ -505,13 +505,13 @@ static struct rpc_procinfo mnt3_procedures[] = {
 
 static struct rpc_version mnt_version1 = {
        .number         = 1,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt_procedures),
        .procs          = mnt_procedures,
 };
 
 static struct rpc_version mnt_version3 = {
        .number         = 3,
-       .nrprocs        = 2,
+       .nrprocs        = ARRAY_SIZE(mnt3_procedures),
        .procs          = mnt3_procedures,
 };
 
index 6a653ffd8e4e121e37c29d88ff2f5b0b4dbe264f..4435e5e1f904e3e5ba26f4eb578fc30c5f6d997b 100644 (file)
@@ -3361,6 +3361,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
        ret = nfs_revalidate_inode(server, inode);
        if (ret < 0)
                return ret;
+       if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
+               nfs_zap_acl_cache(inode);
        ret = nfs4_read_cached_acl(inode, buf, buflen);
        if (ret != -ENOENT)
                return ret;
@@ -3389,6 +3391,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
        nfs_inode_return_delegation(inode);
        buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
+       /*
+        * Acl update can result in inode attribute update.
+        * so mark the attribute cache invalid.
+        */
+       spin_lock(&inode->i_lock);
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
+       spin_unlock(&inode->i_lock);
        nfs_access_zap_cache(inode);
        nfs_zap_acl_cache(inode);
        return ret;
index 137b549e63dbcfa3971aac43091eb91a29a7b69f..b68536cc9046ec937b9b4ccddb98b2acf468f1db 100644 (file)
@@ -115,7 +115,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
 {
        if (!nfs_lock_request_dontget(req))
                return 0;
-       if (req->wb_page != NULL)
+       if (test_bit(PG_MAPPED, &req->wb_flags))
                radix_tree_tag_set(&NFS_I(req->wb_context->path.dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
        return 1;
 }
@@ -125,7 +125,7 @@ int nfs_set_page_tag_locked(struct nfs_page *req)
  */
 void nfs_clear_page_tag_locked(struct nfs_page *req)
 {
-       if (req->wb_page != NULL) {
+       if (test_bit(PG_MAPPED, &req->wb_flags)) {
                struct inode *inode = req->wb_context->path.dentry->d_inode;
                struct nfs_inode *nfsi = NFS_I(inode);
 
index e4b62c6f5a6e9eb721eda53d836c41055ab2e1b7..aedcaa7f291fbe4405f2b68c13f407c7de6be9ba 100644 (file)
@@ -152,7 +152,6 @@ static void nfs_readpage_release(struct nfs_page *req)
                        (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 3c045044fca25183147704f3689c744549ebd77b..4100630c9a5b65f47bb5379ee2bc62f78e60284e 100644 (file)
@@ -1069,12 +1069,10 @@ static int nfs_parse_mount_options(char *raw,
                        mnt->flags |= NFS_MOUNT_VER3;
                        mnt->version = 3;
                        break;
-#ifdef CONFIG_NFS_V4
                case Opt_v4:
                        mnt->flags &= ~NFS_MOUNT_VER3;
                        mnt->version = 4;
                        break;
-#endif
                case Opt_udp:
                        mnt->flags &= ~NFS_MOUNT_TCP;
                        mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
@@ -1286,12 +1284,10 @@ static int nfs_parse_mount_options(char *raw,
                                mnt->flags |= NFS_MOUNT_VER3;
                                mnt->version = 3;
                                break;
-#ifdef CONFIG_NFS_V4
                        case NFS4_VERSION:
                                mnt->flags &= ~NFS_MOUNT_VER3;
                                mnt->version = 4;
                                break;
-#endif
                        default:
                                goto out_invalid_value;
                        }
index 4c14c17a5276a410bb383e3650f106ab56cf47d6..10d648ea128bf6345df70da0e15ee8ce443ab8e6 100644 (file)
@@ -390,6 +390,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
                if (nfs_have_delegation(inode, FMODE_WRITE))
                        nfsi->change_attr++;
        }
+       set_bit(PG_MAPPED, &req->wb_flags);
        SetPagePrivate(req->wb_page);
        set_page_private(req->wb_page, (unsigned long)req);
        nfsi->npages++;
@@ -415,6 +416,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        spin_lock(&inode->i_lock);
        set_page_private(req->wb_page, 0);
        ClearPagePrivate(req->wb_page);
+       clear_bit(PG_MAPPED, &req->wb_flags);
        radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
        nfsi->npages--;
        if (!nfsi->npages) {
@@ -422,7 +424,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
                iput(inode);
        } else
                spin_unlock(&inode->i_lock);
-       nfs_clear_request(req);
        nfs_release_request(req);
 }
 
index 2a533a0af2a98ed91afb84e71669d328cb67a866..7e84a852cdae8117334fec6ee00d085fc29c0c66 100644 (file)
@@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp)
        err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
                        &fhp->fh_post_attr);
        fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
-       if (err)
+       if (err) {
                fhp->fh_post_saved = 0;
-       else
+               /* Grab the ctime anyway - set_change_info might use it */
+               fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
+       } else
                fhp->fh_post_saved = 1;
 }
 
index 4d476ff08ae6add1ec3a1b597909f1375af78b7b..60fce3dc5cb5d9f90d22b9f9c91ddc7ddeb9ff1d 100644 (file)
@@ -484,18 +484,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
 static inline void
 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
-       BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved);
-       cinfo->atomic = 1;
+       BUG_ON(!fhp->fh_pre_saved);
+       cinfo->atomic = fhp->fh_post_saved;
        cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
-       if (cinfo->change_supported) {
-               cinfo->before_change = fhp->fh_pre_change;
-               cinfo->after_change = fhp->fh_post_change;
-       } else {
-               cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
-               cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
-               cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
-               cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
-       }
+
+       cinfo->before_change = fhp->fh_pre_change;
+       cinfo->after_change = fhp->fh_post_change;
+       cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
+       cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
+       cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
+       cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
+
 }
 
 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
index d2af0a8381a63975e9668d1aa7babb942bd4f4e2..77a59891734e925318f4a91723f96eb55f7b5ae8 100644 (file)
@@ -297,6 +297,7 @@ xfs_rename(
         * it and some incremental backup programs won't work without it.
         */
        xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG);
+       xfs_trans_log_inode(tp, src_ip, XFS_ILOG_CORE);
 
        /*
         * Adjust the link count on src_dp.  This is necessary when
index 551793c9b6e8c25b2b1d3e36a4fe8ffcb4a0f24a..0e98e679d3a749cfda3898c2fe59f82d18ca87c3 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef __ACPI_VIDEO_H
 #define __ACPI_VIDEO_H
 
+#include <linux/errno.h> /* for ENODEV */
+
+struct acpi_device;
+
 #define ACPI_VIDEO_DISPLAY_CRT  1
 #define ACPI_VIDEO_DISPLAY_TV   2
 #define ACPI_VIDEO_DISPLAY_DVI  3
@@ -26,4 +30,3 @@ static inline int acpi_video_get_edid(struct acpi_device *device, int type,
 #endif
 
 #endif
-
index 050a7bccb8365ef117f365ebe3d3a8d337efc390..67c91b4418b06e59ea9de82e0c67dfb4cc5a7554 100644 (file)
@@ -219,7 +219,7 @@ static inline int acpi_video_display_switch_support(void)
 
 extern int acpi_blacklisted(void);
 extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d);
-extern int acpi_osi_setup(char *str);
+extern void acpi_osi_setup(char *str);
 
 #ifdef CONFIG_ACPI_NUMA
 int acpi_get_pxm(acpi_handle handle);
index c9e06cc70dad585c6c185db2d1503d3fad4a5a48..090f0eacde296ec52a06fe5eb1b13c07808b7ada 100644 (file)
@@ -602,6 +602,7 @@ struct address_space_operations {
        sector_t (*bmap)(struct address_space *, sector_t);
        void (*invalidatepage) (struct page *, unsigned long);
        int (*releasepage) (struct page *, gfp_t);
+       void (*freepage)(struct page *);
        ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
        int (*get_xip_mem)(struct address_space *, pgoff_t, int,
index 5c51f367c0610166bbf6ec12d6fedc7587d7420e..add8a1b8bcf0057c3f328c51dc96a4d82ae331a5 100644 (file)
@@ -29,7 +29,7 @@ struct wm8994_ldo_pdata {
 #define WM8994_CONFIGURE_GPIO 0x8000
 
 #define WM8994_DRC_REGS 5
-#define WM8994_EQ_REGS  19
+#define WM8994_EQ_REGS  20
 
 /**
  * DRC configurations are specified with a label and a set of register
index c66fdb7d6998129701f6eaa653f1d28dd641e332..29d504d5d1c31f5698433657dd534c1500f317b2 100644 (file)
@@ -401,6 +401,7 @@ extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
 extern const struct address_space_operations nfs_file_aops;
+extern const struct address_space_operations nfs_dir_aops;
 
 static inline struct nfs_open_context *nfs_file_open_context(struct file *filp)
 {
index f8b60e7f4c44d9b652a94bca2ab8945130bdb061..d55cee73f63477a326b73cf7eb15e3e277567b14 100644 (file)
@@ -29,6 +29,7 @@
  */
 enum {
        PG_BUSY = 0,
+       PG_MAPPED,
        PG_CLEAN,
        PG_NEED_COMMIT,
        PG_NEED_RESCHED,
index 2fb46bc9340d9b40617042ba8bb253754e4b6f67..ed5cdeb3604dbe6ea1fe807b33a69bf140d1622a 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef _LINUX_VIDEO_OUTPUT_H
 #define _LINUX_VIDEO_OUTPUT_H
 #include <linux/device.h>
+#include <linux/err.h>
 struct output_device;
 struct output_properties {
        int (*set_state)(struct output_device *);
@@ -34,9 +35,23 @@ struct output_device {
        struct device dev;
 };
 #define to_output_device(obj) container_of(obj, struct output_device, dev)
+#if    defined(CONFIG_VIDEO_OUTPUT_CONTROL) || defined(CONFIG_VIDEO_OUTPUT_CONTROL_MODULE)
 struct output_device *video_output_register(const char *name,
        struct device *dev,
        void *devdata,
        struct output_properties *op);
 void video_output_unregister(struct output_device *dev);
+#else
+static struct output_device *video_output_register(const char *name,
+        struct device *dev,
+        void *devdata,
+        struct output_properties *op)
+{
+       return ERR_PTR(-ENODEV);
+}
+static void video_output_unregister(struct output_device *dev)
+{
+       return;
+}
+#endif
 #endif
index ea89840fc65fa2b499ce3c19c657e9e8a680b240..6b9aee20f2426b88024a25749402fc5ca1ff7a0a 100644 (file)
@@ -143,13 +143,18 @@ void __remove_from_page_cache(struct page *page)
 void remove_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
+       void (*freepage)(struct page *);
 
        BUG_ON(!PageLocked(page));
 
+       freepage = mapping->a_ops->freepage;
        spin_lock_irq(&mapping->tree_lock);
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (freepage)
+               freepage(page);
 }
 EXPORT_SYMBOL(remove_from_page_cache);
 
index ba887bff48c5a263c315a6ef098284df4df5bb44..3c2d5ddfa0d49f3cf31449e214d8fbd50e92ad08 100644 (file)
@@ -390,6 +390,10 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
        mem_cgroup_uncharge_cache_page(page);
+
+       if (mapping->a_ops->freepage)
+               mapping->a_ops->freepage(page);
+
        page_cache_release(page);       /* pagecache ref */
        return 1;
 failed:
index d31d7ce52c0ea2dbbf85b26019c9fdd70fab624a..9ca587c692748adbc715b440ff5aa8c89357c511 100644 (file)
@@ -494,9 +494,16 @@ static int __remove_mapping(struct address_space *mapping, struct page *page)
                spin_unlock_irq(&mapping->tree_lock);
                swapcache_free(swap, page);
        } else {
+               void (*freepage)(struct page *);
+
+               freepage = mapping->a_ops->freepage;
+
                __remove_from_page_cache(page);
                spin_unlock_irq(&mapping->tree_lock);
                mem_cgroup_uncharge_cache_page(page);
+
+               if (freepage != NULL)
+                       freepage(page);
        }
 
        return 1;
index ea2ff78dcf7b7ec4f2555210af82379017e6e291..3f2c5559ca1a49a496b9d531625c1e175fb029c8 100644 (file)
@@ -212,6 +212,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
        spin_lock(&svc_xprt_class_lock);
        list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
                struct svc_xprt *newxprt;
+               unsigned short newport;
 
                if (strcmp(xprt_name, xcl->xcl_name))
                        continue;
@@ -230,8 +231,9 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                spin_lock_bh(&serv->sv_lock);
                list_add(&newxprt->xpt_list, &serv->sv_permsocks);
                spin_unlock_bh(&serv->sv_lock);
+               newport = svc_xprt_local_port(newxprt);
                clear_bit(XPT_BUSY, &newxprt->xpt_flags);
-               return svc_xprt_local_port(newxprt);
+               return newport;
        }
  err:
        spin_unlock(&svc_xprt_class_lock);
@@ -425,8 +427,13 @@ void svc_xprt_received(struct svc_xprt *xprt)
 {
        BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags));
        xprt->xpt_pool = NULL;
+       /* As soon as we clear busy, the xprt could be closed and
+        * 'put', so we need a reference to call svc_xprt_enqueue with:
+        */
+       svc_xprt_get(xprt);
        clear_bit(XPT_BUSY, &xprt->xpt_flags);
        svc_xprt_enqueue(xprt);
+       svc_xprt_put(xprt);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_received);
 
index cb0c23a6b473e07bd9d768f9430e7cde2342639c..4a663471dadc1e1e00d712bd5656577aeba56984 100644 (file)
@@ -189,6 +189,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
        a->channels = GRAB_BITS(buf, 0, 0, 3);
        a->channels++;
 
+       a->sample_bits = 0;
+       a->max_bitrate = 0;
+
        a->format = GRAB_BITS(buf, 0, 3, 4);
        switch (a->format) {
        case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
@@ -198,7 +201,6 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 
        case AUDIO_CODING_TYPE_LPCM:
                val = GRAB_BITS(buf, 2, 0, 3);
-               a->sample_bits = 0;
                for (i = 0; i < 3; i++)
                        if (val & (1 << i))
                                a->sample_bits |= cea_sample_sizes[i + 1];
@@ -598,24 +600,19 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
 {
        int i;
 
-       pcm->rates = 0;
-       pcm->formats = 0;
-       pcm->maxbps = 0;
-       pcm->channels_min = -1;
-       pcm->channels_max = 0;
+       /* assume basic audio support (the basic audio flag is not in ELD;
+        * however, all audio capable sinks are required to support basic
+        * audio) */
+       pcm->rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+       pcm->formats = SNDRV_PCM_FMTBIT_S16_LE;
+       pcm->maxbps = 16;
+       pcm->channels_max = 2;
        for (i = 0; i < eld->sad_count; i++) {
                struct cea_sad *a = &eld->sad[i];
                pcm->rates |= a->rates;
-               if (a->channels < pcm->channels_min)
-                       pcm->channels_min = a->channels;
                if (a->channels > pcm->channels_max)
                        pcm->channels_max = a->channels;
                if (a->format == AUDIO_CODING_TYPE_LPCM) {
-                       if (a->sample_bits & AC_SUPPCM_BITS_16) {
-                               pcm->formats |= SNDRV_PCM_FMTBIT_S16_LE;
-                               if (pcm->maxbps < 16)
-                                       pcm->maxbps = 16;
-                       }
                        if (a->sample_bits & AC_SUPPCM_BITS_20) {
                                pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
                                if (pcm->maxbps < 20)
@@ -635,7 +632,6 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
        /* restrict the parameters by the values the codec provides */
        pcm->rates &= codec_pars->rates;
        pcm->formats &= codec_pars->formats;
-       pcm->channels_min = max(pcm->channels_min, codec_pars->channels_min);
        pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
        pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
 }
index 21aa9b0e28f6cb466a81a4d1e4c48622c71f89c9..b030c8eba21fdc618fe0b5bfb32cf5b156c39bba 100644 (file)
@@ -2296,6 +2296,7 @@ static int azx_dev_free(struct snd_device *device)
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1025, 0x026f, "Acer Aspire 5538", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
index 846d1ead47fdf1c184fb92f37ae1faf099ec45af..76bd58a0e2b637e2c17a79cc94ab54e0747de227 100644 (file)
@@ -2116,8 +2116,8 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        struct conexant_spec *spec = codec->spec;
        unsigned int pinctl;
 
-       snd_printdd("CXT5066: update speaker, hp_present=%d\n",
-               spec->hp_present);
+       snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
+                   spec->hp_present, spec->cur_eapd);
 
        /* Port A (HP) */
        pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
@@ -2125,11 +2125,20 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
                        pinctl);
 
        /* Port D (HP/LO) */
-       pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
-               ? spec->port_d_mode : 0;
-       /* Mute if Port A is connected on Thinkpad */
-       if (spec->thinkpad && (spec->hp_present & 1))
-               pinctl = 0;
+       if (spec->dell_automute) {
+               /* DELL AIO Port Rule: PortA>  PortD>  IntSpk */
+               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
+                       ? PIN_OUT : 0;
+       } else if (spec->thinkpad) {
+               if (spec->cur_eapd)
+                       pinctl = spec->port_d_mode;
+               /* Mute dock line-out if Port A (laptop HP) is present */
+               if (spec->hp_present&  1)
+                       pinctl = 0;
+       } else {
+               pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
+                       ? spec->port_d_mode : 0;
+       }
        snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
 
@@ -2137,14 +2146,6 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
        pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
        snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
                        pinctl);
-
-       if (spec->dell_automute) {
-               /* DELL AIO Port Rule: PortA > PortD > IntSpk */
-               pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
-                       ? PIN_OUT : 0;
-               snd_hda_codec_write(codec, 0x1c, 0,
-                       AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
-       }
 }
 
 /* turn on/off EAPD (+ mute HP) as a master switch */
@@ -3095,8 +3096,7 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
-       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
-                     CXT5066_DELL_LAPTOP),
+       SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
@@ -3109,6 +3109,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD),
index d3e49aa5b9ecd42f6db6f5892319e6602ad9b7ab..31df7747990d0be6690a520321a0498c9caba349 100644 (file)
@@ -834,7 +834,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
                        return -ENODEV;
        } else {
                /* fallback to the codec default */
-               hinfo->channels_min = codec_pars->channels_min;
                hinfo->channels_max = codec_pars->channels_max;
                hinfo->rates = codec_pars->rates;
                hinfo->formats = codec_pars->formats;
index 8fddc9d08726670c8d67dc1ce9f31dd1f82a56c4..2d7d7de8498a7947bb9c6180bc757017535c343c 100644 (file)
@@ -4595,6 +4595,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
        SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
        SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
+       SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
        SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
        SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
index a2e0ed59b3769f0b7d73024a6e4740338b1ccb81..879dff2714dd3c522211dbac3c636a5191d8ce4b 100644 (file)
@@ -491,16 +491,16 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
                paifa |= 0x8;
                break;
        case SNDRV_PCM_FORMAT_S20_3LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_20;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
-               paifa |= 0x10;
+               paifa |= 0x0;
                paifb |= WM8580_AIF_LENGTH_24;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
-               paifa |= 0x10;
-               paifb |= WM8580_AIF_LENGTH_24;
+               paifa |= 0x0;
+               paifb |= WM8580_AIF_LENGTH_32;
                break;
        default:
                return -EINVAL;
index e8092745a207674caaf4351d815870e7367b4003..1304ca91a11c708c567f69c45052c95f1f7be17e 100644 (file)
@@ -3339,7 +3339,7 @@ static irqreturn_t wm8962_irq(int irq, void *data)
        int mask;
        int active;
 
-       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
 
        active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
        active &= ~mask;
index 19ca782ac970f1956243862534e5df1df12a3113..0e24092722c39522d85980a71f8a3727d01cf63f 100644 (file)
@@ -293,7 +293,7 @@ SOC_DOUBLE_R("Speaker Switch",
 SOC_DOUBLE_R("Speaker ZC Switch",
             WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
             7, 1, 0),
-SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
+SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
               spkboost_tlv),
 SOC_ENUM("Speaker Reference", speaker_ref),
 SOC_ENUM("Speaker Mode", speaker_mode),
index 441285ade024ff33589cd22204ef5cb82a1f14ea..85b7d548f1675f14c1a2065bbcffcf7d229a2e27 100644 (file)
@@ -1619,12 +1619,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 #ifdef CONFIG_SND_SOC_AC97_BUS
        /* register any AC97 codecs */
        for (i = 0; i < card->num_rtd; i++) {
-                       ret = soc_register_ac97_dai_link(&card->rtd[i]);
-                       if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
-                               goto probe_dai_err;
-                       }
+               ret = soc_register_ac97_dai_link(&card->rtd[i]);
+               if (ret < 0) {
+                       printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+                       while (--i >= 0)
+                               soc_unregister_ac97_dai_link(&card->rtd[i]);
+                       goto probe_dai_err;
                }
+       }
 #endif
 
        card->instantiated = 1;
@@ -3072,7 +3074,9 @@ int snd_soc_register_dais(struct device *dev,
                pr_debug("Registered DAI '%s'\n", dai->name);
        }
 
+       mutex_lock(&client_mutex);
        snd_soc_instantiate_cards();
+       mutex_unlock(&client_mutex);
        return 0;
 
 err: