Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Mar 2009 17:24:39 +0000 (10:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Mar 2009 17:24:39 +0000 (10:24 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6: (28 commits)
  Blackfin arch: SPI_MMC is now mainlined MMC_SPI
  Blackfin arch: disable legacy /proc/scsi/ support by default
  Blackfin arch: remove duplicated ANOMALY_05000448 ifdef check
  Blackfin arch: add stubs for anomalies 447 and 448
  Blackfin arch: cleanup bfin_sport.h header and export it to userspace
  Blackfin arch: fix bug - gdb signull case make trunk kernel panic frequently
  Blackfin arch: remove spurious dash when dcache is off
  Blackfin arch: mark init_pda as __init as only __init funcs all it
  Blackfin arch: fix bug - On bf548-ezkit, ethernet fails to work after wakeup from "mem"
  Blackfin arch: Random read/write errors are a bad thing
  Blackfin arch: update default kernel config, select KSZ8893M driver for BF518
  Blackfin arch: Fix bug - KGDB single step into the middle of a 4 bytes instruction on bf561 after soft bp is hit
  Blackfin arch: Fix bug - make ksz8893m driver available when bfin_mac is enabled
  Blackfin arch: make sure people do not set the kernel load address too high
  Blackfin arch: fix bug - The SPORT_HYS bit is not set for BF561 0.5
  Blackfin arch: update anomaly sheets to match latest public info
  Blackfin arch: Fix BUG - kernel fails to build in pm.c when allow wakeup fromi standby by GPIO
  Blackfin arch: PM_BFIN_WAKE_GP: update help
  Blackfin arch: fix bug - kgdb fails to continue after setting breakpoint on bf561-ezkit kernel with smp patch
  Blackfin arch: Enable Write Back Cache on all Blackfin Boards
  ...

49 files changed:
Documentation/filesystems/squashfs.txt
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/include/mach/board.h
arch/ia64/sn/pci/pcibr/pcibr_dma.c
arch/mips/include/asm/compat.h
block/blk-merge.c
drivers/ata/ahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/sata_nv.c
drivers/block/cciss.c
drivers/block/loop.c
drivers/block/xen-blkfront.c
drivers/dca/dca-core.c
drivers/dma/dmatest.c
drivers/dma/fsldma.c
drivers/dma/ioat.c
drivers/dma/ioat_dca.c
drivers/dma/ioat_dma.c
drivers/dma/ioatdma.h
drivers/dma/ioatdma_hw.h
drivers/dma/ioatdma_registers.h
drivers/dma/iop-adma.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/mv_xor.c
drivers/ide/Kconfig
drivers/ide/Makefile
drivers/ide/at91_ide.c [new file with mode: 0644]
drivers/ide/ide-disk_proc.c
drivers/ide/ide-floppy_proc.c
drivers/ide/ide-io.c
drivers/ide/ide-iops.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
fs/squashfs/block.c
fs/squashfs/cache.c
fs/squashfs/inode.c
fs/squashfs/squashfs.h
fs/squashfs/super.c
include/linux/ata.h
include/linux/dmaengine.h
include/linux/hdreg.h
include/linux/ide.h
include/linux/libata.h
include/linux/serio.h
security/smack/smack_lsm.c
security/smack/smackfs.c
sound/pci/hda/patch_sigmatel.c

index 3e79e4a7a3920ac659ad2b3b76ed339aaf04e9f3..b324c033035ad097fda59b86897ae0720df9f09b 100644 (file)
@@ -22,7 +22,7 @@ Squashfs filesystem features versus Cramfs:
 
                                Squashfs                Cramfs
 
-Max filesystem size:           2^64                    16 MiB
+Max filesystem size:           2^64                    256 MiB
 Max file size:                 ~ 2 TiB                 16 MiB
 Max files:                     unlimited               unlimited
 Max directories:               unlimited               unlimited
index 134af97ff3403f1c309b4b6c962665c860fa796d..b7f23324231560635b0d053ac7fac703a249e19f 100644 (file)
@@ -347,6 +347,111 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
 void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  Compact Flash (PCMCIA or IDE)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) || \
+    defined(CONFIG_BLK_DEV_IDE_AT91) || defined(CONFIG_BLK_DEV_IDE_AT91_MODULE)
+
+static struct at91_cf_data cf0_data;
+
+static struct resource cf0_resources[] = {
+       [0] = {
+               .start  = AT91_CHIPSELECT_4,
+               .end    = AT91_CHIPSELECT_4 + SZ_256M - 1,
+               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+       }
+};
+
+static struct platform_device cf0_device = {
+       .id             = 0,
+       .dev            = {
+                               .platform_data  = &cf0_data,
+       },
+       .resource       = cf0_resources,
+       .num_resources  = ARRAY_SIZE(cf0_resources),
+};
+
+static struct at91_cf_data cf1_data;
+
+static struct resource cf1_resources[] = {
+       [0] = {
+               .start  = AT91_CHIPSELECT_5,
+               .end    = AT91_CHIPSELECT_5 + SZ_256M - 1,
+               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+       }
+};
+
+static struct platform_device cf1_device = {
+       .id             = 1,
+       .dev            = {
+                               .platform_data  = &cf1_data,
+       },
+       .resource       = cf1_resources,
+       .num_resources  = ARRAY_SIZE(cf1_resources),
+};
+
+void __init at91_add_device_cf(struct at91_cf_data *data)
+{
+       unsigned long ebi0_csa;
+       struct platform_device *pdev;
+
+       if (!data)
+               return;
+
+       /*
+        * assign CS4 or CS5 to SMC with Compact Flash logic support,
+        * we assume SMC timings are configured by board code,
+        * except True IDE where timings are controlled by driver
+        */
+       ebi0_csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
+       switch (data->chipselect) {
+       case 4:
+               at91_set_A_periph(AT91_PIN_PD6, 0);  /* EBI0_NCS4/CFCS0 */
+               ebi0_csa |= AT91_MATRIX_EBI0_CS4A_SMC_CF1;
+               cf0_data = *data;
+               pdev = &cf0_device;
+               break;
+       case 5:
+               at91_set_A_periph(AT91_PIN_PD7, 0);  /* EBI0_NCS5/CFCS1 */
+               ebi0_csa |= AT91_MATRIX_EBI0_CS5A_SMC_CF2;
+               cf1_data = *data;
+               pdev = &cf1_device;
+               break;
+       default:
+               printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n",
+                      data->chipselect);
+               return;
+       }
+       at91_sys_write(AT91_MATRIX_EBI0CSA, ebi0_csa);
+
+       if (data->det_pin) {
+               at91_set_gpio_input(data->det_pin, 1);
+               at91_set_deglitch(data->det_pin, 1);
+       }
+
+       if (data->irq_pin) {
+               at91_set_gpio_input(data->irq_pin, 1);
+               at91_set_deglitch(data->irq_pin, 1);
+       }
+
+       if (data->vcc_pin)
+               /* initially off */
+               at91_set_gpio_output(data->vcc_pin, 0);
+
+       /* enable EBI controlled pins */
+       at91_set_A_periph(AT91_PIN_PD5, 1);  /* NWAIT */
+       at91_set_A_periph(AT91_PIN_PD8, 0);  /* CFCE1 */
+       at91_set_A_periph(AT91_PIN_PD9, 0);  /* CFCE2 */
+       at91_set_A_periph(AT91_PIN_PD14, 0); /* CFNRW */
+
+       pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "at91_ide" : "at91_cf";
+       platform_device_register(pdev);
+}
+#else
+void __init at91_add_device_cf(struct at91_cf_data *data) {}
+#endif
 
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
index 0b3ae21b4565abb471fbedd59c15c96a3e4450f5..793fe7b25f367653292110e5936c1c8b4bcdc3d8 100644 (file)
@@ -56,6 +56,9 @@ struct at91_cf_data {
        u8      vcc_pin;                /* power switching */
        u8      rst_pin;                /* card reset */
        u8      chipselect;             /* EBI Chip Select number */
+       u8      flags;
+#define AT91_CF_TRUE_IDE       0x01
+#define AT91_IDE_SWAP_A0_A2    0x02
 };
 extern void __init at91_add_device_cf(struct at91_cf_data *data);
 
index e626e50a938a3ce91b2d9926f06d036d63f29609..060df4aa9916853297a0be09d4221c5a95e37654 100644 (file)
@@ -135,11 +135,10 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
        if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
                pci_addr = IS_PIC_SOFT(pcibus_info) ?
                                PHYS_TO_DMA(paddr) :
-                               PHYS_TO_TIODMA(paddr) | dma_attributes;
+                               PHYS_TO_TIODMA(paddr);
        else
-               pci_addr = IS_PIC_SOFT(pcibus_info) ?
-                               paddr :
-                               paddr | dma_attributes;
+               pci_addr = paddr;
+       pci_addr |= dma_attributes;
 
        /* Handle Bus mode */
        if (IS_PCIX(pcibus_info))
index ac5d541368e934a30ca17ac03e58bd990b9eb7ca..6c5b40905dd66daff610de074e5f17f7dd17fc8d 100644 (file)
@@ -3,6 +3,8 @@
 /*
  * Architecture specific compatibility types
  */
+#include <linux/seccomp.h>
+#include <linux/thread_info.h>
 #include <linux/types.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -218,4 +220,9 @@ struct compat_shmid64_ds {
        compat_ulong_t  __unused2;
 };
 
+static inline int is_compat_task(void)
+{
+       return test_thread_flag(TIF_32BIT);
+}
+
 #endif /* _ASM_COMPAT_H */
index a104593e70c38cdfdaebc1cf1214934e37ce3284..5a244f05360f5ca67592e29a7270f3874bf16c37 100644 (file)
@@ -39,14 +39,13 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect)
 }
 
 static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
-                                            struct bio *bio,
-                                            unsigned int *seg_size_ptr)
+                                            struct bio *bio)
 {
        unsigned int phys_size;
        struct bio_vec *bv, *bvprv = NULL;
        int cluster, i, high, highprv = 1;
        unsigned int seg_size, nr_phys_segs;
-       struct bio *fbio;
+       struct bio *fbio, *bbio;
 
        if (!bio)
                return 0;
@@ -87,26 +86,20 @@ new_segment:
                        seg_size = bv->bv_len;
                        highprv = high;
                }
+               bbio = bio;
        }
 
-       if (seg_size_ptr)
-               *seg_size_ptr = seg_size;
+       if (nr_phys_segs == 1 && seg_size > fbio->bi_seg_front_size)
+               fbio->bi_seg_front_size = seg_size;
+       if (seg_size > bbio->bi_seg_back_size)
+               bbio->bi_seg_back_size = seg_size;
 
        return nr_phys_segs;
 }
 
 void blk_recalc_rq_segments(struct request *rq)
 {
-       unsigned int seg_size = 0, phys_segs;
-
-       phys_segs = __blk_recalc_rq_segments(rq->q, rq->bio, &seg_size);
-
-       if (phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
-               rq->bio->bi_seg_front_size = seg_size;
-       if (seg_size > rq->biotail->bi_seg_back_size)
-               rq->biotail->bi_seg_back_size = seg_size;
-
-       rq->nr_phys_segments = phys_segs;
+       rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio);
 }
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
@@ -114,7 +107,7 @@ void blk_recount_segments(struct request_queue *q, struct bio *bio)
        struct bio *nxt = bio->bi_next;
 
        bio->bi_next = NULL;
-       bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, NULL);
+       bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio);
        bio->bi_next = nxt;
        bio->bi_flags |= (1 << BIO_SEG_VALID);
 }
index a603bbf9b1b706caf37a15b94eb8b6ecb4a3e8dc..66e012cd3271f98cc8541c95ca13fb327b4dd7c7 100644 (file)
@@ -582,18 +582,18 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci },            /* MCP79 */
        { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci },            /* MCP79 */
        { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci },            /* MCP79 */
-       { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci },            /* MCP7B */
-       { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci },            /* MCP7B */
+       { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci },            /* MCP89 */
+       { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci },            /* MCP89 */
 
        /* SiS */
        { PCI_VDEVICE(SI, 0x1184), board_ahci },                /* SiS 966 */
index 9fbf0595f3d44fd3f51d1339c9bbe127db7fa698..060bcd601f5758d63ae95e017fe7f501c8dd0607 100644 (file)
@@ -1322,14 +1322,16 @@ static u64 ata_id_n_sectors(const u16 *id)
 {
        if (ata_id_has_lba(id)) {
                if (ata_id_has_lba48(id))
-                       return ata_id_u64(id, 100);
+                       return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
                else
-                       return ata_id_u32(id, 60);
+                       return ata_id_u32(id, ATA_ID_LBA_CAPACITY);
        } else {
                if (ata_id_current_chs_valid(id))
-                       return ata_id_u32(id, 57);
+                       return id[ATA_ID_CUR_CYLS] * id[ATA_ID_CUR_HEADS] *
+                              id[ATA_ID_CUR_SECTORS];
                else
-                       return id[1] * id[3] * id[6];
+                       return id[ATA_ID_CYLS] * id[ATA_ID_HEADS] *
+                              id[ATA_ID_SECTORS];
        }
 }
 
@@ -4612,7 +4614,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
        VPRINTK("unmapping %u sg elements\n", qc->n_elem);
 
        if (qc->n_elem)
-               dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
+               dma_unmap_sg(ap->dev, sg, qc->orig_n_elem, dir);
 
        qc->flags &= ~ATA_QCFLAG_DMAMAP;
        qc->sg = NULL;
@@ -4727,7 +4729,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
                return -1;
 
        DPRINTK("%d sg elements mapped\n", n_elem);
-
+       qc->orig_n_elem = qc->n_elem;
        qc->n_elem = n_elem;
        qc->flags |= ATA_QCFLAG_DMAMAP;
 
index ce2ef04753390b2c95dacd591662efd3c1800ebb..ea890911d4fa3f67863b8f52e7aebc258b4ce7e7 100644 (file)
@@ -2423,11 +2423,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
                }
 
                /* prereset() might have cleared ATA_EH_RESET.  If so,
-                * bang classes and return.
+                * bang classes, thaw and return.
                 */
                if (reset && !(ehc->i.action & ATA_EH_RESET)) {
                        ata_for_each_dev(dev, link, ALL)
                                classes[dev->devno] = ATA_DEV_NONE;
+                       if ((ap->pflags & ATA_PFLAG_FROZEN) &&
+                           ata_is_host_link(link))
+                               ata_eh_thaw_port(ap);
                        rc = 0;
                        goto out;
                }
@@ -2901,7 +2904,7 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
        int i;
 
        for (i = 0; i < ATA_EH_UA_TRIES; i++) {
-               u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+               u8 *sense_buffer = dev->link->ap->sector_buf;
                u8 sense_key = 0;
                unsigned int err_mask;
 
index 55a8eed3f3a35cb9fa64b9e67800a40d72d5d062..f65b53785a8f93f304cfddc4261491ab7c37a090 100644 (file)
@@ -2523,7 +2523,7 @@ static void __exit nv_exit(void)
 module_init(nv_init);
 module_exit(nv_exit);
 module_param_named(adma, adma_enabled, bool, 0444);
-MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
+MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
 module_param_named(swncq, swncq_enabled, bool, 0444);
 MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
 
index b5a06111463018b5d93f3d2b944caf9c60654281..4f9b6d7920173d19f85dc0cb822c3e33d87b1db9 100644 (file)
@@ -3606,11 +3606,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
                if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev))
                        return -ENODEV;
 
-               /* Some devices (notably the HP Smart Array 5i Controller)
-                  need a little pause here */
-               schedule_timeout_uninterruptible(30*HZ);
-
-               /* Now try to get the controller to respond to a no-op */
+               /* Now try to get the controller to respond to a no-op. Some
+                  devices (notably the HP Smart Array 5i Controller) need
+                  up to 30 seconds to respond. */
                for (i=0; i<30; i++) {
                        if (cciss_noop(pdev) == 0)
                                break;
index edbaac6c05739ab183e69f94c1dc230acea27176..bf034557767243ecbb0fd3c56538f7877e222345 100644 (file)
@@ -392,8 +392,7 @@ lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
        struct loop_device *lo = p->lo;
        struct page *page = buf->page;
        sector_t IV;
-       size_t size;
-       int ret;
+       int size, ret;
 
        ret = buf->ops->confirm(pipe, buf);
        if (unlikely(ret))
index b6c8ce25435994558885e9e4b9c4ac6aafaa9357..8f905089b72b7e49c2434d1b6abba9fa76321051 100644 (file)
@@ -977,6 +977,8 @@ static void backend_changed(struct xenbus_device *dev,
                break;
 
        case XenbusStateClosing:
+               if (info->gd == NULL)
+                       xenbus_dev_fatal(dev, -ENODEV, "gd is NULL");
                bd = bdget_disk(info->gd, 0);
                if (bd == NULL)
                        xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
index 33bd7534751820841d19732a5d5e79b4dea9adbf..25b743abfb59442b52ccec0057573716249bdbbf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
index 732fa1ec36ab3ae885b784ca1ea5bb863cc3c58f..e190d8b30700c40858fceb83afa05f49d9ce8d2e 100644 (file)
@@ -430,13 +430,15 @@ late_initcall(dmatest_init);
 static void __exit dmatest_exit(void)
 {
        struct dmatest_chan *dtc, *_dtc;
+       struct dma_chan *chan;
 
        list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
                list_del(&dtc->node);
+               chan = dtc->chan;
                dmatest_cleanup_channel(dtc);
                pr_debug("dmatest: dropped channel %s\n",
-                        dma_chan_name(dtc->chan));
-               dma_release_channel(dtc->chan);
+                        dma_chan_name(chan));
+               dma_release_channel(chan);
        }
 }
 module_exit(dmatest_exit);
index 70126a60623939dddc6af7a59aa7b1eac8a51637..86d6da47f558765736149344b2c595b13a289f3f 100644 (file)
@@ -158,7 +158,8 @@ static void dma_start(struct fsl_dma_chan *fsl_chan)
 
 static void dma_halt(struct fsl_dma_chan *fsl_chan)
 {
-       int i = 0;
+       int i;
+
        DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
                DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA,
                32);
@@ -166,8 +167,11 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan)
                DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS
                | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32);
 
-       while (!dma_is_idle(fsl_chan) && (i++ < 100))
+       for (i = 0; i < 100; i++) {
+               if (dma_is_idle(fsl_chan))
+                       break;
                udelay(10);
+       }
        if (i >= 100 && !dma_is_idle(fsl_chan))
                dev_err(fsl_chan->dev, "DMA halt timeout!\n");
 }
index 4105d6575b645dc7674c35ea5bca0c60bde89d9f..ed83dd9df192a5a4b65d5f1f15b3e1e2349178b3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Intel I/OAT DMA Linux driver
- * Copyright(c) 2007 Intel Corporation.
+ * Copyright(c) 2007 - 2009 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
index 6cf622da0286481fccb32a73285c72c83fb6a57b..c012a1e150431972649b10a502cf658f9a71320b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Intel I/OAT DMA Linux driver
- * Copyright(c) 2007 Intel Corporation.
+ * Copyright(c) 2007 - 2009 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
 
 #define DCA_TAG_MAP_MASK 0xDF
 
+/* expected tag map bytes for I/OAT ver.2 */
+#define DCA2_TAG_MAP_BYTE0 0x80
+#define DCA2_TAG_MAP_BYTE1 0x0
+#define DCA2_TAG_MAP_BYTE2 0x81
+#define DCA2_TAG_MAP_BYTE3 0x82
+#define DCA2_TAG_MAP_BYTE4 0x82
+
+/* verify if tag map matches expected values */
+static inline int dca2_tag_map_valid(u8 *tag_map)
+{
+       return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) &&
+               (tag_map[1] == DCA2_TAG_MAP_BYTE1) &&
+               (tag_map[2] == DCA2_TAG_MAP_BYTE2) &&
+               (tag_map[3] == DCA2_TAG_MAP_BYTE3) &&
+               (tag_map[4] == DCA2_TAG_MAP_BYTE4));
+}
+
 /*
  * "Legacy" DCA systems do not implement the DCA register set in the
  * I/OAT device.  Software needs direct support for their tag mappings.
@@ -452,6 +469,13 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase)
                        ioatdca->tag_map[i] = 0;
        }
 
+       if (!dca2_tag_map_valid(ioatdca->tag_map)) {
+               dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, "
+                       "disabling DCA\n");
+               free_dca_provider(dca);
+               return NULL;
+       }
+
        err = register_dca_provider(dca, &pdev->dev);
        if (err) {
                free_dca_provider(dca);
index b3759c4b65360c0c3b72664c0a675887474f041e..5905cd36bcd23b43b86dcc532a1a70cc5ce5ce58 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Intel I/OAT DMA Linux driver
- * Copyright(c) 2004 - 2007 Intel Corporation.
+ * Copyright(c) 2004 - 2009 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -189,11 +189,13 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
                ioat_chan->xfercap = xfercap;
                ioat_chan->desccount = 0;
                INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2);
-               if (ioat_chan->device->version != IOAT_VER_1_2) {
-                       writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
-                                       | IOAT_DMA_DCA_ANY_CPU,
-                               ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
-               }
+               if (ioat_chan->device->version == IOAT_VER_2_0)
+                       writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE |
+                              IOAT_DMA_DCA_ANY_CPU,
+                              ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
+               else if (ioat_chan->device->version == IOAT_VER_3_0)
+                       writel(IOAT_DMA_DCA_ANY_CPU,
+                              ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
                spin_lock_init(&ioat_chan->cleanup_lock);
                spin_lock_init(&ioat_chan->desc_lock);
                INIT_LIST_HEAD(&ioat_chan->free_desc);
@@ -1169,9 +1171,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
                                 * up if the client is done with the descriptor
                                 */
                                if (async_tx_test_ack(&desc->async_tx)) {
-                                       list_del(&desc->node);
-                                       list_add_tail(&desc->node,
-                                                     &ioat_chan->free_desc);
+                                       list_move_tail(&desc->node,
+                                                      &ioat_chan->free_desc);
                                } else
                                        desc->async_tx.cookie = 0;
                        } else {
@@ -1362,6 +1363,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
        dma_cookie_t cookie;
        int err = 0;
        struct completion cmp;
+       unsigned long tmo;
 
        src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
        if (!src)
@@ -1413,9 +1415,10 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
        }
        device->common.device_issue_pending(dma_chan);
 
-       wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
+       tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
 
-       if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
+       if (tmo == 0 ||
+           device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
                                        != DMA_SUCCESS) {
                dev_err(&device->pdev->dev,
                        "Self-test copy timed out, disabling\n");
@@ -1657,6 +1660,13 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
                " %d channels, device version 0x%02x, driver version %s\n",
                device->common.chancnt, device->version, IOAT_DMA_VERSION);
 
+       if (!device->common.chancnt) {
+               dev_err(&device->pdev->dev,
+                       "Intel(R) I/OAT DMA Engine problem found: "
+                       "zero channels detected\n");
+               goto err_setup_interrupts;
+       }
+
        err = ioat_dma_setup_interrupts(device);
        if (err)
                goto err_setup_interrupts;
@@ -1696,6 +1706,9 @@ void ioat_dma_remove(struct ioatdma_device *device)
        struct dma_chan *chan, *_chan;
        struct ioat_dma_chan *ioat_chan;
 
+       if (device->version != IOAT_VER_3_0)
+               cancel_delayed_work(&device->work);
+
        ioat_dma_remove_interrupts(device);
 
        dma_async_device_unregister(&device->common);
@@ -1707,10 +1720,6 @@ void ioat_dma_remove(struct ioatdma_device *device)
        pci_release_regions(device->pdev);
        pci_disable_device(device->pdev);
 
-       if (device->version != IOAT_VER_3_0) {
-               cancel_delayed_work(&device->work);
-       }
-
        list_for_each_entry_safe(chan, _chan,
                                 &device->common.channels, device_node) {
                ioat_chan = to_ioat_chan(chan);
index a3306d0e1372a44b2950bc06d220d9b716f0bb00..a52ff4bd4601f78dbfe3fe472bb0b26c568e422d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -29,7 +29,7 @@
 #include <linux/pci_ids.h>
 #include <net/tcp.h>
 
-#define IOAT_DMA_VERSION  "3.30"
+#define IOAT_DMA_VERSION  "3.64"
 
 enum ioat_interrupt {
        none = 0,
@@ -135,12 +135,14 @@ static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev)
        #ifdef CONFIG_NET_DMA
        switch (dev->version) {
        case IOAT_VER_1_2:
-       case IOAT_VER_3_0:
                sysctl_tcp_dma_copybreak = 4096;
                break;
        case IOAT_VER_2_0:
                sysctl_tcp_dma_copybreak = 2048;
                break;
+       case IOAT_VER_3_0:
+               sysctl_tcp_dma_copybreak = 262144;
+               break;
        }
        #endif
 }
index f1ae2c776f7487b40e695395e3562679f420b29e..afa57eef86c946e685d13b8e2e7554ec66a7ff6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
index 827cb503cac6979a0fa98e3fbd25a113e14fda27..49bc277424f8c319b3a46369fe13e9339dc6cce6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved.
+ * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
index 647374acba94a7c526d04236af5a855f81b7258c..16adbe61cfb2cd60efd1a01246be3f9c9f4eac43 100644 (file)
@@ -928,19 +928,19 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
 
        for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
                xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
-               if (!xor_srcs[src_idx])
-                       while (src_idx--) {
+               if (!xor_srcs[src_idx]) {
+                       while (src_idx--)
                                __free_page(xor_srcs[src_idx]);
-                               return -ENOMEM;
-                       }
+                       return -ENOMEM;
+               }
        }
 
        dest = alloc_page(GFP_KERNEL);
-       if (!dest)
-               while (src_idx--) {
+       if (!dest) {
+               while (src_idx--)
                        __free_page(xor_srcs[src_idx]);
-                       return -ENOMEM;
-               }
+               return -ENOMEM;
+       }
 
        /* Fill in src buffers */
        for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
index 1f154d08e98f88cfbff23c192bf473dcdfa5cad0..ae50a9d1a4e683ae4665debfdb8a1294bbde05cc 100644 (file)
@@ -729,7 +729,7 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan,
 
        ichan->status = IPU_CHANNEL_READY;
 
-       spin_unlock_irqrestore(ipu->lock, flags);
+       spin_unlock_irqrestore(&ipu->lock, flags);
 
        return 0;
 }
index 5d5d5b31867fc9e28dd70696e52ad00fa68c997c..cb7f26fb9f188ce594081069bd61c6e99c957930 100644 (file)
@@ -1019,19 +1019,19 @@ mv_xor_xor_self_test(struct mv_xor_device *device)
 
        for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
                xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
-               if (!xor_srcs[src_idx])
-                       while (src_idx--) {
+               if (!xor_srcs[src_idx]) {
+                       while (src_idx--)
                                __free_page(xor_srcs[src_idx]);
-                               return -ENOMEM;
-                       }
+                       return -ENOMEM;
+               }
        }
 
        dest = alloc_page(GFP_KERNEL);
-       if (!dest)
-               while (src_idx--) {
+       if (!dest) {
+               while (src_idx--)
                        __free_page(xor_srcs[src_idx]);
-                       return -ENOMEM;
-               }
+               return -ENOMEM;
+       }
 
        /* Fill in src buffers */
        for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
index e072903b12f016aab1aa0d72e0939907253ff033..5ea3bfad172a02a1c27100920fec28c5d60b1e4f 100644 (file)
@@ -721,6 +721,11 @@ config BLK_DEV_IDE_TX4939
        depends on SOC_TX4939
        select BLK_DEV_IDEDMA_SFF
 
+config BLK_DEV_IDE_AT91
+       tristate "Atmel AT91 (SAM9, CAP9, AT572D940HF) IDE support"
+       depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40
+       select IDE_TIMINGS
+
 config IDE_ARM
        tristate "ARM IDE support"
        depends on ARM && (ARCH_RPC || ARCH_SHARK)
index d0e3d7d5b4672bf9874a1832b7fff2aaf5239007..1c326d94aa6d932021476f041801ddf4f57e9e8c 100644 (file)
@@ -116,3 +116,4 @@ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX)    += au1xxx-ide.o
 
 obj-$(CONFIG_BLK_DEV_IDE_TX4938)       += tx4938ide.o
 obj-$(CONFIG_BLK_DEV_IDE_TX4939)       += tx4939ide.o
+obj-$(CONFIG_BLK_DEV_IDE_AT91)         += at91_ide.o
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c
new file mode 100644 (file)
index 0000000..1bb50f4
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller
+ * with Compact Flash True IDE logic
+ *
+ * Copyright (c) 2008, 2009 Kelvatek Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/ide.h>
+#include <linux/platform_device.h>
+
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/at91sam9263.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/at91sam9263_matrix.h>
+
+#define DRV_NAME "at91_ide"
+
+#define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args)
+#define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args)
+
+/*
+ * Access to IDE device is possible through EBI Static Memory Controller
+ * with Compact Flash logic. For details see EBI and SMC datasheet sections
+ * of any microcontroller from AT91SAM9 family.
+ *
+ * Within SMC chip select address space, lines A[23:21] distinguish Compact
+ * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are:
+ *   0x00c0000 - True IDE
+ *   0x00e0000 - Alternate True IDE (Alt Status Register)
+ *
+ * On True IDE mode Task File and Data Register are mapped at the same address.
+ * To distinguish access between these two different bus data width is used:
+ * 8Bit for Task File, 16Bit for Data I/O.
+ *
+ * After initialization we do 8/16 bit flipping (changes in SMC MODE register)
+ * only inside IDE callback routines which are serialized by IDE layer,
+ * so no additional locking needed.
+ */
+
+#define TASK_FILE      0x00c00000
+#define ALT_MODE       0x00e00000
+#define REGS_SIZE      8
+
+#define enter_16bit(cs, mode) do {                                     \
+       mode = at91_sys_read(AT91_SMC_MODE(cs));                        \
+       at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16);      \
+} while (0)
+
+#define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode);
+
+static void set_smc_timings(const u8 chipselect, const u16 cycle,
+                           const u16 setup, const u16 pulse,
+                           const u16 data_float, int use_iordy)
+{
+       unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
+                            AT91_SMC_BAT_SELECT;
+
+       /* disable or enable waiting for IORDY signal */
+       if (use_iordy)
+               mode |= AT91_SMC_EXNWMODE_READY;
+
+       /* add data float cycles if needed */
+       if (data_float)
+               mode |= AT91_SMC_TDF_(data_float);
+
+       at91_sys_write(AT91_SMC_MODE(chipselect), mode);
+
+       /* setup timings in SMC */
+       at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) |
+                                                  AT91_SMC_NCS_WRSETUP_(0) |
+                                                  AT91_SMC_NRDSETUP_(setup) |
+                                                  AT91_SMC_NCS_RDSETUP_(0));
+       at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) |
+                                                  AT91_SMC_NCS_WRPULSE_(cycle) |
+                                                  AT91_SMC_NRDPULSE_(pulse) |
+                                                  AT91_SMC_NCS_RDPULSE_(cycle));
+       at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) |
+                                                  AT91_SMC_NRDCYCLE_(cycle));
+}
+
+static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz)
+{
+       u64 tmp = ns;
+
+       tmp *= mck_hz;
+       tmp += 1000*1000*1000 - 1; /* round up */
+       do_div(tmp, 1000*1000*1000);
+       return (unsigned int) tmp;
+}
+
+static void apply_timings(const u8 chipselect, const u8 pio,
+                         const struct ide_timing *timing, int use_iordy)
+{
+       unsigned int t0, t1, t2, t6z;
+       unsigned int cycle, setup, pulse, data_float;
+       unsigned int mck_hz;
+       struct clk *mck;
+
+       /* see table 22 of Compact Flash standard 4.1 for the meaning,
+        * we do not stretch active (t2) time, so setup (t1) + hold time (th)
+        * assure at least minimal recovery (t2i) time */
+       t0 = timing->cyc8b;
+       t1 = timing->setup;
+       t2 = timing->act8b;
+       t6z = (pio < 5) ? 30 : 20;
+
+       pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z);
+
+       mck = clk_get(NULL, "mck");
+       BUG_ON(IS_ERR(mck));
+       mck_hz = clk_get_rate(mck);
+       pdbg("mck_hz=%u\n", mck_hz);
+
+       cycle = calc_mck_cycles(t0, mck_hz);
+       setup = calc_mck_cycles(t1, mck_hz);
+       pulse = calc_mck_cycles(t2, mck_hz);
+       data_float = calc_mck_cycles(t6z, mck_hz);
+
+       pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n",
+            cycle, setup, pulse, data_float);
+
+       set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy);
+}
+
+static void at91_ide_input_data(ide_drive_t *drive, struct request *rq,
+                               void *buf, unsigned int len)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       u8 chipselect = hwif->select_data;
+       unsigned long mode;
+
+       pdbg("cs %u buf %p len %d\n", chipselect, buf, len);
+
+       len++;
+
+       enter_16bit(chipselect, mode);
+       __ide_mm_insw((void __iomem *) io_ports->data_addr, buf, len / 2);
+       leave_16bit(chipselect, mode);
+}
+
+static void at91_ide_output_data(ide_drive_t *drive, struct request *rq,
+                                void *buf, unsigned int len)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       u8 chipselect = hwif->select_data;
+       unsigned long mode;
+
+       pdbg("cs %u buf %p len %d\n", chipselect,  buf, len);
+
+       enter_16bit(chipselect, mode);
+       __ide_mm_outsw((void __iomem *) io_ports->data_addr, buf, len / 2);
+       leave_16bit(chipselect, mode);
+}
+
+static u8 ide_mm_inb(unsigned long port)
+{
+       return readb((void __iomem *) port);
+}
+
+static void ide_mm_outb(u8 value, unsigned long port)
+{
+       writeb(value, (void __iomem *) port);
+}
+
+static void at91_ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
+       u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
+       if (task->tf_flags & IDE_TFLAG_FLAGGED)
+               HIHI = 0xFF;
+
+       if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+               u16 data = (tf->hob_data << 8) | tf->data;
+
+               at91_ide_output_data(drive, NULL, &data, 2);
+       }
+
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+               ide_mm_outb(tf->hob_feature, io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+               ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+               ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+               ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+               ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+               ide_mm_outb(tf->feature, io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+               ide_mm_outb(tf->nsect, io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+               ide_mm_outb(tf->lbal, io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+               ide_mm_outb(tf->lbam, io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+               ide_mm_outb(tf->lbah, io_ports->lbah_addr);
+
+       if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+               ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr);
+}
+
+static void at91_ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       struct ide_taskfile *tf = &task->tf;
+
+       if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+               u16 data;
+
+               at91_ide_input_data(drive, NULL, &data, 2);
+               tf->data = data & 0xff;
+               tf->hob_data = (data >> 8) & 0xff;
+       }
+
+       /* be sure we're looking at the low order bits */
+       ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+       if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+               tf->feature = ide_mm_inb(io_ports->feature_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+               tf->nsect  = ide_mm_inb(io_ports->nsect_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+               tf->lbal   = ide_mm_inb(io_ports->lbal_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+               tf->lbam   = ide_mm_inb(io_ports->lbam_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+               tf->lbah   = ide_mm_inb(io_ports->lbah_addr);
+       if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+               tf->device = ide_mm_inb(io_ports->device_addr);
+
+       if (task->tf_flags & IDE_TFLAG_LBA48) {
+               ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+                       tf->hob_feature = ide_mm_inb(io_ports->feature_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+                       tf->hob_nsect   = ide_mm_inb(io_ports->nsect_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+                       tf->hob_lbal    = ide_mm_inb(io_ports->lbal_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+                       tf->hob_lbam    = ide_mm_inb(io_ports->lbam_addr);
+               if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+                       tf->hob_lbah    = ide_mm_inb(io_ports->lbah_addr);
+       }
+}
+
+static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+       struct ide_timing *timing;
+       u8 chipselect = drive->hwif->select_data;
+       int use_iordy = 0;
+
+       pdbg("chipselect %u pio %u\n", chipselect, pio);
+
+       timing = ide_timing_find_mode(XFER_PIO_0 + pio);
+       BUG_ON(!timing);
+
+       if ((pio > 2 || ata_id_has_iordy(drive->id)) &&
+           !(ata_id_is_cfa(drive->id) && pio > 4))
+               use_iordy = 1;
+
+       apply_timings(chipselect, pio, timing, use_iordy);
+}
+
+static const struct ide_tp_ops at91_ide_tp_ops = {
+       .exec_command   = ide_exec_command,
+       .read_status    = ide_read_status,
+       .read_altstatus = ide_read_altstatus,
+       .set_irq        = ide_set_irq,
+
+       .tf_load        = at91_ide_tf_load,
+       .tf_read        = at91_ide_tf_read,
+
+       .input_data     = at91_ide_input_data,
+       .output_data    = at91_ide_output_data,
+};
+
+static const struct ide_port_ops at91_ide_port_ops = {
+       .set_pio_mode   = at91_ide_set_pio_mode,
+};
+
+static const struct ide_port_info at91_ide_port_info __initdata = {
+       .port_ops       = &at91_ide_port_ops,
+       .tp_ops         = &at91_ide_tp_ops,
+       .host_flags     = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE |
+                         IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS,
+       .pio_mask       = ATA_PIO5,
+};
+
+/*
+ * If interrupt is delivered through GPIO, IRQ are triggered on falling
+ * and rising edge of signal. Whereas IDE device request interrupt on high
+ * level (rising edge in our case). This mean we have fake interrupts, so
+ * we need to check interrupt pin and exit instantly from ISR when line
+ * is on low level.
+ */
+
+irqreturn_t at91_irq_handler(int irq, void *dev_id)
+{
+       int ntries = 8;
+       int pin_val1, pin_val2;
+
+       /* additional deglitch, line can be noisy in badly designed PCB */
+       do {
+               pin_val1 = at91_get_gpio_value(irq);
+               pin_val2 = at91_get_gpio_value(irq);
+       } while (pin_val1 != pin_val2 && --ntries > 0);
+
+       if (pin_val1 == 0 || ntries <= 0)
+               return IRQ_HANDLED;
+
+       return ide_intr(irq, dev_id);
+}
+
+static int __init at91_ide_probe(struct platform_device *pdev)
+{
+       int ret;
+       hw_regs_t hw;
+       hw_regs_t *hws[] = { &hw, NULL, NULL, NULL };
+       struct ide_host *host;
+       struct resource *res;
+       unsigned long tf_base = 0, ctl_base = 0;
+       struct at91_cf_data *board = pdev->dev.platform_data;
+
+       if (!board)
+               return -ENODEV;
+
+       if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) {
+               perr("no device detected\n");
+               return -ENODEV;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               perr("can't get memory resource\n");
+               return -ENODEV;
+       }
+
+       if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE,
+                                    REGS_SIZE, "ide") ||
+           !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE,
+                                    REGS_SIZE, "alt")) {
+               perr("memory resources in use\n");
+               return -EBUSY;
+       }
+
+       pdbg("chipselect %u irq %u res %08lx\n", board->chipselect,
+            board->irq_pin, (unsigned long) res->start);
+
+       tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE,
+                                              REGS_SIZE);
+       ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE,
+                                               REGS_SIZE);
+       if (!tf_base || !ctl_base) {
+               perr("can't map memory regions\n");
+               return -EBUSY;
+       }
+
+       memset(&hw, 0, sizeof(hw));
+
+       if (board->flags & AT91_IDE_SWAP_A0_A2) {
+               /* workaround for stupid hardware bug */
+               hw.io_ports.data_addr   = tf_base + 0;
+               hw.io_ports.error_addr  = tf_base + 4;
+               hw.io_ports.nsect_addr  = tf_base + 2;
+               hw.io_ports.lbal_addr   = tf_base + 6;
+               hw.io_ports.lbam_addr   = tf_base + 1;
+               hw.io_ports.lbah_addr   = tf_base + 5;
+               hw.io_ports.device_addr = tf_base + 3;
+               hw.io_ports.command_addr = tf_base + 7;
+               hw.io_ports.ctl_addr    = ctl_base + 3;
+       } else
+               ide_std_init_ports(&hw, tf_base, ctl_base + 6);
+
+       hw.irq = board->irq_pin;
+       hw.chipset = ide_generic;
+       hw.dev = &pdev->dev;
+
+       host = ide_host_alloc(&at91_ide_port_info, hws);
+       if (!host) {
+               perr("failed to allocate ide host\n");
+               return -ENOMEM;
+       }
+
+       /* setup Static Memory Controller - PIO 0 as default */
+       apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0);
+
+       /* with GPIO interrupt we have to do quirks in handler */
+       if (board->irq_pin >= PIN_BASE)
+               host->irq_handler = at91_irq_handler;
+
+       host->ports[0]->select_data = board->chipselect;
+
+       ret = ide_host_register(host, &at91_ide_port_info, hws);
+       if (ret) {
+               perr("failed to register ide host\n");
+               goto err_free_host;
+       }
+       platform_set_drvdata(pdev, host);
+       return 0;
+
+err_free_host:
+       ide_host_free(host);
+       return ret;
+}
+
+static int __exit at91_ide_remove(struct platform_device *pdev)
+{
+       struct ide_host *host = platform_get_drvdata(pdev);
+
+       ide_host_remove(host);
+       return 0;
+}
+
+static struct platform_driver at91_ide_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+       },
+       .remove = __exit_p(at91_ide_remove),
+};
+
+static int __init at91_ide_init(void)
+{
+       return platform_driver_probe(&at91_ide_driver, at91_ide_probe);
+}
+
+static void __exit at91_ide_exit(void)
+{
+       platform_driver_unregister(&at91_ide_driver);
+}
+
+module_init(at91_ide_init);
+module_exit(at91_ide_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stanislaw Gruszka <stf_xl@wp.pl>");
+
index 1146f4204c6e4499ac93f75bfc409d14642c25a1..1f86dcbd2b1c83c00eb68ccb6f8ca62164445c63 100644 (file)
@@ -125,5 +125,5 @@ const struct ide_proc_devset ide_disk_settings[] = {
        IDE_PROC_DEVSET(multcount,      0,    16),
        IDE_PROC_DEVSET(nowerr,         0,     1),
        IDE_PROC_DEVSET(wcache,         0,     1),
-       { 0 },
+       { NULL },
 };
index 3ec762cb60abfcceae5e0f5ede250adbc2ec2f7c..fcd4d8153df567f06f00a5cf5b642dc25306af87 100644 (file)
@@ -29,5 +29,5 @@ const struct ide_proc_devset ide_floppy_settings[] = {
        IDE_PROC_DEVSET(bios_head, 0,  255),
        IDE_PROC_DEVSET(bios_sect, 0,   63),
        IDE_PROC_DEVSET(ticks,     0,  255),
-       { 0 },
+       { NULL },
 };
index 9ee51adf567faefd6ade2873a41444a1d44ca961..a9a6c208288a27173970b705de620fea3e076294 100644 (file)
@@ -908,7 +908,7 @@ void ide_timer_expiry (unsigned long data)
        ide_drive_t     *uninitialized_var(drive);
        ide_handler_t   *handler;
        unsigned long   flags;
-       unsigned long   wait = -1;
+       int             wait = -1;
        int             plug_device = 0;
 
        spin_lock_irqsave(&hwif->lock, flags);
@@ -1162,6 +1162,7 @@ out_early:
 
        return irq_ret;
 }
+EXPORT_SYMBOL_GPL(ide_intr);
 
 /**
  *     ide_do_drive_cmd        -       issue IDE special command
index 753b92ebe0ae5e72416d78cf3fe4baf0a94aabd6..b1892bd95c6fe5e7d270e3b92e2fd825b6847cb3 100644 (file)
@@ -315,6 +315,8 @@ void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
        u8 io_32bit = drive->io_32bit;
        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 
+       len++;
+
        if (io_32bit) {
                unsigned long uninitialized_var(flags);
 
index ce0818a993f68a42bf445bc79dea4eaa0ccc94da..ee8e3e7cad51e6b66ce1737d263633e947e6e29c 100644 (file)
@@ -950,6 +950,7 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
 static int init_irq (ide_hwif_t *hwif)
 {
        struct ide_io_ports *io_ports = &hwif->io_ports;
+       irq_handler_t irq_handler;
        int sa = 0;
 
        mutex_lock(&ide_cfg_mtx);
@@ -959,6 +960,10 @@ static int init_irq (ide_hwif_t *hwif)
        hwif->timer.function = &ide_timer_expiry;
        hwif->timer.data = (unsigned long)hwif;
 
+       irq_handler = hwif->host->irq_handler;
+       if (irq_handler == NULL)
+               irq_handler = ide_intr;
+
 #if defined(__mc68000__)
        sa = IRQF_SHARED;
 #endif /* __mc68000__ */
@@ -969,7 +974,7 @@ static int init_irq (ide_hwif_t *hwif)
        if (io_ports->ctl_addr)
                hwif->tp_ops->set_irq(hwif, 1);
 
-       if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif))
+       if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
                goto out_up;
 
        if (!hwif->rqsize) {
index 1d8978b3314a93bfb6d5bf8e05a52dcd11a94757..a7b9287ee0d4309bc30a9fe5d97df93f6f74eb3a 100644 (file)
@@ -231,7 +231,7 @@ static const struct ide_proc_devset ide_generic_settings[] = {
        IDE_PROC_DEVSET(pio_mode, 0, 255),
        IDE_PROC_DEVSET(unmaskirq, 0, 1),
        IDE_PROC_DEVSET(using_dma, 0, 1),
-       { 0 },
+       { NULL },
 };
 
 static void proc_ide_settings_warn(void)
index bb450a7608c2fe9a8ef08f19b03d86ba980f3fde..4e6181c7bbdaf613e18a6fdd461cdfdef60afa83 100644 (file)
@@ -2166,7 +2166,7 @@ static const struct ide_proc_devset idetape_settings[] = {
        __IDE_PROC_DEVSET(speed,        0, 0xffff, NULL, NULL),
        __IDE_PROC_DEVSET(tdsc,         IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
                                        mulf_tdsc, divf_tdsc),
-       { 0 },
+       { NULL },
 };
 #endif
 
index c837dfc2b3c613799a228744e5de396ca206b1ee..321728f48f2d0c38204a312fbc67685428ee318e 100644 (file)
@@ -80,7 +80,7 @@ static struct buffer_head *get_block_length(struct super_block *sb,
  * generated a larger block - this does occasionally happen with zlib).
  */
 int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
-                       int length, u64 *next_index, int srclength)
+                       int length, u64 *next_index, int srclength, int pages)
 {
        struct squashfs_sb_info *msblk = sb->s_fs_info;
        struct buffer_head **bh;
@@ -185,6 +185,14 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
                        }
 
                        if (msblk->stream.avail_out == 0) {
+                               if (page == pages) {
+                                       ERROR("zlib_inflate tried to "
+                                               "decompress too much data, "
+                                               "expected %d bytes.  Zlib "
+                                               "data probably corrupt\n",
+                                               srclength);
+                                       goto release_mutex;
+                               }
                                msblk->stream.next_out = buffer[page++];
                                msblk->stream.avail_out = PAGE_CACHE_SIZE;
                        }
@@ -268,7 +276,8 @@ block_release:
                put_bh(bh[k]);
 
 read_failure:
-       ERROR("sb_bread failed reading block 0x%llx\n", cur_index);
+       ERROR("squashfs_read_data failed to read block 0x%llx\n",
+                                       (unsigned long long) index);
        kfree(bh);
        return -EIO;
 }
index f29eda16d25ebd6c9bee029b872ac97e5a31fc29..1c4739e33af638bf819278c755e2d656ec64288d 100644 (file)
@@ -119,7 +119,7 @@ struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb,
 
                        entry->length = squashfs_read_data(sb, entry->data,
                                block, length, &entry->next_index,
-                               cache->block_size);
+                               cache->block_size, cache->pages);
 
                        spin_lock(&cache->lock);
 
@@ -406,7 +406,7 @@ int squashfs_read_table(struct super_block *sb, void *buffer, u64 block,
        for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
                data[i] = buffer;
        res = squashfs_read_data(sb, data, block, length |
-               SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length);
+               SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages);
        kfree(data);
        return res;
 }
index 7a63398bb855ab6982810ae366b577139e6abe92..9101dbde39ece6a9ca5d8b47d3344c1f3bdc6879 100644 (file)
@@ -133,7 +133,8 @@ int squashfs_read_inode(struct inode *inode, long long ino)
        type = le16_to_cpu(sqshb_ino->inode_type);
        switch (type) {
        case SQUASHFS_REG_TYPE: {
-               unsigned int frag_offset, frag_size, frag;
+               unsigned int frag_offset, frag;
+               int frag_size;
                u64 frag_blk;
                struct squashfs_reg_inode *sqsh_ino = &squashfs_ino.reg;
 
@@ -175,7 +176,8 @@ int squashfs_read_inode(struct inode *inode, long long ino)
                break;
        }
        case SQUASHFS_LREG_TYPE: {
-               unsigned int frag_offset, frag_size, frag;
+               unsigned int frag_offset, frag;
+               int frag_size;
                u64 frag_blk;
                struct squashfs_lreg_inode *sqsh_ino = &squashfs_ino.lreg;
 
index 6b2515d027d5b0545b0ac490baf1df9a1acd138c..0e9feb6adf7e120ccad9efd9815717fd44dbc83c 100644 (file)
@@ -34,7 +34,7 @@ static inline struct squashfs_inode_info *squashfs_i(struct inode *inode)
 
 /* block.c */
 extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *,
-                               int);
+                               int, int);
 
 /* cache.c */
 extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
index 071df5b5b49184a28d354f217b78844002e4053b..681ec0d83799cc22595f44aadad42ca5d63e0538 100644 (file)
@@ -389,7 +389,7 @@ static int __init init_squashfs_fs(void)
                return err;
        }
 
-       printk(KERN_INFO "squashfs: version 4.0 (2009/01/03) "
+       printk(KERN_INFO "squashfs: version 4.0 (2009/01/31) "
                "Phillip Lougher\n");
 
        return 0;
index 08a86d5cdf1b7ea2c6c995f1073aaa59092d9a8c..9a061accd8b8de95f7dcb282d2488f0613418c9e 100644 (file)
@@ -89,6 +89,8 @@ enum {
        ATA_ID_DLF              = 128,
        ATA_ID_CSFO             = 129,
        ATA_ID_CFA_POWER        = 160,
+       ATA_ID_CFA_KEY_MGMT     = 162,
+       ATA_ID_CFA_MODES        = 163,
        ATA_ID_ROT_SPEED        = 217,
        ATA_ID_PIO4             = (1 << 1),
 
index f0413845f20ee75481543cb97c570d6dbda142b4..1956c8d46d326ea98c2286a6f3f47e8e428518a1 100644 (file)
@@ -97,7 +97,6 @@ typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
 
 /**
  * struct dma_chan_percpu - the per-CPU part of struct dma_chan
- * @refcount: local_t used for open-coded "bigref" counting
  * @memcpy_count: transaction counter
  * @bytes_transferred: byte counter
  */
@@ -114,9 +113,6 @@ struct dma_chan_percpu {
  * @cookie: last cookie value returned to client
  * @chan_id: channel ID for sysfs
  * @dev: class device for sysfs
- * @refcount: kref, used in "bigref" slow-mode
- * @slow_ref: indicates that the DMA channel is free
- * @rcu: the DMA channel's RCU head
  * @device_node: used to add this to the device chan list
  * @local: per-cpu pointer to a struct dma_chan_percpu
  * @client-count: how many clients are using this channel
@@ -213,8 +209,6 @@ struct dma_async_tx_descriptor {
  * @global_node: list_head for global dma_device_list
  * @cap_mask: one or more dma_capability flags
  * @max_xor: maximum number of xor sources, 0 if no capability
- * @refcount: reference count
- * @done: IO completion struct
  * @dev_id: unique device ID
  * @dev: struct device reference for dma mapping api
  * @device_alloc_chan_resources: allocate resources and return the
@@ -227,6 +221,7 @@ struct dma_async_tx_descriptor {
  * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
  * @device_prep_slave_sg: prepares a slave dma operation
  * @device_terminate_all: terminate all pending operations
+ * @device_is_tx_complete: poll for transaction completion
  * @device_issue_pending: push pending transactions to hardware
  */
 struct dma_device {
index c37e9241fae785ce24930473b59f3029c6e99ff0..ed21bd3dbd2552a9322a45c943e078d0e6a4e2fc 100644 (file)
@@ -511,7 +511,6 @@ struct hd_driveid {
        unsigned short  words69_70[2];  /* reserved words 69-70
                                         * future command overlap and queuing
                                         */
-       /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
        unsigned short  words71_74[4];  /* reserved words 71-74
                                         * for IDENTIFY PACKET DEVICE command
                                         */
index fe235b65207ee74d43e74818d94bdaf6759816d5..e0cedfe9fad46b63d13fad9ce0a006d5e75fecd3 100644 (file)
@@ -866,6 +866,7 @@ struct ide_host {
        unsigned int    n_ports;
        struct device   *dev[2];
        unsigned int    (*init_chipset)(struct pci_dev *);
+       irq_handler_t   irq_handler;
        unsigned long   host_flags;
        void            *host_priv;
        ide_hwif_t      *cur_port;      /* for hosts requiring serialization */
index 5d87bc09a1f5bcef65f97a4c06599c8e9f7295b1..dc18b87ed72244e90e898f43885f5bdca3c806b2 100644 (file)
@@ -275,7 +275,7 @@ enum {
         * advised to wait only for the following duration before
         * doing SRST.
         */
-       ATA_TMOUT_PMP_SRST_WAIT = 1000,
+       ATA_TMOUT_PMP_SRST_WAIT = 5000,
 
        /* ATA bus states */
        BUS_UNKNOWN             = 0,
@@ -530,6 +530,7 @@ struct ata_queued_cmd {
        unsigned long           flags;          /* ATA_QCFLAG_xxx */
        unsigned int            tag;
        unsigned int            n_elem;
+       unsigned int            orig_n_elem;
 
        int                     dma_dir;
 
@@ -750,7 +751,8 @@ struct ata_port {
        acpi_handle             acpi_handle;
        struct ata_acpi_gtm     __acpi_init_gtm; /* use ata_acpi_init_gtm() */
 #endif
-       u8                      sector_buf[ATA_SECT_SIZE]; /* owned by EH */
+       /* owned by EH */
+       u8                      sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;
 };
 
 /* The following initializer overrides a method to NULL whether one of
index 1bcb357a01a1d00781b97fcad67eaa45dd82fba7..e0417e4d3f15ad3fdd66ef845c7ef8854f72aaae 100644 (file)
@@ -212,7 +212,7 @@ static inline void serio_unpin_driver(struct serio *serio)
 #define SERIO_FUJITSU  0x35
 #define SERIO_ZHENHUA  0x36
 #define SERIO_INEXIO   0x37
-#define SERIO_TOUCHIT213       0x37
+#define SERIO_TOUCHIT213       0x38
 #define SERIO_W8001    0x39
 
 #endif
index 0278bc08304440df4af600670312e7bd3bce764c..e7ded1326b0ff835cec48f4e448b0c69f8df1d04 100644 (file)
@@ -1498,58 +1498,31 @@ static int smack_socket_post_create(struct socket *sock, int family,
  * looks for host based access restrictions
  *
  * This version will only be appropriate for really small
- * sets of single label hosts. Because of the masking
- * it cannot shortcut out on the first match. There are
- * numerious ways to address the problem, but none of them
- * have been applied here.
+ * sets of single label hosts.
  *
  * Returns the label of the far end or NULL if it's not special.
  */
 static char *smack_host_label(struct sockaddr_in *sip)
 {
        struct smk_netlbladdr *snp;
-       char *bestlabel = NULL;
        struct in_addr *siap = &sip->sin_addr;
-       struct in_addr *liap;
-       struct in_addr *miap;
-       struct in_addr bestmask;
 
        if (siap->s_addr == 0)
                return NULL;
 
-       bestmask.s_addr = 0;
-
        for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
-               liap = &snp->smk_host.sin_addr;
-               miap = &snp->smk_mask;
-               /*
-                * If the addresses match after applying the list entry mask
-                * the entry matches the address. If it doesn't move along to
-                * the next entry.
-                */
-               if ((liap->s_addr & miap->s_addr) !=
-                   (siap->s_addr & miap->s_addr))
-                       continue;
                /*
-                * If the list entry mask identifies a single address
-                * it can't get any more specific.
+                * we break after finding the first match because
+                * the list is sorted from longest to shortest mask
+                * so we have found the most specific match
                 */
-               if (miap->s_addr == 0xffffffff)
+               if ((&snp->smk_host.sin_addr)->s_addr  ==
+                       (siap->s_addr & (&snp->smk_mask)->s_addr)) {
                        return snp->smk_label;
-               /*
-                * If the list entry mask is less specific than the best
-                * already found this entry is uninteresting.
-                */
-               if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr)
-                       continue;
-               /*
-                * This is better than any entry found so far.
-                */
-               bestmask.s_addr = miap->s_addr;
-               bestlabel = snp->smk_label;
+               }
        }
 
-       return bestlabel;
+       return NULL;
 }
 
 /**
index 8e42800878f468912c56cece9336e7c8c6bfa727..51f0efc50dab46a9200f98b6d22db0039a9a0653 100644 (file)
@@ -650,10 +650,6 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
 
        return skp;
 }
-/*
-#define BEMASK 0x80000000
-*/
-#define BEMASK 0x00000001
 #define BEBITS (sizeof(__be32) * 8)
 
 /*
@@ -663,12 +659,10 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
 {
        struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
        unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
-       __be32 bebits;
-       int maskn = 0;
+       int maskn;
+       u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
 
-       for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)
-               if ((skp->smk_mask.s_addr & bebits) == 0)
-                       break;
+       for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
 
        seq_printf(s, "%u.%u.%u.%u/%d %s\n",
                hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
@@ -701,6 +695,42 @@ static int smk_open_netlbladdr(struct inode *inode, struct file *file)
        return seq_open(file, &netlbladdr_seq_ops);
 }
 
+/**
+ * smk_netlbladdr_insert
+ * @new : netlabel to insert
+ *
+ * This helper insert netlabel in the smack_netlbladdrs list
+ * sorted by netmask length (longest to smallest)
+ */
+static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
+{
+       struct smk_netlbladdr *m;
+
+       if (smack_netlbladdrs == NULL) {
+               smack_netlbladdrs = new;
+               return;
+       }
+
+       /* the comparison '>' is a bit hacky, but works */
+       if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) {
+               new->smk_next = smack_netlbladdrs;
+               smack_netlbladdrs = new;
+               return;
+       }
+       for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) {
+               if (m->smk_next == NULL) {
+                       m->smk_next = new;
+                       return;
+               }
+               if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) {
+                       new->smk_next = m->smk_next;
+                       m->smk_next = new;
+                       return;
+               }
+       }
+}
+
+
 /**
  * smk_write_netlbladdr - write() for /smack/netlabel
  * @filp: file pointer, not actually used
@@ -724,8 +754,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
        struct netlbl_audit audit_info;
        struct in_addr mask;
        unsigned int m;
-       __be32 bebits = BEMASK;
+       u32 mask_bits = (1<<31);
        __be32 nsa;
+       u32 temp_mask;
 
        /*
         * Must have privilege.
@@ -761,10 +792,13 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
        if (sp == NULL)
                return -EINVAL;
 
-       for (mask.s_addr = 0; m > 0; m--) {
-               mask.s_addr |= bebits;
-               bebits <<= 1;
+       for (temp_mask = 0; m > 0; m--) {
+               temp_mask |= mask_bits;
+               mask_bits >>= 1;
        }
+       mask.s_addr = cpu_to_be32(temp_mask);
+
+       newname.sin_addr.s_addr &= mask.s_addr;
        /*
         * Only allow one writer at a time. Writes should be
         * quite rare and small in any case.
@@ -772,6 +806,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
        mutex_lock(&smk_netlbladdr_lock);
 
        nsa = newname.sin_addr.s_addr;
+       /* try to find if the prefix is already in the list */
        for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
                if (skp->smk_host.sin_addr.s_addr == nsa &&
                    skp->smk_mask.s_addr == mask.s_addr)
@@ -787,9 +822,8 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
                        rc = 0;
                        skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
                        skp->smk_mask.s_addr = mask.s_addr;
-                       skp->smk_next = smack_netlbladdrs;
                        skp->smk_label = sp;
-                       smack_netlbladdrs = skp;
+                       smk_netlbladdr_insert(skp);
                }
        } else {
                rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
index 3bc427645da8ef1411400990b67c9fc181e4cece..6094344fb223312bb668ad92b1cab3bcc626c068 100644 (file)
@@ -1207,7 +1207,7 @@ static const char *slave_vols[] = {
        "LFE Playback Volume",
        "Side Playback Volume",
        "Headphone Playback Volume",
-       "Headphone Playback Volume",
+       "Headphone2 Playback Volume",
        "Speaker Playback Volume",
        "External Speaker Playback Volume",
        "Speaker2 Playback Volume",
@@ -1221,7 +1221,7 @@ static const char *slave_sws[] = {
        "LFE Playback Switch",
        "Side Playback Switch",
        "Headphone Playback Switch",
-       "Headphone Playback Switch",
+       "Headphone2 Playback Switch",
        "Speaker Playback Switch",
        "External Speaker Playback Switch",
        "Speaker2 Playback Switch",
@@ -3516,6 +3516,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
        if (! spec->autocfg.line_outs)
                return 0; /* can't find valid pin config */
 
+#if 0 /* FIXME: temporarily disabled */
        /* If we have no real line-out pin and multiple hp-outs, HPs should
         * be set up as multi-channel outputs.
         */
@@ -3535,6 +3536,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
                spec->autocfg.line_out_type = AUTO_PIN_HP_OUT;
                spec->autocfg.hp_outs = 0;
        }
+#endif /* FIXME: temporarily disabled */
        if (spec->autocfg.mono_out_pin) {
                int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) &
                        (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP);