DRM full analysis - ADD_FB2 (4)

Continuing from the previous article: Full analysis of DRM - ADD_FB2 (3)

This article refers to the following blog posts:

DRM driver (4) ADD_FB

Thanks!

This article begins to formally analyze the drm_mode_addfb2 function. For ease of understanding, the drm_mode_addfb2 function code is posted again:

/**
 * drm_mode_addfb2 - add an FB to the graphics configuration
 * @dev: drm device for the ioctl
 * @data: data pointer for the ioctl
 * @file_priv: drm file for the ioctl call
 *
 * Add a new FB to the specified CRTC, given a user request with format. This is
 * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
 * and uses fourcc codes as pixel format specifiers.
 *
 * Called by the user via ioctl.
 *
 * Returns:
 * Zero on success, negative errno on failure.
 */
int drm_mode_addfb2(struct drm_device *dev,
		    void *data, struct drm_file *file_priv)
{
	struct drm_mode_fb_cmd2 *r = data;
	struct drm_framebuffer *fb;
 
	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EOPNOTSUPP;
 
	fb = drm_internal_framebuffer_create(dev, r, file_priv);
	if (IS_ERR(fb))
		return PTR_ERR(fb);
 
	drm_dbg_kms(dev, "[FB:%d]\n", fb->base.id);
	r->fb_id = fb->base.id;
 
	/* Transfer ownership to the filp for reaping on close */
	mutex_lock(&file_priv->fbs_lock);
	list_add(&fb->filp_head, &file_priv->fbs);
	mutex_unlock(&file_priv->fbs_lock);
 
	return 0;
}

Let’s look at the first step and first function: drm_core_check_feature. The corresponding code snippet is:

    if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EOPNOTSUPP;

The drm_core_check_feature function is in include/drm/drm_drv.h. The code is as follows:

/**
 * drm_core_check_feature - check driver feature flags
 * @dev: DRM device to check
 * @feature: feature flag
 *
 * This checks @dev for driver features, see &drm_driver.driver_features,
 * &drm_device.driver_features, and the various &enum drm_driver_feature flags.
 *
 * Returns true if the @feature is supported, false otherwise.
 */
static inline bool drm_core_check_feature(const struct drm_device *dev,
					  enum drm_driver_feature feature)
{
	return drm_core_check_all_features(dev, feature);
}

As you can see, the actual work is done by the drm_core_check_all_features function. The drm_core_check_all_features function is above, the code is as follows:

/**
 * drm_core_check_all_features - check driver feature flags mask
 * @dev: DRM device to check
 * @features: feature flag(s) mask
 *
 * This checks @dev for driver features, see &drm_driver.driver_features,
 * &drm_device.driver_features, and the various &enum drm_driver_feature flags.
 *
 * Returns true if all features in the @features mask are supported, false
 * otherwise.
 */
static inline bool drm_core_check_all_features(const struct drm_device *dev,
					       u32 features)
{
	u32 supported = dev->driver->driver_features & dev->driver_features;
 
	return features && (supported & features) == features;
}

The function of the function is to first AND the driver_features in the struct drm_driver *driver (driver instance) corresponding to the struct drm_device *dev (device instance) with the driver_features of the struct drm_device *dev (device instance) itself, to obtain the feature space limited to the device itself. Several items. Then see if any of these items support features. If features themselves are non-zero and supported, return true; otherwise return false. Once false is returned, the drm_core_check_feature function finally returns -EOPNOTSUPP (defined in include/uapi/asm-generic/errno.h), which means "Operation not supported on transport endpoint", that is, the operation is not supported on the transport endpoint.

Follow up in depth to the specific details of the call. DRIVER_MODESET is a macro, defined in include/drm/drm_drv.h, as follows:

    /**
	 * @DRIVER_MODESET:
	 *
	 * Driver supports mode setting interfaces (KMS).
	 */
	DRIVER_MODESET			= BIT(1),

The features passed into the drm_core_check_all_features function here are DRIVER_MODESET (value is 2), which represents support for the KMS (Kernel Mode Setting) interface (or not).

Focus on dev->driver->driver_features. dev->driver means the drm driver corresponding to the drm device. In fact, dev->driver corresponds to different struct drm_driver instances for different graphics card drivers. Here we still take the two graphics cards Intel and AMD that the author has actually come into contact with as examples.

  • Intel i915

The struct drm_driver initialization code corresponding to the Intel i915 graphics driver is in drivers/gpu/drm/i915/i915_driver.c, as follows:

static const struct drm_driver i915_drm_driver = {
	/* Don't use MTRRs here; the Xserver or userspace app should
	 * deal with them for Intel hardware.
	 */
	.driver_features =
	    DRIVER_GEM |
	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ |
	    DRIVER_SYNCOBJ_TIMELINE,
	.release = i915_driver_release,
	.open = i915_driver_open,
	.lastclose = i915_driver_lastclose,
	.postclose = i915_driver_postclose,
 
	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
	.gem_prime_import = i915_gem_prime_import,
 
	.dumb_create = i915_gem_dumb_create,
	.dumb_map_offset = i915_gem_dumb_mmap_offset,
 
	.ioctls = i915_ioctls,
	.num_ioctls = ARRAY_SIZE(i915_ioctls),
	.fops = &i915_driver_fops,
	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,
	.date = DRIVER_DATE,
	.major = DRIVER_MAJOR,
	.minor = DRIVER_MINOR,
	.patchlevel = DRIVER_PATCHLEVEL,
};

As can be seen from the code, for the i915 graphics card driver, its supported features are:

    .driver_features =
	    DRIVER_GEM |
	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ |
	    DRIVER_SYNCOBJ_TIMELINE,
  • AMD Raedon

There are two drivers for AMD graphics cards: Raedon and AMDGPU.

Let’s talk about the Raedon driver first. The struct drm_driver initialization code corresponding to the Raedon graphics driver is in drivers/gpu/drm/radeon/radeon_drv.c, as follows:

static const struct drm_driver kms_driver = {
	.driver_features =
	    DRIVER_GEM | DRIVER_RENDER | DRIVER_MODESET,
	.load = radeon_driver_load_kms,
	.open = radeon_driver_open_kms,
	.postclose = radeon_driver_postclose_kms,
	.lastclose = radeon_driver_lastclose_kms,
	.unload = radeon_driver_unload_kms,
	.ioctls = radeon_ioctls_kms,
	.num_ioctls = ARRAY_SIZE(radeon_ioctls_kms),
	.dumb_create = radeon_mode_dumb_create,
	.dumb_map_offset = radeon_mode_dumb_mmap,
	.fops = &radeon_driver_kms_fops,
 
	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
	.gem_prime_import_sg_table = radeon_gem_prime_import_sg_table,
	.gem_prime_mmap = drm_gem_prime_mmap,
 
	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,
	.date = DRIVER_DATE,
	.major = KMS_DRIVER_MAJOR,
	.minor = KMS_DRIVER_MINOR,
	.patchlevel = KMS_DRIVER_PATCHLEVEL,
};

As can be seen from the code, for the AMD Raedon graphics driver, the features it supports are:

    .driver_features =
	    DRIVER_GEM | DRIVER_RENDER | DRIVER_MODESET,
  • AMD AMDGPU

Let’s look at the AMDGPU driver. The struct drm_driver initialization code corresponding to the AMDGPU graphics driver is in drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c, as follows:

static const struct drm_driver amdgpu_kms_driver = {
	.driver_features =
	    DRIVER_ATOMIC |
	    DRIVER_GEM |
	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
	    DRIVER_SYNCOBJ_TIMELINE,
	.open = amdgpu_driver_open_kms,
	.postclose = amdgpu_driver_postclose_kms,
	.lastclose = amdgpu_driver_lastclose_kms,
	.ioctls = amdgpu_ioctls_kms,
	.num_ioctls = ARRAY_SIZE(amdgpu_ioctls_kms),
	.dumb_create = amdgpu_mode_dumb_create,
	.dumb_map_offset = amdgpu_mode_dumb_mmap,
	.fops = &amdgpu_driver_kms_fops,
	.release = &amdgpu_driver_release_kms,
 
	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
	.gem_prime_import = amdgpu_gem_prime_import,
	.gem_prime_mmap = drm_gem_prime_mmap,
 
	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,
	.date = DRIVER_DATE,
	.major = KMS_DRIVER_MAJOR,
	.minor = KMS_DRIVER_MINOR,
	.patchlevel = KMS_DRIVER_PATCHLEVEL,
};

As can be seen from the code, for the AMD AMDGPU graphics card driver, its supported features are:

    .driver_features =
	    DRIVER_ATOMIC |
	    DRIVER_GEM |
	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
	    DRIVER_SYNCOBJ_TIMELINE,

It can be seen that the above three graphics cards all support the DRIVER_MODESET feature.

For dev->driver_features, which is the driver_features of the device instance, it is not as obvious as dev->driver->driver_features, which is the driver_features of the driver instance. Under DRM, which is the kernel source code path, there are several related points, as follows:

1) In the drm_dev_init function of drivers/gpu/drm/drm_drv.c:

static int drm_dev_init(struct drm_device *dev,
			const struct drm_driver *driver,
			struct device *parent)
{
	struct inode *inode;
	int ret;
 
	……
	/* no per-device feature limits by default */
	dev->driver_features = ~0u;
    ……
}

2) In the vduse_dev_reset function of drivers/vdpa/vdpa_user/vduse_dev.c:

static void vduse_dev_reset(struct vduse_dev *dev)
{
	int i;
	struct vduse_iova_domain *domain = dev->domain;
 
	/* The coherent mappings are handled in vduse_dev_free_coherent() */
	if (domain->bounce_map)
		vduse_domain_reset_bounce_map(domain);
 
	down_write(&dev->rwsem);
 
	dev->status = 0;
	dev->driver_features = 0;
	dev->generation++;
	spin_lock(&dev->irq_lock);
	dev->config_cb.callback = NULL;
	dev->config_cb.private = NULL;
	spin_unlock(&dev->irq_lock);
	flush_work(&dev->inject);
 
    ……
}

3) In the vduse_vdpa_set_driver_features function of drivers/vdpa/vdpa_user/vduse_dev.c:

static int vduse_vdpa_set_driver_features(struct vdpa_device *vdpa, u64 features)
{
	struct vduse_dev *dev = vdpa_to_vduse(vdpa);
 
	dev->driver_features = features;
	return 0;
}

At this point, the first step in the drm_mode_addfb2 function: the drm_core_check_feature function has been analyzed. The remaining steps and functions will be analyzed in the following articles.

Guess you like

Origin blog.csdn.net/phmatthaus/article/details/133377231