diff options
Diffstat (limited to 'drivers')
54 files changed, 592 insertions, 273 deletions
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index fefc2ca7cc3..33dc6a00480 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c @@ -250,10 +250,6 @@ static const char *cper_pcie_port_type_strs[] = { static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, const struct acpi_hest_generic_data *gdata) { -#ifdef CONFIG_ACPI_APEI_PCIEAER - struct pci_dev *dev; -#endif - if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? @@ -285,20 +281,6 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, printk( "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", pfx, pcie->bridge.secondary_status, pcie->bridge.control); -#ifdef CONFIG_ACPI_APEI_PCIEAER - dev = pci_get_domain_bus_and_slot(pcie->device_id.segment, - pcie->device_id.bus, pcie->device_id.function); - if (!dev) { - pr_err("PCI AER Cannot get PCI device %04x:%02x:%02x.%d\n", - pcie->device_id.segment, pcie->device_id.bus, - pcie->device_id.slot, pcie->device_id.function); - return; - } - if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) - cper_print_aer(pfx, dev, gdata->error_severity, - (struct aer_capability_regs *) pcie->aer_info); - pci_dev_put(dev); -#endif } static const char *apei_estatus_section_flag_strs[] = { diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index d668a8ae602..403baf4dffc 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -454,7 +454,9 @@ static void ghes_do_proc(struct ghes *ghes, aer_severity = cper_severity_to_aer(sev); aer_recover_queue(pcie_err->device_id.segment, pcie_err->device_id.bus, - devfn, aer_severity); + devfn, aer_severity, + (struct aer_capability_regs *) + pcie_err->aer_info); } } diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 765fdf5ce57..bf416a8391a 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -1154,7 +1154,7 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained); sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1, - DMA_BIDIRECTIONAL, assoc_chained); + DMA_TO_DEVICE, assoc_chained); if (likely(req->src == req->dst)) { sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, DMA_BIDIRECTIONAL, src_chained); @@ -1336,7 +1336,7 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained); sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1, - DMA_BIDIRECTIONAL, assoc_chained); + DMA_TO_DEVICE, assoc_chained); if (likely(req->src == req->dst)) { sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, DMA_BIDIRECTIONAL, src_chained); diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index b623c599e57..8bd1bb6dbe4 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -523,13 +523,11 @@ static void efivar_update_sysfs_entries(struct work_struct *work) struct efivar_entry *entry; int err; - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - return; - /* Add new sysfs entries */ while (1) { - memset(entry, 0, sizeof(*entry)); + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return; err = efivar_init(efivar_update_sysfs_entry, entry, true, false, &efivar_sysfs_list); diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index e8894bc9e6d..c200e4d71e3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -48,6 +48,8 @@ struct exynos_drm_crtc { unsigned int pipe; unsigned int dpms; enum exynos_crtc_mode mode; + wait_queue_head_t pending_flip_queue; + atomic_t pending_flip; }; static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) @@ -61,6 +63,13 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) return; } + if (mode > DRM_MODE_DPMS_ON) { + /* wait for the completion of page flip. */ + wait_event(exynos_crtc->pending_flip_queue, + atomic_read(&exynos_crtc->pending_flip) == 0); + drm_vblank_off(crtc->dev, exynos_crtc->pipe); + } + exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms); exynos_crtc->dpms = mode; } @@ -217,7 +226,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, ret = drm_vblank_get(dev, exynos_crtc->pipe); if (ret) { DRM_DEBUG("failed to acquire vblank counter\n"); - list_del(&event->base.link); goto out; } @@ -225,6 +233,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, spin_lock_irq(&dev->event_lock); list_add_tail(&event->base.link, &dev_priv->pageflip_event_list); + atomic_set(&exynos_crtc->pending_flip, 1); spin_unlock_irq(&dev->event_lock); crtc->fb = fb; @@ -344,6 +353,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) exynos_crtc->pipe = nr; exynos_crtc->dpms = DRM_MODE_DPMS_OFF; + init_waitqueue_head(&exynos_crtc->pending_flip_queue); + atomic_set(&exynos_crtc->pending_flip, 0); exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true); if (!exynos_crtc->plane) { kfree(exynos_crtc); @@ -398,7 +409,8 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc) { struct exynos_drm_private *dev_priv = dev->dev_private; struct drm_pending_vblank_event *e, *t; - struct timeval now; + struct drm_crtc *drm_crtc = dev_priv->crtc[crtc]; + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc); unsigned long flags; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -411,14 +423,11 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc) if (crtc != e->pipe) continue; - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); + list_del(&e->base.link); + drm_send_vblank_event(dev, -1, e); drm_vblank_put(dev, crtc); + atomic_set(&exynos_crtc->pending_flip, 0); + wake_up(&exynos_crtc->pending_flip_queue); } spin_unlock_irqrestore(&dev->event_lock, flags); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 68f0045f86b..8f007aaeffc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -182,7 +182,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, helper->fb = exynos_drm_framebuffer_init(dev, &mode_cmd, &exynos_gem_obj->base); - if (IS_ERR_OR_NULL(helper->fb)) { + if (IS_ERR(helper->fb)) { DRM_ERROR("failed to create drm framebuffer.\n"); ret = PTR_ERR(helper->fb); goto err_destroy_gem; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 773f583fa96..4a1616a18ab 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -12,9 +12,9 @@ * */ #include <linux/kernel.h> -#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/clk.h> #include <linux/pm_runtime.h> @@ -1845,7 +1845,7 @@ static int fimc_probe(struct platform_device *pdev) } ctx->irq = res->start; - ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler, + ret = devm_request_threaded_irq(dev, ctx->irq, NULL, fimc_irq_handler, IRQF_ONESHOT, "drm_fimc", ctx); if (ret < 0) { dev_err(dev, "failed to request irq.\n"); @@ -1854,7 +1854,7 @@ static int fimc_probe(struct platform_device *pdev) ret = fimc_setup_clocks(ctx); if (ret < 0) - goto err_free_irq; + return ret; ippdrv = &ctx->ippdrv; ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops; @@ -1884,7 +1884,7 @@ static int fimc_probe(struct platform_device *pdev) goto err_pm_dis; } - dev_info(&pdev->dev, "drm fimc registered successfully.\n"); + dev_info(dev, "drm fimc registered successfully.\n"); return 0; @@ -1892,8 +1892,6 @@ err_pm_dis: pm_runtime_disable(dev); err_put_clk: fimc_put_clocks(ctx); -err_free_irq: - free_irq(ctx->irq, ctx); return ret; } @@ -1911,8 +1909,6 @@ static int fimc_remove(struct platform_device *pdev) pm_runtime_set_suspended(dev); pm_runtime_disable(dev); - free_irq(ctx->irq, ctx); - return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 746b282b343..97c61dbffd8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -885,7 +885,7 @@ static int fimd_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - if (pdev->dev.of_node) { + if (dev->of_node) { pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { DRM_ERROR("memory allocation for pdata failed\n"); @@ -899,7 +899,7 @@ static int fimd_probe(struct platform_device *pdev) return ret; } } else { - pdata = pdev->dev.platform_data; + pdata = dev->platform_data; if (!pdata) { DRM_ERROR("no platform data specified\n"); return -EINVAL; @@ -912,7 +912,7 @@ static int fimd_probe(struct platform_device *pdev) return -EINVAL; } - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -930,7 +930,7 @@ static int fimd_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ctx->regs = devm_ioremap_resource(&pdev->dev, res); + ctx->regs = devm_ioremap_resource(dev, res); if (IS_ERR(ctx->regs)) return PTR_ERR(ctx->regs); @@ -942,7 +942,7 @@ static int fimd_probe(struct platform_device *pdev) ctx->irq = res->start; - ret = devm_request_irq(&pdev->dev, ctx->irq, fimd_irq_handler, + ret = devm_request_irq(dev, ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx); if (ret) { dev_err(dev, "irq request failed.\n"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 47a493c8a71..af75434ee4d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -1379,7 +1379,7 @@ static int g2d_probe(struct platform_device *pdev) struct exynos_drm_subdrv *subdrv; int ret; - g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL); + g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL); if (!g2d) { dev_err(dev, "failed to allocate driver data\n"); return -ENOMEM; @@ -1417,7 +1417,7 @@ static int g2d_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - g2d->regs = devm_ioremap_resource(&pdev->dev, res); + g2d->regs = devm_ioremap_resource(dev, res); if (IS_ERR(g2d->regs)) { ret = PTR_ERR(g2d->regs); goto err_put_clk; @@ -1430,7 +1430,7 @@ static int g2d_probe(struct platform_device *pdev) goto err_put_clk; } - ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0, + ret = devm_request_irq(dev, g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d); if (ret < 0) { dev_err(dev, "irq request failed\n"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 7841c3b8a20..762f40d548b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -1704,7 +1704,7 @@ static int gsc_probe(struct platform_device *pdev) } ctx->irq = res->start; - ret = request_threaded_irq(ctx->irq, NULL, gsc_irq_handler, + ret = devm_request_threaded_irq(dev, ctx->irq, NULL, gsc_irq_handler, IRQF_ONESHOT, "drm_gsc", ctx); if (ret < 0) { dev_err(dev, "failed to request irq.\n"); @@ -1725,7 +1725,7 @@ static int gsc_probe(struct platform_device *pdev) ret = gsc_init_prop_list(ippdrv); if (ret < 0) { dev_err(dev, "failed to init property list.\n"); - goto err_get_irq; + return ret; } DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id, @@ -1743,15 +1743,12 @@ static int gsc_probe(struct platform_device *pdev) goto err_ippdrv_register; } - dev_info(&pdev->dev, "drm gsc registered successfully.\n"); + dev_info(dev, "drm gsc registered successfully.\n"); return 0; err_ippdrv_register: - devm_kfree(dev, ippdrv->prop_list); pm_runtime_disable(dev); -err_get_irq: - free_irq(ctx->irq, ctx); return ret; } @@ -1761,15 +1758,12 @@ static int gsc_remove(struct platform_device *pdev) struct gsc_context *ctx = get_gsc_context(dev); struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; - devm_kfree(dev, ippdrv->prop_list); exynos_drm_ippdrv_unregister(ippdrv); mutex_destroy(&ctx->lock); pm_runtime_set_suspended(dev); pm_runtime_disable(dev); - free_irq(ctx->irq, ctx); - return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index ba2f0f1aa05..437fb947e46 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -442,7 +442,7 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) { DRM_LOG_KMS("failed to alloc common hdmi context.\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 29d2ad31449..be1e8846346 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -222,7 +222,7 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx, /* find ipp driver using idr */ ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock, ipp_id); - if (IS_ERR_OR_NULL(ippdrv)) { + if (IS_ERR(ippdrv)) { DRM_ERROR("not found ipp%d driver.\n", ipp_id); return ippdrv; } @@ -388,7 +388,7 @@ static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property) DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id); ippdrv = ipp_find_drv_by_handle(prop_id); - if (IS_ERR_OR_NULL(ippdrv)) { + if (IS_ERR(ippdrv)) { DRM_ERROR("failed to get ipp driver.\n"); return -EINVAL; } @@ -492,7 +492,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, /* find ipp driver using ipp id */ ippdrv = ipp_find_driver(ctx, property); - if (IS_ERR_OR_NULL(ippdrv)) { + if (IS_ERR(ippdrv)) { DRM_ERROR("failed to get ipp driver.\n"); return -EINVAL; } @@ -521,19 +521,19 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data, c_node->state = IPP_STATE_IDLE; c_node->start_work = ipp_create_cmd_work(); - if (IS_ERR_OR_NULL(c_node->start_work)) { + if (IS_ERR(c_node->start_work)) { DRM_ERROR("failed to create start work.\n"); goto err_clear; } c_node->stop_work = ipp_create_cmd_work(); - if (IS_ERR_OR_NULL(c_node->stop_work)) { + if (IS_ERR(c_node->stop_work)) { DRM_ERROR("failed to create stop work.\n"); goto err_free_start; } c_node->event_work = ipp_create_event_work(); - if (IS_ERR_OR_NULL(c_node->event_work)) { + if (IS_ERR(c_node->event_work)) { DRM_ERROR("failed to create event work.\n"); goto err_free_stop; } @@ -915,7 +915,7 @@ static int ipp_queue_buf_with_run(struct device *dev, DRM_DEBUG_KMS("%s\n", __func__); ippdrv = ipp_find_drv_by_handle(qbuf->prop_id); - if (IS_ERR_OR_NULL(ippdrv)) { + if (IS_ERR(ippdrv)) { DRM_ERROR("failed to get ipp driver.\n"); return -EFAULT; } @@ -1909,7 +1909,7 @@ static int ipp_probe(struct platform_device *pdev) struct exynos_drm_subdrv *subdrv; int ret; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -1963,7 +1963,7 @@ static int ipp_probe(struct platform_device *pdev) goto err_cmd_workq; } - dev_info(&pdev->dev, "drm ipp registered successfully.\n"); + dev_info(dev, "drm ipp registered successfully.\n"); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 947f09f15ad..9b6c70964d7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -666,8 +666,8 @@ static int rotator_probe(struct platform_device *pdev) return rot->irq; } - ret = request_threaded_irq(rot->irq, NULL, rotator_irq_handler, - IRQF_ONESHOT, "drm_rotator", rot); + ret = devm_request_threaded_irq(dev, rot->irq, NULL, + rotator_irq_handler, IRQF_ONESHOT, "drm_rotator", rot); if (ret < 0) { dev_err(dev, "failed to request irq\n"); return ret; @@ -676,8 +676,7 @@ static int rotator_probe(struct platform_device *pdev) rot->clock = devm_clk_get(dev, "rotator"); if (IS_ERR(rot->clock)) { dev_err(dev, "failed to get clock\n"); - ret = PTR_ERR(rot->clock); - goto err_clk_get; + return PTR_ERR(rot->clock); } pm_runtime_enable(dev); @@ -709,10 +708,7 @@ static int rotator_probe(struct platform_device *pdev) return 0; err_ippdrv_register: - devm_kfree(dev, ippdrv->prop_list); pm_runtime_disable(dev); -err_clk_get: - free_irq(rot->irq, rot); return ret; } @@ -722,13 +718,10 @@ static int rotator_remove(struct platform_device *pdev) struct rot_context *rot = dev_get_drvdata(dev); struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv; - devm_kfree(dev, ippdrv->prop_list); exynos_drm_ippdrv_unregister(ippdrv); pm_runtime_disable(dev); - free_irq(rot->irq, rot); - return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 9504b0cd825..24376c194a5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -594,7 +594,7 @@ static int vidi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("%s\n", __FILE__); - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -612,7 +612,7 @@ static int vidi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctx); - ret = device_create_file(&pdev->dev, &dev_attr_connection); + ret = device_create_file(dev, &dev_attr_connection); if (ret < 0) DRM_INFO("failed to create connection sysfs.\n"); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 6652597586a..fd1426dca88 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1946,14 +1946,14 @@ static int hdmi_probe(struct platform_device *pdev) DRM_DEBUG_KMS("[%d]\n", __LINE__); - if (pdev->dev.of_node) { + if (dev->of_node) { pdata = drm_hdmi_dt_parse_pdata(dev); if (IS_ERR(pdata)) { DRM_ERROR("failed to parse dt\n"); return PTR_ERR(pdata); } } else { - pdata = pdev->dev.platform_data; + pdata = dev->platform_data; } if (!pdata) { @@ -1961,14 +1961,14 @@ static int hdmi_probe(struct platform_device *pdev) return -EINVAL; } - drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx), + drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL); if (!drm_hdmi_ctx) { DRM_ERROR("failed to allocate common hdmi context.\n"); return -ENOMEM; } - hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context), + hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL); if (!hdata) { DRM_ERROR("out of memory\n"); @@ -1985,7 +1985,7 @@ static int hdmi_probe(struct platform_device *pdev) if (dev->of_node) { const struct of_device_id *match; match = of_match_node(of_match_ptr(hdmi_match_types), - pdev->dev.of_node); + dev->of_node); if (match == NULL) return -ENODEV; hdata->type = (enum hdmi_type)match->data; @@ -2005,11 +2005,11 @@ static int hdmi_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hdata->regs = devm_ioremap_resource(&pdev->dev, res); + hdata->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hdata->regs)) return PTR_ERR(hdata->regs); - ret = devm_gpio_request(&pdev->dev, hdata->hpd_gpio, "HPD"); + ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD"); if (ret) { DRM_ERROR("failed to request HPD gpio\n"); return ret; @@ -2041,7 +2041,7 @@ static int hdmi_probe(struct platform_device *pdev) hdata->hpd = gpio_get_value(hdata->hpd_gpio); - ret = request_threaded_irq(hdata->irq, NULL, + ret = devm_request_threaded_irq(dev, hdata->irq, NULL, hdmi_irq_thread, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "hdmi", drm_hdmi_ctx); @@ -2070,16 +2070,11 @@ err_ddc: static int hdmi_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev); - struct hdmi_context *hdata = ctx->ctx; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); pm_runtime_disable(dev); - free_irq(hdata->irq, hdata); - - /* hdmiphy i2c driver */ i2c_del_driver(&hdmiphy_driver); /* DDC i2c driver */ diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index ec3e376b7e0..7c197d3820c 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1061,7 +1061,7 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx, return -ENXIO; } - mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start, + mixer_res->mixer_regs = devm_ioremap(dev, res->start, resource_size(res)); if (mixer_res->mixer_regs == NULL) { dev_err(dev, "register mapping failed.\n"); @@ -1074,7 +1074,7 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx, return -ENXIO; } - ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, + ret = devm_request_irq(dev, res->start, mixer_irq_handler, 0, "drm_mixer", ctx); if (ret) { dev_err(dev, "request interrupt failed.\n"); @@ -1118,7 +1118,7 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx, return -ENXIO; } - mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, + mixer_res->vp_regs = devm_ioremap(dev, res->start, resource_size(res)); if (mixer_res->vp_regs == NULL) { dev_err(dev, "register mapping failed.\n"); @@ -1169,14 +1169,14 @@ static int mixer_probe(struct platform_device *pdev) dev_info(dev, "probe start\n"); - drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx), + drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx), GFP_KERNEL); if (!drm_hdmi_ctx) { DRM_ERROR("failed to allocate common hdmi context.\n"); return -ENOMEM; } - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) { DRM_ERROR("failed to alloc mixer context.\n"); return -ENOMEM; @@ -1187,14 +1187,14 @@ static int mixer_probe(struct platform_device *pdev) if (dev->of_node) { const struct of_device_id *match; match = of_match_node(of_match_ptr(mixer_match_types), - pdev->dev.of_node); + dev->of_node); drv = (struct mixer_drv_data *)match->data; } else { drv = (struct mixer_drv_data *) platform_get_device_id(pdev)->driver_data; } - ctx->dev = &pdev->dev; + ctx->dev = dev; ctx->parent_ctx = (void *)drm_hdmi_ctx; drm_hdmi_ctx->ctx = (void *)ctx; ctx->vp_enabled = drv->is_vp_enabled; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9ebe895c17d..a2e4953b8e8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -364,40 +364,64 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */ INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */ INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */ - INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */ + INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT3 desktop */ INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */ INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */ - INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */ + INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT3 server */ INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */ + INTEL_VGA_DEVICE(0x040B, &intel_haswell_d_info), /* GT1 reserved */ + INTEL_VGA_DEVICE(0x041B, &intel_haswell_d_info), /* GT2 reserved */ + INTEL_VGA_DEVICE(0x042B, &intel_haswell_d_info), /* GT3 reserved */ + INTEL_VGA_DEVICE(0x040E, &intel_haswell_d_info), /* GT1 reserved */ + INTEL_VGA_DEVICE(0x041E, &intel_haswell_d_info), /* GT2 reserved */ + INTEL_VGA_DEVICE(0x042E, &intel_haswell_d_info), /* GT3 reserved */ INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */ INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */ - INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */ + INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT3 desktop */ INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */ INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */ - INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */ + INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT3 server */ INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */ INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */ - INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */ + INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT3 mobile */ + INTEL_VGA_DEVICE(0x0C0B, &intel_haswell_d_info), /* SDV GT1 reserved */ + INTEL_VGA_DEVICE(0x0C1B, &intel_haswell_d_info), /* SDV GT2 reserved */ + INTEL_VGA_DEVICE(0x0C2B, &intel_haswell_d_info), /* SDV GT3 reserved */ + INTEL_VGA_DEVICE(0x0C0E, &intel_haswell_d_info), /* SDV GT1 reserved */ + INTEL_VGA_DEVICE(0x0C1E, &intel_haswell_d_info), /* SDV GT2 reserved */ + INTEL_VGA_DEVICE(0x0C2E, &intel_haswell_d_info), /* SDV GT3 reserved */ INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */ INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */ - INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */ + INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT3 desktop */ INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */ INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */ - INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */ + INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT3 server */ INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ - INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ + INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT3 mobile */ + INTEL_VGA_DEVICE(0x0A0B, &intel_haswell_d_info), /* ULT GT1 reserved */ + INTEL_VGA_DEVICE(0x0A1B, &intel_haswell_d_info), /* ULT GT2 reserved */ + INTEL_VGA_DEVICE(0x0A2B, &intel_haswell_d_info), /* ULT GT3 reserved */ + INTEL_VGA_DEVICE(0x0A0E, &intel_haswell_m_info), /* ULT GT1 reserved */ + INTEL_VGA_DEVICE(0x0A1E, &intel_haswell_m_info), /* ULT GT2 reserved */ + INTEL_VGA_DEVICE(0x0A2E, &intel_haswell_m_info), /* ULT GT3 reserved */ INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */ INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */ - INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ + INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT3 desktop */ INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */ INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */ - INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ + INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT3 server */ INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */ INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */ - INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ + INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT3 mobile */ + INTEL_VGA_DEVICE(0x0D0B, &intel_haswell_d_info), /* CRW GT1 reserved */ + INTEL_VGA_DEVICE(0x0D1B, &intel_haswell_d_info), /* CRW GT2 reserved */ + INTEL_VGA_DEVICE(0x0D2B, &intel_haswell_d_info), /* CRW GT3 reserved */ + INTEL_VGA_DEVICE(0x0D0E, &intel_haswell_d_info), /* CRW GT1 reserved */ + INTEL_VGA_DEVICE(0x0D1E, &intel_haswell_d_info), /* CRW GT2 reserved */ + INTEL_VGA_DEVICE(0x0D2E, &intel_haswell_d_info), /* CRW GT3 reserved */ INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0f31, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0f32, &intel_valleyview_m_info), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d5dcf7fe1ee..b9d00dcf9a2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1943,4 +1943,19 @@ static inline void __user *to_user_ptr(u64 address) return (void __user *)(uintptr_t)address; } +static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m) +{ + unsigned long j = msecs_to_jiffies(m); + + return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1); +} + +static inline unsigned long +timespec_to_jiffies_timeout(const struct timespec *value) +{ + unsigned long j = timespec_to_jiffies(value); + + return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1); +} + #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6165535d15f..a6cf8e84397 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1003,7 +1003,7 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, wait_forever = false; } - timeout_jiffies = timespec_to_jiffies(&wait_time); + timeout_jiffies = timespec_to_jiffies_timeout(&wait_time); if (WARN_ON(!ring->irq_get(ring))) return -ENODEV; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index efe82991975..ad1117bebd7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8140,6 +8140,21 @@ static void intel_set_config_restore_state(struct drm_device *dev, } } +static bool +is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors, + int num_connectors) +{ + int i; + + for (i = 0; i < num_connectors; i++) + if (connectors[i].encoder && + connectors[i].encoder->crtc == crtc && + connectors[i].dpms != DRM_MODE_DPMS_ON) + return true; + + return false; +} + static void intel_set_config_compute_mode_changes(struct drm_mode_set *set, struct intel_set_config *config) @@ -8147,7 +8162,11 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set, /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ - if (set->crtc->fb != set->fb) { + if (set->connectors != NULL && + is_crtc_connector_off(set->crtc, *set->connectors, + set->num_connectors)) { + config->mode_changed = true; + } else if (set->crtc->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ if (set->crtc->fb == NULL) { DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); @@ -8157,8 +8176,9 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set, } else if (set->fb->pixel_format != set->crtc->fb->pixel_format) { config->mode_changed = true; - } else + } else { config->fb_changed = true; + } } if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y)) @@ -8332,11 +8352,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set) ret = intel_set_mode(set->crtc, set->mode, set->x, set->y, set->fb); - if (ret) { - DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n", - set->crtc->base.id, ret); - goto fail; - } } else if (config->fb_changed) { intel_crtc_wait_for_pending_flips(set->crtc); @@ -8344,18 +8359,18 @@ static int intel_crtc_set_config(struct drm_mode_set *set) set->x, set->y, set->fb); } - intel_set_config_free(config); - - return 0; - + if (ret) { + DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n", + set->crtc->base.id, ret); fail: - intel_set_config_restore_state(dev, config); + intel_set_config_restore_state(dev, config); - /* Try to restore the config */ - if (config->mode_changed && - intel_set_mode(save_set.crtc, save_set.mode, - save_set.x, save_set.y, save_set.fb)) - DRM_ERROR("failed to restore config after modeset failure\n"); + /* Try to restore the config */ + if (config->mode_changed && + intel_set_mode(save_set.crtc, save_set.mode, + save_set.x, save_set.y, save_set.fb)) + DRM_ERROR("failed to restore config after modeset failure\n"); + } out_config: intel_set_config_free(config); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3d704b706a8..70789b1b564 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -303,7 +303,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) if (has_aux_irq) done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, - msecs_to_jiffies(10)); + msecs_to_jiffies_timeout(10)); else done = wait_for_atomic(C, 10) == 0; if (!done) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 5d245031e39..639fe192997 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -228,7 +228,7 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv, * need to wake up periodically and check that ourselves. */ I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en); - for (i = 0; i < msecs_to_jiffies(50) + 1; i++) { + for (i = 0; i < msecs_to_jiffies_timeout(50); i++) { prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait, TASK_UNINTERRUPTIBLE); @@ -263,7 +263,8 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) /* Important: The hw handles only the first bit, so set only one! */ I915_WRITE(GMBUS4 + reg_offset, GMBUS_IDLE_EN); - ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10); + ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C, + msecs_to_jiffies_timeout(10)); I915_WRITE(GMBUS4 + reg_offset, 0); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 7bf22d4a3d9..f17dc2ab03e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -638,17 +638,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, } s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head); - if (s->event) { - struct drm_pending_vblank_event *e = s->event; - struct timeval now; - - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - list_add_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - } + if (s->event) + drm_send_vblank_event(dev, -1, s->event); list_del(&s->head); if (ps) diff --git a/drivers/gpu/drm/qxl/Kconfig b/drivers/gpu/drm/qxl/Kconfig index 2f1a57e1114..d6c12796023 100644 --- a/drivers/gpu/drm/qxl/Kconfig +++ b/drivers/gpu/drm/qxl/Kconfig @@ -4,6 +4,7 @@ config DRM_QXL select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT + select FB_DEFERRED_IO select DRM_KMS_HELPER select DRM_TTM help diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index 6db7370373e..a4b71b25fa5 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -151,7 +151,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data, struct qxl_bo *cmd_bo; int release_type; struct drm_qxl_command *commands = - (struct drm_qxl_command *)execbuffer->commands; + (struct drm_qxl_command *)(uintptr_t)execbuffer->commands; if (DRM_COPY_FROM_USER(&user_cmd, &commands[cmd_num], sizeof(user_cmd))) @@ -193,7 +193,7 @@ static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data, for (i = 0 ; i < user_cmd.relocs_num; ++i) { if (DRM_COPY_FROM_USER(&reloc, - &((struct drm_qxl_reloc *)user_cmd.relocs)[i], + &((struct drm_qxl_reloc *)(uintptr_t)user_cmd.relocs)[i], sizeof(reloc))) { qxl_bo_list_unreserve(&reloc_list, true); qxl_release_unreserve(qdev, release); diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 85127ed24cf..e27ce2a907c 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -128,12 +128,13 @@ int qxl_device_init(struct qxl_device *qdev, qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0)); qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size); - DRM_DEBUG_KMS("qxl: vram %p-%p(%dM %dk), surface %p-%p(%dM %dk)\n", - (void *)qdev->vram_base, (void *)pci_resource_end(pdev, 0), + DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk)\n", + (unsigned long long)qdev->vram_base, + (unsigned long long)pci_resource_end(pdev, 0), (int)pci_resource_len(pdev, 0) / 1024 / 1024, (int)pci_resource_len(pdev, 0) / 1024, - (void *)qdev->surfaceram_base, - (void *)pci_resource_end(pdev, 1), + (unsigned long long)qdev->surfaceram_base, + (unsigned long long)pci_resource_end(pdev, 1), (int)qdev->surfaceram_size / 1024 / 1024, (int)qdev->surfaceram_size / 1024); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 8f9e2d31b25..8546e3b333b 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4999,8 +4999,7 @@ void evergreen_fini(struct radeon_device *rdev) void evergreen_pcie_gen2_enable(struct radeon_device *rdev) { - u32 link_width_cntl, speed_cntl, mask; - int ret; + u32 link_width_cntl, speed_cntl; if (radeon_pcie_gen2 == 0) return; @@ -5015,11 +5014,8 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev) if (ASIC_IS_X2(rdev)) return; - ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) + if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && + (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) return; speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 1a08008c978..b45e6484867 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -4631,8 +4631,6 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) { u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; u16 link_cntl2; - u32 mask; - int ret; if (radeon_pcie_gen2 == 0) return; @@ -4651,11 +4649,8 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) if (rdev->family <= CHIP_R600) return; - ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) + if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && + (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) return; speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c2c59fb1ea0..189973836cf 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -467,23 +467,27 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; + /* required for EFI mode on macbook2,1 which uses an r5xx asic */ if (efi_enabled(EFI_BOOT) && - rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) + (rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) && + (rdev->family < CHIP_R600)) return false; + if (ASIC_IS_NODCE(rdev)) + goto check_memsize; + /* first check CRTCs */ - if (ASIC_IS_DCE41(rdev)) { + if (ASIC_IS_DCE4(rdev)) { reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - if (reg & EVERGREEN_CRTC_MASTER_EN) - return true; - } else if (ASIC_IS_DCE4(rdev)) { - reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + reg |= RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + reg |= RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + } if (reg & EVERGREEN_CRTC_MASTER_EN) return true; } else if (ASIC_IS_AVIVO(rdev)) { @@ -500,6 +504,7 @@ bool radeon_card_posted(struct radeon_device *rdev) } } +check_memsize: /* then check MEM_SIZE, in case the crtcs are off */ if (rdev->family >= CHIP_R600) reg = RREG32(R600_CONFIG_MEMSIZE); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index e38fd559f1a..eb18bb7af1c 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -271,8 +271,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; struct radeon_unpin_work *work; - struct drm_pending_vblank_event *e; - struct timeval now; unsigned long flags; u32 update_pending; int vpos, hpos; @@ -328,14 +326,9 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) radeon_crtc->unpin_work = NULL; /* wakeup userspace */ - if (work->event) { - e = work->event; - e->event.sequence = drm_vblank_count_and_time(rdev->ddev, crtc_id, &now); - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - list_add_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - } + if (work->event) + drm_send_vblank_event(rdev->ddev, crtc_id, work->event); + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 83f612a9500..08aef24afe4 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -862,10 +862,8 @@ int rv770_uvd_resume(struct radeon_device *rdev) chip_id = 0x0100000b; break; case CHIP_SUMO: - chip_id = 0x0100000c; - break; case CHIP_SUMO2: - chip_id = 0x0100000d; + chip_id = 0x0100000c; break; case CHIP_PALM: chip_id = 0x0100000e; @@ -2113,8 +2111,6 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) { u32 link_width_cntl, lanes, speed_cntl, tmp; u16 link_cntl2; - u32 mask; - int ret; if (radeon_pcie_gen2 == 0) return; @@ -2129,11 +2125,8 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) if (ASIC_IS_X2(rdev)) return; - ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) + if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && + (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) return; DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 5ffade69af2..d1ba9d88f31 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2616,7 +2616,7 @@ static void si_gpu_init(struct radeon_device *rdev) default: rdev->config.si.max_shader_engines = 1; rdev->config.si.max_tile_pipes = 4; - rdev->config.si.max_cu_per_sh = 2; + rdev->config.si.max_cu_per_sh = 5; rdev->config.si.max_sh_per_se = 2; rdev->config.si.max_backends_per_se = 4; rdev->config.si.max_texture_channel_caches = 4; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 7dff49ed66e..99e2034e49c 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -451,27 +451,16 @@ void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc) { struct drm_pending_vblank_event *event; struct drm_device *dev = scrtc->crtc.dev; - struct timeval vblanktime; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); event = scrtc->event; scrtc->event = NULL; + if (event) { + drm_send_vblank_event(dev, 0, event); + drm_vblank_put(dev, 0); + } spin_unlock_irqrestore(&dev->event_lock, flags); - - if (event == NULL) - return; - - event->event.sequence = drm_vblank_count_and_time(dev, 0, &vblanktime); - event->event.tv_sec = vblanktime.tv_sec; - event->event.tv_usec = vblanktime.tv_usec; - - spin_lock_irqsave(&dev->event_lock, flags); - list_add_tail(&event->base.link, &event->base.file_priv->event_list); - wake_up_interruptible(&event->base.file_priv->event_wait); - spin_unlock_irqrestore(&dev->event_lock, flags); - - drm_vblank_put(dev, 0); } static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc, diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h index ca2754a3cd6..5e040085c2f 100644 --- a/drivers/media/pci/zoran/zoran.h +++ b/drivers/media/pci/zoran/zoran.h @@ -176,7 +176,7 @@ struct zoran_fh; struct zoran_mapping { struct zoran_fh *fh; - int count; + atomic_t count; }; struct zoran_buffer { diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index 1168a84a737..d133c30c3fd 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -2803,8 +2803,7 @@ static void zoran_vm_open (struct vm_area_struct *vma) { struct zoran_mapping *map = vma->vm_private_data; - - map->count++; + atomic_inc(&map->count); } static void @@ -2815,7 +2814,7 @@ zoran_vm_close (struct vm_area_struct *vma) struct zoran *zr = fh->zr; int i; - if (--map->count > 0) + if (!atomic_dec_and_mutex_lock(&map->count, &zr->resource_lock)) return; dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr), @@ -2828,14 +2827,16 @@ zoran_vm_close (struct vm_area_struct *vma) kfree(map); /* Any buffers still mapped? */ - for (i = 0; i < fh->buffers.num_buffers; i++) - if (fh->buffers.buffer[i].map) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].map) { + mutex_unlock(&zr->resource_lock); return; + } + } dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode)); - mutex_lock(&zr->resource_lock); if (fh->map_mode == ZORAN_MAP_MODE_RAW) { if (fh->buffers.active != ZORAN_FREE) { @@ -2939,7 +2940,7 @@ zoran_mmap (struct file *file, goto mmap_unlock_and_return; } map->fh = fh; - map->count = 1; + atomic_set(&map->count, 1); vma->vm_ops = &zoran_vm_ops; vma->vm_flags |= VM_DONTEXPAND; diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 8ec8b4f4856..0f4554e48cc 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -580,6 +580,7 @@ struct aer_recover_entry u8 devfn; u16 domain; int severity; + struct aer_capability_regs *regs; }; static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry, @@ -593,7 +594,7 @@ static DEFINE_SPINLOCK(aer_recover_ring_lock); static DECLARE_WORK(aer_recover_work, aer_recover_work_func); void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, - int severity) + int severity, struct aer_capability_regs *aer_regs) { unsigned long flags; struct aer_recover_entry entry = { @@ -601,6 +602,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, .devfn = devfn, .domain = domain, .severity = severity, + .regs = aer_regs, }; spin_lock_irqsave(&aer_recover_ring_lock, flags); @@ -627,6 +629,7 @@ static void aer_recover_work_func(struct work_struct *work) PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn)); continue; } + cper_print_aer(pdev, entry.severity, entry.regs); do_recovery(pdev, entry.severity); pci_dev_put(pdev); } diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 5ab14251839..2c7c9f5f592 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -220,7 +220,7 @@ int cper_severity_to_aer(int cper_severity) } EXPORT_SYMBOL_GPL(cper_severity_to_aer); -void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity, +void cper_print_aer(struct pci_dev *dev, int cper_severity, struct aer_capability_regs *aer) { int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; @@ -244,7 +244,7 @@ void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity, agent = AER_GET_AGENT(aer_severity, status); dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask); - cper_print_bits(prefix, status, status_strs, status_strs_size); + cper_print_bits("", status, status_strs, status_strs_size); dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n", aer_error_layer[layer], aer_agent_string[agent]); if (aer_severity != AER_CORRECTABLE) diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index c67c37e23dd..694c3ace452 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -610,7 +610,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d) bool found = false; unsigned long config; - mutex_lock(&pctldev->mutex); + mutex_lock(&pinctrl_maps_mutex); /* Parse the pinctrl map and look for the elected pin/state */ for_each_maps(maps_node, i, map) { @@ -659,7 +659,7 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d) confops->pin_config_config_dbg_show(pctldev, s, config); exit: - mutex_unlock(&pctldev->mutex); + mutex_unlock(&pinctrl_maps_mutex); return 0; } diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c index a67af419f53..d6b41747d68 100644 --- a/drivers/pinctrl/pinctrl-coh901.c +++ b/drivers/pinctrl/pinctrl-coh901.c @@ -830,7 +830,8 @@ static int __init u300_gpio_probe(struct platform_device *pdev) return 0; err_no_range: - err = gpiochip_remove(&gpio->chip); + if (gpiochip_remove(&gpio->chip)) + dev_err(&pdev->dev, "failed to remove gpio chip\n"); err_no_chip: err_no_domain: err_no_port: diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index ac742817ebc..2d76f66a2e0 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -196,6 +196,12 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data) return IRQ_HANDLED; } +struct exynos_eint_gpio_save { + u32 eint_con; + u32 eint_fltcon0; + u32 eint_fltcon1; +}; + /* * exynos_eint_gpio_init() - setup handling of external gpio interrupts. * @d: driver data of samsung pinctrl driver. @@ -204,8 +210,8 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) { struct samsung_pin_bank *bank; struct device *dev = d->dev; - unsigned int ret; - unsigned int i; + int ret; + int i; if (!d->irq) { dev_err(dev, "irq number not available\n"); @@ -227,11 +233,29 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) bank->nr_pins, &exynos_gpio_irqd_ops, bank); if (!bank->irq_domain) { dev_err(dev, "gpio irq domain add failed\n"); - return -ENXIO; + ret = -ENXIO; + goto err_domains; + } + + bank->soc_priv = devm_kzalloc(d->dev, + sizeof(struct exynos_eint_gpio_save), GFP_KERNEL); + if (!bank->soc_priv) { + irq_domain_remove(bank->irq_domain); + ret = -ENOMEM; + goto err_domains; } } return 0; + +err_domains: + for (--i, --bank; i >= 0; --i, --bank) { + if (bank->eint_type != EINT_TYPE_GPIO) + continue; + irq_domain_remove(bank->irq_domain); + } + + return ret; } static void exynos_wkup_irq_unmask(struct irq_data *irqd) @@ -326,6 +350,28 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) return 0; } +static u32 exynos_eint_wake_mask = 0xffffffff; + +u32 exynos_get_eint_wake_mask(void) +{ + return exynos_eint_wake_mask; +} + +static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); + unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq); + + pr_info("wake %s for irq %d\n", on ? "enabled" : "disabled", irqd->irq); + + if (!on) + exynos_eint_wake_mask |= bit; + else + exynos_eint_wake_mask &= ~bit; + + return 0; +} + /* * irq_chip for wakeup interrupts */ @@ -335,6 +381,7 @@ static struct irq_chip exynos_wkup_irq_chip = { .irq_mask = exynos_wkup_irq_mask, .irq_ack = exynos_wkup_irq_ack, .irq_set_type = exynos_wkup_irq_set_type, + .irq_set_wake = exynos_wkup_irq_set_wake, }; /* interrupt handler for wakeup interrupts 0..15 */ @@ -505,6 +552,72 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) return 0; } +static void exynos_pinctrl_suspend_bank( + struct samsung_pinctrl_drv_data *drvdata, + struct samsung_pin_bank *bank) +{ + struct exynos_eint_gpio_save *save = bank->soc_priv; + void __iomem *regs = drvdata->virt_base; + + save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET + + bank->eint_offset); + save->eint_fltcon0 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset); + save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset + 4); + + pr_debug("%s: save con %#010x\n", bank->name, save->eint_con); + pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0); + pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1); +} + +static void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata) +{ + struct samsung_pin_ctrl *ctrl = drvdata->ctrl; + struct samsung_pin_bank *bank = ctrl->pin_banks; + int i; + + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) + if (bank->eint_type == EINT_TYPE_GPIO) + exynos_pinctrl_suspend_bank(drvdata, bank); +} + +static void exynos_pinctrl_resume_bank( + struct samsung_pinctrl_drv_data *drvdata, + struct samsung_pin_bank *bank) +{ + struct exynos_eint_gpio_save *save = bank->soc_priv; + void __iomem *regs = drvdata->virt_base; + + pr_debug("%s: con %#010x => %#010x\n", bank->name, + readl(regs + EXYNOS_GPIO_ECON_OFFSET + + bank->eint_offset), save->eint_con); + pr_debug("%s: fltcon0 %#010x => %#010x\n", bank->name, + readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset), save->eint_fltcon0); + pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name, + readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset + 4), save->eint_fltcon1); + + writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET + + bank->eint_offset); + writel(save->eint_fltcon0, regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset); + writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET + + 2 * bank->eint_offset + 4); +} + +static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata) +{ + struct samsung_pin_ctrl *ctrl = drvdata->ctrl; + struct samsung_pin_bank *bank = ctrl->pin_banks; + int i; + + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) + if (bank->eint_type == EINT_TYPE_GPIO) + exynos_pinctrl_resume_bank(drvdata, bank); +} + /* pin banks of exynos4210 pin-controller 0 */ static struct samsung_pin_bank exynos4210_pin_banks0[] = { EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), @@ -568,6 +681,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4210-gpio-ctrl0", }, { /* pin-controller instance 1 data */ @@ -582,6 +697,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4210-gpio-ctrl1", }, { /* pin-controller instance 2 data */ @@ -663,6 +780,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl0", }, { /* pin-controller instance 1 data */ @@ -677,6 +796,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl1", }, { /* pin-controller instance 2 data */ @@ -687,6 +808,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl2", }, { /* pin-controller instance 3 data */ @@ -697,6 +820,8 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos4x12-gpio-ctrl3", }, }; @@ -775,6 +900,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = { .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos5250-gpio-ctrl0", }, { /* pin-controller instance 1 data */ @@ -785,6 +912,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos5250-gpio-ctrl1", }, { /* pin-controller instance 2 data */ @@ -795,6 +924,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos5250-gpio-ctrl2", }, { /* pin-controller instance 3 data */ @@ -805,6 +936,8 @@ struct samsung_pin_ctrl exynos5250_pin_ctrl[] = { .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, .svc = EXYNOS_SVC_OFFSET, .eint_gpio_init = exynos_eint_gpio_init, + .suspend = exynos_pinctrl_suspend, + .resume = exynos_pinctrl_resume, .label = "exynos5250-gpio-ctrl3", }, }; diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index 9b1f77a5bf0..3c91c357792 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h @@ -19,6 +19,7 @@ /* External GPIO and wakeup interrupt related definitions */ #define EXYNOS_GPIO_ECON_OFFSET 0x700 +#define EXYNOS_GPIO_EFLTCON_OFFSET 0x800 #define EXYNOS_GPIO_EMASK_OFFSET 0x900 #define EXYNOS_GPIO_EPEND_OFFSET 0xA00 #define EXYNOS_WKUP_ECON_OFFSET 0xE00 diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 055d0162098..63ac22e8967 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -28,6 +28,7 @@ #include <linux/gpio.h> #include <linux/irqdomain.h> #include <linux/spinlock.h> +#include <linux/syscore_ops.h> #include "core.h" #include "pinctrl-samsung.h" @@ -48,6 +49,9 @@ static struct pin_config { { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, }; +/* Global list of devices (struct samsung_pinctrl_drv_data) */ +LIST_HEAD(drvdata_list); + static unsigned int pin_base; static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc) @@ -956,9 +960,151 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) ctrl->eint_wkup_init(drvdata); platform_set_drvdata(pdev, drvdata); + + /* Add to the global list */ + list_add_tail(&drvdata->node, &drvdata_list); + return 0; } +#ifdef CONFIG_PM + +/** + * samsung_pinctrl_suspend_dev - save pinctrl state for suspend for a device + * + * Save data for all banks handled by this device. + */ +static void samsung_pinctrl_suspend_dev( + struct samsung_pinctrl_drv_data *drvdata) +{ + struct samsung_pin_ctrl *ctrl = drvdata->ctrl; + void __iomem *virt_base = drvdata->virt_base; + int i; + + for (i = 0; i < ctrl->nr_banks; i++) { + struct samsung_pin_bank *bank = &ctrl->pin_banks[i]; + void __iomem *reg = virt_base + bank->pctl_offset; + + u8 *offs = bank->type->reg_offset; + u8 *widths = bank->type->fld_width; + enum pincfg_type type; + + /* Registers without a powerdown config aren't lost */ + if (!widths[PINCFG_TYPE_CON_PDN]) + continue; + + for (type = 0; type < PINCFG_TYPE_NUM; type++) + if (widths[type]) + bank->pm_save[type] = readl(reg + offs[type]); + + if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) { + /* Some banks have two config registers */ + bank->pm_save[PINCFG_TYPE_NUM] = + readl(reg + offs[PINCFG_TYPE_FUNC] + 4); + pr_debug("Save %s @ %p (con %#010x %08x)\n", + bank->name, reg, + bank->pm_save[PINCFG_TYPE_FUNC], + bank->pm_save[PINCFG_TYPE_NUM]); + } else { + pr_debug("Save %s @ %p (con %#010x)\n", bank->name, + reg, bank->pm_save[PINCFG_TYPE_FUNC]); + } + } + + if (ctrl->suspend) + ctrl->suspend(drvdata); +} + +/** + * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device + * + * Restore one of the banks that was saved during suspend. + * + * We don't bother doing anything complicated to avoid glitching lines since + * we're called before pad retention is turned off. + */ +static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) +{ + struct samsung_pin_ctrl *ctrl = drvdata->ctrl; + void __iomem *virt_base = drvdata->virt_base; + int i; + + if (ctrl->resume) + ctrl->resume(drvdata); + + for (i = 0; i < ctrl->nr_banks; i++) { + struct samsung_pin_bank *bank = &ctrl->pin_banks[i]; + void __iomem *reg = virt_base + bank->pctl_offset; + + u8 *offs = bank->type->reg_offset; + u8 *widths = bank->type->fld_width; + enum pincfg_type type; + + /* Registers without a powerdown config aren't lost */ + if (!widths[PINCFG_TYPE_CON_PDN]) + continue; + + if (widths[PINCFG_TYPE_FUNC] * bank->nr_pins > 32) { + /* Some banks have two config registers */ + pr_debug("%s @ %p (con %#010x %08x => %#010x %08x)\n", + bank->name, reg, + readl(reg + offs[PINCFG_TYPE_FUNC]), + readl(reg + offs[PINCFG_TYPE_FUNC] + 4), + bank->pm_save[PINCFG_TYPE_FUNC], + bank->pm_save[PINCFG_TYPE_NUM]); + writel(bank->pm_save[PINCFG_TYPE_NUM], + reg + offs[PINCFG_TYPE_FUNC] + 4); + } else { + pr_debug("%s @ %p (con %#010x => %#010x)\n", bank->name, + reg, readl(reg + offs[PINCFG_TYPE_FUNC]), + bank->pm_save[PINCFG_TYPE_FUNC]); + } + for (type = 0; type < PINCFG_TYPE_NUM; type++) + if (widths[type]) + writel(bank->pm_save[type], reg + offs[type]); + } +} + +/** + * samsung_pinctrl_suspend - save pinctrl state for suspend + * + * Save data for all banks across all devices. + */ +static int samsung_pinctrl_suspend(void) +{ + struct samsung_pinctrl_drv_data *drvdata; + + list_for_each_entry(drvdata, &drvdata_list, node) { + samsung_pinctrl_suspend_dev(drvdata); + } + + return 0; +} + +/** + * samsung_pinctrl_resume - restore pinctrl state for suspend + * + * Restore data for all banks across all devices. + */ +static void samsung_pinctrl_resume(void) +{ + struct samsung_pinctrl_drv_data *drvdata; + + list_for_each_entry_reverse(drvdata, &drvdata_list, node) { + samsung_pinctrl_resume_dev(drvdata); + } +} + +#else +#define samsung_pinctrl_suspend NULL +#define samsung_pinctrl_resume NULL +#endif + +static struct syscore_ops samsung_pinctrl_syscore_ops = { + .suspend = samsung_pinctrl_suspend, + .resume = samsung_pinctrl_resume, +}; + static const struct of_device_id samsung_pinctrl_dt_match[] = { #ifdef CONFIG_PINCTRL_EXYNOS { .compatible = "samsung,exynos4210-pinctrl", @@ -987,6 +1133,14 @@ static struct platform_driver samsung_pinctrl_driver = { static int __init samsung_pinctrl_drv_register(void) { + /* + * Register syscore ops for save/restore of registers across suspend. + * It's important to ensure that this driver is running at an earlier + * initcall level than any arch-specific init calls that install syscore + * ops that turn off pad retention (like exynos_pm_resume). + */ + register_syscore_ops(&samsung_pinctrl_syscore_ops); + return platform_driver_register(&samsung_pinctrl_driver); } postcore_initcall(samsung_pinctrl_drv_register); diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index 7c7f9ebcd05..26d3519240c 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -127,6 +127,7 @@ struct samsung_pin_bank_type { * @gpio_chip: GPIO chip of the bank. * @grange: linux gpio pin range supported by this bank. * @slock: spinlock protecting bank registers + * @pm_save: saved register values during suspend */ struct samsung_pin_bank { struct samsung_pin_bank_type *type; @@ -138,12 +139,15 @@ struct samsung_pin_bank { u32 eint_mask; u32 eint_offset; char *name; + void *soc_priv; struct device_node *of_node; struct samsung_pinctrl_drv_data *drvdata; struct irq_domain *irq_domain; struct gpio_chip gpio_chip; struct pinctrl_gpio_range grange; spinlock_t slock; + + u32 pm_save[PINCFG_TYPE_NUM + 1]; /* +1 to handle double CON registers*/ }; /** @@ -184,11 +188,15 @@ struct samsung_pin_ctrl { int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); + void (*suspend)(struct samsung_pinctrl_drv_data *); + void (*resume)(struct samsung_pinctrl_drv_data *); + char *label; }; /** * struct samsung_pinctrl_drv_data: wrapper for holding driver data together. + * @node: global list node * @virt_base: register base address of the controller. * @dev: device instance representing the controller. * @irq: interrpt number used by the controller to notify gpio interrupts. @@ -201,6 +209,7 @@ struct samsung_pin_ctrl { * @nr_function: number of such pin functions. */ struct samsung_pinctrl_drv_data { + struct list_head node; void __iomem *virt_base; struct device *dev; int irq; diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c index c52fc2c0873..b7d8c890514 100644 --- a/drivers/pinctrl/pinctrl-sunxi.c +++ b/drivers/pinctrl/pinctrl-sunxi.c @@ -1990,8 +1990,10 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev) } clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); goto gpiochip_error; + } clk_prepare_enable(clk); @@ -2000,7 +2002,8 @@ static int sunxi_pinctrl_probe(struct platform_device *pdev) return 0; gpiochip_error: - ret = gpiochip_remove(pctl->chip); + if (gpiochip_remove(pctl->chip)) + dev_err(&pdev->dev, "failed to remove gpio chip\n"); pinctrl_error: pinctrl_unregister(pctl->pctl_dev); return ret; diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index ab63104e8dc..70d986e04af 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -609,8 +609,7 @@ int wmt_pinctrl_probe(struct platform_device *pdev, return 0; fail_range: - err = gpiochip_remove(&data->gpio_chip); - if (err) + if (gpiochip_remove(&data->gpio_chip)) dev_err(&pdev->dev, "failed to remove gpio chip\n"); fail_gpio: pinctrl_unregister(data->pctl_dev); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index db66357211e..86f0c5d5c11 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -84,6 +84,7 @@ static int proc_scsi_host_open(struct inode *inode, struct file *file) static const struct file_operations proc_scsi_fops = { .open = proc_scsi_host_open, + .release = single_release, .read = seq_read, .llseek = seq_lseek, .write = proc_scsi_host_write diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c index ea61c869110..ff5c6335093 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c @@ -316,31 +316,14 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) { - struct drm_pending_vblank_event *e; - struct timeval now; unsigned long flags; struct drm_device *drm = ipu_crtc->base.dev; spin_lock_irqsave(&drm->event_lock, flags); - - e = ipu_crtc->page_flip_event; - if (!e) { - spin_unlock_irqrestore(&drm->event_lock, flags); - return; - } - - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; + if (ipu_crtc->page_flip_event) + drm_send_vblank_event(drm, -1, ipu_crtc->page_flip_event); ipu_crtc->page_flip_event = NULL; - imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); - - list_add_tail(&e->base.link, &e->base.file_priv->event_list); - - wake_up_interruptible(&e->base.file_priv->event_wait); - spin_unlock_irqrestore(&drm->event_lock, flags); } diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 18e8bd8fa94..cc072c66c76 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c @@ -41,6 +41,8 @@ module_param(selfballooning, bool, S_IRUGO); #ifdef CONFIG_FRONTSWAP static bool frontswap __read_mostly = true; module_param(frontswap, bool, S_IRUGO); +#else /* CONFIG_FRONTSWAP */ +#define frontswap (0) #endif /* CONFIG_FRONTSWAP */ #ifdef CONFIG_XEN_SELFBALLOONING diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index a2278ba7fb2..4e8ba38aa0c 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -106,7 +106,7 @@ static void pcistub_device_release(struct kref *kref) else pci_restore_state(dev); - if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { + if (dev->msix_cap) { struct physdev_pci_device ppdev = { .seg = pci_domain_nr(dev->bus), .bus = dev->bus->number, @@ -371,7 +371,7 @@ static int pcistub_init_device(struct pci_dev *dev) if (err) goto config_release; - if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { + if (dev->msix_cap) { struct physdev_pci_device ppdev = { .seg = pci_domain_nr(dev->bus), .bus = dev->bus->number, diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 61786be9138..ec097d6f964 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -534,7 +534,7 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, err = xenbus_map_ring(dev, gnt_ref, &node->handle, addr); if (err) - goto out_err; + goto out_err_free_ballooned_pages; spin_lock(&xenbus_valloc_lock); list_add(&node->next, &xenbus_valloc_pages); @@ -543,8 +543,9 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, *vaddr = addr; return 0; - out_err: + out_err_free_ballooned_pages: free_xenballooned_pages(1, &node->page); + out_err: kfree(node); return err; } diff --git a/drivers/xen/xenbus/xenbus_comms.h b/drivers/xen/xenbus/xenbus_comms.h index c8abd3b8a6c..e74f9c1fbd8 100644 --- a/drivers/xen/xenbus/xenbus_comms.h +++ b/drivers/xen/xenbus/xenbus_comms.h @@ -45,6 +45,7 @@ int xb_wait_for_data_to_read(void); int xs_input_avail(void); extern struct xenstore_domain_interface *xen_store_interface; extern int xen_store_evtchn; +extern enum xenstore_init xen_store_domain_type; extern const struct file_operations xen_xenbus_fops; diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 3325884c693..56cfaaa9d00 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -69,6 +69,9 @@ EXPORT_SYMBOL_GPL(xen_store_evtchn); struct xenstore_domain_interface *xen_store_interface; EXPORT_SYMBOL_GPL(xen_store_interface); +enum xenstore_init xen_store_domain_type; +EXPORT_SYMBOL_GPL(xen_store_domain_type); + static unsigned long xen_store_mfn; static BLOCKING_NOTIFIER_HEAD(xenstore_chain); @@ -719,17 +722,11 @@ static int __init xenstored_local_init(void) return err; } -enum xenstore_init { - UNKNOWN, - PV, - HVM, - LOCAL, -}; static int __init xenbus_init(void) { int err = 0; - enum xenstore_init usage = UNKNOWN; uint64_t v = 0; + xen_store_domain_type = XS_UNKNOWN; if (!xen_domain()) return -ENODEV; @@ -737,29 +734,29 @@ static int __init xenbus_init(void) xenbus_ring_ops_init(); if (xen_pv_domain()) - usage = PV; + xen_store_domain_type = XS_PV; if (xen_hvm_domain()) - usage = HVM; + xen_store_domain_type = XS_HVM; if (xen_hvm_domain() && xen_initial_domain()) - usage = LOCAL; + xen_store_domain_type = XS_LOCAL; if (xen_pv_domain() && !xen_start_info->store_evtchn) - usage = LOCAL; + xen_store_domain_type = XS_LOCAL; if (xen_pv_domain() && xen_start_info->store_evtchn) xenstored_ready = 1; - switch (usage) { - case LOCAL: + switch (xen_store_domain_type) { + case XS_LOCAL: err = xenstored_local_init(); if (err) goto out_error; xen_store_interface = mfn_to_virt(xen_store_mfn); break; - case PV: + case XS_PV: xen_store_evtchn = xen_start_info->store_evtchn; xen_store_mfn = xen_start_info->store_mfn; xen_store_interface = mfn_to_virt(xen_store_mfn); break; - case HVM: + case XS_HVM: err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); if (err) goto out_error; diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h index bb4f92ed873..146f857a36f 100644 --- a/drivers/xen/xenbus/xenbus_probe.h +++ b/drivers/xen/xenbus/xenbus_probe.h @@ -47,6 +47,13 @@ struct xen_bus_type { struct bus_type bus; }; +enum xenstore_init { + XS_UNKNOWN, + XS_PV, + XS_HVM, + XS_LOCAL, +}; + extern struct device_attribute xenbus_dev_attrs[]; extern int xenbus_match(struct device *_dev, struct device_driver *_drv); diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 3159a37d966..a7e25073de1 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -29,6 +29,8 @@ #include "xenbus_probe.h" +static struct workqueue_struct *xenbus_frontend_wq; + /* device/<type>/<id> => <type>-<id> */ static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) { @@ -89,9 +91,40 @@ static void backend_changed(struct xenbus_watch *watch, xenbus_otherend_changed(watch, vec, len, 1); } +static void xenbus_frontend_delayed_resume(struct work_struct *w) +{ + struct xenbus_device *xdev = container_of(w, struct xenbus_device, work); + + xenbus_dev_resume(&xdev->dev); +} + +static int xenbus_frontend_dev_resume(struct device *dev) +{ + /* + * If xenstored is running in this domain, we cannot access the backend + * state at the moment, so we need to defer xenbus_dev_resume + */ + if (xen_store_domain_type == XS_LOCAL) { + struct xenbus_device *xdev = to_xenbus_device(dev); + + if (!xenbus_frontend_wq) { + pr_err("%s: no workqueue to process delayed resume\n", + xdev->nodename); + return -EFAULT; + } + + INIT_WORK(&xdev->work, xenbus_frontend_delayed_resume); + queue_work(xenbus_frontend_wq, &xdev->work); + + return 0; + } + + return xenbus_dev_resume(dev); +} + static const struct dev_pm_ops xenbus_pm_ops = { .suspend = xenbus_dev_suspend, - .resume = xenbus_dev_resume, + .resume = xenbus_frontend_dev_resume, .freeze = xenbus_dev_suspend, .thaw = xenbus_dev_cancel, .restore = xenbus_dev_resume, @@ -440,6 +473,8 @@ static int __init xenbus_probe_frontend_init(void) register_xenstore_notifier(&xenstore_notifier); + xenbus_frontend_wq = create_workqueue("xenbus_frontend"); + return 0; } subsys_initcall(xenbus_probe_frontend_init); |