Merge d7067ecdbabb73f68a6c3410cbe11a545a9359eb on remote branch

Change-Id: Iea5f2b0cf8f85a62b8d8b486895e28a8b2372a91
This commit is contained in:
Linux Build Service Account 2021-12-29 07:29:13 -08:00
commit d97685e68a
51 changed files with 5328 additions and 158 deletions

View File

@ -477,16 +477,21 @@
ccw_timeout_log [S390]
See Documentation/s390/CommonIO for details.
cgroup_disable= [KNL] Disable a particular controller
Format: {name of the controller(s) to disable}
cgroup_disable= [KNL] Disable a particular controller or optional feature
Format: {name of the controller(s) or feature(s) to disable}
The effects of cgroup_disable=foo are:
- foo isn't auto-mounted if you mount all cgroups in
a single hierarchy
- foo isn't visible as an individually mountable
subsystem
- if foo is an optional feature then the feature is
disabled and corresponding cgroup files are not
created
{Currently only "memory" controller deal with this and
cut the overhead, others just disable the usage. So
only cgroup_disable=memory is actually worthy}
Specifying "pressure" disables per-cgroup pressure
stall information accounting feature
cgroup_no_v1= [KNL] Disable one, multiple, all cgroup controllers in v1
Format: { controller[,controller...] | "all" }

View File

@ -68,6 +68,8 @@ CONFIG_ZSMALLOC=y
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_SECCOMP=y
CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
CONFIG_CPU_FREQ_TIMES=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y

View File

@ -72,6 +72,8 @@ CONFIG_ZSMALLOC=y
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_SECCOMP=y
CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
CONFIG_CPU_FREQ_TIMES=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y

View File

@ -21,6 +21,12 @@
qcom,ion-heap-type = "SYSTEM";
};
qcom,ion-heap@26 { /* USER CONTIG HEAP */
reg = <26>;
memory-region = <&user_contig_mem>;
qcom,ion-heap-type = "DMA";
};
qcom,ion-heap@27 { /* QSEECOM HEAP */
reg = <27>;
memory-region = <&qseecom_mem>;

View File

@ -507,7 +507,13 @@
no-map;
reg = <0 0x5e400000 0 0x1400000>;
};
user_contig_mem: user_contig_region {
compatible = "shared-dma-pool";
alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
reusable;
alignment = <0x0 0x400000>;
size = <0x0 0x1000000>;
};
qseecom_ta_mem: qseecom_ta_region {
compatible = "shared-dma-pool";
alloc-ranges = <0 0x00000000 0 0xffffffff>;

View File

@ -82,6 +82,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
# CONFIG_EFI is not set
CONFIG_KRYO_PMU_WORKAROUND=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set

View File

@ -88,6 +88,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
CONFIG_KRYO_PMU_WORKAROUND=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y

View File

@ -77,6 +77,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
# CONFIG_EFI is not set
CONFIG_KRYO_PMU_WORKAROUND=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set

View File

@ -83,6 +83,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
CONFIG_KRYO_PMU_WORKAROUND=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y

View File

@ -82,6 +82,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
# CONFIG_EFI is not set
CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y
CONFIG_KRYO_PMU_WORKAROUND=y

View File

@ -89,6 +89,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y
CONFIG_KRYO_PMU_WORKAROUND=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set

View File

@ -81,6 +81,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
CONFIG_PM_WAKELOCKS=y
@ -438,6 +440,7 @@ CONFIG_DVB_MPQ=m
CONFIG_DVB_MPQ_DEMUX=m
CONFIG_DVB_MPQ_SW=y
CONFIG_DRM=y
CONFIG_DRM_CLIENT_BOOTSPLASH=y
CONFIG_DRM_MSM_REGISTER_LOGGING=y
CONFIG_DRM_SDE_EVTLOG_DEBUG=y
CONFIG_DRM_SDE_RSC=y

View File

@ -87,6 +87,8 @@ CONFIG_SETEND_EMULATION=y
CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_CMDLINE="cgroup_disable=pressure"
CONFIG_CMDLINE_EXTEND=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
CONFIG_PM_WAKELOCKS=y
@ -452,6 +454,7 @@ CONFIG_DVB_MPQ=m
CONFIG_DVB_MPQ_DEMUX=m
CONFIG_DVB_MPQ_SW=y
CONFIG_DRM=y
CONFIG_DRM_CLIENT_BOOTSPLASH=y
CONFIG_DRM_MSM_REGISTER_LOGGING=y
CONFIG_DRM_SDE_EVTLOG_DEBUG=y
CONFIG_DRM_SDE_RSC=y

View File

@ -64,6 +64,13 @@ config DRM_DEBUG_MM_SELFTEST
If in doubt, say "N".
config DRM_CLIENT_BOOTSPLASH
bool "DRM Bootsplash"
help
Choose this option to enable DRM bootsplash. This option needs to be
selected only if UEFI bootsplash is disabled. Choosing this option
will render splash logo in display panel during boot up.
config DRM_KMS_HELPER
tristate
depends on DRM

View File

@ -29,6 +29,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-$(CONFIG_OF) += drm_of.o
drm-$(CONFIG_AGP) += drm_agpsupport.o
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
drm-$(CONFIG_DRM_CLIENT_BOOTSPLASH) += drm_bootsplash.o
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \

View File

@ -0,0 +1,333 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/notifier.h>
#include <linux/keyboard.h>
#include <linux/completion.h>
#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_modes.h>
#include <drm/drm_client.h>
#include "drm_internal.h"
#include "drm_splash.h"
static bool drm_bootsplash_enabled;
module_param_named(bootsplash_enabled, drm_bootsplash_enabled, bool, 0664);
static void drm_bootsplash_client_unregister(struct drm_client_dev *client);
static int drm_bootsplash_client_hotplug(struct drm_client_dev *client);
struct drm_bootsplash {
struct drm_client_dev client;
struct mutex lock;
struct drm_client_display *display;
struct drm_client_buffer *buffer;
struct work_struct worker;
struct completion xref;
bool started;
bool stop;
};
static void is_drm_bootsplash_enabled(struct device *dev)
{
drm_bootsplash_enabled = of_property_read_bool(dev->of_node,
"qcom,sde-drm-fb-splash-logo-enabled");
}
static void drm_bootsplash_buffer_delete(struct drm_bootsplash *splash)
{
if (!IS_ERR_OR_NULL(splash->buffer))
drm_client_framebuffer_delete(splash->buffer);
splash->buffer = NULL;
}
static int drm_bootsplash_buffer_create(
struct drm_bootsplash *splash, u32 width, u32 height)
{
splash->buffer =
drm_client_framebuffer_create(&splash->client,
width, height, SPLASH_IMAGE_FORMAT);
if (IS_ERR(splash->buffer)) {
drm_bootsplash_buffer_delete(splash);
return PTR_ERR(splash->buffer);
}
splash->buffer->vaddr =
drm_client_buffer_vmap(splash->buffer);
if (!splash->buffer->vaddr)
DRM_ERROR("drm_client_buffer_vmap fail\n");
return 0;
}
static int drm_bootsplash_display_probe(struct drm_bootsplash *splash)
{
struct drm_client_dev *client = &splash->client;
unsigned int width = 0, height = 0;
unsigned int num_non_tiled = 0, i;
unsigned int modeset_mask = 0;
struct drm_mode_set *modeset;
bool tiled = false;
int ret;
ret = drm_client_modeset_probe(client, 0, 0);
if (ret)
return ret;
mutex_lock(&client->modeset_mutex);
drm_client_for_each_modeset(modeset, client) {
if (!modeset->mode)
continue;
if (modeset->connectors[0]->has_tile)
tiled = true;
else
num_non_tiled++;
}
if (!tiled && !num_non_tiled) {
drm_bootsplash_buffer_delete(splash);
ret = -ENOENT;
goto out;
}
/* Assume only one tiled monitor is possible */
if (tiled) {
int hdisplay = 0, vdisplay = 0;
i = 0;
drm_client_for_each_modeset(modeset, client) {
i++;
if (!modeset->connectors[0]->has_tile)
continue;
if (!modeset->y)
hdisplay += modeset->mode->hdisplay;
if (!modeset->x)
vdisplay += modeset->mode->vdisplay;
modeset_mask |= BIT(i - 1);
}
width = hdisplay;
height = vdisplay;
goto trim;
}
/* The rest have one display per modeset, pick the largest */
i = 0;
drm_client_for_each_modeset(modeset, client) {
i++;
if (!modeset->mode || modeset->connectors[0]->has_tile)
continue;
if (modeset->mode->hdisplay *
modeset->mode->vdisplay > width * height) {
width = modeset->mode->hdisplay;
height = modeset->mode->vdisplay;
modeset_mask = BIT(i - 1);
}
}
trim:
i = 0;
drm_client_for_each_modeset(modeset, client) {
unsigned int j;
if (modeset_mask & BIT(i++))
continue;
drm_mode_destroy(client->dev, modeset->mode);
modeset->mode = NULL;
for (j = 0; j < modeset->num_connectors; j++) {
drm_connector_unreference(modeset->connectors[j]);
modeset->connectors[j] = NULL;
}
modeset->num_connectors = 0;
}
if (!splash->buffer ||
splash->buffer->fb->width != width ||
splash->buffer->fb->height != height) {
drm_bootsplash_buffer_delete(splash);
ret = drm_bootsplash_buffer_create(splash, width, height);
}
out:
mutex_unlock(&client->modeset_mutex);
return ret;
}
static int drm_bootsplash_display_commit_buffer(
struct drm_bootsplash *splash)
{
struct drm_client_dev *client = &splash->client;
struct drm_mode_set *modeset;
mutex_lock(&client->modeset_mutex);
drm_client_for_each_modeset(modeset, client) {
if (modeset->mode)
modeset->fb = splash->buffer->fb;
}
mutex_unlock(&client->modeset_mutex);
return drm_client_modeset_commit(client);
}
/* Draw a box for copying the image */
static void drm_bootsplash_draw_box(struct drm_client_buffer *buffer)
{
unsigned int width = buffer->fb->width;
unsigned int height = buffer->fb->height;
unsigned int x, y, z;
u32 *pix;
pix = buffer->vaddr;
pix += ((height / 2) - 50) * width;
pix += (width / 2) - 50;
z = 0;
for (y = 0; y < SPLASH_IMAGE_HEIGHT; y++) {
for (x = 0; x < SPLASH_IMAGE_WIDTH; x++)
*pix++ = splash_bgr888_image[z++];
pix += width - SPLASH_IMAGE_WIDTH;
}
}
static int drm_bootsplash_draw(struct drm_bootsplash *splash)
{
if (!splash->buffer)
return -ENOENT;
drm_bootsplash_draw_box(splash->buffer);
return drm_bootsplash_display_commit_buffer(splash);
}
static void drm_bootsplash_worker(struct work_struct *work)
{
struct drm_bootsplash *splash =
container_of(work, struct drm_bootsplash, worker);
struct drm_client_dev *client = &splash->client;
struct drm_device *dev = client->dev;
bool stop = false;
int ret = 0;
mutex_lock(&splash->lock);
stop = splash->stop;
ret = drm_bootsplash_draw(splash);
mutex_unlock(&splash->lock);
if (stop || ret == -ENOENT || ret == -EBUSY)
goto skip;
msleep(5000);
splash->stop = true;
skip:
drm_lastclose(dev);
drm_bootsplash_buffer_delete(splash);
DRM_DEBUG("Bootsplash has stopped (start=%u, stop=%u, ret=%d).\n",
splash->started, splash->stop, ret);
complete(&splash->xref);
}
static int drm_bootsplash_client_hotplug(struct drm_client_dev *client)
{
struct drm_bootsplash *splash =
container_of(client, struct drm_bootsplash, client);
int ret = 0, retval;
if (splash->stop)
goto out_unlock;
ret = drm_bootsplash_display_probe(splash);
if (ret < 0) {
if (splash->started && ret == -ENOENT)
splash->stop = true;
goto out_unlock;
}
if (!splash->started) {
splash->started = true;
reinit_completion(&splash->xref);
schedule_work(&splash->worker);
retval = wait_for_completion_interruptible(&splash->xref);
if (retval < 0)
DRM_ERROR("wait for bootsplash worker failed\n");
}
out_unlock:
return ret;
}
static const struct drm_client_funcs drm_bootsplash_client_funcs = {
.owner = THIS_MODULE,
.unregister = drm_bootsplash_client_unregister,
.hotplug = drm_bootsplash_client_hotplug,
};
static void drm_bootsplash_client_unregister(struct drm_client_dev *client)
{
struct drm_bootsplash *splash =
container_of(client, struct drm_bootsplash, client);
mutex_lock(&splash->lock);
splash->stop = true;
mutex_unlock(&splash->lock);
flush_work(&splash->worker);
drm_client_release(client);
kfree(splash);
}
void drm_bootsplash_client_register(struct drm_device *dev)
{
struct drm_bootsplash *splash;
int ret;
is_drm_bootsplash_enabled(dev->dev);
if (!drm_bootsplash_enabled)
return;
splash = kzalloc(sizeof(*splash), GFP_KERNEL);
if (!splash)
return;
ret = drm_client_init(dev, &splash->client, "bootsplash",
&drm_bootsplash_client_funcs);
if (ret) {
DRM_DEV_ERROR(dev->dev, "Fail to create client, ret=%d\n", ret);
kfree(splash);
return;
}
/* For this simple example only allow the first */
drm_bootsplash_enabled = false;
mutex_init(&splash->lock);
INIT_WORK(&splash->worker, drm_bootsplash_worker);
init_completion(&splash->xref);
ret = drm_bootsplash_client_hotplug(&splash->client);
if (ret)
DRM_DEV_ERROR(dev->dev, "client hotplug ret=%d\n", ret);
drm_client_register(&splash->client);
}
MODULE_DESCRIPTION("bootsplash");

View File

@ -59,7 +59,6 @@ static void drm_client_close(struct drm_client_dev *client)
drm_file_free(client->file);
}
EXPORT_SYMBOL(drm_client_close);
/**
* drm_client_init - Initialise a DRM client
@ -161,6 +160,13 @@ void drm_client_release(struct drm_client_dev *client)
}
EXPORT_SYMBOL(drm_client_release);
void drm_client_dev_register(struct drm_device *dev)
{
#ifdef CONFIG_DRM_CLIENT_BOOTSPLASH
drm_bootsplash_client_register(dev);
#endif
}
void drm_client_dev_unregister(struct drm_device *dev)
{
struct drm_client_dev *client, *tmp;
@ -180,6 +186,7 @@ void drm_client_dev_unregister(struct drm_device *dev)
}
mutex_unlock(&dev->clientlist_mutex);
}
EXPORT_SYMBOL(drm_client_dev_unregister);
/**
* drm_client_dev_hotplug - Send hotplug event to clients
@ -253,7 +260,6 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
struct drm_device *dev = client->dev;
struct drm_client_buffer *buffer;
struct drm_gem_object *obj;
void *vaddr;
int ret;
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
@ -280,6 +286,40 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
buffer->gem = obj;
return buffer;
err_delete:
drm_client_buffer_delete(buffer);
return ERR_PTR(ret);
}
/**
* drm_client_buffer_vmap - Map DRM client buffer into address space
* @buffer: DRM client buffer
*
* This function maps a client buffer into kernel address space. If the
* buffer is already mapped, it returns the mapping's address.
*
* Client buffer mappings are not ref'counted. Each call to
* drm_client_buffer_vmap() should be followed by a call to
* drm_client_buffer_vunmap(); or the client buffer should be mapped
* throughout its lifetime. The latter is the default.
*
* Returns:
* The mapped memory's address
*/
void *drm_client_buffer_vmap(struct drm_client_buffer *buffer)
{
struct drm_device *dev = buffer->client->dev;
void *vaddr;
if (buffer->vaddr)
return buffer->vaddr;
if (!dev->driver->gem_prime_vmap)
return ERR_PTR(-ENOTSUPP);
/*
* FIXME: The dependency on GEM here isn't required, we could
* convert the driver handle to a dma-buf instead and use the
@ -288,21 +328,35 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
* fd_install step out of the driver backend hooks, to make that
* final step optional for internal users.
*/
vaddr = dev->driver->gem_prime_vmap(obj);
if (!vaddr) {
ret = -ENOMEM;
goto err_delete;
vaddr = dev->driver->gem_prime_vmap(buffer->gem);
if (IS_ERR(vaddr)) {
return vaddr;
}
buffer->vaddr = vaddr;
return buffer;
err_delete:
drm_client_buffer_delete(buffer);
return ERR_PTR(ret);
return vaddr;
}
EXPORT_SYMBOL(drm_client_buffer_vmap);
/**
* drm_client_buffer_vunmap - Unmap DRM client buffer
* @buffer: DRM client buffer
*
* This function removes a client buffer's memory mapping. This
* function is only required by clients that manage their buffers
* by themselves. By default, DRM client buffers are mapped throughout
* their entire lifetime.
*/
void drm_client_buffer_vunmap(struct drm_client_buffer *buffer)
{
struct drm_device *dev = buffer->client->dev;
if (buffer->vaddr && dev->driver->gem_prime_vunmap)
dev->driver->gem_prime_vunmap(buffer->gem, buffer->vaddr);
buffer->vaddr = NULL;
}
EXPORT_SYMBOL(drm_client_buffer_vunmap);
static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
{

View File

@ -11,9 +11,23 @@
#include <linux/mutex.h>
#include <linux/slab.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_client.h>
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <drm/drm_encoder.h>
#include <drm/drm_print.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
#define DRM_CLIENT_MAX_CLONED_CONNECTORS 8
struct drm_client_offset {
int x, y;
};
int drm_client_modeset_create(struct drm_client_dev *client)
{
@ -53,7 +67,7 @@ err_free:
return -ENOMEM;
}
void drm_client_modeset_release(struct drm_client_dev *client)
static void drm_client_modeset_release(struct drm_client_dev *client)
{
struct drm_mode_set *modeset;
unsigned int i;
@ -70,8 +84,6 @@ void drm_client_modeset_release(struct drm_client_dev *client)
modeset->num_connectors = 0;
}
}
/* TODO: Remove export when modeset code has been moved over */
EXPORT_SYMBOL(drm_client_modeset_release);
void drm_client_modeset_free(struct drm_client_dev *client)
{
@ -90,7 +102,8 @@ void drm_client_modeset_free(struct drm_client_dev *client)
kfree(client->modesets);
}
struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc)
static struct drm_mode_set *
drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc)
{
struct drm_mode_set *modeset;
@ -100,5 +113,908 @@ struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, stru
return NULL;
}
/* TODO: Remove export when modeset code has been moved over */
EXPORT_SYMBOL(drm_client_find_modeset);
static struct drm_display_mode *
drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height)
{
struct drm_display_mode *mode;
list_for_each_entry(mode, &connector->modes, head) {
if (mode->hdisplay > width ||
mode->vdisplay > height)
continue;
if (mode->type & DRM_MODE_TYPE_PREFERRED)
return mode;
}
return NULL;
}
static struct drm_display_mode *
drm_connector_pick_cmdline_mode(struct drm_connector *connector)
{
struct drm_cmdline_mode *cmdline_mode;
struct drm_display_mode *mode;
bool prefer_non_interlace;
cmdline_mode = &connector->cmdline_mode;
if (cmdline_mode->specified == false)
return NULL;
/* attempt to find a matching mode in the list of modes
* we have gotten so far, if not add a CVT mode that conforms
*/
if (cmdline_mode->rb || cmdline_mode->margins)
goto create_mode;
prefer_non_interlace = !cmdline_mode->interlace;
again:
list_for_each_entry(mode, &connector->modes, head) {
/* Check (optional) mode name first */
if (!strcmp(mode->name, cmdline_mode->name))
return mode;
/* check width/height */
if (mode->hdisplay != cmdline_mode->xres ||
mode->vdisplay != cmdline_mode->yres)
continue;
if (cmdline_mode->refresh_specified) {
if (mode->vrefresh != cmdline_mode->refresh)
continue;
}
if (cmdline_mode->interlace) {
if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
continue;
} else if (prefer_non_interlace) {
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
continue;
}
return mode;
}
if (prefer_non_interlace) {
prefer_non_interlace = false;
goto again;
}
create_mode:
mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode);
if (mode)
list_add(&mode->head, &connector->modes);
return mode;
}
static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
{
bool enable;
if (strict)
enable = connector->status == connector_status_connected;
else
enable = connector->status != connector_status_disconnected;
return enable;
}
static void drm_client_connectors_enabled(struct drm_connector **connectors,
unsigned int connector_count,
bool *enabled)
{
bool any_enabled = false;
struct drm_connector *connector;
int i = 0;
for (i = 0; i < connector_count; i++) {
connector = connectors[i];
enabled[i] = drm_connector_enabled(connector, true);
DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
enabled[i] ? "yes" : "no");
any_enabled |= enabled[i];
}
if (any_enabled)
return;
for (i = 0; i < connector_count; i++)
enabled[i] = drm_connector_enabled(connectors[i], false);
}
static bool drm_client_target_cloned(struct drm_device *dev,
struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes,
struct drm_client_offset *offsets,
bool *enabled, int width, int height)
{
int count, i, j;
bool can_clone = false;
struct drm_display_mode *dmt_mode, *mode;
/* only contemplate cloning in the single crtc case */
if (dev->mode_config.num_crtc > 1)
return false;
count = 0;
for (i = 0; i < connector_count; i++) {
if (enabled[i])
count++;
}
/* only contemplate cloning if more than one connector is enabled */
if (count <= 1)
return false;
/* check the command line or if nothing common pick 1024x768 */
can_clone = true;
for (i = 0; i < connector_count; i++) {
if (!enabled[i])
continue;
modes[i] = drm_connector_pick_cmdline_mode(connectors[i]);
if (!modes[i]) {
can_clone = false;
break;
}
for (j = 0; j < i; j++) {
if (!enabled[j])
continue;
if (!drm_mode_match(modes[j], modes[i],
DRM_MODE_MATCH_TIMINGS |
DRM_MODE_MATCH_CLOCK |
DRM_MODE_MATCH_FLAGS |
DRM_MODE_MATCH_3D_FLAGS))
can_clone = false;
}
}
if (can_clone) {
DRM_DEBUG_KMS("can clone using command line\n");
return true;
}
/* try and find a 1024x768 mode on each connector */
can_clone = true;
dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
for (i = 0; i < connector_count; i++) {
if (!enabled[i])
continue;
list_for_each_entry(mode, &connectors[i]->modes, head) {
if (drm_mode_match(mode, dmt_mode,
DRM_MODE_MATCH_TIMINGS |
DRM_MODE_MATCH_CLOCK |
DRM_MODE_MATCH_FLAGS |
DRM_MODE_MATCH_3D_FLAGS))
modes[i] = mode;
}
if (!modes[i])
can_clone = false;
}
if (can_clone) {
DRM_DEBUG_KMS("can clone using 1024x768\n");
return true;
}
DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
return false;
}
static int drm_client_get_tile_offsets(struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes,
struct drm_client_offset *offsets,
int idx,
int h_idx, int v_idx)
{
struct drm_connector *connector;
int i;
int hoffset = 0, voffset = 0;
for (i = 0; i < connector_count; i++) {
connector = connectors[i];
if (!connector->has_tile)
continue;
if (!modes[i] && (h_idx || v_idx)) {
DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
connector->base.id);
continue;
}
if (connector->tile_h_loc < h_idx)
hoffset += modes[i]->hdisplay;
if (connector->tile_v_loc < v_idx)
voffset += modes[i]->vdisplay;
}
offsets[idx].x = hoffset;
offsets[idx].y = voffset;
DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx);
return 0;
}
static bool drm_client_target_preferred(struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes,
struct drm_client_offset *offsets,
bool *enabled, int width, int height)
{
const u64 mask = BIT_ULL(connector_count) - 1;
struct drm_connector *connector;
u64 conn_configured = 0;
int tile_pass = 0;
int i;
retry:
for (i = 0; i < connector_count; i++) {
connector = connectors[i];
if (conn_configured & BIT_ULL(i))
continue;
if (enabled[i] == false) {
conn_configured |= BIT_ULL(i);
continue;
}
/* first pass over all the untiled connectors */
if (tile_pass == 0 && connector->has_tile)
continue;
if (tile_pass == 1) {
if (connector->tile_h_loc != 0 ||
connector->tile_v_loc != 0)
continue;
} else {
if (connector->tile_h_loc != tile_pass - 1 &&
connector->tile_v_loc != tile_pass - 1)
/* if this tile_pass doesn't cover any of the tiles - keep going */
continue;
/*
* find the tile offsets for this pass - need to find
* all tiles left and above
*/
drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i,
connector->tile_h_loc, connector->tile_v_loc);
}
DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
connector->base.id);
/* got for command line mode first */
modes[i] = drm_connector_pick_cmdline_mode(connector);
if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n",
connector->base.id, connector->tile_group ? connector->tile_group->id : 0);
modes[i] = drm_connector_has_preferred_mode(connector, width, height);
}
/* No preferred modes, pick one off the list */
if (!modes[i] && !list_empty(&connector->modes)) {
list_for_each_entry(modes[i], &connector->modes, head)
break;
}
DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
"none");
conn_configured |= BIT_ULL(i);
}
if ((conn_configured & mask) != mask) {
tile_pass++;
goto retry;
}
return true;
}
static bool connector_has_possible_crtc(struct drm_connector *connector,
struct drm_crtc *crtc)
{
struct drm_encoder *encoder;
int i;
drm_connector_for_each_possible_encoder(connector, encoder, i) {
if (encoder->possible_crtcs & drm_crtc_mask(crtc))
return true;
}
return false;
}
static int drm_client_pick_crtcs(struct drm_client_dev *client,
struct drm_connector **connectors,
unsigned int connector_count,
struct drm_crtc **best_crtcs,
struct drm_display_mode **modes,
int n, int width, int height)
{
struct drm_device *dev = client->dev;
struct drm_connector *connector;
int my_score, best_score, score;
struct drm_crtc **crtcs, *crtc;
struct drm_mode_set *modeset;
int o;
if (n == connector_count)
return 0;
connector = connectors[n];
best_crtcs[n] = NULL;
best_score = drm_client_pick_crtcs(client, connectors, connector_count,
best_crtcs, modes, n + 1, width, height);
if (modes[n] == NULL)
return best_score;
crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
if (!crtcs)
return best_score;
my_score = 1;
if (connector->status == connector_status_connected)
my_score++;
if (connector->cmdline_mode.specified)
my_score++;
if (drm_connector_has_preferred_mode(connector, width, height))
my_score++;
/*
* select a crtc for this connector and then attempt to configure
* remaining connectors
*/
drm_client_for_each_modeset(modeset, client) {
crtc = modeset->crtc;
if (!connector_has_possible_crtc(connector, crtc))
continue;
for (o = 0; o < n; o++)
if (best_crtcs[o] == crtc)
break;
if (o < n) {
/* ignore cloning unless only a single crtc */
if (dev->mode_config.num_crtc > 1)
continue;
if (!drm_mode_equal(modes[o], modes[n]))
continue;
}
crtcs[n] = crtc;
memcpy(crtcs, best_crtcs, n * sizeof(*crtcs));
score = my_score + drm_client_pick_crtcs(client, connectors, connector_count,
crtcs, modes, n + 1, width, height);
if (score > best_score) {
best_score = score;
memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs));
}
}
kfree(crtcs);
return best_score;
}
/* Try to read the BIOS display configuration and use it for the initial config */
static bool drm_client_firmware_config(struct drm_client_dev *client,
struct drm_connector **connectors,
unsigned int connector_count,
struct drm_crtc **crtcs,
struct drm_display_mode **modes,
struct drm_client_offset *offsets,
bool *enabled, int width, int height)
{
unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG);
unsigned long conn_configured, conn_seq, mask;
struct drm_device *dev = client->dev;
int i, j;
bool *save_enabled;
bool fallback = true, ret = true;
int num_connectors_enabled = 0;
int num_connectors_detected = 0;
struct drm_modeset_acquire_ctx ctx;
if (!drm_drv_uses_atomic_modeset(dev))
return false;
save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
if (!save_enabled)
return false;
drm_modeset_acquire_init(&ctx, 0);
while (drm_modeset_lock_all_ctx(dev, &ctx) != 0)
drm_modeset_backoff(&ctx);
memcpy(save_enabled, enabled, count);
mask = GENMASK(count - 1, 0);
conn_configured = 0;
retry:
conn_seq = conn_configured;
for (i = 0; i < count; i++) {
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_crtc *new_crtc;
connector = connectors[i];
if (conn_configured & BIT(i))
continue;
if (conn_seq == 0 && !connector->has_tile)
continue;
if (connector->status == connector_status_connected)
num_connectors_detected++;
if (!enabled[i]) {
DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
connector->name);
conn_configured |= BIT(i);
continue;
}
if (connector->force == DRM_FORCE_OFF) {
DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
connector->name);
enabled[i] = false;
continue;
}
encoder = connector->state->best_encoder;
if (!encoder || WARN_ON(!connector->state->crtc)) {
if (connector->force > DRM_FORCE_OFF)
goto bail;
DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
connector->name);
enabled[i] = false;
conn_configured |= BIT(i);
continue;
}
num_connectors_enabled++;
new_crtc = connector->state->crtc;
/*
* Make sure we're not trying to drive multiple connectors
* with a single CRTC, since our cloning support may not
* match the BIOS.
*/
for (j = 0; j < count; j++) {
if (crtcs[j] == new_crtc) {
DRM_DEBUG_KMS("fallback: cloned configuration\n");
goto bail;
}
}
DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
connector->name);
/* go for command line mode first */
modes[i] = drm_connector_pick_cmdline_mode(connector);
/* try for preferred next */
if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
connector->name, connector->has_tile);
modes[i] = drm_connector_has_preferred_mode(connector, width, height);
}
/* No preferred mode marked by the EDID? Are there any modes? */
if (!modes[i] && !list_empty(&connector->modes)) {
DRM_DEBUG_KMS("using first mode listed on connector %s\n",
connector->name);
modes[i] = list_first_entry(&connector->modes,
struct drm_display_mode,
head);
}
/* last resort: use current mode */
if (!modes[i]) {
/*
* IMPORTANT: We want to use the adjusted mode (i.e.
* after the panel fitter upscaling) as the initial
* config, not the input mode, which is what crtc->mode
* usually contains. But since our current
* code puts a mode derived from the post-pfit timings
* into crtc->mode this works out correctly.
*
* This is crtc->mode and not crtc->state->mode for the
* fastboot check to work correctly.
*/
DRM_DEBUG_KMS("looking for current mode on connector %s\n",
connector->name);
modes[i] = &connector->state->crtc->mode;
}
crtcs[i] = new_crtc;
DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n",
connector->name,
connector->state->crtc->base.id,
connector->state->crtc->name,
modes[i]->hdisplay, modes[i]->vdisplay,
modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "");
fallback = false;
conn_configured |= BIT(i);
}
if ((conn_configured & mask) != mask && conn_configured != conn_seq)
goto retry;
/*
* If the BIOS didn't enable everything it could, fall back to have the
* same user experiencing of lighting up as much as possible like the
* fbdev helper library.
*/
if (num_connectors_enabled != num_connectors_detected &&
num_connectors_enabled < dev->mode_config.num_crtc) {
DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
num_connectors_detected);
fallback = true;
}
if (fallback) {
bail:
DRM_DEBUG_KMS("Not using firmware configuration\n");
memcpy(enabled, save_enabled, count);
ret = false;
}
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
kfree(save_enabled);
return ret;
}
/**
* drm_client_modeset_probe() - Probe for displays
* @client: DRM client
* @width: Maximum display mode width (optional)
* @height: Maximum display mode height (optional)
*
* This function sets up display pipelines for enabled connectors and stores the
* config in the client's modeset array.
*
* Returns:
* Zero on success or negative error code on failure.
*/
int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height)
{
struct drm_connector *connector, **connectors = NULL;
struct drm_connector_list_iter conn_iter;
struct drm_device *dev = client->dev;
unsigned int total_modes_count = 0;
struct drm_client_offset *offsets;
unsigned int connector_count = 0;
struct drm_display_mode **modes;
struct drm_crtc **crtcs;
int i, ret = 0;
bool *enabled;
DRM_DEBUG_KMS("\n");
if (!width)
width = dev->mode_config.max_width;
if (!height)
height = dev->mode_config.max_height;
drm_connector_list_iter_begin(dev, &conn_iter);
drm_client_for_each_connector_iter(connector, &conn_iter) {
struct drm_connector **tmp;
tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL);
if (!tmp) {
ret = -ENOMEM;
goto free_connectors;
}
connectors = tmp;
drm_connector_get(connector);
connectors[connector_count++] = connector;
}
drm_connector_list_iter_end(&conn_iter);
if (!connector_count)
return 0;
crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL);
offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL);
enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL);
if (!crtcs || !modes || !enabled || !offsets) {
DRM_ERROR("Memory allocation failed\n");
ret = -ENOMEM;
goto out;
}
mutex_lock(&client->modeset_mutex);
mutex_lock(&dev->mode_config.mutex);
for (i = 0; i < connector_count; i++)
total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height);
if (!total_modes_count)
DRM_DEBUG_KMS("No connectors reported connected with modes\n");
drm_client_connectors_enabled(connectors, connector_count, enabled);
if (!drm_client_firmware_config(client, connectors, connector_count, crtcs,
modes, offsets, enabled, width, height)) {
memset(modes, 0, connector_count * sizeof(*modes));
memset(crtcs, 0, connector_count * sizeof(*crtcs));
memset(offsets, 0, connector_count * sizeof(*offsets));
if (!drm_client_target_cloned(dev, connectors, connector_count, modes,
offsets, enabled, width, height) &&
!drm_client_target_preferred(connectors, connector_count, modes,
offsets, enabled, width, height))
DRM_ERROR("Unable to find initial modes\n");
DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
width, height);
drm_client_pick_crtcs(client, connectors, connector_count,
crtcs, modes, 0, width, height);
}
mutex_unlock(&dev->mode_config.mutex);
drm_client_modeset_release(client);
for (i = 0; i < connector_count; i++) {
struct drm_display_mode *mode = modes[i];
struct drm_crtc *crtc = crtcs[i];
struct drm_client_offset *offset = &offsets[i];
if (mode && crtc) {
struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc);
struct drm_connector *connector = connectors[i];
DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
mode->name, crtc->base.id, offset->x, offset->y);
if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS ||
(dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) {
ret = -EINVAL;
break;
}
modeset->mode = drm_mode_duplicate(dev, mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = connector;
modeset->x = offset->x;
modeset->y = offset->y;
}
}
mutex_unlock(&client->modeset_mutex);
out:
kfree(crtcs);
kfree(modes);
kfree(offsets);
kfree(enabled);
free_connectors:
for (i = 0; i < connector_count; i++)
drm_connector_put(connectors[i]);
kfree(connectors);
return ret;
}
EXPORT_SYMBOL(drm_client_modeset_probe);
static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active)
{
struct drm_device *dev = client->dev;
struct drm_plane *plane;
struct drm_atomic_state *state;
struct drm_modeset_acquire_ctx ctx;
struct drm_mode_set *mode_set;
int ret;
drm_modeset_acquire_init(&ctx, 0);
state = drm_atomic_state_alloc(dev);
if (!state) {
ret = -ENOMEM;
goto out_ctx;
}
state->acquire_ctx = &ctx;
retry:
drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
goto out_state;
}
plane_state->rotation = DRM_MODE_ROTATE_0;
/* disable non-primary: */
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
continue;
ret = __drm_atomic_helper_disable_plane(plane, plane_state);
if (ret != 0)
goto out_state;
}
drm_client_for_each_modeset(mode_set, client) {
ret = __drm_atomic_helper_set_config(mode_set, state);
if (ret != 0)
goto out_state;
/*
* __drm_atomic_helper_set_config() sets active when a
* mode is set, unconditionally clear it if we force DPMS off
*/
if (!active) {
struct drm_crtc *crtc = mode_set->crtc;
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
crtc_state->active = false;
}
}
ret = drm_atomic_commit(state);
out_state:
if (ret == -EDEADLK)
goto backoff;
out_ctx:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
return ret;
backoff:
drm_atomic_state_clear(state);
drm_modeset_backoff(&ctx);
goto retry;
}
static int drm_client_modeset_commit_legacy(struct drm_client_dev *client)
{
struct drm_device *dev = client->dev;
struct drm_mode_set *mode_set;
struct drm_plane *plane;
int ret = 0;
drm_modeset_lock_all(dev);
drm_for_each_plane(plane, dev) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane);
}
drm_client_for_each_modeset(mode_set, client) {
struct drm_crtc *crtc = mode_set->crtc;
if (crtc->funcs->cursor_set2) {
ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
if (ret)
goto out;
} else if (crtc->funcs->cursor_set) {
ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
if (ret)
goto out;
}
ret = drm_mode_set_config_internal(mode_set);
if (ret)
goto out;
}
out:
drm_modeset_unlock_all(dev);
return ret;
}
/**
* drm_client_modeset_commit_force() - Force commit CRTC configuration
* @client: DRM client
*
* Commit modeset configuration to crtcs without checking if there is a DRM master.
*
* Returns:
* Zero on success or negative error code on failure.
*/
int drm_client_modeset_commit_force(struct drm_client_dev *client)
{
struct drm_device *dev = client->dev;
int ret;
mutex_lock(&client->modeset_mutex);
if (drm_drv_uses_atomic_modeset(dev))
ret = drm_client_modeset_commit_atomic(client, true);
else
ret = drm_client_modeset_commit_legacy(client);
mutex_unlock(&client->modeset_mutex);
return ret;
}
EXPORT_SYMBOL(drm_client_modeset_commit_force);
/**
* drm_client_modeset_commit() - Commit CRTC configuration
* @client: DRM client
*
* Commit modeset configuration to crtcs.
*
* Returns:
* Zero on success or negative error code on failure.
*/
int drm_client_modeset_commit(struct drm_client_dev *client)
{
struct drm_device *dev = client->dev;
int ret;
if (!drm_master_internal_acquire(dev))
return -EBUSY;
ret = drm_client_modeset_commit_force(client);
drm_master_internal_release(dev);
return ret;
}
EXPORT_SYMBOL(drm_client_modeset_commit);
static void drm_client_modeset_dpms_legacy(struct drm_client_dev *client, int dpms_mode)
{
struct drm_device *dev = client->dev;
struct drm_connector *connector;
struct drm_mode_set *modeset;
int j;
drm_modeset_lock_all(dev);
drm_client_for_each_modeset(modeset, client) {
if (!modeset->crtc->enabled)
continue;
for (j = 0; j < modeset->num_connectors; j++) {
connector = modeset->connectors[j];
connector->funcs->dpms(connector, dpms_mode);
drm_object_property_set_value(&connector->base,
dev->mode_config.dpms_property, dpms_mode);
}
}
drm_modeset_unlock_all(dev);
}
/**
* drm_client_modeset_dpms() - Set DPMS mode
* @client: DRM client
* @mode: DPMS mode
*
* Note: For atomic drivers @mode is reduced to on/off.
*
* Returns:
* Zero on success or negative error code on failure.
*/
int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
{
struct drm_device *dev = client->dev;
int ret = 0;
if (!drm_master_internal_acquire(dev))
return -EBUSY;
mutex_lock(&client->modeset_mutex);
if (drm_drv_uses_atomic_modeset(dev))
ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON);
else
drm_client_modeset_dpms_legacy(client, mode);
mutex_unlock(&client->modeset_mutex);
drm_master_internal_release(dev);
return ret;
}
EXPORT_SYMBOL(drm_client_modeset_dpms);

View File

@ -133,8 +133,9 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
connector->force = mode->force;
}
DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n",
connector->name,
mode->name,
mode->xres, mode->yres,
mode->refresh_specified ? mode->refresh : 60,
mode->rb ? " reduced blanking" : "",
@ -1309,7 +1310,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
if (!connector)
return -ENOENT;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
drm_connector_for_each_possible_encoder(connector, encoder, i)
if (connector->encoder_ids[i] != 0)
encoders_count++;

View File

@ -839,6 +839,7 @@ err_minors:
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
out_unlock:
mutex_unlock(&drm_global_mutex);
return ret;
}
EXPORT_SYMBOL(drm_dev_register);
@ -866,8 +867,6 @@ void drm_dev_unregister(struct drm_device *dev)
dev->registered = false;
drm_client_dev_unregister(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev);

View File

@ -158,17 +158,8 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor)
goto out_prime_destroy;
}
if (drm_is_primary_client(file)) {
ret = drm_master_open(file);
if (ret)
goto out_close;
}
return file;
out_close:
if (dev->driver->postclose)
dev->driver->postclose(dev, file);
out_prime_destroy:
if (drm_core_check_feature(dev, DRIVER_PRIME))
drm_prime_destroy_file_private(&file->prime);
@ -373,6 +364,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
{
struct drm_device *dev = minor->dev;
struct drm_file *priv;
int ret = 0;
if (filp->f_flags & O_EXCL)
return -EBUSY; /* No exclusive opens */
@ -387,6 +379,14 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
if (IS_ERR(priv))
return PTR_ERR(priv);
if (drm_is_primary_client(priv)) {
ret = drm_master_open(priv);
if (ret) {
drm_file_free(priv);
return ret;
}
}
filp->private_data = priv;
filp->f_mode |= FMODE_UNSIGNED_OFFSET;
priv->filp = filp;

View File

@ -940,6 +940,100 @@ struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_mode_duplicate);
static bool drm_mode_match_timings(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
return mode1->hdisplay == mode2->hdisplay &&
mode1->hsync_start == mode2->hsync_start &&
mode1->hsync_end == mode2->hsync_end &&
mode1->htotal == mode2->htotal &&
mode1->hskew == mode2->hskew &&
mode1->vdisplay == mode2->vdisplay &&
mode1->vsync_start == mode2->vsync_start &&
mode1->vsync_end == mode2->vsync_end &&
mode1->vtotal == mode2->vtotal &&
mode1->vscan == mode2->vscan;
}
static bool drm_mode_match_clock(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
/*
* do clock check convert to PICOS
* so fb modes get matched the same
*/
if (mode1->clock && mode2->clock)
return KHZ2PICOS(mode1->clock) == KHZ2PICOS(mode2->clock);
else
return mode1->clock == mode2->clock;
}
static bool drm_mode_match_flags(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
return (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
(mode2->flags & ~DRM_MODE_FLAG_3D_MASK);
}
static bool drm_mode_match_3d_flags(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
return (mode1->flags & DRM_MODE_FLAG_3D_MASK) ==
(mode2->flags & DRM_MODE_FLAG_3D_MASK);
}
static bool drm_mode_match_aspect_ratio(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
return mode1->picture_aspect_ratio == mode2->picture_aspect_ratio;
}
/**
* drm_mode_match - test modes for (partial) equality
* @mode1: first mode
* @mode2: second mode
* @match_flags: which parts need to match (DRM_MODE_MATCH_*)
*
* Check to see if @mode1 and @mode2 are equivalent.
*
* Returns:
* True if the modes are (partially) equal, false otherwise.
*/
bool drm_mode_match(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2,
unsigned int match_flags)
{
if (!mode1 && !mode2)
return true;
if (!mode1 || !mode2)
return false;
if (match_flags & DRM_MODE_MATCH_TIMINGS &&
!drm_mode_match_timings(mode1, mode2))
return false;
if (match_flags & DRM_MODE_MATCH_CLOCK &&
!drm_mode_match_clock(mode1, mode2))
return false;
if (match_flags & DRM_MODE_MATCH_FLAGS &&
!drm_mode_match_flags(mode1, mode2))
return false;
if (match_flags & DRM_MODE_MATCH_3D_FLAGS &&
!drm_mode_match_3d_flags(mode1, mode2))
return false;
if (match_flags & DRM_MODE_MATCH_ASPECT_RATIO &&
!drm_mode_match_aspect_ratio(mode1, mode2))
return false;
return true;
}
EXPORT_SYMBOL(drm_mode_match);
/**
* drm_mode_equal - test modes for equality
* @mode1: first mode
@ -950,23 +1044,14 @@ EXPORT_SYMBOL(drm_mode_duplicate);
* Returns:
* True if the modes are equal, false otherwise.
*/
bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
bool drm_mode_equal(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
if (!mode1 && !mode2)
return true;
if (!mode1 || !mode2)
return false;
/* do clock check convert to PICOS so fb modes get matched
* the same */
if (mode1->clock && mode2->clock) {
if (KHZ2PICOS(mode1->clock) != KHZ2PICOS(mode2->clock))
return false;
} else if (mode1->clock != mode2->clock)
return false;
return drm_mode_equal_no_clocks(mode1, mode2);
return drm_mode_match(mode1, mode2,
DRM_MODE_MATCH_TIMINGS |
DRM_MODE_MATCH_CLOCK |
DRM_MODE_MATCH_FLAGS |
DRM_MODE_MATCH_3D_FLAGS);
}
EXPORT_SYMBOL(drm_mode_equal);
@ -981,13 +1066,13 @@ EXPORT_SYMBOL(drm_mode_equal);
* Returns:
* True if the modes are equal, false otherwise.
*/
bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) !=
(mode2->flags & DRM_MODE_FLAG_3D_MASK))
return false;
return drm_mode_equal_no_clocks_no_stereo(mode1, mode2);
return drm_mode_match(mode1, mode2,
DRM_MODE_MATCH_TIMINGS |
DRM_MODE_MATCH_FLAGS |
DRM_MODE_MATCH_3D_FLAGS);
}
EXPORT_SYMBOL(drm_mode_equal_no_clocks);
@ -1005,21 +1090,9 @@ EXPORT_SYMBOL(drm_mode_equal_no_clocks);
bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2)
{
if (mode1->hdisplay == mode2->hdisplay &&
mode1->hsync_start == mode2->hsync_start &&
mode1->hsync_end == mode2->hsync_end &&
mode1->htotal == mode2->htotal &&
mode1->hskew == mode2->hskew &&
mode1->vdisplay == mode2->vdisplay &&
mode1->vsync_start == mode2->vsync_start &&
mode1->vsync_end == mode2->vsync_end &&
mode1->vtotal == mode2->vtotal &&
mode1->vscan == mode2->vscan &&
(mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
(mode2->flags & ~DRM_MODE_FLAG_3D_MASK))
return true;
return false;
return drm_mode_match(mode1, mode2,
DRM_MODE_MATCH_TIMINGS |
DRM_MODE_MATCH_FLAGS);
}
EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);

3527
drivers/gpu/drm/drm_splash.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
#include <linux/extcon.h>
#include <linux/soc/qcom/fsa4480-i2c.h>
#include <drm/drm_client.h>
#include "sde_connector.h"
#include "msm_drv.h"
@ -126,6 +127,12 @@ static const struct of_device_id dp_dt_match[] = {
{}
};
static void dp_display_update_hdcp_info(struct dp_display_private *dp);
static bool dp_display_framework_ready(struct dp_display_private *dp)
{
return dp->dp_display.post_open ? false : true;
}
static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp)
{
return dp->link->hdcp_status.hdcp_version && dp->hdcp.ops;
@ -342,6 +349,13 @@ static void dp_display_hdcp_cb_work(struct work_struct *work)
dp = container_of(dw, struct dp_display_private, hdcp_cb_work);
dp_display_update_hdcp_info(dp);
if (!dp_display_is_hdcp_enabled(dp))
return;
dp->link->hdcp_status.hdcp_state = HDCP_STATE_AUTHENTICATING;
if (!dp->power_on || !dp->is_connected || atomic_read(&dp->aborted) ||
dp->hdcp_abort)
return;
@ -627,6 +641,36 @@ static void dp_display_send_hpd_event(struct dp_display_private *dp)
envp);
}
static void dp_display_post_open(struct dp_display *dp_display)
{
struct drm_connector *connector;
struct dp_display_private *dp;
if (!dp_display) {
pr_err("invalid input\n");
return;
}
dp = container_of(dp_display, struct dp_display_private, dp_display);
if (IS_ERR_OR_NULL(dp)) {
pr_err("invalid params\n");
return;
}
connector = dp->dp_display.base_connector;
if (!connector) {
pr_err("connector not set\n");
return;
}
/* if cable is already connected, send notification */
if (dp->hpd->hpd_high)
queue_work(dp->wq, &dp->connect_work);
else
dp_display->post_open = NULL;
}
static int dp_display_send_hpd_notification(struct dp_display_private *dp)
{
int ret = 0;
@ -639,6 +683,15 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp)
else
dp->dp_display.is_sst_connected = false;
if (!dp_display_framework_ready(dp)) {
pr_debug("%s: dp display framework not ready\n", __func__);
if (!dp->dp_display.is_bootsplash_en) {
dp->dp_display.is_bootsplash_en = true;
drm_client_dev_register(dp->dp_display.drm_dev);
}
return ret;
}
reinit_completion(&dp->notification_comp);
dp_display_send_hpd_event(dp);
@ -1205,6 +1258,11 @@ static void dp_display_connect_work(struct work_struct *work)
struct dp_display_private *dp = container_of(work,
struct dp_display_private, connect_work);
if (dp->dp_display.is_sst_connected && dp_display_framework_ready(dp)) {
pr_debug("HPD already on\n");
return;
}
if (atomic_read(&dp->aborted)) {
pr_warn("HPD off requested\n");
return;
@ -1453,6 +1511,7 @@ error_ctrl:
error_panel:
dp_link_put(dp->link);
error_link:
dp->aux->drm_aux_deregister(dp->aux);
dp_aux_put(dp->aux);
error_aux:
dp_power_put(dp->power);
@ -2782,7 +2841,7 @@ static int dp_display_probe(struct platform_device *pdev)
g_dp_display->unprepare = dp_display_unprepare;
g_dp_display->request_irq = dp_request_irq;
g_dp_display->get_debug = dp_get_debug;
g_dp_display->post_open = NULL;
g_dp_display->post_open = dp_display_post_open;
g_dp_display->post_init = dp_display_post_init;
g_dp_display->config_hdr = dp_display_config_hdr;
g_dp_display->mst_install = dp_display_mst_install;

View File

@ -72,6 +72,7 @@ struct dp_display {
u32 max_vdisplay;
u32 no_mst_encoder;
void *dp_mst_prv_info;
bool is_bootsplash_en;
int (*enable)(struct dp_display *dp_display, void *panel);
int (*post_enable)(struct dp_display *dp_display, void *panel);

View File

@ -49,6 +49,7 @@
#include "msm_kms.h"
#include "sde_wb.h"
#include "sde_dbg.h"
#include <drm/drm_client.h>
/*
* MSM driver version:
@ -311,6 +312,7 @@ static int msm_drm_uninit(struct device *dev)
drm_mode_config_cleanup(ddev);
if (priv->registered) {
drm_client_dev_unregister(ddev);
drm_dev_unregister(ddev);
priv->registered = false;
}

View File

@ -2944,7 +2944,8 @@ static void sde_crtc_vblank_cb(void *data)
sde_crtc->vblank_cb_count++;
sde_crtc->vblank_last_cb_time = ktime_get();
sysfs_notify_dirent(sde_crtc->vsync_event_sf);
if (sde_crtc->vsync_event_sf)
sysfs_notify_dirent(sde_crtc->vsync_event_sf);
drm_crtc_handle_vblank(crtc);
DRM_DEBUG_VBL("crtc%d\n", crtc->base.id);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -243,35 +243,34 @@ int cam_cdm_stream_ops_internal(void *hw_priv,
return -EINVAL;
core = (struct cam_cdm *)cdm_hw->core_info;
mutex_lock(&cdm_hw->hw_mutex);
client_idx = CAM_CDM_GET_CLIENT_IDX(*handle);
client = core->clients[client_idx];
if (!client) {
CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle);
mutex_unlock(&cdm_hw->hw_mutex);
return -EINVAL;
}
cam_cdm_get_client_refcount(client);
if (*handle != client->handle) {
CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle);
cam_cdm_put_client_refcount(client);
return -EINVAL;
rc = -EINVAL;
goto end;
}
if (operation == true) {
if (true == client->stream_on) {
CAM_ERR(CAM_CDM,
"Invalid CDM client is already streamed ON");
cam_cdm_put_client_refcount(client);
return rc;
goto end;
}
} else {
if (client->stream_on == false) {
CAM_ERR(CAM_CDM,
"Invalid CDM client is already streamed Off");
cam_cdm_put_client_refcount(client);
return rc;
goto end;
}
}
mutex_lock(&cdm_hw->hw_mutex);
if (operation == true) {
if (!cdm_hw->open_count) {
struct cam_ahb_vote ahb_vote;

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 2021 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -27,6 +27,7 @@
#include <media/cam_req_mgr.h>
#include <media/cam_defs.h>
#include <media/cam_icp.h>
#include "cam_mem_mgr.h"
#include "cam_req_mgr_dev.h"
#include "cam_subdev.h"
#include "cam_node.h"
@ -95,10 +96,17 @@ static int cam_icp_subdev_open(struct v4l2_subdev *sd,
goto end;
}
rc = cam_mem_mgr_init();
if (rc) {
CAM_ERR(CAM_CRM, "mem mgr init failed");
goto end;
}
hw_mgr_intf = &node->hw_mgr_intf;
rc = hw_mgr_intf->hw_open(hw_mgr_intf->hw_mgr_priv, NULL);
if (rc < 0) {
CAM_ERR(CAM_ICP, "FW download failed");
cam_mem_mgr_deinit();
goto end;
}
g_icp_dev.open_cnt++;
@ -140,6 +148,7 @@ static int cam_icp_subdev_close(struct v4l2_subdev *sd,
goto end;
}
cam_mem_mgr_deinit();
end:
mutex_unlock(&g_icp_dev.icp_lock);
return 0;

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -24,8 +24,11 @@
#include "cam_smmu_api.h"
#include "cam_debug_util.h"
static struct cam_mem_table tbl;
static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED);
static struct cam_mem_table tbl = {
.m_lock = __MUTEX_INITIALIZER(tbl.m_lock),
};
static atomic_t cam_mem_mgr_refcnt = ATOMIC_INIT(0);
static int cam_mem_util_get_dma_dir(uint32_t flags)
{
@ -129,12 +132,27 @@ int cam_mem_mgr_init(void)
int i;
int bitmap_size;
mutex_lock(&tbl.m_lock);
if (atomic_inc_return(&cam_mem_mgr_refcnt) > 1) {
CAM_DBG(CAM_MEM,
"Mem mgr refcnt: %d",
atomic_read(&cam_mem_mgr_refcnt));
mutex_unlock(&tbl.m_lock);
return 0;
}
memset(tbl.bufq, 0, sizeof(tbl.bufq));
bitmap_size = BITS_TO_LONGS(CAM_MEM_BUFQ_MAX) * sizeof(long);
tbl.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!tbl.bitmap)
if (!tbl.bitmap) {
atomic_dec(&cam_mem_mgr_refcnt);
CAM_DBG(CAM_MEM, "Mem mgr refcnt: %d",
atomic_read(&cam_mem_mgr_refcnt));
mutex_unlock(&tbl.m_lock);
return -ENOMEM;
}
tbl.bits = bitmap_size * BITS_PER_BYTE;
bitmap_zero(tbl.bitmap, tbl.bits);
@ -145,9 +163,8 @@ int cam_mem_mgr_init(void)
tbl.bufq[i].fd = -1;
tbl.bufq[i].buf_handle = -1;
}
mutex_init(&tbl.m_lock);
atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_INITIALIZED);
mutex_unlock(&tbl.m_lock);
return 0;
}
@ -189,7 +206,7 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle,
*len_ptr = 0;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -240,7 +257,7 @@ int cam_mem_get_cpu_buf(int32_t buf_handle, uintptr_t *vaddr_ptr, size_t *len)
int idx;
struct dma_buf *dmabuf = NULL;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -306,7 +323,7 @@ int cam_mem_put_cpu_buf(int32_t buf_handle)
int idx;
struct dma_buf *dmabuf = NULL;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -360,7 +377,7 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
uint32_t cache_dir;
unsigned long dmabuf_flag = 0;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -664,7 +681,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd)
uintptr_t kvaddr = 0;
size_t klen;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -786,7 +803,7 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd)
dma_addr_t hw_vaddr = 0;
size_t len = 0;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -957,7 +974,6 @@ static int cam_mem_mgr_cleanup_table(void)
{
int i;
mutex_lock(&tbl.m_lock);
for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) {
if (!tbl.bufq[i].active) {
CAM_DBG(CAM_MEM,
@ -993,21 +1009,25 @@ static int cam_mem_mgr_cleanup_table(void)
bitmap_zero(tbl.bitmap, tbl.bits);
/* We need to reserve slot 0 because 0 is invalid */
set_bit(0, tbl.bitmap);
mutex_unlock(&tbl.m_lock);
return 0;
}
void cam_mem_mgr_deinit(void)
{
atomic_set(&cam_mem_mgr_state, CAM_MEM_MGR_UNINITIALIZED);
cam_mem_mgr_cleanup_table();
mutex_lock(&tbl.m_lock);
if (!atomic_dec_and_test(&cam_mem_mgr_refcnt)) {
CAM_DBG(CAM_MEM, "Mem mgr refcnt: %d",
atomic_read(&cam_mem_mgr_refcnt));
mutex_unlock(&tbl.m_lock);
return;
}
cam_mem_mgr_cleanup_table();
bitmap_zero(tbl.bitmap, tbl.bits);
kfree(tbl.bitmap);
tbl.bitmap = NULL;
mutex_unlock(&tbl.m_lock);
mutex_destroy(&tbl.m_lock);
}
static int cam_mem_util_unmap(int32_t idx,
@ -1098,7 +1118,7 @@ int cam_mem_mgr_release(struct cam_mem_mgr_release_cmd *cmd)
int idx;
int rc;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -1151,7 +1171,7 @@ int cam_mem_mgr_request_mem(struct cam_mem_mgr_request_desc *inp,
enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -1276,7 +1296,7 @@ int cam_mem_mgr_release_mem(struct cam_mem_mgr_memory_desc *inp)
int32_t idx;
int rc;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -1329,7 +1349,7 @@ int cam_mem_mgr_reserve_memory_region(struct cam_mem_mgr_request_desc *inp,
int32_t smmu_hdl = 0;
int32_t num_hdl = 0;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}
@ -1423,7 +1443,7 @@ int cam_mem_mgr_free_memory_region(struct cam_mem_mgr_memory_desc *inp)
int rc;
int32_t smmu_hdl;
if (!atomic_read(&cam_mem_mgr_state)) {
if (!atomic_read(&cam_mem_mgr_refcnt)) {
CAM_ERR(CAM_MEM, "failed. mem_mgr not initialized");
return -EINVAL;
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2019, 2021 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -20,12 +20,6 @@
#define CAM_MEM_BUFQ_MAX 1024
/* Enum for possible mem mgr states */
enum cam_mem_mgr_state {
CAM_MEM_MGR_UNINITIALIZED,
CAM_MEM_MGR_INITIALIZED,
};
/*Enum for possible SMMU operations */
enum cam_smmu_mapping_client {
CAM_SMMU_MAPPING_USER,

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -128,21 +128,6 @@ static int32_t cam_get_free_handle_index(void)
return idx;
}
static void cam_dump_tbl_info(void)
{
int i;
for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++)
CAM_INFO(CAM_CRM, "session_hdl=%x hdl_value=%x\n"
"type=%d state=%d dev_id=%lld",
hdl_tbl->hdl[i].session_hdl,
hdl_tbl->hdl[i].hdl_value,
hdl_tbl->hdl[i].type,
hdl_tbl->hdl[i].state,
hdl_tbl->hdl[i].dev_id);
}
int32_t cam_create_session_hdl(void *priv)
{
int idx;
@ -159,7 +144,6 @@ int32_t cam_create_session_hdl(void *priv)
idx = cam_get_free_handle_index();
if (idx < 0) {
CAM_ERR(CAM_CRM, "Unable to create session handle");
cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock);
return idx;
}
@ -193,7 +177,6 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
idx = cam_get_free_handle_index();
if (idx < 0) {
CAM_ERR(CAM_CRM, "Unable to create device handle");
cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock);
return idx;
}

View File

@ -485,6 +485,7 @@ static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest,
source->buff_pool_base_sgt);
if (result) {
kfree(dest->data_buff_list);
dest->data_buff_list = NULL;
return result;
}
@ -492,6 +493,7 @@ static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest,
source->ring_base_sgt);
if (result) {
kfree(dest->data_buff_list);
dest->data_buff_list = NULL;
ipa_smmu_free_sgt(&dest->buff_pool_base_sgt);
return result;
}
@ -502,6 +504,7 @@ static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest,
static void ipa_uc_ntn_free_conn_smmu_info(struct ipa_ntn_setup_info *params)
{
kfree(params->data_buff_list);
params->data_buff_list = NULL;
ipa_smmu_free_sgt(&params->buff_pool_base_sgt);
ipa_smmu_free_sgt(&params->ring_base_sgt);
}

View File

@ -381,6 +381,7 @@ static void ipa3_active_clients_log_destroy(void)
kfree(active_clients_table_buf);
active_clients_table_buf = NULL;
kfree(ipa3_ctx->ipa3_active_clients_logging.log_buffer[0]);
ipa3_ctx->ipa3_active_clients_logging.log_buffer[0] = NULL;
ipa3_ctx->ipa3_active_clients_logging.log_head = 0;
ipa3_ctx->ipa3_active_clients_logging.log_tail =
IPA3_ACTIVE_CLIENTS_LOG_BUFFER_SIZE_LINES - 1;
@ -7574,8 +7575,10 @@ fail_bus_reg:
fail_init_mem_partition:
fail_bind:
kfree(ipa3_ctx->ctrl);
ipa3_ctx->ctrl = NULL;
fail_mem_ctrl:
kfree(ipa3_ctx->ipa_tz_unlock_reg);
ipa3_ctx->ipa_tz_unlock_reg = NULL;
fail_tz_unlock_reg:
if (ipa3_ctx->logbuf)
ipc_log_context_destroy(ipa3_ctx->logbuf);
@ -8015,6 +8018,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
IPAERR("failed to read register addresses\n");
kfree(ipa_tz_unlock_reg);
kfree(ipa_drv_res->ipa_tz_unlock_reg);
ipa_drv_res->ipa_tz_unlock_reg = NULL;
return -EFAULT;
}

View File

@ -1264,10 +1264,12 @@ fail_repl:
ep->sys->repl_hdlr = ipa3_replenish_rx_cache;
ep->sys->repl->capacity = 0;
kfree(ep->sys->repl);
ep->sys->repl = NULL;
fail_page_recycle_repl:
if (ep->sys->page_recycle_repl) {
ep->sys->page_recycle_repl->capacity = 0;
kfree(ep->sys->page_recycle_repl);
ep->sys->page_recycle_repl = NULL;
}
fail_gen2:
if (ipa3_ctx->use_ipa_pm)
@ -2654,6 +2656,7 @@ static void ipa3_cleanup_rx(struct ipa3_sys_context *sys)
kfree(sys->repl->cache);
kfree(sys->repl);
sys->repl = NULL;
}
if (sys->page_recycle_repl) {
for (i = 0; i < sys->page_recycle_repl->capacity; i++) {
@ -2672,6 +2675,7 @@ static void ipa3_cleanup_rx(struct ipa3_sys_context *sys)
}
kfree(sys->page_recycle_repl->cache);
kfree(sys->page_recycle_repl);
sys->page_recycle_repl = NULL;
}
}

View File

@ -777,6 +777,7 @@ alloc_chrdev0_region_fail:
class_destroy(odl_cdev[0].class);
create_char_dev0_fail:
kfree(ipa3_odl_ctx);
ipa3_odl_ctx = NULL;
fail_mem_ctx:
return result;
}

View File

@ -637,6 +637,7 @@ int ipa_pm_init(struct ipa_pm_init_params *params)
if (!ipa_pm_ctx->wq) {
IPA_PM_ERR("create workqueue failed\n");
kfree(ipa_pm_ctx);
ipa_pm_ctx = NULL;
return -ENOMEM;
}

View File

@ -759,6 +759,7 @@ static void ipa_release_ap_smmu_mappings(enum ipa_client_type client)
ipa3_ctx->wdi_map_cnt--;
}
kfree(wdi_res[i].res);
wdi_res[i].res = NULL;
wdi_res[i].valid = false;
}
}
@ -795,6 +796,7 @@ static void ipa_release_uc_smmu_mappings(enum ipa_client_type client)
ipa3_ctx->wdi_map_cnt--;
}
kfree(wdi_res[i].res);
wdi_res[i].res = NULL;
wdi_res[i].valid = false;
}
}
@ -946,6 +948,7 @@ void ipa3_release_wdi3_gsi_smmu_mappings(u8 dir)
ipa3_ctx->wdi_map_cnt--;
}
kfree(wdi_res[i].res);
wdi_res[i].res = NULL;
wdi_res[i].valid = false;
}
}

View File

@ -175,6 +175,8 @@ int ion_hyp_assign_sg(struct sg_table *sgt, int *dest_vm_list,
if (dest_vm_list[i] == VMID_CP_SEC_DISPLAY ||
dest_vm_list[i] == VMID_CP_DSP_EXT)
dest_perms[i] = PERM_READ;
else if (dest_vm_list[i] == VMID_CP_CDSP)
dest_perms[i] = PERM_READ | PERM_WRITE | PERM_EXEC;
else if (dest_vm_list[i] == VMID_CP_CAMERA_ENCODE) {
j = i;
dest_perms[i] = PERM_READ | PERM_WRITE;
@ -305,6 +307,8 @@ int ion_hyp_assign_from_flags(u64 base, u64 size, unsigned long flags)
if (vmids[i] == VMID_CP_SEC_DISPLAY ||
vmids[i] == VMID_CP_DSP_EXT)
modes[i] = PERM_READ;
else if (vmids[i] == VMID_CP_CDSP)
modes[i] = PERM_READ | PERM_WRITE | PERM_EXEC;
else
modes[i] = PERM_READ | PERM_WRITE;

View File

@ -136,7 +136,7 @@ static char sensor_clients[QMI_TS_MAX_NR][QMI_CLIENT_NAME_LENGTH] = {
static int32_t encode_qmi(int32_t val)
{
uint32_t shift = 0, local_val = 0;
int32_t temp_val = 0;
unsigned long temp_val = 0;
if (val == INT_MAX || val == INT_MIN)
return 0;
@ -146,8 +146,7 @@ static int32_t encode_qmi(int32_t val)
temp_val *= -1;
local_val |= 1 << QMI_FL_SIGN_BIT;
}
shift = find_last_bit((const unsigned long *)&temp_val,
sizeof(temp_val) * 8);
shift = find_last_bit(&temp_val, sizeof(temp_val) * 8);
local_val |= ((shift + 127) << QMI_MANTISSA_MSB);
temp_val &= ~(1 << shift);
@ -291,6 +290,13 @@ static int qmi_ts_request(struct qmi_sensor *qmi_sens,
qmi_sens->low_thresh != INT_MIN;
req.temp_threshold_low =
encode_qmi(qmi_sens->low_thresh);
pr_debug("Sensor:%s set high_trip:%d, low_trip:%d, high_valid:%d, low_valid:%d\n",
qmi_sens->qmi_name,
qmi_sens->high_thresh,
qmi_sens->low_thresh,
req.temp_threshold_high_valid,
req.temp_threshold_low_valid);
}
mutex_lock(&ts->mutex);

View File

@ -2097,9 +2097,6 @@ static void msm_hs_config_port(struct uart_port *uport, int cfg_flags)
/* Handle CTS changes (Called from interrupt handler) */
static void msm_hs_handle_delta_cts_locked(struct uart_port *uport)
{
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
msm_hs_resource_vote(msm_uport);
/* clear interrupt */
msm_hs_write(uport, UART_DM_CR, RESET_CTS);
/* Calling CLOCK API. Hence mb() requires here. */
@ -2108,7 +2105,6 @@ static void msm_hs_handle_delta_cts_locked(struct uart_port *uport)
/* clear the IOCTL TIOCMIWAIT if called */
wake_up_interruptible(&uport->state->port.delta_msr_wait);
msm_hs_resource_unvote(msm_uport);
}
static irqreturn_t msm_hs_isr(int irq, void *dev)

View File

@ -36,6 +36,7 @@ struct drm_atomic_state;
struct drm_private_obj;
struct drm_private_state;
#ifdef CONFIG_DRM_KMS_HELPER
int drm_atomic_helper_check_modeset(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_atomic_helper_check_planes(struct drm_device *dev,
@ -179,6 +180,29 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
struct drm_modeset_acquire_ctx *ctx);
void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj,
struct drm_private_state *state);
#else
int drm_atomic_helper_disable_plane(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx)
{
return 0;
}
int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
struct drm_plane_state *plane_state)
{
return 0;
}
int drm_atomic_helper_set_config(struct drm_mode_set *set,
struct drm_modeset_acquire_ctx *ctx)
{
return 0;
}
int __drm_atomic_helper_set_config(struct drm_mode_set *set,
struct drm_atomic_state *state)
{
return 0;
}
#endif
/**
* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC

View File

@ -17,8 +17,6 @@ struct drm_gem_object;
struct drm_minor;
struct module;
#define DRM_CLIENT_MAX_CLONED_CONNECTORS 8
/**
* struct drm_client_funcs - DRM client callbacks
*/
@ -106,7 +104,9 @@ struct drm_client_dev {
int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
const char *name, const struct drm_client_funcs *funcs);
void drm_client_register(struct drm_client_dev *client);
void drm_client_release(struct drm_client_dev *client);
void drm_client_dev_register(struct drm_device *dev);
void drm_client_dev_unregister(struct drm_device *dev);
void drm_client_dev_hotplug(struct drm_device *dev);
void drm_client_dev_restore(struct drm_device *dev);
@ -149,11 +149,19 @@ struct drm_client_buffer {
struct drm_client_buffer *
drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
void *drm_client_buffer_vmap(struct drm_client_buffer *buffer);
void drm_client_buffer_vunmap(struct drm_client_buffer *buffer);
int drm_client_modeset_create(struct drm_client_dev *client);
void drm_client_modeset_free(struct drm_client_dev *client);
void drm_client_modeset_release(struct drm_client_dev *client);
struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc);
int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height);
int drm_client_modeset_commit_force(struct drm_client_dev *client);
int drm_client_modeset_commit(struct drm_client_dev *client);
int drm_client_modeset_dpms(struct drm_client_dev *client, int mode);
#ifdef CONFIG_DRM_CLIENT_BOOTSPLASH
void drm_bootsplash_client_register(struct drm_device *dev);
#endif
/**
* drm_client_for_each_modeset() - Iterate over client modesets
@ -164,6 +172,21 @@ struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, stru
for (({ lockdep_assert_held(&(client)->modeset_mutex); }), \
modeset = (client)->modesets; modeset->crtc; modeset++)
/**
* drm_client_for_each_connector_iter - connector_list iterator macro
* @connector: &struct drm_connector pointer used as cursor
* @iter: &struct drm_connector_list_iter
*
* This iterates the connectors that are useable for internal clients (excludes
* writeback connectors).
*
* For more info see drm_for_each_connector_iter().
*/
#define drm_client_for_each_connector_iter(connector, iter) \
drm_for_each_connector_iter(connector, iter) \
if ((connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)\
&& (connector->connector_type != DRM_MODE_CONNECTOR_VIRTUAL))
int drm_client_debugfs_init(struct drm_minor *minor);
#endif

View File

@ -657,6 +657,12 @@ struct drm_connector_funcs {
/* mode specified on the command line */
struct drm_cmdline_mode {
/**
* @name:
*
* Name of the mode.
*/
char name[DRM_DISPLAY_MODE_LEN];
bool specified;
bool refresh_specified;
bool bpp_specified;
@ -1103,4 +1109,17 @@ void drm_connector_list_iter_end(struct drm_connector_list_iter *iter);
#define drm_for_each_connector_iter(connector, iter) \
while ((connector = drm_connector_list_iter_next(iter)))
/**
* drm_connector_for_each_possible_encoder - iterate connector's possible encoders
* @connector: &struct drm_connector pointer
* @encoder: &struct drm_encoder pointer used as cursor
* @__i: int iteration cursor, for macro-internal use
*/
#define drm_connector_for_each_possible_encoder(connector, encoder, __i) \
for ((__i) = 0; (__i) < ARRAY_SIZE((connector)->encoder_ids) && \
(connector)->encoder_ids[(__i)] != 0; (__i)++) \
for_each_if((encoder) = \
drm_encoder_find((connector)->dev, NULL, \
(connector)->encoder_ids[(__i)])) \
#endif

View File

@ -150,6 +150,12 @@ enum drm_mode_status {
#define DRM_MODE_FLAG_3D_MAX DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF
#define DRM_MODE_MATCH_TIMINGS (1 << 0)
#define DRM_MODE_MATCH_CLOCK (1 << 1)
#define DRM_MODE_MATCH_FLAGS (1 << 2)
#define DRM_MODE_MATCH_3D_FLAGS (1 << 3)
#define DRM_MODE_MATCH_ASPECT_RATIO (1 << 4)
/**
* struct drm_display_mode - DRM kernel-internal display mode structure
* @hdisplay: horizontal display size
@ -493,6 +499,9 @@ void drm_mode_copy(struct drm_display_mode *dst,
const struct drm_display_mode *src);
struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
const struct drm_display_mode *mode);
bool drm_mode_match(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2,
unsigned int match_flags);
bool drm_mode_equal(const struct drm_display_mode *mode1,
const struct drm_display_mode *mode2);
bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,

View File

@ -92,6 +92,7 @@ enum {
CFTYPE_NO_PREFIX = (1 << 3), /* (DON'T USE FOR NEW FILES) no subsys prefix */
CFTYPE_WORLD_WRITABLE = (1 << 4), /* (DON'T USE FOR NEW FILES) S_IWUGO */
CFTYPE_PRESSURE = (1 << 6), /* only if pressure feature is enabled */
/* internal flags, do not use outside cgroup core proper */
__CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */

View File

@ -643,6 +643,8 @@ static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
return &cgrp->psi;
}
bool cgroup_psi_enabled(void);
static inline void cgroup_init_kthreadd(void)
{
/*
@ -707,6 +709,11 @@ static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
return NULL;
}
static inline bool cgroup_psi_enabled(void)
{
return false;
}
static inline bool task_under_cgroup_hierarchy(struct task_struct *task,
struct cgroup *ancestor)
{

View File

@ -322,6 +322,7 @@ enum drm_mode_subconnector {
#define DRM_MODE_CONNECTOR_VIRTUAL 15
#define DRM_MODE_CONNECTOR_DSI 16
#define DRM_MODE_CONNECTOR_DPI 17
#define DRM_MODE_CONNECTOR_WRITEBACK 18
struct drm_mode_get_connector {

View File

@ -203,6 +203,22 @@ struct cgroup_namespace init_cgroup_ns = {
static struct file_system_type cgroup2_fs_type;
static struct cftype cgroup_base_files[];
/* cgroup optional features */
enum cgroup_opt_features {
#ifdef CONFIG_PSI
OPT_FEATURE_PRESSURE,
#endif
OPT_FEATURE_COUNT
};
static const char *cgroup_opt_feature_names[OPT_FEATURE_COUNT] = {
#ifdef CONFIG_PSI
"pressure",
#endif
};
static u16 cgroup_feature_disable_mask __read_mostly;
static int cgroup_apply_control(struct cgroup *cgrp);
static void cgroup_finalize_control(struct cgroup *cgrp, int ret);
static void css_task_iter_skip(struct css_task_iter *it,
@ -3413,6 +3429,18 @@ static void cgroup_pressure_release(struct kernfs_open_file *of)
{
psi_trigger_replace(&of->priv, NULL);
}
bool cgroup_psi_enabled(void)
{
return (cgroup_feature_disable_mask & (1 << OPT_FEATURE_PRESSURE)) == 0;
}
#else /* CONFIG_PSI */
bool cgroup_psi_enabled(void)
{
return false;
}
#endif /* CONFIG_PSI */
static int cgroup_file_open(struct kernfs_open_file *of)
@ -3617,6 +3645,8 @@ static int cgroup_addrm_files(struct cgroup_subsys_state *css,
restart:
for (cft = cfts; cft != cft_end && cft->name[0] != '\0'; cft++) {
/* does cft->flags tell us to skip this file on @cgrp? */
if ((cft->flags & CFTYPE_PRESSURE) && !cgroup_psi_enabled())
continue;
if ((cft->flags & __CFTYPE_ONLY_ON_DFL) && !cgroup_on_dfl(cgrp))
continue;
if ((cft->flags & __CFTYPE_NOT_ON_DFL) && cgroup_on_dfl(cgrp))
@ -3693,6 +3723,9 @@ static int cgroup_init_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
WARN_ON(cft->ss || cft->kf_ops);
if ((cft->flags & CFTYPE_PRESSURE) && !cgroup_psi_enabled())
continue;
if (cft->seq_start)
kf_ops = &cgroup_kf_ops;
else
@ -4587,7 +4620,7 @@ static struct cftype cgroup_base_files[] = {
#ifdef CONFIG_PSI
{
.name = "io.pressure",
.flags = CFTYPE_NOT_ON_ROOT,
.flags = CFTYPE_NOT_ON_ROOT | CFTYPE_PRESSURE,
.seq_show = cgroup_io_pressure_show,
.write = cgroup_io_pressure_write,
.poll = cgroup_pressure_poll,
@ -4595,7 +4628,7 @@ static struct cftype cgroup_base_files[] = {
},
{
.name = "memory.pressure",
.flags = CFTYPE_NOT_ON_ROOT,
.flags = CFTYPE_NOT_ON_ROOT | CFTYPE_PRESSURE,
.seq_show = cgroup_memory_pressure_show,
.write = cgroup_memory_pressure_write,
.poll = cgroup_pressure_poll,
@ -4603,7 +4636,7 @@ static struct cftype cgroup_base_files[] = {
},
{
.name = "cpu.pressure",
.flags = CFTYPE_NOT_ON_ROOT,
.flags = CFTYPE_NOT_ON_ROOT | CFTYPE_PRESSURE,
.seq_show = cgroup_cpu_pressure_show,
.write = cgroup_cpu_pressure_write,
.poll = cgroup_pressure_poll,
@ -5770,6 +5803,15 @@ static int __init cgroup_disable(char *str)
continue;
cgroup_disable_mask |= 1 << i;
}
for (i = 0; i < OPT_FEATURE_COUNT; i++) {
if (strcmp(token, cgroup_opt_feature_names[i]))
continue;
cgroup_feature_disable_mask |= 1 << i;
pr_info("Disabling %s control group feature\n",
cgroup_opt_feature_names[i]);
break;
}
}
return 1;
}

View File

@ -146,6 +146,7 @@
static int psi_bug __read_mostly;
DEFINE_STATIC_KEY_FALSE(psi_disabled);
DEFINE_STATIC_KEY_TRUE(psi_cgroups_enabled);
#ifdef CONFIG_PSI_DEFAULT_DISABLED
static bool psi_enable;
@ -210,6 +211,9 @@ void __init psi_init(void)
return;
}
if (!cgroup_psi_enabled())
static_branch_disable(&psi_cgroups_enabled);
psi_period = jiffies_to_nsecs(PSI_FREQ);
group_init(&psi_system);
}
@ -723,23 +727,23 @@ static u32 psi_group_change(struct psi_group *group, int cpu,
static struct psi_group *iterate_groups(struct task_struct *task, void **iter)
{
if (*iter == &psi_system)
return NULL;
#ifdef CONFIG_CGROUPS
struct cgroup *cgroup = NULL;
if (static_branch_likely(&psi_cgroups_enabled)) {
struct cgroup *cgroup = NULL;
if (!*iter)
cgroup = task->cgroups->dfl_cgrp;
else if (*iter == &psi_system)
return NULL;
else
cgroup = cgroup_parent(*iter);
if (!*iter)
cgroup = task->cgroups->dfl_cgrp;
else
cgroup = cgroup_parent(*iter);
if (cgroup && cgroup_parent(cgroup)) {
*iter = cgroup;
return cgroup_psi(cgroup);
if (cgroup && cgroup_parent(cgroup)) {
*iter = cgroup;
return cgroup_psi(cgroup);
}
}
#else
if (*iter)
return NULL;
#endif
*iter = &psi_system;
return &psi_system;

View File

@ -2654,7 +2654,7 @@ sub process {
"email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
}
}
if ($chk_author && $line =~ /^\s*signed-off-by:.*(quicinc|qualcomm)\.com/i) {
if ($chk_author && $line =~ /^\s*signed-off-by:.*(qualcomm)\.com/i) {
WARN("BAD_SIGN_OFF",
"invalid Signed-off-by identity\n" . $line );
}
@ -2787,7 +2787,7 @@ sub process {
}
#check the patch for invalid author credentials
if ($chk_author && $line =~ /^From:.*(quicinc|qualcomm)\.com/) {
if ($chk_author && $line =~ /^From:.*(qualcomm)\.com/) {
WARN("BAD_AUTHOR", "invalid author identity\n" . $line );
}