diff options
| author | Dave Airlie <airlied@redhat.com> | 2013-05-03 10:13:08 +1000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2013-05-03 10:13:08 +1000 | 
| commit | d2dbaaf6265d292575bfe41bf668b0cab759e19c (patch) | |
| tree | 255a26df4d499798d0af62d43773594ca2cd0ad7 /drivers/gpu | |
| parent | 7e17fc0b69fbec2c25398adfb18a18fa6b210a53 (diff) | |
| parent | f3b2bbdc8a87a080ccd23d27fca4b87d61340dd4 (diff) | |
| download | olio-linux-3.10-d2dbaaf6265d292575bfe41bf668b0cab759e19c.tar.xz olio-linux-3.10-d2dbaaf6265d292575bfe41bf668b0cab759e19c.zip  | |
Merge branch 'server-fixes' into drm-next
Merge the fixes for the server driver dirty update paths
* server-fixes:
  drm/cirrus: deal with bo reserve fail in dirty update path
  drm/ast: deal with bo reserve fail in dirty update path
  drm/mgag200: deal with bo reserve fail in dirty update path
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/ast/ast_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_fb.c | 43 | ||||
| -rw-r--r-- | drivers/gpu/drm/ast/ast_ttm.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_fbdev.c | 38 | ||||
| -rw-r--r-- | drivers/gpu/drm/cirrus/cirrus_ttm.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_fb.c | 43 | ||||
| -rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_ttm.c | 4 | 
9 files changed, 127 insertions, 11 deletions
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 528429252f0..02e52d543e4 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -241,6 +241,8 @@ struct ast_fbdev {  	void *sysram;  	int size;  	struct ttm_bo_kmap_obj mapping; +	int x1, y1, x2, y2; /* dirty rect */ +	spinlock_t dirty_lock;  };  #define to_ast_crtc(x) container_of(x, struct ast_crtc, base) diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 34931fe7d2c..fbc0823cfa1 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -53,16 +53,52 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,  	int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8;  	int ret;  	bool unmap = false; +	bool store_for_later = false; +	int x2, y2; +	unsigned long flags;  	obj = afbdev->afb.obj;  	bo = gem_to_ast_bo(obj); +	/* +	 * try and reserve the BO, if we fail with busy +	 * then the BO is being moved and we should +	 * store up the damage until later. +	 */  	ret = ast_bo_reserve(bo, true);  	if (ret) { -		DRM_ERROR("failed to reserve fb bo\n"); +		if (ret != -EBUSY) +			return; + +		store_for_later = true; +	} + +	x2 = x + width - 1; +	y2 = y + height - 1; +	spin_lock_irqsave(&afbdev->dirty_lock, flags); + +	if (afbdev->y1 < y) +		y = afbdev->y1; +	if (afbdev->y2 > y2) +		y2 = afbdev->y2; +	if (afbdev->x1 < x) +		x = afbdev->x1; +	if (afbdev->x2 > x2) +		x2 = afbdev->x2; + +	if (store_for_later) { +		afbdev->x1 = x; +		afbdev->x2 = x2; +		afbdev->y1 = y; +		afbdev->y2 = y2; +		spin_unlock_irqrestore(&afbdev->dirty_lock, flags);  		return;  	} +	afbdev->x1 = afbdev->y1 = INT_MAX; +	afbdev->x2 = afbdev->y2 = 0; +	spin_unlock_irqrestore(&afbdev->dirty_lock, flags); +  	if (!bo->kmap.virtual) {  		ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);  		if (ret) { @@ -72,10 +108,10 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,  		}  		unmap = true;  	} -	for (i = y; i < y + height; i++) { +	for (i = y; i <= y2; i++) {  		/* assume equal stride for now */  		src_offset = dst_offset = i * afbdev->afb.base.pitches[0] + (x * bpp); -		memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp); +		memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, (x2 - x + 1) * bpp);  	}  	if (unmap) @@ -292,6 +328,7 @@ int ast_fbdev_init(struct drm_device *dev)  	ast->fbdev = afbdev;  	afbdev->helper.funcs = &ast_fb_helper_funcs; +	spin_lock_init(&afbdev->dirty_lock);  	ret = drm_fb_helper_init(dev, &afbdev->helper,  				 1, 1);  	if (ret) { diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 3602731a611..09da3393c52 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c @@ -316,7 +316,7 @@ int ast_bo_reserve(struct ast_bo *bo, bool no_wait)  	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);  	if (ret) { -		if (ret != -ERESTARTSYS) +		if (ret != -ERESTARTSYS && ret != -EBUSY)  			DRM_ERROR("reserve failed %p\n", bo);  		return ret;  	} diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index 6e0cc724e5a..7ca05959688 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -154,6 +154,8 @@ struct cirrus_fbdev {  	struct list_head fbdev_list;  	void *sysram;  	int size; +	int x1, y1, x2, y2; /* dirty rect */ +	spinlock_t dirty_lock;  };  struct cirrus_bo { diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index e25afccaf85..3541b567bbd 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -27,16 +27,51 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,  	int bpp = (afbdev->gfb.base.bits_per_pixel + 7)/8;  	int ret;  	bool unmap = false; +	bool store_for_later = false; +	int x2, y2; +	unsigned long flags;  	obj = afbdev->gfb.obj;  	bo = gem_to_cirrus_bo(obj); +	/* +	 * try and reserve the BO, if we fail with busy +	 * then the BO is being moved and we should +	 * store up the damage until later. +	 */  	ret = cirrus_bo_reserve(bo, true);  	if (ret) { -		DRM_ERROR("failed to reserve fb bo\n"); +		if (ret != -EBUSY) +			return; +		store_for_later = true; +	} + +	x2 = x + width - 1; +	y2 = y + height - 1; +	spin_lock_irqsave(&afbdev->dirty_lock, flags); + +	if (afbdev->y1 < y) +		y = afbdev->y1; +	if (afbdev->y2 > y2) +		y2 = afbdev->y2; +	if (afbdev->x1 < x) +		x = afbdev->x1; +	if (afbdev->x2 > x2) +		x2 = afbdev->x2; + +	if (store_for_later) { +		afbdev->x1 = x; +		afbdev->x2 = x2; +		afbdev->y1 = y; +		afbdev->y2 = y2; +		spin_unlock_irqrestore(&afbdev->dirty_lock, flags);  		return;  	} +	afbdev->x1 = afbdev->y1 = INT_MAX; +	afbdev->x2 = afbdev->y2 = 0; +	spin_unlock_irqrestore(&afbdev->dirty_lock, flags); +  	if (!bo->kmap.virtual) {  		ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);  		if (ret) { @@ -268,6 +303,7 @@ int cirrus_fbdev_init(struct cirrus_device *cdev)  	cdev->mode_info.gfbdev = gfbdev;  	gfbdev->helper.funcs = &cirrus_fb_helper_funcs; +	spin_lock_init(&gfbdev->dirty_lock);  	ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,  				 cdev->num_crtc, CIRRUSFB_CONN_LIMIT); diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c index 1413a26e490..2ed8cfc740c 100644 --- a/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -321,7 +321,7 @@ int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)  	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);  	if (ret) { -		if (ret != -ERESTARTSYS) +		if (ret != -ERESTARTSYS && ret != -EBUSY)  			DRM_ERROR("reserve failed %p\n", bo);  		return ret;  	} diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index dcfc973e29f..bf29b2f4d68 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -115,6 +115,8 @@ struct mga_fbdev {  	void *sysram;  	int size;  	struct ttm_bo_kmap_obj mapping; +	int x1, y1, x2, y2; /* dirty rect */ +	spinlock_t dirty_lock;  };  struct mga_crtc { diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 421beabec45..5da824ce9ba 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -29,16 +29,52 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,  	int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8;  	int ret;  	bool unmap = false; +	bool store_for_later = false; +	int x2, y2; +	unsigned long flags;  	obj = mfbdev->mfb.obj;  	bo = gem_to_mga_bo(obj); +	/* +	 * try and reserve the BO, if we fail with busy +	 * then the BO is being moved and we should +	 * store up the damage until later. +	 */  	ret = mgag200_bo_reserve(bo, true);  	if (ret) { -		DRM_ERROR("failed to reserve fb bo\n"); +		if (ret != -EBUSY) +			return; + +		store_for_later = true; +	} + +	x2 = x + width - 1; +	y2 = y + height - 1; +	spin_lock_irqsave(&mfbdev->dirty_lock, flags); + +	if (mfbdev->y1 < y) +		y = mfbdev->y1; +	if (mfbdev->y2 > y2) +		y2 = mfbdev->y2; +	if (mfbdev->x1 < x) +		x = mfbdev->x1; +	if (mfbdev->x2 > x2) +		x2 = mfbdev->x2; + +	if (store_for_later) { +		mfbdev->x1 = x; +		mfbdev->x2 = x2; +		mfbdev->y1 = y; +		mfbdev->y2 = y2; +		spin_unlock_irqrestore(&mfbdev->dirty_lock, flags);  		return;  	} +	mfbdev->x1 = mfbdev->y1 = INT_MAX; +	mfbdev->x2 = mfbdev->y2 = 0; +	spin_unlock_irqrestore(&mfbdev->dirty_lock, flags); +  	if (!bo->kmap.virtual) {  		ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);  		if (ret) { @@ -48,10 +84,10 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev,  		}  		unmap = true;  	} -	for (i = y; i < y + height; i++) { +	for (i = y; i <= y2; i++) {  		/* assume equal stride for now */  		src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp); -		memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, width * bpp); +		memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp);  	}  	if (unmap) @@ -252,6 +288,7 @@ int mgag200_fbdev_init(struct mga_device *mdev)  	mdev->mfbdev = mfbdev;  	mfbdev->helper.funcs = &mga_fb_helper_funcs; +	spin_lock_init(&mfbdev->dirty_lock);  	ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,  				 mdev->num_crtc, MGAG200FB_CONN_LIMIT); diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index 8fc9d920194..401c9891d3a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c @@ -315,8 +315,8 @@ int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)  	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);  	if (ret) { -		if (ret != -ERESTARTSYS) -			DRM_ERROR("reserve failed %p\n", bo); +		if (ret != -ERESTARTSYS && ret != -EBUSY) +			DRM_ERROR("reserve failed %p %d\n", bo, ret);  		return ret;  	}  	return 0;  |