Merge branch 'partner/android-exynos-r11-4.19-rvc-jr3' into android-exynos-r11-4.19

JUL 2023.1

Bug: 280774281
Change-Id: I2b5558abf36662bf0a5bcdd9e02f113027b16012
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 337e177..252d13b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -468,9 +468,19 @@
  *                        (protected by binder_deferred_lock)
  * @deferred_work:        bitmap of deferred work to perform
  *                        (protected by binder_deferred_lock)
+ * @outstanding_txns:     number of transactions to be transmitted before
+ *                        processes in freeze_wait are woken up
+ *                        (protected by @inner_lock)
  * @is_dead:              process is dead and awaiting free
  *                        when outstanding transactions are cleaned up
  *                        (protected by @inner_lock)
+ * @sync_recv:            process received sync transactions since last frozen
+ *                        (protected by @inner_lock)
+ * @async_recv:           process received async transactions since last frozen
+ *                        (protected by @inner_lock)
+ * @freeze_wait:          waitqueue of processes waiting for all outstanding
+ *                        transactions to be processed
+ *                        (protected by @inner_lock)
  * @todo:                 list of work for this process
  *                        (protected by @inner_lock)
  * @stats:                per-process binder statistics
@@ -514,7 +524,12 @@
 	const struct cred *cred;
 	struct hlist_node deferred_work_node;
 	int deferred_work;
+	int outstanding_txns;
 	bool is_dead;
+	bool is_frozen;
+	bool sync_recv;
+	bool async_recv;
+	wait_queue_head_t freeze_wait;
 
 	struct list_head todo;
 	struct binder_stats stats;
@@ -2087,6 +2102,10 @@
 
 	if (target_proc) {
 		binder_inner_proc_lock(target_proc);
+		target_proc->outstanding_txns--;
+		BUG_ON(target_proc->outstanding_txns < 0);
+		if (!target_proc->outstanding_txns && target_proc->is_frozen)
+			wake_up_interruptible_all(&target_proc->freeze_wait);
 		if (t->buffer)
 			t->buffer->transaction = NULL;
 		binder_inner_proc_unlock(target_proc);
@@ -2837,10 +2856,11 @@
  * If the @thread parameter is not NULL, the transaction is always queued
  * to the waitlist of that specific thread.
  *
- * Return:	true if the transactions was successfully queued
- *		false if the target process or thread is dead
+ * Return:	0 if the transaction was successfully queued
+ *		BR_DEAD_REPLY if the target process or thread is dead
+ *		BR_FROZEN_REPLY if the target process or thread is frozen
  */
-static bool binder_proc_transaction(struct binder_transaction *t,
+static int binder_proc_transaction(struct binder_transaction *t,
 				    struct binder_proc *proc,
 				    struct binder_thread *thread)
 {
@@ -2864,11 +2884,18 @@
 	}
 
 	binder_inner_proc_lock(proc);
+	if (proc->is_frozen) {
+		proc->sync_recv |= !oneway;
+		proc->async_recv |= oneway;
+	}
 
-	if (proc->is_dead || (thread && thread->is_dead)) {
+	if ((proc->is_frozen && !oneway) || proc->is_dead ||
+			(thread && thread->is_dead)) {
+		bool proc_is_dead = proc->is_dead
+			|| (thread && thread->is_dead);
 		binder_inner_proc_unlock(proc);
 		binder_node_unlock(node);
-		return false;
+		return proc_is_dead ? BR_DEAD_REPLY : BR_FROZEN_REPLY;
 	}
 
 	if (!thread && !pending_async)
@@ -2887,10 +2914,11 @@
 	if (!pending_async)
 		binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */);
 
+	proc->outstanding_txns++;
 	binder_inner_proc_unlock(proc);
 	binder_node_unlock(node);
 
-	return true;
+	return 0;
 }
 
 /**
@@ -3508,13 +3536,16 @@
 	if (reply) {
 		binder_enqueue_thread_work(thread, tcomplete);
 		binder_inner_proc_lock(target_proc);
-		if (target_thread->is_dead) {
+		if (target_thread->is_dead || target_proc->is_frozen) {
+			return_error = target_thread->is_dead ?
+				BR_DEAD_REPLY : BR_FROZEN_REPLY;
 			binder_inner_proc_unlock(target_proc);
 			goto err_dead_proc_or_thread;
 		}
 		BUG_ON(t->buffer->async_transaction != 0);
 		binder_pop_transaction_ilocked(target_thread, in_reply_to);
 		binder_enqueue_thread_work_ilocked(target_thread, &t->work);
+		target_proc->outstanding_txns++;
 		binder_inner_proc_unlock(target_proc);
 		wake_up_interruptible_sync(&target_thread->wait);
 		binder_restore_priority(current, in_reply_to->saved_priority);
@@ -3534,7 +3565,9 @@
 		t->from_parent = thread->transaction_stack;
 		thread->transaction_stack = t;
 		binder_inner_proc_unlock(proc);
-		if (!binder_proc_transaction(t, target_proc, target_thread)) {
+		return_error = binder_proc_transaction(t,
+				target_proc, target_thread);
+		if (return_error) {
 			binder_inner_proc_lock(proc);
 			binder_pop_transaction_ilocked(thread, t);
 			binder_inner_proc_unlock(proc);
@@ -3544,7 +3577,8 @@
 		BUG_ON(target_node == NULL);
 		BUG_ON(t->buffer->async_transaction != 1);
 		binder_enqueue_thread_work(thread, tcomplete);
-		if (!binder_proc_transaction(t, target_proc, NULL))
+		return_error = binder_proc_transaction(t, target_proc, NULL);
+		if (return_error)
 			goto err_dead_proc_or_thread;
 	}
 	if (target_thread)
@@ -3561,7 +3595,6 @@
 	return;
 
 err_dead_proc_or_thread:
-	return_error = BR_DEAD_REPLY;
 	return_error_line = __LINE__;
 	binder_dequeue_work(proc, tcomplete);
 err_translate_failed:
@@ -4167,7 +4200,7 @@
 		binder_inner_proc_lock(proc);
 		list_del_init(&thread->waiting_thread_node);
 		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
+			ret = -EINTR;
 			break;
 		}
 	}
@@ -4671,6 +4704,7 @@
 
 	BUG_ON(!list_empty(&proc->todo));
 	BUG_ON(!list_empty(&proc->delivered_death));
+	WARN_ON(proc->outstanding_txns);
 	device = container_of(proc->context, struct binder_device, context);
 	if (refcount_dec_and_test(&device->ref)) {
 		kfree(proc->context->name);
@@ -4732,6 +4766,7 @@
 			     (t->to_thread == thread) ? "in" : "out");
 
 		if (t->to_thread == thread) {
+			t->to_proc->outstanding_txns--;
 			t->to_proc = NULL;
 			t->to_thread = NULL;
 			if (t->buffer) {
@@ -4975,6 +5010,76 @@
 	return 0;
 }
 
+static int binder_ioctl_freeze(struct binder_freeze_info *info,
+			       struct binder_proc *target_proc)
+{
+	int ret = 0;
+
+	if (!info->enable) {
+		binder_inner_proc_lock(target_proc);
+		target_proc->sync_recv = false;
+		target_proc->async_recv = false;
+		target_proc->is_frozen = false;
+		binder_inner_proc_unlock(target_proc);
+		return 0;
+	}
+
+	/*
+	 * Freezing the target. Prevent new transactions by
+	 * setting frozen state. If timeout specified, wait
+	 * for transactions to drain.
+	 */
+	binder_inner_proc_lock(target_proc);
+	target_proc->sync_recv = false;
+	target_proc->async_recv = false;
+	target_proc->is_frozen = true;
+	binder_inner_proc_unlock(target_proc);
+
+	if (info->timeout_ms > 0)
+		ret = wait_event_interruptible_timeout(
+			target_proc->freeze_wait,
+			(!target_proc->outstanding_txns),
+			msecs_to_jiffies(info->timeout_ms));
+
+	if (!ret && target_proc->outstanding_txns)
+		ret = -EAGAIN;
+
+	if (ret < 0) {
+		binder_inner_proc_lock(target_proc);
+		target_proc->is_frozen = false;
+		binder_inner_proc_unlock(target_proc);
+	}
+
+	return ret;
+}
+
+static int binder_ioctl_get_freezer_info(
+				struct binder_frozen_status_info *info)
+{
+	struct binder_proc *target_proc;
+	bool found = false;
+
+	info->sync_recv = 0;
+	info->async_recv = 0;
+
+	mutex_lock(&binder_procs_lock);
+	hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
+		if (target_proc->pid == info->pid) {
+			found = true;
+			binder_inner_proc_lock(target_proc);
+			info->sync_recv |= target_proc->sync_recv;
+			info->async_recv |= target_proc->async_recv;
+			binder_inner_proc_unlock(target_proc);
+		}
+	}
+	mutex_unlock(&binder_procs_lock);
+
+	if (!found)
+		return -EINVAL;
+
+	return 0;
+}
+
 static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	int ret;
@@ -5093,6 +5198,84 @@
 		}
 		break;
 	}
+	case BINDER_FREEZE: {
+		struct binder_freeze_info info;
+		struct binder_proc **target_procs = NULL, *target_proc;
+		int target_procs_count = 0, i = 0;
+
+		ret = 0;
+
+		if (copy_from_user(&info, ubuf, sizeof(info))) {
+			ret = -EFAULT;
+			goto err;
+		}
+
+		mutex_lock(&binder_procs_lock);
+		hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
+			if (target_proc->pid == info.pid)
+				target_procs_count++;
+		}
+
+		if (target_procs_count == 0) {
+			mutex_unlock(&binder_procs_lock);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		target_procs = kmalloc(sizeof(struct binder_proc *) *
+					       target_procs_count,
+				       GFP_KERNEL);
+
+		if (!target_procs) {
+			mutex_unlock(&binder_procs_lock);
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
+			if (target_proc->pid != info.pid)
+				continue;
+
+			binder_inner_proc_lock(target_proc);
+			target_proc->tmp_ref++;
+			binder_inner_proc_unlock(target_proc);
+
+			target_procs[i++] = target_proc;
+		}
+		mutex_unlock(&binder_procs_lock);
+
+		for (i = 0; i < target_procs_count; i++) {
+			if (ret >= 0)
+				ret = binder_ioctl_freeze(&info,
+							  target_procs[i]);
+
+			binder_proc_dec_tmpref(target_procs[i]);
+		}
+
+		kfree(target_procs);
+
+		if (ret < 0)
+			goto err;
+		break;
+	}
+	case BINDER_GET_FROZEN_INFO: {
+		struct binder_frozen_status_info info;
+
+		if (copy_from_user(&info, ubuf, sizeof(info))) {
+			ret = -EFAULT;
+			goto err;
+		}
+
+		ret = binder_ioctl_get_freezer_info(&info);
+		if (ret < 0)
+			goto err;
+
+		if (copy_to_user(ubuf, &info, sizeof(info))) {
+			ret = -EFAULT;
+			goto err;
+		}
+		break;
+	}
 	default:
 		ret = -EINVAL;
 		goto err;
@@ -5102,7 +5285,7 @@
 	if (thread)
 		thread->looper_need_return = false;
 	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
-	if (ret && ret != -ERESTARTSYS)
+	if (ret && ret != -EINTR)
 		pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
 err_unlocked:
 	trace_binder_ioctl_done(ret);
@@ -5207,6 +5390,7 @@
 	mutex_init(&proc->files_lock);
 	proc->cred = get_cred(filp->f_cred);
 	INIT_LIST_HEAD(&proc->todo);
+	init_waitqueue_head(&proc->freeze_wait);
 	if (binder_supported_policy(current->policy)) {
 		proc->default_priority.sched_policy = current->policy;
 		proc->default_priority.prio = current->normal_prio;
@@ -5428,6 +5612,9 @@
 	proc->tmp_ref++;
 
 	proc->is_dead = true;
+	proc->is_frozen = false;
+	proc->sync_recv = false;
+	proc->async_recv = false;
 	threads = 0;
 	active_transactions = 0;
 	while ((n = rb_first(&proc->threads))) {
diff --git a/drivers/video/fbdev/exynos/dpu30/panels/panel-boe-wf012fbm.c b/drivers/video/fbdev/exynos/dpu30/panels/panel-boe-wf012fbm.c
index 2e60e6f..1f7a1d1 100644
--- a/drivers/video/fbdev/exynos/dpu30/panels/panel-boe-wf012fbm.c
+++ b/drivers/video/fbdev/exynos/dpu30/panels/panel-boe-wf012fbm.c
@@ -19,6 +19,28 @@
 
 #define PANEL_MAX_TRIES 3
 
+// Look up table to convert between AOD and Interactive DBV that would
+// yield the same display nits, defined in go/rh-eos-dbv-lut
+const static u8 InteractiveToAodDbvLUT[] = {
+	0,   3,   5,   5,   8,   15,  16,  21,  25,  30,  33,  38,  43,
+	47,  51,  56,  59,  69,  69,  72,  77,  79,  81,  83,  86,  88,
+	90,  92,  94,  96,  98,  101, 103, 106, 110, 112, 114, 116, 120,
+	122, 125, 128, 130, 134, 136, 140, 143, 146, 149, 152, 155, 158,
+	162, 166, 169, 174, 178, 182, 186, 188, 192, 196, 201, 205, 211,
+	215, 220, 225, 228, 232, 237, 241, 246, 251
+};
+
+static u8 interactive_to_aod_brightness(u8 interactive_brightness)
+{
+	if (interactive_brightness >= sizeof(InteractiveToAodDbvLUT)) {
+		// This means Interactive brightness (nits) is already saturated
+		// if converted to Doze brightness (i.e. > max AOD 150 nits).
+		// Let's return the maximum DBV here, which is 255.
+		return 255;
+	}
+	return InteractiveToAodDbvLUT[interactive_brightness];
+}
+
 static int wf012fbm_suspend(struct exynos_panel_device *panel)
 {
 	struct dsim_device *dsim = get_dsim_drvdata(0);
@@ -81,6 +103,19 @@
 	dsim_write_data_seq(dsim, false, 0x57, 0x30);
 	dsim_write_data_seq(dsim, false, 0xff, 0x10);
 
+	/* Disable master DBV control mode */
+	dsim_write_data_seq(dsim, false, 0xff, 0x21);
+	dsim_write_data_seq(dsim, false, 0xfb, 0x01);
+	dsim_write_data_seq(dsim, false, 0x5d, 0x00);
+	dsim_write_data_seq(dsim, false, 0xff, 0x10);
+
+	/* No gradual DBV change during the mode transition */
+	dsim_write_data_seq(dsim, false, 0xff, 0x25);
+	dsim_write_data_seq(dsim, false, 0xfb, 0x01);
+	dsim_write_data_seq(dsim, false, 0x74, 0xa1);
+	dsim_write_data_seq(dsim, false, 0x76, 0x51);
+	dsim_write_data_seq(dsim, false, 0xff, 0x10);
+
 	/* Write sequence for setting the PWM frequency if necessary*/
 	ret = dsim_read_data(dsim, MIPI_DSI_DCS_READ,
 			0xDA, sizeof(buf), buf);
@@ -350,50 +385,13 @@
 static int wf012fbm_doze(struct exynos_panel_device *panel)
 {
 	struct dsim_device *dsim = get_dsim_drvdata(0);
-	u8 aod_brightness = 0;
-	u8 interactive_brightness = 0;
-	u16 brightness_u16 = 0;
 
 	DPU_INFO_PANEL("%s +\n", __func__);
 	mutex_lock(&panel->ops_lock);
 	/* Page select */
 	dsim_write_data_seq(dsim, false, 0xff, 0x10);
-	/* Calculate normalized brightness */
-	interactive_brightness = panel->bl->props.brightness;
-	if (interactive_brightness > 0) {
-		brightness_u16 =
-			DIV_ROUND_CLOSEST(interactive_brightness * 650, 150);
-		/* If normalized brightness is set late after mode-change
-		frame finish, it could cause a dip when interactive brightness
-		gets scaled down (150/650) and rises back up to the normalized
-		level. To cover for this case, let's scale down the normalized
-		brightness by 90% so that it doesn't rise back up. This should
-		only apply to brighter level (i.e. > 20/255) where the dip
-		could be seen easily. */
-		if (interactive_brightness > 20) {
-			brightness_u16 = brightness_u16 * 90 / 100;
-		}
-		aod_brightness = brightness_u16 > 255 ? 255 : brightness_u16;
-	}
-
 	/* Idle Mode */
 	dsim_write_data_seq(dsim, false, MIPI_DCS_ENTER_IDLE_MODE);
-	/* Set normalized brightness */
-	if (!panel->doze_brightness_normalized && aod_brightness != 0) {
-		/* Delay until mode-change frame.
-		This requires an exact delay of 1 frame after exit-doze cmd */
-		usleep_range(16667, 16667);
-		/* Disable brightness dimming */
-		dsim_write_data_seq(dsim, false, 0x53, 0x20);
-		/* Set normalized brightness */
-		dsim_write_data_seq(dsim, false, 0x51, aod_brightness);
-		/* Delay until mode-change frame ends */
-		usleep_range(16667, 16667);
-		/* Enable brightness dimming */
-		dsim_write_data_seq(dsim, false, 0x53, 0x28);
-		panel->doze_brightness_normalized = true;
-	}
-
 	/* Exit HBM in case it's on */
 	dsim_write_data_seq(dsim, false, 0x66, 0x00);
 
@@ -409,7 +407,8 @@
 
 static int wf012fbm_set_light(struct exynos_panel_device *panel, u32 br_val)
 {
-	u8 data;
+	u8 interactive_brightness;
+	u8 aod_brightness;
 	struct dsim_device *dsim = get_dsim_drvdata(0);
 	/*
 	 * Only set brightness if it's not currently in doze mode as AP
@@ -424,9 +423,14 @@
 	if (dsim->state != DSIM_STATE_DOZE) {
 		mutex_lock(&panel->ops_lock);
 		/* WRDISBV(8bit): 1st DBV[7:0] */
-		data = br_val & 0xFF;
-		dsim_write_data_seq(dsim, false, 0x51, data);
+		interactive_brightness = br_val & 0xFF;
+		aod_brightness =
+			interactive_to_aod_brightness(interactive_brightness);
+		dsim_write_data_seq(dsim, false, 0x51, interactive_brightness);
+		dsim_write_data_seq(dsim, false, 0x61, aod_brightness);
 		mutex_unlock(&panel->ops_lock);
+		DPU_INFO_PANEL("%s: set brightness (i=%d, aod=%d)\n", __func__,
+			       interactive_brightness, aod_brightness);
 	} else {
 		DPU_INFO_PANEL("%s: skip doze br=%d\n", __func__, br_val);
 	}
@@ -466,50 +470,22 @@
 static int wf012fbm_exit_doze(struct exynos_panel_device *panel)
 {
 	struct dsim_device *dsim = get_dsim_drvdata(0);
-	unsigned char buf[1] = {0};
-	u8 normalized_brightness = 0;
+	u8 brightness = 0;
 
 	DPU_INFO_PANEL("%s +\n", __func__);
 	mutex_lock(&panel->ops_lock);
+	/* page select 0x10 */
 	dsim_write_data_seq(dsim, false, 0xff, 0x10);
-	/* Read brightness */
-	dsim_read_data(dsim, MIPI_DSI_DCS_READ,
-			MIPI_DCS_GET_DISPLAY_BRIGHTNESS, sizeof(buf), buf);
-	if (buf[0] != 0) {
-		panel->bl->props.brightness = buf[0];
-		/* Calculate interactive DBV that would yield the same
-		brightness nits to the current AOD DBV.
-		As both interactive and AOD DBV-nits conversion are linear,
-		this can be done by scaling with the max brightness nits
-		(150 nits for AOD and 650 nits for interactive at DBV255) */
-		normalized_brightness = DIV_ROUND_CLOSEST(buf[0] * 150, 650);
-		/* If normalized brightness is set late after mode-change
-		frame finish, it could cause a spike when AOD brightness gets
-		scaled up (650/150) and dip back down to the normalized level.
-		To cover for this case, let's scale up the normalized
-		brightness by 120% so that it doesn't dip back down */
-		normalized_brightness = normalized_brightness * 120 / 100;
+	/* Read interactive brightness */
+	dsim_read_data(dsim, MIPI_DSI_DCS_READ, 0x51,
+			sizeof(brightness), &brightness);
+	if (brightness != 0) {
+		panel->bl->props.brightness = brightness;
 	}
 	/* Exit Idle Mode */
 	dsim_write_data_seq(dsim, false, MIPI_DCS_EXIT_IDLE_MODE);
-	/* Flatten mode-change brightness ramp */
-	if (normalized_brightness != 0) {
-		panel->bl->props.brightness = normalized_brightness;
-		/* Delay until mode-change frame.
-		This requires an exact delay of 1 frame after exit-doze cmd */
-		usleep_range(16667, 16667);
-		/* Disable brightness dimming */
-		dsim_write_data_seq(dsim, false, 0x53, 0x20);
-		/* Set normalized brightness */
-		dsim_write_data_seq(dsim, false, 0x51, normalized_brightness);
-		/* Delay until mode-change frame ends */
-		usleep_range(16667, 16667);
-		/* Enable brightness dimming */
-		dsim_write_data_seq(dsim, false, 0x53, 0x28);
-	}
-	panel->doze_brightness_normalized = false;
 	mutex_unlock(&panel->ops_lock);
-	DPU_INFO_PANEL("%s -\n", __func__);
+	DPU_INFO_PANEL("%s - read br=%d\n", __func__, brightness);
 	return 0;
 }
 
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index f02aef1..4ad24d0 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -517,7 +517,8 @@
 	if (unlikely(!inode))
 		return failed_creating(dentry);
 
-	inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+	/* Do not set bits for OTH */
+	inode->i_mode = S_IFDIR | S_IRWXU | S_IRUSR| S_IRGRP | S_IXUSR | S_IXGRP;
 	inode->i_op = ops;
 	inode->i_fop = &simple_dir_operations;
 	inode->i_uid = d_inode(dentry->d_parent)->i_uid;
diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h
index 36a53fd..d5bcba6 100644
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -264,6 +264,18 @@
 	__u32            reserved3;
 };
 
+struct binder_freeze_info {
+	__u32            pid;
+	__u32            enable;
+	__u32            timeout_ms;
+};
+
+struct binder_frozen_status_info {
+	__u32            pid;
+	__u32            sync_recv;
+	__u32            async_recv;
+};
+
 #define BINDER_WRITE_READ		_IOWR('b', 1, struct binder_write_read)
 #define BINDER_SET_IDLE_TIMEOUT		_IOW('b', 3, __s64)
 #define BINDER_SET_MAX_THREADS		_IOW('b', 5, __u32)
@@ -274,6 +286,8 @@
 #define BINDER_GET_NODE_DEBUG_INFO	_IOWR('b', 11, struct binder_node_debug_info)
 #define BINDER_GET_NODE_INFO_FOR_REF	_IOWR('b', 12, struct binder_node_info_for_ref)
 #define BINDER_SET_CONTEXT_MGR_EXT	_IOW('b', 13, struct flat_binder_object)
+#define BINDER_FREEZE			_IOW('b', 14, struct binder_freeze_info)
+#define BINDER_GET_FROZEN_INFO		_IOWR('b', 15, struct binder_frozen_status_info)
 
 /*
  * NOTE: Two special error codes you should check for when calling
@@ -454,6 +468,12 @@
 	 * The the last transaction (either a bcTRANSACTION or
 	 * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory).  No parameters.
 	 */
+
+	BR_FROZEN_REPLY = _IO('r', 18),
+	/*
+	 * The target of the last transaction (either a bcTRANSACTION or
+	 * a bcATTEMPT_ACQUIRE) is frozen.  No parameters.
+	 */
 };
 
 enum binder_driver_command_protocol {