diff options
50 files changed, 1167 insertions, 851 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e43eb1a9d8c..ee63a123235 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2104,7 +2104,7 @@ int drm_mode_addfb(struct drm_device *dev, fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); if (IS_ERR(fb)) { - DRM_ERROR("could not create framebuffer\n"); + DRM_DEBUG_KMS("could not create framebuffer\n"); ret = PTR_ERR(fb); goto out; } @@ -2193,7 +2193,7 @@ static int framebuffer_check(struct drm_mode_fb_cmd2 *r) ret = format_check(r); if (ret) { - DRM_ERROR("bad framebuffer format 0x%08x\n", r->pixel_format); + DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format); return ret; } @@ -2202,12 +2202,12 @@ static int framebuffer_check(struct drm_mode_fb_cmd2 *r) num_planes = drm_format_num_planes(r->pixel_format); if (r->width == 0 || r->width % hsub) { - DRM_ERROR("bad framebuffer width %u\n", r->height); + DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); return -EINVAL; } if (r->height == 0 || r->height % vsub) { - DRM_ERROR("bad framebuffer height %u\n", r->height); + DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); return -EINVAL; } @@ -2215,12 +2215,12 @@ static int framebuffer_check(struct drm_mode_fb_cmd2 *r) unsigned int width = r->width / (i != 0 ? hsub : 1); if (!r->handles[i]) { - DRM_ERROR("no buffer object handle for plane %d\n", i); + DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); return -EINVAL; } if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) { - DRM_ERROR("bad pitch %u for plane %d\n", r->pitches[i], i); + DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); return -EINVAL; } } @@ -2257,12 +2257,12 @@ int drm_mode_addfb2(struct drm_device *dev, return -EINVAL; if ((config->min_width > r->width) || (r->width > config->max_width)) { - DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n", + DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", r->width, config->min_width, config->max_width); return -EINVAL; } if ((config->min_height > r->height) || (r->height > config->max_height)) { - DRM_ERROR("bad framebuffer height %d, should be >= %d && <= %d\n", + DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", r->height, config->min_height, config->max_height); return -EINVAL; } @@ -2275,7 +2275,7 @@ int drm_mode_addfb2(struct drm_device *dev, fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); if (IS_ERR(fb)) { - DRM_ERROR("could not create framebuffer\n"); + DRM_DEBUG_KMS("could not create framebuffer\n"); ret = PTR_ERR(fb); goto out; } diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile index 1583982917c..dd7d6b57996 100644 --- a/drivers/gpu/drm/gma500/Makefile +++ b/drivers/gpu/drm/gma500/Makefile @@ -1,7 +1,7 @@ # # KMS driver for the GMA500 # -ccflags-y += -Iinclude/drm +ccflags-y += -I$(srctree)/include/drm gma500_gfx-y += gem_glue.o \ accel_2d.o \ @@ -12,8 +12,8 @@ gma500_gfx-y += gem_glue.o \ intel_bios.o \ intel_i2c.o \ intel_gmbus.o \ - intel_opregion.o \ mmu.o \ + opregion.o \ power.o \ psb_drv.o \ psb_intel_display.o \ diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 62f9b735459..c10f02068d1 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -57,8 +57,7 @@ static int cdv_output_init(struct drm_device *dev) cdv_intel_crt_init(dev, &dev_priv->mode_dev); cdv_intel_lvds_init(dev, &dev_priv->mode_dev); - /* These bits indicate HDMI not SDVO on CDV, but we don't yet support - the HDMI interface */ + /* These bits indicate HDMI not SDVO on CDV */ if (REG_READ(SDVOB) & SDVO_DETECTED) cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); if (REG_READ(SDVOC) & SDVO_DETECTED) @@ -69,76 +68,71 @@ static int cdv_output_init(struct drm_device *dev) #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE /* - * Poulsbo Backlight Interfaces + * Cedartrail Backlght Interfaces */ -#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 - -#define PSB_BLC_PWM_PRECISION_FACTOR 10 -#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE -#define PSB_BLC_MIN_PWM_REG_FREQ 0x2 - -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) - -static int cdv_brightness; static struct backlight_device *cdv_backlight_device; -static int cdv_get_brightness(struct backlight_device *bd) +static int cdv_backlight_combination_mode(struct drm_device *dev) { - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return cdv_brightness; + return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE; } - -static int cdv_backlight_setup(struct drm_device *dev) +static int cdv_get_brightness(struct backlight_device *bd) { - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long core_clock; - /* u32 bl_max_freq; */ - /* unsigned long value; */ - u16 bl_max_freq; - uint32_t value; - uint32_t blc_pwm_precision_factor; - - /* get bl_max_freq and pol from dev_priv*/ - if (!dev_priv->lvds_bl) { - dev_err(dev->dev, "Has no valid LVDS backlight info\n"); - return -ENOENT; - } - bl_max_freq = dev_priv->lvds_bl->freq; - blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; + struct drm_device *dev = bl_get_data(bd); + u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - core_clock = dev_priv->core_freq; + if (cdv_backlight_combination_mode(dev)) { + u8 lbpc; - value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; - value *= blc_pwm_precision_factor; - value /= bl_max_freq; - value /= blc_pwm_precision_factor; + val &= ~1; + pci_read_config_byte(dev->pdev, 0xF4, &lbpc); + val *= lbpc; + } + return val; +} - if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || - value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) - return -ERANGE; - else { - /* FIXME */ +static u32 cdv_get_max_backlight(struct drm_device *dev) +{ + u32 max = REG_READ(BLC_PWM_CTL); + + if (max == 0) { + DRM_DEBUG_KMS("LVDS Panel PWM value is 0!\n"); + /* i915 does this, I believe which means that we should not + * smash PWM control as firmware will take control of it. */ + return 1; } - return 0; + + max >>= 16; + if (cdv_backlight_combination_mode(dev)) + max *= 0xff; + return max; } static int cdv_set_brightness(struct backlight_device *bd) { + struct drm_device *dev = bl_get_data(bd); int level = bd->props.brightness; + u32 blc_pwm_ctl; /* Percentage 1-100% being valid */ if (level < 1) level = 1; - /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ - cdv_brightness = level; + if (cdv_backlight_combination_mode(dev)) { + u32 max = cdv_get_max_backlight(dev); + u8 lbpc; + + lbpc = level * 0xfe / max + 1; + level /= lbpc; + + pci_write_config_byte(dev->pdev, 0xF4, lbpc); + } + + blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | + (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); return 0; } @@ -150,7 +144,6 @@ static const struct backlight_ops cdv_ops = { static int cdv_backlight_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; - int ret; struct backlight_properties props; memset(&props, 0, sizeof(struct backlight_properties)); @@ -162,14 +155,9 @@ static int cdv_backlight_init(struct drm_device *dev) if (IS_ERR(cdv_backlight_device)) return PTR_ERR(cdv_backlight_device); - ret = cdv_backlight_setup(dev); - if (ret < 0) { - backlight_device_unregister(cdv_backlight_device); - cdv_backlight_device = NULL; - return ret; - } - cdv_backlight_device->props.brightness = 100; - cdv_backlight_device->props.max_brightness = 100; + cdv_backlight_device->props.brightness = + cdv_get_brightness(cdv_backlight_device); + cdv_backlight_device->props.max_brightness = cdv_get_max_backlight(dev); backlight_update_status(cdv_backlight_device); dev_priv->backlight_device = cdv_backlight_device; return 0; @@ -244,11 +232,12 @@ static void cdv_init_pm(struct drm_device *dev) static void cdv_errata(struct drm_device *dev) { /* Disable bonus launch. - * CPU and GPU competes for memory and display misses updates and flickers. - * Worst with dual core, dual displays. + * CPU and GPU competes for memory and display misses updates and + * flickers. Worst with dual core, dual displays. * - * Fixes were done to Win 7 gfx driver to disable a feature called Bonus - * Launch to work around the issue, by degrading performance. + * Fixes were done to Win 7 gfx driver to disable a feature called + * Bonus Launch to work around the issue, by degrading + * performance. */ CDV_MSG_WRITE32(3, 0x30, 0x08027108); } @@ -501,7 +490,7 @@ static int cdv_chip_setup(struct drm_device *dev) struct drm_psb_private *dev_priv = dev->dev_private; INIT_WORK(&dev_priv->hotplug_work, cdv_hotplug_work_func); cdv_get_core_freq(dev); - gma_intel_opregion_init(dev); + psb_intel_opregion_init(dev); psb_intel_init_bios(dev); cdv_hotplug_enable(dev, false); return 0; diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 44a8353d92b..ff5b58eb878 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -556,7 +556,7 @@ static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder) drm_encoder_cleanup(encoder); } -const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { +static const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { .destroy = cdv_intel_lvds_enc_destroy, }; diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index c9fe4bdeb68..f47f883ff9e 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -408,6 +408,8 @@ static int psbfb_create(struct psb_fbdev *fbdev, return -ENOMEM; } + memset(dev_priv->vram_addr + backing->offset, 0, size); + mutex_lock(&dev->struct_mutex); info = framebuffer_alloc(0, device); @@ -453,8 +455,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, info->fix.ypanstep = 0; /* Accessed stolen memory directly */ - info->screen_base = (char *)dev_priv->vram_addr + - backing->offset; + info->screen_base = dev_priv->vram_addr + backing->offset; info->screen_size = size; if (dev_priv->gtt.stolen_size) { @@ -571,7 +572,7 @@ static int psbfb_probe(struct drm_fb_helper *helper, return new_fb; } -struct drm_fb_helper_funcs psb_fb_helper_funcs = { +static struct drm_fb_helper_funcs psb_fb_helper_funcs = { .gamma_set = psbfb_gamma_set, .gamma_get = psbfb_gamma_get, .fb_probe = psbfb_probe, diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 54e5c9e1e6f..4cd33df5f93 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -61,7 +61,7 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) * Given a gtt_range object return the GTT offset of the page table * entries for this gtt_range */ -static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) +static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) { struct drm_psb_private *dev_priv = dev->dev_private; unsigned long offset; @@ -82,7 +82,8 @@ static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) */ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) { - u32 *gtt_slot, pte; + u32 __iomem *gtt_slot; + u32 pte; struct page **pages; int i; @@ -126,7 +127,8 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) { struct drm_psb_private *dev_priv = dev->dev_private; - u32 *gtt_slot, pte; + u32 __iomem *gtt_slot; + u32 pte; int i; WARN_ON(r->stolen); @@ -152,7 +154,8 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) */ void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll) { - u32 *gtt_slot, pte; + u32 __iomem *gtt_slot; + u32 pte; int i; if (roll >= r->npage) { @@ -413,7 +416,6 @@ int psb_gtt_init(struct drm_device *dev, int resume) unsigned long stolen_size, vram_stolen_size; unsigned i, num_pages; unsigned pfn_base; - uint32_t vram_pages; uint32_t dvmt_mode = 0; struct psb_gtt *pg; @@ -529,7 +531,7 @@ int psb_gtt_init(struct drm_device *dev, int resume) */ pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; - vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT; + num_pages = vram_stolen_size >> PAGE_SHIFT; printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", num_pages, pfn_base << PAGE_SHIFT, 0); for (i = 0; i < num_pages; ++i) { diff --git a/drivers/gpu/drm/gma500/intel_opregion.c b/drivers/gpu/drm/gma500/intel_opregion.c deleted file mode 100644 index 7041f40afff..00000000000 --- a/drivers/gpu/drm/gma500/intel_opregion.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * FIXME: resolve with the i915 version - */ - -#include "psb_drv.h" - -#define PCI_ASLE 0xe4 -#define PCI_ASLS 0xfc - -#define OPREGION_HEADER_OFFSET 0 -#define OPREGION_ACPI_OFFSET 0x100 -#define ACPI_CLID 0x01ac /* current lid state indicator */ -#define ACPI_CDCK 0x01b0 /* current docking state indicator */ -#define OPREGION_SWSCI_OFFSET 0x200 -#define OPREGION_ASLE_OFFSET 0x300 -#define OPREGION_VBT_OFFSET 0x400 - -#define OPREGION_SIGNATURE "IntelGraphicsMem" -#define MBOX_ACPI (1<<0) -#define MBOX_SWSCI (1<<1) -#define MBOX_ASLE (1<<2) - -struct opregion_header { - u8 signature[16]; - u32 size; - u32 opregion_ver; - u8 bios_ver[32]; - u8 vbios_ver[16]; - u8 driver_ver[16]; - u32 mboxes; - u8 reserved[164]; -} __packed; - -/* OpRegion mailbox #1: public ACPI methods */ -struct opregion_acpi { - u32 drdy; /* driver readiness */ - u32 csts; /* notification status */ - u32 cevt; /* current event */ - u8 rsvd1[20]; - u32 didl[8]; /* supported display devices ID list */ - u32 cpdl[8]; /* currently presented display list */ - u32 cadl[8]; /* currently active display list */ - u32 nadl[8]; /* next active devices list */ - u32 aslp; /* ASL sleep time-out */ - u32 tidx; /* toggle table index */ - u32 chpd; /* current hotplug enable indicator */ - u32 clid; /* current lid state*/ - u32 cdck; /* current docking state */ - u32 sxsw; /* Sx state resume */ - u32 evts; /* ASL supported events */ - u32 cnot; /* current OS notification */ - u32 nrdy; /* driver status */ - u8 rsvd2[60]; -} __attribute__((packed)); - -/* OpRegion mailbox #2: SWSCI */ -struct opregion_swsci { - u32 scic; /* SWSCI command|status|data */ - u32 parm; /* command parameters */ - u32 dslp; /* driver sleep time-out */ - u8 rsvd[244]; -} __attribute__((packed)); - -/* OpRegion mailbox #3: ASLE */ -struct opregion_asle { - u32 ardy; /* driver readiness */ - u32 aslc; /* ASLE interrupt command */ - u32 tche; /* technology enabled indicator */ - u32 alsi; /* current ALS illuminance reading */ - u32 bclp; /* backlight brightness to set */ - u32 pfit; /* panel fitting state */ - u32 cblv; /* current brightness level */ - u16 bclm[20]; /* backlight level duty cycle mapping table */ - u32 cpfm; /* current panel fitting mode */ - u32 epfm; /* enabled panel fitting modes */ - u8 plut[74]; /* panel LUT and identifier */ - u32 pfmb; /* PWM freq and min brightness */ - u8 rsvd[102]; -} __attribute__((packed)); - -/* ASLE irq request bits */ -#define ASLE_SET_ALS_ILLUM (1 << 0) -#define ASLE_SET_BACKLIGHT (1 << 1) -#define ASLE_SET_PFIT (1 << 2) -#define ASLE_SET_PWM_FREQ (1 << 3) -#define ASLE_REQ_MSK 0xf - -/* response bits of ASLE irq request */ -#define ASLE_ALS_ILLUM_FAILED (1<<10) -#define ASLE_BACKLIGHT_FAILED (1<<12) -#define ASLE_PFIT_FAILED (1<<14) -#define ASLE_PWM_FREQ_FAILED (1<<16) - -/* ASLE backlight brightness to set */ -#define ASLE_BCLP_VALID (1<<31) -#define ASLE_BCLP_MSK (~(1<<31)) - -/* ASLE panel fitting request */ -#define ASLE_PFIT_VALID (1<<31) -#define ASLE_PFIT_CENTER (1<<0) -#define ASLE_PFIT_STRETCH_TEXT (1<<1) -#define ASLE_PFIT_STRETCH_GFX (1<<2) - -/* PWM frequency and minimum brightness */ -#define ASLE_PFMB_BRIGHTNESS_MASK (0xff) -#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8) -#define ASLE_PFMB_PWM_MASK (0x7ffffe00) -#define ASLE_PFMB_PWM_VALID (1<<31) - -#define ASLE_CBLV_VALID (1<<31) - -#define ACPI_OTHER_OUTPUT (0<<8) -#define ACPI_VGA_OUTPUT (1<<8) -#define ACPI_TV_OUTPUT (2<<8) -#define ACPI_DIGITAL_OUTPUT (3<<8) -#define ACPI_LVDS_OUTPUT (4<<8) - -int gma_intel_opregion_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct psb_intel_opregion *opregion = &dev_priv->opregion; - u32 opregion_phy; - void *base; - u32 *lid_state; - - dev_priv->lid_state = NULL; - - pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy); - if (opregion_phy == 0) - return -ENOTSUPP; - - base = ioremap(opregion_phy, 8*1024); - if (!base) - return -ENOMEM; - /* FIXME: should use _io ops - ditto on i915 */ - if (memcmp(base, OPREGION_SIGNATURE, 16)) { - DRM_ERROR("opregion signature mismatch\n"); - iounmap(base); - return -EINVAL; - } - - lid_state = base + 0x01ac; - - dev_priv->lid_state = lid_state; - dev_priv->lid_last_state = readl(lid_state); - opregion->header = base; - opregion->vbt = base + OPREGION_VBT_OFFSET; - return 0; -} - -int gma_intel_opregion_exit(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - if (dev_priv->opregion.header) - iounmap(dev_priv->opregion.header); - return 0; -} diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c index a0bd48cd92f..717f4db28c3 100644 --- a/drivers/gpu/drm/gma500/mdfld_device.c +++ b/drivers/gpu/drm/gma500/mdfld_device.c @@ -672,8 +672,8 @@ const struct psb_ops mdfld_chip_ops = { .accel_2d = 0, .pipes = 3, .crtcs = 3, - .lvds_mask = (1 << 1); - .hdmi_mask = (1 << 1); + .lvds_mask = (1 << 1), + .hdmi_mask = (1 << 1), .sgx_offset = MRST_SGX_OFFSET, .chip_setup = mid_chip_setup, diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c index d52358b744a..b34ff097b97 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c @@ -869,7 +869,6 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, mdfld_set_pipe_timing(dsi_config, pipe); REG_WRITE(DSPABASE, 0x00); - REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4)); REG_WRITE(DSPASIZE, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index 5eee9ad80da..b2a790bd989 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c @@ -118,139 +118,214 @@ static void mid_get_pci_revID(struct drm_psb_private *dev_priv) dev_priv->platform_rev_id); } +struct vbt_header { + u32 signature; + u8 revision; +} __packed; + +/* The same for r0 and r1 */ +struct vbt_r0 { + struct vbt_header vbt_header; + u8 size; + u8 checksum; +} __packed; + +struct vbt_r10 { + struct vbt_header vbt_header; + u8 checksum; + u16 size; + u8 panel_count; + u8 primary_panel_idx; + u8 secondary_panel_idx; + u8 __reserved[5]; +} __packed; + +static int read_vbt_r0(u32 addr, struct vbt_r0 *vbt) +{ + void __iomem *vbt_virtual; + + vbt_virtual = ioremap(addr, sizeof(*vbt)); + if (vbt_virtual == NULL) + return -1; + + memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt)); + iounmap(vbt_virtual); + + return 0; +} + +static int read_vbt_r10(u32 addr, struct vbt_r10 *vbt) +{ + void __iomem *vbt_virtual; + + vbt_virtual = ioremap(addr, sizeof(*vbt)); + if (!vbt_virtual) + return -1; + + memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt)); + iounmap(vbt_virtual); + + return 0; +} + +static int mid_get_vbt_data_r0(struct drm_psb_private *dev_priv, u32 addr) +{ + struct vbt_r0 vbt; + void __iomem *gct_virtual; + struct gct_r0 gct; + u8 bpi; + + if (read_vbt_r0(addr, &vbt)) + return -1; + + gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt)); + if (!gct_virtual) + return -1; + memcpy_fromio(&gct, gct_virtual, sizeof(gct)); + iounmap(gct_virtual); + + bpi = gct.PD.BootPanelIndex; + dev_priv->gct_data.bpi = bpi; + dev_priv->gct_data.pt = gct.PD.PanelType; + dev_priv->gct_data.DTD = gct.panel[bpi].DTD; + dev_priv->gct_data.Panel_Port_Control = + gct.panel[bpi].Panel_Port_Control; + dev_priv->gct_data.Panel_MIPI_Display_Descriptor = + gct.panel[bpi].Panel_MIPI_Display_Descriptor; + + return 0; +} + +static int mid_get_vbt_data_r1(struct drm_psb_private *dev_priv, u32 addr) +{ + struct vbt_r0 vbt; + void __iomem *gct_virtual; + struct gct_r1 gct; + u8 bpi; + + if (read_vbt_r0(addr, &vbt)) + return -1; + + gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt)); + if (!gct_virtual) + return -1; + memcpy_fromio(&gct, gct_virtual, sizeof(gct)); + iounmap(gct_virtual); + + bpi = gct.PD.BootPanelIndex; + dev_priv->gct_data.bpi = bpi; + dev_priv->gct_data.pt = gct.PD.PanelType; + dev_priv->gct_data.DTD = gct.panel[bpi].DTD; + dev_priv->gct_data.Panel_Port_Control = + gct.panel[bpi].Panel_Port_Control; + dev_priv->gct_data.Panel_MIPI_Display_Descriptor = + gct.panel[bpi].Panel_MIPI_Display_Descriptor; + + return 0; +} + +static int mid_get_vbt_data_r10(struct drm_psb_private *dev_priv, u32 addr) +{ + struct vbt_r10 vbt; + void __iomem *gct_virtual; + struct gct_r10 *gct; + struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; + struct gct_r10_timing_info *ti; + int ret = -1; + + if (read_vbt_r10(addr, &vbt)) + return -1; + + gct = kmalloc(sizeof(*gct) * vbt.panel_count, GFP_KERNEL); + if (!gct) + return -1; + + gct_virtual = ioremap(addr + sizeof(vbt), + sizeof(*gct) * vbt.panel_count); + if (!gct_virtual) + goto out; + memcpy_fromio(gct, gct_virtual, sizeof(*gct)); + iounmap(gct_virtual); + + dev_priv->gct_data.bpi = vbt.primary_panel_idx; + dev_priv->gct_data.Panel_MIPI_Display_Descriptor = + gct[vbt.primary_panel_idx].Panel_MIPI_Display_Descriptor; + + ti = &gct[vbt.primary_panel_idx].DTD; + dp_ti->pixel_clock = ti->pixel_clock; + dp_ti->hactive_hi = ti->hactive_hi; + dp_ti->hactive_lo = ti->hactive_lo; + dp_ti->hblank_hi = ti->hblank_hi; + dp_ti->hblank_lo = ti->hblank_lo; + dp_ti->hsync_offset_hi = ti->hsync_offset_hi; + dp_ti->hsync_offset_lo = ti->hsync_offset_lo; + dp_ti->hsync_pulse_width_hi = ti->hsync_pulse_width_hi; + dp_ti->hsync_pulse_width_lo = ti->hsync_pulse_width_lo; + dp_ti->vactive_hi = ti->vactive_hi; + dp_ti->vactive_lo = ti->vactive_lo; + dp_ti->vblank_hi = ti->vblank_hi; + dp_ti->vblank_lo = ti->vblank_lo; + dp_ti->vsync_offset_hi = ti->vsync_offset_hi; + dp_ti->vsync_offset_lo = ti->vsync_offset_lo; + dp_ti->vsync_pulse_width_hi = ti->vsync_pulse_width_hi; + dp_ti->vsync_pulse_width_lo = ti->vsync_pulse_width_lo; + + ret = 0; +out: + kfree(gct); + return ret; +} + static void mid_get_vbt_data(struct drm_psb_private *dev_priv) { struct drm_device *dev = dev_priv->dev; - struct oaktrail_vbt *vbt = &dev_priv->vbt_data; u32 addr; - u16 new_size; - u8 *vbt_virtual; - u8 bpi; - u8 number_desc = 0; - struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; - struct gct_r10_timing_info ti; - void *pGCT; + u8 __iomem *vbt_virtual; + struct vbt_header vbt_header; struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); + int ret = -1; - /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ + /* Get the address of the platform config vbt */ pci_read_config_dword(pci_gfx_root, 0xFC, &addr); pci_dev_put(pci_gfx_root); dev_dbg(dev->dev, "drm platform config address is %x\n", addr); - /* check for platform config address == 0. */ - /* this means fw doesn't support vbt */ - - if (addr == 0) { - vbt->size = 0; - return; - } + if (!addr) + goto out; /* get the virtual address of the vbt */ - vbt_virtual = ioremap(addr, sizeof(*vbt)); - if (vbt_virtual == NULL) { - vbt->size = 0; - return; - } + vbt_virtual = ioremap(addr, sizeof(vbt_header)); + if (!vbt_virtual) + goto out; - memcpy(vbt, vbt_virtual, sizeof(*vbt)); - iounmap(vbt_virtual); /* Free virtual address space */ + memcpy_fromio(&vbt_header, vbt_virtual, sizeof(vbt_header)); + iounmap(vbt_virtual); - /* No matching signature don't process the data */ - if (memcmp(vbt->signature, "$GCT", 4)) { - vbt->size = 0; - return; - } + if (memcmp(&vbt_header.signature, "$GCT", 4)) + goto out; + + dev_dbg(dev->dev, "GCT revision is %02x\n", vbt_header.revision); - dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); - - switch (vbt->revision) { - case 0: - vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, - vbt->size - sizeof(*vbt) + 4); - pGCT = vbt->oaktrail_gct; - bpi = ((struct oaktrail_gct_v1 *)pGCT)->PD.BootPanelIndex; - dev_priv->gct_data.bpi = bpi; - dev_priv->gct_data.pt = - ((struct oaktrail_gct_v1 *)pGCT)->PD.PanelType; - memcpy(&dev_priv->gct_data.DTD, - &((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].DTD, - sizeof(struct oaktrail_timing_info)); - dev_priv->gct_data.Panel_Port_Control = - ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; - dev_priv->gct_data.Panel_MIPI_Display_Descriptor = - ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; + switch (vbt_header.revision) { + case 0x00: + ret = mid_get_vbt_data_r0(dev_priv, addr); break; - case 1: - vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, - vbt->size - sizeof(*vbt) + 4); - pGCT = vbt->oaktrail_gct; - bpi = ((struct oaktrail_gct_v2 *)pGCT)->PD.BootPanelIndex; - dev_priv->gct_data.bpi = bpi; - dev_priv->gct_data.pt = - ((struct oaktrail_gct_v2 *)pGCT)->PD.PanelType; - memcpy(&dev_priv->gct_data.DTD, - &((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].DTD, - sizeof(struct oaktrail_timing_info)); - dev_priv->gct_data.Panel_Port_Control = - ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; - dev_priv->gct_data.Panel_MIPI_Display_Descriptor = - ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; + case 0x01: + ret = mid_get_vbt_data_r1(dev_priv, addr); break; case 0x10: - /*header definition changed from rev 01 (v2) to rev 10h. */ - /*so, some values have changed location*/ - new_size = vbt->checksum; /*checksum contains lo size byte*/ - /*LSB of oaktrail_gct contains hi size byte*/ - new_size |= ((0xff & (unsigned int)(long)vbt->oaktrail_gct)) << 8; - - vbt->checksum = vbt->size; /*size contains the checksum*/ - if (new_size > 0xff) - vbt->size = 0xff; /*restrict size to 255*/ - else - vbt->size = new_size; - - /* number of descriptors defined in the GCT */ - number_desc = ((0xff00 & (unsigned int)(long)vbt->oaktrail_gct)) >> 8; - bpi = ((0xff0000 & (unsigned int)(long)vbt->oaktrail_gct)) >> 16; - vbt->oaktrail_gct = ioremap(addr + GCT_R10_HEADER_SIZE, - GCT_R10_DISPLAY_DESC_SIZE * number_desc); - pGCT = vbt->oaktrail_gct; - pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); - dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ - - /*copy the GCT display timings into a temp structure*/ - memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); - - /*now copy the temp struct into the dev_priv->gct_data*/ - dp_ti->pixel_clock = ti.pixel_clock; - dp_ti->hactive_hi = ti.hactive_hi; - dp_ti->hactive_lo = ti.hactive_lo; - dp_ti->hblank_hi = ti.hblank_hi; - dp_ti->hblank_lo = ti.hblank_lo; - dp_ti->hsync_offset_hi = ti.hsync_offset_hi; - dp_ti->hsync_offset_lo = ti.hsync_offset_lo; - dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; - dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; - dp_ti->vactive_hi = ti.vactive_hi; - dp_ti->vactive_lo = ti.vactive_lo; - dp_ti->vblank_hi = ti.vblank_hi; - dp_ti->vblank_lo = ti.vblank_lo; - dp_ti->vsync_offset_hi = ti.vsync_offset_hi; - dp_ti->vsync_offset_lo = ti.vsync_offset_lo; - dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; - dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; - - /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ - dev_priv->gct_data.Panel_MIPI_Display_Descriptor = - *((u8 *)pGCT + 0x0d); - dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= - (*((u8 *)pGCT + 0x0e)) << 8; + ret = mid_get_vbt_data_r10(dev_priv, addr); break; default: dev_err(dev->dev, "Unknown revision of GCT!\n"); - vbt->size = 0; } + +out: + if (ret) + dev_err(dev->dev, "Unable to read GCT!"); + else + dev_priv->has_gct = true; } int mid_chip_setup(struct drm_device *dev) diff --git a/drivers/gpu/drm/gma500/oaktrail.h b/drivers/gpu/drm/gma500/oaktrail.h index 2da1f368f14..f2f9f38a536 100644 --- a/drivers/gpu/drm/gma500/oaktrail.h +++ b/drivers/gpu/drm/gma500/oaktrail.h @@ -19,14 +19,6 @@ /* MID device specific descriptors */ -struct oaktrail_vbt { - s8 signature[4]; /*4 bytes,"$GCT" */ - u8 revision; - u8 size; - u8 checksum; - void *oaktrail_gct; -} __packed; - struct oaktrail_timing_info { u16 pixel_clock; u8 hactive_lo; @@ -161,7 +153,7 @@ union oaktrail_panel_rx { u16 panel_receiver; } __packed; -struct oaktrail_gct_v1 { +struct gct_r0 { union { /*8 bits,Defined as follows: */ struct { u8 PanelType:4; /*4 bits, Bit field for panels*/ @@ -178,7 +170,7 @@ struct oaktrail_gct_v1 { union oaktrail_panel_rx panelrx[4]; /* panel receivers*/ } __packed; -struct oaktrail_gct_v2 { +struct gct_r1 { union { /*8 bits,Defined as follows: */ struct { u8 PanelType:4; /*4 bits, Bit field for panels*/ @@ -195,6 +187,16 @@ struct oaktrail_gct_v2 { union oaktrail_panel_rx panelrx[4]; /* panel receivers*/ } __packed; +struct gct_r10 { + struct gct_r10_timing_info DTD; + u16 Panel_MIPI_Display_Descriptor; + u16 Panel_MIPI_Receiver_Descriptor; + u16 Panel_Backlight_Inverter_Descriptor; + u8 Panel_Initial_Brightness; + u32 MIPI_Ctlr_Init_ptr; + u32 MIPI_Panel_Init_ptr; +} __packed; + struct oaktrail_gct_data { u8 bpi; /* boot panel index, number of panel used during boot */ u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */ @@ -213,9 +215,6 @@ struct oaktrail_gct_data { #define MODE_SETTING_IN_DSR 0x4 #define MODE_SETTING_ENCODER_DONE 0x8 -#define GCT_R10_HEADER_SIZE 16 -#define GCT_R10_DISPLAY_DESC_SIZE 28 - /* * Moorestown HDMI interfaces */ diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 4c5a1864adf..0bb74cc3ecf 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -458,27 +458,26 @@ static int oaktrail_power_up(struct drm_device *dev) static int oaktrail_chip_setup(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_vbt *vbt = &dev_priv->vbt_data; int ret; - + ret = mid_chip_setup(dev); if (ret < 0) return ret; - if (vbt->size == 0) { + if (!dev_priv->has_gct) { /* Now pull the BIOS data */ - gma_intel_opregion_init(dev); + psb_intel_opregion_init(dev); psb_intel_init_bios(dev); } + oaktrail_hdmi_setup(dev); return 0; } static void oaktrail_teardown(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; - struct oaktrail_vbt *vbt = &dev_priv->vbt_data; oaktrail_hdmi_teardown(dev); - if (vbt->size == 0) + if (!dev_priv->has_gct) psb_intel_destroy_bios(dev); } diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c index 5e84fbde749..88627e3ba1e 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c @@ -250,7 +250,7 @@ static irqreturn_t oaktrail_hdmi_i2c_handler(int this_irq, void *dev) */ static void oaktrail_hdmi_i2c_gpio_fix(void) { - void *base; + void __iomem *base; unsigned int gpio_base = 0xff12c000; int gpio_len = 0x1000; u32 temp; diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index 654f32b22b2..558c77fb55e 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -257,7 +257,7 @@ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev, mode_dev->panel_fixed_mode = NULL; /* Use the firmware provided data on Moorestown */ - if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/ + if (dev_priv->has_gct) { mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return; @@ -371,7 +371,7 @@ void oaktrail_lvds_init(struct drm_device *dev, BRIGHTNESS_MAX_LEVEL); mode_dev->panel_wants_dither = false; - if (dev_priv->vbt_data.size != 0x00) + if (dev_priv->has_gct) mode_dev->panel_wants_dither = (dev_priv->gct_data. Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE); if (dev_priv->lvds_dither) diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c new file mode 100644 index 00000000000..05661bfeac7 --- /dev/null +++ b/drivers/gpu/drm/gma500/opregion.c @@ -0,0 +1,350 @@ +/* + * Copyright 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#include <linux/acpi_io.h> +#endif +#include "psb_drv.h" +#include "psb_intel_reg.h" + +#define PCI_ASLE 0xe4 +#define PCI_ASLS 0xfc + +#define OPREGION_HEADER_OFFSET 0 +#define OPREGION_ACPI_OFFSET 0x100 +#define ACPI_CLID 0x01ac /* current lid state indicator */ +#define ACPI_CDCK 0x01b0 /* current docking state indicator */ +#define OPREGION_SWSCI_OFFSET 0x200 +#define OPREGION_ASLE_OFFSET 0x300 +#define OPREGION_VBT_OFFSET 0x400 + +#define OPREGION_SIGNATURE "IntelGraphicsMem" +#define MBOX_ACPI (1<<0) +#define MBOX_SWSCI (1<<1) +#define MBOX_ASLE (1<<2) + +struct opregion_header { + u8 signature[16]; + u32 size; + u32 opregion_ver; + u8 bios_ver[32]; + u8 vbios_ver[16]; + u8 driver_ver[16]; + u32 mboxes; + u8 reserved[164]; +} __packed; + +/* OpRegion mailbox #1: public ACPI methods */ +struct opregion_acpi { + u32 drdy; /* driver readiness */ + u32 csts; /* notification status */ + u32 cevt; /* current event */ + u8 rsvd1[20]; + u32 didl[8]; /* supported display devices ID list */ + u32 cpdl[8]; /* currently presented display list */ + u32 cadl[8]; /* currently active display list */ + u32 nadl[8]; /* next active devices list */ + u32 aslp; /* ASL sleep time-out */ + u32 tidx; /* toggle table index */ + u32 chpd; /* current hotplug enable indicator */ + u32 clid; /* current lid state*/ + u32 cdck; /* current docking state */ + u32 sxsw; /* Sx state resume */ + u32 evts; /* ASL supported events */ + u32 cnot; /* current OS notification */ + u32 nrdy; /* driver status */ + u8 rsvd2[60]; +} __packed; + +/* OpRegion mailbox #2: SWSCI */ +struct opregion_swsci { + /*FIXME: add it later*/ +} __packed; + +/* OpRegion mailbox #3: ASLE */ +struct opregion_asle { + u32 ardy; /* driver readiness */ + u32 aslc; /* ASLE interrupt command */ + u32 tche; /* technology enabled indicator */ + u32 alsi; /* current ALS illuminance reading */ + u32 bclp; /* backlight brightness to set */ + u32 pfit; /* panel fitting state */ + u32 cblv; /* current brightness level */ + u16 bclm[20]; /* backlight level duty cycle mapping table */ + u32 cpfm; /* current panel fitting mode */ + u32 epfm; /* enabled panel fitting modes */ + u8 plut[74]; /* panel LUT and identifier */ + u32 pfmb; /* PWM freq and min brightness */ + u8 rsvd[102]; +} __packed; + +/* ASLE irq request bits */ +#define ASLE_SET_ALS_ILLUM (1 << 0) +#define ASLE_SET_BACKLIGHT (1 << 1) +#define ASLE_SET_PFIT (1 << 2) +#define ASLE_SET_PWM_FREQ (1 << 3) +#define ASLE_REQ_MSK 0xf + +/* response bits of ASLE irq request */ +#define ASLE_ALS_ILLUM_FAILED (1<<10) +#define ASLE_BACKLIGHT_FAILED (1<<12) +#define ASLE_PFIT_FAILED (1<<14) +#define ASLE_PWM_FREQ_FAILED (1<<16) + +/* ASLE backlight brightness to set */ +#define ASLE_BCLP_VALID (1<<31) +#define ASLE_BCLP_MSK (~(1<<31)) + +/* ASLE panel fitting request */ +#define ASLE_PFIT_VALID (1<<31) +#define ASLE_PFIT_CENTER (1<<0) +#define ASLE_PFIT_STRETCH_TEXT (1<<1) +#define ASLE_PFIT_STRETCH_GFX (1<<2) + +/* response bits of ASLE irq request */ +#define ASLE_ALS_ILLUM_FAILED (1<<10) +#define ASLE_BACKLIGHT_FAILED (1<<12) +#define ASLE_PFIT_FAILED (1<<14) +#define ASLE_PWM_FREQ_FAILED (1<<16) + +/* ASLE backlight brightness to set */ +#define ASLE_BCLP_VALID (1<<31) +#define ASLE_BCLP_MSK (~(1<<31)) + +/* ASLE panel fitting request */ +#define ASLE_PFIT_VALID (1<<31) +#define ASLE_PFIT_CENTER (1<<0) +#define ASLE_PFIT_STRETCH_TEXT (1<<1) +#define ASLE_PFIT_STRETCH_GFX (1<<2) + +/* PWM frequency and minimum brightness */ +#define ASLE_PFMB_BRIGHTNESS_MASK (0xff) +#define ASLE_PFMB_BRIGHTNESS_VALID (1<<8) +#define ASLE_PFMB_PWM_MASK (0x7ffffe00) +#define ASLE_PFMB_PWM_VALID (1<<31) + +#define ASLE_CBLV_VALID (1<<31) + +static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct opregion_asle *asle = dev_priv->opregion.asle; + struct backlight_device *bd = dev_priv->backlight_device; + u32 max; + + DRM_DEBUG_DRIVER("asle set backlight %x\n", bclp); + + if (!(bclp & ASLE_BCLP_VALID)) + return ASLE_BACKLIGHT_FAILED; + + if (bd == NULL) + return ASLE_BACKLIGHT_FAILED; + + bclp &= ASLE_BCLP_MSK; + if (bclp > 255) + return ASLE_BACKLIGHT_FAILED; + +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE + max = bd->props.max_brightness; + bd->props.brightness = bclp * max / 255; + backlight_update_status(bd); +#endif + asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID; + + return 0; +} + +void psb_intel_opregion_asle_intr(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct opregion_asle *asle = dev_priv->opregion.asle; + u32 asle_stat = 0; + u32 asle_req; + + if (!asle) + return; + + asle_req = asle->aslc & ASLE_REQ_MSK; + if (!asle_req) { + DRM_DEBUG_DRIVER("non asle set request??\n"); + return; + } + + if (asle_req & ASLE_SET_BACKLIGHT) + asle_stat |= asle_set_backlight(dev, asle->bclp); + + asle->aslc = asle_stat; +} + +#define ASLE_ALS_EN (1<<0) +#define ASLE_BLC_EN (1<<1) +#define ASLE_PFIT_EN (1<<2) +#define ASLE_PFMB_EN (1<<3) + +void psb_intel_opregion_enable_asle(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct opregion_asle *asle = dev_priv->opregion.asle; + + if (asle) { + /* Don't do this on Medfield or other non PC like devices, they + use the bit for something different altogether */ + psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); + psb_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE); + + asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN + | ASLE_PFMB_EN; + asle->ardy = 1; + } +} + +#define ACPI_EV_DISPLAY_SWITCH (1<<0) +#define ACPI_EV_LID (1<<1) +#define ACPI_EV_DOCK (1<<2) + +static struct psb_intel_opregion *system_opregion; + +static int psb_intel_opregion_video_event(struct notifier_block *nb, + unsigned long val, void *data) +{ + /* The only video events relevant to opregion are 0x80. These indicate + either a docking event, lid switch or display switch request. In + Linux, these are handled by the dock, button and video drivers. + We might want to fix the video driver to be opregion-aware in + future, but right now we just indicate to the firmware that the + request has been handled */ + + struct opregion_acpi *acpi; + + if (!system_opregion) + return NOTIFY_DONE; + + acpi = system_opregion->acpi; + acpi->csts = 0; + + return NOTIFY_OK; +} + +static struct notifier_block psb_intel_opregion_notifier = { + .notifier_call = psb_intel_opregion_video_event, +}; + +void psb_intel_opregion_init(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct psb_intel_opregion *opregion = &dev_priv->opregion; + + if (!opregion->header) + return; + + if (opregion->acpi) { + /* Notify BIOS we are ready to handle ACPI video ext notifs. + * Right now, all the events are handled by the ACPI video + * module. We don't actually need to do anything with them. */ + opregion->acpi->csts = 0; + opregion->acpi->drdy = 1; + + system_opregion = opregion; + register_acpi_notifier(&psb_intel_opregion_notifier); + } + + if (opregion->asle) + psb_intel_opregion_enable_asle(dev); +} + +void psb_intel_opregion_fini(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct psb_intel_opregion *opregion = &dev_priv->opregion; + + if (!opregion->header) + return; + + if (opregion->acpi) { + opregion->acpi->drdy = 0; + + system_opregion = NULL; + unregister_acpi_notifier(&psb_intel_opregion_notifier); + } + + /* just clear all opregion memory pointers now */ + iounmap(opregion->header); + opregion->header = NULL; + opregion->acpi = NULL; + opregion->swsci = NULL; + opregion->asle = NULL; + opregion->vbt = NULL; +} + +int psb_intel_opregion_setup(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct psb_intel_opregion *opregion = &dev_priv->opregion; + u32 opregion_phy, mboxes; + void __iomem *base; + int err = 0; + + pci_read_config_dword(dev->pdev, PCI_ASLS, &opregion_phy); + if (opregion_phy == 0) { + DRM_DEBUG_DRIVER("ACPI Opregion not supported\n"); + return -ENOTSUPP; + } + DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy); +#ifdef CONFIG_ACPI + base = acpi_os_ioremap(opregion_phy, 8*1024); +#else + base = ioremap(opregion_phy, 8*1024); +#endif + if (!base) + return -ENOMEM; + + if (memcmp(base, OPREGION_SIGNATURE, 16)) { + DRM_DEBUG_DRIVER("opregion signature mismatch\n"); + err = -EINVAL; + goto err_out; + } + + opregion->header = base; + opregion->vbt = base + OPREGION_VBT_OFFSET; + + opregion->lid_state = base + ACPI_CLID; + + mboxes = opregion->header->mboxes; + if (mboxes & MBOX_ACPI) { + DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); + opregion->acpi = base + OPREGION_ACPI_OFFSET; + } + + if (mboxes & MBOX_ASLE) { + DRM_DEBUG_DRIVER("ASLE supported\n"); + opregion->asle = base + OPREGION_ASLE_OFFSET; + } + + return 0; + +err_out: + iounmap(base); + return err; +} + diff --git a/drivers/gpu/drm/gma500/opregion.h b/drivers/gpu/drm/gma500/opregion.h new file mode 100644 index 00000000000..a392ea8908b --- /dev/null +++ b/drivers/gpu/drm/gma500/opregion.h @@ -0,0 +1,29 @@ +/* + * Copyright 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +extern void psb_intel_opregion_asle_intr(struct drm_device *dev); +extern void psb_intel_opregion_enable_asle(struct drm_device *dev); +extern void psb_intel_opregion_init(struct drm_device *dev); +extern void psb_intel_opregion_fini(struct drm_device *dev); +extern int psb_intel_opregion_setup(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 34e6866a73b..e95cddbceb6 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -293,7 +293,7 @@ static int psb_chip_setup(struct drm_device *dev) { psb_get_core_freq(dev); gma_intel_setup_gmbus(dev); - gma_intel_opregion_init(dev); + psb_intel_opregion_init(dev); psb_intel_init_bios(dev); return 0; } diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index d5a6eab8227..0e85978877e 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -215,12 +215,11 @@ static int psb_driver_unload(struct drm_device *dev) /* Kill vblank etc here */ gma_backlight_exit(dev); - psb_modeset_cleanup(dev); if (dev_priv) { + psb_intel_opregion_fini(dev); psb_lid_timer_takedown(dev_priv); - gma_intel_opregion_exit(dev); if (dev_priv->ops->chip_teardown) dev_priv->ops->chip_teardown(dev); @@ -310,6 +309,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) if (!dev_priv->sgx_reg) goto out_err; + psb_intel_opregion_setup(dev); + ret = dev_priv->ops->chip_setup(dev); if (ret) goto out_err; @@ -349,9 +350,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); -/* igd_opregion_init(&dev_priv->opregion_dev); */ acpi_video_register(); - if (dev_priv->lid_state) + if (dev_priv->opregion.lid_state) psb_lid_timer_init(dev_priv); ret = drm_vblank_init(dev, dev_priv->num_pipe); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index d3528a69420..270a27bc936 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -30,6 +30,7 @@ #include "psb_intel_drv.h" #include "gtt.h" #include "power.h" +#include "opregion.h" #include "oaktrail.h" /* Append new drm mode definition here, align with libdrm definition */ @@ -120,6 +121,7 @@ enum { #define PSB_HWSTAM 0x2098 #define PSB_INSTPM 0x20C0 #define PSB_INT_IDENTITY_R 0x20A4 +#define _PSB_IRQ_ASLE (1<<0) #define _MDFLD_PIPEC_EVENT_FLAG (1<<2) #define _MDFLD_PIPEC_VBLANK_FLAG (1<<3) #define _PSB_DPST_PIPEB_FLAG (1<<4) @@ -259,7 +261,7 @@ struct psb_intel_opregion { struct opregion_swsci *swsci; struct opregion_asle *asle; void *vbt; - int enabled; + u32 __iomem *lid_state; }; struct sdvo_device_mapping { @@ -505,9 +507,9 @@ struct drm_psb_private { /* GTT Memory manager */ struct psb_gtt_mm *gtt_mm; struct page *scratch_page; - u32 *gtt_map; + u32 __iomem *gtt_map; uint32_t stolen_base; - void *vram_addr; + u8 __iomem *vram_addr; unsigned long vram_stolen_size; int gtt_initialized; u16 gmch_ctrl; /* Saved GTT setup */ @@ -523,8 +525,8 @@ struct drm_psb_private { * Register base */ - uint8_t *sgx_reg; - uint8_t *vdc_reg; + uint8_t __iomem *sgx_reg; + uint8_t __iomem *vdc_reg; uint32_t gatt_free_offset; /* @@ -610,7 +612,7 @@ struct drm_psb_private { int rpm_enabled; /* MID specific */ - struct oaktrail_vbt vbt_data; + bool has_gct; struct oaktrail_gct_data gct_data; /* Oaktrail HDMI state */ @@ -638,7 +640,6 @@ struct drm_psb_private { spinlock_t lid_lock; struct timer_list lid_timer; struct psb_intel_opregion opregion; - u32 *lid_state; u32 lid_last_state; /* diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h index 519a9cd9ffb..8e8c8efb0a8 100644 --- a/drivers/gpu/drm/gma500/psb_intel_reg.h +++ b/drivers/gpu/drm/gma500/psb_intel_reg.h @@ -507,6 +507,7 @@ #define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17) #define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18) #define PIPE_TE_ENABLE (1UL << 22) +#define PIPE_LEGACY_BLC_EVENT_ENABLE (1UL << 22) #define PIPE_DPST_EVENT_ENABLE (1UL << 23) #define PIPE_VSYNC_ENABL (1UL << 25) #define PIPE_HDMI_AUDIO_UNDERRUN (1UL << 26) diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 2fcdffdc906..8652cdf3f03 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -190,6 +190,9 @@ static void mid_pipe_event_handler(struct drm_device *dev, int pipe) */ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) { + if (vdc_stat & _PSB_IRQ_ASLE) + psb_intel_opregion_asle_intr(dev); + if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) mid_pipe_event_handler(dev, 0); @@ -283,6 +286,7 @@ void psb_irq_preinstall(struct drm_device *dev) /* Revisit this area - want per device masks ? */ if (dev_priv->ops->hotplug) dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; + dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE; /* This register is safe even if display island is off */ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); @@ -422,7 +426,7 @@ void psb_irq_turn_off_dpst(struct drm_device *dev) psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), + PSB_WVDC32(pwm_reg & ~PWM_PHASEIN_INT_ENABLE, PWM_CONTROL_LOGIC); pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c index b867aabe6bf..7ff8bb2bdc2 100644 --- a/drivers/gpu/drm/gma500/psb_lid.c +++ b/drivers/gpu/drm/gma500/psb_lid.c @@ -29,7 +29,7 @@ static void psb_lid_timer_func(unsigned long data) struct drm_device *dev = (struct drm_device *)dev_priv->dev; struct timer_list *lid_timer = &dev_priv->lid_timer; unsigned long irq_flags; - u32 *lid_state = dev_priv->lid_state; + u32 __iomem *lid_state = dev_priv->opregion.lid_state; u32 pp_status; if (readl(lid_state) == dev_priv->lid_last_state) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index eed7acefb49..ecc29bc1cbe 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2424,27 +2424,18 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin u32 srbm_status; u32 grbm_status; u32 grbm_status_se0, grbm_status_se1; - struct r100_gpu_lockup *lockup = &rdev->config.evergreen.lockup; - int r; srbm_status = RREG32(SRBM_STATUS); grbm_status = RREG32(GRBM_STATUS); grbm_status_se0 = RREG32(GRBM_STATUS_SE0); grbm_status_se1 = RREG32(GRBM_STATUS_SE1); if (!(grbm_status & GUI_ACTIVE)) { - r100_gpu_lockup_update(lockup, ring); + radeon_ring_lockup_update(ring); return false; } /* force CP activities */ - r = radeon_ring_lock(rdev, ring, 2); - if (!r) { - /* PACKET2 NOP */ - radeon_ring_write(ring, 0x80000000); - radeon_ring_write(ring, 0x80000000); - radeon_ring_unlock_commit(rdev, ring); - } - ring->rptr = RREG32(CP_RB_RPTR); - return r100_gpu_cp_is_lockup(rdev, lockup, ring); + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); } static int evergreen_gpu_soft_reset(struct radeon_device *rdev) @@ -3376,12 +3367,9 @@ static int evergreen_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - DRM_ERROR("radeon: failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } r = r600_audio_init(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index a48ca53fcd6..9cd2657eb2c 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1392,35 +1392,6 @@ int cayman_cp_resume(struct radeon_device *rdev) return 0; } -bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) -{ - u32 srbm_status; - u32 grbm_status; - u32 grbm_status_se0, grbm_status_se1; - struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup; - int r; - - srbm_status = RREG32(SRBM_STATUS); - grbm_status = RREG32(GRBM_STATUS); - grbm_status_se0 = RREG32(GRBM_STATUS_SE0); - grbm_status_se1 = RREG32(GRBM_STATUS_SE1); - if (!(grbm_status & GUI_ACTIVE)) { - r100_gpu_lockup_update(lockup, ring); - return false; - } - /* force CP activities */ - r = radeon_ring_lock(rdev, ring, 2); - if (!r) { - /* PACKET2 NOP */ - radeon_ring_write(ring, 0x80000000); - radeon_ring_write(ring, 0x80000000); - radeon_ring_unlock_commit(rdev, ring); - } - /* XXX deal with CP0,1,2 */ - ring->rptr = RREG32(ring->rptr_reg); - return r100_gpu_cp_is_lockup(rdev, lockup, ring); -} - static int cayman_gpu_soft_reset(struct radeon_device *rdev) { struct evergreen_mc_save save; @@ -1601,12 +1572,9 @@ static int cayman_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - DRM_ERROR("radeon: failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } r = radeon_vm_manager_start(rdev); if (r) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index cb114185428..ad6ceb73171 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -660,7 +660,7 @@ int r100_pci_gart_enable(struct radeon_device *rdev) tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; WREG32(RADEON_AIC_CNTL, tmp); r100_pci_gart_tlb_flush(rdev); - DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", + DRM_INFO("PCI GART of %uM enabled (table at 0x%016llX).\n", (unsigned)(rdev->mc.gtt_size >> 20), (unsigned long long)rdev->gart.table_addr); rdev->gart.ready = true; @@ -2159,79 +2159,18 @@ int r100_mc_wait_for_idle(struct radeon_device *rdev) return -1; } -void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, struct radeon_ring *ring) -{ - lockup->last_cp_rptr = ring->rptr; - lockup->last_jiffies = jiffies; -} - -/** - * r100_gpu_cp_is_lockup() - check if CP is lockup by recording information - * @rdev: radeon device structure - * @lockup: r100_gpu_lockup structure holding CP lockup tracking informations - * @cp: radeon_cp structure holding CP information - * - * We don't need to initialize the lockup tracking information as we will either - * have CP rptr to a different value of jiffies wrap around which will force - * initialization of the lockup tracking informations. - * - * A possible false positivie is if we get call after while and last_cp_rptr == - * the current CP rptr, even if it's unlikely it might happen. To avoid this - * if the elapsed time since last call is bigger than 2 second than we return - * false and update the tracking information. Due to this the caller must call - * r100_gpu_cp_is_lockup several time in less than 2sec for lockup to be reported - * the fencing code should be cautious about that. - * - * Caller should write to the ring to force CP to do something so we don't get - * false positive when CP is just gived nothing to do. - * - **/ -bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *lockup, struct radeon_ring *ring) -{ - unsigned long cjiffies, elapsed; - - cjiffies = jiffies; - if (!time_after(cjiffies, lockup->last_jiffies)) { - /* likely a wrap around */ - lockup->last_cp_rptr = ring->rptr; - lockup->last_jiffies = jiffies; - return false; - } - if (ring->rptr != lockup->last_cp_rptr) { - /* CP is still working no lockup */ - lockup->last_cp_rptr = ring->rptr; - lockup->last_jiffies = jiffies; - return false; - } - elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); - if (elapsed >= 10000) { - dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); - return true; - } - /* give a chance to the GPU ... */ - return false; -} - bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) { u32 rbbm_status; - int r; rbbm_status = RREG32(R_000E40_RBBM_STATUS); if (!G_000E40_GUI_ACTIVE(rbbm_status)) { - r100_gpu_lockup_update(&rdev->config.r100.lockup, ring); + radeon_ring_lockup_update(ring); return false; } /* force CP activities */ - r = radeon_ring_lock(rdev, ring, 2); - if (!r) { - /* PACKET2 NOP */ - radeon_ring_write(ring, 0x80000000); - radeon_ring_write(ring, 0x80000000); - radeon_ring_unlock_commit(rdev, ring); - } - ring->rptr = RREG32(ring->rptr_reg); - return r100_gpu_cp_is_lockup(rdev, &rdev->config.r100.lockup, ring); + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); } void r100_bm_disable(struct radeon_device *rdev) @@ -2300,7 +2239,6 @@ int r100_asic_reset(struct radeon_device *rdev) if (G_000E40_SE_BUSY(status) || G_000E40_RE_BUSY(status) || G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) { dev_err(rdev->dev, "failed to reset GPU\n"); - rdev->gpu_lockup = true; ret = -1; } else dev_info(rdev->dev, "GPU reset succeed\n"); @@ -3969,12 +3907,9 @@ static int r100_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index fa14383f9ca..6419a5900e6 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -377,28 +377,6 @@ void r300_gpu_init(struct radeon_device *rdev) rdev->num_gb_pipes, rdev->num_z_pipes); } -bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) -{ - u32 rbbm_status; - int r; - - rbbm_status = RREG32(R_000E40_RBBM_STATUS); - if (!G_000E40_GUI_ACTIVE(rbbm_status)) { - r100_gpu_lockup_update(&rdev->config.r300.lockup, ring); - return false; - } - /* force CP activities */ - r = radeon_ring_lock(rdev, ring, 2); - if (!r) { - /* PACKET2 NOP */ - radeon_ring_write(ring, 0x80000000); - radeon_ring_write(ring, 0x80000000); - radeon_ring_unlock_commit(rdev, ring); - } - ring->rptr = RREG32(RADEON_CP_RB_RPTR); - return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, ring); -} - int r300_asic_reset(struct radeon_device *rdev) { struct r100_mc_save save; @@ -449,7 +427,6 @@ int r300_asic_reset(struct radeon_device *rdev) /* Check if GPU is idle */ if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { dev_err(rdev->dev, "failed to reset GPU\n"); - rdev->gpu_lockup = true; ret = -1; } else dev_info(rdev->dev, "GPU reset succeed\n"); @@ -1418,12 +1395,9 @@ static int r300_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index f3fcaacfea0..99137be7a30 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -279,12 +279,9 @@ static int r420_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index ebcc15b03c9..b5cf8375cd2 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -207,12 +207,10 @@ static int r520_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } + return 0; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index c37b727fda7..d02f13fdaa6 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1350,31 +1350,17 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) u32 srbm_status; u32 grbm_status; u32 grbm_status2; - struct r100_gpu_lockup *lockup; - int r; - - if (rdev->family >= CHIP_RV770) - lockup = &rdev->config.rv770.lockup; - else - lockup = &rdev->config.r600.lockup; srbm_status = RREG32(R_000E50_SRBM_STATUS); grbm_status = RREG32(R_008010_GRBM_STATUS); grbm_status2 = RREG32(R_008014_GRBM_STATUS2); if (!G_008010_GUI_ACTIVE(grbm_status)) { - r100_gpu_lockup_update(lockup, ring); + radeon_ring_lockup_update(ring); return false; } /* force CP activities */ - r = radeon_ring_lock(rdev, ring, 2); - if (!r) { - /* PACKET2 NOP */ - radeon_ring_write(ring, 0x80000000); - radeon_ring_write(ring, 0x80000000); - radeon_ring_unlock_commit(rdev, ring); - } - ring->rptr = RREG32(ring->rptr_reg); - return r100_gpu_cp_is_lockup(rdev, lockup, ring); + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); } int r600_asic_reset(struct radeon_device *rdev) @@ -2494,12 +2480,9 @@ int r600_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - DRM_ERROR("radeon: failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 610acee74a3..82ffa6a05cc 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -94,6 +94,7 @@ extern int radeon_disp_priority; extern int radeon_hw_i2c; extern int radeon_pcie_gen2; extern int radeon_msi; +extern int radeon_lockup_timeout; /* * Copy from radeon_drv.h so we don't have to include both and have conflicting @@ -255,10 +256,8 @@ struct radeon_fence_driver { volatile uint32_t *cpu_addr; atomic_t seq; uint32_t last_seq; - unsigned long last_jiffies; - unsigned long last_timeout; + unsigned long last_activity; wait_queue_head_t queue; - struct list_head created; struct list_head emitted; struct list_head signaled; bool initialized; @@ -286,7 +285,7 @@ void radeon_fence_process(struct radeon_device *rdev, int ring); bool radeon_fence_signaled(struct radeon_fence *fence); int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); int radeon_fence_wait_next(struct radeon_device *rdev, int ring); -int radeon_fence_wait_last(struct radeon_device *rdev, int ring); +int radeon_fence_wait_empty(struct radeon_device *rdev, int ring); struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); void radeon_fence_unref(struct radeon_fence **fence); int radeon_fence_count_emitted(struct radeon_device *rdev, int ring); @@ -462,6 +461,10 @@ void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, struct radeon_semaphore *semaphore); void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, struct radeon_semaphore *semaphore); +int radeon_semaphore_sync_rings(struct radeon_device *rdev, + struct radeon_semaphore *semaphore, + bool sync_to[RADEON_NUM_RINGS], + int dst_ring); void radeon_semaphore_free(struct radeon_device *rdev, struct radeon_semaphore *semaphore); @@ -668,6 +671,8 @@ struct radeon_ring { unsigned ring_size; unsigned ring_free_dw; int count_dw; + unsigned long last_activity; + unsigned last_rptr; uint64_t gpu_addr; uint32_t align_mask; uint32_t ptr_mask; @@ -802,6 +807,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev); void radeon_ib_pool_fini(struct radeon_device *rdev); int radeon_ib_pool_start(struct radeon_device *rdev); int radeon_ib_pool_suspend(struct radeon_device *rdev); +int radeon_ib_ring_tests(struct radeon_device *rdev); /* Ring access between begin & end cannot sleep */ int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *cp); void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); @@ -811,6 +817,9 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *cp); void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *cp); void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp); int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); +void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); +void radeon_ring_lockup_update(struct radeon_ring *ring); +bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); @@ -1162,7 +1171,6 @@ struct radeon_asic { int (*resume)(struct radeon_device *rdev); int (*suspend)(struct radeon_device *rdev); void (*vga_set_state)(struct radeon_device *rdev, bool state); - bool (*gpu_is_lockup)(struct radeon_device *rdev, struct radeon_ring *cp); int (*asic_reset)(struct radeon_device *rdev); /* ioctl hw specific callback. Some hw might want to perform special * operation on specific ioctl. For instance on wait idle some hw @@ -1191,6 +1199,7 @@ struct radeon_asic { void (*ring_start)(struct radeon_device *rdev, struct radeon_ring *cp); int (*ring_test)(struct radeon_device *rdev, struct radeon_ring *cp); int (*ib_test)(struct radeon_device *rdev, struct radeon_ring *cp); + bool (*is_lockup)(struct radeon_device *rdev, struct radeon_ring *cp); } ring[RADEON_NUM_RINGS]; /* irqs */ struct { @@ -1269,16 +1278,10 @@ struct radeon_asic { /* * Asic structures */ -struct r100_gpu_lockup { - unsigned long last_jiffies; - u32 last_cp_rptr; -}; - struct r100_asic { const unsigned *reg_safe_bm; unsigned reg_safe_bm_size; u32 hdp_cntl; - struct r100_gpu_lockup lockup; }; struct r300_asic { @@ -1286,7 +1289,6 @@ struct r300_asic { unsigned reg_safe_bm_size; u32 resync_scratch; u32 hdp_cntl; - struct r100_gpu_lockup lockup; }; struct r600_asic { @@ -1308,7 +1310,6 @@ struct r600_asic { unsigned tiling_group_size; unsigned tile_config; unsigned backend_map; - struct r100_gpu_lockup lockup; }; struct rv770_asic { @@ -1334,7 +1335,6 @@ struct rv770_asic { unsigned tiling_group_size; unsigned tile_config; unsigned backend_map; - struct r100_gpu_lockup lockup; }; struct evergreen_asic { @@ -1361,7 +1361,6 @@ struct evergreen_asic { unsigned tiling_group_size; unsigned tile_config; unsigned backend_map; - struct r100_gpu_lockup lockup; }; struct cayman_asic { @@ -1400,7 +1399,6 @@ struct cayman_asic { unsigned multi_gpu_tile_size; unsigned tile_config; - struct r100_gpu_lockup lockup; }; struct si_asic { @@ -1431,7 +1429,6 @@ struct si_asic { unsigned multi_gpu_tile_size; unsigned tile_config; - struct r100_gpu_lockup lockup; }; union radeon_asic_config { @@ -1547,7 +1544,6 @@ struct radeon_device { struct radeon_mutex cs_mutex; struct radeon_wb wb; struct radeon_dummy_page dummy_page; - bool gpu_lockup; bool shutdown; bool suspend; bool need_dma32; @@ -1740,7 +1736,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev)) #define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)].cs_parse((p)) #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state)) -#define radeon_gpu_is_lockup(rdev, cp) (rdev)->asic->gpu_is_lockup((rdev), (cp)) #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev)) #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev)) #define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart.set_page((rdev), (i), (p)) @@ -1749,6 +1744,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_ib_test(rdev, r, cp) (rdev)->asic->ring[(r)].ib_test((rdev), (cp)) #define radeon_ring_ib_execute(rdev, r, ib) (rdev)->asic->ring[(r)].ib_execute((rdev), (ib)) #define radeon_ring_ib_parse(rdev, r, ib) (rdev)->asic->ring[(r)].ib_parse((rdev), (ib)) +#define radeon_ring_is_lockup(rdev, r, cp) (rdev)->asic->ring[(r)].is_lockup((rdev), (cp)) #define radeon_irq_set(rdev) (rdev)->asic->irq.set((rdev)) #define radeon_irq_process(rdev) (rdev)->asic->irq.process((rdev)) #define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->display.get_vblank_counter((rdev), (crtc)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index be4dc2ff0e4..f533df5f7d5 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -134,7 +134,6 @@ static struct radeon_asic r100_asic = { .suspend = &r100_suspend, .resume = &r100_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r100_gpu_is_lockup, .asic_reset = &r100_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -152,6 +151,7 @@ static struct radeon_asic r100_asic = { .ring_start = &r100_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -208,7 +208,6 @@ static struct radeon_asic r200_asic = { .suspend = &r100_suspend, .resume = &r100_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r100_gpu_is_lockup, .asic_reset = &r100_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -226,6 +225,7 @@ static struct radeon_asic r200_asic = { .ring_start = &r100_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -282,7 +282,6 @@ static struct radeon_asic r300_asic = { .suspend = &r300_suspend, .resume = &r300_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &r300_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -300,6 +299,7 @@ static struct radeon_asic r300_asic = { .ring_start = &r300_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -356,7 +356,6 @@ static struct radeon_asic r300_asic_pcie = { .suspend = &r300_suspend, .resume = &r300_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &r300_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -374,6 +373,7 @@ static struct radeon_asic r300_asic_pcie = { .ring_start = &r300_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -430,7 +430,6 @@ static struct radeon_asic r420_asic = { .suspend = &r420_suspend, .resume = &r420_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &r300_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -448,6 +447,7 @@ static struct radeon_asic r420_asic = { .ring_start = &r300_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -504,7 +504,6 @@ static struct radeon_asic rs400_asic = { .suspend = &rs400_suspend, .resume = &rs400_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &r300_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -522,6 +521,7 @@ static struct radeon_asic rs400_asic = { .ring_start = &r300_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -578,7 +578,6 @@ static struct radeon_asic rs600_asic = { .suspend = &rs600_suspend, .resume = &rs600_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &rs600_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -596,6 +595,7 @@ static struct radeon_asic rs600_asic = { .ring_start = &r300_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -652,7 +652,6 @@ static struct radeon_asic rs690_asic = { .suspend = &rs690_suspend, .resume = &rs690_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &rs600_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -670,6 +669,7 @@ static struct radeon_asic rs690_asic = { .ring_start = &r300_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -726,7 +726,6 @@ static struct radeon_asic rv515_asic = { .suspend = &rv515_suspend, .resume = &rv515_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &rs600_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -744,6 +743,7 @@ static struct radeon_asic rv515_asic = { .ring_start = &rv515_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -800,7 +800,6 @@ static struct radeon_asic r520_asic = { .suspend = &rv515_suspend, .resume = &r520_resume, .vga_set_state = &r100_vga_set_state, - .gpu_is_lockup = &r300_gpu_is_lockup, .asic_reset = &rs600_asic_reset, .ioctl_wait_idle = NULL, .gui_idle = &r100_gui_idle, @@ -818,6 +817,7 @@ static struct radeon_asic r520_asic = { .ring_start = &rv515_ring_start, .ring_test = &r100_ring_test, .ib_test = &r100_ib_test, + .is_lockup = &r100_gpu_is_lockup, } }, .irq = { @@ -874,7 +874,6 @@ static struct radeon_asic r600_asic = { .suspend = &r600_suspend, .resume = &r600_resume, .vga_set_state = &r600_vga_set_state, - .gpu_is_lockup = &r600_gpu_is_lockup, .asic_reset = &r600_asic_reset, .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, @@ -891,6 +890,7 @@ static struct radeon_asic r600_asic = { .cs_parse = &r600_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &r600_gpu_is_lockup, } }, .irq = { @@ -946,7 +946,6 @@ static struct radeon_asic rs780_asic = { .fini = &r600_fini, .suspend = &r600_suspend, .resume = &r600_resume, - .gpu_is_lockup = &r600_gpu_is_lockup, .vga_set_state = &r600_vga_set_state, .asic_reset = &r600_asic_reset, .ioctl_wait_idle = r600_ioctl_wait_idle, @@ -964,6 +963,7 @@ static struct radeon_asic rs780_asic = { .cs_parse = &r600_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &r600_gpu_is_lockup, } }, .irq = { @@ -1020,7 +1020,6 @@ static struct radeon_asic rv770_asic = { .suspend = &rv770_suspend, .resume = &rv770_resume, .asic_reset = &r600_asic_reset, - .gpu_is_lockup = &r600_gpu_is_lockup, .vga_set_state = &r600_vga_set_state, .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, @@ -1037,6 +1036,7 @@ static struct radeon_asic rv770_asic = { .cs_parse = &r600_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &r600_gpu_is_lockup, } }, .irq = { @@ -1092,7 +1092,6 @@ static struct radeon_asic evergreen_asic = { .fini = &evergreen_fini, .suspend = &evergreen_suspend, .resume = &evergreen_resume, - .gpu_is_lockup = &evergreen_gpu_is_lockup, .asic_reset = &evergreen_asic_reset, .vga_set_state = &r600_vga_set_state, .ioctl_wait_idle = r600_ioctl_wait_idle, @@ -1110,6 +1109,7 @@ static struct radeon_asic evergreen_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, } }, .irq = { @@ -1165,7 +1165,6 @@ static struct radeon_asic sumo_asic = { .fini = &evergreen_fini, .suspend = &evergreen_suspend, .resume = &evergreen_resume, - .gpu_is_lockup = &evergreen_gpu_is_lockup, .asic_reset = &evergreen_asic_reset, .vga_set_state = &r600_vga_set_state, .ioctl_wait_idle = r600_ioctl_wait_idle, @@ -1183,6 +1182,7 @@ static struct radeon_asic sumo_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, }, }, .irq = { @@ -1238,7 +1238,6 @@ static struct radeon_asic btc_asic = { .fini = &evergreen_fini, .suspend = &evergreen_suspend, .resume = &evergreen_resume, - .gpu_is_lockup = &evergreen_gpu_is_lockup, .asic_reset = &evergreen_asic_reset, .vga_set_state = &r600_vga_set_state, .ioctl_wait_idle = r600_ioctl_wait_idle, @@ -1256,6 +1255,7 @@ static struct radeon_asic btc_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, } }, .irq = { @@ -1321,7 +1321,6 @@ static struct radeon_asic cayman_asic = { .fini = &cayman_fini, .suspend = &cayman_suspend, .resume = &cayman_resume, - .gpu_is_lockup = &cayman_gpu_is_lockup, .asic_reset = &cayman_asic_reset, .vga_set_state = &r600_vga_set_state, .ioctl_wait_idle = r600_ioctl_wait_idle, @@ -1340,6 +1339,7 @@ static struct radeon_asic cayman_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, }, [CAYMAN_RING_TYPE_CP1_INDEX] = { .ib_execute = &cayman_ring_ib_execute, @@ -1349,6 +1349,7 @@ static struct radeon_asic cayman_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, }, [CAYMAN_RING_TYPE_CP2_INDEX] = { .ib_execute = &cayman_ring_ib_execute, @@ -1358,6 +1359,7 @@ static struct radeon_asic cayman_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, } }, .irq = { @@ -1413,7 +1415,6 @@ static struct radeon_asic trinity_asic = { .fini = &cayman_fini, .suspend = &cayman_suspend, .resume = &cayman_resume, - .gpu_is_lockup = &cayman_gpu_is_lockup, .asic_reset = &cayman_asic_reset, .vga_set_state = &r600_vga_set_state, .ioctl_wait_idle = r600_ioctl_wait_idle, @@ -1432,6 +1433,7 @@ static struct radeon_asic trinity_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, }, [CAYMAN_RING_TYPE_CP1_INDEX] = { .ib_execute = &cayman_ring_ib_execute, @@ -1441,6 +1443,7 @@ static struct radeon_asic trinity_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, }, [CAYMAN_RING_TYPE_CP2_INDEX] = { .ib_execute = &cayman_ring_ib_execute, @@ -1450,6 +1453,7 @@ static struct radeon_asic trinity_asic = { .cs_parse = &evergreen_cs_parse, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &evergreen_gpu_is_lockup, } }, .irq = { @@ -1515,7 +1519,6 @@ static struct radeon_asic si_asic = { .fini = &si_fini, .suspend = &si_suspend, .resume = &si_resume, - .gpu_is_lockup = &si_gpu_is_lockup, .asic_reset = &si_asic_reset, .vga_set_state = &r600_vga_set_state, .ioctl_wait_idle = r600_ioctl_wait_idle, @@ -1534,6 +1537,7 @@ static struct radeon_asic si_asic = { .cs_parse = NULL, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &si_gpu_is_lockup, }, [CAYMAN_RING_TYPE_CP1_INDEX] = { .ib_execute = &si_ring_ib_execute, @@ -1543,6 +1547,7 @@ static struct radeon_asic si_asic = { .cs_parse = NULL, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &si_gpu_is_lockup, }, [CAYMAN_RING_TYPE_CP2_INDEX] = { .ib_execute = &si_ring_ib_execute, @@ -1552,6 +1557,7 @@ static struct radeon_asic si_asic = { .cs_parse = NULL, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, + .is_lockup = &si_gpu_is_lockup, } }, .irq = { diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index b135bec649d..78309318bd3 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -103,11 +103,6 @@ int r100_pci_gart_enable(struct radeon_device *rdev); void r100_pci_gart_disable(struct radeon_device *rdev); int r100_debugfs_mc_info_init(struct radeon_device *rdev); int r100_gui_wait_for_idle(struct radeon_device *rdev); -void r100_gpu_lockup_update(struct r100_gpu_lockup *lockup, - struct radeon_ring *cp); -bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, - struct r100_gpu_lockup *lockup, - struct radeon_ring *cp); void r100_ib_fini(struct radeon_device *rdev); int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); void r100_irq_disable(struct radeon_device *rdev); @@ -159,7 +154,6 @@ extern int r300_init(struct radeon_device *rdev); extern void r300_fini(struct radeon_device *rdev); extern int r300_suspend(struct radeon_device *rdev); extern int r300_resume(struct radeon_device *rdev); -extern bool r300_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); extern int r300_asic_reset(struct radeon_device *rdev); extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); extern void r300_fence_ring_emit(struct radeon_device *rdev, @@ -443,7 +437,6 @@ int cayman_init(struct radeon_device *rdev); void cayman_fini(struct radeon_device *rdev); int cayman_suspend(struct radeon_device *rdev); int cayman_resume(struct radeon_device *rdev); -bool cayman_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); int cayman_asic_reset(struct radeon_device *rdev); void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); int cayman_vm_init(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 2cad9fde92f..576f4f6919f 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -1561,6 +1561,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) (rdev->pdev->subsystem_device == 0x4150)) { /* Mac G5 tower 9600 */ rdev->mode_info.connector_table = CT_MAC_G5_9600; + } else if ((rdev->pdev->device == 0x4c66) && + (rdev->pdev->subsystem_vendor == 0x1002) && + (rdev->pdev->subsystem_device == 0x4c66)) { + /* SAM440ep RV250 embedded board */ + rdev->mode_info.connector_table = CT_SAM440EP; } else #endif /* CONFIG_PPC_PMAC */ #ifdef CONFIG_PPC64 @@ -2134,6 +2139,67 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_SVIDEO, &hpd); break; + case CT_SAM440EP: + DRM_INFO("Connector Table: %d (SAM440ep embedded board)\n", + rdev->mode_info.connector_table); + /* LVDS */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_LCD1_SUPPORT, + 0), + ATOM_DEVICE_LCD1_SUPPORT); + radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, + DRM_MODE_CONNECTOR_LVDS, &ddc_i2c, + CONNECTOR_OBJECT_ID_LVDS, + &hpd); + /* DVI-I - secondary dac, int tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* VGA - primary dac */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 2, + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_VGA, &ddc_i2c, + CONNECTOR_OBJECT_ID_VGA, + &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 3, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; default: DRM_INFO("Connector table: %d (invalid)\n", rdev->mode_info.connector_table); diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index e7b0b5d51bc..c66beb1662b 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -118,6 +118,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority static int radeon_cs_sync_rings(struct radeon_cs_parser *p) { bool sync_to_ring[RADEON_NUM_RINGS] = { }; + bool need_sync = false; int i, r; for (i = 0; i < p->nrelocs; i++) { @@ -126,36 +127,24 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) if (!(p->relocs[i].flags & RADEON_RELOC_DONT_SYNC)) { struct radeon_fence *fence = p->relocs[i].robj->tbo.sync_obj; - if (!radeon_fence_signaled(fence)) { + if (fence->ring != p->ring && !radeon_fence_signaled(fence)) { sync_to_ring[fence->ring] = true; + need_sync = true; } } } - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - /* no need to sync to our own or unused rings */ - if (i == p->ring || !sync_to_ring[i] || !p->rdev->ring[i].ready) - continue; - - if (!p->ib->fence->semaphore) { - r = radeon_semaphore_create(p->rdev, &p->ib->fence->semaphore); - if (r) - return r; - } - - r = radeon_ring_lock(p->rdev, &p->rdev->ring[i], 3); - if (r) - return r; - radeon_semaphore_emit_signal(p->rdev, i, p->ib->fence->semaphore); - radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[i]); + if (!need_sync) { + return 0; + } - r = radeon_ring_lock(p->rdev, &p->rdev->ring[p->ring], 3); - if (r) - return r; - radeon_semaphore_emit_wait(p->rdev, p->ring, p->ib->fence->semaphore); - radeon_ring_unlock_commit(p->rdev, &p->rdev->ring[p->ring]); + r = radeon_semaphore_create(p->rdev, &p->ib->fence->semaphore); + if (r) { + return r; } - return 0; + + return radeon_semaphore_sync_rings(p->rdev, p->ib->fence->semaphore, + sync_to_ring, p->ring); } int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) @@ -172,6 +161,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) /* get chunks */ INIT_LIST_HEAD(&p->validated); p->idx = 0; + p->ib = NULL; + p->const_ib = NULL; p->chunk_ib_idx = -1; p->chunk_relocs_idx = -1; p->chunk_flags_idx = -1; @@ -336,6 +327,9 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) kfree(parser->chunks); kfree(parser->chunks_array); radeon_ib_free(parser->rdev, &parser->ib); + if (parser->const_ib) { + radeon_ib_free(parser->rdev, &parser->const_ib); + } } static int radeon_cs_ib_chunk(struct radeon_device *rdev, @@ -507,6 +501,16 @@ out: return r; } +static int radeon_cs_handle_lockup(struct radeon_device *rdev, int r) +{ + if (r == -EDEADLK) { + r = radeon_gpu_reset(rdev); + if (!r) + r = -EAGAIN; + } + return r; +} + int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; @@ -528,6 +532,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r) { DRM_ERROR("Failed to initialize parser !\n"); radeon_cs_parser_fini(&parser, r); + r = radeon_cs_handle_lockup(rdev, r); radeon_mutex_unlock(&rdev->cs_mutex); return r; } @@ -536,6 +541,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r != -ERESTARTSYS) DRM_ERROR("Failed to parse relocation %d!\n", r); radeon_cs_parser_fini(&parser, r); + r = radeon_cs_handle_lockup(rdev, r); radeon_mutex_unlock(&rdev->cs_mutex); return r; } @@ -549,6 +555,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) } out: radeon_cs_parser_fini(&parser, r); + r = radeon_cs_handle_lockup(rdev, r); radeon_mutex_unlock(&rdev->cs_mutex); return r; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 76a118df04f..ff28210dede 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -714,7 +714,6 @@ int radeon_device_init(struct radeon_device *rdev, rdev->is_atom_bios = false; rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; - rdev->gpu_lockup = false; rdev->accel_working = false; DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", @@ -916,7 +915,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) radeon_bo_evict_vram(rdev); /* wait for gpu to finish processing current batch */ for (i = 0; i < RADEON_NUM_RINGS; i++) - radeon_fence_wait_last(rdev, i); + radeon_fence_wait_empty(rdev, i); radeon_save_bios_scratch_regs(rdev); @@ -987,9 +986,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) int r; int resched; - /* Prevent CS ioctl from interfering */ - radeon_mutex_lock(&rdev->cs_mutex); - radeon_save_bios_scratch_regs(rdev); /* block TTM */ resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); @@ -1004,8 +1000,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); } - radeon_mutex_unlock(&rdev->cs_mutex); - if (r) { /* bad news, how to tell it to userspace ? */ dev_info(rdev->dev, "GPU reset failed\n"); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index ef7bb3f6eca..e62e56a57ee 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -128,6 +128,7 @@ int radeon_disp_priority = 0; int radeon_hw_i2c = 0; int radeon_pcie_gen2 = 0; int radeon_msi = -1; +int radeon_lockup_timeout = 10000; MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); module_param_named(no_wb, radeon_no_wb, int, 0444); @@ -177,6 +178,9 @@ module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)"); module_param_named(msi, radeon_msi, int, 0444); +MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 10000 = 10 seconds, 0 = disable)"); +module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444); + static int radeon_suspend(struct drm_device *dev, pm_message_t state) { drm_radeon_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 4bd36a354fb..5bb78bf547e 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -71,16 +71,13 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) return 0; } fence->seq = atomic_add_return(1, &rdev->fence_drv[fence->ring].seq); - if (!rdev->ring[fence->ring].ready) - /* FIXME: cp is not running assume everythings is done right - * away - */ - radeon_fence_write(rdev, fence->seq, fence->ring); - else - radeon_fence_ring_emit(rdev, fence->ring, fence); - + radeon_fence_ring_emit(rdev, fence->ring, fence); trace_radeon_fence_emit(rdev->ddev, fence->seq); fence->emitted = true; + /* are we the first fence on a previusly idle ring? */ + if (list_empty(&rdev->fence_drv[fence->ring].emitted)) { + rdev->fence_drv[fence->ring].last_activity = jiffies; + } list_move_tail(&fence->list, &rdev->fence_drv[fence->ring].emitted); write_unlock_irqrestore(&rdev->fence_lock, irq_flags); return 0; @@ -92,34 +89,14 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev, int ring) struct list_head *i, *n; uint32_t seq; bool wake = false; - unsigned long cjiffies; seq = radeon_fence_read(rdev, ring); - if (seq != rdev->fence_drv[ring].last_seq) { - rdev->fence_drv[ring].last_seq = seq; - rdev->fence_drv[ring].last_jiffies = jiffies; - rdev->fence_drv[ring].last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; - } else { - cjiffies = jiffies; - if (time_after(cjiffies, rdev->fence_drv[ring].last_jiffies)) { - cjiffies -= rdev->fence_drv[ring].last_jiffies; - if (time_after(rdev->fence_drv[ring].last_timeout, cjiffies)) { - /* update the timeout */ - rdev->fence_drv[ring].last_timeout -= cjiffies; - } else { - /* the 500ms timeout is elapsed we should test - * for GPU lockup - */ - rdev->fence_drv[ring].last_timeout = 1; - } - } else { - /* wrap around update last jiffies, we will just wait - * a little longer - */ - rdev->fence_drv[ring].last_jiffies = cjiffies; - } + if (seq == rdev->fence_drv[ring].last_seq) return false; - } + + rdev->fence_drv[ring].last_seq = seq; + rdev->fence_drv[ring].last_activity = jiffies; + n = NULL; list_for_each(i, &rdev->fence_drv[ring].emitted) { fence = list_entry(i, struct radeon_fence, list); @@ -162,8 +139,6 @@ int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence, int ring) { - unsigned long irq_flags; - *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); if ((*fence) == NULL) { return -ENOMEM; @@ -176,10 +151,6 @@ int radeon_fence_create(struct radeon_device *rdev, (*fence)->ring = ring; (*fence)->semaphore = NULL; INIT_LIST_HEAD(&(*fence)->list); - - write_lock_irqsave(&rdev->fence_lock, irq_flags); - list_add_tail(&(*fence)->list, &rdev->fence_drv[ring].created); - write_unlock_irqrestore(&rdev->fence_lock, irq_flags); return 0; } @@ -191,9 +162,6 @@ bool radeon_fence_signaled(struct radeon_fence *fence) if (!fence) return true; - if (fence->rdev->gpu_lockup) - return true; - write_lock_irqsave(&fence->rdev->fence_lock, irq_flags); signaled = fence->signaled; /* if we are shuting down report all fence as signaled */ @@ -217,68 +185,80 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) struct radeon_device *rdev; unsigned long irq_flags, timeout; u32 seq; - int r; + int i, r; + bool signaled; if (fence == NULL) { WARN(1, "Querying an invalid fence : %p !\n", fence); - return 0; + return -EINVAL; } + rdev = fence->rdev; - if (radeon_fence_signaled(fence)) { - return 0; - } - timeout = rdev->fence_drv[fence->ring].last_timeout; -retry: - /* save current sequence used to check for GPU lockup */ - seq = rdev->fence_drv[fence->ring].last_seq; - trace_radeon_fence_wait_begin(rdev->ddev, seq); - if (intr) { + signaled = radeon_fence_signaled(fence); + while (!signaled) { + read_lock_irqsave(&rdev->fence_lock, irq_flags); + timeout = jiffies - RADEON_FENCE_JIFFIES_TIMEOUT; + if (time_after(rdev->fence_drv[fence->ring].last_activity, timeout)) { + /* the normal case, timeout is somewhere before last_activity */ + timeout = rdev->fence_drv[fence->ring].last_activity - timeout; + } else { + /* either jiffies wrapped around, or no fence was signaled in the last 500ms + * anyway we will just wait for the minimum amount and then check for a lockup */ + timeout = 1; + } + /* save current sequence value used to check for GPU lockups */ + seq = rdev->fence_drv[fence->ring].last_seq; + read_unlock_irqrestore(&rdev->fence_lock, irq_flags); + + trace_radeon_fence_wait_begin(rdev->ddev, seq); radeon_irq_kms_sw_irq_get(rdev, fence->ring); - r = wait_event_interruptible_timeout(rdev->fence_drv[fence->ring].queue, - radeon_fence_signaled(fence), timeout); + if (intr) { + r = wait_event_interruptible_timeout( + rdev->fence_drv[fence->ring].queue, + (signaled = radeon_fence_signaled(fence)), timeout); + } else { + r = wait_event_timeout( + rdev->fence_drv[fence->ring].queue, + (signaled = radeon_fence_signaled(fence)), timeout); + } radeon_irq_kms_sw_irq_put(rdev, fence->ring); if (unlikely(r < 0)) { return r; } - } else { - radeon_irq_kms_sw_irq_get(rdev, fence->ring); - r = wait_event_timeout(rdev->fence_drv[fence->ring].queue, - radeon_fence_signaled(fence), timeout); - radeon_irq_kms_sw_irq_put(rdev, fence->ring); - } - trace_radeon_fence_wait_end(rdev->ddev, seq); - if (unlikely(!radeon_fence_signaled(fence))) { - /* we were interrupted for some reason and fence isn't - * isn't signaled yet, resume wait - */ - if (r) { - timeout = r; - goto retry; - } - /* don't protect read access to rdev->fence_drv[t].last_seq - * if we experiencing a lockup the value doesn't change - */ - if (seq == rdev->fence_drv[fence->ring].last_seq && - radeon_gpu_is_lockup(rdev, &rdev->ring[fence->ring])) { - /* good news we believe it's a lockup */ - printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", - fence->seq, seq); - /* FIXME: what should we do ? marking everyone - * as signaled for now - */ - rdev->gpu_lockup = true; - r = radeon_gpu_reset(rdev); - if (r) - return r; - radeon_fence_write(rdev, fence->seq, fence->ring); - rdev->gpu_lockup = false; + trace_radeon_fence_wait_end(rdev->ddev, seq); + + if (unlikely(!signaled)) { + /* we were interrupted for some reason and fence + * isn't signaled yet, resume waiting */ + if (r) { + continue; + } + + write_lock_irqsave(&rdev->fence_lock, irq_flags); + /* check if sequence value has changed since last_activity */ + if (seq != rdev->fence_drv[fence->ring].last_seq) { + write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + continue; + } + + /* change sequence value on all rings, so nobody else things there is a lockup */ + for (i = 0; i < RADEON_NUM_RINGS; ++i) + rdev->fence_drv[i].last_seq -= 0x10000; + + rdev->fence_drv[fence->ring].last_activity = jiffies; + write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + + if (radeon_ring_is_lockup(rdev, fence->ring, &rdev->ring[fence->ring])) { + + /* good news we believe it's a lockup */ + printk(KERN_WARNING "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", + fence->seq, seq); + + /* mark the ring as not ready any more */ + rdev->ring[fence->ring].ready = false; + return -EDEADLK; + } } - timeout = RADEON_FENCE_JIFFIES_TIMEOUT; - write_lock_irqsave(&rdev->fence_lock, irq_flags); - rdev->fence_drv[fence->ring].last_timeout = RADEON_FENCE_JIFFIES_TIMEOUT; - rdev->fence_drv[fence->ring].last_jiffies = jiffies; - write_unlock_irqrestore(&rdev->fence_lock, irq_flags); - goto retry; } return 0; } @@ -289,13 +269,14 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int ring) struct radeon_fence *fence; int r; - if (rdev->gpu_lockup) { - return 0; - } write_lock_irqsave(&rdev->fence_lock, irq_flags); + if (!rdev->ring[ring].ready) { + write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + return -EBUSY; + } if (list_empty(&rdev->fence_drv[ring].emitted)) { write_unlock_irqrestore(&rdev->fence_lock, irq_flags); - return 0; + return -ENOENT; } fence = list_entry(rdev->fence_drv[ring].emitted.next, struct radeon_fence, list); @@ -306,16 +287,17 @@ int radeon_fence_wait_next(struct radeon_device *rdev, int ring) return r; } -int radeon_fence_wait_last(struct radeon_device *rdev, int ring) +int radeon_fence_wait_empty(struct radeon_device *rdev, int ring) { unsigned long irq_flags; struct radeon_fence *fence; int r; - if (rdev->gpu_lockup) { - return 0; - } write_lock_irqsave(&rdev->fence_lock, irq_flags); + if (!rdev->ring[ring].ready) { + write_unlock_irqrestore(&rdev->fence_lock, irq_flags); + return -EBUSY; + } if (list_empty(&rdev->fence_drv[ring].emitted)) { write_unlock_irqrestore(&rdev->fence_lock, irq_flags); return 0; @@ -419,7 +401,6 @@ static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) rdev->fence_drv[ring].cpu_addr = NULL; rdev->fence_drv[ring].gpu_addr = 0; atomic_set(&rdev->fence_drv[ring].seq, 0); - INIT_LIST_HEAD(&rdev->fence_drv[ring].created); INIT_LIST_HEAD(&rdev->fence_drv[ring].emitted); INIT_LIST_HEAD(&rdev->fence_drv[ring].signaled); init_waitqueue_head(&rdev->fence_drv[ring].queue); @@ -450,7 +431,7 @@ void radeon_fence_driver_fini(struct radeon_device *rdev) for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { if (!rdev->fence_drv[ring].initialized) continue; - radeon_fence_wait_last(rdev, ring); + radeon_fence_wait_empty(rdev, ring); wake_up_all(&rdev->fence_drv[ring].queue); write_lock_irqsave(&rdev->fence_lock, irq_flags); radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index c7008b5210f..e15cb1fe2c3 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -154,6 +154,17 @@ void radeon_gem_object_close(struct drm_gem_object *obj, radeon_bo_unreserve(rbo); } +static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) +{ + if (r == -EDEADLK) { + radeon_mutex_lock(&rdev->cs_mutex); + r = radeon_gpu_reset(rdev); + if (!r) + r = -EAGAIN; + radeon_mutex_unlock(&rdev->cs_mutex); + } + return r; +} /* * GEM ioctls. @@ -210,12 +221,14 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, args->initial_domain, false, false, &gobj); if (r) { + r = radeon_gem_handle_lockup(rdev, r); return r; } r = drm_gem_handle_create(filp, gobj, &handle); /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(gobj); if (r) { + r = radeon_gem_handle_lockup(rdev, r); return r; } args->handle = handle; @@ -245,6 +258,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); drm_gem_object_unreference_unlocked(gobj); + r = radeon_gem_handle_lockup(robj->rdev, r); return r; } @@ -301,6 +315,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, break; } drm_gem_object_unreference_unlocked(gobj); + r = radeon_gem_handle_lockup(robj->rdev, r); return r; } @@ -322,6 +337,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, if (robj->rdev->asic->ioctl_wait_idle) robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj); drm_gem_object_unreference_unlocked(gobj); + r = radeon_gem_handle_lockup(robj->rdev, r); return r; } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 0c3cdbd614d..499a5fed8b2 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -210,6 +210,7 @@ enum radeon_connector_table { CT_RN50_POWER, CT_MAC_X800, CT_MAC_G5_9600, + CT_SAM440EP }; enum radeon_dvo_chip { diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index cc33b3d7c33..2eb4c6ed198 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -34,7 +34,7 @@ #include "atom.h" int radeon_debugfs_ib_init(struct radeon_device *rdev); -int radeon_debugfs_ring_init(struct radeon_device *rdev); +int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx) { @@ -237,9 +237,6 @@ int radeon_ib_pool_init(struct radeon_device *rdev) if (radeon_debugfs_ib_init(rdev)) { DRM_ERROR("Failed to register debugfs file for IB !\n"); } - if (radeon_debugfs_ring_init(rdev)) { - DRM_ERROR("Failed to register debugfs file for rings !\n"); - } radeon_mutex_unlock(&rdev->ib_pool.mutex); return 0; } @@ -270,6 +267,36 @@ int radeon_ib_pool_suspend(struct radeon_device *rdev) return radeon_sa_bo_manager_suspend(rdev, &rdev->ib_pool.sa_manager); } +int radeon_ib_ring_tests(struct radeon_device *rdev) +{ + unsigned i; + int r; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + struct radeon_ring *ring = &rdev->ring[i]; + + if (!ring->ready) + continue; + + r = radeon_ib_test(rdev, i, ring); + if (r) { + ring->ready = false; + + if (i == RADEON_RING_TYPE_GFX_INDEX) { + /* oh, oh, that's really bad */ + DRM_ERROR("radeon: failed testing IB on GFX ring (%d).\n", r); + rdev->accel_working = false; + return r; + + } else { + /* still not good, but we can live with it */ + DRM_ERROR("radeon: failed testing IB on ring %d (%d).\n", i, r); + } + } + } + return 0; +} + /* * Ring. */ @@ -319,7 +346,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi if (ndw < ring->ring_free_dw) { break; } + mutex_unlock(&ring->mutex); r = radeon_fence_wait_next(rdev, radeon_ring_index(rdev, ring)); + mutex_lock(&ring->mutex); if (r) return r; } @@ -369,6 +398,75 @@ void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *rin mutex_unlock(&ring->mutex); } +void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) +{ + int r; + + mutex_lock(&ring->mutex); + radeon_ring_free_size(rdev, ring); + if (ring->rptr == ring->wptr) { + r = radeon_ring_alloc(rdev, ring, 1); + if (!r) { + radeon_ring_write(ring, ring->nop); + radeon_ring_commit(rdev, ring); + } + } + mutex_unlock(&ring->mutex); +} + +void radeon_ring_lockup_update(struct radeon_ring *ring) +{ + ring->last_rptr = ring->rptr; + ring->last_activity = jiffies; +} + +/** + * radeon_ring_test_lockup() - check if ring is lockedup by recording information + * @rdev: radeon device structure + * @ring: radeon_ring structure holding ring information + * + * We don't need to initialize the lockup tracking information as we will either + * have CP rptr to a different value of jiffies wrap around which will force + * initialization of the lockup tracking informations. + * + * A possible false positivie is if we get call after while and last_cp_rptr == + * the current CP rptr, even if it's unlikely it might happen. To avoid this + * if the elapsed time since last call is bigger than 2 second than we return + * false and update the tracking information. Due to this the caller must call + * radeon_ring_test_lockup several time in less than 2sec for lockup to be reported + * the fencing code should be cautious about that. + * + * Caller should write to the ring to force CP to do something so we don't get + * false positive when CP is just gived nothing to do. + * + **/ +bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) +{ + unsigned long cjiffies, elapsed; + uint32_t rptr; + + cjiffies = jiffies; + if (!time_after(cjiffies, ring->last_activity)) { + /* likely a wrap around */ + radeon_ring_lockup_update(ring); + return false; + } + rptr = RREG32(ring->rptr_reg); + ring->rptr = (rptr & ring->ptr_reg_mask) >> ring->ptr_reg_shift; + if (ring->rptr != ring->last_rptr) { + /* CP is still working no lockup */ + radeon_ring_lockup_update(ring); + return false; + } + elapsed = jiffies_to_msecs(cjiffies - ring->last_activity); + if (radeon_lockup_timeout && elapsed >= radeon_lockup_timeout) { + dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); + return true; + } + /* give a chance to the GPU ... */ + return false; +} + int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) @@ -411,6 +509,9 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig } ring->ptr_mask = (ring->ring_size / 4) - 1; ring->ring_free_dw = ring->ring_size / 4; + if (radeon_debugfs_ring_init(rdev, ring)) { + DRM_ERROR("Failed to register debugfs file for rings !\n"); + } return 0; } @@ -501,17 +602,24 @@ static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32]; static unsigned radeon_debugfs_ib_idx[RADEON_IB_POOL_SIZE]; #endif -int radeon_debugfs_ring_init(struct radeon_device *rdev) +int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring) { #if defined(CONFIG_DEBUG_FS) - if (rdev->family >= CHIP_CAYMAN) - return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, - ARRAY_SIZE(radeon_debugfs_ring_info_list)); - else - return radeon_debugfs_add_files(rdev, radeon_debugfs_ring_info_list, 1); -#else - return 0; + unsigned i; + for (i = 0; i < ARRAY_SIZE(radeon_debugfs_ring_info_list); ++i) { + struct drm_info_list *info = &radeon_debugfs_ring_info_list[i]; + int ridx = *(int*)radeon_debugfs_ring_info_list[i].data; + unsigned r; + + if (&rdev->ring[ridx] != ring) + continue; + + r = radeon_debugfs_add_files(rdev, info, 1); + if (r) + return r; + } #endif + return 0; } int radeon_debugfs_ib_init(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c index 4cce47e7dc0..8fbfe69b7bc 100644 --- a/drivers/gpu/drm/radeon/radeon_sa.c +++ b/drivers/gpu/drm/radeon/radeon_sa.c @@ -150,7 +150,7 @@ int radeon_sa_bo_new(struct radeon_device *rdev, offset = 0; list_for_each_entry(tmp, &sa_manager->sa_bo, list) { /* room before this object ? */ - if ((tmp->offset - offset) >= size) { + if (offset < tmp->offset && (tmp->offset - offset) >= size) { head = tmp->list.prev; goto out; } diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 61dd4e3c920..930a08af900 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -149,6 +149,62 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); } +int radeon_semaphore_sync_rings(struct radeon_device *rdev, + struct radeon_semaphore *semaphore, + bool sync_to[RADEON_NUM_RINGS], + int dst_ring) +{ + int i, r; + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + unsigned num_ops = i == dst_ring ? RADEON_NUM_RINGS : 1; + + /* don't lock unused rings */ + if (!sync_to[i] && i != dst_ring) + continue; + + /* prevent GPU deadlocks */ + if (!rdev->ring[i].ready) { + dev_err(rdev->dev, "Trying to sync to a disabled ring!"); + r = -EINVAL; + goto error; + } + + r = radeon_ring_lock(rdev, &rdev->ring[i], num_ops * 8); + if (r) + goto error; + } + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + /* no need to sync to our own or unused rings */ + if (!sync_to[i] || i == dst_ring) + continue; + + radeon_semaphore_emit_signal(rdev, i, semaphore); + radeon_semaphore_emit_wait(rdev, dst_ring, semaphore); + } + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + + /* don't unlock unused rings */ + if (!sync_to[i] && i != dst_ring) + continue; + + radeon_ring_unlock_commit(rdev, &rdev->ring[i]); + } + + return 0; + +error: + /* unlock all locks taken so far */ + for (--i; i >= 0; --i) { + if (sync_to[i] || i == dst_ring) { + radeon_ring_unlock_undo(rdev, &rdev->ring[i]); + } + } + return r; +} + void radeon_semaphore_free(struct radeon_device *rdev, struct radeon_semaphore *semaphore) { diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index f493c6403af..5e3d54ded1b 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -222,8 +222,8 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, { struct radeon_device *rdev; uint64_t old_start, new_start; - struct radeon_fence *fence; - int r, i; + struct radeon_fence *fence, *old_fence; + int r; rdev = radeon_get_rdev(bo->bdev); r = radeon_fence_create(rdev, &fence, radeon_copy_ring_index(rdev)); @@ -242,6 +242,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, break; default: DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + radeon_fence_unref(&fence); return -EINVAL; } switch (new_mem->mem_type) { @@ -253,42 +254,35 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, break; default: DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + radeon_fence_unref(&fence); return -EINVAL; } if (!rdev->ring[radeon_copy_ring_index(rdev)].ready) { DRM_ERROR("Trying to move memory with ring turned off.\n"); + radeon_fence_unref(&fence); return -EINVAL; } BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); /* sync other rings */ - if (rdev->family >= CHIP_R600) { - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - /* no need to sync to our own or unused rings */ - if (i == radeon_copy_ring_index(rdev) || !rdev->ring[i].ready) - continue; - - if (!fence->semaphore) { - r = radeon_semaphore_create(rdev, &fence->semaphore); - /* FIXME: handle semaphore error */ - if (r) - continue; - } + old_fence = bo->sync_obj; + if (old_fence && old_fence->ring != fence->ring + && !radeon_fence_signaled(old_fence)) { + bool sync_to_ring[RADEON_NUM_RINGS] = { }; + sync_to_ring[old_fence->ring] = true; + + r = radeon_semaphore_create(rdev, &fence->semaphore); + if (r) { + radeon_fence_unref(&fence); + return r; + } - r = radeon_ring_lock(rdev, &rdev->ring[i], 3); - /* FIXME: handle ring lock error */ - if (r) - continue; - radeon_semaphore_emit_signal(rdev, i, fence->semaphore); - radeon_ring_unlock_commit(rdev, &rdev->ring[i]); - - r = radeon_ring_lock(rdev, &rdev->ring[radeon_copy_ring_index(rdev)], 3); - /* FIXME: handle ring lock error */ - if (r) - continue; - radeon_semaphore_emit_wait(rdev, radeon_copy_ring_index(rdev), fence->semaphore); - radeon_ring_unlock_commit(rdev, &rdev->ring[radeon_copy_ring_index(rdev)]); + r = radeon_semaphore_sync_rings(rdev, fence->semaphore, + sync_to_ring, fence->ring); + if (r) { + radeon_fence_unref(&fence); + return r; } } diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 4cf381b3a6d..a464eb5e2df 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -430,12 +430,9 @@ static int rs400_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 10706c66b84..25f9eef12c4 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -396,7 +396,6 @@ int rs600_asic_reset(struct radeon_device *rdev) /* Check if GPU is idle */ if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { dev_err(rdev->dev, "failed to reset GPU\n"); - rdev->gpu_lockup = true; ret = -1; } else dev_info(rdev->dev, "GPU reset succeed\n"); @@ -919,12 +918,9 @@ static int rs600_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index f2c3b9d75f1..3277ddecfe9 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -647,12 +647,9 @@ static int rs690_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index d8d78fe1794..7f08cedb533 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -412,12 +412,10 @@ static int rv515_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "failed testing IB (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } + return 0; } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index cdab1aeaed6..a8b001641e4 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1114,12 +1114,9 @@ static int rv770_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); - if (r) { - dev_err(rdev->dev, "IB test failed (%d).\n", r); - rdev->accel_working = false; + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 9727a16c040..779f0b604fa 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2217,8 +2217,6 @@ bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) u32 srbm_status; u32 grbm_status, grbm_status2; u32 grbm_status_se0, grbm_status_se1; - struct r100_gpu_lockup *lockup = &rdev->config.si.lockup; - int r; srbm_status = RREG32(SRBM_STATUS); grbm_status = RREG32(GRBM_STATUS); @@ -2226,20 +2224,12 @@ bool si_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) grbm_status_se0 = RREG32(GRBM_STATUS_SE0); grbm_status_se1 = RREG32(GRBM_STATUS_SE1); if (!(grbm_status & GUI_ACTIVE)) { - r100_gpu_lockup_update(lockup, ring); + radeon_ring_lockup_update(ring); return false; } /* force CP activities */ - r = radeon_ring_lock(rdev, ring, 2); - if (!r) { - /* PACKET2 NOP */ - radeon_ring_write(ring, 0x80000000); - radeon_ring_write(ring, 0x80000000); - radeon_ring_unlock_commit(rdev, ring); - } - /* XXX deal with CP0,1,2 */ - ring->rptr = RREG32(ring->rptr_reg); - return r100_gpu_cp_is_lockup(rdev, lockup, ring); + radeon_ring_force_activity(rdev, ring); + return radeon_ring_test_lockup(rdev, ring); } static int si_gpu_soft_reset(struct radeon_device *rdev) diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 367ab18dccf..0ee42d9acdc 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h @@ -183,8 +183,13 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc); */ #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE +#ifdef CONFIG_VGA_ARB extern struct pci_dev *vga_default_device(void); extern void vga_set_default_device(struct pci_dev *pdev); +#else +static inline struct pci_dev *vga_default_device(void) { return NULL; }; +static inline void vga_set_default_device(struct pci_dev *pdev) { }; +#endif #endif /** |