18c2ecf20Sopenharmony_ci/**************************************************************************
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
48c2ecf20Sopenharmony_ci * All Rights Reserved.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the
88c2ecf20Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
98c2ecf20Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
108c2ecf20Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
118c2ecf20Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
128c2ecf20Sopenharmony_ci * the following conditions:
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the
158c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
168c2ecf20Sopenharmony_ci * of the Software.
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
198c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
208c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
218c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
228c2ecf20Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
238c2ecf20Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
248c2ecf20Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci **************************************************************************/
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/*
308c2ecf20Sopenharmony_ci * Authors:
318c2ecf20Sopenharmony_ci *    Thomas Hellström <thomas-at-tungstengraphics-dot-com>
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include <video/sisfb.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <drm/drm_device.h>
378c2ecf20Sopenharmony_ci#include <drm/drm_file.h>
388c2ecf20Sopenharmony_ci#include <drm/sis_drm.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#include "sis_drv.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define VIDEO_TYPE 0
448c2ecf20Sopenharmony_ci#define AGP_TYPE 1
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistruct sis_memblock {
488c2ecf20Sopenharmony_ci	struct drm_mm_node mm_node;
498c2ecf20Sopenharmony_ci	struct sis_memreq req;
508c2ecf20Sopenharmony_ci	struct list_head owner_list;
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
548c2ecf20Sopenharmony_ci/* fb management via fb device */
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define SIS_MM_ALIGN_SHIFT 0
578c2ecf20Sopenharmony_ci#define SIS_MM_ALIGN_MASK 0
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#else /* CONFIG_FB_SIS[_MODULE] */
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define SIS_MM_ALIGN_SHIFT 4
628c2ecf20Sopenharmony_ci#define SIS_MM_ALIGN_MASK ((1 << SIS_MM_ALIGN_SHIFT) - 1)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#endif /* CONFIG_FB_SIS[_MODULE] */
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	drm_sis_private_t *dev_priv = dev->dev_private;
698c2ecf20Sopenharmony_ci	drm_sis_fb_t *fb = data;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	mutex_lock(&dev->struct_mutex);
728c2ecf20Sopenharmony_ci	/* Unconditionally init the drm_mm, even though we don't use it when the
738c2ecf20Sopenharmony_ci	 * fb sis driver is available - make cleanup easier. */
748c2ecf20Sopenharmony_ci	drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> SIS_MM_ALIGN_SHIFT);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	dev_priv->vram_initialized = 1;
778c2ecf20Sopenharmony_ci	dev_priv->vram_offset = fb->offset;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	mutex_unlock(&dev->struct_mutex);
808c2ecf20Sopenharmony_ci	DRM_DEBUG("offset = %lu, size = %lu\n", fb->offset, fb->size);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	return 0;
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
868c2ecf20Sopenharmony_ci			 void *data, int pool)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	drm_sis_private_t *dev_priv = dev->dev_private;
898c2ecf20Sopenharmony_ci	drm_sis_mem_t *mem = data;
908c2ecf20Sopenharmony_ci	int retval = 0, user_key;
918c2ecf20Sopenharmony_ci	struct sis_memblock *item;
928c2ecf20Sopenharmony_ci	struct sis_file_private *file_priv = file->driver_priv;
938c2ecf20Sopenharmony_ci	unsigned long offset;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	mutex_lock(&dev->struct_mutex);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	if (0 == ((pool == 0) ? dev_priv->vram_initialized :
988c2ecf20Sopenharmony_ci		      dev_priv->agp_initialized)) {
998c2ecf20Sopenharmony_ci		DRM_ERROR
1008c2ecf20Sopenharmony_ci		    ("Attempt to allocate from uninitialized memory manager.\n");
1018c2ecf20Sopenharmony_ci		mutex_unlock(&dev->struct_mutex);
1028c2ecf20Sopenharmony_ci		return -EINVAL;
1038c2ecf20Sopenharmony_ci	}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	item = kzalloc(sizeof(*item), GFP_KERNEL);
1068c2ecf20Sopenharmony_ci	if (!item) {
1078c2ecf20Sopenharmony_ci		retval = -ENOMEM;
1088c2ecf20Sopenharmony_ci		goto fail_alloc;
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
1128c2ecf20Sopenharmony_ci	if (pool == AGP_TYPE) {
1138c2ecf20Sopenharmony_ci		retval = drm_mm_insert_node(&dev_priv->agp_mm,
1148c2ecf20Sopenharmony_ci					    &item->mm_node,
1158c2ecf20Sopenharmony_ci					    mem->size);
1168c2ecf20Sopenharmony_ci		offset = item->mm_node.start;
1178c2ecf20Sopenharmony_ci	} else {
1188c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
1198c2ecf20Sopenharmony_ci		item->req.size = mem->size;
1208c2ecf20Sopenharmony_ci		sis_malloc(&item->req);
1218c2ecf20Sopenharmony_ci		if (item->req.size == 0)
1228c2ecf20Sopenharmony_ci			retval = -ENOMEM;
1238c2ecf20Sopenharmony_ci		offset = item->req.offset;
1248c2ecf20Sopenharmony_ci#else
1258c2ecf20Sopenharmony_ci		retval = drm_mm_insert_node(&dev_priv->vram_mm,
1268c2ecf20Sopenharmony_ci					    &item->mm_node,
1278c2ecf20Sopenharmony_ci					    mem->size);
1288c2ecf20Sopenharmony_ci		offset = item->mm_node.start;
1298c2ecf20Sopenharmony_ci#endif
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci	if (retval)
1328c2ecf20Sopenharmony_ci		goto fail_alloc;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
1358c2ecf20Sopenharmony_ci	if (retval < 0)
1368c2ecf20Sopenharmony_ci		goto fail_idr;
1378c2ecf20Sopenharmony_ci	user_key = retval;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	list_add(&item->owner_list, &file_priv->obj_list);
1408c2ecf20Sopenharmony_ci	mutex_unlock(&dev->struct_mutex);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	mem->offset = ((pool == 0) ?
1438c2ecf20Sopenharmony_ci		      dev_priv->vram_offset : dev_priv->agp_offset) +
1448c2ecf20Sopenharmony_ci	    (offset << SIS_MM_ALIGN_SHIFT);
1458c2ecf20Sopenharmony_ci	mem->free = user_key;
1468c2ecf20Sopenharmony_ci	mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	return 0;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cifail_idr:
1518c2ecf20Sopenharmony_ci	drm_mm_remove_node(&item->mm_node);
1528c2ecf20Sopenharmony_cifail_alloc:
1538c2ecf20Sopenharmony_ci	kfree(item);
1548c2ecf20Sopenharmony_ci	mutex_unlock(&dev->struct_mutex);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	mem->offset = 0;
1578c2ecf20Sopenharmony_ci	mem->size = 0;
1588c2ecf20Sopenharmony_ci	mem->free = 0;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	DRM_DEBUG("alloc %d, size = %ld, offset = %ld\n", pool, mem->size,
1618c2ecf20Sopenharmony_ci		  mem->offset);
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	return retval;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	drm_sis_private_t *dev_priv = dev->dev_private;
1698c2ecf20Sopenharmony_ci	drm_sis_mem_t *mem = data;
1708c2ecf20Sopenharmony_ci	struct sis_memblock *obj;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	mutex_lock(&dev->struct_mutex);
1738c2ecf20Sopenharmony_ci	obj = idr_find(&dev_priv->object_idr, mem->free);
1748c2ecf20Sopenharmony_ci	if (obj == NULL) {
1758c2ecf20Sopenharmony_ci		mutex_unlock(&dev->struct_mutex);
1768c2ecf20Sopenharmony_ci		return -EINVAL;
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	idr_remove(&dev_priv->object_idr, mem->free);
1808c2ecf20Sopenharmony_ci	list_del(&obj->owner_list);
1818c2ecf20Sopenharmony_ci	if (drm_mm_node_allocated(&obj->mm_node))
1828c2ecf20Sopenharmony_ci		drm_mm_remove_node(&obj->mm_node);
1838c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
1848c2ecf20Sopenharmony_ci	else
1858c2ecf20Sopenharmony_ci		sis_free(obj->req.offset);
1868c2ecf20Sopenharmony_ci#endif
1878c2ecf20Sopenharmony_ci	kfree(obj);
1888c2ecf20Sopenharmony_ci	mutex_unlock(&dev->struct_mutex);
1898c2ecf20Sopenharmony_ci	DRM_DEBUG("free = 0x%lx\n", mem->free);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	return 0;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic int sis_fb_alloc(struct drm_device *dev, void *data,
1958c2ecf20Sopenharmony_ci			struct drm_file *file_priv)
1968c2ecf20Sopenharmony_ci{
1978c2ecf20Sopenharmony_ci	return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic int sis_ioctl_agp_init(struct drm_device *dev, void *data,
2018c2ecf20Sopenharmony_ci			      struct drm_file *file_priv)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	drm_sis_private_t *dev_priv = dev->dev_private;
2048c2ecf20Sopenharmony_ci	drm_sis_agp_t *agp = data;
2058c2ecf20Sopenharmony_ci	dev_priv = dev->dev_private;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	mutex_lock(&dev->struct_mutex);
2088c2ecf20Sopenharmony_ci	drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> SIS_MM_ALIGN_SHIFT);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	dev_priv->agp_initialized = 1;
2118c2ecf20Sopenharmony_ci	dev_priv->agp_offset = agp->offset;
2128c2ecf20Sopenharmony_ci	mutex_unlock(&dev->struct_mutex);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	DRM_DEBUG("offset = %lu, size = %lu\n", agp->offset, agp->size);
2158c2ecf20Sopenharmony_ci	return 0;
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_cistatic int sis_ioctl_agp_alloc(struct drm_device *dev, void *data,
2198c2ecf20Sopenharmony_ci			       struct drm_file *file_priv)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	return sis_drm_alloc(dev, file_priv, data, AGP_TYPE);
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic drm_local_map_t *sis_reg_init(struct drm_device *dev)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	struct drm_map_list *entry;
2288c2ecf20Sopenharmony_ci	drm_local_map_t *map;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	list_for_each_entry(entry, &dev->maplist, head) {
2318c2ecf20Sopenharmony_ci		map = entry->map;
2328c2ecf20Sopenharmony_ci		if (!map)
2338c2ecf20Sopenharmony_ci			continue;
2348c2ecf20Sopenharmony_ci		if (map->type == _DRM_REGISTERS)
2358c2ecf20Sopenharmony_ci			return map;
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci	return NULL;
2388c2ecf20Sopenharmony_ci}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ciint sis_idle(struct drm_device *dev)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	drm_sis_private_t *dev_priv = dev->dev_private;
2438c2ecf20Sopenharmony_ci	uint32_t idle_reg;
2448c2ecf20Sopenharmony_ci	unsigned long end;
2458c2ecf20Sopenharmony_ci	int i;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (dev_priv->idle_fault)
2488c2ecf20Sopenharmony_ci		return 0;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (dev_priv->mmio == NULL) {
2518c2ecf20Sopenharmony_ci		dev_priv->mmio = sis_reg_init(dev);
2528c2ecf20Sopenharmony_ci		if (dev_priv->mmio == NULL) {
2538c2ecf20Sopenharmony_ci			DRM_ERROR("Could not find register map.\n");
2548c2ecf20Sopenharmony_ci			return 0;
2558c2ecf20Sopenharmony_ci		}
2568c2ecf20Sopenharmony_ci	}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	/*
2598c2ecf20Sopenharmony_ci	 * Implement a device switch here if needed
2608c2ecf20Sopenharmony_ci	 */
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	if (dev_priv->chipset != SIS_CHIP_315)
2638c2ecf20Sopenharmony_ci		return 0;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	/*
2668c2ecf20Sopenharmony_ci	 * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
2678c2ecf20Sopenharmony_ci	 * because its polling frequency is too low.
2688c2ecf20Sopenharmony_ci	 */
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	end = jiffies + (HZ * 3);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	for (i = 0; i < 4; ++i) {
2738c2ecf20Sopenharmony_ci		do {
2748c2ecf20Sopenharmony_ci			idle_reg = SIS_READ(0x85cc);
2758c2ecf20Sopenharmony_ci		} while (!time_after_eq(jiffies, end) &&
2768c2ecf20Sopenharmony_ci			  ((idle_reg & 0x80000000) != 0x80000000));
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	if (time_after_eq(jiffies, end)) {
2808c2ecf20Sopenharmony_ci		DRM_ERROR("Graphics engine idle timeout. "
2818c2ecf20Sopenharmony_ci			  "Disabling idle check\n");
2828c2ecf20Sopenharmony_ci		dev_priv->idle_fault = 1;
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	/*
2868c2ecf20Sopenharmony_ci	 * The caller never sees an error code. It gets trapped
2878c2ecf20Sopenharmony_ci	 * in libdrm.
2888c2ecf20Sopenharmony_ci	 */
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	return 0;
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_civoid sis_lastclose(struct drm_device *dev)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	drm_sis_private_t *dev_priv = dev->dev_private;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	if (!dev_priv)
2998c2ecf20Sopenharmony_ci		return;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	mutex_lock(&dev->struct_mutex);
3028c2ecf20Sopenharmony_ci	if (dev_priv->vram_initialized) {
3038c2ecf20Sopenharmony_ci		drm_mm_takedown(&dev_priv->vram_mm);
3048c2ecf20Sopenharmony_ci		dev_priv->vram_initialized = 0;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci	if (dev_priv->agp_initialized) {
3078c2ecf20Sopenharmony_ci		drm_mm_takedown(&dev_priv->agp_mm);
3088c2ecf20Sopenharmony_ci		dev_priv->agp_initialized = 0;
3098c2ecf20Sopenharmony_ci	}
3108c2ecf20Sopenharmony_ci	dev_priv->mmio = NULL;
3118c2ecf20Sopenharmony_ci	mutex_unlock(&dev->struct_mutex);
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_civoid sis_reclaim_buffers_locked(struct drm_device *dev,
3158c2ecf20Sopenharmony_ci				struct drm_file *file)
3168c2ecf20Sopenharmony_ci{
3178c2ecf20Sopenharmony_ci	struct sis_file_private *file_priv = file->driver_priv;
3188c2ecf20Sopenharmony_ci	struct sis_memblock *entry, *next;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	if (!(dev->master && file->master->lock.hw_lock))
3218c2ecf20Sopenharmony_ci		return;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	drm_legacy_idlelock_take(&file->master->lock);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	mutex_lock(&dev->struct_mutex);
3268c2ecf20Sopenharmony_ci	if (list_empty(&file_priv->obj_list)) {
3278c2ecf20Sopenharmony_ci		mutex_unlock(&dev->struct_mutex);
3288c2ecf20Sopenharmony_ci		drm_legacy_idlelock_release(&file->master->lock);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		return;
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	sis_idle(dev);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	list_for_each_entry_safe(entry, next, &file_priv->obj_list,
3378c2ecf20Sopenharmony_ci				 owner_list) {
3388c2ecf20Sopenharmony_ci		list_del(&entry->owner_list);
3398c2ecf20Sopenharmony_ci		if (drm_mm_node_allocated(&entry->mm_node))
3408c2ecf20Sopenharmony_ci			drm_mm_remove_node(&entry->mm_node);
3418c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
3428c2ecf20Sopenharmony_ci		else
3438c2ecf20Sopenharmony_ci			sis_free(entry->req.offset);
3448c2ecf20Sopenharmony_ci#endif
3458c2ecf20Sopenharmony_ci		kfree(entry);
3468c2ecf20Sopenharmony_ci	}
3478c2ecf20Sopenharmony_ci	mutex_unlock(&dev->struct_mutex);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	drm_legacy_idlelock_release(&file->master->lock);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	return;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ciconst struct drm_ioctl_desc sis_ioctls[] = {
3558c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
3568c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(SIS_FB_FREE, sis_drm_free, DRM_AUTH),
3578c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
3588c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
3598c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
3608c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
3618c2ecf20Sopenharmony_ci};
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ciint sis_max_ioctl = ARRAY_SIZE(sis_ioctls);
364