1771fe6b9SJerome Glisse /*
2771fe6b9SJerome Glisse  * Copyright 2008 Advanced Micro Devices, Inc.
3771fe6b9SJerome Glisse  * Copyright 2008 Red Hat Inc.
4771fe6b9SJerome Glisse  * Copyright 2009 Jerome Glisse.
5771fe6b9SJerome Glisse  *
6771fe6b9SJerome Glisse  * Permission is hereby granted, free of charge, to any person obtaining a
7771fe6b9SJerome Glisse  * copy of this software and associated documentation files (the "Software"),
8771fe6b9SJerome Glisse  * to deal in the Software without restriction, including without limitation
9771fe6b9SJerome Glisse  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10771fe6b9SJerome Glisse  * and/or sell copies of the Software, and to permit persons to whom the
11771fe6b9SJerome Glisse  * Software is furnished to do so, subject to the following conditions:
12771fe6b9SJerome Glisse  *
13771fe6b9SJerome Glisse  * The above copyright notice and this permission notice shall be included in
14771fe6b9SJerome Glisse  * all copies or substantial portions of the Software.
15771fe6b9SJerome Glisse  *
16771fe6b9SJerome Glisse  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17771fe6b9SJerome Glisse  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18771fe6b9SJerome Glisse  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19771fe6b9SJerome Glisse  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20771fe6b9SJerome Glisse  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21771fe6b9SJerome Glisse  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22771fe6b9SJerome Glisse  * OTHER DEALINGS IN THE SOFTWARE.
23771fe6b9SJerome Glisse  *
24771fe6b9SJerome Glisse  * Authors: Dave Airlie
25771fe6b9SJerome Glisse  *          Alex Deucher
26771fe6b9SJerome Glisse  *          Jerome Glisse
27771fe6b9SJerome Glisse  */
28771fe6b9SJerome Glisse 
292ef79416SThomas Zimmermann #include <linux/pci.h>
3010ebc0bcSDave Airlie #include <linux/pm_runtime.h>
31f9183127SSam Ravnborg #include <linux/slab.h>
32f9183127SSam Ravnborg #include <linux/uaccess.h>
33f9183127SSam Ravnborg #include <linux/vga_switcheroo.h>
34f9183127SSam Ravnborg 
35f9183127SSam Ravnborg #include <drm/drm_file.h>
36f9183127SSam Ravnborg #include <drm/drm_ioctl.h>
37f9183127SSam Ravnborg #include <drm/radeon_drm.h>
38f9183127SSam Ravnborg 
39f9183127SSam Ravnborg #include "radeon.h"
40f9183127SSam Ravnborg #include "radeon_asic.h"
419c69e42eSLee Jones #include "radeon_drv.h"
4259718dbfSLee Jones #include "radeon_kms.h"
4378488659SAlex Deucher 
4478488659SAlex Deucher #if defined(CONFIG_VGA_SWITCHEROO)
4590c4cde9SAlex Deucher bool radeon_has_atpx(void);
4678488659SAlex Deucher #else
radeon_has_atpx(void)4790c4cde9SAlex Deucher static inline bool radeon_has_atpx(void) { return false; }
4878488659SAlex Deucher #endif
4978488659SAlex Deucher 
50f482a141SAlex Deucher /**
51f482a141SAlex Deucher  * radeon_driver_unload_kms - Main unload function for KMS.
52f482a141SAlex Deucher  *
53f482a141SAlex Deucher  * @dev: drm dev pointer
54f482a141SAlex Deucher  *
55f482a141SAlex Deucher  * This is the main unload function for KMS (all asics).
56f482a141SAlex Deucher  * It calls radeon_modeset_fini() to tear down the
57f482a141SAlex Deucher  * displays, and radeon_device_fini() to tear down
58f482a141SAlex Deucher  * the rest of the device (CP, writeback, etc.).
59f482a141SAlex Deucher  * Returns 0 on success.
60f482a141SAlex Deucher  */
radeon_driver_unload_kms(struct drm_device * dev)6111b3c20bSGabriel Krisman Bertazi void radeon_driver_unload_kms(struct drm_device *dev)
62cf0fe456SJerome Glisse {
63cf0fe456SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
64771fe6b9SJerome Glisse 
65cf0fe456SJerome Glisse 	if (rdev == NULL)
6611b3c20bSGabriel Krisman Bertazi 		return;
6710ebc0bcSDave Airlie 
680cd9cb76SAlex Deucher 	if (rdev->rmmio == NULL)
690cd9cb76SAlex Deucher 		goto done_free;
7010ebc0bcSDave Airlie 
7119de659cSLukas Wunner 	if (radeon_is_px(dev)) {
7210ebc0bcSDave Airlie 		pm_runtime_get_sync(dev->dev);
738fecb6a9SLukas Wunner 		pm_runtime_forbid(dev->dev);
7419de659cSLukas Wunner 	}
7510ebc0bcSDave Airlie 
76c4917074SAlex Deucher 	radeon_acpi_fini(rdev);
7710ebc0bcSDave Airlie 
78cf0fe456SJerome Glisse 	radeon_modeset_fini(rdev);
79cf0fe456SJerome Glisse 	radeon_device_fini(rdev);
800cd9cb76SAlex Deucher 
8143359786SThomas Zimmermann 	if (rdev->agp)
8243359786SThomas Zimmermann 		arch_phys_wc_del(rdev->agp->agp_mtrr);
8343359786SThomas Zimmermann 	kfree(rdev->agp);
8443359786SThomas Zimmermann 	rdev->agp = NULL;
85b8076b5eSDaniel Vetter 
860cd9cb76SAlex Deucher done_free:
87cf0fe456SJerome Glisse 	kfree(rdev);
88cf0fe456SJerome Glisse 	dev->dev_private = NULL;
89cf0fe456SJerome Glisse }
90cf0fe456SJerome Glisse 
91f482a141SAlex Deucher /**
92f482a141SAlex Deucher  * radeon_driver_load_kms - Main load function for KMS.
93f482a141SAlex Deucher  *
94f482a141SAlex Deucher  * @dev: drm dev pointer
95f482a141SAlex Deucher  * @flags: device flags
96f482a141SAlex Deucher  *
97f482a141SAlex Deucher  * This is the main load function for KMS (all asics).
98f482a141SAlex Deucher  * It calls radeon_device_init() to set up the non-display
99f482a141SAlex Deucher  * parts of the chip (asic init, CP, writeback, etc.), and
100f482a141SAlex Deucher  * radeon_modeset_init() to set up the display parts
101f482a141SAlex Deucher  * (crtcs, encoders, hotplug detect, etc.).
102f482a141SAlex Deucher  * Returns 0 on success, error on failure.
103f482a141SAlex Deucher  */
radeon_driver_load_kms(struct drm_device * dev,unsigned long flags)104771fe6b9SJerome Glisse int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
105771fe6b9SJerome Glisse {
106d86a4126SThomas Zimmermann 	struct pci_dev *pdev = to_pci_dev(dev->dev);
107771fe6b9SJerome Glisse 	struct radeon_device *rdev;
108d7a2952fSAlberto Milone 	int r, acpi_status;
109771fe6b9SJerome Glisse 
110771fe6b9SJerome Glisse 	rdev = kzalloc(sizeof(struct radeon_device), GFP_KERNEL);
111771fe6b9SJerome Glisse 	if (rdev == NULL) {
112771fe6b9SJerome Glisse 		return -ENOMEM;
113771fe6b9SJerome Glisse 	}
114771fe6b9SJerome Glisse 	dev->dev_private = (void *)rdev;
115771fe6b9SJerome Glisse 
1165c1736cfSThomas Zimmermann #ifdef __alpha__
1175c1736cfSThomas Zimmermann 	rdev->hose = pdev->sysdata;
1185c1736cfSThomas Zimmermann #endif
1195c1736cfSThomas Zimmermann 
12043359786SThomas Zimmermann 	if (pci_find_capability(pdev, PCI_CAP_ID_AGP))
12193def70cSNirmoy Das 		rdev->agp = radeon_agp_head_init(dev);
12243359786SThomas Zimmermann 	if (rdev->agp) {
12343359786SThomas Zimmermann 		rdev->agp->agp_mtrr = arch_phys_wc_add(
12443359786SThomas Zimmermann 			rdev->agp->agp_info.aper_base,
12543359786SThomas Zimmermann 			rdev->agp->agp_info.aper_size *
12643359786SThomas Zimmermann 			1024 * 1024);
12743359786SThomas Zimmermann 	}
12843359786SThomas Zimmermann 
129771fe6b9SJerome Glisse 	/* update BUS flag */
130d86a4126SThomas Zimmermann 	if (pci_find_capability(pdev, PCI_CAP_ID_AGP)) {
131771fe6b9SJerome Glisse 		flags |= RADEON_IS_AGP;
132d86a4126SThomas Zimmermann 	} else if (pci_is_pcie(pdev)) {
133771fe6b9SJerome Glisse 		flags |= RADEON_IS_PCIE;
134771fe6b9SJerome Glisse 	} else {
135771fe6b9SJerome Glisse 		flags |= RADEON_IS_PCI;
136771fe6b9SJerome Glisse 	}
137771fe6b9SJerome Glisse 
13873acacc7SAlex Deucher 	if ((radeon_runtime_pm != 0) &&
13990c4cde9SAlex Deucher 	    radeon_has_atpx() &&
1407ffb0ce3SLukas Wunner 	    ((flags & RADEON_IS_IGP) == 0) &&
141d86a4126SThomas Zimmermann 	    !pci_is_thunderbolt_attached(pdev))
14290c4cde9SAlex Deucher 		flags |= RADEON_IS_PX;
14390c4cde9SAlex Deucher 
1446cf8a3f5SJerome Glisse 	/* radeon_device_init should report only fatal error
1456cf8a3f5SJerome Glisse 	 * like memory allocation failure or iomapping failure,
1466cf8a3f5SJerome Glisse 	 * or memory manager initialization failure, it must
1476cf8a3f5SJerome Glisse 	 * properly initialize the GPU MC controller and permit
1486cf8a3f5SJerome Glisse 	 * VRAM allocation
1496cf8a3f5SJerome Glisse 	 */
150d86a4126SThomas Zimmermann 	r = radeon_device_init(rdev, dev, pdev, flags);
151771fe6b9SJerome Glisse 	if (r) {
152d86a4126SThomas Zimmermann 		dev_err(dev->dev, "Fatal error during GPU init\n");
153cf0fe456SJerome Glisse 		goto out;
1546cf8a3f5SJerome Glisse 	}
155d7a2952fSAlberto Milone 
1566cf8a3f5SJerome Glisse 	/* Again modeset_init should fail only on fatal error
1576cf8a3f5SJerome Glisse 	 * otherwise it should provide enough functionalities
1586cf8a3f5SJerome Glisse 	 * for shadowfb to run
1596cf8a3f5SJerome Glisse 	 */
1606cf8a3f5SJerome Glisse 	r = radeon_modeset_init(rdev);
161cf0fe456SJerome Glisse 	if (r)
162d86a4126SThomas Zimmermann 		dev_err(dev->dev, "Fatal error during modeset init\n");
163fda4b25cSLuca Tettamanti 
164fda4b25cSLuca Tettamanti 	/* Call ACPI methods: require modeset init
165fda4b25cSLuca Tettamanti 	 * but failure is not fatal
166fda4b25cSLuca Tettamanti 	 */
167fda4b25cSLuca Tettamanti 	if (!r) {
168fda4b25cSLuca Tettamanti 		acpi_status = radeon_acpi_init(rdev);
169fda4b25cSLuca Tettamanti 		if (acpi_status)
170d86a4126SThomas Zimmermann 			dev_dbg(dev->dev, "Error during ACPI methods call\n");
171fda4b25cSLuca Tettamanti 	}
172fda4b25cSLuca Tettamanti 
17390c4cde9SAlex Deucher 	if (radeon_is_px(dev)) {
174e0751556SRafael J. Wysocki 		dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
17510ebc0bcSDave Airlie 		pm_runtime_use_autosuspend(dev->dev);
17610ebc0bcSDave Airlie 		pm_runtime_set_autosuspend_delay(dev->dev, 5000);
17710ebc0bcSDave Airlie 		pm_runtime_set_active(dev->dev);
17810ebc0bcSDave Airlie 		pm_runtime_allow(dev->dev);
17910ebc0bcSDave Airlie 		pm_runtime_mark_last_busy(dev->dev);
18010ebc0bcSDave Airlie 		pm_runtime_put_autosuspend(dev->dev);
18110ebc0bcSDave Airlie 	}
18210ebc0bcSDave Airlie 
183cf0fe456SJerome Glisse out:
184cf0fe456SJerome Glisse 	if (r)
185cf0fe456SJerome Glisse 		radeon_driver_unload_kms(dev);
18610ebc0bcSDave Airlie 
18710ebc0bcSDave Airlie 
188771fe6b9SJerome Glisse 	return r;
189771fe6b9SJerome Glisse }
190771fe6b9SJerome Glisse 
191f482a141SAlex Deucher /**
192f482a141SAlex Deucher  * radeon_set_filp_rights - Set filp right.
193f482a141SAlex Deucher  *
194f482a141SAlex Deucher  * @dev: drm dev pointer
195f482a141SAlex Deucher  * @owner: drm file
196f482a141SAlex Deucher  * @applier: drm file
197f482a141SAlex Deucher  * @value: value
198f482a141SAlex Deucher  *
199f482a141SAlex Deucher  * Sets the filp rights for the device (all asics).
200f482a141SAlex Deucher  */
radeon_set_filp_rights(struct drm_device * dev,struct drm_file ** owner,struct drm_file * applier,uint32_t * value)2019eba4a93SMarek Olšák static void radeon_set_filp_rights(struct drm_device *dev,
2029eba4a93SMarek Olšák 				   struct drm_file **owner,
2039eba4a93SMarek Olšák 				   struct drm_file *applier,
2049eba4a93SMarek Olšák 				   uint32_t *value)
2059eba4a93SMarek Olšák {
20645c1da50SDaniel Vetter 	struct radeon_device *rdev = dev->dev_private;
20745c1da50SDaniel Vetter 
20845c1da50SDaniel Vetter 	mutex_lock(&rdev->gem.mutex);
2099eba4a93SMarek Olšák 	if (*value == 1) {
2109eba4a93SMarek Olšák 		/* wants rights */
2119eba4a93SMarek Olšák 		if (!*owner)
2129eba4a93SMarek Olšák 			*owner = applier;
2139eba4a93SMarek Olšák 	} else if (*value == 0) {
2149eba4a93SMarek Olšák 		/* revokes rights */
2159eba4a93SMarek Olšák 		if (*owner == applier)
2169eba4a93SMarek Olšák 			*owner = NULL;
2179eba4a93SMarek Olšák 	}
2189eba4a93SMarek Olšák 	*value = *owner == applier ? 1 : 0;
21945c1da50SDaniel Vetter 	mutex_unlock(&rdev->gem.mutex);
2209eba4a93SMarek Olšák }
221771fe6b9SJerome Glisse 
222771fe6b9SJerome Glisse /*
2239eba4a93SMarek Olšák  * Userspace get information ioctl
224771fe6b9SJerome Glisse  */
225f482a141SAlex Deucher /**
226f482a141SAlex Deucher  * radeon_info_ioctl - answer a device specific request.
227f482a141SAlex Deucher  *
228f5194f70SLee Jones  * @dev: drm device pointer
229f482a141SAlex Deucher  * @data: request object
230f482a141SAlex Deucher  * @filp: drm filp
231f482a141SAlex Deucher  *
232f482a141SAlex Deucher  * This function is used to pass device specific parameters to the userspace
233f482a141SAlex Deucher  * drivers.  Examples include: pci device id, pipeline parms, tiling params,
234f482a141SAlex Deucher  * etc. (all asics).
235f482a141SAlex Deucher  * Returns 0 on success, -EINVAL on failure.
236f482a141SAlex Deucher  */
radeon_info_ioctl(struct drm_device * dev,void * data,struct drm_file * filp)237384bc5e0SDaniel Vetter int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
238771fe6b9SJerome Glisse {
239771fe6b9SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
2406759a0a7SMarek Olšák 	struct drm_radeon_info *info = data;
241bc35afdbSJerome Glisse 	struct radeon_mode_info *minfo = &rdev->mode_info;
24264d7b8beSJerome Glisse 	uint32_t *value, value_tmp, *value_ptr, value_size;
243*a32ba6bdSChristian König 	struct ttm_resource_manager *man;
24464d7b8beSJerome Glisse 	uint64_t value64;
245bc35afdbSJerome Glisse 	struct drm_crtc *crtc;
246bc35afdbSJerome Glisse 	int i, found;
247771fe6b9SJerome Glisse 
2486759a0a7SMarek Olšák 	value_ptr = (uint32_t *)((unsigned long)info->value);
24964d7b8beSJerome Glisse 	value = &value_tmp;
25064d7b8beSJerome Glisse 	value_size = sizeof(uint32_t);
251d8ab3557SDr. David Alan Gilbert 
252771fe6b9SJerome Glisse 	switch (info->request) {
253771fe6b9SJerome Glisse 	case RADEON_INFO_DEVICE_ID:
254d86a4126SThomas Zimmermann 		*value = to_pci_dev(dev->dev)->device;
255771fe6b9SJerome Glisse 		break;
256771fe6b9SJerome Glisse 	case RADEON_INFO_NUM_GB_PIPES:
25764d7b8beSJerome Glisse 		*value = rdev->num_gb_pipes;
258771fe6b9SJerome Glisse 		break;
259f779b3e5SAlex Deucher 	case RADEON_INFO_NUM_Z_PIPES:
26064d7b8beSJerome Glisse 		*value = rdev->num_z_pipes;
261f779b3e5SAlex Deucher 		break;
262733289c2SJerome Glisse 	case RADEON_INFO_ACCEL_WORKING:
263148a03bcSAlex Deucher 		/* xf86-video-ati 6.13.0 relies on this being false for evergreen */
264148a03bcSAlex Deucher 		if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK))
26564d7b8beSJerome Glisse 			*value = false;
266148a03bcSAlex Deucher 		else
26764d7b8beSJerome Glisse 			*value = rdev->accel_working;
268733289c2SJerome Glisse 		break;
269bc35afdbSJerome Glisse 	case RADEON_INFO_CRTC_FROM_ID:
2701d6ac185SDaniel Vetter 		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
27164d7b8beSJerome Glisse 			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
27264d7b8beSJerome Glisse 			return -EFAULT;
27364d7b8beSJerome Glisse 		}
274bc35afdbSJerome Glisse 		for (i = 0, found = 0; i < rdev->num_crtc; i++) {
275bc35afdbSJerome Glisse 			crtc = (struct drm_crtc *)minfo->crtcs[i];
27664d7b8beSJerome Glisse 			if (crtc && crtc->base.id == *value) {
2770baf2d8fSAlex Deucher 				struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
27864d7b8beSJerome Glisse 				*value = radeon_crtc->crtc_id;
279bc35afdbSJerome Glisse 				found = 1;
280bc35afdbSJerome Glisse 				break;
281bc35afdbSJerome Glisse 			}
282bc35afdbSJerome Glisse 		}
283bc35afdbSJerome Glisse 		if (!found) {
28464d7b8beSJerome Glisse 			DRM_DEBUG_KMS("unknown crtc id %d\n", *value);
285bc35afdbSJerome Glisse 			return -EINVAL;
286bc35afdbSJerome Glisse 		}
287bc35afdbSJerome Glisse 		break;
288148a03bcSAlex Deucher 	case RADEON_INFO_ACCEL_WORKING2:
2893c64bd26SAlex Deucher 		if (rdev->family == CHIP_HAWAII) {
2909eb401afSAndreas Boll 			if (rdev->accel_working) {
2919eb401afSAndreas Boll 				if (rdev->new_fw)
2929eb401afSAndreas Boll 					*value = 3;
2933c64bd26SAlex Deucher 				else
2949eb401afSAndreas Boll 					*value = 2;
2959eb401afSAndreas Boll 			} else {
2963c64bd26SAlex Deucher 				*value = 0;
2979eb401afSAndreas Boll 			}
2983c64bd26SAlex Deucher 		} else {
29964d7b8beSJerome Glisse 			*value = rdev->accel_working;
3003c64bd26SAlex Deucher 		}
301148a03bcSAlex Deucher 		break;
302e7aeeba6SAlex Deucher 	case RADEON_INFO_TILING_CONFIG:
30364f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
30464f759ccSAlex Deucher 			*value = rdev->config.cik.tile_config;
30564f759ccSAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
30664d7b8beSJerome Glisse 			*value = rdev->config.si.tile_config;
307c1b2f69fSMichel Dänzer 		else if (rdev->family >= CHIP_CAYMAN)
30864d7b8beSJerome Glisse 			*value = rdev->config.cayman.tile_config;
309fecf1d07SAlex Deucher 		else if (rdev->family >= CHIP_CEDAR)
31064d7b8beSJerome Glisse 			*value = rdev->config.evergreen.tile_config;
311e7aeeba6SAlex Deucher 		else if (rdev->family >= CHIP_RV770)
31264d7b8beSJerome Glisse 			*value = rdev->config.rv770.tile_config;
313e7aeeba6SAlex Deucher 		else if (rdev->family >= CHIP_R600)
31464d7b8beSJerome Glisse 			*value = rdev->config.r600.tile_config;
315e7aeeba6SAlex Deucher 		else {
316d9fdaafbSDave Airlie 			DRM_DEBUG_KMS("tiling config is r6xx+ only!\n");
317e7aeeba6SAlex Deucher 			return -EINVAL;
318e7aeeba6SAlex Deucher 		}
319b824b364SAlex Deucher 		break;
320ab9e1f59SDave Airlie 	case RADEON_INFO_WANT_HYPERZ:
32143861f71SMarek Olšák 		/* The "value" here is both an input and output parameter.
32243861f71SMarek Olšák 		 * If the input value is 1, filp requests hyper-z access.
32343861f71SMarek Olšák 		 * If the input value is 0, filp revokes its hyper-z access.
32443861f71SMarek Olšák 		 *
32543861f71SMarek Olšák 		 * When returning, the value is 1 if filp owns hyper-z access,
32643861f71SMarek Olšák 		 * 0 otherwise. */
3271d6ac185SDaniel Vetter 		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
32864d7b8beSJerome Glisse 			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
32964d7b8beSJerome Glisse 			return -EFAULT;
33064d7b8beSJerome Glisse 		}
33164d7b8beSJerome Glisse 		if (*value >= 2) {
33264d7b8beSJerome Glisse 			DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", *value);
33343861f71SMarek Olšák 			return -EINVAL;
334ab9e1f59SDave Airlie 		}
33564d7b8beSJerome Glisse 		radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, value);
3369eba4a93SMarek Olšák 		break;
3379eba4a93SMarek Olšák 	case RADEON_INFO_WANT_CMASK:
3389eba4a93SMarek Olšák 		/* The same logic as Hyper-Z. */
3391d6ac185SDaniel Vetter 		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
34064d7b8beSJerome Glisse 			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
34164d7b8beSJerome Glisse 			return -EFAULT;
34264d7b8beSJerome Glisse 		}
34364d7b8beSJerome Glisse 		if (*value >= 2) {
34464d7b8beSJerome Glisse 			DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", *value);
3459eba4a93SMarek Olšák 			return -EINVAL;
34643861f71SMarek Olšák 		}
34764d7b8beSJerome Glisse 		radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, value);
348e7aeeba6SAlex Deucher 		break;
34958bbf018SAlex Deucher 	case RADEON_INFO_CLOCK_CRYSTAL_FREQ:
35058bbf018SAlex Deucher 		/* return clock value in KHz */
351454d2e2aSAlex Deucher 		if (rdev->asic->get_xclk)
35264d7b8beSJerome Glisse 			*value = radeon_get_xclk(rdev) * 10;
353454d2e2aSAlex Deucher 		else
35464d7b8beSJerome Glisse 			*value = rdev->clock.spll.reference_freq * 10;
35558bbf018SAlex Deucher 		break;
356486af189SDave Airlie 	case RADEON_INFO_NUM_BACKENDS:
35764f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
35864f759ccSAlex Deucher 			*value = rdev->config.cik.max_backends_per_se *
35964f759ccSAlex Deucher 				rdev->config.cik.max_shader_engines;
36064f759ccSAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
36164d7b8beSJerome Glisse 			*value = rdev->config.si.max_backends_per_se *
362c1b2f69fSMichel Dänzer 				rdev->config.si.max_shader_engines;
363c1b2f69fSMichel Dänzer 		else if (rdev->family >= CHIP_CAYMAN)
36464d7b8beSJerome Glisse 			*value = rdev->config.cayman.max_backends_per_se *
365fecf1d07SAlex Deucher 				rdev->config.cayman.max_shader_engines;
366fecf1d07SAlex Deucher 		else if (rdev->family >= CHIP_CEDAR)
36764d7b8beSJerome Glisse 			*value = rdev->config.evergreen.max_backends;
368486af189SDave Airlie 		else if (rdev->family >= CHIP_RV770)
36964d7b8beSJerome Glisse 			*value = rdev->config.rv770.max_backends;
370486af189SDave Airlie 		else if (rdev->family >= CHIP_R600)
37164d7b8beSJerome Glisse 			*value = rdev->config.r600.max_backends;
372486af189SDave Airlie 		else {
373486af189SDave Airlie 			return -EINVAL;
374486af189SDave Airlie 		}
375486af189SDave Airlie 		break;
3766565945bSAlex Deucher 	case RADEON_INFO_NUM_TILE_PIPES:
37764f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
37864f759ccSAlex Deucher 			*value = rdev->config.cik.max_tile_pipes;
37964f759ccSAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
38064d7b8beSJerome Glisse 			*value = rdev->config.si.max_tile_pipes;
381c1b2f69fSMichel Dänzer 		else if (rdev->family >= CHIP_CAYMAN)
38264d7b8beSJerome Glisse 			*value = rdev->config.cayman.max_tile_pipes;
3836565945bSAlex Deucher 		else if (rdev->family >= CHIP_CEDAR)
38464d7b8beSJerome Glisse 			*value = rdev->config.evergreen.max_tile_pipes;
3856565945bSAlex Deucher 		else if (rdev->family >= CHIP_RV770)
38664d7b8beSJerome Glisse 			*value = rdev->config.rv770.max_tile_pipes;
3876565945bSAlex Deucher 		else if (rdev->family >= CHIP_R600)
38864d7b8beSJerome Glisse 			*value = rdev->config.r600.max_tile_pipes;
3896565945bSAlex Deucher 		else {
3906565945bSAlex Deucher 			return -EINVAL;
3916565945bSAlex Deucher 		}
3926565945bSAlex Deucher 		break;
3938aeb96f8SAlex Deucher 	case RADEON_INFO_FUSION_GART_WORKING:
39464d7b8beSJerome Glisse 		*value = 1;
3958aeb96f8SAlex Deucher 		break;
396e55b9422SAlex Deucher 	case RADEON_INFO_BACKEND_MAP:
39764f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
3981ddce27dSMichel Dänzer 			*value = rdev->config.cik.backend_map;
39964f759ccSAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
40064d7b8beSJerome Glisse 			*value = rdev->config.si.backend_map;
401c1b2f69fSMichel Dänzer 		else if (rdev->family >= CHIP_CAYMAN)
40264d7b8beSJerome Glisse 			*value = rdev->config.cayman.backend_map;
403e55b9422SAlex Deucher 		else if (rdev->family >= CHIP_CEDAR)
40464d7b8beSJerome Glisse 			*value = rdev->config.evergreen.backend_map;
405e55b9422SAlex Deucher 		else if (rdev->family >= CHIP_RV770)
40664d7b8beSJerome Glisse 			*value = rdev->config.rv770.backend_map;
407e55b9422SAlex Deucher 		else if (rdev->family >= CHIP_R600)
40864d7b8beSJerome Glisse 			*value = rdev->config.r600.backend_map;
409e55b9422SAlex Deucher 		else {
410e55b9422SAlex Deucher 			return -EINVAL;
411e55b9422SAlex Deucher 		}
412e55b9422SAlex Deucher 		break;
413721604a1SJerome Glisse 	case RADEON_INFO_VA_START:
414721604a1SJerome Glisse 		/* this is where we report if vm is supported or not */
415721604a1SJerome Glisse 		if (rdev->family < CHIP_CAYMAN)
416721604a1SJerome Glisse 			return -EINVAL;
41764d7b8beSJerome Glisse 		*value = RADEON_VA_RESERVED_SIZE;
418721604a1SJerome Glisse 		break;
419721604a1SJerome Glisse 	case RADEON_INFO_IB_VM_MAX_SIZE:
420721604a1SJerome Glisse 		/* this is where we report if vm is supported or not */
421721604a1SJerome Glisse 		if (rdev->family < CHIP_CAYMAN)
422721604a1SJerome Glisse 			return -EINVAL;
42364d7b8beSJerome Glisse 		*value = RADEON_IB_VM_MAX_SIZE;
424721604a1SJerome Glisse 		break;
425609c1e15STom Stellard 	case RADEON_INFO_MAX_PIPES:
42664f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
42764f759ccSAlex Deucher 			*value = rdev->config.cik.max_cu_per_sh;
42864f759ccSAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
42964d7b8beSJerome Glisse 			*value = rdev->config.si.max_cu_per_sh;
430c1b2f69fSMichel Dänzer 		else if (rdev->family >= CHIP_CAYMAN)
43164d7b8beSJerome Glisse 			*value = rdev->config.cayman.max_pipes_per_simd;
432609c1e15STom Stellard 		else if (rdev->family >= CHIP_CEDAR)
43364d7b8beSJerome Glisse 			*value = rdev->config.evergreen.max_pipes;
434609c1e15STom Stellard 		else if (rdev->family >= CHIP_RV770)
43564d7b8beSJerome Glisse 			*value = rdev->config.rv770.max_pipes;
436609c1e15STom Stellard 		else if (rdev->family >= CHIP_R600)
43764d7b8beSJerome Glisse 			*value = rdev->config.r600.max_pipes;
438609c1e15STom Stellard 		else {
439609c1e15STom Stellard 			return -EINVAL;
440609c1e15STom Stellard 		}
441609c1e15STom Stellard 		break;
44264d7b8beSJerome Glisse 	case RADEON_INFO_TIMESTAMP:
44364d7b8beSJerome Glisse 		if (rdev->family < CHIP_R600) {
44464d7b8beSJerome Glisse 			DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
44564d7b8beSJerome Glisse 			return -EINVAL;
44664d7b8beSJerome Glisse 		}
44764d7b8beSJerome Glisse 		value = (uint32_t *)&value64;
44864d7b8beSJerome Glisse 		value_size = sizeof(uint64_t);
44964d7b8beSJerome Glisse 		value64 = radeon_get_gpu_clock_counter(rdev);
45064d7b8beSJerome Glisse 		break;
4512e1a7674SAlex Deucher 	case RADEON_INFO_MAX_SE:
45264f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
45364f759ccSAlex Deucher 			*value = rdev->config.cik.max_shader_engines;
45464f759ccSAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
45564d7b8beSJerome Glisse 			*value = rdev->config.si.max_shader_engines;
4562e1a7674SAlex Deucher 		else if (rdev->family >= CHIP_CAYMAN)
45764d7b8beSJerome Glisse 			*value = rdev->config.cayman.max_shader_engines;
4582e1a7674SAlex Deucher 		else if (rdev->family >= CHIP_CEDAR)
45964d7b8beSJerome Glisse 			*value = rdev->config.evergreen.num_ses;
4602e1a7674SAlex Deucher 		else
46164d7b8beSJerome Glisse 			*value = 1;
4622e1a7674SAlex Deucher 		break;
4632e1a7674SAlex Deucher 	case RADEON_INFO_MAX_SH_PER_SE:
46464f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
46564f759ccSAlex Deucher 			*value = rdev->config.cik.max_sh_per_se;
46664f759ccSAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
46764d7b8beSJerome Glisse 			*value = rdev->config.si.max_sh_per_se;
4682e1a7674SAlex Deucher 		else
4692e1a7674SAlex Deucher 			return -EINVAL;
4702e1a7674SAlex Deucher 		break;
471a0a53aa8SSamuel Li 	case RADEON_INFO_FASTFB_WORKING:
47264d7b8beSJerome Glisse 		*value = rdev->fastfb_working;
473a0a53aa8SSamuel Li 		break;
474902aaef6SChristian König 	case RADEON_INFO_RING_WORKING:
4751d6ac185SDaniel Vetter 		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
47664d7b8beSJerome Glisse 			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
47764d7b8beSJerome Glisse 			return -EFAULT;
47864d7b8beSJerome Glisse 		}
47964d7b8beSJerome Glisse 		switch (*value) {
480902aaef6SChristian König 		case RADEON_CS_RING_GFX:
481902aaef6SChristian König 		case RADEON_CS_RING_COMPUTE:
48264d7b8beSJerome Glisse 			*value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready;
483902aaef6SChristian König 			break;
484902aaef6SChristian König 		case RADEON_CS_RING_DMA:
48564d7b8beSJerome Glisse 			*value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready;
48664d7b8beSJerome Glisse 			*value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready;
487902aaef6SChristian König 			break;
488902aaef6SChristian König 		case RADEON_CS_RING_UVD:
48964d7b8beSJerome Glisse 			*value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
490902aaef6SChristian König 			break;
491f7ba8b04SChristian König 		case RADEON_CS_RING_VCE:
492f7ba8b04SChristian König 			*value = rdev->ring[TN_RING_TYPE_VCE1_INDEX].ready;
493f7ba8b04SChristian König 			break;
494902aaef6SChristian König 		default:
495902aaef6SChristian König 			return -EINVAL;
496902aaef6SChristian König 		}
497902aaef6SChristian König 		break;
49864d7b8beSJerome Glisse 	case RADEON_INFO_SI_TILE_MODE_ARRAY:
49964f759ccSAlex Deucher 		if (rdev->family >= CHIP_BONAIRE) {
50039aee490SAlex Deucher 			value = rdev->config.cik.tile_mode_array;
50139aee490SAlex Deucher 			value_size = sizeof(uint32_t)*32;
50239aee490SAlex Deucher 		} else if (rdev->family >= CHIP_TAHITI) {
50364d7b8beSJerome Glisse 			value = rdev->config.si.tile_mode_array;
50464d7b8beSJerome Glisse 			value_size = sizeof(uint32_t)*32;
50539aee490SAlex Deucher 		} else {
50639aee490SAlex Deucher 			DRM_DEBUG_KMS("tile mode array is si+ only!\n");
50739aee490SAlex Deucher 			return -EINVAL;
50839aee490SAlex Deucher 		}
50964d7b8beSJerome Glisse 		break;
51032f79a8aSMichel Dänzer 	case RADEON_INFO_CIK_MACROTILE_MODE_ARRAY:
51132f79a8aSMichel Dänzer 		if (rdev->family >= CHIP_BONAIRE) {
51232f79a8aSMichel Dänzer 			value = rdev->config.cik.macrotile_mode_array;
51332f79a8aSMichel Dänzer 			value_size = sizeof(uint32_t)*16;
51432f79a8aSMichel Dänzer 		} else {
51532f79a8aSMichel Dänzer 			DRM_DEBUG_KMS("macrotile mode array is cik+ only!\n");
51632f79a8aSMichel Dänzer 			return -EINVAL;
51732f79a8aSMichel Dänzer 		}
51832f79a8aSMichel Dänzer 		break;
519e5b9e750STom Stellard 	case RADEON_INFO_SI_CP_DMA_COMPUTE:
520e5b9e750STom Stellard 		*value = 1;
521e5b9e750STom Stellard 		break;
522439a1cffSMarek Olšák 	case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
523439a1cffSMarek Olšák 		if (rdev->family >= CHIP_BONAIRE) {
524439a1cffSMarek Olšák 			*value = rdev->config.cik.backend_enable_mask;
525439a1cffSMarek Olšák 		} else if (rdev->family >= CHIP_TAHITI) {
526439a1cffSMarek Olšák 			*value = rdev->config.si.backend_enable_mask;
527439a1cffSMarek Olšák 		} else {
528439a1cffSMarek Olšák 			DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
5298dbc2ccaSColin Ian King 			return -EINVAL;
530439a1cffSMarek Olšák 		}
531439a1cffSMarek Olšák 		break;
532f5f1f897SAlex Deucher 	case RADEON_INFO_MAX_SCLK:
533f5f1f897SAlex Deucher 		if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
534f5f1f897SAlex Deucher 		    rdev->pm.dpm_enabled)
535f5f1f897SAlex Deucher 			*value = rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk * 10;
536f5f1f897SAlex Deucher 		else
537f5f1f897SAlex Deucher 			*value = rdev->pm.default_sclk * 10;
538f5f1f897SAlex Deucher 		break;
53998ccc291SChristian König 	case RADEON_INFO_VCE_FW_VERSION:
54098ccc291SChristian König 		*value = rdev->vce.fw_version;
54198ccc291SChristian König 		break;
54298ccc291SChristian König 	case RADEON_INFO_VCE_FB_VERSION:
54398ccc291SChristian König 		*value = rdev->vce.fb_version;
54498ccc291SChristian König 		break;
54567e8e3f9SMarek Olšák 	case RADEON_INFO_NUM_BYTES_MOVED:
54667e8e3f9SMarek Olšák 		value = (uint32_t *)&value64;
54767e8e3f9SMarek Olšák 		value_size = sizeof(uint64_t);
54867e8e3f9SMarek Olšák 		value64 = atomic64_read(&rdev->num_bytes_moved);
54967e8e3f9SMarek Olšák 		break;
55067e8e3f9SMarek Olšák 	case RADEON_INFO_VRAM_USAGE:
55167e8e3f9SMarek Olšák 		value = (uint32_t *)&value64;
55267e8e3f9SMarek Olšák 		value_size = sizeof(uint64_t);
553*a32ba6bdSChristian König 		man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM);
554*a32ba6bdSChristian König 		value64 = ttm_resource_manager_usage(man);
55567e8e3f9SMarek Olšák 		break;
55667e8e3f9SMarek Olšák 	case RADEON_INFO_GTT_USAGE:
55767e8e3f9SMarek Olšák 		value = (uint32_t *)&value64;
55867e8e3f9SMarek Olšák 		value_size = sizeof(uint64_t);
559*a32ba6bdSChristian König 		man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_TT);
560*a32ba6bdSChristian König 		value64 = ttm_resource_manager_usage(man);
56167e8e3f9SMarek Olšák 		break;
56265fcf668SAlex Deucher 	case RADEON_INFO_ACTIVE_CU_COUNT:
56365fcf668SAlex Deucher 		if (rdev->family >= CHIP_BONAIRE)
56465fcf668SAlex Deucher 			*value = rdev->config.cik.active_cus;
56565fcf668SAlex Deucher 		else if (rdev->family >= CHIP_TAHITI)
56665fcf668SAlex Deucher 			*value = rdev->config.si.active_cus;
56765fcf668SAlex Deucher 		else if (rdev->family >= CHIP_CAYMAN)
56865fcf668SAlex Deucher 			*value = rdev->config.cayman.active_simds;
56965fcf668SAlex Deucher 		else if (rdev->family >= CHIP_CEDAR)
57065fcf668SAlex Deucher 			*value = rdev->config.evergreen.active_simds;
57165fcf668SAlex Deucher 		else if (rdev->family >= CHIP_RV770)
57265fcf668SAlex Deucher 			*value = rdev->config.rv770.active_simds;
57365fcf668SAlex Deucher 		else if (rdev->family >= CHIP_R600)
57465fcf668SAlex Deucher 			*value = rdev->config.r600.active_simds;
57565fcf668SAlex Deucher 		else
57665fcf668SAlex Deucher 			*value = 1;
57765fcf668SAlex Deucher 		break;
578d6d2a188SAlex Deucher 	case RADEON_INFO_CURRENT_GPU_TEMP:
579d6d2a188SAlex Deucher 		/* get temperature in millidegrees C */
580d6d2a188SAlex Deucher 		if (rdev->asic->pm.get_temperature)
581d6d2a188SAlex Deucher 			*value = radeon_get_temperature(rdev);
582d6d2a188SAlex Deucher 		else
583d6d2a188SAlex Deucher 			*value = 0;
584d6d2a188SAlex Deucher 		break;
5855c363a86SAlex Deucher 	case RADEON_INFO_CURRENT_GPU_SCLK:
5865c363a86SAlex Deucher 		/* get sclk in Mhz */
5875c363a86SAlex Deucher 		if (rdev->pm.dpm_enabled)
5885c363a86SAlex Deucher 			*value = radeon_dpm_get_current_sclk(rdev) / 100;
5895c363a86SAlex Deucher 		else
5905c363a86SAlex Deucher 			*value = rdev->pm.current_sclk / 100;
5915c363a86SAlex Deucher 		break;
5925c363a86SAlex Deucher 	case RADEON_INFO_CURRENT_GPU_MCLK:
5935c363a86SAlex Deucher 		/* get mclk in Mhz */
5945c363a86SAlex Deucher 		if (rdev->pm.dpm_enabled)
5955c363a86SAlex Deucher 			*value = radeon_dpm_get_current_mclk(rdev) / 100;
5965c363a86SAlex Deucher 		else
5975c363a86SAlex Deucher 			*value = rdev->pm.current_mclk / 100;
5985c363a86SAlex Deucher 		break;
5994535cb9cSAlex Deucher 	case RADEON_INFO_READ_REG:
6004535cb9cSAlex Deucher 		if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
6014535cb9cSAlex Deucher 			DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
6024535cb9cSAlex Deucher 			return -EFAULT;
6034535cb9cSAlex Deucher 		}
6044535cb9cSAlex Deucher 		if (radeon_get_allowed_info_register(rdev, *value, value))
6054535cb9cSAlex Deucher 			return -EINVAL;
6064535cb9cSAlex Deucher 		break;
6073bc980bfSMichel Dänzer 	case RADEON_INFO_VA_UNMAP_WORKING:
6083bc980bfSMichel Dänzer 		*value = true;
6093bc980bfSMichel Dänzer 		break;
61072b9076bSMarek Olšák 	case RADEON_INFO_GPU_RESET_COUNTER:
61172b9076bSMarek Olšák 		*value = atomic_read(&rdev->gpu_reset_counter);
61272b9076bSMarek Olšák 		break;
613771fe6b9SJerome Glisse 	default:
614d9fdaafbSDave Airlie 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
615771fe6b9SJerome Glisse 		return -EINVAL;
616771fe6b9SJerome Glisse 	}
6171d6ac185SDaniel Vetter 	if (copy_to_user(value_ptr, (char *)value, value_size)) {
6186759a0a7SMarek Olšák 		DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
619771fe6b9SJerome Glisse 		return -EFAULT;
620771fe6b9SJerome Glisse 	}
621771fe6b9SJerome Glisse 	return 0;
622771fe6b9SJerome Glisse }
623771fe6b9SJerome Glisse 
624f482a141SAlex Deucher /**
625f482a141SAlex Deucher  * radeon_driver_open_kms - drm callback for open
626f482a141SAlex Deucher  *
627f482a141SAlex Deucher  * @dev: drm dev pointer
628f482a141SAlex Deucher  * @file_priv: drm file
629f482a141SAlex Deucher  *
630f482a141SAlex Deucher  * On device open, init vm on cayman+ (all asics).
631f482a141SAlex Deucher  * Returns 0 on success, error on failure.
632f482a141SAlex Deucher  */
radeon_driver_open_kms(struct drm_device * dev,struct drm_file * file_priv)633771fe6b9SJerome Glisse int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
634771fe6b9SJerome Glisse {
635721604a1SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
636ab50cb9dSZhou Qingyang 	struct radeon_fpriv *fpriv;
637ab50cb9dSZhou Qingyang 	struct radeon_vm *vm;
63810ebc0bcSDave Airlie 	int r;
639721604a1SJerome Glisse 
640721604a1SJerome Glisse 	file_priv->driver_priv = NULL;
641721604a1SJerome Glisse 
64210ebc0bcSDave Airlie 	r = pm_runtime_get_sync(dev->dev);
6439fb10671SAditya Pakki 	if (r < 0) {
6449fb10671SAditya Pakki 		pm_runtime_put_autosuspend(dev->dev);
64510ebc0bcSDave Airlie 		return r;
6469fb10671SAditya Pakki 	}
64710ebc0bcSDave Airlie 
648721604a1SJerome Glisse 	/* new gpu have virtual address space support */
649721604a1SJerome Glisse 	if (rdev->family >= CHIP_CAYMAN) {
650721604a1SJerome Glisse 
651721604a1SJerome Glisse 		fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
652721604a1SJerome Glisse 		if (unlikely(!fpriv)) {
65332c59dc1SAlex Deucher 			r = -ENOMEM;
6544722f463SChristian König 			goto err_suspend;
655721604a1SJerome Glisse 		}
656721604a1SJerome Glisse 
657544143f9SAlex Deucher 		if (rdev->accel_working) {
658cc9e67e3SChristian König 			vm = &fpriv->vm;
659cc9e67e3SChristian König 			r = radeon_vm_init(rdev, vm);
660ab50cb9dSZhou Qingyang 			if (r)
6614722f463SChristian König 				goto err_fpriv;
662d72d43cfSChristian König 
663f1e3dc70SChristian König 			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
664ab50cb9dSZhou Qingyang 			if (r)
6654722f463SChristian König 				goto err_vm_fini;
666f1e3dc70SChristian König 
667d72d43cfSChristian König 			/* map the ib pool buffer read only into
668d72d43cfSChristian König 			 * virtual address space */
669cc9e67e3SChristian König 			vm->ib_bo_va = radeon_vm_bo_add(rdev, vm,
670d72d43cfSChristian König 							rdev->ring_tmp_bo.bo);
671ab50cb9dSZhou Qingyang 			if (!vm->ib_bo_va) {
672ab50cb9dSZhou Qingyang 				r = -ENOMEM;
6734722f463SChristian König 				goto err_vm_fini;
674ab50cb9dSZhou Qingyang 			}
675ab50cb9dSZhou Qingyang 
676cc9e67e3SChristian König 			r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va,
677cc9e67e3SChristian König 						  RADEON_VA_IB_OFFSET,
678d72d43cfSChristian König 						  RADEON_VM_PAGE_READABLE |
679d72d43cfSChristian König 						  RADEON_VM_PAGE_SNOOPED);
680ab50cb9dSZhou Qingyang 			if (r)
6814722f463SChristian König 				goto err_vm_fini;
68224f47accSJérôme Glisse 		}
683721604a1SJerome Glisse 		file_priv->driver_priv = fpriv;
684721604a1SJerome Glisse 	}
68510ebc0bcSDave Airlie 
6864722f463SChristian König 	pm_runtime_mark_last_busy(dev->dev);
6874722f463SChristian König 	pm_runtime_put_autosuspend(dev->dev);
6884722f463SChristian König 	return 0;
689ab50cb9dSZhou Qingyang 
6904722f463SChristian König err_vm_fini:
691ab50cb9dSZhou Qingyang 	radeon_vm_fini(rdev, vm);
6924722f463SChristian König err_fpriv:
693ab50cb9dSZhou Qingyang 	kfree(fpriv);
6944722f463SChristian König 
6954722f463SChristian König err_suspend:
69610ebc0bcSDave Airlie 	pm_runtime_mark_last_busy(dev->dev);
69710ebc0bcSDave Airlie 	pm_runtime_put_autosuspend(dev->dev);
69832c59dc1SAlex Deucher 	return r;
699771fe6b9SJerome Glisse }
700771fe6b9SJerome Glisse 
701f482a141SAlex Deucher /**
702f482a141SAlex Deucher  * radeon_driver_postclose_kms - drm callback for post close
703f482a141SAlex Deucher  *
704f482a141SAlex Deucher  * @dev: drm dev pointer
705f482a141SAlex Deucher  * @file_priv: drm file
706f482a141SAlex Deucher  *
70778910246SDaniel Vetter  * On device close, tear down hyperz and cmask filps on r1xx-r5xx
70878910246SDaniel Vetter  * (all asics).  And tear down vm on cayman+ (all asics).
709f482a141SAlex Deucher  */
radeon_driver_postclose_kms(struct drm_device * dev,struct drm_file * file_priv)710771fe6b9SJerome Glisse void radeon_driver_postclose_kms(struct drm_device *dev,
711771fe6b9SJerome Glisse 				 struct drm_file *file_priv)
712771fe6b9SJerome Glisse {
713721604a1SJerome Glisse 	struct radeon_device *rdev = dev->dev_private;
714721604a1SJerome Glisse 
71578910246SDaniel Vetter 	pm_runtime_get_sync(dev->dev);
71678910246SDaniel Vetter 
71778910246SDaniel Vetter 	mutex_lock(&rdev->gem.mutex);
71878910246SDaniel Vetter 	if (rdev->hyperz_filp == file_priv)
71978910246SDaniel Vetter 		rdev->hyperz_filp = NULL;
72078910246SDaniel Vetter 	if (rdev->cmask_filp == file_priv)
72178910246SDaniel Vetter 		rdev->cmask_filp = NULL;
72278910246SDaniel Vetter 	mutex_unlock(&rdev->gem.mutex);
72378910246SDaniel Vetter 
72478910246SDaniel Vetter 	radeon_uvd_free_handles(rdev, file_priv);
72578910246SDaniel Vetter 	radeon_vce_free_handles(rdev, file_priv);
72678910246SDaniel Vetter 
727721604a1SJerome Glisse 	/* new gpu have virtual address space support */
728721604a1SJerome Glisse 	if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) {
729721604a1SJerome Glisse 		struct radeon_fpriv *fpriv = file_priv->driver_priv;
730cc9e67e3SChristian König 		struct radeon_vm *vm = &fpriv->vm;
731d72d43cfSChristian König 		int r;
732d72d43cfSChristian König 
73324f47accSJérôme Glisse 		if (rdev->accel_working) {
734d72d43cfSChristian König 			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
735d72d43cfSChristian König 			if (!r) {
736cc9e67e3SChristian König 				if (vm->ib_bo_va)
737cc9e67e3SChristian König 					radeon_vm_bo_rmv(rdev, vm->ib_bo_va);
738d72d43cfSChristian König 				radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
739d72d43cfSChristian König 			}
740544143f9SAlex Deucher 			radeon_vm_fini(rdev, vm);
74124f47accSJérôme Glisse 		}
742721604a1SJerome Glisse 
743721604a1SJerome Glisse 		kfree(fpriv);
744721604a1SJerome Glisse 		file_priv->driver_priv = NULL;
745721604a1SJerome Glisse 	}
7469b96b63fSAlex Deucher 	pm_runtime_mark_last_busy(dev->dev);
7479b96b63fSAlex Deucher 	pm_runtime_put_autosuspend(dev->dev);
748771fe6b9SJerome Glisse }
749771fe6b9SJerome Glisse 
750771fe6b9SJerome Glisse /*
751771fe6b9SJerome Glisse  * VBlank related functions.
752771fe6b9SJerome Glisse  */
753f482a141SAlex Deucher /**
754f482a141SAlex Deucher  * radeon_get_vblank_counter_kms - get frame count
755f482a141SAlex Deucher  *
756d7757ba3SThomas Zimmermann  * @crtc: crtc to get the frame count from
757f482a141SAlex Deucher  *
758f482a141SAlex Deucher  * Gets the frame count on the requested crtc (all asics).
759f482a141SAlex Deucher  * Returns frame count on success, -EINVAL on failure.
760f482a141SAlex Deucher  */
radeon_get_vblank_counter_kms(struct drm_crtc * crtc)761d7757ba3SThomas Zimmermann u32 radeon_get_vblank_counter_kms(struct drm_crtc *crtc)
762771fe6b9SJerome Glisse {
763d7757ba3SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
764d7757ba3SThomas Zimmermann 	unsigned int pipe = crtc->index;
765c55d21eaSMario Kleiner 	int vpos, hpos, stat;
766c55d21eaSMario Kleiner 	u32 count;
7677ed220d7SMichel Dänzer 	struct radeon_device *rdev = dev->dev_private;
7687ed220d7SMichel Dänzer 
76985a21eafSThierry Reding 	if (pipe >= rdev->num_crtc) {
7704e926d2dSThierry Reding 		DRM_ERROR("Invalid crtc %u\n", pipe);
7717ed220d7SMichel Dänzer 		return -EINVAL;
7727ed220d7SMichel Dänzer 	}
7737ed220d7SMichel Dänzer 
774c55d21eaSMario Kleiner 	/* The hw increments its frame counter at start of vsync, not at start
775c55d21eaSMario Kleiner 	 * of vblank, as is required by DRM core vblank counter handling.
776c55d21eaSMario Kleiner 	 * Cook the hw count here to make it appear to the caller as if it
777c55d21eaSMario Kleiner 	 * incremented at start of vblank. We measure distance to start of
778c55d21eaSMario Kleiner 	 * vblank in vpos. vpos therefore will be >= 0 between start of vblank
779c55d21eaSMario Kleiner 	 * and start of vsync, so vpos >= 0 means to bump the hw frame counter
780c55d21eaSMario Kleiner 	 * result by 1 to give the proper appearance to caller.
781c55d21eaSMario Kleiner 	 */
7824e926d2dSThierry Reding 	if (rdev->mode_info.crtcs[pipe]) {
783c55d21eaSMario Kleiner 		/* Repeat readout if needed to provide stable result if
784c55d21eaSMario Kleiner 		 * we cross start of vsync during the queries.
785c55d21eaSMario Kleiner 		 */
786c55d21eaSMario Kleiner 		do {
7874e926d2dSThierry Reding 			count = radeon_get_vblank_counter(rdev, pipe);
788c55d21eaSMario Kleiner 			/* Ask radeon_get_crtc_scanoutpos to return vpos as
789c55d21eaSMario Kleiner 			 * distance to start of vblank, instead of regular
790c55d21eaSMario Kleiner 			 * vertical scanout pos.
791c55d21eaSMario Kleiner 			 */
792c55d21eaSMario Kleiner 			stat = radeon_get_crtc_scanoutpos(
7934e926d2dSThierry Reding 				dev, pipe, GET_DISTANCE_TO_VBLANKSTART,
794c55d21eaSMario Kleiner 				&vpos, &hpos, NULL, NULL,
7954e926d2dSThierry Reding 				&rdev->mode_info.crtcs[pipe]->base.hwmode);
7964e926d2dSThierry Reding 		} while (count != radeon_get_vblank_counter(rdev, pipe));
797c55d21eaSMario Kleiner 
798c55d21eaSMario Kleiner 		if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) !=
799c55d21eaSMario Kleiner 		    (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) {
800c55d21eaSMario Kleiner 			DRM_DEBUG_VBL("Query failed! stat %d\n", stat);
801c55d21eaSMario Kleiner 		}
802c55d21eaSMario Kleiner 		else {
8034e926d2dSThierry Reding 			DRM_DEBUG_VBL("crtc %u: dist from vblank start %d\n",
8044e926d2dSThierry Reding 				      pipe, vpos);
805c55d21eaSMario Kleiner 
806c55d21eaSMario Kleiner 			/* Bump counter if we are at >= leading edge of vblank,
807c55d21eaSMario Kleiner 			 * but before vsync where vpos would turn negative and
808c55d21eaSMario Kleiner 			 * the hw counter really increments.
809c55d21eaSMario Kleiner 			 */
810c55d21eaSMario Kleiner 			if (vpos >= 0)
811c55d21eaSMario Kleiner 				count++;
812c55d21eaSMario Kleiner 		}
813c55d21eaSMario Kleiner 	}
814c55d21eaSMario Kleiner 	else {
815c55d21eaSMario Kleiner 	    /* Fallback to use value as is. */
8164e926d2dSThierry Reding 	    count = radeon_get_vblank_counter(rdev, pipe);
817c55d21eaSMario Kleiner 	    DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
818c55d21eaSMario Kleiner 	}
819c55d21eaSMario Kleiner 
820c55d21eaSMario Kleiner 	return count;
821771fe6b9SJerome Glisse }
822771fe6b9SJerome Glisse 
823f482a141SAlex Deucher /**
824f482a141SAlex Deucher  * radeon_enable_vblank_kms - enable vblank interrupt
825f482a141SAlex Deucher  *
826f482a141SAlex Deucher  * @crtc: crtc to enable vblank interrupt for
827f482a141SAlex Deucher  *
828f482a141SAlex Deucher  * Enable the interrupt on the requested crtc (all asics).
829f482a141SAlex Deucher  * Returns 0 on success, -EINVAL on failure.
830f482a141SAlex Deucher  */
radeon_enable_vblank_kms(struct drm_crtc * crtc)831d7757ba3SThomas Zimmermann int radeon_enable_vblank_kms(struct drm_crtc *crtc)
832771fe6b9SJerome Glisse {
833d7757ba3SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
834d7757ba3SThomas Zimmermann 	unsigned int pipe = crtc->index;
8357ed220d7SMichel Dänzer 	struct radeon_device *rdev = dev->dev_private;
836fb98257aSChristian Koenig 	unsigned long irqflags;
837fb98257aSChristian Koenig 	int r;
8387ed220d7SMichel Dänzer 
839a2eb03a5SChenTao 	if (pipe >= rdev->num_crtc) {
840d7757ba3SThomas Zimmermann 		DRM_ERROR("Invalid crtc %d\n", pipe);
8417ed220d7SMichel Dänzer 		return -EINVAL;
8427ed220d7SMichel Dänzer 	}
8437ed220d7SMichel Dänzer 
844fb98257aSChristian Koenig 	spin_lock_irqsave(&rdev->irq.lock, irqflags);
845d7757ba3SThomas Zimmermann 	rdev->irq.crtc_vblank_int[pipe] = true;
846fb98257aSChristian Koenig 	r = radeon_irq_set(rdev);
847fb98257aSChristian Koenig 	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
848fb98257aSChristian Koenig 	return r;
849771fe6b9SJerome Glisse }
850771fe6b9SJerome Glisse 
851f482a141SAlex Deucher /**
852f482a141SAlex Deucher  * radeon_disable_vblank_kms - disable vblank interrupt
853f482a141SAlex Deucher  *
854f482a141SAlex Deucher  * @crtc: crtc to disable vblank interrupt for
855f482a141SAlex Deucher  *
856f482a141SAlex Deucher  * Disable the interrupt on the requested crtc (all asics).
857f482a141SAlex Deucher  */
radeon_disable_vblank_kms(struct drm_crtc * crtc)858d7757ba3SThomas Zimmermann void radeon_disable_vblank_kms(struct drm_crtc *crtc)
859771fe6b9SJerome Glisse {
860d7757ba3SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
861d7757ba3SThomas Zimmermann 	unsigned int pipe = crtc->index;
8627ed220d7SMichel Dänzer 	struct radeon_device *rdev = dev->dev_private;
863fb98257aSChristian Koenig 	unsigned long irqflags;
8647ed220d7SMichel Dänzer 
865a2eb03a5SChenTao 	if (pipe >= rdev->num_crtc) {
866d7757ba3SThomas Zimmermann 		DRM_ERROR("Invalid crtc %d\n", pipe);
8677ed220d7SMichel Dänzer 		return;
8687ed220d7SMichel Dänzer 	}
8697ed220d7SMichel Dänzer 
870fb98257aSChristian Koenig 	spin_lock_irqsave(&rdev->irq.lock, irqflags);
871d7757ba3SThomas Zimmermann 	rdev->irq.crtc_vblank_int[pipe] = false;
8727ed220d7SMichel Dänzer 	radeon_irq_set(rdev);
873fb98257aSChristian Koenig 	spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
874771fe6b9SJerome Glisse }
875