Merge branch 'for-current' of https://github.com/PeterHuewe/linux-tpmdd into for...
authorJames Morris <james.l.morris@oracle.com>
Mon, 9 Mar 2015 13:38:16 +0000 (00:38 +1100)
committerJames Morris <james.l.morris@oracle.com>
Mon, 9 Mar 2015 13:38:16 +0000 (00:38 +1100)
129 files changed:
Documentation/CodeOfConflict [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-imx.txt
Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
MAINTAINERS
Makefile
arch/arm64/mm/pageattr.c
drivers/android/binder.c
drivers/cpufreq/exynos-cpufreq.c
drivers/dma/at_xdmac.c
drivers/dma/dw/core.c
drivers/dma/ioat/dma_v3.c
drivers/dma/mmp_pdma.c
drivers/dma/mmp_tdma.c
drivers/dma/qcom_bam_dma.c
drivers/dma/sh/shdmac.c
drivers/gpu/drm/drm_mm.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/intel_fifo_underrun.c
drivers/gpu/drm/imx/dw_hdmi-imx.c
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/parallel-display.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
drivers/gpu/drm/msm/msm_atomic.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/ipu-v3/ipu-di.c
drivers/i2c/busses/i2c-designware-baytrail.c
drivers/iio/adc/mcp3422.c
drivers/iio/adc/qcom-spmi-iadc.c
drivers/iio/common/ssp_sensors/ssp_dev.c
drivers/iio/dac/ad5686.c
drivers/iio/humidity/dht11.c
drivers/iio/humidity/si7020.c
drivers/iio/imu/adis16400_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/light/Kconfig
drivers/iio/magnetometer/Kconfig
drivers/misc/mei/init.c
drivers/staging/comedi/drivers/adv_pci1710.c
drivers/staging/comedi/drivers/comedi_isadma.c
drivers/staging/comedi/drivers/vmk80xx.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/resolver/ad2s1200.c
drivers/thermal/int340x_thermal/int340x_thermal_zone.c
drivers/thermal/samsung/exynos_tmu.c
drivers/thermal/thermal_core.c
drivers/tty/bfin_jtag_comm.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/of_serial.c
drivers/tty/serial/sprd_serial.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/devio.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/gadget/configfs.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/gadget/function/f_sourcesink.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/uvc_v4l2.c
drivers/usb/gadget/function/uvc_video.c
drivers/usb/gadget/legacy/g_ffs.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/isp1760/isp1760-hcd.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/omap2430.c
drivers/usb/renesas_usbhs/Kconfig
drivers/usb/serial/bus.c
drivers/usb/serial/ch341.c
drivers/usb/serial/console.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/generic.c
drivers/usb/serial/mxuport.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/unusual_uas.h
drivers/usb/storage/usb.c
fs/btrfs/ctree.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ordered-data.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/xattr.c
include/drm/drm_mm.h
include/drm/ttm/ttm_bo_api.h
include/drm/ttm/ttm_bo_driver.h
include/linux/serial_core.h
include/linux/usb/serial.h
include/uapi/linux/serial.h
kernel/livepatch/core.c
kernel/module.c
kernel/printk/console_cmdline.h
kernel/printk/printk.c
net/irda/ircomm/ircomm_tty.c
net/sunrpc/cache.c

diff --git a/Documentation/CodeOfConflict b/Documentation/CodeOfConflict
new file mode 100644 (file)
index 0000000..1684d0b
--- /dev/null
@@ -0,0 +1,27 @@
+Code of Conflict
+----------------
+
+The Linux kernel development effort is a very personal process compared
+to "traditional" ways of developing software.  Your code and ideas
+behind it will be carefully reviewed, often resulting in critique and
+criticism.  The review will almost always require improvements to the
+code before it can be included in the kernel.  Know that this happens
+because everyone involved wants to see the best possible solution for
+the overall success of Linux.  This development process has been proven
+to create the most robust operating system kernel ever, and we do not
+want to do anything to cause the quality of submission and eventual
+result to ever decrease.
+
+If however, anyone feels personally abused, threatened, or otherwise
+uncomfortable due to this process, that is not acceptable.  If so,
+please contact the Linux Foundation's Technical Advisory Board at
+<tab@lists.linux-foundation.org>, or the individual members, and they
+will work to resolve the issue to the best of their ability.  For more
+information on who is on the Technical Advisory Board and what their
+role is, please see:
+       http://www.linuxfoundation.org/programs/advisory-councils/tab
+
+As a reviewer of code, please strive to keep things civil and focused on
+the technical issues involved.  We are all humans, and frustrations can
+be high on both sides of the process.  Try to keep in mind the immortal
+words of Bill and Ted, "Be excellent to each other."
index 52d37fd8d3e5c151471a70fb45ff2d4a09317a18..ce4311d726ae5e4a414e6240cc8832e876a9c24e 100644 (file)
@@ -7,6 +7,7 @@ Required properties:
   - "fsl,vf610-i2c" for I2C compatible with the one integrated on Vybrid vf610 SoC
 - reg : Should contain I2C/HS-I2C registers location and length
 - interrupts : Should contain I2C/HS-I2C interrupt
+- clocks : Should contain the I2C/HS-I2C clock specifier
 
 Optional properties:
 - clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
index 7f76214f728aa6028f133a94d04f183ccb3b1c38..289c40ed747042a70b13f9912dc0b5c443f7827e 100644 (file)
@@ -21,6 +21,18 @@ Optional properties:
 - reg-io-width : the size (in bytes) of the IO accesses that should be
   performed on the device.  If this property is not present then single byte
   accesses are used.
+- dcd-override : Override the DCD modem status signal. This signal will always
+  be reported as active instead of being obtained from the modem status
+  register. Define this if your serial port does not use this pin.
+- dsr-override : Override the DTS modem status signal. This signal will always
+  be reported as active instead of being obtained from the modem status
+  register. Define this if your serial port does not use this pin.
+- cts-override : Override the CTS modem status signal. This signal will always
+  be reported as active instead of being obtained from the modem status
+  register. Define this if your serial port does not use this pin.
+- ri-override : Override the RI modem status signal. This signal will always be
+  reported as inactive instead of being obtained from the modem status register.
+  Define this if your serial port does not use this pin.
 
 Example:
 
@@ -31,6 +43,10 @@ Example:
                interrupts = <10>;
                reg-shift = <2>;
                reg-io-width = <4>;
+               dcd-override;
+               dsr-override;
+               cts-override;
+               ri-override;
        };
 
 Example with one clock:
index 42f686f2e4b241230daeb84318948d330a759a99..6239a305dff0d9f871713651babb9e7398450365 100644 (file)
@@ -8480,6 +8480,14 @@ S:       Supported
 L:     netdev@vger.kernel.org
 F:     drivers/net/ethernet/samsung/sxgbe/
 
+SAMSUNG THERMAL DRIVER
+M:     Lukasz Majewski <l.majewski@samsung.com>
+L:     linux-pm@vger.kernel.org
+L:     linux-samsung-soc@vger.kernel.org
+S:     Supported
+T:     https://github.com/lmajewski/linux-samsung-thermal.git
+F:     drivers/thermal/samsung/
+
 SAMSUNG USB2 PHY DRIVER
 M:     Kamil Debski <k.debski@samsung.com>
 L:     linux-kernel@vger.kernel.org
index e6a9b1b94656b6e70cd2735cc1fcdaea32789cf4..1100ff3c77e3723339ccdb5a7f3ced2ff5347bee 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Hurr durr I'ma sheep
 
 # *DOCUMENTATION*
index bb0ea94c4ba1a563383f92f0f6f212c770b82d23..1d3ec3ddd84b72e654819b7818d03cbaf082815e 100644 (file)
@@ -51,7 +51,10 @@ static int change_memory_common(unsigned long addr, int numpages,
                WARN_ON_ONCE(1);
        }
 
-       if (!is_module_address(start) || !is_module_address(end - 1))
+       if (start < MODULES_VADDR || start >= MODULES_END)
+               return -EINVAL;
+
+       if (end < MODULES_VADDR || end >= MODULES_END)
                return -EINVAL;
 
        data.set_mask = set_mask;
index 33b09b6568a4a464657b51667ffe8596c7893b2f..6607f3c6ace1033fd4ca449d579bd2b7638e3963 100644 (file)
@@ -551,7 +551,6 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
 {
        void *page_addr;
        unsigned long user_page_addr;
-       struct vm_struct tmp_area;
        struct page **page;
        struct mm_struct *mm;
 
@@ -600,10 +599,11 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
                                proc->pid, page_addr);
                        goto err_alloc_page_failed;
                }
-               tmp_area.addr = page_addr;
-               tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */;
-               ret = map_vm_area(&tmp_area, PAGE_KERNEL, page);
-               if (ret) {
+               ret = map_kernel_range_noflush((unsigned long)page_addr,
+                                       PAGE_SIZE, PAGE_KERNEL, page);
+               flush_cache_vmap((unsigned long)page_addr,
+                               (unsigned long)page_addr + PAGE_SIZE);
+               if (ret != 1) {
                        pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n",
                               proc->pid, page_addr);
                        goto err_map_kernel_failed;
index 5e98c6b1f284b651f0b74d3673c55f997e47f081..82d2fbb20f7eb70d94a9c9c6e1d6ec3708f53ee0 100644 (file)
@@ -159,7 +159,7 @@ static struct cpufreq_driver exynos_driver = {
 
 static int exynos_cpufreq_probe(struct platform_device *pdev)
 {
-       struct device_node *cpus, *np;
+       struct device_node *cpu0;
        int ret = -EINVAL;
 
        exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
@@ -206,28 +206,19 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
        if (ret)
                goto err_cpufreq_reg;
 
-       cpus = of_find_node_by_path("/cpus");
-       if (!cpus) {
-               pr_err("failed to find cpus node\n");
+       cpu0 = of_get_cpu_node(0, NULL);
+       if (!cpu0) {
+               pr_err("failed to find cpu0 node\n");
                return 0;
        }
 
-       np = of_get_next_child(cpus, NULL);
-       if (!np) {
-               pr_err("failed to find cpus child node\n");
-               of_node_put(cpus);
-               return 0;
-       }
-
-       if (of_find_property(np, "#cooling-cells", NULL)) {
-               cdev = of_cpufreq_cooling_register(np,
+       if (of_find_property(cpu0, "#cooling-cells", NULL)) {
+               cdev = of_cpufreq_cooling_register(cpu0,
                                                   cpu_present_mask);
                if (IS_ERR(cdev))
                        pr_err("running cpufreq without cooling device: %ld\n",
                               PTR_ERR(cdev));
        }
-       of_node_put(np);
-       of_node_put(cpus);
 
        return 0;
 
index 09e2825a547a2098cc28a0e3e20079c33c52fe09..d9891d3461f6fbd42f5cb85041147513ca07ba73 100644 (file)
@@ -664,7 +664,6 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
        struct at_xdmac_desc    *first = NULL, *prev = NULL;
        unsigned int            periods = buf_len / period_len;
        int                     i;
-       u32                     cfg;
 
        dev_dbg(chan2dev(chan), "%s: buf_addr=%pad, buf_len=%zd, period_len=%zd, dir=%s, flags=0x%lx\n",
                __func__, &buf_addr, buf_len, period_len,
@@ -700,17 +699,17 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
                if (direction == DMA_DEV_TO_MEM) {
                        desc->lld.mbr_sa = atchan->per_src_addr;
                        desc->lld.mbr_da = buf_addr + i * period_len;
-                       cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
+                       desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG];
                } else {
                        desc->lld.mbr_sa = buf_addr + i * period_len;
                        desc->lld.mbr_da = atchan->per_dst_addr;
-                       cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
+                       desc->lld.mbr_cfg = atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG];
                }
                desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1
                        | AT_XDMAC_MBR_UBC_NDEN
                        | AT_XDMAC_MBR_UBC_NSEN
                        | AT_XDMAC_MBR_UBC_NDE
-                       | period_len >> at_xdmac_get_dwidth(cfg);
+                       | period_len >> at_xdmac_get_dwidth(desc->lld.mbr_cfg);
 
                dev_dbg(chan2dev(chan),
                         "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
index 455b7a4f1e87fe890019eb6acd459e8d7c000667..a8ad05291b274498b55deef4bba88a2dbf1ffbd3 100644 (file)
@@ -626,7 +626,7 @@ static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
        dev_vdbg(dw->dma.dev, "%s: status=0x%x\n", __func__, status);
 
        /* Check if we have any interrupt from the DMAC */
-       if (!status)
+       if (!status || !dw->in_use)
                return IRQ_NONE;
 
        /*
index 77a6dcf25b98b818b9d83ecbbf0d99edc3783056..194ec20c940841c9b0de473ac43417f4235c0482 100644 (file)
@@ -230,6 +230,10 @@ static bool is_bwd_noraid(struct pci_dev *pdev)
        switch (pdev->device) {
        case PCI_DEVICE_ID_INTEL_IOAT_BWD2:
        case PCI_DEVICE_ID_INTEL_IOAT_BWD3:
+       case PCI_DEVICE_ID_INTEL_IOAT_BDXDE0:
+       case PCI_DEVICE_ID_INTEL_IOAT_BDXDE1:
+       case PCI_DEVICE_ID_INTEL_IOAT_BDXDE2:
+       case PCI_DEVICE_ID_INTEL_IOAT_BDXDE3:
                return true;
        default:
                return false;
index 8926f271904e45dcf1f4ed7532afe6fc3cbdb323..eb410044e1af5415f4aa1aad48f7564588be1bb1 100644 (file)
@@ -219,6 +219,9 @@ static irqreturn_t mmp_pdma_int_handler(int irq, void *dev_id)
 
        while (dint) {
                i = __ffs(dint);
+               /* only handle interrupts belonging to pdma driver*/
+               if (i >= pdev->dma_channels)
+                       break;
                dint &= (dint - 1);
                phy = &pdev->phy[i];
                ret = mmp_pdma_chan_handler(irq, phy);
@@ -999,6 +1002,9 @@ static int mmp_pdma_probe(struct platform_device *op)
        struct resource *iores;
        int i, ret, irq = 0;
        int dma_channels = 0, irq_num = 0;
+       const enum dma_slave_buswidth widths =
+               DMA_SLAVE_BUSWIDTH_1_BYTE   | DMA_SLAVE_BUSWIDTH_2_BYTES |
+               DMA_SLAVE_BUSWIDTH_4_BYTES;
 
        pdev = devm_kzalloc(&op->dev, sizeof(*pdev), GFP_KERNEL);
        if (!pdev)
@@ -1066,6 +1072,10 @@ static int mmp_pdma_probe(struct platform_device *op)
        pdev->device.device_config = mmp_pdma_config;
        pdev->device.device_terminate_all = mmp_pdma_terminate_all;
        pdev->device.copy_align = PDMA_ALIGNMENT;
+       pdev->device.src_addr_widths = widths;
+       pdev->device.dst_addr_widths = widths;
+       pdev->device.directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM);
+       pdev->device.residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
 
        if (pdev->dev->coherent_dma_mask)
                dma_set_mask(pdev->dev, pdev->dev->coherent_dma_mask);
index 70c2fa9963cd4d942afa0b8a99f42c4d2ede784b..b6f4e1fc9c784cc0a3fce3d76877774760cd8c59 100644 (file)
@@ -110,7 +110,7 @@ struct mmp_tdma_chan {
        struct tasklet_struct           tasklet;
 
        struct mmp_tdma_desc            *desc_arr;
-       phys_addr_t                     desc_arr_phys;
+       dma_addr_t                      desc_arr_phys;
        int                             desc_num;
        enum dma_transfer_direction     dir;
        dma_addr_t                      dev_addr;
@@ -166,9 +166,12 @@ static void mmp_tdma_enable_chan(struct mmp_tdma_chan *tdmac)
 static int mmp_tdma_disable_chan(struct dma_chan *chan)
 {
        struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+       u32 tdcr;
 
-       writel(readl(tdmac->reg_base + TDCR) & ~TDCR_CHANEN,
-                                       tdmac->reg_base + TDCR);
+       tdcr = readl(tdmac->reg_base + TDCR);
+       tdcr |= TDCR_ABR;
+       tdcr &= ~TDCR_CHANEN;
+       writel(tdcr, tdmac->reg_base + TDCR);
 
        tdmac->status = DMA_COMPLETE;
 
@@ -296,12 +299,27 @@ static int mmp_tdma_clear_chan_irq(struct mmp_tdma_chan *tdmac)
        return -EAGAIN;
 }
 
+static size_t mmp_tdma_get_pos(struct mmp_tdma_chan *tdmac)
+{
+       size_t reg;
+
+       if (tdmac->idx == 0) {
+               reg = __raw_readl(tdmac->reg_base + TDSAR);
+               reg -= tdmac->desc_arr[0].src_addr;
+       } else if (tdmac->idx == 1) {
+               reg = __raw_readl(tdmac->reg_base + TDDAR);
+               reg -= tdmac->desc_arr[0].dst_addr;
+       } else
+               return -EINVAL;
+
+       return reg;
+}
+
 static irqreturn_t mmp_tdma_chan_handler(int irq, void *dev_id)
 {
        struct mmp_tdma_chan *tdmac = dev_id;
 
        if (mmp_tdma_clear_chan_irq(tdmac) == 0) {
-               tdmac->pos = (tdmac->pos + tdmac->period_len) % tdmac->buf_len;
                tasklet_schedule(&tdmac->tasklet);
                return IRQ_HANDLED;
        } else
@@ -343,7 +361,7 @@ static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac)
        int size = tdmac->desc_num * sizeof(struct mmp_tdma_desc);
 
        gpool = tdmac->pool;
-       if (tdmac->desc_arr)
+       if (gpool && tdmac->desc_arr)
                gen_pool_free(gpool, (unsigned long)tdmac->desc_arr,
                                size);
        tdmac->desc_arr = NULL;
@@ -499,6 +517,7 @@ static enum dma_status mmp_tdma_tx_status(struct dma_chan *chan,
 {
        struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
 
+       tdmac->pos = mmp_tdma_get_pos(tdmac);
        dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
                         tdmac->buf_len - tdmac->pos);
 
@@ -610,7 +629,7 @@ static int mmp_tdma_probe(struct platform_device *pdev)
        int i, ret;
        int irq = 0, irq_num = 0;
        int chan_num = TDMA_CHANNEL_NUM;
-       struct gen_pool *pool;
+       struct gen_pool *pool = NULL;
 
        of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev);
        if (of_id)
index d7a33b3ac46603883e61577f80e29076c0b71221..9c914d62590626fb8f407d7f0bed63b27c37a4f1 100644 (file)
@@ -162,9 +162,9 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = {
        [BAM_P_IRQ_STTS]        = { 0x1010, 0x1000, 0x00, 0x00 },
        [BAM_P_IRQ_CLR]         = { 0x1014, 0x1000, 0x00, 0x00 },
        [BAM_P_IRQ_EN]          = { 0x1018, 0x1000, 0x00, 0x00 },
-       [BAM_P_EVNT_DEST_ADDR]  = { 0x102C, 0x00, 0x1000, 0x00 },
-       [BAM_P_EVNT_REG]        = { 0x1018, 0x00, 0x1000, 0x00 },
-       [BAM_P_SW_OFSTS]        = { 0x1000, 0x00, 0x1000, 0x00 },
+       [BAM_P_EVNT_DEST_ADDR]  = { 0x182C, 0x00, 0x1000, 0x00 },
+       [BAM_P_EVNT_REG]        = { 0x1818, 0x00, 0x1000, 0x00 },
+       [BAM_P_SW_OFSTS]        = { 0x1800, 0x00, 0x1000, 0x00 },
        [BAM_P_DATA_FIFO_ADDR]  = { 0x1824, 0x00, 0x1000, 0x00 },
        [BAM_P_DESC_FIFO_ADDR]  = { 0x181C, 0x00, 0x1000, 0x00 },
        [BAM_P_EVNT_GEN_TRSHLD] = { 0x1828, 0x00, 0x1000, 0x00 },
@@ -1143,6 +1143,10 @@ static int bam_dma_probe(struct platform_device *pdev)
        dma_cap_set(DMA_SLAVE, bdev->common.cap_mask);
 
        /* initialize dmaengine apis */
+       bdev->common.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+       bdev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+       bdev->common.src_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       bdev->common.dst_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES;
        bdev->common.device_alloc_chan_resources = bam_alloc_chan;
        bdev->common.device_free_chan_resources = bam_free_chan;
        bdev->common.device_prep_slave_sg = bam_prep_slave_sg;
index b2431aa300331270fa949ea5c14c41602a6c8e69..9f1d4c7dbab8389039e4ae1da636ca13521314ee 100644 (file)
@@ -582,15 +582,12 @@ static void sh_dmae_chan_remove(struct sh_dmae_device *shdev)
        }
 }
 
-static void sh_dmae_shutdown(struct platform_device *pdev)
-{
-       struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
-       sh_dmae_ctl_stop(shdev);
-}
-
 #ifdef CONFIG_PM
 static int sh_dmae_runtime_suspend(struct device *dev)
 {
+       struct sh_dmae_device *shdev = dev_get_drvdata(dev);
+
+       sh_dmae_ctl_stop(shdev);
        return 0;
 }
 
@@ -605,6 +602,9 @@ static int sh_dmae_runtime_resume(struct device *dev)
 #ifdef CONFIG_PM_SLEEP
 static int sh_dmae_suspend(struct device *dev)
 {
+       struct sh_dmae_device *shdev = dev_get_drvdata(dev);
+
+       sh_dmae_ctl_stop(shdev);
        return 0;
 }
 
@@ -929,13 +929,12 @@ static int sh_dmae_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver sh_dmae_driver = {
-       .driver         = {
+       .driver         = {
                .pm     = &sh_dmae_pm,
                .name   = SH_DMAE_DRV_NAME,
                .of_match_table = sh_dmae_of_match,
        },
        .remove         = sh_dmae_remove,
-       .shutdown       = sh_dmae_shutdown,
 };
 
 static int __init sh_dmae_init(void)
index 04a209e2b66d7d61428398bb5b58b2222ec2a712..7fc6f8bd4821c5ce60cd60bba97bd281bd6f44dd 100644 (file)
  */
 
 static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
-                                               unsigned long size,
+                                               u64 size,
                                                unsigned alignment,
                                                unsigned long color,
                                                enum drm_mm_search_flags flags);
 static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
-                                               unsigned long size,
+                                               u64 size,
                                                unsigned alignment,
                                                unsigned long color,
-                                               unsigned long start,
-                                               unsigned long end,
+                                               u64 start,
+                                               u64 end,
                                                enum drm_mm_search_flags flags);
 
 static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
                                 struct drm_mm_node *node,
-                                unsigned long size, unsigned alignment,
+                                u64 size, unsigned alignment,
                                 unsigned long color,
                                 enum drm_mm_allocator_flags flags)
 {
        struct drm_mm *mm = hole_node->mm;
-       unsigned long hole_start = drm_mm_hole_node_start(hole_node);
-       unsigned long hole_end = drm_mm_hole_node_end(hole_node);
-       unsigned long adj_start = hole_start;
-       unsigned long adj_end = hole_end;
+       u64 hole_start = drm_mm_hole_node_start(hole_node);
+       u64 hole_end = drm_mm_hole_node_end(hole_node);
+       u64 adj_start = hole_start;
+       u64 adj_end = hole_end;
 
        BUG_ON(node->allocated);
 
@@ -124,12 +124,15 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
                adj_start = adj_end - size;
 
        if (alignment) {
-               unsigned tmp = adj_start % alignment;
-               if (tmp) {
+               u64 tmp = adj_start;
+               unsigned rem;
+
+               rem = do_div(tmp, alignment);
+               if (rem) {
                        if (flags & DRM_MM_CREATE_TOP)
-                               adj_start -= tmp;
+                               adj_start -= rem;
                        else
-                               adj_start += alignment - tmp;
+                               adj_start += alignment - rem;
                }
        }
 
@@ -176,9 +179,9 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
 int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
 {
        struct drm_mm_node *hole;
-       unsigned long end = node->start + node->size;
-       unsigned long hole_start;
-       unsigned long hole_end;
+       u64 end = node->start + node->size;
+       u64 hole_start;
+       u64 hole_end;
 
        BUG_ON(node == NULL);
 
@@ -227,7 +230,7 @@ EXPORT_SYMBOL(drm_mm_reserve_node);
  * 0 on success, -ENOSPC if there's no suitable hole.
  */
 int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
-                              unsigned long size, unsigned alignment,
+                              u64 size, unsigned alignment,
                               unsigned long color,
                               enum drm_mm_search_flags sflags,
                               enum drm_mm_allocator_flags aflags)
@@ -246,16 +249,16 @@ EXPORT_SYMBOL(drm_mm_insert_node_generic);
 
 static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
                                       struct drm_mm_node *node,
-                                      unsigned long size, unsigned alignment,
+                                      u64 size, unsigned alignment,
                                       unsigned long color,
-                                      unsigned long start, unsigned long end,
+                                      u64 start, u64 end,
                                       enum drm_mm_allocator_flags flags)
 {
        struct drm_mm *mm = hole_node->mm;
-       unsigned long hole_start = drm_mm_hole_node_start(hole_node);
-       unsigned long hole_end = drm_mm_hole_node_end(hole_node);
-       unsigned long adj_start = hole_start;
-       unsigned long adj_end = hole_end;
+       u64 hole_start = drm_mm_hole_node_start(hole_node);
+       u64 hole_end = drm_mm_hole_node_end(hole_node);
+       u64 adj_start = hole_start;
+       u64 adj_end = hole_end;
 
        BUG_ON(!hole_node->hole_follows || node->allocated);
 
@@ -271,12 +274,15 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
                mm->color_adjust(hole_node, color, &adj_start, &adj_end);
 
        if (alignment) {
-               unsigned tmp = adj_start % alignment;
-               if (tmp) {
+               u64 tmp = adj_start;
+               unsigned rem;
+
+               rem = do_div(tmp, alignment);
+               if (rem) {
                        if (flags & DRM_MM_CREATE_TOP)
-                               adj_start -= tmp;
+                               adj_start -= rem;
                        else
-                               adj_start += alignment - tmp;
+                               adj_start += alignment - rem;
                }
        }
 
@@ -324,9 +330,9 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
  * 0 on success, -ENOSPC if there's no suitable hole.
  */
 int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
-                                       unsigned long size, unsigned alignment,
+                                       u64 size, unsigned alignment,
                                        unsigned long color,
-                                       unsigned long start, unsigned long end,
+                                       u64 start, u64 end,
                                        enum drm_mm_search_flags sflags,
                                        enum drm_mm_allocator_flags aflags)
 {
@@ -387,32 +393,34 @@ void drm_mm_remove_node(struct drm_mm_node *node)
 }
 EXPORT_SYMBOL(drm_mm_remove_node);
 
-static int check_free_hole(unsigned long start, unsigned long end,
-                          unsigned long size, unsigned alignment)
+static int check_free_hole(u64 start, u64 end, u64 size, unsigned alignment)
 {
        if (end - start < size)
                return 0;
 
        if (alignment) {
-               unsigned tmp = start % alignment;
+               u64 tmp = start;
+               unsigned rem;
+
+               rem = do_div(tmp, alignment);
                if (tmp)
-                       start += alignment - tmp;
+                       start += alignment - rem;
        }
 
        return end >= start + size;
 }
 
 static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
-                                                     unsigned long size,
+                                                     u64 size,
                                                      unsigned alignment,
                                                      unsigned long color,
                                                      enum drm_mm_search_flags flags)
 {
        struct drm_mm_node *entry;
        struct drm_mm_node *best;
-       unsigned long adj_start;
-       unsigned long adj_end;
-       unsigned long best_size;
+       u64 adj_start;
+       u64 adj_end;
+       u64 best_size;
 
        BUG_ON(mm->scanned_blocks);
 
@@ -421,7 +429,7 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
 
        __drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
                               flags & DRM_MM_SEARCH_BELOW) {
-               unsigned long hole_size = adj_end - adj_start;
+               u64 hole_size = adj_end - adj_start;
 
                if (mm->color_adjust) {
                        mm->color_adjust(entry, color, &adj_start, &adj_end);
@@ -445,18 +453,18 @@ static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
 }
 
 static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
-                                                       unsigned long size,
+                                                       u64 size,
                                                        unsigned alignment,
                                                        unsigned long color,
-                                                       unsigned long start,
-                                                       unsigned long end,
+                                                       u64 start,
+                                                       u64 end,
                                                        enum drm_mm_search_flags flags)
 {
        struct drm_mm_node *entry;
        struct drm_mm_node *best;
-       unsigned long adj_start;
-       unsigned long adj_end;
-       unsigned long best_size;
+       u64 adj_start;
+       u64 adj_end;
+       u64 best_size;
 
        BUG_ON(mm->scanned_blocks);
 
@@ -465,7 +473,7 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
 
        __drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
                               flags & DRM_MM_SEARCH_BELOW) {
-               unsigned long hole_size = adj_end - adj_start;
+               u64 hole_size = adj_end - adj_start;
 
                if (adj_start < start)
                        adj_start = start;
@@ -561,7 +569,7 @@ EXPORT_SYMBOL(drm_mm_replace_node);
  * adding/removing nodes to/from the scan list are allowed.
  */
 void drm_mm_init_scan(struct drm_mm *mm,
-                     unsigned long size,
+                     u64 size,
                      unsigned alignment,
                      unsigned long color)
 {
@@ -594,11 +602,11 @@ EXPORT_SYMBOL(drm_mm_init_scan);
  * adding/removing nodes to/from the scan list are allowed.
  */
 void drm_mm_init_scan_with_range(struct drm_mm *mm,
-                                unsigned long size,
+                                u64 size,
                                 unsigned alignment,
                                 unsigned long color,
-                                unsigned long start,
-                                unsigned long end)
+                                u64 start,
+                                u64 end)
 {
        mm->scan_color = color;
        mm->scan_alignment = alignment;
@@ -627,8 +635,8 @@ bool drm_mm_scan_add_block(struct drm_mm_node *node)
 {
        struct drm_mm *mm = node->mm;
        struct drm_mm_node *prev_node;
-       unsigned long hole_start, hole_end;
-       unsigned long adj_start, adj_end;
+       u64 hole_start, hole_end;
+       u64 adj_start, adj_end;
 
        mm->scanned_blocks++;
 
@@ -731,7 +739,7 @@ EXPORT_SYMBOL(drm_mm_clean);
  *
  * Note that @mm must be cleared to 0 before calling this function.
  */
-void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
+void drm_mm_init(struct drm_mm * mm, u64 start, u64 size)
 {
        INIT_LIST_HEAD(&mm->hole_stack);
        mm->scanned_blocks = 0;
@@ -766,18 +774,17 @@ void drm_mm_takedown(struct drm_mm * mm)
 }
 EXPORT_SYMBOL(drm_mm_takedown);
 
-static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry,
-                                      const char *prefix)
+static u64 drm_mm_debug_hole(struct drm_mm_node *entry,
+                                    const char *prefix)
 {
-       unsigned long hole_start, hole_end, hole_size;
+       u64 hole_start, hole_end, hole_size;
 
        if (entry->hole_follows) {
                hole_start = drm_mm_hole_node_start(entry);
                hole_end = drm_mm_hole_node_end(entry);
                hole_size = hole_end - hole_start;
-               printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
-                       prefix, hole_start, hole_end,
-                       hole_size);
+               pr_debug("%s %#llx-%#llx: %llu: free\n", prefix, hole_start,
+                        hole_end, hole_size);
                return hole_size;
        }
 
@@ -792,35 +799,34 @@ static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry,
 void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
 {
        struct drm_mm_node *entry;
-       unsigned long total_used = 0, total_free = 0, total = 0;
+       u64 total_used = 0, total_free = 0, total = 0;
 
        total_free += drm_mm_debug_hole(&mm->head_node, prefix);
 
        drm_mm_for_each_node(entry, mm) {
-               printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
-                       prefix, entry->start, entry->start + entry->size,
-                       entry->size);
+               pr_debug("%s %#llx-%#llx: %llu: used\n", prefix, entry->start,
+                        entry->start + entry->size, entry->size);
                total_used += entry->size;
                total_free += drm_mm_debug_hole(entry, prefix);
        }
        total = total_free + total_used;
 
-       printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
-               total_used, total_free);
+       pr_debug("%s total: %llu, used %llu free %llu\n", prefix, total,
+                total_used, total_free);
 }
 EXPORT_SYMBOL(drm_mm_debug_table);
 
 #if defined(CONFIG_DEBUG_FS)
-static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
+static u64 drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
 {
-       unsigned long hole_start, hole_end, hole_size;
+       u64 hole_start, hole_end, hole_size;
 
        if (entry->hole_follows) {
                hole_start = drm_mm_hole_node_start(entry);
                hole_end = drm_mm_hole_node_end(entry);
                hole_size = hole_end - hole_start;
-               seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
-                               hole_start, hole_end, hole_size);
+               seq_printf(m, "%#llx-%#llx: %llu: free\n", hole_start,
+                          hole_end, hole_size);
                return hole_size;
        }
 
@@ -835,20 +841,20 @@ static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *en
 int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
 {
        struct drm_mm_node *entry;
-       unsigned long total_used = 0, total_free = 0, total = 0;
+       u64 total_used = 0, total_free = 0, total = 0;
 
        total_free += drm_mm_dump_hole(m, &mm->head_node);
 
        drm_mm_for_each_node(entry, mm) {
-               seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
-                               entry->start, entry->start + entry->size,
-                               entry->size);
+               seq_printf(m, "%#016llx-%#016llx: %llu: used\n", entry->start,
+                          entry->start + entry->size, entry->size);
                total_used += entry->size;
                total_free += drm_mm_dump_hole(m, entry);
        }
        total = total_free + total_used;
 
-       seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free);
+       seq_printf(m, "total: %llu, used %llu free %llu\n", total,
+                  total_used, total_free);
        return 0;
 }
 EXPORT_SYMBOL(drm_mm_dump_table);
index 96e811fe24ca79cd1b6438591cf1eb05379f0edd..e8b18e542da4311169a4b0ec6c6f45fe73a711cd 100644 (file)
@@ -152,12 +152,12 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
                        seq_puts(m, " (pp");
                else
                        seq_puts(m, " (g");
-               seq_printf(m, "gtt offset: %08lx, size: %08lx, type: %u)",
+               seq_printf(m, "gtt offset: %08llx, size: %08llx, type: %u)",
                           vma->node.start, vma->node.size,
                           vma->ggtt_view.type);
        }
        if (obj->stolen)
-               seq_printf(m, " (stolen: %08lx)", obj->stolen->start);
+               seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
        if (obj->pin_mappable || obj->fault_mappable) {
                char s[3], *t = s;
                if (obj->pin_mappable)
index 8039cec71fc24a3750812dc519b08bee6a824f41..cc6ea53d2b81951553d4b135a1760cb127e574c2 100644 (file)
@@ -622,7 +622,7 @@ static int i915_drm_suspend(struct drm_device *dev)
        return 0;
 }
 
-static int i915_drm_suspend_late(struct drm_device *drm_dev)
+static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
 {
        struct drm_i915_private *dev_priv = drm_dev->dev_private;
        int ret;
@@ -636,7 +636,17 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev)
        }
 
        pci_disable_device(drm_dev->pdev);
-       pci_set_power_state(drm_dev->pdev, PCI_D3hot);
+       /*
+        * During hibernation on some GEN4 platforms the BIOS may try to access
+        * the device even though it's already in D3 and hang the machine. So
+        * leave the device in D0 on those platforms and hope the BIOS will
+        * power down the device properly. Platforms where this was seen:
+        * Lenovo Thinkpad X301, X61s
+        */
+       if (!(hibernation &&
+             drm_dev->pdev->subsystem_vendor == PCI_VENDOR_ID_LENOVO &&
+             INTEL_INFO(dev_priv)->gen == 4))
+               pci_set_power_state(drm_dev->pdev, PCI_D3hot);
 
        return 0;
 }
@@ -662,7 +672,7 @@ int i915_suspend_legacy(struct drm_device *dev, pm_message_t state)
        if (error)
                return error;
 
-       return i915_drm_suspend_late(dev);
+       return i915_drm_suspend_late(dev, false);
 }
 
 static int i915_drm_resume(struct drm_device *dev)
@@ -950,7 +960,17 @@ static int i915_pm_suspend_late(struct device *dev)
        if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
 
-       return i915_drm_suspend_late(drm_dev);
+       return i915_drm_suspend_late(drm_dev, false);
+}
+
+static int i915_pm_poweroff_late(struct device *dev)
+{
+       struct drm_device *drm_dev = dev_to_i915(dev)->dev;
+
+       if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+               return 0;
+
+       return i915_drm_suspend_late(drm_dev, true);
 }
 
 static int i915_pm_resume_early(struct device *dev)
@@ -1520,7 +1540,7 @@ static const struct dev_pm_ops i915_pm_ops = {
        .thaw_early = i915_pm_resume_early,
        .thaw = i915_pm_resume,
        .poweroff = i915_pm_suspend,
-       .poweroff_late = i915_pm_suspend_late,
+       .poweroff_late = i915_pm_poweroff_late,
        .restore_early = i915_pm_resume_early,
        .restore = i915_pm_resume,
 
index 746f77fb57a314d5b94542b12b67b7a16bfb50eb..dccdc8aad2e24c2351766a1ec591f5a57dd3940b 100644 (file)
@@ -1145,7 +1145,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 
        ppgtt->base.clear_range(&ppgtt->base, 0, ppgtt->base.total, true);
 
-       DRM_DEBUG_DRIVER("Allocated pde space (%ldM) at GTT entry: %lx\n",
+       DRM_DEBUG_DRIVER("Allocated pde space (%lldM) at GTT entry: %llx\n",
                         ppgtt->node.size >> 20,
                         ppgtt->node.start / PAGE_SIZE);
 
@@ -1713,8 +1713,8 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
 
 static void i915_gtt_color_adjust(struct drm_mm_node *node,
                                  unsigned long color,
-                                 unsigned long *start,
-                                 unsigned long *end)
+                                 u64 *start,
+                                 u64 *end)
 {
        if (node->color != color)
                *start += 4096;
index 04e248dd2259715426e8ad82b817b59d3634b24a..54daa66c697077f5b0609ddb5eec0d7989db780a 100644 (file)
@@ -282,16 +282,6 @@ bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
        return ret;
 }
 
-static bool
-__cpu_fifo_underrun_reporting_enabled(struct drm_i915_private *dev_priv,
-                                     enum pipe pipe)
-{
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       return !intel_crtc->cpu_fifo_underrun_disabled;
-}
-
 /**
  * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
  * @dev_priv: i915 device instance
@@ -352,9 +342,15 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
 void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
                                         enum pipe pipe)
 {
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+
+       /* We may be called too early in init, thanks BIOS! */
+       if (crtc == NULL)
+               return;
+
        /* GMCH can't disable fifo underruns, filter them. */
        if (HAS_GMCH_DISPLAY(dev_priv->dev) &&
-           !__cpu_fifo_underrun_reporting_enabled(dev_priv, pipe))
+           to_intel_crtc(crtc)->cpu_fifo_underrun_disabled)
                return;
 
        if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false))
index 121d30ca2d4448f379c743ac781bb9910ccd2d44..87fe8ed92ebeb8bf996fb95b79731dbebdbed2dd 100644 (file)
@@ -70,7 +70,9 @@ static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = {
                118800000, { 0x091c, 0x091c, 0x06dc },
        }, {
                216000000, { 0x06dc, 0x0b5c, 0x091c },
-       }
+       }, {
+               ~0UL, { 0x0000, 0x0000, 0x0000 },
+       },
 };
 
 static const struct dw_hdmi_sym_term imx_sym_term[] = {
@@ -136,11 +138,34 @@ static struct drm_encoder_funcs dw_hdmi_imx_encoder_funcs = {
        .destroy = drm_encoder_cleanup,
 };
 
+static enum drm_mode_status imx6q_hdmi_mode_valid(struct drm_connector *con,
+                                                 struct drm_display_mode *mode)
+{
+       if (mode->clock < 13500)
+               return MODE_CLOCK_LOW;
+       if (mode->clock > 266000)
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
+}
+
+static enum drm_mode_status imx6dl_hdmi_mode_valid(struct drm_connector *con,
+                                                  struct drm_display_mode *mode)
+{
+       if (mode->clock < 13500)
+               return MODE_CLOCK_LOW;
+       if (mode->clock > 270000)
+               return MODE_CLOCK_HIGH;
+
+       return MODE_OK;
+}
+
 static struct dw_hdmi_plat_data imx6q_hdmi_drv_data = {
-       .mpll_cfg = imx_mpll_cfg,
-       .cur_ctr  = imx_cur_ctr,
-       .sym_term = imx_sym_term,
-       .dev_type = IMX6Q_HDMI,
+       .mpll_cfg   = imx_mpll_cfg,
+       .cur_ctr    = imx_cur_ctr,
+       .sym_term   = imx_sym_term,
+       .dev_type   = IMX6Q_HDMI,
+       .mode_valid = imx6q_hdmi_mode_valid,
 };
 
 static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = {
@@ -148,6 +173,7 @@ static struct dw_hdmi_plat_data imx6dl_hdmi_drv_data = {
        .cur_ctr  = imx_cur_ctr,
        .sym_term = imx_sym_term,
        .dev_type = IMX6DL_HDMI,
+       .mode_valid = imx6dl_hdmi_mode_valid,
 };
 
 static const struct of_device_id dw_hdmi_imx_dt_ids[] = {
index 1b86aac0b341c7083b15e03163338989a1543592..2d6dc94e1e64e973f61a1294c24bba6d2d788ae2 100644 (file)
@@ -163,22 +163,7 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
 {
        struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
        struct imx_ldb *ldb = imx_ldb_ch->ldb;
-       struct drm_display_mode *mode = &encoder->crtc->hwmode;
        u32 pixel_fmt;
-       unsigned long serial_clk;
-       unsigned long di_clk = mode->clock * 1000;
-       int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
-
-       if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
-               /* dual channel LVDS mode */
-               serial_clk = 3500UL * mode->clock;
-               imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk);
-               imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk);
-       } else {
-               serial_clk = 7000UL * mode->clock;
-               imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk,
-                               di_clk);
-       }
 
        switch (imx_ldb_ch->chno) {
        case 0:
@@ -247,6 +232,9 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
        struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
        struct imx_ldb *ldb = imx_ldb_ch->ldb;
        int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
+       unsigned long serial_clk;
+       unsigned long di_clk = mode->clock * 1000;
+       int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
 
        if (mode->clock > 170000) {
                dev_warn(ldb->dev,
@@ -257,6 +245,16 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
                         "%s: mode exceeds 85 MHz pixel clock\n", __func__);
        }
 
+       if (dual) {
+               serial_clk = 3500UL * mode->clock;
+               imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk);
+               imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk);
+       } else {
+               serial_clk = 7000UL * mode->clock;
+               imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk,
+                                 di_clk);
+       }
+
        /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
        if (imx_ldb_ch == &ldb->channel[0]) {
                if (mode->flags & DRM_MODE_FLAG_NVSYNC)
index 5e83e007080f7ae757b3f6c567cd791a595bd9d1..900dda6a8e71b5501293b8d4be06ddb8288dee27 100644 (file)
@@ -236,8 +236,11 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
        }
 
        panel_node = of_parse_phandle(np, "fsl,panel", 0);
-       if (panel_node)
+       if (panel_node) {
                imxpd->panel = of_drm_find_panel(panel_node);
+               if (!imxpd->panel)
+                       return -EPROBE_DEFER;
+       }
 
        imxpd->dev = dev;
 
index 8edd531cb62166ad1291be18ffc26ba033cbc71d..7369ee7f0c5544a6c44b9850e4ded92217da2596 100644 (file)
@@ -32,7 +32,10 @@ static void mdp4_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
 void mdp4_irq_preinstall(struct msm_kms *kms)
 {
        struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       mdp4_enable(mdp4_kms);
        mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, 0xffffffff);
+       mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
+       mdp4_disable(mdp4_kms);
 }
 
 int mdp4_irq_postinstall(struct msm_kms *kms)
@@ -53,7 +56,9 @@ int mdp4_irq_postinstall(struct msm_kms *kms)
 void mdp4_irq_uninstall(struct msm_kms *kms)
 {
        struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       mdp4_enable(mdp4_kms);
        mdp4_write(mdp4_kms, REG_MDP4_INTR_ENABLE, 0x00000000);
+       mdp4_disable(mdp4_kms);
 }
 
 irqreturn_t mdp4_irq(struct msm_kms *kms)
index 09b4a25eb553fa9cad7f68ad8a61afa13a8d90a0..c276624290afedb3f8de9fe9db2ed9271cab5ff4 100644 (file)
@@ -8,17 +8,9 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2014-12-05 15:34:49)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2014-10-31 16:48:57)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (   8253 bytes, from 2014-12-08 16:13:00)
+- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml            (  27229 bytes, from 2015-02-10 17:00:41)
+- /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2014-06-02 18:31:15)
+- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2015-01-23 16:20:19)
 
 Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
@@ -910,6 +902,7 @@ static inline uint32_t __offset_LM(uint32_t idx)
                case 2: return (mdp5_cfg->lm.base[2]);
                case 3: return (mdp5_cfg->lm.base[3]);
                case 4: return (mdp5_cfg->lm.base[4]);
+               case 5: return (mdp5_cfg->lm.base[5]);
                default: return INVALID_IDX(idx);
        }
 }
index 46fac545dc2bb8f84e8d6bc241d88931d926b23e..2f2863cf8b45f21e692e3e50f09c88275d83da63 100644 (file)
@@ -62,8 +62,8 @@ struct mdp5_crtc {
 
                /* current cursor being scanned out: */
                struct drm_gem_object *scanout_bo;
-               uint32_t width;
-               uint32_t height;
+               uint32_t width, height;
+               uint32_t x, y;
        } cursor;
 };
 #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
@@ -103,8 +103,8 @@ static void crtc_flush_all(struct drm_crtc *crtc)
        struct drm_plane *plane;
        uint32_t flush_mask = 0;
 
-       /* we could have already released CTL in the disable path: */
-       if (!mdp5_crtc->ctl)
+       /* this should not happen: */
+       if (WARN_ON(!mdp5_crtc->ctl))
                return;
 
        drm_atomic_crtc_for_each_plane(plane, crtc) {
@@ -143,6 +143,11 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
        drm_atomic_crtc_for_each_plane(plane, crtc) {
                mdp5_plane_complete_flip(plane);
        }
+
+       if (mdp5_crtc->ctl && !crtc->state->enable) {
+               mdp5_ctl_release(mdp5_crtc->ctl);
+               mdp5_crtc->ctl = NULL;
+       }
 }
 
 static void unref_cursor_worker(struct drm_flip_work *work, void *val)
@@ -386,14 +391,17 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)
        mdp5_crtc->event = crtc->state->event;
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
+       /*
+        * If no CTL has been allocated in mdp5_crtc_atomic_check(),
+        * it means we are trying to flush a CRTC whose state is disabled:
+        * nothing else needs to be done.
+        */
+       if (unlikely(!mdp5_crtc->ctl))
+               return;
+
        blend_setup(crtc);
        crtc_flush_all(crtc);
        request_pending(crtc, PENDING_FLIP);
-
-       if (mdp5_crtc->ctl && !crtc->state->enable) {
-               mdp5_ctl_release(mdp5_crtc->ctl);
-               mdp5_crtc->ctl = NULL;
-       }
 }
 
 static int mdp5_crtc_set_property(struct drm_crtc *crtc,
@@ -403,6 +411,32 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc,
        return -EINVAL;
 }
 
+static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)
+{
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       uint32_t xres = crtc->mode.hdisplay;
+       uint32_t yres = crtc->mode.vdisplay;
+
+       /*
+        * Cursor Region Of Interest (ROI) is a plane read from cursor
+        * buffer to render. The ROI region is determined by the visibility of
+        * the cursor point. In the default Cursor image the cursor point will
+        * be at the top left of the cursor image, unless it is specified
+        * otherwise using hotspot feature.
+        *
+        * If the cursor point reaches the right (xres - x < cursor.width) or
+        * bottom (yres - y < cursor.height) boundary of the screen, then ROI
+        * width and ROI height need to be evaluated to crop the cursor image
+        * accordingly.
+        * (xres-x) will be new cursor width when x > (xres - cursor.width)
+        * (yres-y) will be new cursor height when y > (yres - cursor.height)
+        */
+       *roi_w = min(mdp5_crtc->cursor.width, xres -
+                       mdp5_crtc->cursor.x);
+       *roi_h = min(mdp5_crtc->cursor.height, yres -
+                       mdp5_crtc->cursor.y);
+}
+
 static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
                struct drm_file *file, uint32_t handle,
                uint32_t width, uint32_t height)
@@ -416,6 +450,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
        unsigned int depth;
        enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
        uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
+       uint32_t roi_w, roi_h;
        unsigned long flags;
 
        if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
@@ -446,6 +481,12 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
        old_bo = mdp5_crtc->cursor.scanout_bo;
 
+       mdp5_crtc->cursor.scanout_bo = cursor_bo;
+       mdp5_crtc->cursor.width = width;
+       mdp5_crtc->cursor.height = height;
+
+       get_roi(crtc, &roi_w, &roi_h);
+
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
                        MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
@@ -453,19 +494,14 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
                        MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) |
                        MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width));
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
-                       MDP5_LM_CURSOR_SIZE_ROI_H(height) |
-                       MDP5_LM_CURSOR_SIZE_ROI_W(width));
+                       MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
+                       MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr);
 
-
        blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN;
-       blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_TRANSP_EN;
        blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha);
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg);
 
-       mdp5_crtc->cursor.scanout_bo = cursor_bo;
-       mdp5_crtc->cursor.width = width;
-       mdp5_crtc->cursor.height = height;
        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
 
        ret = mdp5_ctl_set_cursor(mdp5_crtc->ctl, true);
@@ -489,31 +525,18 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
-       uint32_t xres = crtc->mode.hdisplay;
-       uint32_t yres = crtc->mode.vdisplay;
        uint32_t roi_w;
        uint32_t roi_h;
        unsigned long flags;
 
-       x = (x > 0) ? x : 0;
-       y = (y > 0) ? y : 0;
+       /* In case the CRTC is disabled, just drop the cursor update */
+       if (unlikely(!crtc->state->enable))
+               return 0;
 
-       /*
-        * Cursor Region Of Interest (ROI) is a plane read from cursor
-        * buffer to render. The ROI region is determined by the visiblity of
-        * the cursor point. In the default Cursor image the cursor point will
-        * be at the top left of the cursor image, unless it is specified
-        * otherwise using hotspot feature.
-        *
-        * If the cursor point reaches the right (xres - x < cursor.width) or
-        * bottom (yres - y < cursor.height) boundary of the screen, then ROI
-        * width and ROI height need to be evaluated to crop the cursor image
-        * accordingly.
-        * (xres-x) will be new cursor width when x > (xres - cursor.width)
-        * (yres-y) will be new cursor height when y > (yres - cursor.height)
-        */
-       roi_w = min(mdp5_crtc->cursor.width, xres - x);
-       roi_h = min(mdp5_crtc->cursor.height, yres - y);
+       mdp5_crtc->cursor.x = x = max(x, 0);
+       mdp5_crtc->cursor.y = y = max(y, 0);
+
+       get_roi(crtc, &roi_w, &roi_h);
 
        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
        mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(mdp5_crtc->lm),
@@ -544,8 +567,8 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = {
 static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
        .mode_fixup = mdp5_crtc_mode_fixup,
        .mode_set_nofb = mdp5_crtc_mode_set_nofb,
-       .prepare = mdp5_crtc_disable,
-       .commit = mdp5_crtc_enable,
+       .disable = mdp5_crtc_disable,
+       .enable = mdp5_crtc_enable,
        .atomic_check = mdp5_crtc_atomic_check,
        .atomic_begin = mdp5_crtc_atomic_begin,
        .atomic_flush = mdp5_crtc_atomic_flush,
index d6a14bb99988199db0993dd654255eecf2269539..af0e02fa4f4821ac7a71a4b641fde76db366a8cd 100644 (file)
@@ -267,14 +267,14 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder)
        mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1);
        spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
 
-       mdp5_encoder->enabled = false;
+       mdp5_encoder->enabled = true;
 }
 
 static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
        .mode_fixup = mdp5_encoder_mode_fixup,
        .mode_set = mdp5_encoder_mode_set,
-       .prepare = mdp5_encoder_disable,
-       .commit = mdp5_encoder_enable,
+       .disable = mdp5_encoder_disable,
+       .enable = mdp5_encoder_enable,
 };
 
 /* initialize encoder */
index 70ac81edd40f3bb7d6de68553b7be350005312ec..a9407105b9b799bea9fc787a923e7dc914bee30a 100644 (file)
@@ -34,7 +34,10 @@ static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
 void mdp5_irq_preinstall(struct msm_kms *kms)
 {
        struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       mdp5_enable(mdp5_kms);
        mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff);
+       mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
+       mdp5_disable(mdp5_kms);
 }
 
 int mdp5_irq_postinstall(struct msm_kms *kms)
@@ -57,7 +60,9 @@ int mdp5_irq_postinstall(struct msm_kms *kms)
 void mdp5_irq_uninstall(struct msm_kms *kms)
 {
        struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+       mdp5_enable(mdp5_kms);
        mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
+       mdp5_disable(mdp5_kms);
 }
 
 static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
index 871aa2108dc694795e74f2b308031c849ad1a966..18fd643b6e6915c3a2e13c149640d9917459eb12 100644 (file)
@@ -219,8 +219,10 @@ int msm_atomic_commit(struct drm_device *dev,
         * mark our set of crtc's as busy:
         */
        ret = start_atomic(dev->dev_private, c->crtc_mask);
-       if (ret)
+       if (ret) {
+               kfree(c);
                return ret;
+       }
 
        /*
         * This is the point of no return - everything below never fails except
index 79924e4b1b495577f26822f8f03801b67e4497a6..6751553abe4afe4bc408cd08863a7981b858bece 100644 (file)
@@ -418,7 +418,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
        nouveau_fbcon_zfill(dev, fbcon);
 
        /* To allow resizeing without swapping buffers */
-       NV_INFO(drm, "allocated %dx%d fb: 0x%lx, bo %p\n",
+       NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n",
                nouveau_fb->base.width, nouveau_fb->base.height,
                nvbo->bo.offset, nvbo);
 
index ed644a4f6f57c4254349c3881a16955cd42cbc05..86807ee91bd13a7640f5b925aa4b5a4c0d9d615d 100644 (file)
@@ -1405,6 +1405,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
               (x << 16) | y);
        viewport_w = crtc->mode.hdisplay;
        viewport_h = (crtc->mode.vdisplay + 1) & ~1;
+       if ((rdev->family >= CHIP_BONAIRE) &&
+           (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE))
+               viewport_h *= 2;
        WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
               (viewport_w << 16) | viewport_h);
 
index 7fe7b749e182543b5c742e3b7fba76eeeffcc783..c39c1d0d9d4e328d8df7f19caf2b52c68b1988b3 100644 (file)
@@ -1626,7 +1626,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        struct radeon_connector *radeon_connector = NULL;
        struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
        bool travis_quirk = false;
-       int encoder_mode;
 
        if (connector) {
                radeon_connector = to_radeon_connector(connector);
@@ -1722,13 +1721,6 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                }
                break;
        }
-
-       encoder_mode = atombios_get_encoder_mode(encoder);
-       if (connector && (radeon_audio != 0) &&
-           ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
-            (ENCODER_MODE_IS_DP(encoder_mode) &&
-             drm_detect_monitor_audio(radeon_connector_edid(connector)))))
-               radeon_audio_dpms(encoder, mode);
 }
 
 static void
@@ -1737,10 +1729,19 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+       int encoder_mode = atombios_get_encoder_mode(encoder);
 
        DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
                  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
                  radeon_encoder->active_device);
+
+       if (connector && (radeon_audio != 0) &&
+           ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
+            (ENCODER_MODE_IS_DP(encoder_mode) &&
+             drm_detect_monitor_audio(radeon_connector_edid(connector)))))
+               radeon_audio_dpms(encoder, mode);
+
        switch (radeon_encoder->encoder_id) {
        case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
@@ -2170,12 +2171,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
                /* handled in dpms */
-               encoder_mode = atombios_get_encoder_mode(encoder);
-               if (connector && (radeon_audio != 0) &&
-                   ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
-                    (ENCODER_MODE_IS_DP(encoder_mode) &&
-                     drm_detect_monitor_audio(radeon_connector_edid(connector)))))
-                       radeon_audio_mode_set(encoder, adjusted_mode);
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DDI:
        case ENCODER_OBJECT_ID_INTERNAL_DVO1:
@@ -2197,6 +2192,13 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        }
 
        atombios_apply_encoder_quirks(encoder, adjusted_mode);
+
+       encoder_mode = atombios_get_encoder_mode(encoder);
+       if (connector && (radeon_audio != 0) &&
+           ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
+            (ENCODER_MODE_IS_DP(encoder_mode) &&
+             drm_detect_monitor_audio(radeon_connector_edid(connector)))))
+               radeon_audio_mode_set(encoder, adjusted_mode);
 }
 
 static bool
index 0c993da9c8fb0503e9658339d10d6b28ac90a66c..3e670d344a2047151e289ab7dce348001ddf4280 100644 (file)
@@ -7555,6 +7555,9 @@ int cik_irq_set(struct radeon_device *rdev)
        WREG32(DC_HPD5_INT_CONTROL, hpd5);
        WREG32(DC_HPD6_INT_CONTROL, hpd6);
 
+       /* posting read */
+       RREG32(SRBM_STATUS);
+
        return 0;
 }
 
index 192c8038915187df6714fbd6d653f57dba449c13..3adc2afe32aa6be372abcdd925001bbc79176745 100644 (file)
@@ -26,6 +26,9 @@
 #include "radeon_audio.h"
 #include "sid.h"
 
+#define DCE8_DCCG_AUDIO_DTO1_PHASE     0x05b8
+#define DCE8_DCCG_AUDIO_DTO1_MODULE    0x05bc
+
 u32 dce6_endpoint_rreg(struct radeon_device *rdev,
                              u32 block_offset, u32 reg)
 {
@@ -252,72 +255,67 @@ void dce6_audio_enable(struct radeon_device *rdev,
 void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
        struct radeon_crtc *crtc, unsigned int clock)
 {
-    /* Two dtos; generally use dto0 for HDMI */
+       /* Two dtos; generally use dto0 for HDMI */
        u32 value = 0;
 
-    if (crtc)
+       if (crtc)
                value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
 
        WREG32(DCCG_AUDIO_DTO_SOURCE, value);
 
-    /* Express [24MHz / target pixel clock] as an exact rational
-     * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
-     * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
-     */
-    WREG32(DCCG_AUDIO_DTO0_PHASE, 24000);
-    WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
+       /* Express [24MHz / target pixel clock] as an exact rational
+        * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+        * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+        */
+       WREG32(DCCG_AUDIO_DTO0_PHASE, 24000);
+       WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
 }
 
 void dce6_dp_audio_set_dto(struct radeon_device *rdev,
        struct radeon_crtc *crtc, unsigned int clock)
 {
-    /* Two dtos; generally use dto1 for DP */
+       /* Two dtos; generally use dto1 for DP */
        u32 value = 0;
        value |= DCCG_AUDIO_DTO_SEL;
 
-    if (crtc)
+       if (crtc)
                value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
 
        WREG32(DCCG_AUDIO_DTO_SOURCE, value);
 
-    /* Express [24MHz / target pixel clock] as an exact rational
-     * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
-     * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
-     */
-    WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
-    WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
+       /* Express [24MHz / target pixel clock] as an exact rational
+        * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+        * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+        */
+       if (ASIC_IS_DCE8(rdev)) {
+               WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000);
+               WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock);
+       } else {
+               WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
+               WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
+       }
 }
 
-void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable)
+void dce6_dp_enable(struct drm_encoder *encoder, bool enable)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       uint32_t offset;
 
        if (!dig || !dig->afmt)
                return;
 
-       offset = dig->afmt->offset;
-
        if (enable) {
-        if (dig->afmt->enabled)
-            return;
-
-               WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
-               WREG32(EVERGREEN_DP_SEC_CNTL + offset,
-                       EVERGREEN_DP_SEC_ASP_ENABLE |           /* Audio packet transmission */
-                       EVERGREEN_DP_SEC_ATP_ENABLE |           /* Audio timestamp packet transmission */
-                       EVERGREEN_DP_SEC_AIP_ENABLE |           /* Audio infoframe packet transmission */
-                       EVERGREEN_DP_SEC_STREAM_ENABLE);        /* Master enable for secondary stream engine */
-               radeon_audio_enable(rdev, dig->afmt->pin, true);
+               WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset,
+                      EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
+               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset,
+                      EVERGREEN_DP_SEC_ASP_ENABLE |            /* Audio packet transmission */
+                      EVERGREEN_DP_SEC_ATP_ENABLE |            /* Audio timestamp packet transmission */
+                      EVERGREEN_DP_SEC_AIP_ENABLE |            /* Audio infoframe packet transmission */
+                      EVERGREEN_DP_SEC_STREAM_ENABLE); /* Master enable for secondary stream engine */
        } else {
-               if (!dig->afmt->enabled)
-                       return;
-
-               WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0);
-               radeon_audio_enable(rdev, dig->afmt->pin, false);
+               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0);
        }
 
        dig->afmt->enabled = enable;
index 4c0e24b3bb9022aac8cfe59868022c096941dd60..973df064c14feb193a81c99109665c2186d03dc6 100644 (file)
@@ -4593,6 +4593,9 @@ int evergreen_irq_set(struct radeon_device *rdev)
        WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5);
        WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6);
 
+       /* posting read */
+       RREG32(SRBM_STATUS);
+
        return 0;
 }
 
index 1d9aebc79595d050dd52d6e28da01939b908bc16..c18d4ecbd95d02baa907d4d15b6da43f282f4e67 100644 (file)
@@ -272,7 +272,7 @@ void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
 }
 
 void dce4_dp_audio_set_dto(struct radeon_device *rdev,
-       struct radeon_crtc *crtc, unsigned int clock)
+                          struct radeon_crtc *crtc, unsigned int clock)
 {
        u32 value;
 
@@ -294,7 +294,7 @@ void dce4_dp_audio_set_dto(struct radeon_device *rdev,
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
        WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
-       WREG32(DCCG_AUDIO_DTO1_MODULE, rdev->clock.max_pixel_clock * 10);
+       WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
 }
 
 void dce4_set_vbi_packet(struct drm_encoder *encoder, u32 offset)
@@ -350,20 +350,9 @@ void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
 
-       WREG32(HDMI_INFOFRAME_CONTROL0 + offset,
-               HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
-               HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
-
        WREG32(AFMT_INFOFRAME_CONTROL0 + offset,
                AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
 
-       WREG32(HDMI_INFOFRAME_CONTROL1 + offset,
-               HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
-
-       WREG32(HDMI_AUDIO_PACKET_CONTROL + offset,
-               HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
-               HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
-
        WREG32(AFMT_60958_0 + offset,
                AFMT_60958_CS_CHANNEL_NUMBER_L(1));
 
@@ -408,15 +397,19 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
        if (!dig || !dig->afmt)
                return;
 
-       /* Silent, r600_hdmi_enable will raise WARN for us */
-       if (enable && dig->afmt->enabled)
-               return;
-       if (!enable && !dig->afmt->enabled)
-               return;
+       if (enable) {
+               WREG32(HDMI_INFOFRAME_CONTROL1 + dig->afmt->offset,
+                      HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
+
+               WREG32(HDMI_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                      HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
+                      HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
 
-       if (!enable && dig->afmt->pin) {
-               radeon_audio_enable(rdev, dig->afmt->pin, 0);
-               dig->afmt->pin = NULL;
+               WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
+                      HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
+                      HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
+       } else {
+               WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, 0);
        }
 
        dig->afmt->enabled = enable;
@@ -425,33 +418,28 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
                  enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id);
 }
 
-void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable)
+void evergreen_dp_enable(struct drm_encoder *encoder, bool enable)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       uint32_t offset;
 
        if (!dig || !dig->afmt)
                return;
 
-       offset = dig->afmt->offset;
-
        if (enable) {
                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
                struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                struct radeon_connector_atom_dig *dig_connector;
                uint32_t val;
 
-               if (dig->afmt->enabled)
-                       return;
-
-               WREG32(EVERGREEN_DP_SEC_TIMESTAMP + offset, EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
+               WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset,
+                      EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
 
                if (radeon_connector->con_priv) {
                        dig_connector = radeon_connector->con_priv;
-                       val = RREG32(EVERGREEN_DP_SEC_AUD_N + offset);
+                       val = RREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset);
                        val &= ~EVERGREEN_DP_SEC_N_BASE_MULTIPLE(0xf);
 
                        if (dig_connector->dp_clock == 162000)
@@ -459,21 +447,16 @@ void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable)
                        else
                                val |= EVERGREEN_DP_SEC_N_BASE_MULTIPLE(5);
 
-                       WREG32(EVERGREEN_DP_SEC_AUD_N + offset, val);
+                       WREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset, val);
                }
 
-               WREG32(EVERGREEN_DP_SEC_CNTL + offset,
+               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset,
                        EVERGREEN_DP_SEC_ASP_ENABLE |           /* Audio packet transmission */
                        EVERGREEN_DP_SEC_ATP_ENABLE |           /* Audio timestamp packet transmission */
                        EVERGREEN_DP_SEC_AIP_ENABLE |           /* Audio infoframe packet transmission */
                        EVERGREEN_DP_SEC_STREAM_ENABLE);        /* Master enable for secondary stream engine */
-               radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
        } else {
-               if (!dig->afmt->enabled)
-                       return;
-
-               WREG32(EVERGREEN_DP_SEC_CNTL + offset, 0);
-               radeon_audio_enable(rdev, dig->afmt->pin, 0);
+               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0);
        }
 
        dig->afmt->enabled = enable;
index 279801ca5110aff68d80ea452751d7f9b0bf748f..04f2514f756453bfdc7275a52c65549e631cfc6c 100644 (file)
@@ -728,6 +728,10 @@ int r100_irq_set(struct radeon_device *rdev)
                tmp |= RADEON_FP2_DETECT_MASK;
        }
        WREG32(RADEON_GEN_INT_CNTL, tmp);
+
+       /* read back to post the write */
+       RREG32(RADEON_GEN_INT_CNTL);
+
        return 0;
 }
 
index 07a71a2488c93404f0803e3fbefe4c6204a4b5da..2fcad344492f526a98b46b34d2979cd9dd5a872e 100644 (file)
@@ -3784,6 +3784,9 @@ int r600_irq_set(struct radeon_device *rdev)
                WREG32(RV770_CG_THERMAL_INT, thermal_int);
        }
 
+       /* posting read */
+       RREG32(R_000E50_SRBM_STATUS);
+
        return 0;
 }
 
index 62c91ed669ce24bdf4f96ea3eb0c7c446e457b1b..dd6606b8e23ca9a3bfd3f7be414b17d01af2aacb 100644 (file)
@@ -476,17 +476,6 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable)
        if (!dig || !dig->afmt)
                return;
 
-       /* Silent, r600_hdmi_enable will raise WARN for us */
-       if (enable && dig->afmt->enabled)
-               return;
-       if (!enable && !dig->afmt->enabled)
-               return;
-
-       if (!enable && dig->afmt->pin) {
-               radeon_audio_enable(rdev, dig->afmt->pin, 0);
-               dig->afmt->pin = NULL;
-       }
-
        /* Older chipsets require setting HDMI and routing manually */
        if (!ASIC_IS_DCE3(rdev)) {
                if (enable)
index a3ceef6d9632509b5d1d4cb760539af02a033efe..b21ef69a34ac2a2703f7adad0ee20a15f07d3509 100644 (file)
@@ -101,8 +101,8 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
        struct drm_display_mode *mode);
 void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
 void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable);
-void evergreen_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable);
-void dce6_enable_dp_audio_packets(struct drm_encoder *encoder, bool enable);
+void evergreen_dp_enable(struct drm_encoder *encoder, bool enable);
+void dce6_dp_enable(struct drm_encoder *encoder, bool enable);
 
 static const u32 pin_offsets[7] =
 {
@@ -210,7 +210,7 @@ static struct radeon_audio_funcs dce4_dp_funcs = {
        .set_avi_packet = evergreen_set_avi_packet,
        .set_audio_packet = dce4_set_audio_packet,
        .mode_set = radeon_audio_dp_mode_set,
-       .dpms = evergreen_enable_dp_audio_packets,
+       .dpms = evergreen_dp_enable,
 };
 
 static struct radeon_audio_funcs dce6_hdmi_funcs = {
@@ -240,7 +240,7 @@ static struct radeon_audio_funcs dce6_dp_funcs = {
        .set_avi_packet = evergreen_set_avi_packet,
        .set_audio_packet = dce4_set_audio_packet,
        .mode_set = radeon_audio_dp_mode_set,
-       .dpms = dce6_enable_dp_audio_packets,
+       .dpms = dce6_dp_enable,
 };
 
 static void radeon_audio_interface_init(struct radeon_device *rdev)
@@ -452,7 +452,7 @@ void radeon_audio_enable(struct radeon_device *rdev,
 }
 
 void radeon_audio_detect(struct drm_connector *connector,
-       enum drm_connector_status status)
+                        enum drm_connector_status status)
 {
        struct radeon_device *rdev;
        struct radeon_encoder *radeon_encoder;
@@ -483,14 +483,11 @@ void radeon_audio_detect(struct drm_connector *connector,
                else
                        radeon_encoder->audio = rdev->audio.hdmi_funcs;
 
-               radeon_audio_write_speaker_allocation(connector->encoder);
-               radeon_audio_write_sad_regs(connector->encoder);
-               if (connector->encoder->crtc)
-                       radeon_audio_write_latency_fields(connector->encoder,
-                               &connector->encoder->crtc->mode);
+               dig->afmt->pin = radeon_audio_get_pin(connector->encoder);
                radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
        } else {
                radeon_audio_enable(rdev, dig->afmt->pin, 0);
+               dig->afmt->pin = NULL;
        }
 }
 
@@ -694,23 +691,22 @@ static void radeon_audio_set_mute(struct drm_encoder *encoder, bool mute)
  * update the info frames with the data from the current display mode
  */
 static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
-       struct drm_display_mode *mode)
+                                      struct drm_display_mode *mode)
 {
-       struct radeon_device *rdev = encoder->dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
        if (!dig || !dig->afmt)
                return;
 
-       /* disable audio prior to setting up hw */
-       dig->afmt->pin = radeon_audio_get_pin(encoder);
-       radeon_audio_enable(rdev, dig->afmt->pin, 0);
+       radeon_audio_set_mute(encoder, true);
 
+       radeon_audio_write_speaker_allocation(encoder);
+       radeon_audio_write_sad_regs(encoder);
+       radeon_audio_write_latency_fields(encoder, mode);
        radeon_audio_set_dto(encoder, mode->clock);
        radeon_audio_set_vbi_packet(encoder);
        radeon_hdmi_set_color_depth(encoder);
-       radeon_audio_set_mute(encoder, false);
        radeon_audio_update_acr(encoder, mode->clock);
        radeon_audio_set_audio_packet(encoder);
        radeon_audio_select_pin(encoder);
@@ -718,8 +714,7 @@ static void radeon_audio_hdmi_mode_set(struct drm_encoder *encoder,
        if (radeon_audio_set_avi_packet(encoder, mode) < 0)
                return;
 
-       /* enable audio after to setting up hw */
-       radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+       radeon_audio_set_mute(encoder, false);
 }
 
 static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
@@ -729,23 +724,26 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct radeon_connector_atom_dig *dig_connector =
+               radeon_connector->con_priv;
 
        if (!dig || !dig->afmt)
                return;
 
-       /* disable audio prior to setting up hw */
-       dig->afmt->pin = radeon_audio_get_pin(encoder);
-       radeon_audio_enable(rdev, dig->afmt->pin, 0);
-
-       radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
+       radeon_audio_write_speaker_allocation(encoder);
+       radeon_audio_write_sad_regs(encoder);
+       radeon_audio_write_latency_fields(encoder, mode);
+       if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev))
+               radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
+       else
+               radeon_audio_set_dto(encoder, dig_connector->dp_clock);
        radeon_audio_set_audio_packet(encoder);
        radeon_audio_select_pin(encoder);
 
        if (radeon_audio_set_avi_packet(encoder, mode) < 0)
                return;
-
-       /* enable audio after to setting up hw */
-       radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
 }
 
 void radeon_audio_mode_set(struct drm_encoder *encoder,
index a579ed379f20f4609b5b9736dc123e6c5adf1ea8..4d0f96cc3da4488b0a324058533d26500011293f 100644 (file)
@@ -256,11 +256,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
        u32 ring = RADEON_CS_RING_GFX;
        s32 priority = 0;
 
+       INIT_LIST_HEAD(&p->validated);
+
        if (!cs->num_chunks) {
                return 0;
        }
+
        /* get chunks */
-       INIT_LIST_HEAD(&p->validated);
        p->idx = 0;
        p->ib.sa_bo = NULL;
        p->const_ib.sa_bo = NULL;
index d81182ad53ec6920b4f7027595882cebf26cdcfc..97a904835759f7876b2b69be104493cf302554a7 100644 (file)
@@ -694,6 +694,10 @@ int rs600_irq_set(struct radeon_device *rdev)
        WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2);
        if (ASIC_IS_DCE2(rdev))
                WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0);
+
+       /* posting read */
+       RREG32(R_000040_GEN_INT_CNTL);
+
        return 0;
 }
 
index bcf516a8a2f1960a9403b765460a363ba0feaedd..e088e5558da0117c1d3a85cac06bcf129a8a78c2 100644 (file)
@@ -6203,6 +6203,9 @@ int si_irq_set(struct radeon_device *rdev)
 
        WREG32(CG_THERMAL_INT, thermal_int);
 
+       /* posting read */
+       RREG32(SRBM_STATUS);
+
        return 0;
 }
 
index c27118cab16a625a978a2d57e22297f518764b4b..99a9835c9f615919c063af1ce0ca0e596aed8c15 100644 (file)
 
 #define DCCG_AUDIO_DTO0_PHASE                           0x05b0
 #define DCCG_AUDIO_DTO0_MODULE                          0x05b4
-#define DCCG_AUDIO_DTO1_PHASE                           0x05b8
-#define DCCG_AUDIO_DTO1_MODULE                          0x05bc
+#define DCCG_AUDIO_DTO1_PHASE                           0x05c0
+#define DCCG_AUDIO_DTO1_MODULE                          0x05c4
 
 #define AFMT_AUDIO_SRC_CONTROL                          0x713c
 #define                AFMT_AUDIO_SRC_SELECT(x)                (((x) & 7) << 0)
index d395b0bef73b0ce8afffa1d40fb9ea47022ac7fd..8d9b7de2561339b03e2b191e45454eadfd454668 100644 (file)
@@ -74,7 +74,7 @@ static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type)
        pr_err("    has_type: %d\n", man->has_type);
        pr_err("    use_type: %d\n", man->use_type);
        pr_err("    flags: 0x%08X\n", man->flags);
-       pr_err("    gpu_offset: 0x%08lX\n", man->gpu_offset);
+       pr_err("    gpu_offset: 0x%08llX\n", man->gpu_offset);
        pr_err("    size: %llu\n", man->size);
        pr_err("    available_caching: 0x%08X\n", man->available_caching);
        pr_err("    default_caching: 0x%08X\n", man->default_caching);
index b61d6be97602222d3ae51b39d939d00cf8f5731b..3ddfb3d0b64d266cb95345ccb68c1a991521cc1d 100644 (file)
@@ -459,6 +459,8 @@ static void ipu_di_config_clock(struct ipu_di *di,
 
                clkrate = clk_get_rate(di->clk_ipu);
                div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
+               if (div == 0)
+                       div = 1;
                rate = clkrate / div;
 
                error = rate / (sig->mode.pixelclock / 1000);
index 5f1ff4cc5c34036ea6284adf9d00fce0ef1fabae..7d7ae97476e2c4cec01765e700e0748bece538bc 100644 (file)
 #include <linux/acpi.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
+
 #include <asm/iosf_mbi.h>
+
 #include "i2c-designware-core.h"
 
 #define SEMAPHORE_TIMEOUT      100
 #define PUNIT_SEMAPHORE                0x7
+#define PUNIT_SEMAPHORE_BIT    BIT(0)
+#define PUNIT_SEMAPHORE_ACQUIRE        BIT(1)
 
 static unsigned long acquired;
 
 static int get_sem(struct device *dev, u32 *sem)
 {
-       u32 reg_val;
+       u32 data;
        int ret;
 
        ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ, PUNIT_SEMAPHORE,
-                           &reg_val);
+                               &data);
        if (ret) {
                dev_err(dev, "iosf failed to read punit semaphore\n");
                return ret;
        }
 
-       *sem = reg_val & 0x1;
+       *sem = data & PUNIT_SEMAPHORE_BIT;
 
        return 0;
 }
@@ -52,27 +56,29 @@ static void reset_semaphore(struct device *dev)
                return;
        }
 
-       data = data & 0xfffffffe;
+       data &= ~PUNIT_SEMAPHORE_BIT;
        if (iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
-                                PUNIT_SEMAPHORE, data))
+                               PUNIT_SEMAPHORE, data))
                dev_err(dev, "iosf failed to reset punit semaphore during write\n");
 }
 
-int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
+static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
 {
-       u32 sem = 0;
+       u32 sem;
        int ret;
        unsigned long start, end;
 
+       might_sleep();
+
        if (!dev || !dev->dev)
                return -ENODEV;
 
-       if (!dev->acquire_lock)
+       if (!dev->release_lock)
                return 0;
 
-       /* host driver writes 0x2 to side band semaphore register */
+       /* host driver writes to side band semaphore register */
        ret = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
-                                PUNIT_SEMAPHORE, 0x2);
+                               PUNIT_SEMAPHORE, PUNIT_SEMAPHORE_ACQUIRE);
        if (ret) {
                dev_err(dev->dev, "iosf punit semaphore request failed\n");
                return ret;
@@ -81,7 +87,7 @@ int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
        /* host driver waits for bit 0 to be set in semaphore register */
        start = jiffies;
        end = start + msecs_to_jiffies(SEMAPHORE_TIMEOUT);
-       while (!time_after(jiffies, end)) {
+       do {
                ret = get_sem(dev->dev, &sem);
                if (!ret && sem) {
                        acquired = jiffies;
@@ -91,14 +97,14 @@ int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
                }
 
                usleep_range(1000, 2000);
-       }
+       } while (time_before(jiffies, end));
 
        dev_err(dev->dev, "punit semaphore timed out, resetting\n");
        reset_semaphore(dev->dev);
 
        ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
-               PUNIT_SEMAPHORE, &sem);
-       if (!ret)
+                               PUNIT_SEMAPHORE, &sem);
+       if (ret)
                dev_err(dev->dev, "iosf failed to read punit semaphore\n");
        else
                dev_err(dev->dev, "PUNIT SEM: %d\n", sem);
@@ -107,9 +113,8 @@ int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
 
        return -ETIMEDOUT;
 }
-EXPORT_SYMBOL(baytrail_i2c_acquire);
 
-void baytrail_i2c_release(struct dw_i2c_dev *dev)
+static void baytrail_i2c_release(struct dw_i2c_dev *dev)
 {
        if (!dev || !dev->dev)
                return;
@@ -121,7 +126,6 @@ void baytrail_i2c_release(struct dw_i2c_dev *dev)
        dev_dbg(dev->dev, "punit semaphore held for %ums\n",
                jiffies_to_msecs(jiffies - acquired));
 }
-EXPORT_SYMBOL(baytrail_i2c_release);
 
 int i2c_dw_eval_lock_support(struct dw_i2c_dev *dev)
 {
@@ -137,7 +141,6 @@ int i2c_dw_eval_lock_support(struct dw_i2c_dev *dev)
                return 0;
 
        status = acpi_evaluate_integer(handle, "_SEM", NULL, &shared_host);
-
        if (ACPI_FAILURE(status))
                return 0;
 
@@ -153,7 +156,6 @@ int i2c_dw_eval_lock_support(struct dw_i2c_dev *dev)
 
        return 0;
 }
-EXPORT_SYMBOL(i2c_dw_eval_lock_support);
 
 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
 MODULE_DESCRIPTION("Baytrail I2C Semaphore driver");
index 51672256072bc8db2778e6c60982f320c680f3d4..b96c636470ef504e3b7f3d5612602bcc76a3a3a0 100644 (file)
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
        }
 
-/* LSB is in nV to eliminate floating point */
-static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625};
-
-/*
- *  scales calculated as:
- *  rates_to_lsb[sample_rate] / (1 << pga);
- *  pga is 1 for 0, 2
- */
-
 static const int mcp3422_scales[4][4] = {
-       { 1000000, 250000, 62500, 15625 },
-       { 500000 , 125000, 31250, 7812 },
-       { 250000 , 62500 , 15625, 3906 },
-       { 125000 , 31250 , 7812 , 1953 } };
+       { 1000000, 500000, 250000, 125000 },
+       { 250000 , 125000, 62500 , 31250  },
+       { 62500  , 31250 , 15625 , 7812   },
+       { 15625  , 7812  , 3906  , 1953   } };
 
 /* Constant msleep times for data acquisitions */
 static const int mcp3422_read_times[4] = {
index b9666f2f5e514f8d3a66a0a192b190bcbd2a44d5..fabd24edc2a1d07534d2a67e9a1c8e78ef353cae 100644 (file)
@@ -296,7 +296,8 @@ static int iadc_do_conversion(struct iadc_chip *iadc, int chan, u16 *data)
        if (iadc->poll_eoc) {
                ret = iadc_poll_wait_eoc(iadc, wait);
        } else {
-               ret = wait_for_completion_timeout(&iadc->complete, wait);
+               ret = wait_for_completion_timeout(&iadc->complete,
+                       usecs_to_jiffies(wait));
                if (!ret)
                        ret = -ETIMEDOUT;
                else
index 52d70435f5a11c55ed186003c70bce311002f918..55a90082a29bd4846aaea896f8c7f847d96fcb45 100644 (file)
@@ -640,6 +640,7 @@ static int ssp_remove(struct spi_device *spi)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ssp_suspend(struct device *dev)
 {
        int ret;
@@ -688,6 +689,7 @@ static int ssp_resume(struct device *dev)
 
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
 static const struct dev_pm_ops ssp_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(ssp_suspend, ssp_resume)
index f57562aa396f44462a9fdc822741d09bf37531f4..15c73e20272d874655e544366e2a8d6f1c24912a 100644 (file)
@@ -322,7 +322,7 @@ static int ad5686_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
        spi_set_drvdata(spi, indio_dev);
 
-       st->reg = devm_regulator_get(&spi->dev, "vcc");
+       st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
        if (!IS_ERR(st->reg)) {
                ret = regulator_enable(st->reg);
                if (ret)
index 623c145d8a97241bd0c2e284d9bb273dfcfb72da..7d79a1ac5f5f09ba332fee3ebb94c486280ce024 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/wait.h>
 #include <linux/bitops.h>
 #include <linux/completion.h>
+#include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 
 #define DHT11_DATA_VALID_TIME  2000000000  /* 2s in ns */
 
-#define DHT11_EDGES_PREAMBLE 4
+#define DHT11_EDGES_PREAMBLE 2
 #define DHT11_BITS_PER_READ 40
+/*
+ * Note that when reading the sensor actually 84 edges are detected, but
+ * since the last edge is not significant, we only store 83:
+ */
 #define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
 
 /* Data transmission timing (nano seconds) */
@@ -57,6 +62,7 @@ struct dht11 {
        int                             irq;
 
        struct completion               completion;
+       struct mutex                    lock;
 
        s64                             timestamp;
        int                             temperature;
@@ -88,7 +94,7 @@ static int dht11_decode(struct dht11 *dht11, int offset)
        unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
 
        /* Calculate timestamp resolution */
-       for (i = 0; i < dht11->num_edges; ++i) {
+       for (i = 1; i < dht11->num_edges; ++i) {
                t = dht11->edges[i].ts - dht11->edges[i-1].ts;
                if (t > 0 && t < timeres)
                        timeres = t;
@@ -138,6 +144,27 @@ static int dht11_decode(struct dht11 *dht11, int offset)
        return 0;
 }
 
+/*
+ * IRQ handler called on GPIO edges
+ */
+static irqreturn_t dht11_handle_irq(int irq, void *data)
+{
+       struct iio_dev *iio = data;
+       struct dht11 *dht11 = iio_priv(iio);
+
+       /* TODO: Consider making the handler safe for IRQ sharing */
+       if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
+               dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
+               dht11->edges[dht11->num_edges++].value =
+                                               gpio_get_value(dht11->gpio);
+
+               if (dht11->num_edges >= DHT11_EDGES_PER_READ)
+                       complete(&dht11->completion);
+       }
+
+       return IRQ_HANDLED;
+}
+
 static int dht11_read_raw(struct iio_dev *iio_dev,
                        const struct iio_chan_spec *chan,
                        int *val, int *val2, long m)
@@ -145,6 +172,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
        struct dht11 *dht11 = iio_priv(iio_dev);
        int ret;
 
+       mutex_lock(&dht11->lock);
        if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
                reinit_completion(&dht11->completion);
 
@@ -157,8 +185,17 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
                if (ret)
                        goto err;
 
+               ret = request_irq(dht11->irq, dht11_handle_irq,
+                                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                                 iio_dev->name, iio_dev);
+               if (ret)
+                       goto err;
+
                ret = wait_for_completion_killable_timeout(&dht11->completion,
                                                                 HZ);
+
+               free_irq(dht11->irq, iio_dev);
+
                if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
                        dev_err(&iio_dev->dev,
                                        "Only %d signal edges detected\n",
@@ -185,6 +222,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
                ret = -EINVAL;
 err:
        dht11->num_edges = -1;
+       mutex_unlock(&dht11->lock);
        return ret;
 }
 
@@ -193,27 +231,6 @@ static const struct iio_info dht11_iio_info = {
        .read_raw               = dht11_read_raw,
 };
 
-/*
- * IRQ handler called on GPIO edges
-*/
-static irqreturn_t dht11_handle_irq(int irq, void *data)
-{
-       struct iio_dev *iio = data;
-       struct dht11 *dht11 = iio_priv(iio);
-
-       /* TODO: Consider making the handler safe for IRQ sharing */
-       if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
-               dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
-               dht11->edges[dht11->num_edges++].value =
-                                               gpio_get_value(dht11->gpio);
-
-               if (dht11->num_edges >= DHT11_EDGES_PER_READ)
-                       complete(&dht11->completion);
-       }
-
-       return IRQ_HANDLED;
-}
-
 static const struct iio_chan_spec dht11_chan_spec[] = {
        { .type = IIO_TEMP,
                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), },
@@ -256,11 +273,6 @@ static int dht11_probe(struct platform_device *pdev)
                dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio);
                return -EINVAL;
        }
-       ret = devm_request_irq(dev, dht11->irq, dht11_handle_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               pdev->name, iio);
-       if (ret)
-               return ret;
 
        dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
        dht11->num_edges = -1;
@@ -268,6 +280,7 @@ static int dht11_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, iio);
 
        init_completion(&dht11->completion);
+       mutex_init(&dht11->lock);
        iio->name = pdev->name;
        iio->dev.parent = &pdev->dev;
        iio->info = &dht11_iio_info;
index b54164677b898d5c9e5b4b9983fe61271f3c80b5..fa3b809aff5efd425ce96031aec1c066b644feb2 100644 (file)
@@ -45,12 +45,12 @@ static int si7020_read_raw(struct iio_dev *indio_dev,
                           struct iio_chan_spec const *chan, int *val,
                           int *val2, long mask)
 {
-       struct i2c_client *client = iio_priv(indio_dev);
+       struct i2c_client **client = iio_priv(indio_dev);
        int ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               ret = i2c_smbus_read_word_data(client,
+               ret = i2c_smbus_read_word_data(*client,
                                               chan->type == IIO_TEMP ?
                                               SI7020CMD_TEMP_HOLD :
                                               SI7020CMD_RH_HOLD);
@@ -126,7 +126,7 @@ static int si7020_probe(struct i2c_client *client,
        /* Wait the maximum power-up time after software reset. */
        msleep(15);
 
-       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*client));
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (!indio_dev)
                return -ENOMEM;
 
index b70873de04ea50a7cb73f34835f15c43ceff9eb1..fa795dcd5f75ec0a1e8de143bc0122ef36bf9409 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/debugfs.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -414,7 +415,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                mutex_unlock(&indio_dev->mlock);
                if (ret)
                        return ret;
-               val16 = ((val16 & 0xFFF) << 4) >> 4;
+               val16 = sign_extend32(val16, 11);
                *val = val16;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
index f73e60b7a79611b8825bfe90ea3ba5a5e1b253b1..d8d5bed65e072cae577968edb78e2e592c2a5bfa 100644 (file)
@@ -780,7 +780,11 @@ static int inv_mpu_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, indio_dev);
        indio_dev->dev.parent = &client->dev;
-       indio_dev->name = id->name;
+       /* id will be NULL when enumerated via ACPI */
+       if (id)
+               indio_dev->name = (char *)id->name;
+       else
+               indio_dev->name = (char *)dev_name(&client->dev);
        indio_dev->channels = inv_mpu_channels;
        indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
 
index ae68c64bdad3ef7480d15da5d1187c1fd4f7ba4f..a224afd6380c84eff7c76996c7c38eb621493140 100644 (file)
@@ -73,6 +73,7 @@ config CM36651
 config GP2AP020A00F
        tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
        depends on I2C
+       select REGMAP_I2C
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select IRQ_WORK
@@ -126,6 +127,7 @@ config HID_SENSOR_PROX
 config JSA1212
        tristate "JSA1212 ALS and proximity sensor driver"
        depends on I2C
+       select REGMAP_I2C
        help
         Say Y here if you want to build a IIO driver for JSA1212
         proximity & ALS sensor device.
index 4c7a4c52dd06bf7be91a6a1b1d9d56ff7984650c..a5d6de72c523bab274f003cc8431ce05b29630c7 100644 (file)
@@ -18,6 +18,8 @@ config AK8975
 
 config AK09911
        tristate "Asahi Kasei AK09911 3-axis Compass"
+       depends on I2C
+       depends on GPIOLIB
        select AK8975
        help
          Deprecated: AK09911 is now supported by AK8975 driver.
index 9306219d5675442b186b0ab6381fdd246ad09e60..6ad049a08e4d9d27880e62b69a8d249207fa5a13 100644 (file)
@@ -341,6 +341,8 @@ void mei_stop(struct mei_device *dev)
 
        dev->dev_state = MEI_DEV_POWER_DOWN;
        mei_reset(dev);
+       /* move device to disabled state unconditionally */
+       dev->dev_state = MEI_DEV_DISABLED;
 
        mutex_unlock(&dev->device_lock);
 
index 9800c01e6fb97409966e1b35157656ff139f31ea..3f72451d2de01aa44d1b16f633ddd8999894db25 100644 (file)
@@ -426,7 +426,6 @@ static int pci171x_ai_insn_read(struct comedi_device *dev,
                                unsigned int *data)
 {
        struct pci1710_private *devpriv = dev->private;
-       unsigned int chan = CR_CHAN(insn->chanspec);
        int ret = 0;
        int i;
 
@@ -447,7 +446,7 @@ static int pci171x_ai_insn_read(struct comedi_device *dev,
                if (ret)
                        break;
 
-               ret = pci171x_ai_read_sample(dev, s, chan, &val);
+               ret = pci171x_ai_read_sample(dev, s, 0, &val);
                if (ret)
                        break;
 
index dbdea71d6b95b5e3c25a0a2fe2deb9eb57422a94..e856f01ca07716c8acb3881bbe8e4373a64beab5 100644 (file)
@@ -91,9 +91,10 @@ unsigned int comedi_isadma_disable_on_sample(unsigned int dma_chan,
                        stalled++;
                        if (stalled > 10)
                                break;
+               } else {
+                       residue = new_residue;
+                       stalled = 0;
                }
-               residue = new_residue;
-               stalled = 0;
        }
        return residue;
 }
index e37118321a278466ab75f1e51294b2183551bc58..a0906685e27fcb59d9712e9b2619c9f343e5db5e 100644 (file)
@@ -103,11 +103,6 @@ enum vmk80xx_model {
        VMK8061_MODEL
 };
 
-struct firmware_version {
-       unsigned char ic3_vers[32];     /* USB-Controller */
-       unsigned char ic6_vers[32];     /* CPU */
-};
-
 static const struct comedi_lrange vmk8061_range = {
        2, {
                UNI_RANGE(5),
@@ -156,68 +151,12 @@ static const struct vmk80xx_board vmk80xx_boardinfo[] = {
 struct vmk80xx_private {
        struct usb_endpoint_descriptor *ep_rx;
        struct usb_endpoint_descriptor *ep_tx;
-       struct firmware_version fw;
        struct semaphore limit_sem;
        unsigned char *usb_rx_buf;
        unsigned char *usb_tx_buf;
        enum vmk80xx_model model;
 };
 
-static int vmk80xx_check_data_link(struct comedi_device *dev)
-{
-       struct vmk80xx_private *devpriv = dev->private;
-       struct usb_device *usb = comedi_to_usb_dev(dev);
-       unsigned int tx_pipe;
-       unsigned int rx_pipe;
-       unsigned char tx[1];
-       unsigned char rx[2];
-
-       tx_pipe = usb_sndbulkpipe(usb, 0x01);
-       rx_pipe = usb_rcvbulkpipe(usb, 0x81);
-
-       tx[0] = VMK8061_CMD_RD_PWR_STAT;
-
-       /*
-        * Check that IC6 (PIC16F871) is powered and
-        * running and the data link between IC3 and
-        * IC6 is working properly
-        */
-       usb_bulk_msg(usb, tx_pipe, tx, 1, NULL, devpriv->ep_tx->bInterval);
-       usb_bulk_msg(usb, rx_pipe, rx, 2, NULL, HZ * 10);
-
-       return (int)rx[1];
-}
-
-static void vmk80xx_read_eeprom(struct comedi_device *dev, int flag)
-{
-       struct vmk80xx_private *devpriv = dev->private;
-       struct usb_device *usb = comedi_to_usb_dev(dev);
-       unsigned int tx_pipe;
-       unsigned int rx_pipe;
-       unsigned char tx[1];
-       unsigned char rx[64];
-       int cnt;
-
-       tx_pipe = usb_sndbulkpipe(usb, 0x01);
-       rx_pipe = usb_rcvbulkpipe(usb, 0x81);
-
-       tx[0] = VMK8061_CMD_RD_VERSION;
-
-       /*
-        * Read the firmware version info of IC3 and
-        * IC6 from the internal EEPROM of the IC
-        */
-       usb_bulk_msg(usb, tx_pipe, tx, 1, NULL, devpriv->ep_tx->bInterval);
-       usb_bulk_msg(usb, rx_pipe, rx, 64, &cnt, HZ * 10);
-
-       rx[cnt] = '\0';
-
-       if (flag & IC3_VERSION)
-               strncpy(devpriv->fw.ic3_vers, rx + 1, 24);
-       else                    /* IC6_VERSION */
-               strncpy(devpriv->fw.ic6_vers, rx + 25, 24);
-}
-
 static void vmk80xx_do_bulk_msg(struct comedi_device *dev)
 {
        struct vmk80xx_private *devpriv = dev->private;
@@ -878,16 +817,6 @@ static int vmk80xx_auto_attach(struct comedi_device *dev,
 
        usb_set_intfdata(intf, devpriv);
 
-       if (devpriv->model == VMK8061_MODEL) {
-               vmk80xx_read_eeprom(dev, IC3_VERSION);
-               dev_info(&intf->dev, "%s\n", devpriv->fw.ic3_vers);
-
-               if (vmk80xx_check_data_link(dev)) {
-                       vmk80xx_read_eeprom(dev, IC6_VERSION);
-                       dev_info(&intf->dev, "%s\n", devpriv->fw.ic6_vers);
-               }
-       }
-
        if (devpriv->model == VMK8055_MODEL)
                vmk80xx_reset_device(dev);
 
index d9d6fad7cb00725f43142967bad4ca6b39a32b06..816174388f13347447c495700e3dad85e7c269db 100644 (file)
@@ -214,11 +214,17 @@ struct mxs_lradc {
        unsigned long           is_divided;
 
        /*
-        * Touchscreen LRADC channels receives a private slot in the CTRL4
-        * register, the slot #7. Therefore only 7 slots instead of 8 in the
-        * CTRL4 register can be mapped to LRADC channels when using the
-        * touchscreen.
-        *
+        * When the touchscreen is enabled, we give it two private virtual
+        * channels: #6 and #7. This means that only 6 virtual channels (instead
+        * of 8) will be available for buffered capture.
+        */
+#define TOUCHSCREEN_VCHANNEL1          7
+#define TOUCHSCREEN_VCHANNEL2          6
+#define BUFFER_VCHANS_LIMITED          0x3f
+#define BUFFER_VCHANS_ALL              0xff
+       u8                      buffer_vchans;
+
+       /*
         * Furthermore, certain LRADC channels are shared between touchscreen
         * and/or touch-buttons and generic LRADC block. Therefore when using
         * either of these, these channels are not available for the regular
@@ -342,6 +348,9 @@ struct mxs_lradc {
 #define        LRADC_CTRL4                             0x140
 #define        LRADC_CTRL4_LRADCSELECT_MASK(n)         (0xf << ((n) * 4))
 #define        LRADC_CTRL4_LRADCSELECT_OFFSET(n)       ((n) * 4)
+#define        LRADC_CTRL4_LRADCSELECT(n, x) \
+                               (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \
+                               LRADC_CTRL4_LRADCSELECT_MASK(n))
 
 #define LRADC_RESOLUTION                       12
 #define LRADC_SINGLE_SAMPLE_MASK               ((1 << LRADC_RESOLUTION) - 1)
@@ -416,6 +425,14 @@ static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc)
                                        LRADC_STATUS_TOUCH_DETECT_RAW);
 }
 
+static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch,
+                                 unsigned ch)
+{
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch),
+                               LRADC_CTRL4);
+       mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4);
+}
+
 static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
 {
        /*
@@ -450,12 +467,8 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
                LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
                        LRADC_DELAY(3));
 
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
-                       LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
-                       LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1);
 
-       /* wake us again, when the complete conversion is done */
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
        /*
         * after changing the touchscreen plates setting
         * the signals need some initial time to settle. Start the
@@ -509,12 +522,8 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
                LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
                                        LRADC_DELAY(3));
 
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
-                       LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
-                       LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1);
 
-       /* wake us again, when the conversions are done */
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
        /*
         * after changing the touchscreen plates setting
         * the signals need some initial time to settle. Start the
@@ -580,36 +589,6 @@ static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc,
 #define TS_CH_XM 4
 #define TS_CH_YM 5
 
-static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
-{
-       u32 reg;
-       int val;
-
-       reg = readl(lradc->base + LRADC_CTRL1);
-
-       /* only channels 3 to 5 are of interest here */
-       if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
-       } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
-       } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
-       } else {
-               return -EIO;
-       }
-
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
-
-       return val;
-}
-
 /*
  * YP(open)--+-------------+
  *           |             |--+
@@ -653,7 +632,8 @@ static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_X;
-       mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP);
+       mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
 }
 
 /*
@@ -674,7 +654,8 @@ static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_Y;
-       mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM);
+       mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
 }
 
 /*
@@ -695,7 +676,10 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
-       mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP);
+       mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2,
+                                               TOUCHSCREEN_VCHANNEL1);
 }
 
 static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
@@ -708,6 +692,19 @@ static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
 
+static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc)
+{
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
+                               LRADC_CTRL1);
+       mxs_lradc_reg_set(lradc,
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
+       /*
+        * start with the Y-pos, because it uses nearly the same plate
+        * settings like the touch detection
+        */
+       mxs_lradc_prepare_y_pos(lradc);
+}
+
 static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
 {
        input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
@@ -725,10 +722,12 @@ static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc)
         * start a dummy conversion to burn time to settle the signals
         * note: we are not interested in the conversion's value
         */
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
-       mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1));
+       mxs_lradc_reg_clear(lradc,
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
+       mxs_lradc_reg_wrt(lradc,
+               LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) |
                LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
                        LRADC_DELAY(2));
 }
@@ -760,59 +759,45 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
 
        /* if it is released, wait for the next touch via IRQ */
        lradc->cur_plate = LRADC_TOUCH;
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
 
 /* touchscreen's state machine */
 static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
 {
-       int val;
-
        switch (lradc->cur_plate) {
        case LRADC_TOUCH:
-               /*
-                * start with the Y-pos, because it uses nearly the same plate
-                * settings like the touch detection
-                */
-               if (mxs_lradc_check_touch_event(lradc)) {
-                       mxs_lradc_reg_clear(lradc,
-                                       LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-                                       LRADC_CTRL1);
-                       mxs_lradc_prepare_y_pos(lradc);
-               }
+               if (mxs_lradc_check_touch_event(lradc))
+                       mxs_lradc_start_touch_event(lradc);
                mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
                                        LRADC_CTRL1);
                return;
 
        case LRADC_SAMPLE_Y:
-               val = mxs_lradc_read_ts_channel(lradc);
-               if (val < 0) {
-                       mxs_lradc_enable_touch_detection(lradc); /* re-start */
-                       return;
-               }
-               lradc->ts_y_pos = val;
+               lradc->ts_y_pos = mxs_lradc_read_raw_channel(lradc,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_prepare_x_pos(lradc);
                return;
 
        case LRADC_SAMPLE_X:
-               val = mxs_lradc_read_ts_channel(lradc);
-               if (val < 0) {
-                       mxs_lradc_enable_touch_detection(lradc); /* re-start */
-                       return;
-               }
-               lradc->ts_x_pos = val;
+               lradc->ts_x_pos = mxs_lradc_read_raw_channel(lradc,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_prepare_pressure(lradc);
                return;
 
        case LRADC_SAMPLE_PRESSURE:
-               lradc->ts_pressure =
-                       mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+               lradc->ts_pressure = mxs_lradc_read_ts_pressure(lradc,
+                                                       TOUCHSCREEN_VCHANNEL2,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_complete_touch_event(lradc);
                return;
 
        case LRADC_SAMPLE_VALID:
-               val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
                mxs_lradc_finish_touch_event(lradc, 1);
                break;
        }
@@ -844,9 +829,9 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val)
         * used if doing raw sampling.
         */
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0),
                        LRADC_CTRL1);
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+       mxs_lradc_reg_clear(lradc, 0x1, LRADC_CTRL0);
 
        /* Enable / disable the divider per requirement */
        if (test_bit(chan, &lradc->is_divided))
@@ -1090,9 +1075,8 @@ static void mxs_lradc_disable_ts(struct mxs_lradc *lradc)
 {
        /* stop all interrupts from firing */
        mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
-               LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
-               LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
-               LRADC_CTRL1);
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
 
        /* Power-down touchscreen touch-detect circuitry. */
        mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
@@ -1158,26 +1142,31 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
        struct iio_dev *iio = data;
        struct mxs_lradc *lradc = iio_priv(iio);
        unsigned long reg = readl(lradc->base + LRADC_CTRL1);
+       uint32_t clr_irq = mxs_lradc_irq_mask(lradc);
        const uint32_t ts_irq_mask =
                LRADC_CTRL1_TOUCH_DETECT_IRQ |
-               LRADC_CTRL1_LRADC_IRQ(2) |
-               LRADC_CTRL1_LRADC_IRQ(3) |
-               LRADC_CTRL1_LRADC_IRQ(4) |
-               LRADC_CTRL1_LRADC_IRQ(5);
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2);
 
        if (!(reg & mxs_lradc_irq_mask(lradc)))
                return IRQ_NONE;
 
-       if (lradc->use_touchscreen && (reg & ts_irq_mask))
+       if (lradc->use_touchscreen && (reg & ts_irq_mask)) {
                mxs_lradc_handle_touch(lradc);
 
-       if (iio_buffer_enabled(iio))
-               iio_trigger_poll(iio->trig);
-       else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
+               /* Make sure we don't clear the next conversion's interrupt. */
+               clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+                               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2));
+       }
+
+       if (iio_buffer_enabled(iio)) {
+               if (reg & lradc->buffer_vchans)
+                       iio_trigger_poll(iio->trig);
+       } else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) {
                complete(&lradc->completion);
+       }
 
-       mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc),
-                       LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1);
 
        return IRQ_HANDLED;
 }
@@ -1289,9 +1278,10 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
        }
 
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-                                                       LRADC_CTRL1);
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+               mxs_lradc_reg_clear(lradc,
+                       lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
+                       LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0);
 
        for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
                ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
@@ -1324,10 +1314,11 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
        mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
                                        LRADC_DELAY_KICK, LRADC_DELAY(0));
 
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+       mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0);
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-                                       LRADC_CTRL1);
+               mxs_lradc_reg_clear(lradc,
+                       lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
+                       LRADC_CTRL1);
 
        kfree(lradc->buffer);
        mutex_unlock(&lradc->lock);
@@ -1353,7 +1344,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio,
        if (lradc->use_touchbutton)
                rsvd_chans++;
        if (lradc->use_touchscreen)
-               rsvd_chans++;
+               rsvd_chans += 2;
 
        /* Test for attempts to map channels with special mode of operation. */
        if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS))
@@ -1413,6 +1404,13 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
                .channel = 8,
                .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
        },
+       /* Hidden channel to keep indexes */
+       {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .scan_index = -1,
+               .channel = 9,
+       },
        MXS_ADC_CHAN(10, IIO_VOLTAGE),  /* VDDIO */
        MXS_ADC_CHAN(11, IIO_VOLTAGE),  /* VTH */
        MXS_ADC_CHAN(12, IIO_VOLTAGE),  /* VDDA */
@@ -1583,6 +1581,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 
        touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
 
+       if (touch_ret == 0)
+               lradc->buffer_vchans = BUFFER_VCHANS_LIMITED;
+       else
+               lradc->buffer_vchans = BUFFER_VCHANS_ALL;
+
        /* Grab all IRQ sources */
        for (i = 0; i < of_cfg->irq_count; i++) {
                lradc->irq[i] = platform_get_irq(pdev, i);
index 017d2f8379b78ca86f7e30ed0e85855684c7b6ec..c17893b4918c82bf176e9ecfac235cd6439e7763 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -68,7 +69,7 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev,
                break;
        case IIO_ANGL_VEL:
                vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
-               vel = (vel << 4) >> 4;
+               vel = sign_extend32(vel, 11);
                *val = vel;
                break;
        default:
index f88b0887702568578a5d288f925ab1c5b08e7a97..1e25133d35e2cbe8e7476a382bd27433a5801b0c 100644 (file)
@@ -208,7 +208,7 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
                                trip_cnt, GFP_KERNEL);
                if (!int34x_thermal_zone->aux_trips) {
                        ret = -ENOMEM;
-                       goto free_mem;
+                       goto err_trip_alloc;
                }
                trip_mask = BIT(trip_cnt) - 1;
                int34x_thermal_zone->aux_trip_nr = trip_cnt;
@@ -248,14 +248,15 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
                                                0, 0);
        if (IS_ERR(int34x_thermal_zone->zone)) {
                ret = PTR_ERR(int34x_thermal_zone->zone);
-               goto free_lpat;
+               goto err_thermal_zone;
        }
 
        return int34x_thermal_zone;
 
-free_lpat:
+err_thermal_zone:
        acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
-free_mem:
+       kfree(int34x_thermal_zone->aux_trips);
+err_trip_alloc:
        kfree(int34x_thermal_zone);
        return ERR_PTR(ret);
 }
@@ -266,6 +267,7 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone
 {
        thermal_zone_device_unregister(int34x_thermal_zone->zone);
        acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table);
+       kfree(int34x_thermal_zone->aux_trips);
        kfree(int34x_thermal_zone);
 }
 EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove);
index 1fc54ab911d206f0c4b8e2f9aa01b62f8d1f4a22..1d30b0975651547bdc1464befd517eb450957fc0 100644 (file)
@@ -682,6 +682,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
 
        if (on) {
                con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
+               con |= (1 << EXYNOS7_PD_DET_EN_SHIFT);
                interrupt_en =
                        (of_thermal_is_trip_valid(tz, 7)
                        << EXYNOS7_TMU_INTEN_RISE7_SHIFT) |
@@ -704,9 +705,9 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
                        interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
        } else {
                con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
+               con &= ~(1 << EXYNOS7_PD_DET_EN_SHIFT);
                interrupt_en = 0; /* Disable all interrupts */
        }
-       con |= 1 << EXYNOS7_PD_DET_EN_SHIFT;
 
        writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
        writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
index 48491d1a81d650f1d10812c1fb8d5e05ff99cbe1..174d3bcf8bd7a16a161cdf94c53e8d14efaa55a6 100644 (file)
@@ -899,6 +899,22 @@ thermal_cooling_device_trip_point_show(struct device *dev,
                return sprintf(buf, "%d\n", instance->trip);
 }
 
+static struct attribute *cooling_device_attrs[] = {
+       &dev_attr_cdev_type.attr,
+       &dev_attr_max_state.attr,
+       &dev_attr_cur_state.attr,
+       NULL,
+};
+
+static const struct attribute_group cooling_device_attr_group = {
+       .attrs = cooling_device_attrs,
+};
+
+static const struct attribute_group *cooling_device_attr_groups[] = {
+       &cooling_device_attr_group,
+       NULL,
+};
+
 /* Device management */
 
 /**
@@ -1130,6 +1146,7 @@ __thermal_cooling_device_register(struct device_node *np,
        cdev->ops = ops;
        cdev->updated = false;
        cdev->device.class = &thermal_class;
+       cdev->device.groups = cooling_device_attr_groups;
        cdev->devdata = devdata;
        dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
        result = device_register(&cdev->device);
@@ -1139,21 +1156,6 @@ __thermal_cooling_device_register(struct device_node *np,
                return ERR_PTR(result);
        }
 
-       /* sys I/F */
-       if (type) {
-               result = device_create_file(&cdev->device, &dev_attr_cdev_type);
-               if (result)
-                       goto unregister;
-       }
-
-       result = device_create_file(&cdev->device, &dev_attr_max_state);
-       if (result)
-               goto unregister;
-
-       result = device_create_file(&cdev->device, &dev_attr_cur_state);
-       if (result)
-               goto unregister;
-
        /* Add 'this' new cdev to the global cdev list */
        mutex_lock(&thermal_list_lock);
        list_add(&cdev->node, &thermal_cdev_list);
@@ -1163,11 +1165,6 @@ __thermal_cooling_device_register(struct device_node *np,
        bind_cdev(cdev);
 
        return cdev;
-
-unregister:
-       release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id);
-       device_unregister(&cdev->device);
-       return ERR_PTR(result);
 }
 
 /**
index d7b198c400c755487309cf6e6d9b615c9cfe4a69..ce24182f851479ab61372d1091840696cfe6857f 100644 (file)
@@ -210,18 +210,6 @@ bfin_jc_chars_in_buffer(struct tty_struct *tty)
        return circ_cnt(&bfin_jc_write_buf);
 }
 
-static void
-bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-       unsigned long expire = jiffies + timeout;
-       while (!circ_empty(&bfin_jc_write_buf)) {
-               if (signal_pending(current))
-                       break;
-               if (time_after(jiffies, expire))
-                       break;
-       }
-}
-
 static const struct tty_operations bfin_jc_ops = {
        .open            = bfin_jc_open,
        .close           = bfin_jc_close,
@@ -230,7 +218,6 @@ static const struct tty_operations bfin_jc_ops = {
        .flush_chars     = bfin_jc_flush_chars,
        .write_room      = bfin_jc_write_room,
        .chars_in_buffer = bfin_jc_chars_in_buffer,
-       .wait_until_sent = bfin_jc_wait_until_sent,
 };
 
 static int __init bfin_jc_init(void)
index e3b9570a1eff8aa467ec7dabbe93369c47940e87..deae122c9c4bac6a2bb28d6bbc191bfc18d16747 100644 (file)
@@ -2138,8 +2138,8 @@ int serial8250_do_startup(struct uart_port *port)
        /*
         * Clear the interrupt registers.
         */
-       if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
-               serial_port_in(port, UART_RX);
+       serial_port_in(port, UART_LSR);
+       serial_port_in(port, UART_RX);
        serial_port_in(port, UART_IIR);
        serial_port_in(port, UART_MSR);
 
@@ -2300,8 +2300,8 @@ dont_test_tx_en:
         * saved flags to avoid getting false values from polling
         * routines or the previous session.
         */
-       if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
-               serial_port_in(port, UART_RX);
+       serial_port_in(port, UART_LSR);
+       serial_port_in(port, UART_RX);
        serial_port_in(port, UART_IIR);
        serial_port_in(port, UART_MSR);
        up->lsr_saved_flags = 0;
@@ -2394,8 +2394,7 @@ void serial8250_do_shutdown(struct uart_port *port)
         * Read data port to reset things, and then unlink from
         * the IRQ chain.
         */
-       if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
-               serial_port_in(port, UART_RX);
+       serial_port_in(port, UART_RX);
        serial8250_rpm_put(up);
 
        del_timer_sync(&up->timer);
index e60116235836498e5b20ce56219b7d8c949acd25..2ab229ddee389ee20fa7923f93e43ddda944bbf0 100644 (file)
@@ -59,6 +59,8 @@ struct dw8250_data {
        u8                      usr_reg;
        int                     last_mcr;
        int                     line;
+       int                     msr_mask_on;
+       int                     msr_mask_off;
        struct clk              *clk;
        struct clk              *pclk;
        struct reset_control    *rst;
@@ -81,6 +83,12 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
                value &= ~UART_MSR_DCTS;
        }
 
+       /* Override any modem control signals if needed */
+       if (offset == UART_MSR) {
+               value |= d->msr_mask_on;
+               value &= ~d->msr_mask_off;
+       }
+
        return value;
 }
 
@@ -334,6 +342,30 @@ static int dw8250_probe_of(struct uart_port *p,
        if (id >= 0)
                p->line = id;
 
+       if (of_property_read_bool(np, "dcd-override")) {
+               /* Always report DCD as active */
+               data->msr_mask_on |= UART_MSR_DCD;
+               data->msr_mask_off |= UART_MSR_DDCD;
+       }
+
+       if (of_property_read_bool(np, "dsr-override")) {
+               /* Always report DSR as active */
+               data->msr_mask_on |= UART_MSR_DSR;
+               data->msr_mask_off |= UART_MSR_DDSR;
+       }
+
+       if (of_property_read_bool(np, "cts-override")) {
+               /* Always report DSR as active */
+               data->msr_mask_on |= UART_MSR_DSR;
+               data->msr_mask_off |= UART_MSR_DDSR;
+       }
+
+       if (of_property_read_bool(np, "ri-override")) {
+               /* Always report Ring indicator as inactive */
+               data->msr_mask_off |= UART_MSR_RI;
+               data->msr_mask_off |= UART_MSR_TERI;
+       }
+
        /* clock got configured through clk api, all done */
        if (p->uartclk)
                return 0;
index daf2c82984e95d94d806b175bc59944ac1cd9713..892eb32cdef4bd98586d02e2e432c38aea512797 100644 (file)
@@ -69,7 +69,7 @@ static void moan_device(const char *str, struct pci_dev *dev)
               "Please send the output of lspci -vv, this\n"
               "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
               "manufacturer and name of serial board or\n"
-              "modem board to rmk+serial@arm.linux.org.uk.\n",
+              "modem board to <linux-serial@vger.kernel.org>.\n",
               pci_name(dev), str, dev->vendor, dev->device,
               dev->subsystem_vendor, dev->subsystem_device);
 }
@@ -1987,13 +1987,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = byt_serial_setup,
        },
-       {
-               .vendor         = PCI_VENDOR_ID_INTEL,
-               .device         = PCI_DEVICE_ID_INTEL_QRK_UART,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_default_setup,
-       },
        {
                .vendor         = PCI_VENDOR_ID_INTEL,
                .device         = PCI_DEVICE_ID_INTEL_BSW_UART1,
@@ -2199,13 +2192,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
        /*
         * PLX
         */
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_9030,
-               .subvendor      = PCI_SUBVENDOR_ID_PERLE,
-               .subdevice      = PCI_ANY_ID,
-               .setup          = pci_default_setup,
-       },
        {
                .vendor         = PCI_VENDOR_ID_PLX,
                .device         = PCI_DEVICE_ID_PLX_9050,
@@ -5415,10 +5401,6 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID,
                0, 0, pbn_b0_bt_2_115200 },
 
-       {       PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH352_2S,
-               PCI_ANY_ID, PCI_ANY_ID,
-               0, 0, pbn_b0_bt_2_115200 },
-
        {       PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
                PCI_ANY_ID, PCI_ANY_ID,
                0, 0, pbn_wch384_4 },
index 7ff61e24a195cbca54d60aaefd65bbdf3d0af187..33fb94f7896773c53141ec283f15a3a18be96f1a 100644 (file)
@@ -133,10 +133,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
        if (of_find_property(np, "no-loopback-test", NULL))
                port->flags |= UPF_SKIP_TEST;
 
-       ret = of_alias_get_id(np, "serial");
-       if (ret >= 0)
-               port->line = ret;
-
        port->dev = &ofdev->dev;
 
        switch (type) {
index 594b63331ef40e42fa75a87cde1c139a46014398..bca975f5093b73fd5ebf3e0f4ec8c42e97dfea35 100644 (file)
@@ -293,8 +293,10 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
 
        ims = serial_in(port, SPRD_IMSR);
 
-       if (!ims)
+       if (!ims) {
+               spin_unlock(&port->lock);
                return IRQ_NONE;
+       }
 
        serial_out(port, SPRD_ICLR, ~0);
 
index 51f066aa375e64789e03b9a527679e3a0a7e1c8d..2bb4dfc028734079f29a89bfb779bfdc7e0079eb 100644 (file)
@@ -1028,8 +1028,8 @@ EXPORT_SYMBOL(start_tty);
 /* We limit tty time update visibility to every 8 seconds or so. */
 static void tty_update_time(struct timespec *time)
 {
-       unsigned long sec = get_seconds() & ~7;
-       if ((long)(sec - time->tv_sec) > 0)
+       unsigned long sec = get_seconds();
+       if (abs(sec - time->tv_sec) & ~7)
                time->tv_sec = sec;
 }
 
index a5cf253b2544f001a775f93a7905e63475f7eb7e..632fc815206169281af9aa13f6ca345eb846eabe 100644 (file)
@@ -217,11 +217,17 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 #endif
        if (!timeout)
                timeout = MAX_SCHEDULE_TIMEOUT;
-       if (wait_event_interruptible_timeout(tty->write_wait,
-                       !tty_chars_in_buffer(tty), timeout) >= 0) {
-               if (tty->ops->wait_until_sent)
-                       tty->ops->wait_until_sent(tty, timeout);
-       }
+
+       timeout = wait_event_interruptible_timeout(tty->write_wait,
+                       !tty_chars_in_buffer(tty), timeout);
+       if (timeout <= 0)
+               return;
+
+       if (timeout == MAX_SCHEDULE_TIMEOUT)
+               timeout = 0;
+
+       if (tty->ops->wait_until_sent)
+               tty->ops->wait_until_sent(tty, timeout);
 }
 EXPORT_SYMBOL(tty_wait_until_sent);
 
index e78720b59d67e66adebff9594475b124341b0608..683617714e7cf852fdf3fc2d4ec8590ab6d1a114 100644 (file)
@@ -1650,6 +1650,8 @@ static int acm_reset_resume(struct usb_interface *intf)
 
 static const struct usb_device_id acm_ids[] = {
        /* quirky and broken devices */
+       { USB_DEVICE(0x076d, 0x0006), /* Denso Cradle CU-321 */
+       .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
        { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */
        .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
        { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
index 66abdbcfbfa55c08c4989d5ce4fe16b087486a79..11635537c052cdc5d4e4c78d615a09aafc4c5e83 100644 (file)
@@ -501,6 +501,7 @@ static void async_completed(struct urb *urb)
        as->status = urb->status;
        signr = as->signr;
        if (signr) {
+               memset(&sinfo, 0, sizeof(sinfo));
                sinfo.si_signo = as->signr;
                sinfo.si_errno = as->status;
                sinfo.si_code = SI_ASYNCIO;
@@ -2382,6 +2383,7 @@ static void usbdev_remove(struct usb_device *udev)
                wake_up_all(&ps->wait);
                list_del_init(&ps->list);
                if (ps->discsignr) {
+                       memset(&sinfo, 0, sizeof(sinfo));
                        sinfo.si_signo = ps->discsignr;
                        sinfo.si_errno = EPIPE;
                        sinfo.si_code = SI_ASYNCIO;
index 172d64e585b61b014f3333ef200d2cb2ba48958d..52e0c4e5e48efa8cc1ccecf0ee30364ff1419634 100644 (file)
@@ -205,6 +205,18 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value)
                                                omap->irq0_offset, value);
 }
 
+static void dwc3_omap_write_irqmisc_clr(struct dwc3_omap *omap, u32 value)
+{
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_MISC +
+                                               omap->irqmisc_offset, value);
+}
+
+static void dwc3_omap_write_irq0_clr(struct dwc3_omap *omap, u32 value)
+{
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_0 -
+                                               omap->irq0_offset, value);
+}
+
 static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
        enum omap_dwc3_vbus_id_status status)
 {
@@ -345,9 +357,23 @@ static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
 
 static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
 {
+       u32                     reg;
+
        /* disable all IRQs */
-       dwc3_omap_write_irqmisc_set(omap, 0x00);
-       dwc3_omap_write_irq0_set(omap, 0x00);
+       reg = USBOTGSS_IRQO_COREIRQ_ST;
+       dwc3_omap_write_irq0_clr(omap, reg);
+
+       reg = (USBOTGSS_IRQMISC_OEVT |
+                       USBOTGSS_IRQMISC_DRVVBUS_RISE |
+                       USBOTGSS_IRQMISC_CHRGVBUS_RISE |
+                       USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
+                       USBOTGSS_IRQMISC_IDPULLUP_RISE |
+                       USBOTGSS_IRQMISC_DRVVBUS_FALL |
+                       USBOTGSS_IRQMISC_CHRGVBUS_FALL |
+                       USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
+                       USBOTGSS_IRQMISC_IDPULLUP_FALL);
+
+       dwc3_omap_write_irqmisc_clr(omap, reg);
 }
 
 static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
index 75648145dc1b686a89cae9f8d4de451b71ef376a..c42765b3a060bc6b28b0f7a55f0231489afe651c 100644 (file)
@@ -1161,7 +1161,6 @@ static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
        if (desc->opts_mutex)
                mutex_lock(desc->opts_mutex);
        memcpy(desc->ext_compat_id, page, l);
-       desc->ext_compat_id[l] = '\0';
 
        if (desc->opts_mutex)
                mutex_unlock(desc->opts_mutex);
@@ -1192,7 +1191,6 @@ static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
        if (desc->opts_mutex)
                mutex_lock(desc->opts_mutex);
        memcpy(desc->ext_compat_id + 8, page, l);
-       desc->ext_compat_id[l + 8] = '\0';
 
        if (desc->opts_mutex)
                mutex_unlock(desc->opts_mutex);
index 426d69a9c018a0a651beac78ce63709c4b283613..a2612fb79eff261ee336b73940f88e7514f9c5e0 100644 (file)
@@ -569,7 +569,7 @@ fail:
        return status;
 }
 
-const struct file_operations f_hidg_fops = {
+static const struct file_operations f_hidg_fops = {
        .owner          = THIS_MODULE,
        .open           = f_hidg_open,
        .release        = f_hidg_release,
index c89e96cfa3e47b95d179d06910d528710e59d5de..c0c3ef272714b58ea4980ba25cf24076b502a105 100644 (file)
@@ -417,7 +417,10 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                        return -EINVAL;
 
                spin_lock(&port->lock);
-               __pn_reset(f);
+
+               if (fp->in_ep->driver_data)
+                       __pn_reset(f);
+
                if (alt == 1) {
                        int i;
 
index e07c50ced64ddc09256b271f72a5baacfc3b8f18..e3dae47baef3d3bfcf8d7dc5124cc22bbcc8a272 100644 (file)
@@ -344,7 +344,7 @@ static struct usb_endpoint_descriptor ss_int_source_desc = {
        .bInterval =            USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL),
 };
 
-struct usb_ss_ep_comp_descriptor ss_int_source_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_int_source_comp_desc = {
        .bLength =              USB_DT_SS_EP_COMP_SIZE,
        .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 
@@ -362,7 +362,7 @@ static struct usb_endpoint_descriptor ss_int_sink_desc = {
        .bInterval =            USB_MS_TO_SS_INTERVAL(GZERO_INT_INTERVAL),
 };
 
-struct usb_ss_ep_comp_descriptor ss_int_sink_comp_desc = {
+static struct usb_ss_ep_comp_descriptor ss_int_sink_comp_desc = {
        .bLength =              USB_DT_SS_EP_COMP_SIZE,
        .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 
index 33e16658e5cfeb50d01c44c7a63a2379634e82b7..6d3eb8b00a488446db954334e80ac12eccf0d5cf 100644 (file)
@@ -54,7 +54,7 @@
 #define UNFLW_CTRL     8
 #define OVFLW_CTRL     10
 
-const char *uac2_name = "snd_uac2";
+static const char *uac2_name = "snd_uac2";
 
 struct uac2_req {
        struct uac2_rtd_params *pp; /* parent param */
@@ -634,7 +634,7 @@ static struct usb_interface_descriptor std_ac_if_desc = {
 };
 
 /* Clock source for IN traffic */
-struct uac_clock_source_descriptor in_clk_src_desc = {
+static struct uac_clock_source_descriptor in_clk_src_desc = {
        .bLength = sizeof in_clk_src_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -646,7 +646,7 @@ struct uac_clock_source_descriptor in_clk_src_desc = {
 };
 
 /* Clock source for OUT traffic */
-struct uac_clock_source_descriptor out_clk_src_desc = {
+static struct uac_clock_source_descriptor out_clk_src_desc = {
        .bLength = sizeof out_clk_src_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -658,7 +658,7 @@ struct uac_clock_source_descriptor out_clk_src_desc = {
 };
 
 /* Input Terminal for USB_OUT */
-struct uac2_input_terminal_descriptor usb_out_it_desc = {
+static struct uac2_input_terminal_descriptor usb_out_it_desc = {
        .bLength = sizeof usb_out_it_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -672,7 +672,7 @@ struct uac2_input_terminal_descriptor usb_out_it_desc = {
 };
 
 /* Input Terminal for I/O-In */
-struct uac2_input_terminal_descriptor io_in_it_desc = {
+static struct uac2_input_terminal_descriptor io_in_it_desc = {
        .bLength = sizeof io_in_it_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -686,7 +686,7 @@ struct uac2_input_terminal_descriptor io_in_it_desc = {
 };
 
 /* Ouput Terminal for USB_IN */
-struct uac2_output_terminal_descriptor usb_in_ot_desc = {
+static struct uac2_output_terminal_descriptor usb_in_ot_desc = {
        .bLength = sizeof usb_in_ot_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -700,7 +700,7 @@ struct uac2_output_terminal_descriptor usb_in_ot_desc = {
 };
 
 /* Ouput Terminal for I/O-Out */
-struct uac2_output_terminal_descriptor io_out_ot_desc = {
+static struct uac2_output_terminal_descriptor io_out_ot_desc = {
        .bLength = sizeof io_out_ot_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -713,7 +713,7 @@ struct uac2_output_terminal_descriptor io_out_ot_desc = {
        .bmControls = (CONTROL_RDWR << COPY_CTRL),
 };
 
-struct uac2_ac_header_descriptor ac_hdr_desc = {
+static struct uac2_ac_header_descriptor ac_hdr_desc = {
        .bLength = sizeof ac_hdr_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -751,7 +751,7 @@ static struct usb_interface_descriptor std_as_out_if1_desc = {
 };
 
 /* Audio Stream OUT Intface Desc */
-struct uac2_as_header_descriptor as_out_hdr_desc = {
+static struct uac2_as_header_descriptor as_out_hdr_desc = {
        .bLength = sizeof as_out_hdr_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -764,7 +764,7 @@ struct uac2_as_header_descriptor as_out_hdr_desc = {
 };
 
 /* Audio USB_OUT Format */
-struct uac2_format_type_i_descriptor as_out_fmt1_desc = {
+static struct uac2_format_type_i_descriptor as_out_fmt1_desc = {
        .bLength = sizeof as_out_fmt1_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
        .bDescriptorSubtype = UAC_FORMAT_TYPE,
@@ -772,7 +772,7 @@ struct uac2_format_type_i_descriptor as_out_fmt1_desc = {
 };
 
 /* STD AS ISO OUT Endpoint */
-struct usb_endpoint_descriptor fs_epout_desc = {
+static struct usb_endpoint_descriptor fs_epout_desc = {
        .bLength = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType = USB_DT_ENDPOINT,
 
@@ -782,7 +782,7 @@ struct usb_endpoint_descriptor fs_epout_desc = {
        .bInterval = 1,
 };
 
-struct usb_endpoint_descriptor hs_epout_desc = {
+static struct usb_endpoint_descriptor hs_epout_desc = {
        .bLength = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType = USB_DT_ENDPOINT,
 
@@ -828,7 +828,7 @@ static struct usb_interface_descriptor std_as_in_if1_desc = {
 };
 
 /* Audio Stream IN Intface Desc */
-struct uac2_as_header_descriptor as_in_hdr_desc = {
+static struct uac2_as_header_descriptor as_in_hdr_desc = {
        .bLength = sizeof as_in_hdr_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
 
@@ -841,7 +841,7 @@ struct uac2_as_header_descriptor as_in_hdr_desc = {
 };
 
 /* Audio USB_IN Format */
-struct uac2_format_type_i_descriptor as_in_fmt1_desc = {
+static struct uac2_format_type_i_descriptor as_in_fmt1_desc = {
        .bLength = sizeof as_in_fmt1_desc,
        .bDescriptorType = USB_DT_CS_INTERFACE,
        .bDescriptorSubtype = UAC_FORMAT_TYPE,
@@ -849,7 +849,7 @@ struct uac2_format_type_i_descriptor as_in_fmt1_desc = {
 };
 
 /* STD AS ISO IN Endpoint */
-struct usb_endpoint_descriptor fs_epin_desc = {
+static struct usb_endpoint_descriptor fs_epin_desc = {
        .bLength = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType = USB_DT_ENDPOINT,
 
@@ -859,7 +859,7 @@ struct usb_endpoint_descriptor fs_epin_desc = {
        .bInterval = 1,
 };
 
-struct usb_endpoint_descriptor hs_epin_desc = {
+static struct usb_endpoint_descriptor hs_epin_desc = {
        .bLength = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType = USB_DT_ENDPOINT,
 
@@ -1563,7 +1563,7 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
                agdev->out_ep->driver_data = NULL;
 }
 
-struct usb_function *afunc_alloc(struct usb_function_instance *fi)
+static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
 {
        struct audio_dev *agdev;
        struct f_uac2_opts *opts;
index 5aad7fededa589bdb7b143a9f6dfbfb65c81cedd..8b818fd027b3380772030c2a650c67df830a4e56 100644 (file)
@@ -27,6 +27,7 @@
 #include "uvc.h"
 #include "uvc_queue.h"
 #include "uvc_video.h"
+#include "uvc_v4l2.h"
 
 /* --------------------------------------------------------------------------
  * Requests handling
index 9cb86bc1a9a5444b4ed7895489c2b0c5860bac37..50a5e637ca35ad804925112675e54b2ee115b80f 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "uvc.h"
 #include "uvc_queue.h"
+#include "uvc_video.h"
 
 /* --------------------------------------------------------------------------
  * Video codecs
index 06acfa55864a639a6015689770b4ccb06f01ad40..b01b88e1b716a5902d5276196ef459663545a216 100644 (file)
@@ -133,7 +133,9 @@ struct gfs_configuration {
        struct usb_configuration c;
        int (*eth)(struct usb_configuration *c);
        int num;
-} gfs_configurations[] = {
+};
+
+static struct gfs_configuration gfs_configurations[] = {
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
        {
                .eth            = bind_rndis_config,
@@ -278,7 +280,7 @@ static void *functionfs_acquire_dev(struct ffs_dev *dev)
        if (!try_module_get(THIS_MODULE))
                return ERR_PTR(-ENOENT);
        
-       return 0;
+       return NULL;
 }
 
 static void functionfs_release_dev(struct ffs_dev *dev)
index 7f76c8a12f89db425e19c4f3a2a5200de542dbd7..fd53c9ebd662a5fb4593c99ce5dd7c2552ad83c5 100644 (file)
@@ -37,6 +37,9 @@
 
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI     0x8c31
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI  0x9c31
+#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI            0x22b5
+#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI                0xa12f
+#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI       0x9d2f
 
 static const char hcd_name[] = "xhci_hcd";
 
@@ -133,6 +136,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
        }
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+               (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
+               xhci->quirks |= XHCI_PME_STUCK_QUIRK;
+       }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_EJ168) {
                xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -159,6 +168,21 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                                "QUIRK: Resetting on resume");
 }
 
+/*
+ * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
+ * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
+ */
+static void xhci_pme_quirk(struct xhci_hcd *xhci)
+{
+       u32 val;
+       void __iomem *reg;
+
+       reg = (void __iomem *) xhci->cap_regs + 0x80a4;
+       val = readl(reg);
+       writel(val | BIT(28), reg);
+       readl(reg);
+}
+
 /* called during probe() after chip reset completes */
 static int xhci_pci_setup(struct usb_hcd *hcd)
 {
@@ -283,6 +307,9 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
        if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
                pdev->no_d3cold = true;
 
+       if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+               xhci_pme_quirk(xhci);
+
        return xhci_suspend(xhci, do_wakeup);
 }
 
@@ -313,6 +340,9 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
        if (pdev->vendor == PCI_VENDOR_ID_INTEL)
                usb_enable_intel_xhci_ports(pdev);
 
+       if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+               xhci_pme_quirk(xhci);
+
        retval = xhci_resume(xhci, hibernated);
        return retval;
 }
index 08d402b15482d936ca36d6d20cc381d8279a35a2..0e11d61408ff3f95a3110636e858119f4037cf0c 100644 (file)
@@ -83,16 +83,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
        if (irq < 0)
                return -ENODEV;
 
-
-       if (of_device_is_compatible(pdev->dev.of_node,
-                                   "marvell,armada-375-xhci") ||
-           of_device_is_compatible(pdev->dev.of_node,
-                                   "marvell,armada-380-xhci")) {
-               ret = xhci_mvebu_mbus_init_quirk(pdev);
-               if (ret)
-                       return ret;
-       }
-
        /* Initialize dma_mask and coherent_dma_mask to 32-bits */
        ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
        if (ret)
@@ -127,6 +117,15 @@ static int xhci_plat_probe(struct platform_device *pdev)
                        goto put_hcd;
        }
 
+       if (of_device_is_compatible(pdev->dev.of_node,
+                                   "marvell,armada-375-xhci") ||
+           of_device_is_compatible(pdev->dev.of_node,
+                                   "marvell,armada-380-xhci")) {
+               ret = xhci_mvebu_mbus_init_quirk(pdev);
+               if (ret)
+                       goto disable_clk;
+       }
+
        ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (ret)
                goto disable_clk;
index 88da8d6298201fa5c7b7e4a93ff67fe303cb84b5..5fb66db89e05549da9cd4e94a15abbbcc3ba5a19 100644 (file)
@@ -1729,7 +1729,7 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
        if (!command)
                return;
 
-       ep->ep_state |= EP_HALTED;
+       ep->ep_state |= EP_HALTED | EP_RECENTLY_HALTED;
        ep->stopped_stream = stream_id;
 
        xhci_queue_reset_ep(xhci, command, slot_id, ep_index);
@@ -1946,7 +1946,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
        if (event_trb != ep_ring->dequeue) {
                /* The event was for the status stage */
                if (event_trb == td->last_trb) {
-                       if (td->urb->actual_length != 0) {
+                       if (td->urb_length_set) {
                                /* Don't overwrite a previously set error code
                                 */
                                if ((*status == -EINPROGRESS || *status == 0) &&
@@ -1960,7 +1960,13 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                                        td->urb->transfer_buffer_length;
                        }
                } else {
-               /* Maybe the event was for the data stage? */
+                       /*
+                        * Maybe the event was for the data stage? If so, update
+                        * already the actual_length of the URB and flag it as
+                        * set, so that it is not overwritten in the event for
+                        * the last TRB.
+                        */
+                       td->urb_length_set = true;
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
index ec8ac16748547a2ac87bf9aa225ed0a36c0bf7df..b06d1a53652da3ff9446e99c870c4c56fe044e5e 100644 (file)
@@ -1338,6 +1338,12 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                goto exit;
        }
 
+       /* Reject urb if endpoint is in soft reset, queue must stay empty */
+       if (xhci->devs[slot_id]->eps[ep_index].ep_state & EP_CONFIG_PENDING) {
+               xhci_warn(xhci, "Can't enqueue URB while ep is in soft reset\n");
+               ret = -EINVAL;
+       }
+
        if (usb_endpoint_xfer_isoc(&urb->ep->desc))
                size = urb->number_of_packets;
        else
@@ -2948,23 +2954,36 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
        }
 }
 
-/* Called when clearing halted device. The core should have sent the control
+/* Called after clearing a halted device. USB core should have sent the control
  * message to clear the device halt condition. The host side of the halt should
- * already be cleared with a reset endpoint command issued when the STALL tx
- * event was received.
- *
- * Context: in_interrupt
+ * already be cleared with a reset endpoint command issued immediately when the
+ * STALL tx event was received.
  */
 
 void xhci_endpoint_reset(struct usb_hcd *hcd,
                struct usb_host_endpoint *ep)
 {
        struct xhci_hcd *xhci;
+       struct usb_device *udev;
+       struct xhci_virt_device *virt_dev;
+       struct xhci_virt_ep *virt_ep;
+       struct xhci_input_control_ctx *ctrl_ctx;
+       struct xhci_command *command;
+       unsigned int ep_index, ep_state;
+       unsigned long flags;
+       u32 ep_flag;
 
        xhci = hcd_to_xhci(hcd);
+       udev = (struct usb_device *) ep->hcpriv;
+       if (!ep->hcpriv)
+               return;
+       virt_dev = xhci->devs[udev->slot_id];
+       ep_index = xhci_get_endpoint_index(&ep->desc);
+       virt_ep = &virt_dev->eps[ep_index];
+       ep_state = virt_ep->ep_state;
 
        /*
-        * We might need to implement the config ep cmd in xhci 4.8.1 note:
+        * Implement the config ep command in xhci 4.6.8 additional note:
         * The Reset Endpoint Command may only be issued to endpoints in the
         * Halted state. If software wishes reset the Data Toggle or Sequence
         * Number of an endpoint that isn't in the Halted state, then software
@@ -2972,9 +2991,72 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
         * for the target endpoint. that is in the Stopped state.
         */
 
-       /* For now just print debug to follow the situation */
-       xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n",
-                ep->desc.bEndpointAddress);
+       if (ep_state & SET_DEQ_PENDING || ep_state & EP_RECENTLY_HALTED) {
+               virt_ep->ep_state &= ~EP_RECENTLY_HALTED;
+               xhci_dbg(xhci, "ep recently halted, no toggle reset needed\n");
+               return;
+       }
+
+       /* Only interrupt and bulk ep's use Data toggle, USB2 spec 5.5.4-> */
+       if (usb_endpoint_xfer_control(&ep->desc) ||
+           usb_endpoint_xfer_isoc(&ep->desc))
+               return;
+
+       ep_flag = xhci_get_endpoint_flag(&ep->desc);
+
+       if (ep_flag == SLOT_FLAG || ep_flag == EP0_FLAG)
+               return;
+
+       command = xhci_alloc_command(xhci, true, true, GFP_NOWAIT);
+       if (!command) {
+               xhci_err(xhci, "Could not allocate xHCI command structure.\n");
+               return;
+       }
+
+       spin_lock_irqsave(&xhci->lock, flags);
+
+       /* block ringing ep doorbell */
+       virt_ep->ep_state |= EP_CONFIG_PENDING;
+
+       /*
+        * Make sure endpoint ring is empty before resetting the toggle/seq.
+        * Driver is required to synchronously cancel all transfer request.
+        *
+        * xhci 4.6.6 says we can issue a configure endpoint command on a
+        * running endpoint ring as long as it's idle (queue empty)
+        */
+
+       if (!list_empty(&virt_ep->ring->td_list)) {
+               dev_err(&udev->dev, "EP not empty, refuse reset\n");
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               goto cleanup;
+       }
+
+       xhci_dbg(xhci, "Reset toggle/seq for slot %d, ep_index: %d\n",
+                udev->slot_id, ep_index);
+
+       ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx);
+       if (!ctrl_ctx) {
+               xhci_err(xhci, "Could not get input context, bad type. virt_dev: %p, in_ctx %p\n",
+                        virt_dev, virt_dev->in_ctx);
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               goto cleanup;
+       }
+       xhci_setup_input_ctx_for_config_ep(xhci, command->in_ctx,
+                                          virt_dev->out_ctx, ctrl_ctx,
+                                          ep_flag, ep_flag);
+       xhci_endpoint_copy(xhci, command->in_ctx, virt_dev->out_ctx, ep_index);
+
+       xhci_queue_configure_endpoint(xhci, command, command->in_ctx->dma,
+                                    udev->slot_id, false);
+       xhci_ring_cmd_db(xhci);
+       spin_unlock_irqrestore(&xhci->lock, flags);
+
+       wait_for_completion(command->completion);
+
+cleanup:
+       virt_ep->ep_state &= ~EP_CONFIG_PENDING;
+       xhci_free_command(xhci, command);
 }
 
 static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
index 974514762a1402aee4164cf5556c9321bea49d44..265ab1771d24c887d1ba950f2c77f9ee38144438 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * xHCI host controller driver
  *
@@ -88,9 +89,10 @@ struct xhci_cap_regs {
 #define HCS_IST(p)             (((p) >> 0) & 0xf)
 /* bits 4:7, max number of Event Ring segments */
 #define HCS_ERST_MAX(p)                (((p) >> 4) & 0xf)
+/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */
 /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
-/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */
-#define HCS_MAX_SCRATCHPAD(p)   (((p) >> 27) & 0x1f)
+/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */
+#define HCS_MAX_SCRATCHPAD(p)   ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f))
 
 /* HCSPARAMS3 - hcs_params3 - bitmasks */
 /* bits 0:7, Max U1 to U0 latency for the roothub ports */
@@ -863,6 +865,8 @@ struct xhci_virt_ep {
 #define EP_HAS_STREAMS         (1 << 4)
 /* Transitioning the endpoint to not using streams, don't enqueue URBs */
 #define EP_GETTING_NO_STREAMS  (1 << 5)
+#define EP_RECENTLY_HALTED     (1 << 6)
+#define EP_CONFIG_PENDING      (1 << 7)
        /* ----  Related to URB cancellation ---- */
        struct list_head        cancelled_td_list;
        struct xhci_td          *stopped_td;
@@ -1288,6 +1292,8 @@ struct xhci_td {
        struct xhci_segment     *start_seg;
        union xhci_trb          *first_trb;
        union xhci_trb          *last_trb;
+       /* actual_length of the URB has already been set */
+       bool                    urb_length_set;
 };
 
 /* xHCI command default timeout value */
@@ -1560,6 +1566,7 @@ struct xhci_hcd {
 #define XHCI_SPURIOUS_WAKEUP   (1 << 18)
 /* For controllers with a broken beyond repair streams implementation */
 #define XHCI_BROKEN_STREAMS    (1 << 19)
+#define XHCI_PME_STUCK_QUIRK   (1 << 20)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index eba9b82e2d70c19c5b75dc1b6c3d6a0182ee4d5e..3cb98b1d5d2960171bea26d4fff70e2217d9e7f0 100644 (file)
@@ -1274,7 +1274,7 @@ static void errata2_function(unsigned long data)
        for (slot = 0; slot < 32; slot++)
                if (priv->atl_slots[slot].qh && time_after(jiffies,
                                        priv->atl_slots[slot].timestamp +
-                                       SLOT_TIMEOUT * HZ / 1000)) {
+                                       msecs_to_jiffies(SLOT_TIMEOUT))) {
                        ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
                        if (!FROM_DW0_VALID(ptd.dw0) &&
                                        !FROM_DW3_ACTIVE(ptd.dw3))
@@ -1286,7 +1286,7 @@ static void errata2_function(unsigned long data)
 
        spin_unlock_irqrestore(&priv->lock, spinflags);
 
-       errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000;
+       errata2_timer.expires = jiffies + msecs_to_jiffies(SLOT_CHECK_PERIOD);
        add_timer(&errata2_timer);
 }
 
@@ -1336,7 +1336,7 @@ static int isp1760_run(struct usb_hcd *hcd)
                return retval;
 
        setup_timer(&errata2_timer, errata2_function, (unsigned long)hcd);
-       errata2_timer.expires = jiffies + SLOT_CHECK_PERIOD * HZ / 1000;
+       errata2_timer.expires = jiffies + msecs_to_jiffies(SLOT_CHECK_PERIOD);
        add_timer(&errata2_timer);
 
        chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG);
index e6f4cbfeed9736006e852c306aed7f4839987a95..067920f2d570fb77be332cf16e885bf63e0a352c 100644 (file)
@@ -1969,10 +1969,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
                goto fail0;
        }
 
-       pm_runtime_use_autosuspend(musb->controller);
-       pm_runtime_set_autosuspend_delay(musb->controller, 200);
-       pm_runtime_enable(musb->controller);
-
        spin_lock_init(&musb->lock);
        musb->board_set_power = plat->set_power;
        musb->min_power = plat->min_power;
@@ -1991,6 +1987,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb_readl = musb_default_readl;
        musb_writel = musb_default_writel;
 
+       /* We need musb_read/write functions initialized for PM */
+       pm_runtime_use_autosuspend(musb->controller);
+       pm_runtime_set_autosuspend_delay(musb->controller, 200);
+       pm_runtime_irq_safe(musb->controller);
+       pm_runtime_enable(musb->controller);
+
        /* The musb_platform_init() call:
         *   - adjusts musb->mregs
         *   - sets the musb->isr
index 53bd0e71d19f02e3582db6ac21d0e617765c0ad1..a900c9877195ad6ef2048ddb8c2813c8e196feed 100644 (file)
@@ -457,12 +457,27 @@ static int dsps_musb_init(struct musb *musb)
        if (IS_ERR(musb->xceiv))
                return PTR_ERR(musb->xceiv);
 
+       musb->phy = devm_phy_get(dev->parent, "usb2-phy");
+
        /* Returns zero if e.g. not clocked */
        rev = dsps_readl(reg_base, wrp->revision);
        if (!rev)
                return -ENODEV;
 
        usb_phy_init(musb->xceiv);
+       if (IS_ERR(musb->phy))  {
+               musb->phy = NULL;
+       } else {
+               ret = phy_init(musb->phy);
+               if (ret < 0)
+                       return ret;
+               ret = phy_power_on(musb->phy);
+               if (ret) {
+                       phy_exit(musb->phy);
+                       return ret;
+               }
+       }
+
        setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
 
        /* Reset the musb */
@@ -502,6 +517,8 @@ static int dsps_musb_exit(struct musb *musb)
 
        del_timer_sync(&glue->timer);
        usb_phy_shutdown(musb->xceiv);
+       phy_power_off(musb->phy);
+       phy_exit(musb->phy);
        debugfs_remove_recursive(glue->dbgfs_root);
 
        return 0;
@@ -610,7 +627,7 @@ static int dsps_musb_reset(struct musb *musb)
        struct device *dev = musb->controller;
        struct dsps_glue *glue = dev_get_drvdata(dev->parent);
        const struct dsps_musb_wrapper *wrp = glue->wrp;
-       int session_restart = 0;
+       int session_restart = 0, error;
 
        if (glue->sw_babble_enabled)
                session_restart = sw_babble_control(musb);
@@ -624,8 +641,14 @@ static int dsps_musb_reset(struct musb *musb)
                dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
                usleep_range(100, 200);
                usb_phy_shutdown(musb->xceiv);
+               error = phy_power_off(musb->phy);
+               if (error)
+                       dev_err(dev, "phy shutdown failed: %i\n", error);
                usleep_range(100, 200);
                usb_phy_init(musb->xceiv);
+               error = phy_power_on(musb->phy);
+               if (error)
+                       dev_err(dev, "phy powerup failed: %i\n", error);
                session_restart = 1;
        }
 
@@ -687,7 +710,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,
        struct musb_hdrc_config *config;
        struct platform_device *musb;
        struct device_node *dn = parent->dev.of_node;
-       int ret;
+       int ret, val;
 
        memset(resources, 0, sizeof(resources));
        res = platform_get_resource_byname(parent, IORESOURCE_MEM, "mc");
@@ -739,7 +762,10 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,
        pdata.mode = get_musb_port_mode(dev);
        /* DT keeps this entry in mA, musb expects it as per USB spec */
        pdata.power = get_int_prop(dn, "mentor,power") / 2;
-       config->multipoint = of_property_read_bool(dn, "mentor,multipoint");
+
+       ret = of_property_read_u32(dn, "mentor,multipoint", &val);
+       if (!ret && val)
+               config->multipoint = true;
 
        ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
        if (ret) {
index 883a9adfdfff5f0c1643036e0be7d7d22d1e73a8..c3d5fc9dfb5bd56f5adc0a3cee337ffd1c31541f 100644 (file)
@@ -2613,7 +2613,7 @@ static const struct hc_driver musb_hc_driver = {
        .description            = "musb-hcd",
        .product_desc           = "MUSB HDRC host driver",
        .hcd_priv_size          = sizeof(struct musb *),
-       .flags                  = HCD_USB2 | HCD_MEMORY,
+       .flags                  = HCD_USB2 | HCD_MEMORY | HCD_BH,
 
        /* not using irq handler or reset hooks from usbcore, since
         * those must be shared with peripheral code for OTG configs
index 763649eb4987d99cafdc8aa5d3eb77590171150d..cc752d8c7773176d1338d5927c7b7c3bf4fc5ccd 100644 (file)
@@ -516,7 +516,7 @@ static int omap2430_probe(struct platform_device *pdev)
        struct omap2430_glue            *glue;
        struct device_node              *np = pdev->dev.of_node;
        struct musb_hdrc_config         *config;
-       int                             ret = -ENOMEM;
+       int                             ret = -ENOMEM, val;
 
        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
        if (!glue)
@@ -559,7 +559,10 @@ static int omap2430_probe(struct platform_device *pdev)
                of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
                of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
                of_property_read_u32(np, "power", (u32 *)&pdata->power);
-               config->multipoint = of_property_read_bool(np, "multipoint");
+
+               ret = of_property_read_u32(np, "multipoint", &val);
+               if (!ret && val)
+                       config->multipoint = true;
 
                pdata->board_data       = data;
                pdata->config           = config;
index de83b9d0cd5c39449eb71e237ecd2dfa272cdf8c..ebc99ee076ce337275bbea3869abaa830b007111 100644 (file)
@@ -6,6 +6,7 @@ config USB_RENESAS_USBHS
        tristate 'Renesas USBHS controller'
        depends on USB_GADGET
        depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
+       depends on EXTCON || !EXTCON # if EXTCON=m, USBHS cannot be built-in
        default n
        help
          Renesas USBHS is a discrete USB host and peripheral controller chip
index 9374bd2aba20759f4bb4b03d2a9d51058aead9fd..8936a83c96cd60c8a226e0c96a9908c06d356773 100644 (file)
@@ -38,56 +38,51 @@ static int usb_serial_device_match(struct device *dev,
        return 0;
 }
 
-static ssize_t port_number_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct usb_serial_port *port = to_usb_serial_port(dev);
-
-       return sprintf(buf, "%d\n", port->port_number);
-}
-static DEVICE_ATTR_RO(port_number);
-
 static int usb_serial_device_probe(struct device *dev)
 {
        struct usb_serial_driver *driver;
        struct usb_serial_port *port;
+       struct device *tty_dev;
        int retval = 0;
        int minor;
 
        port = to_usb_serial_port(dev);
-       if (!port) {
-               retval = -ENODEV;
-               goto exit;
-       }
+       if (!port)
+               return -ENODEV;
 
        /* make sure suspend/resume doesn't race against port_probe */
        retval = usb_autopm_get_interface(port->serial->interface);
        if (retval)
-               goto exit;
+               return retval;
 
        driver = port->serial->type;
        if (driver->port_probe) {
                retval = driver->port_probe(port);
                if (retval)
-                       goto exit_with_autopm;
+                       goto err_autopm_put;
        }
 
-       retval = device_create_file(dev, &dev_attr_port_number);
-       if (retval) {
-               if (driver->port_remove)
-                       retval = driver->port_remove(port);
-               goto exit_with_autopm;
+       minor = port->minor;
+       tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
+       if (IS_ERR(tty_dev)) {
+               retval = PTR_ERR(tty_dev);
+               goto err_port_remove;
        }
 
-       minor = port->minor;
-       tty_register_device(usb_serial_tty_driver, minor, dev);
+       usb_autopm_put_interface(port->serial->interface);
+
        dev_info(&port->serial->dev->dev,
                 "%s converter now attached to ttyUSB%d\n",
                 driver->description, minor);
 
-exit_with_autopm:
+       return 0;
+
+err_port_remove:
+       if (driver->port_remove)
+               driver->port_remove(port);
+err_autopm_put:
        usb_autopm_put_interface(port->serial->interface);
-exit:
+
        return retval;
 }
 
@@ -114,8 +109,6 @@ static int usb_serial_device_remove(struct device *dev)
        minor = port->minor;
        tty_unregister_device(usb_serial_tty_driver, minor);
 
-       device_remove_file(&port->dev, &dev_attr_port_number);
-
        driver = port->serial->type;
        if (driver->port_remove)
                retval = driver->port_remove(port);
index 2d72aa3564a31e9eeade77423ec16de3d743c706..ede4f5fcfadda11dcdb7ab954769f827bd3c312a 100644 (file)
@@ -84,6 +84,10 @@ struct ch341_private {
        u8 line_status; /* active status of modem control inputs */
 };
 
+static void ch341_set_termios(struct tty_struct *tty,
+                             struct usb_serial_port *port,
+                             struct ktermios *old_termios);
+
 static int ch341_control_out(struct usb_device *dev, u8 request,
                             u16 value, u16 index)
 {
@@ -309,19 +313,12 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
        struct ch341_private *priv = usb_get_serial_port_data(port);
        int r;
 
-       priv->baud_rate = DEFAULT_BAUD_RATE;
-
        r = ch341_configure(serial->dev, priv);
        if (r)
                goto out;
 
-       r = ch341_set_handshake(serial->dev, priv->line_control);
-       if (r)
-               goto out;
-
-       r = ch341_set_baudrate(serial->dev, priv);
-       if (r)
-               goto out;
+       if (tty)
+               ch341_set_termios(tty, port, NULL);
 
        dev_dbg(&port->dev, "%s - submitting interrupt urb\n", __func__);
        r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
index 29fa1c3d0089bee738ed4f54a8b65d4f82dd0c03..3806e7014199d13c892f32e8a03c1b37e286bddb 100644 (file)
@@ -14,6 +14,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/console.h>
@@ -144,6 +145,7 @@ static int usb_console_setup(struct console *co, char *options)
                        init_ldsem(&tty->ldisc_sem);
                        INIT_LIST_HEAD(&tty->tty_files);
                        kref_get(&tty->driver->kref);
+                       __module_get(tty->driver->owner);
                        tty->ops = &usb_console_fake_tty_ops;
                        if (tty_init_termios(tty)) {
                                retval = -ENOMEM;
index f40c856ff758d959318ae4d251eea6cd96f5819a..84ce2d74894c9c3b25c7bcf0185f23887492eb94 100644 (file)
@@ -147,6 +147,8 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
        { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
        { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
+       { USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */
+       { USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */
        { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
        { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
        { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
index 1ebb351b9e9a59c9dbd90ffda56cae1769de764e..3086dec0ef53bbd5d5d3d21087b91469983492fb 100644 (file)
@@ -799,6 +799,8 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
+       { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
@@ -978,6 +980,23 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
        /* GE Healthcare devices */
        { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
+       /* Active Research (Actisense) devices */
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) },
+       { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) },
+       { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) },
        { }                                     /* Terminating entry */
 };
 
index e52409c9be999f817cbdb627f4be8ec6f127cbe6..56b1b55c4751696b2e89633ea90bfe1c2940c436 100644 (file)
@@ -38,6 +38,9 @@
 
 #define FTDI_LUMEL_PD12_PID    0x6002
 
+/* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */
+#define CYBER_CORTEX_AV_PID    0x8698
+
 /*
  * Marvell OpenRD Base, Client
  * http://www.open-rd.org
  */
 #define GE_HEALTHCARE_VID              0x1901
 #define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015
+
+/*
+ * Active Research (Actisense) devices
+ */
+#define ACTISENSE_NDC_PID              0xD9A8 /* NDC USB Serial Adapter */
+#define ACTISENSE_USG_PID              0xD9A9 /* USG USB Serial Adapter */
+#define ACTISENSE_NGT_PID              0xD9AA /* NGT NMEA2000 Interface */
+#define ACTISENSE_NGW_PID              0xD9AB /* NGW NMEA2000 Gateway */
+#define ACTISENSE_D9AC_PID             0xD9AC /* Actisense Reserved */
+#define ACTISENSE_D9AD_PID             0xD9AD /* Actisense Reserved */
+#define ACTISENSE_D9AE_PID             0xD9AE /* Actisense Reserved */
+#define ACTISENSE_D9AF_PID             0xD9AF /* Actisense Reserved */
+#define CHETCO_SEAGAUGE_PID            0xA548 /* SeaGauge USB Adapter */
+#define CHETCO_SEASWITCH_PID           0xA549 /* SeaSwitch USB Adapter */
+#define CHETCO_SEASMART_NMEA2000_PID   0xA54A /* SeaSmart NMEA2000 Gateway */
+#define CHETCO_SEASMART_ETHERNET_PID   0xA54B /* SeaSmart Ethernet Gateway */
+#define CHETCO_SEASMART_WIFI_PID       0xA5AC /* SeaSmart Wifi Gateway */
+#define CHETCO_SEASMART_DISPLAY_PID    0xA5AD /* SeaSmart NMEA2000 Display */
+#define CHETCO_SEASMART_LITE_PID       0xA5AE /* SeaSmart Lite USB Adapter */
+#define CHETCO_SEASMART_ANALOG_PID     0xA5AF /* SeaSmart Analog Adapter */
index ccf1df7c4b80f3f7a596fa3d1d8904eb64a78db6..54e170dd3dad0cec058e29674b98f685f90274df 100644 (file)
@@ -258,7 +258,8 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
         * character or at least one jiffy.
         */
        period = max_t(unsigned long, (10 * HZ / bps), 1);
-       period = min_t(unsigned long, period, timeout);
+       if (timeout)
+               period = min_t(unsigned long, period, timeout);
 
        dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n",
                                        __func__, jiffies_to_msecs(timeout),
@@ -268,7 +269,7 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout)
                schedule_timeout_interruptible(period);
                if (signal_pending(current))
                        break;
-               if (time_after(jiffies, expire))
+               if (timeout && time_after(jiffies, expire))
                        break;
        }
 }
index ab1d690274ae52b3230f04acbd8194a49f68b7ba..460a40669967855cfeea7c6cc911064822c6882a 100644 (file)
@@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
        }
 
        /* Initial port termios */
-       mxuport_set_termios(tty, port, NULL);
+       if (tty)
+               mxuport_set_termios(tty, port, NULL);
 
        /*
         * TODO: use RQ_VENDOR_GET_MSR, once we know what it
index 0f872e6b2c878f9b8de56fc6ae0cddda56468589..829604d11f3fa72a6b5bec5580f150c27c513cbf 100644 (file)
@@ -132,6 +132,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
 #define UART_OVERRUN_ERROR             0x40
 #define UART_CTS                       0x80
 
+static void pl2303_set_break(struct usb_serial_port *port, bool enable);
 
 enum pl2303_type {
        TYPE_01,        /* Type 0 and 1 (difference unknown) */
@@ -615,6 +616,7 @@ static void pl2303_close(struct usb_serial_port *port)
 {
        usb_serial_generic_close(port);
        usb_kill_urb(port->interrupt_in_urb);
+       pl2303_set_break(port, false);
 }
 
 static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -741,17 +743,16 @@ static int pl2303_ioctl(struct tty_struct *tty,
        return -ENOIOCTLCMD;
 }
 
-static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
+static void pl2303_set_break(struct usb_serial_port *port, bool enable)
 {
-       struct usb_serial_port *port = tty->driver_data;
        struct usb_serial *serial = port->serial;
        u16 state;
        int result;
 
-       if (break_state == 0)
-               state = BREAK_OFF;
-       else
+       if (enable)
                state = BREAK_ON;
+       else
+               state = BREAK_OFF;
 
        dev_dbg(&port->dev, "%s - turning break %s\n", __func__,
                        state == BREAK_OFF ? "off" : "on");
@@ -763,6 +764,13 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
                dev_err(&port->dev, "error sending break = %d\n", result);
 }
 
+static void pl2303_break_ctl(struct tty_struct *tty, int state)
+{
+       struct usb_serial_port *port = tty->driver_data;
+
+       pl2303_set_break(port, state);
+}
+
 static void pl2303_update_line_status(struct usb_serial_port *port,
                                      unsigned char *data,
                                      unsigned int actual_length)
index 475723c006f955923d255be9abc408c7fd29027d..529066bbc7e81be1bb67e398f58425febef6a8eb 100644 (file)
@@ -687,6 +687,21 @@ static void serial_port_dtr_rts(struct tty_port *port, int on)
                drv->dtr_rts(p, on);
 }
 
+static ssize_t port_number_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct usb_serial_port *port = to_usb_serial_port(dev);
+
+       return sprintf(buf, "%u\n", port->port_number);
+}
+static DEVICE_ATTR_RO(port_number);
+
+static struct attribute *usb_serial_port_attrs[] = {
+       &dev_attr_port_number.attr,
+       NULL
+};
+ATTRIBUTE_GROUPS(usb_serial_port);
+
 static const struct tty_port_operations serial_port_ops = {
        .carrier_raised         = serial_port_carrier_raised,
        .dtr_rts                = serial_port_dtr_rts,
@@ -902,6 +917,7 @@ static int usb_serial_probe(struct usb_interface *interface,
                port->dev.driver = NULL;
                port->dev.bus = &usb_serial_bus_type;
                port->dev.release = &usb_serial_port_release;
+               port->dev.groups = usb_serial_port_groups;
                device_initialize(&port->dev);
        }
 
@@ -940,8 +956,9 @@ static int usb_serial_probe(struct usb_interface *interface,
                port = serial->port[i];
                if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
                        goto probe_error;
-               buffer_size = max_t(int, serial->type->bulk_out_size,
-                                               usb_endpoint_maxp(endpoint));
+               buffer_size = serial->type->bulk_out_size;
+               if (!buffer_size)
+                       buffer_size = usb_endpoint_maxp(endpoint);
                port->bulk_out_size = buffer_size;
                port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
 
index dbc00e56c7f5c106a67028e1b6da7dfee2c39e5e..82570425fdfe388a5fd05ee6b13439deb676c4fc 100644 (file)
@@ -113,6 +113,13 @@ UNUSUAL_DEV(0x0bc2, 0xab2a, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_ATA_1X),
 
+/* Reported-by: Tom Arild Naess <tanaess@gmail.com> */
+UNUSUAL_DEV(0x152d, 0x0539, 0x0000, 0x9999,
+               "JMicron",
+               "JMS539",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_REPORT_OPCODES),
+
 /* Reported-by: Claudio Bizzarri <claudio.bizzarri@gmail.com> */
 UNUSUAL_DEV(0x152d, 0x0567, 0x0000, 0x9999,
                "JMicron",
index d468d02179f4707d308192ed3578665a41ee96f9..5600c33fcadb219e52e8f985bf692c6ff3a1025e 100644 (file)
@@ -889,6 +889,12 @@ static void usb_stor_scan_dwork(struct work_struct *work)
            !(us->fflags & US_FL_SCM_MULT_TARG)) {
                mutex_lock(&us->dev_mutex);
                us->max_lun = usb_stor_Bulk_max_lun(us);
+               /*
+                * Allow proper scanning of devices that present more than 8 LUNs
+                * While not affecting other devices that may need the previous behavior
+                */
+               if (us->max_lun >= 8)
+                       us_to_host(us)->max_lun = us->max_lun+1;
                mutex_unlock(&us->dev_mutex);
        }
        scsi_scan_host(us_to_host(us));
index 993642199326a757f55c78dbc2722ecc2b409b60..6d67f32e648df72bc5f5b5d707ff39ce8fa4302b 100644 (file)
@@ -1645,14 +1645,14 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 
        parent_nritems = btrfs_header_nritems(parent);
        blocksize = root->nodesize;
-       end_slot = parent_nritems;
+       end_slot = parent_nritems - 1;
 
-       if (parent_nritems == 1)
+       if (parent_nritems <= 1)
                return 0;
 
        btrfs_set_lock_blocking(parent);
 
-       for (i = start_slot; i < end_slot; i++) {
+       for (i = start_slot; i <= end_slot; i++) {
                int close = 1;
 
                btrfs_node_key(parent, &disk_key, i);
@@ -1669,7 +1669,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
                        other = btrfs_node_blockptr(parent, i - 1);
                        close = close_blocks(blocknr, other, blocksize);
                }
-               if (!close && i < end_slot - 2) {
+               if (!close && i < end_slot) {
                        other = btrfs_node_blockptr(parent, i + 1);
                        close = close_blocks(blocknr, other, blocksize);
                }
index 571f402d3fc46e5f0205451e85a7b78f3cc16b50..6f080451fcb11181c10247a542b599412bb42f22 100644 (file)
@@ -3208,6 +3208,8 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
                return 0;
        }
 
+       if (trans->aborted)
+               return 0;
 again:
        inode = lookup_free_space_inode(root, block_group, path);
        if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
@@ -3243,6 +3245,20 @@ again:
         */
        BTRFS_I(inode)->generation = 0;
        ret = btrfs_update_inode(trans, root, inode);
+       if (ret) {
+               /*
+                * So theoretically we could recover from this, simply set the
+                * super cache generation to 0 so we know to invalidate the
+                * cache, but then we'd have to keep track of the block groups
+                * that fail this way so we know we _have_ to reset this cache
+                * before the next commit or risk reading stale cache.  So to
+                * limit our exposure to horrible edge cases lets just abort the
+                * transaction, this only happens in really bad situations
+                * anyway.
+                */
+               btrfs_abort_transaction(trans, root, ret);
+               goto out_put;
+       }
        WARN_ON(ret);
 
        if (i_size_read(inode) > 0) {
index b78bbbac900db833e54fc63bdbff8bae365225f3..30982bbd31c30c2b154836b0f51b94c37e22923c 100644 (file)
@@ -1811,22 +1811,10 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
        mutex_unlock(&inode->i_mutex);
 
        /*
-        * we want to make sure fsync finds this change
-        * but we haven't joined a transaction running right now.
-        *
-        * Later on, someone is sure to update the inode and get the
-        * real transid recorded.
-        *
-        * We set last_trans now to the fs_info generation + 1,
-        * this will either be one more than the running transaction
-        * or the generation used for the next transaction if there isn't
-        * one running right now.
-        *
         * We also have to set last_sub_trans to the current log transid,
         * otherwise subsequent syncs to a file that's been synced in this
         * transaction will appear to have already occured.
         */
-       BTRFS_I(inode)->last_trans = root->fs_info->generation + 1;
        BTRFS_I(inode)->last_sub_trans = root->log_transid;
        if (num_written > 0) {
                err = generic_write_sync(file, pos, num_written);
@@ -1959,25 +1947,37 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        atomic_inc(&root->log_batch);
 
        /*
-        * check the transaction that last modified this inode
-        * and see if its already been committed
-        */
-       if (!BTRFS_I(inode)->last_trans) {
-               mutex_unlock(&inode->i_mutex);
-               goto out;
-       }
-
-       /*
-        * if the last transaction that changed this file was before
-        * the current transaction, we can bail out now without any
-        * syncing
+        * If the last transaction that changed this file was before the current
+        * transaction and we have the full sync flag set in our inode, we can
+        * bail out now without any syncing.
+        *
+        * Note that we can't bail out if the full sync flag isn't set. This is
+        * because when the full sync flag is set we start all ordered extents
+        * and wait for them to fully complete - when they complete they update
+        * the inode's last_trans field through:
+        *
+        *     btrfs_finish_ordered_io() ->
+        *         btrfs_update_inode_fallback() ->
+        *             btrfs_update_inode() ->
+        *                 btrfs_set_inode_last_trans()
+        *
+        * So we are sure that last_trans is up to date and can do this check to
+        * bail out safely. For the fast path, when the full sync flag is not
+        * set in our inode, we can not do it because we start only our ordered
+        * extents and don't wait for them to complete (that is when
+        * btrfs_finish_ordered_io runs), so here at this point their last_trans
+        * value might be less than or equals to fs_info->last_trans_committed,
+        * and setting a speculative last_trans for an inode when a buffered
+        * write is made (such as fs_info->generation + 1 for example) would not
+        * be reliable since after setting the value and before fsync is called
+        * any number of transactions can start and commit (transaction kthread
+        * commits the current transaction periodically), and a transaction
+        * commit does not start nor waits for ordered extents to complete.
         */
        smp_mb();
        if (btrfs_inode_in_log(inode, root->fs_info->generation) ||
-           BTRFS_I(inode)->last_trans <=
-           root->fs_info->last_trans_committed) {
-               BTRFS_I(inode)->last_trans = 0;
-
+           (full_sync && BTRFS_I(inode)->last_trans <=
+            root->fs_info->last_trans_committed)) {
                /*
                 * We'v had everything committed since the last time we were
                 * modified so clear this flag in case it was set for whatever
@@ -2275,6 +2275,8 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
        bool same_page;
        bool no_holes = btrfs_fs_incompat(root->fs_info, NO_HOLES);
        u64 ino_size;
+       bool truncated_page = false;
+       bool updated_inode = false;
 
        ret = btrfs_wait_ordered_range(inode, offset, len);
        if (ret)
@@ -2306,13 +2308,18 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
         * entire page.
         */
        if (same_page && len < PAGE_CACHE_SIZE) {
-               if (offset < ino_size)
+               if (offset < ino_size) {
+                       truncated_page = true;
                        ret = btrfs_truncate_page(inode, offset, len, 0);
+               } else {
+                       ret = 0;
+               }
                goto out_only_mutex;
        }
 
        /* zero back part of the first page */
        if (offset < ino_size) {
+               truncated_page = true;
                ret = btrfs_truncate_page(inode, offset, 0, 0);
                if (ret) {
                        mutex_unlock(&inode->i_mutex);
@@ -2348,6 +2355,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
                if (!ret) {
                        /* zero the front end of the last page */
                        if (tail_start + tail_len < ino_size) {
+                               truncated_page = true;
                                ret = btrfs_truncate_page(inode,
                                                tail_start + tail_len, 0, 1);
                                if (ret)
@@ -2357,8 +2365,8 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
        }
 
        if (lockend < lockstart) {
-               mutex_unlock(&inode->i_mutex);
-               return 0;
+               ret = 0;
+               goto out_only_mutex;
        }
 
        while (1) {
@@ -2506,6 +2514,7 @@ out_trans:
 
        trans->block_rsv = &root->fs_info->trans_block_rsv;
        ret = btrfs_update_inode(trans, root, inode);
+       updated_inode = true;
        btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root);
 out_free:
@@ -2515,6 +2524,22 @@ out:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
                             &cached_state, GFP_NOFS);
 out_only_mutex:
+       if (!updated_inode && truncated_page && !ret && !err) {
+               /*
+                * If we only end up zeroing part of a page, we still need to
+                * update the inode item, so that all the time fields are
+                * updated as well as the necessary btrfs inode in memory fields
+                * for detecting, at fsync time, if the inode isn't yet in the
+                * log tree or it's there but not up to date.
+                */
+               trans = btrfs_start_transaction(root, 1);
+               if (IS_ERR(trans)) {
+                       err = PTR_ERR(trans);
+               } else {
+                       err = btrfs_update_inode(trans, root, inode);
+                       ret = btrfs_end_transaction(trans, root);
+               }
+       }
        mutex_unlock(&inode->i_mutex);
        if (ret && !err)
                err = ret;
index a85c23dfcddbcfd992069811f24b116d74e4dc21..da828cf5e8f885b542012dc3d23854916dc35106 100644 (file)
@@ -7285,7 +7285,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
            ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) &&
             em->block_start != EXTENT_MAP_HOLE)) {
                int type;
-               int ret;
                u64 block_start, orig_start, orig_block_len, ram_bytes;
 
                if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
index 534544e08f769486a97c3c7f3719bed982500783..157cc54fc63486e485a95bf6d8d6da692ef171ca 100644 (file)
@@ -452,9 +452,7 @@ void btrfs_get_logged_extents(struct inode *inode,
                        continue;
                if (entry_end(ordered) <= start)
                        break;
-               if (!list_empty(&ordered->log_list))
-                       continue;
-               if (test_bit(BTRFS_ORDERED_LOGGED, &ordered->flags))
+               if (test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags))
                        continue;
                list_add(&ordered->log_list, logged_list);
                atomic_inc(&ordered->refs);
@@ -511,8 +509,7 @@ void btrfs_wait_logged_extents(struct btrfs_trans_handle *trans,
                wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE,
                                                   &ordered->flags));
 
-               if (!test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags))
-                       list_add_tail(&ordered->trans_list, &trans->ordered);
+               list_add_tail(&ordered->trans_list, &trans->ordered);
                spin_lock_irq(&log->log_extents_lock[index]);
        }
        spin_unlock_irq(&log->log_extents_lock[index]);
index fe5857223515d14753c1f75ce60c2c12e16a3e67..d6033f540cc75cfb49ddbe5f07689d67fdefc492 100644 (file)
@@ -230,6 +230,7 @@ struct pending_dir_move {
        u64 parent_ino;
        u64 ino;
        u64 gen;
+       bool is_orphan;
        struct list_head update_refs;
 };
 
@@ -2984,7 +2985,8 @@ static int add_pending_dir_move(struct send_ctx *sctx,
                                u64 ino_gen,
                                u64 parent_ino,
                                struct list_head *new_refs,
-                               struct list_head *deleted_refs)
+                               struct list_head *deleted_refs,
+                               const bool is_orphan)
 {
        struct rb_node **p = &sctx->pending_dir_moves.rb_node;
        struct rb_node *parent = NULL;
@@ -2999,6 +3001,7 @@ static int add_pending_dir_move(struct send_ctx *sctx,
        pm->parent_ino = parent_ino;
        pm->ino = ino;
        pm->gen = ino_gen;
+       pm->is_orphan = is_orphan;
        INIT_LIST_HEAD(&pm->list);
        INIT_LIST_HEAD(&pm->update_refs);
        RB_CLEAR_NODE(&pm->node);
@@ -3131,16 +3134,20 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
        rmdir_ino = dm->rmdir_ino;
        free_waiting_dir_move(sctx, dm);
 
-       ret = get_first_ref(sctx->parent_root, pm->ino,
-                           &parent_ino, &parent_gen, name);
-       if (ret < 0)
-               goto out;
-
-       ret = get_cur_path(sctx, parent_ino, parent_gen,
-                          from_path);
-       if (ret < 0)
-               goto out;
-       ret = fs_path_add_path(from_path, name);
+       if (pm->is_orphan) {
+               ret = gen_unique_name(sctx, pm->ino,
+                                     pm->gen, from_path);
+       } else {
+               ret = get_first_ref(sctx->parent_root, pm->ino,
+                                   &parent_ino, &parent_gen, name);
+               if (ret < 0)
+                       goto out;
+               ret = get_cur_path(sctx, parent_ino, parent_gen,
+                                  from_path);
+               if (ret < 0)
+                       goto out;
+               ret = fs_path_add_path(from_path, name);
+       }
        if (ret < 0)
                goto out;
 
@@ -3150,7 +3157,8 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
                LIST_HEAD(deleted_refs);
                ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID);
                ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor,
-                                          &pm->update_refs, &deleted_refs);
+                                          &pm->update_refs, &deleted_refs,
+                                          pm->is_orphan);
                if (ret < 0)
                        goto out;
                if (rmdir_ino) {
@@ -3283,6 +3291,127 @@ out:
        return ret;
 }
 
+/*
+ * We might need to delay a directory rename even when no ancestor directory
+ * (in the send root) with a higher inode number than ours (sctx->cur_ino) was
+ * renamed. This happens when we rename a directory to the old name (the name
+ * in the parent root) of some other unrelated directory that got its rename
+ * delayed due to some ancestor with higher number that got renamed.
+ *
+ * Example:
+ *
+ * Parent snapshot:
+ * .                                       (ino 256)
+ * |---- a/                                (ino 257)
+ * |     |---- file                        (ino 260)
+ * |
+ * |---- b/                                (ino 258)
+ * |---- c/                                (ino 259)
+ *
+ * Send snapshot:
+ * .                                       (ino 256)
+ * |---- a/                                (ino 258)
+ * |---- x/                                (ino 259)
+ *       |---- y/                          (ino 257)
+ *             |----- file                 (ino 260)
+ *
+ * Here we can not rename 258 from 'b' to 'a' without the rename of inode 257
+ * from 'a' to 'x/y' happening first, which in turn depends on the rename of
+ * inode 259 from 'c' to 'x'. So the order of rename commands the send stream
+ * must issue is:
+ *
+ * 1 - rename 259 from 'c' to 'x'
+ * 2 - rename 257 from 'a' to 'x/y'
+ * 3 - rename 258 from 'b' to 'a'
+ *
+ * Returns 1 if the rename of sctx->cur_ino needs to be delayed, 0 if it can
+ * be done right away and < 0 on error.
+ */
+static int wait_for_dest_dir_move(struct send_ctx *sctx,
+                                 struct recorded_ref *parent_ref,
+                                 const bool is_orphan)
+{
+       struct btrfs_path *path;
+       struct btrfs_key key;
+       struct btrfs_key di_key;
+       struct btrfs_dir_item *di;
+       u64 left_gen;
+       u64 right_gen;
+       int ret = 0;
+
+       if (RB_EMPTY_ROOT(&sctx->waiting_dir_moves))
+               return 0;
+
+       path = alloc_path_for_send();
+       if (!path)
+               return -ENOMEM;
+
+       key.objectid = parent_ref->dir;
+       key.type = BTRFS_DIR_ITEM_KEY;
+       key.offset = btrfs_name_hash(parent_ref->name, parent_ref->name_len);
+
+       ret = btrfs_search_slot(NULL, sctx->parent_root, &key, path, 0, 0);
+       if (ret < 0) {
+               goto out;
+       } else if (ret > 0) {
+               ret = 0;
+               goto out;
+       }
+
+       di = btrfs_match_dir_item_name(sctx->parent_root, path,
+                                      parent_ref->name, parent_ref->name_len);
+       if (!di) {
+               ret = 0;
+               goto out;
+       }
+       /*
+        * di_key.objectid has the number of the inode that has a dentry in the
+        * parent directory with the same name that sctx->cur_ino is being
+        * renamed to. We need to check if that inode is in the send root as
+        * well and if it is currently marked as an inode with a pending rename,
+        * if it is, we need to delay the rename of sctx->cur_ino as well, so
+        * that it happens after that other inode is renamed.
+        */
+       btrfs_dir_item_key_to_cpu(path->nodes[0], di, &di_key);
+       if (di_key.type != BTRFS_INODE_ITEM_KEY) {
+               ret = 0;
+               goto out;
+       }
+
+       ret = get_inode_info(sctx->parent_root, di_key.objectid, NULL,
+                            &left_gen, NULL, NULL, NULL, NULL);
+       if (ret < 0)
+               goto out;
+       ret = get_inode_info(sctx->send_root, di_key.objectid, NULL,
+                            &right_gen, NULL, NULL, NULL, NULL);
+       if (ret < 0) {
+               if (ret == -ENOENT)
+                       ret = 0;
+               goto out;
+       }
+
+       /* Different inode, no need to delay the rename of sctx->cur_ino */
+       if (right_gen != left_gen) {
+               ret = 0;
+               goto out;
+       }
+
+       if (is_waiting_for_move(sctx, di_key.objectid)) {
+               ret = add_pending_dir_move(sctx,
+                                          sctx->cur_ino,
+                                          sctx->cur_inode_gen,
+                                          di_key.objectid,
+                                          &sctx->new_refs,
+                                          &sctx->deleted_refs,
+                                          is_orphan);
+               if (!ret)
+                       ret = 1;
+       }
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
 static int wait_for_parent_move(struct send_ctx *sctx,
                                struct recorded_ref *parent_ref)
 {
@@ -3349,7 +3478,8 @@ out:
                                           sctx->cur_inode_gen,
                                           ino,
                                           &sctx->new_refs,
-                                          &sctx->deleted_refs);
+                                          &sctx->deleted_refs,
+                                          false);
                if (!ret)
                        ret = 1;
        }
@@ -3372,6 +3502,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
        int did_overwrite = 0;
        int is_orphan = 0;
        u64 last_dir_ino_rm = 0;
+       bool can_rename = true;
 
 verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
 
@@ -3490,12 +3621,22 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                        }
                }
 
+               if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root) {
+                       ret = wait_for_dest_dir_move(sctx, cur, is_orphan);
+                       if (ret < 0)
+                               goto out;
+                       if (ret == 1) {
+                               can_rename = false;
+                               *pending_move = 1;
+                       }
+               }
+
                /*
                 * link/move the ref to the new place. If we have an orphan
                 * inode, move it and update valid_path. If not, link or move
                 * it depending on the inode mode.
                 */
-               if (is_orphan) {
+               if (is_orphan && can_rename) {
                        ret = send_rename(sctx, valid_path, cur->full_path);
                        if (ret < 0)
                                goto out;
@@ -3503,7 +3644,7 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                        ret = fs_path_copy(valid_path, cur->full_path);
                        if (ret < 0)
                                goto out;
-               } else {
+               } else if (can_rename) {
                        if (S_ISDIR(sctx->cur_inode_mode)) {
                                /*
                                 * Dirs can't be linked, so move it. For moved
index 7e80f32550a663e7438d3e5fb8b1c37fcc391b64..88e51aded6bda9744a5fffa19b0b4e701dab925e 100644 (file)
@@ -1052,9 +1052,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
                ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
                if (ret)
                        return ret;
-               ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
-               if (ret)
-                       return ret;
        }
 
        return 0;
index 9a37f8b39bae9058a20aafe11c59793409115005..c5b8ba37f88e31fa188258af9c6e13036c2df18f 100644 (file)
@@ -1012,7 +1012,7 @@ again:
                base = btrfs_item_ptr_offset(leaf, path->slots[0]);
 
                while (cur_offset < item_size) {
-                       extref = (struct btrfs_inode_extref *)base + cur_offset;
+                       extref = (struct btrfs_inode_extref *)(base + cur_offset);
 
                        victim_name_len = btrfs_inode_extref_name_len(leaf, extref);
 
index 47b19465f0dc64e85d00d99eaee50e88de9f1014..883b93623bc5682ecde2684bfe936bb98fd9e51d 100644 (file)
@@ -111,6 +111,8 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
                                        name, name_len, -1);
                if (!di && (flags & XATTR_REPLACE))
                        ret = -ENODATA;
+               else if (IS_ERR(di))
+                       ret = PTR_ERR(di);
                else if (di)
                        ret = btrfs_delete_one_dir_name(trans, root, path, di);
                goto out;
@@ -127,10 +129,12 @@ static int do_setxattr(struct btrfs_trans_handle *trans,
                ASSERT(mutex_is_locked(&inode->i_mutex));
                di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode),
                                        name, name_len, 0);
-               if (!di) {
+               if (!di)
                        ret = -ENODATA;
+               else if (IS_ERR(di))
+                       ret = PTR_ERR(di);
+               if (ret)
                        goto out;
-               }
                btrfs_release_path(path);
                di = NULL;
        }
index a24addfdfcec5568015e4e358402d6afa002e37a..0de6290df4da65f1511658c0ae0bc60bf24679fa 100644 (file)
@@ -68,8 +68,8 @@ struct drm_mm_node {
        unsigned scanned_preceeds_hole : 1;
        unsigned allocated : 1;
        unsigned long color;
-       unsigned long start;
-       unsigned long size;
+       u64 start;
+       u64 size;
        struct drm_mm *mm;
 };
 
@@ -82,16 +82,16 @@ struct drm_mm {
        unsigned int scan_check_range : 1;
        unsigned scan_alignment;
        unsigned long scan_color;
-       unsigned long scan_size;
-       unsigned long scan_hit_start;
-       unsigned long scan_hit_end;
+       u64 scan_size;
+       u64 scan_hit_start;
+       u64 scan_hit_end;
        unsigned scanned_blocks;
-       unsigned long scan_start;
-       unsigned long scan_end;
+       u64 scan_start;
+       u64 scan_end;
        struct drm_mm_node *prev_scanned_node;
 
        void (*color_adjust)(struct drm_mm_node *node, unsigned long color,
-                            unsigned long *start, unsigned long *end);
+                            u64 *start, u64 *end);
 };
 
 /**
@@ -124,7 +124,7 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
        return mm->hole_stack.next;
 }
 
-static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
+static inline u64 __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
 {
        return hole_node->start + hole_node->size;
 }
@@ -140,13 +140,13 @@ static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_no
  * Returns:
  * Start of the subsequent hole.
  */
-static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
+static inline u64 drm_mm_hole_node_start(struct drm_mm_node *hole_node)
 {
        BUG_ON(!hole_node->hole_follows);
        return __drm_mm_hole_node_start(hole_node);
 }
 
-static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
+static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
 {
        return list_entry(hole_node->node_list.next,
                          struct drm_mm_node, node_list)->start;
@@ -163,7 +163,7 @@ static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node
  * Returns:
  * End of the subsequent hole.
  */
-static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
+static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
 {
        return __drm_mm_hole_node_end(hole_node);
 }
@@ -222,7 +222,7 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node);
 
 int drm_mm_insert_node_generic(struct drm_mm *mm,
                               struct drm_mm_node *node,
-                              unsigned long size,
+                              u64 size,
                               unsigned alignment,
                               unsigned long color,
                               enum drm_mm_search_flags sflags,
@@ -245,7 +245,7 @@ int drm_mm_insert_node_generic(struct drm_mm *mm,
  */
 static inline int drm_mm_insert_node(struct drm_mm *mm,
                                     struct drm_mm_node *node,
-                                    unsigned long size,
+                                    u64 size,
                                     unsigned alignment,
                                     enum drm_mm_search_flags flags)
 {
@@ -255,11 +255,11 @@ static inline int drm_mm_insert_node(struct drm_mm *mm,
 
 int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
                                        struct drm_mm_node *node,
-                                       unsigned long size,
+                                       u64 size,
                                        unsigned alignment,
                                        unsigned long color,
-                                       unsigned long start,
-                                       unsigned long end,
+                                       u64 start,
+                                       u64 end,
                                        enum drm_mm_search_flags sflags,
                                        enum drm_mm_allocator_flags aflags);
 /**
@@ -282,10 +282,10 @@ int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
  */
 static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
                                              struct drm_mm_node *node,
-                                             unsigned long size,
+                                             u64 size,
                                              unsigned alignment,
-                                             unsigned long start,
-                  &