Path: blob/master/drivers/gpu/drm/i915/intel_ringbuffer.c
15113 views
/*1* Copyright © 2008-2010 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22* Authors:23* Eric Anholt <[email protected]>24* Zou Nan hai <[email protected]>25* Xiang Hai hao<[email protected]>26*27*/2829#include "drmP.h"30#include "drm.h"31#include "i915_drv.h"32#include "i915_drm.h"33#include "i915_trace.h"34#include "intel_drv.h"3536static inline int ring_space(struct intel_ring_buffer *ring)37{38int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);39if (space < 0)40space += ring->size;41return space;42}4344static u32 i915_gem_get_seqno(struct drm_device *dev)45{46drm_i915_private_t *dev_priv = dev->dev_private;47u32 seqno;4849seqno = dev_priv->next_seqno;5051/* reserve 0 for non-seqno */52if (++dev_priv->next_seqno == 0)53dev_priv->next_seqno = 1;5455return seqno;56}5758static int59render_ring_flush(struct intel_ring_buffer *ring,60u32 invalidate_domains,61u32 flush_domains)62{63struct drm_device *dev = ring->dev;64u32 cmd;65int ret;6667/*68* read/write caches:69*70* I915_GEM_DOMAIN_RENDER is always invalidated, but is71* only flushed if MI_NO_WRITE_FLUSH is unset. On 965, it is72* also flushed at 2d versus 3d pipeline switches.73*74* read-only caches:75*76* I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if77* MI_READ_FLUSH is set, and is always flushed on 965.78*79* I915_GEM_DOMAIN_COMMAND may not exist?80*81* I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is82* invalidated when MI_EXE_FLUSH is set.83*84* I915_GEM_DOMAIN_VERTEX, which exists on 965, is85* invalidated with every MI_FLUSH.86*87* TLBs:88*89* On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND90* and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and91* I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER92* are flushed at any MI_FLUSH.93*/9495cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;96if ((invalidate_domains|flush_domains) &97I915_GEM_DOMAIN_RENDER)98cmd &= ~MI_NO_WRITE_FLUSH;99if (INTEL_INFO(dev)->gen < 4) {100/*101* On the 965, the sampler cache always gets flushed102* and this bit is reserved.103*/104if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)105cmd |= MI_READ_FLUSH;106}107if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)108cmd |= MI_EXE_FLUSH;109110if (invalidate_domains & I915_GEM_DOMAIN_COMMAND &&111(IS_G4X(dev) || IS_GEN5(dev)))112cmd |= MI_INVALIDATE_ISP;113114ret = intel_ring_begin(ring, 2);115if (ret)116return ret;117118intel_ring_emit(ring, cmd);119intel_ring_emit(ring, MI_NOOP);120intel_ring_advance(ring);121122return 0;123}124125static void ring_write_tail(struct intel_ring_buffer *ring,126u32 value)127{128drm_i915_private_t *dev_priv = ring->dev->dev_private;129I915_WRITE_TAIL(ring, value);130}131132u32 intel_ring_get_active_head(struct intel_ring_buffer *ring)133{134drm_i915_private_t *dev_priv = ring->dev->dev_private;135u32 acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ?136RING_ACTHD(ring->mmio_base) : ACTHD;137138return I915_READ(acthd_reg);139}140141static int init_ring_common(struct intel_ring_buffer *ring)142{143drm_i915_private_t *dev_priv = ring->dev->dev_private;144struct drm_i915_gem_object *obj = ring->obj;145u32 head;146147/* Stop the ring if it's running. */148I915_WRITE_CTL(ring, 0);149I915_WRITE_HEAD(ring, 0);150ring->write_tail(ring, 0);151152/* Initialize the ring. */153I915_WRITE_START(ring, obj->gtt_offset);154head = I915_READ_HEAD(ring) & HEAD_ADDR;155156/* G45 ring initialization fails to reset head to zero */157if (head != 0) {158DRM_DEBUG_KMS("%s head not reset to zero "159"ctl %08x head %08x tail %08x start %08x\n",160ring->name,161I915_READ_CTL(ring),162I915_READ_HEAD(ring),163I915_READ_TAIL(ring),164I915_READ_START(ring));165166I915_WRITE_HEAD(ring, 0);167168if (I915_READ_HEAD(ring) & HEAD_ADDR) {169DRM_ERROR("failed to set %s head to zero "170"ctl %08x head %08x tail %08x start %08x\n",171ring->name,172I915_READ_CTL(ring),173I915_READ_HEAD(ring),174I915_READ_TAIL(ring),175I915_READ_START(ring));176}177}178179I915_WRITE_CTL(ring,180((ring->size - PAGE_SIZE) & RING_NR_PAGES)181| RING_REPORT_64K | RING_VALID);182183/* If the head is still not zero, the ring is dead */184if ((I915_READ_CTL(ring) & RING_VALID) == 0 ||185I915_READ_START(ring) != obj->gtt_offset ||186(I915_READ_HEAD(ring) & HEAD_ADDR) != 0) {187DRM_ERROR("%s initialization failed "188"ctl %08x head %08x tail %08x start %08x\n",189ring->name,190I915_READ_CTL(ring),191I915_READ_HEAD(ring),192I915_READ_TAIL(ring),193I915_READ_START(ring));194return -EIO;195}196197if (!drm_core_check_feature(ring->dev, DRIVER_MODESET))198i915_kernel_lost_context(ring->dev);199else {200ring->head = I915_READ_HEAD(ring);201ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;202ring->space = ring_space(ring);203}204205return 0;206}207208/*209* 965+ support PIPE_CONTROL commands, which provide finer grained control210* over cache flushing.211*/212struct pipe_control {213struct drm_i915_gem_object *obj;214volatile u32 *cpu_page;215u32 gtt_offset;216};217218static int219init_pipe_control(struct intel_ring_buffer *ring)220{221struct pipe_control *pc;222struct drm_i915_gem_object *obj;223int ret;224225if (ring->private)226return 0;227228pc = kmalloc(sizeof(*pc), GFP_KERNEL);229if (!pc)230return -ENOMEM;231232obj = i915_gem_alloc_object(ring->dev, 4096);233if (obj == NULL) {234DRM_ERROR("Failed to allocate seqno page\n");235ret = -ENOMEM;236goto err;237}238obj->cache_level = I915_CACHE_LLC;239240ret = i915_gem_object_pin(obj, 4096, true);241if (ret)242goto err_unref;243244pc->gtt_offset = obj->gtt_offset;245pc->cpu_page = kmap(obj->pages[0]);246if (pc->cpu_page == NULL)247goto err_unpin;248249pc->obj = obj;250ring->private = pc;251return 0;252253err_unpin:254i915_gem_object_unpin(obj);255err_unref:256drm_gem_object_unreference(&obj->base);257err:258kfree(pc);259return ret;260}261262static void263cleanup_pipe_control(struct intel_ring_buffer *ring)264{265struct pipe_control *pc = ring->private;266struct drm_i915_gem_object *obj;267268if (!ring->private)269return;270271obj = pc->obj;272kunmap(obj->pages[0]);273i915_gem_object_unpin(obj);274drm_gem_object_unreference(&obj->base);275276kfree(pc);277ring->private = NULL;278}279280static int init_render_ring(struct intel_ring_buffer *ring)281{282struct drm_device *dev = ring->dev;283struct drm_i915_private *dev_priv = dev->dev_private;284int ret = init_ring_common(ring);285286if (INTEL_INFO(dev)->gen > 3) {287int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;288if (IS_GEN6(dev) || IS_GEN7(dev))289mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;290I915_WRITE(MI_MODE, mode);291}292293if (INTEL_INFO(dev)->gen >= 6) {294} else if (IS_GEN5(dev)) {295ret = init_pipe_control(ring);296if (ret)297return ret;298}299300return ret;301}302303static void render_ring_cleanup(struct intel_ring_buffer *ring)304{305if (!ring->private)306return;307308cleanup_pipe_control(ring);309}310311static void312update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno)313{314struct drm_device *dev = ring->dev;315struct drm_i915_private *dev_priv = dev->dev_private;316int id;317318/*319* cs -> 1 = vcs, 0 = bcs320* vcs -> 1 = bcs, 0 = cs,321* bcs -> 1 = cs, 0 = vcs.322*/323id = ring - dev_priv->ring;324id += 2 - i;325id %= 3;326327intel_ring_emit(ring,328MI_SEMAPHORE_MBOX |329MI_SEMAPHORE_REGISTER |330MI_SEMAPHORE_UPDATE);331intel_ring_emit(ring, seqno);332intel_ring_emit(ring,333RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i);334}335336static int337gen6_add_request(struct intel_ring_buffer *ring,338u32 *result)339{340u32 seqno;341int ret;342343ret = intel_ring_begin(ring, 10);344if (ret)345return ret;346347seqno = i915_gem_get_seqno(ring->dev);348update_semaphore(ring, 0, seqno);349update_semaphore(ring, 1, seqno);350351intel_ring_emit(ring, MI_STORE_DWORD_INDEX);352intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);353intel_ring_emit(ring, seqno);354intel_ring_emit(ring, MI_USER_INTERRUPT);355intel_ring_advance(ring);356357*result = seqno;358return 0;359}360361int362intel_ring_sync(struct intel_ring_buffer *ring,363struct intel_ring_buffer *to,364u32 seqno)365{366int ret;367368ret = intel_ring_begin(ring, 4);369if (ret)370return ret;371372intel_ring_emit(ring,373MI_SEMAPHORE_MBOX |374MI_SEMAPHORE_REGISTER |375intel_ring_sync_index(ring, to) << 17 |376MI_SEMAPHORE_COMPARE);377intel_ring_emit(ring, seqno);378intel_ring_emit(ring, 0);379intel_ring_emit(ring, MI_NOOP);380intel_ring_advance(ring);381382return 0;383}384385#define PIPE_CONTROL_FLUSH(ring__, addr__) \386do { \387intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \388PIPE_CONTROL_DEPTH_STALL | 2); \389intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \390intel_ring_emit(ring__, 0); \391intel_ring_emit(ring__, 0); \392} while (0)393394static int395pc_render_add_request(struct intel_ring_buffer *ring,396u32 *result)397{398struct drm_device *dev = ring->dev;399u32 seqno = i915_gem_get_seqno(dev);400struct pipe_control *pc = ring->private;401u32 scratch_addr = pc->gtt_offset + 128;402int ret;403404/* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently405* incoherent with writes to memory, i.e. completely fubar,406* so we need to use PIPE_NOTIFY instead.407*408* However, we also need to workaround the qword write409* incoherence by flushing the 6 PIPE_NOTIFY buffers out to410* memory before requesting an interrupt.411*/412ret = intel_ring_begin(ring, 32);413if (ret)414return ret;415416intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |417PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);418intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);419intel_ring_emit(ring, seqno);420intel_ring_emit(ring, 0);421PIPE_CONTROL_FLUSH(ring, scratch_addr);422scratch_addr += 128; /* write to separate cachelines */423PIPE_CONTROL_FLUSH(ring, scratch_addr);424scratch_addr += 128;425PIPE_CONTROL_FLUSH(ring, scratch_addr);426scratch_addr += 128;427PIPE_CONTROL_FLUSH(ring, scratch_addr);428scratch_addr += 128;429PIPE_CONTROL_FLUSH(ring, scratch_addr);430scratch_addr += 128;431PIPE_CONTROL_FLUSH(ring, scratch_addr);432intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |433PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |434PIPE_CONTROL_NOTIFY);435intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);436intel_ring_emit(ring, seqno);437intel_ring_emit(ring, 0);438intel_ring_advance(ring);439440*result = seqno;441return 0;442}443444static int445render_ring_add_request(struct intel_ring_buffer *ring,446u32 *result)447{448struct drm_device *dev = ring->dev;449u32 seqno = i915_gem_get_seqno(dev);450int ret;451452ret = intel_ring_begin(ring, 4);453if (ret)454return ret;455456intel_ring_emit(ring, MI_STORE_DWORD_INDEX);457intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);458intel_ring_emit(ring, seqno);459intel_ring_emit(ring, MI_USER_INTERRUPT);460intel_ring_advance(ring);461462*result = seqno;463return 0;464}465466static u32467ring_get_seqno(struct intel_ring_buffer *ring)468{469return intel_read_status_page(ring, I915_GEM_HWS_INDEX);470}471472static u32473pc_render_get_seqno(struct intel_ring_buffer *ring)474{475struct pipe_control *pc = ring->private;476return pc->cpu_page[0];477}478479static void480ironlake_enable_irq(drm_i915_private_t *dev_priv, u32 mask)481{482dev_priv->gt_irq_mask &= ~mask;483I915_WRITE(GTIMR, dev_priv->gt_irq_mask);484POSTING_READ(GTIMR);485}486487static void488ironlake_disable_irq(drm_i915_private_t *dev_priv, u32 mask)489{490dev_priv->gt_irq_mask |= mask;491I915_WRITE(GTIMR, dev_priv->gt_irq_mask);492POSTING_READ(GTIMR);493}494495static void496i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)497{498dev_priv->irq_mask &= ~mask;499I915_WRITE(IMR, dev_priv->irq_mask);500POSTING_READ(IMR);501}502503static void504i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)505{506dev_priv->irq_mask |= mask;507I915_WRITE(IMR, dev_priv->irq_mask);508POSTING_READ(IMR);509}510511static bool512render_ring_get_irq(struct intel_ring_buffer *ring)513{514struct drm_device *dev = ring->dev;515drm_i915_private_t *dev_priv = dev->dev_private;516517if (!dev->irq_enabled)518return false;519520spin_lock(&ring->irq_lock);521if (ring->irq_refcount++ == 0) {522if (HAS_PCH_SPLIT(dev))523ironlake_enable_irq(dev_priv,524GT_PIPE_NOTIFY | GT_USER_INTERRUPT);525else526i915_enable_irq(dev_priv, I915_USER_INTERRUPT);527}528spin_unlock(&ring->irq_lock);529530return true;531}532533static void534render_ring_put_irq(struct intel_ring_buffer *ring)535{536struct drm_device *dev = ring->dev;537drm_i915_private_t *dev_priv = dev->dev_private;538539spin_lock(&ring->irq_lock);540if (--ring->irq_refcount == 0) {541if (HAS_PCH_SPLIT(dev))542ironlake_disable_irq(dev_priv,543GT_USER_INTERRUPT |544GT_PIPE_NOTIFY);545else546i915_disable_irq(dev_priv, I915_USER_INTERRUPT);547}548spin_unlock(&ring->irq_lock);549}550551void intel_ring_setup_status_page(struct intel_ring_buffer *ring)552{553struct drm_device *dev = ring->dev;554drm_i915_private_t *dev_priv = ring->dev->dev_private;555u32 mmio = 0;556557/* The ring status page addresses are no longer next to the rest of558* the ring registers as of gen7.559*/560if (IS_GEN7(dev)) {561switch (ring->id) {562case RING_RENDER:563mmio = RENDER_HWS_PGA_GEN7;564break;565case RING_BLT:566mmio = BLT_HWS_PGA_GEN7;567break;568case RING_BSD:569mmio = BSD_HWS_PGA_GEN7;570break;571}572} else if (IS_GEN6(ring->dev)) {573mmio = RING_HWS_PGA_GEN6(ring->mmio_base);574} else {575mmio = RING_HWS_PGA(ring->mmio_base);576}577578I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);579POSTING_READ(mmio);580}581582static int583bsd_ring_flush(struct intel_ring_buffer *ring,584u32 invalidate_domains,585u32 flush_domains)586{587int ret;588589ret = intel_ring_begin(ring, 2);590if (ret)591return ret;592593intel_ring_emit(ring, MI_FLUSH);594intel_ring_emit(ring, MI_NOOP);595intel_ring_advance(ring);596return 0;597}598599static int600ring_add_request(struct intel_ring_buffer *ring,601u32 *result)602{603u32 seqno;604int ret;605606ret = intel_ring_begin(ring, 4);607if (ret)608return ret;609610seqno = i915_gem_get_seqno(ring->dev);611612intel_ring_emit(ring, MI_STORE_DWORD_INDEX);613intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);614intel_ring_emit(ring, seqno);615intel_ring_emit(ring, MI_USER_INTERRUPT);616intel_ring_advance(ring);617618*result = seqno;619return 0;620}621622static bool623gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)624{625struct drm_device *dev = ring->dev;626drm_i915_private_t *dev_priv = dev->dev_private;627628if (!dev->irq_enabled)629return false;630631spin_lock(&ring->irq_lock);632if (ring->irq_refcount++ == 0) {633ring->irq_mask &= ~rflag;634I915_WRITE_IMR(ring, ring->irq_mask);635ironlake_enable_irq(dev_priv, gflag);636}637spin_unlock(&ring->irq_lock);638639return true;640}641642static void643gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)644{645struct drm_device *dev = ring->dev;646drm_i915_private_t *dev_priv = dev->dev_private;647648spin_lock(&ring->irq_lock);649if (--ring->irq_refcount == 0) {650ring->irq_mask |= rflag;651I915_WRITE_IMR(ring, ring->irq_mask);652ironlake_disable_irq(dev_priv, gflag);653}654spin_unlock(&ring->irq_lock);655}656657static bool658bsd_ring_get_irq(struct intel_ring_buffer *ring)659{660struct drm_device *dev = ring->dev;661drm_i915_private_t *dev_priv = dev->dev_private;662663if (!dev->irq_enabled)664return false;665666spin_lock(&ring->irq_lock);667if (ring->irq_refcount++ == 0) {668if (IS_G4X(dev))669i915_enable_irq(dev_priv, I915_BSD_USER_INTERRUPT);670else671ironlake_enable_irq(dev_priv, GT_BSD_USER_INTERRUPT);672}673spin_unlock(&ring->irq_lock);674675return true;676}677static void678bsd_ring_put_irq(struct intel_ring_buffer *ring)679{680struct drm_device *dev = ring->dev;681drm_i915_private_t *dev_priv = dev->dev_private;682683spin_lock(&ring->irq_lock);684if (--ring->irq_refcount == 0) {685if (IS_G4X(dev))686i915_disable_irq(dev_priv, I915_BSD_USER_INTERRUPT);687else688ironlake_disable_irq(dev_priv, GT_BSD_USER_INTERRUPT);689}690spin_unlock(&ring->irq_lock);691}692693static int694ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)695{696int ret;697698ret = intel_ring_begin(ring, 2);699if (ret)700return ret;701702intel_ring_emit(ring,703MI_BATCH_BUFFER_START | (2 << 6) |704MI_BATCH_NON_SECURE_I965);705intel_ring_emit(ring, offset);706intel_ring_advance(ring);707708return 0;709}710711static int712render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,713u32 offset, u32 len)714{715struct drm_device *dev = ring->dev;716int ret;717718if (IS_I830(dev) || IS_845G(dev)) {719ret = intel_ring_begin(ring, 4);720if (ret)721return ret;722723intel_ring_emit(ring, MI_BATCH_BUFFER);724intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);725intel_ring_emit(ring, offset + len - 8);726intel_ring_emit(ring, 0);727} else {728ret = intel_ring_begin(ring, 2);729if (ret)730return ret;731732if (INTEL_INFO(dev)->gen >= 4) {733intel_ring_emit(ring,734MI_BATCH_BUFFER_START | (2 << 6) |735MI_BATCH_NON_SECURE_I965);736intel_ring_emit(ring, offset);737} else {738intel_ring_emit(ring,739MI_BATCH_BUFFER_START | (2 << 6));740intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);741}742}743intel_ring_advance(ring);744745return 0;746}747748static void cleanup_status_page(struct intel_ring_buffer *ring)749{750drm_i915_private_t *dev_priv = ring->dev->dev_private;751struct drm_i915_gem_object *obj;752753obj = ring->status_page.obj;754if (obj == NULL)755return;756757kunmap(obj->pages[0]);758i915_gem_object_unpin(obj);759drm_gem_object_unreference(&obj->base);760ring->status_page.obj = NULL;761762memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));763}764765static int init_status_page(struct intel_ring_buffer *ring)766{767struct drm_device *dev = ring->dev;768drm_i915_private_t *dev_priv = dev->dev_private;769struct drm_i915_gem_object *obj;770int ret;771772obj = i915_gem_alloc_object(dev, 4096);773if (obj == NULL) {774DRM_ERROR("Failed to allocate status page\n");775ret = -ENOMEM;776goto err;777}778obj->cache_level = I915_CACHE_LLC;779780ret = i915_gem_object_pin(obj, 4096, true);781if (ret != 0) {782goto err_unref;783}784785ring->status_page.gfx_addr = obj->gtt_offset;786ring->status_page.page_addr = kmap(obj->pages[0]);787if (ring->status_page.page_addr == NULL) {788memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));789goto err_unpin;790}791ring->status_page.obj = obj;792memset(ring->status_page.page_addr, 0, PAGE_SIZE);793794intel_ring_setup_status_page(ring);795DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",796ring->name, ring->status_page.gfx_addr);797798return 0;799800err_unpin:801i915_gem_object_unpin(obj);802err_unref:803drm_gem_object_unreference(&obj->base);804err:805return ret;806}807808int intel_init_ring_buffer(struct drm_device *dev,809struct intel_ring_buffer *ring)810{811struct drm_i915_gem_object *obj;812int ret;813814ring->dev = dev;815INIT_LIST_HEAD(&ring->active_list);816INIT_LIST_HEAD(&ring->request_list);817INIT_LIST_HEAD(&ring->gpu_write_list);818819init_waitqueue_head(&ring->irq_queue);820spin_lock_init(&ring->irq_lock);821ring->irq_mask = ~0;822823if (I915_NEED_GFX_HWS(dev)) {824ret = init_status_page(ring);825if (ret)826return ret;827}828829obj = i915_gem_alloc_object(dev, ring->size);830if (obj == NULL) {831DRM_ERROR("Failed to allocate ringbuffer\n");832ret = -ENOMEM;833goto err_hws;834}835836ring->obj = obj;837838ret = i915_gem_object_pin(obj, PAGE_SIZE, true);839if (ret)840goto err_unref;841842ring->map.size = ring->size;843ring->map.offset = dev->agp->base + obj->gtt_offset;844ring->map.type = 0;845ring->map.flags = 0;846ring->map.mtrr = 0;847848drm_core_ioremap_wc(&ring->map, dev);849if (ring->map.handle == NULL) {850DRM_ERROR("Failed to map ringbuffer.\n");851ret = -EINVAL;852goto err_unpin;853}854855ring->virtual_start = ring->map.handle;856ret = ring->init(ring);857if (ret)858goto err_unmap;859860/* Workaround an erratum on the i830 which causes a hang if861* the TAIL pointer points to within the last 2 cachelines862* of the buffer.863*/864ring->effective_size = ring->size;865if (IS_I830(ring->dev))866ring->effective_size -= 128;867868return 0;869870err_unmap:871drm_core_ioremapfree(&ring->map, dev);872err_unpin:873i915_gem_object_unpin(obj);874err_unref:875drm_gem_object_unreference(&obj->base);876ring->obj = NULL;877err_hws:878cleanup_status_page(ring);879return ret;880}881882void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)883{884struct drm_i915_private *dev_priv;885int ret;886887if (ring->obj == NULL)888return;889890/* Disable the ring buffer. The ring must be idle at this point */891dev_priv = ring->dev->dev_private;892ret = intel_wait_ring_idle(ring);893if (ret)894DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",895ring->name, ret);896897I915_WRITE_CTL(ring, 0);898899drm_core_ioremapfree(&ring->map, ring->dev);900901i915_gem_object_unpin(ring->obj);902drm_gem_object_unreference(&ring->obj->base);903ring->obj = NULL;904905if (ring->cleanup)906ring->cleanup(ring);907908cleanup_status_page(ring);909}910911static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)912{913unsigned int *virt;914int rem = ring->size - ring->tail;915916if (ring->space < rem) {917int ret = intel_wait_ring_buffer(ring, rem);918if (ret)919return ret;920}921922virt = (unsigned int *)(ring->virtual_start + ring->tail);923rem /= 8;924while (rem--) {925*virt++ = MI_NOOP;926*virt++ = MI_NOOP;927}928929ring->tail = 0;930ring->space = ring_space(ring);931932return 0;933}934935int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)936{937struct drm_device *dev = ring->dev;938struct drm_i915_private *dev_priv = dev->dev_private;939unsigned long end;940u32 head;941942/* If the reported head position has wrapped or hasn't advanced,943* fallback to the slow and accurate path.944*/945head = intel_read_status_page(ring, 4);946if (head > ring->head) {947ring->head = head;948ring->space = ring_space(ring);949if (ring->space >= n)950return 0;951}952953trace_i915_ring_wait_begin(ring);954end = jiffies + 3 * HZ;955do {956ring->head = I915_READ_HEAD(ring);957ring->space = ring_space(ring);958if (ring->space >= n) {959trace_i915_ring_wait_end(ring);960return 0;961}962963if (dev->primary->master) {964struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;965if (master_priv->sarea_priv)966master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;967}968969msleep(1);970if (atomic_read(&dev_priv->mm.wedged))971return -EAGAIN;972} while (!time_after(jiffies, end));973trace_i915_ring_wait_end(ring);974return -EBUSY;975}976977int intel_ring_begin(struct intel_ring_buffer *ring,978int num_dwords)979{980struct drm_i915_private *dev_priv = ring->dev->dev_private;981int n = 4*num_dwords;982int ret;983984if (unlikely(atomic_read(&dev_priv->mm.wedged)))985return -EIO;986987if (unlikely(ring->tail + n > ring->effective_size)) {988ret = intel_wrap_ring_buffer(ring);989if (unlikely(ret))990return ret;991}992993if (unlikely(ring->space < n)) {994ret = intel_wait_ring_buffer(ring, n);995if (unlikely(ret))996return ret;997}998999ring->space -= n;1000return 0;1001}10021003void intel_ring_advance(struct intel_ring_buffer *ring)1004{1005ring->tail &= ring->size - 1;1006ring->write_tail(ring, ring->tail);1007}10081009static const struct intel_ring_buffer render_ring = {1010.name = "render ring",1011.id = RING_RENDER,1012.mmio_base = RENDER_RING_BASE,1013.size = 32 * PAGE_SIZE,1014.init = init_render_ring,1015.write_tail = ring_write_tail,1016.flush = render_ring_flush,1017.add_request = render_ring_add_request,1018.get_seqno = ring_get_seqno,1019.irq_get = render_ring_get_irq,1020.irq_put = render_ring_put_irq,1021.dispatch_execbuffer = render_ring_dispatch_execbuffer,1022.cleanup = render_ring_cleanup,1023};10241025/* ring buffer for bit-stream decoder */10261027static const struct intel_ring_buffer bsd_ring = {1028.name = "bsd ring",1029.id = RING_BSD,1030.mmio_base = BSD_RING_BASE,1031.size = 32 * PAGE_SIZE,1032.init = init_ring_common,1033.write_tail = ring_write_tail,1034.flush = bsd_ring_flush,1035.add_request = ring_add_request,1036.get_seqno = ring_get_seqno,1037.irq_get = bsd_ring_get_irq,1038.irq_put = bsd_ring_put_irq,1039.dispatch_execbuffer = ring_dispatch_execbuffer,1040};104110421043static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,1044u32 value)1045{1046drm_i915_private_t *dev_priv = ring->dev->dev_private;10471048/* Every tail move must follow the sequence below */1049I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,1050GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |1051GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);1052I915_WRITE(GEN6_BSD_RNCID, 0x0);10531054if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &1055GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,105650))1057DRM_ERROR("timed out waiting for IDLE Indicator\n");10581059I915_WRITE_TAIL(ring, value);1060I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,1061GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |1062GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);1063}10641065static int gen6_ring_flush(struct intel_ring_buffer *ring,1066u32 invalidate, u32 flush)1067{1068uint32_t cmd;1069int ret;10701071ret = intel_ring_begin(ring, 4);1072if (ret)1073return ret;10741075cmd = MI_FLUSH_DW;1076if (invalidate & I915_GEM_GPU_DOMAINS)1077cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;1078intel_ring_emit(ring, cmd);1079intel_ring_emit(ring, 0);1080intel_ring_emit(ring, 0);1081intel_ring_emit(ring, MI_NOOP);1082intel_ring_advance(ring);1083return 0;1084}10851086static int1087gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,1088u32 offset, u32 len)1089{1090int ret;10911092ret = intel_ring_begin(ring, 2);1093if (ret)1094return ret;10951096intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);1097/* bit0-7 is the length on GEN6+ */1098intel_ring_emit(ring, offset);1099intel_ring_advance(ring);11001101return 0;1102}11031104static bool1105gen6_render_ring_get_irq(struct intel_ring_buffer *ring)1106{1107return gen6_ring_get_irq(ring,1108GT_USER_INTERRUPT,1109GEN6_RENDER_USER_INTERRUPT);1110}11111112static void1113gen6_render_ring_put_irq(struct intel_ring_buffer *ring)1114{1115return gen6_ring_put_irq(ring,1116GT_USER_INTERRUPT,1117GEN6_RENDER_USER_INTERRUPT);1118}11191120static bool1121gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring)1122{1123return gen6_ring_get_irq(ring,1124GT_GEN6_BSD_USER_INTERRUPT,1125GEN6_BSD_USER_INTERRUPT);1126}11271128static void1129gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)1130{1131return gen6_ring_put_irq(ring,1132GT_GEN6_BSD_USER_INTERRUPT,1133GEN6_BSD_USER_INTERRUPT);1134}11351136/* ring buffer for Video Codec for Gen6+ */1137static const struct intel_ring_buffer gen6_bsd_ring = {1138.name = "gen6 bsd ring",1139.id = RING_BSD,1140.mmio_base = GEN6_BSD_RING_BASE,1141.size = 32 * PAGE_SIZE,1142.init = init_ring_common,1143.write_tail = gen6_bsd_ring_write_tail,1144.flush = gen6_ring_flush,1145.add_request = gen6_add_request,1146.get_seqno = ring_get_seqno,1147.irq_get = gen6_bsd_ring_get_irq,1148.irq_put = gen6_bsd_ring_put_irq,1149.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,1150};11511152/* Blitter support (SandyBridge+) */11531154static bool1155blt_ring_get_irq(struct intel_ring_buffer *ring)1156{1157return gen6_ring_get_irq(ring,1158GT_BLT_USER_INTERRUPT,1159GEN6_BLITTER_USER_INTERRUPT);1160}11611162static void1163blt_ring_put_irq(struct intel_ring_buffer *ring)1164{1165gen6_ring_put_irq(ring,1166GT_BLT_USER_INTERRUPT,1167GEN6_BLITTER_USER_INTERRUPT);1168}116911701171/* Workaround for some stepping of SNB,1172* each time when BLT engine ring tail moved,1173* the first command in the ring to be parsed1174* should be MI_BATCH_BUFFER_START1175*/1176#define NEED_BLT_WORKAROUND(dev) \1177(IS_GEN6(dev) && (dev->pdev->revision < 8))11781179static inline struct drm_i915_gem_object *1180to_blt_workaround(struct intel_ring_buffer *ring)1181{1182return ring->private;1183}11841185static int blt_ring_init(struct intel_ring_buffer *ring)1186{1187if (NEED_BLT_WORKAROUND(ring->dev)) {1188struct drm_i915_gem_object *obj;1189u32 *ptr;1190int ret;11911192obj = i915_gem_alloc_object(ring->dev, 4096);1193if (obj == NULL)1194return -ENOMEM;11951196ret = i915_gem_object_pin(obj, 4096, true);1197if (ret) {1198drm_gem_object_unreference(&obj->base);1199return ret;1200}12011202ptr = kmap(obj->pages[0]);1203*ptr++ = MI_BATCH_BUFFER_END;1204*ptr++ = MI_NOOP;1205kunmap(obj->pages[0]);12061207ret = i915_gem_object_set_to_gtt_domain(obj, false);1208if (ret) {1209i915_gem_object_unpin(obj);1210drm_gem_object_unreference(&obj->base);1211return ret;1212}12131214ring->private = obj;1215}12161217return init_ring_common(ring);1218}12191220static int blt_ring_begin(struct intel_ring_buffer *ring,1221int num_dwords)1222{1223if (ring->private) {1224int ret = intel_ring_begin(ring, num_dwords+2);1225if (ret)1226return ret;12271228intel_ring_emit(ring, MI_BATCH_BUFFER_START);1229intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset);12301231return 0;1232} else1233return intel_ring_begin(ring, 4);1234}12351236static int blt_ring_flush(struct intel_ring_buffer *ring,1237u32 invalidate, u32 flush)1238{1239uint32_t cmd;1240int ret;12411242ret = blt_ring_begin(ring, 4);1243if (ret)1244return ret;12451246cmd = MI_FLUSH_DW;1247if (invalidate & I915_GEM_DOMAIN_RENDER)1248cmd |= MI_INVALIDATE_TLB;1249intel_ring_emit(ring, cmd);1250intel_ring_emit(ring, 0);1251intel_ring_emit(ring, 0);1252intel_ring_emit(ring, MI_NOOP);1253intel_ring_advance(ring);1254return 0;1255}12561257static void blt_ring_cleanup(struct intel_ring_buffer *ring)1258{1259if (!ring->private)1260return;12611262i915_gem_object_unpin(ring->private);1263drm_gem_object_unreference(ring->private);1264ring->private = NULL;1265}12661267static const struct intel_ring_buffer gen6_blt_ring = {1268.name = "blt ring",1269.id = RING_BLT,1270.mmio_base = BLT_RING_BASE,1271.size = 32 * PAGE_SIZE,1272.init = blt_ring_init,1273.write_tail = ring_write_tail,1274.flush = blt_ring_flush,1275.add_request = gen6_add_request,1276.get_seqno = ring_get_seqno,1277.irq_get = blt_ring_get_irq,1278.irq_put = blt_ring_put_irq,1279.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,1280.cleanup = blt_ring_cleanup,1281};12821283int intel_init_render_ring_buffer(struct drm_device *dev)1284{1285drm_i915_private_t *dev_priv = dev->dev_private;1286struct intel_ring_buffer *ring = &dev_priv->ring[RCS];12871288*ring = render_ring;1289if (INTEL_INFO(dev)->gen >= 6) {1290ring->add_request = gen6_add_request;1291ring->irq_get = gen6_render_ring_get_irq;1292ring->irq_put = gen6_render_ring_put_irq;1293} else if (IS_GEN5(dev)) {1294ring->add_request = pc_render_add_request;1295ring->get_seqno = pc_render_get_seqno;1296}12971298if (!I915_NEED_GFX_HWS(dev)) {1299ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;1300memset(ring->status_page.page_addr, 0, PAGE_SIZE);1301}13021303return intel_init_ring_buffer(dev, ring);1304}13051306int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)1307{1308drm_i915_private_t *dev_priv = dev->dev_private;1309struct intel_ring_buffer *ring = &dev_priv->ring[RCS];13101311*ring = render_ring;1312if (INTEL_INFO(dev)->gen >= 6) {1313ring->add_request = gen6_add_request;1314ring->irq_get = gen6_render_ring_get_irq;1315ring->irq_put = gen6_render_ring_put_irq;1316} else if (IS_GEN5(dev)) {1317ring->add_request = pc_render_add_request;1318ring->get_seqno = pc_render_get_seqno;1319}13201321ring->dev = dev;1322INIT_LIST_HEAD(&ring->active_list);1323INIT_LIST_HEAD(&ring->request_list);1324INIT_LIST_HEAD(&ring->gpu_write_list);13251326ring->size = size;1327ring->effective_size = ring->size;1328if (IS_I830(ring->dev))1329ring->effective_size -= 128;13301331ring->map.offset = start;1332ring->map.size = size;1333ring->map.type = 0;1334ring->map.flags = 0;1335ring->map.mtrr = 0;13361337drm_core_ioremap_wc(&ring->map, dev);1338if (ring->map.handle == NULL) {1339DRM_ERROR("can not ioremap virtual address for"1340" ring buffer\n");1341return -ENOMEM;1342}13431344ring->virtual_start = (void __force __iomem *)ring->map.handle;1345return 0;1346}13471348int intel_init_bsd_ring_buffer(struct drm_device *dev)1349{1350drm_i915_private_t *dev_priv = dev->dev_private;1351struct intel_ring_buffer *ring = &dev_priv->ring[VCS];13521353if (IS_GEN6(dev) || IS_GEN7(dev))1354*ring = gen6_bsd_ring;1355else1356*ring = bsd_ring;13571358return intel_init_ring_buffer(dev, ring);1359}13601361int intel_init_blt_ring_buffer(struct drm_device *dev)1362{1363drm_i915_private_t *dev_priv = dev->dev_private;1364struct intel_ring_buffer *ring = &dev_priv->ring[BCS];13651366*ring = gen6_blt_ring;13671368return intel_init_ring_buffer(dev, ring);1369}137013711372