static int savage_bci_get_buffers(struct drm_device *dev, struct drm_file *file_priv, struct drm_dma *d) { struct drm_buf *buf; int i; for (i = d->granted_count; i < d->request_count; i++) { buf = savage_freelist_get(dev); if (!buf) return -EAGAIN; buf->file_priv = file_priv; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; d->granted_count++; } return 0; }
int i915_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_mem_alloc_t *alloc = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } heap = get_heap(dev_priv, alloc->region); if (!heap || !*heap) return -EFAULT; if (alloc->alignment < 12) alloc->alignment = 12; block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); if (!block) return -ENOMEM; mark_block(dev, block, 1); if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
static int mga_getparam( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_getparam_t param; int value; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL( param, (drm_mga_getparam_t __user *)data, sizeof(param) ); DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID ); switch( param.param ) { case MGA_PARAM_IRQ_NR: value = dev->irq; break; case MGA_PARAM_CARD_TYPE: value = dev_priv->chipset; break; default: return DRM_ERR(EINVAL); } if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) { DRM_ERROR( "copy_to_user\n" ); return DRM_ERR(EFAULT); } return 0; }
/* Needs the lock as it touches the ring. */ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_irq_emit_t *emit = data; int result; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) return -EINVAL; LOCK_TEST_WITH_RETURN(dev, file_priv); result = radeon_emit_irq(dev); if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_getparam_t *param = data; int value; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); switch (param->param) { case MGA_PARAM_IRQ_NR: value = drm_dev_to_irq(dev); break; case MGA_PARAM_CARD_TYPE: value = dev_priv->chipset; break; default: return -EINVAL; } if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_info *info; struct radeon_mode_info *minfo = &rdev->mode_info; uint32_t *value_ptr; uint32_t value; struct drm_crtc *crtc; int i, found; info = data; value_ptr = (uint32_t *)((unsigned long)info->value); if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) return -EFAULT; switch (info->request) { case RADEON_INFO_DEVICE_ID: value = dev->pci_device; break; case RADEON_INFO_NUM_GB_PIPES: value = rdev->num_gb_pipes; break; case RADEON_INFO_NUM_Z_PIPES: value = rdev->num_z_pipes; break; case RADEON_INFO_ACCEL_WORKING: /* xf86-video-ati 6.13.0 relies on this being false for evergreen */ if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) value = false; else value = rdev->accel_working; break; case RADEON_INFO_CRTC_FROM_ID: for (i = 0, found = 0; i < rdev->num_crtc; i++) { crtc = (struct drm_crtc *)minfo->crtcs[i]; if (crtc && crtc->base.id == value) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); value = radeon_crtc->crtc_id; found = 1; break; } } if (!found) { DRM_DEBUG("unknown crtc id %d\n", value); return -EINVAL; } break; case RADEON_INFO_ACCEL_WORKING2: value = rdev->accel_working; break; default: DRM_DEBUG("Invalid request %d\n", info->request); return -EINVAL; } if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
/* Needs the lock as it touches the ring. */ int i915_irq_emit(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_irq_emit_t emit; int result; LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data, sizeof(emit)); result = i915_emit_irq(dev); if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; }
/* * Userspace get informations ioctl */ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_info *info; uint32_t *value_ptr; uint32_t value; info = data; value_ptr = (uint32_t *)((unsigned long)info->value); switch (info->request) { case RADEON_INFO_DEVICE_ID: value = dev->pci_device; break; case RADEON_INFO_NUM_GB_PIPES: value = rdev->num_gb_pipes; break; case RADEON_INFO_NUM_Z_PIPES: value = rdev->num_z_pipes; break; case RADEON_INFO_ACCEL_WORKING: value = rdev->accel_working; break; default: DRM_DEBUG("Invalid request %d\n", info->request); return -EINVAL; } if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
static int mga_set_fence(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; u32 temp; DMA_LOCALS; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); /* I would normal do this assignment in the declaration of temp, * but dev_priv may be NULL. */ temp = dev_priv->next_fence_to_post; dev_priv->next_fence_to_post++; BEGIN_DMA(1); DMA_BLOCK(MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000); ADVANCE_DMA(); if (DRM_COPY_TO_USER( (u32 __user *) data, & temp, sizeof(u32))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; }
static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d) { drm_buf_t *buf; int i; for (i = d->granted_count; i < d->request_count; i++) { buf = savage_freelist_get(dev); if (!buf) return DRM_ERR(EAGAIN); buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return DRM_ERR(EFAULT); d->granted_count++; } return 0; }
/*ARGSUSED*/ int i915_gem_get_tiling(DRM_IOCTL_ARGS) { DRM_DEVICE; struct drm_i915_gem_get_tiling args; drm_i915_private_t *dev_priv = dev->dev_private; struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; int ret; if (dev->driver->use_gem != 1) return ENODEV; DRM_COPYFROM_WITH_RETURN(&args, (struct drm_i915_gem_get_tiling __user *) data, sizeof(args)); obj = drm_gem_object_lookup(fpriv, args.handle); if (obj == NULL) return EINVAL; obj_priv = obj->driver_private; spin_lock(&dev->struct_mutex); args.tiling_mode = obj_priv->tiling_mode; switch (obj_priv->tiling_mode) { case I915_TILING_X: args.swizzle_mode = dev_priv->mm.bit_6_swizzle_x; break; case I915_TILING_Y: args.swizzle_mode = dev_priv->mm.bit_6_swizzle_y; break; case I915_TILING_NONE: args.swizzle_mode = I915_BIT_6_SWIZZLE_NONE; break; default: DRM_ERROR("unknown tiling mode\n"); } ret = DRM_COPY_TO_USER((struct drm_i915_gem_get_tiling __user *) data, &args, sizeof(args)); if ( ret != 0) DRM_ERROR(" gem get tiling error! %d", ret); drm_gem_object_unreference(obj); spin_unlock(&dev->struct_mutex); return 0; }
int radeon_mem_alloc( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_mem_alloc_t alloc; struct mem_block *block, **heap; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL( alloc, (drm_radeon_mem_alloc_t *)data, sizeof(alloc) ); heap = get_heap( dev_priv, alloc.region ); if (!heap || !*heap) return DRM_ERR(EFAULT); /* Make things easier on ourselves: all allocations at least * 4k aligned. */ if (alloc.alignment < 12) alloc.alignment = 12; block = alloc_block( *heap, alloc.size, alloc.alignment, DRM_CURRENTPID ); if (!block) return DRM_ERR(ENOMEM); if ( DRM_COPY_TO_USER( alloc.region_offset, &block->start, sizeof(int) ) ) { DRM_ERROR( "copy_to_user\n" ); return DRM_ERR(EFAULT); } return 0; }
int i915_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_mem_alloc *alloc = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return -EINVAL; } heap = get_heap(dev_priv, alloc->region); if (!heap || !*heap) return -EFAULT; /* Make things easier on ourselves: all allocations at least * 4k aligned. */ if (alloc->alignment < 12) alloc->alignment = 12; block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); if (!block) return -ENOMEM; mark_block(dev, block, 1); if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
static int mga_wait_fence(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; u32 fence; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return DRM_ERR(EINVAL); } DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32)); DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); mga_driver_fence_wait(dev, & fence); if (DRM_COPY_TO_USER( (u32 __user *) data, & fence, sizeof(u32))) { DRM_ERROR("copy_to_user\n"); return DRM_ERR(EFAULT); } return 0; }
/* * Userspace get information ioctl */ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_info *info; struct radeon_mode_info *minfo = &rdev->mode_info; uint32_t *value_ptr; uint32_t value; struct drm_crtc *crtc; int i, found; info = data; value_ptr = (uint32_t *)((unsigned long)info->value); if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) return -EFAULT; switch (info->request) { case RADEON_INFO_DEVICE_ID: value = dev->pci_device; break; case RADEON_INFO_NUM_GB_PIPES: value = rdev->num_gb_pipes; break; case RADEON_INFO_NUM_Z_PIPES: value = rdev->num_z_pipes; break; case RADEON_INFO_ACCEL_WORKING: /* xf86-video-ati 6.13.0 relies on this being false for evergreen */ if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) value = false; else value = rdev->accel_working; break; case RADEON_INFO_CRTC_FROM_ID: for (i = 0, found = 0; i < rdev->num_crtc; i++) { crtc = (struct drm_crtc *)minfo->crtcs[i]; if (crtc && crtc->base.id == value) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); value = radeon_crtc->crtc_id; found = 1; break; } } if (!found) { DRM_DEBUG_KMS("unknown crtc id %d\n", value); return -EINVAL; } break; case RADEON_INFO_ACCEL_WORKING2: value = rdev->accel_working; break; case RADEON_INFO_TILING_CONFIG: if (rdev->family >= CHIP_TAHITI) value = rdev->config.si.tile_config; else if (rdev->family >= CHIP_CAYMAN) value = rdev->config.cayman.tile_config; else if (rdev->family >= CHIP_CEDAR) value = rdev->config.evergreen.tile_config; else if (rdev->family >= CHIP_RV770) value = rdev->config.rv770.tile_config; else if (rdev->family >= CHIP_R600) value = rdev->config.r600.tile_config; else { DRM_DEBUG_KMS("tiling config is r6xx+ only!\n"); return -EINVAL; } break; case RADEON_INFO_WANT_HYPERZ: /* The "value" here is both an input and output parameter. * If the input value is 1, filp requests hyper-z access. * If the input value is 0, filp revokes its hyper-z access. * * When returning, the value is 1 if filp owns hyper-z access, * 0 otherwise. */ if (value >= 2) { DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); return -EINVAL; } radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value); break; case RADEON_INFO_WANT_CMASK: /* The same logic as Hyper-Z. */ if (value >= 2) { DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value); return -EINVAL; } radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value); break; case RADEON_INFO_CLOCK_CRYSTAL_FREQ: /* return clock value in KHz */ value = rdev->clock.spll.reference_freq * 10; break; case RADEON_INFO_NUM_BACKENDS: if (rdev->family >= CHIP_TAHITI) value = rdev->config.si.max_backends_per_se * rdev->config.si.max_shader_engines; else if (rdev->family >= CHIP_CAYMAN) value = rdev->config.cayman.max_backends_per_se * rdev->config.cayman.max_shader_engines; else if (rdev->family >= CHIP_CEDAR) value = rdev->config.evergreen.max_backends; else if (rdev->family >= CHIP_RV770) value = rdev->config.rv770.max_backends; else if (rdev->family >= CHIP_R600) value = rdev->config.r600.max_backends; else { return -EINVAL; } break; case RADEON_INFO_NUM_TILE_PIPES: if (rdev->family >= CHIP_TAHITI) value = rdev->config.si.max_tile_pipes; else if (rdev->family >= CHIP_CAYMAN) value = rdev->config.cayman.max_tile_pipes; else if (rdev->family >= CHIP_CEDAR) value = rdev->config.evergreen.max_tile_pipes; else if (rdev->family >= CHIP_RV770) value = rdev->config.rv770.max_tile_pipes; else if (rdev->family >= CHIP_R600) value = rdev->config.r600.max_tile_pipes; else { return -EINVAL; } break; case RADEON_INFO_FUSION_GART_WORKING: value = 1; break; case RADEON_INFO_BACKEND_MAP: if (rdev->family >= CHIP_TAHITI) value = rdev->config.si.backend_map; else if (rdev->family >= CHIP_CAYMAN) value = rdev->config.cayman.backend_map; else if (rdev->family >= CHIP_CEDAR) value = rdev->config.evergreen.backend_map; else if (rdev->family >= CHIP_RV770) value = rdev->config.rv770.backend_map; else if (rdev->family >= CHIP_R600) value = rdev->config.r600.backend_map; else { return -EINVAL; } break; case RADEON_INFO_VA_START: /* this is where we report if vm is supported or not */ if (rdev->family < CHIP_CAYMAN) return -EINVAL; value = RADEON_VA_RESERVED_SIZE; break; case RADEON_INFO_IB_VM_MAX_SIZE: /* this is where we report if vm is supported or not */ if (rdev->family < CHIP_CAYMAN) return -EINVAL; value = RADEON_IB_VM_MAX_SIZE; break; case RADEON_INFO_MAX_PIPES: if (rdev->family >= CHIP_TAHITI) value = rdev->config.si.max_cu_per_sh; else if (rdev->family >= CHIP_CAYMAN) value = rdev->config.cayman.max_pipes_per_simd; else if (rdev->family >= CHIP_CEDAR) value = rdev->config.evergreen.max_pipes; else if (rdev->family >= CHIP_RV770) value = rdev->config.rv770.max_pipes; else if (rdev->family >= CHIP_R600) value = rdev->config.r600.max_pipes; else { return -EINVAL; } break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; } if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
/** * radeon_info_ioctl - answer a device specific request. * * @rdev: radeon device pointer * @data: request object * @filp: drm filp * * This function is used to pass device specific parameters to the userspace * drivers. Examples include: pci device id, pipeline parms, tiling params, * etc. (all asics). * Returns 0 on success, -EINVAL on failure. */ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_info *info = data; struct radeon_mode_info *minfo = &rdev->mode_info; uint32_t *value, value_tmp, *value_ptr, value_size; uint64_t value64; struct drm_crtc *crtc; int i, found; value_ptr = (uint32_t *)((unsigned long)info->value); value = &value_tmp; value_size = sizeof(uint32_t); switch (info->request) { case RADEON_INFO_DEVICE_ID: *value = dev->pdev->device; break; case RADEON_INFO_NUM_GB_PIPES: *value = rdev->num_gb_pipes; break; case RADEON_INFO_NUM_Z_PIPES: *value = rdev->num_z_pipes; break; case RADEON_INFO_ACCEL_WORKING: /* xf86-video-ati 6.13.0 relies on this being false for evergreen */ if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) *value = false; else *value = rdev->accel_working; break; case RADEON_INFO_CRTC_FROM_ID: if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } for (i = 0, found = 0; i < rdev->num_crtc; i++) { crtc = (struct drm_crtc *)minfo->crtcs[i]; if (crtc && crtc->base.id == *value) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); *value = radeon_crtc->crtc_id; found = 1; break; } } if (!found) { DRM_DEBUG_KMS("unknown crtc id %d\n", *value); return -EINVAL; } break; case RADEON_INFO_ACCEL_WORKING2: *value = rdev->accel_working; break; case RADEON_INFO_TILING_CONFIG: if (rdev->family >= CHIP_TAHITI) *value = rdev->config.si.tile_config; else if (rdev->family >= CHIP_CAYMAN) *value = rdev->config.cayman.tile_config; else if (rdev->family >= CHIP_CEDAR) *value = rdev->config.evergreen.tile_config; else if (rdev->family >= CHIP_RV770) *value = rdev->config.rv770.tile_config; else if (rdev->family >= CHIP_R600) *value = rdev->config.r600.tile_config; else { DRM_DEBUG_KMS("tiling config is r6xx+ only!\n"); return -EINVAL; } break; case RADEON_INFO_WANT_HYPERZ: /* The "value" here is both an input and output parameter. * If the input value is 1, filp requests hyper-z access. * If the input value is 0, filp revokes its hyper-z access. * * When returning, the value is 1 if filp owns hyper-z access, * 0 otherwise. */ if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } if (*value >= 2) { DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", *value); return -EINVAL; } radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, value); break; case RADEON_INFO_WANT_CMASK: /* The same logic as Hyper-Z. */ if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } if (*value >= 2) { DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", *value); return -EINVAL; } radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, value); break; case RADEON_INFO_CLOCK_CRYSTAL_FREQ: /* return clock value in KHz */ if (rdev->asic->get_xclk) *value = radeon_get_xclk(rdev) * 10; else *value = rdev->clock.spll.reference_freq * 10; break; case RADEON_INFO_NUM_BACKENDS: if (rdev->family >= CHIP_TAHITI) *value = rdev->config.si.max_backends_per_se * rdev->config.si.max_shader_engines; else if (rdev->family >= CHIP_CAYMAN) *value = rdev->config.cayman.max_backends_per_se * rdev->config.cayman.max_shader_engines; else if (rdev->family >= CHIP_CEDAR) *value = rdev->config.evergreen.max_backends; else if (rdev->family >= CHIP_RV770) *value = rdev->config.rv770.max_backends; else if (rdev->family >= CHIP_R600) *value = rdev->config.r600.max_backends; else { return -EINVAL; } break; case RADEON_INFO_NUM_TILE_PIPES: if (rdev->family >= CHIP_TAHITI) *value = rdev->config.si.max_tile_pipes; else if (rdev->family >= CHIP_CAYMAN) *value = rdev->config.cayman.max_tile_pipes; else if (rdev->family >= CHIP_CEDAR) *value = rdev->config.evergreen.max_tile_pipes; else if (rdev->family >= CHIP_RV770) *value = rdev->config.rv770.max_tile_pipes; else if (rdev->family >= CHIP_R600) *value = rdev->config.r600.max_tile_pipes; else { return -EINVAL; } break; case RADEON_INFO_FUSION_GART_WORKING: *value = 1; break; case RADEON_INFO_BACKEND_MAP: if (rdev->family >= CHIP_TAHITI) *value = rdev->config.si.backend_map; else if (rdev->family >= CHIP_CAYMAN) *value = rdev->config.cayman.backend_map; else if (rdev->family >= CHIP_CEDAR) *value = rdev->config.evergreen.backend_map; else if (rdev->family >= CHIP_RV770) *value = rdev->config.rv770.backend_map; else if (rdev->family >= CHIP_R600) *value = rdev->config.r600.backend_map; else { return -EINVAL; } break; case RADEON_INFO_VA_START: /* this is where we report if vm is supported or not */ if (rdev->family < CHIP_CAYMAN) return -EINVAL; *value = RADEON_VA_RESERVED_SIZE; break; case RADEON_INFO_IB_VM_MAX_SIZE: /* this is where we report if vm is supported or not */ if (rdev->family < CHIP_CAYMAN) return -EINVAL; *value = RADEON_IB_VM_MAX_SIZE; break; case RADEON_INFO_MAX_PIPES: if (rdev->family >= CHIP_TAHITI) *value = rdev->config.si.max_cu_per_sh; else if (rdev->family >= CHIP_CAYMAN) *value = rdev->config.cayman.max_pipes_per_simd; else if (rdev->family >= CHIP_CEDAR) *value = rdev->config.evergreen.max_pipes; else if (rdev->family >= CHIP_RV770) *value = rdev->config.rv770.max_pipes; else if (rdev->family >= CHIP_R600) *value = rdev->config.r600.max_pipes; else { return -EINVAL; } break; case RADEON_INFO_TIMESTAMP: if (rdev->family < CHIP_R600) { DRM_DEBUG_KMS("timestamp is r6xx+ only!\n"); return -EINVAL; } value = (uint32_t*)&value64; value_size = sizeof(uint64_t); value64 = radeon_get_gpu_clock_counter(rdev); break; case RADEON_INFO_MAX_SE: if (rdev->family >= CHIP_TAHITI) *value = rdev->config.si.max_shader_engines; else if (rdev->family >= CHIP_CAYMAN) *value = rdev->config.cayman.max_shader_engines; else if (rdev->family >= CHIP_CEDAR) *value = rdev->config.evergreen.num_ses; else *value = 1; break; case RADEON_INFO_MAX_SH_PER_SE: if (rdev->family >= CHIP_TAHITI) *value = rdev->config.si.max_sh_per_se; else return -EINVAL; break; case RADEON_INFO_FASTFB_WORKING: *value = rdev->fastfb_working; break; case RADEON_INFO_RING_WORKING: if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) { DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); return -EFAULT; } switch (*value) { case RADEON_CS_RING_GFX: case RADEON_CS_RING_COMPUTE: *value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready; break; case RADEON_CS_RING_DMA: *value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready; *value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready; break; case RADEON_CS_RING_UVD: *value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready; break; default: return -EINVAL; } break; case RADEON_INFO_SI_TILE_MODE_ARRAY: if (rdev->family < CHIP_TAHITI) { DRM_DEBUG_KMS("tile mode array is si only!\n"); return -EINVAL; } value = rdev->config.si.tile_mode_array; value_size = sizeof(uint32_t)*32; break; case RADEON_INFO_SI_CP_DMA_COMPUTE: *value = 1; break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; } if (DRM_COPY_TO_USER(value_ptr, (char*)value, value_size)) { DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); return -EFAULT; } return 0; }
/* * Userspace get information ioctl */ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_info *info; struct radeon_mode_info *minfo = &rdev->mode_info; uint32_t *value_ptr; uint32_t value; struct drm_crtc *crtc; int i, found; info = data; value_ptr = (uint32_t *)((unsigned long)info->value); if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) return -EFAULT; switch (info->request) { case RADEON_INFO_DEVICE_ID: value = dev->pci_device; break; case RADEON_INFO_NUM_GB_PIPES: value = rdev->num_gb_pipes; break; case RADEON_INFO_NUM_Z_PIPES: value = rdev->num_z_pipes; break; case RADEON_INFO_ACCEL_WORKING: /* xf86-video-ati 6.13.0 relies on this being false for evergreen */ if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) value = false; else value = rdev->accel_working; break; case RADEON_INFO_CRTC_FROM_ID: for (i = 0, found = 0; i < rdev->num_crtc; i++) { crtc = (struct drm_crtc *)minfo->crtcs[i]; if (crtc && crtc->base.id == value) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); value = radeon_crtc->crtc_id; found = 1; break; } } if (!found) { DRM_DEBUG_KMS("unknown crtc id %d\n", value); return -EINVAL; } break; case RADEON_INFO_ACCEL_WORKING2: value = rdev->accel_working; break; case RADEON_INFO_TILING_CONFIG: if (rdev->family >= CHIP_CEDAR) value = rdev->config.evergreen.tile_config; else if (rdev->family >= CHIP_RV770) value = rdev->config.rv770.tile_config; else if (rdev->family >= CHIP_R600) value = rdev->config.r600.tile_config; else { DRM_DEBUG_KMS("tiling config is r6xx+ only!\n"); return -EINVAL; } break; case RADEON_INFO_WANT_HYPERZ: /* The "value" here is both an input and output parameter. * If the input value is 1, filp requests hyper-z access. * If the input value is 0, filp revokes its hyper-z access. * * When returning, the value is 1 if filp owns hyper-z access, * 0 otherwise. */ if (value >= 2) { DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); return -EINVAL; } radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value); break; case RADEON_INFO_WANT_CMASK: /* The same logic as Hyper-Z. */ if (value >= 2) { DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value); return -EINVAL; } radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value); break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; } if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } return 0; }
/*ARGSUSED*/ int i915_gem_set_tiling(DRM_IOCTL_ARGS) { DRM_DEVICE; struct drm_i915_gem_set_tiling args; drm_i915_private_t *dev_priv = dev->dev_private; struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; int ret; if (dev->driver->use_gem != 1) return ENODEV; DRM_COPYFROM_WITH_RETURN(&args, (struct drm_i915_gem_set_tiling __user *) data, sizeof(args)); obj = drm_gem_object_lookup(fpriv, args.handle); if (obj == NULL) return EINVAL; obj_priv = obj->driver_private; if (!i915_tiling_ok(dev, args.stride, obj->size, args.tiling_mode)) { drm_gem_object_unreference(obj); DRM_DEBUG("i915 tiling is not OK"); return EINVAL; } spin_lock(&dev->struct_mutex); if (args.tiling_mode == I915_TILING_NONE) { args.swizzle_mode = I915_BIT_6_SWIZZLE_NONE; } else { if (args.tiling_mode == I915_TILING_X) args.swizzle_mode = dev_priv->mm.bit_6_swizzle_x; else args.swizzle_mode = dev_priv->mm.bit_6_swizzle_y; /* If we can't handle the swizzling, make it untiled. */ if (args.swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) { args.tiling_mode = I915_TILING_NONE; args.swizzle_mode = I915_BIT_6_SWIZZLE_NONE; } } if (args.tiling_mode != obj_priv->tiling_mode) { int ret; /* Unbind the object, as switching tiling means we're * switching the cache organization due to fencing, probably. */ ret = i915_gem_object_unbind(obj, 1); if (ret != 0) { args.tiling_mode = obj_priv->tiling_mode; spin_unlock(&dev->struct_mutex); drm_gem_object_unreference(obj); DRM_ERROR("tiling switch!! unbind error %d", ret); return ret; } obj_priv->tiling_mode = args.tiling_mode; } obj_priv->stride = args.stride; ret = DRM_COPY_TO_USER((struct drm_i915_gem_set_tiling __user *) data, &args, sizeof(args)); if ( ret != 0) DRM_ERROR(" gem set tiling error! %d", ret); drm_gem_object_unreference(obj); spin_unlock(&dev->struct_mutex); return 0; }