diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 143deb624..f4b277c6b 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -72,7 +72,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port)
 	atomic_dec(&buf->priority);
 	mutex_unlock(&buf->lock);
 	if (restart)
-		queue_work(system_unbound_wq, &buf->work);
+		queue_work(tty_wq, &buf->work);
 }
 EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive);
 
@@ -364,7 +364,7 @@ void tty_schedule_flip(struct tty_port *port)
 	struct tty_bufhead *buf = &port->buf;
 
 	buf->tail->commit = buf->tail->used;
-	schedule_work(&buf->work);
+	queue_work(tty_wq, &buf->work);
 }
 EXPORT_SYMBOL(tty_schedule_flip);
 
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 39988fa91..ffafe3c3a 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -110,6 +110,10 @@
 #define TTY_PARANOIA_CHECK 1
 #define CHECK_TTY_COUNT 1
 
+// for tty_buffer
+struct workqueue_struct* tty_wq __read_mostly;
+EXPORT_SYMBOL(tty_wq);
+
 struct ktermios tty_std_termios = {	/* for the benefit of tty drivers  */
 	.c_iflag = ICRNL | IXON,
 	.c_oflag = OPOST | ONLCR,
@@ -3584,6 +3588,10 @@ void console_sysfs_notify(void)
  */
 int __init tty_init(void)
 {
+	tty_wq = alloc_workqueue("%s", WQ_UNBOUND|WQ_MEM_RECLAIM|WQ_SYSFS, 1, "tty_wq");
+	if(WARN_ON(!tty_wq)){
+		tty_wq = system_wq;
+	}
 	cdev_init(&tty_cdev, &tty_fops);
 	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 22da05d27..d6b9724d8 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -267,7 +267,7 @@ static void unset_locked_termios(struct ktermios *termios,
  * include/asm/termbits.h file.
  */
 static const speed_t baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+	0, 31250, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
 	9600, 19200, 38400, 57600, 115200, 230400, 460800,
 #ifdef __sparc__
 	76800, 153600, 307200, 614400, 921600
@@ -279,7 +279,7 @@ static const speed_t baud_table[] = {
 
 #ifndef __sparc__
 static const tcflag_t baud_bits[] = {
-	B0, B50, B75, B110, B134, B150, B200, B300, B600,
+	B0, B31250, B75, B110, B134, B150, B200, B300, B600,
 	B1200, B1800, B2400, B4800, B9600, B19200, B38400,
 	B57600, B115200, B230400, B460800, B500000, B576000,
 	B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h
index 232b4781a..fb863c9e0 100644
--- a/include/uapi/asm-generic/termbits.h
+++ b/include/uapi/asm-generic/termbits.h
@@ -111,7 +111,7 @@ struct ktermios {
 /* c_cflag bit meaning */
 #define CBAUD	0010017
 #define  B0	0000000		/* hang up */
-#define  B50	0000001
+#define  B31250 0000001
 #define  B75	0000002
 #define  B110	0000003
 #define  B134	0000004
diff --git a/include/linux/tty.h b/include/linux/tty.h
index b90b5c221..157b25261 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -346,6 +346,7 @@ extern void proc_clear_tty(struct task_struct *p);
 extern struct tty_struct *get_current_tty(void);
 /* tty_io.c */
 extern int __init tty_init(void);
+extern struct workqueue_struct* tty_wq;
 #else
 static inline void console_init(void)
 { }
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index bc9d2c2dd..383b26196 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -129,6 +129,7 @@ struct delayed_work {
  * participate in pool hash calculations or equality comparisons.
  */
 struct workqueue_attrs {
+	int			priority;	/* shced_priority */
 	int			nice;		/* nice level */
 	cpumask_var_t		cpumask;	/* allowed CPUs */
 	bool			no_numa;	/* disable NUMA affinity */
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 423c9e37a..34f27f2e9 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -48,6 +48,7 @@
 #include <linux/nodemask.h>
 #include <linux/moduleparam.h>
 #include <linux/uaccess.h>
+#include <linux/sched/rt.h>
 
 #include "workqueue_internal.h"
 
@@ -1737,6 +1738,7 @@ static struct worker *create_worker(struct worker_pool *pool)
 
 	if (pool->cpu >= 0)
 		snprintf(id_buf, sizeof(id_buf), "%d:%d%s", pool->cpu, id,
+			 pool->attrs->priority > 0 ? "X" :
 			 pool->attrs->nice < 0  ? "H" : "");
 	else
 		snprintf(id_buf, sizeof(id_buf), "u%d:%d", pool->id, id);
@@ -1746,6 +1748,10 @@ static struct worker *create_worker(struct worker_pool *pool)
 	if (IS_ERR(worker->task))
 		goto fail;
 
+	if((pool->attrs->priority > 0) && (pool->attrs->priority < MAX_RT_PRIO)){
+		struct sched_param param = { .sched_priority = pool->attrs->priority };
+		sched_setscheduler_nocheck(worker->task, SCHED_FIFO, &param);
+	}
 	set_user_nice(worker->task, pool->attrs->nice);
 
 	/* prevent userland from meddling with cpumask of workqueue workers */
@@ -3358,11 +3364,47 @@ static ssize_t wq_numa_store(struct device *dev, struct device_attribute *attr,
 	return ret ?: count;
 }
 
+static ssize_t wq_priority_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	struct workqueue_attrs *attrs = wq ? wq->unbound_attrs : NULL;
+	int written;
+
+	if (!attrs) return -EINVAL;
+
+	mutex_lock(&wq->mutex);
+	written = scnprintf(buf, PAGE_SIZE, "%d\n", attrs->priority);
+	mutex_unlock(&wq->mutex);
+
+	return written;
+}
+
+static ssize_t wq_priority_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct workqueue_struct *wq = dev_to_wq(dev);
+	struct workqueue_attrs *attrs = wq ? wq_sysfs_prep_attrs(wq) : NULL;
+	int ret = -EINVAL;
+
+	if (!attrs) return -ENOMEM;
+
+	if((kstrtoint(buf, 10, &attrs->priority) == 0)
+	&& (attrs->priority >= 0) && (attrs->priority < MAX_RT_PRIO)){
+		ret = apply_workqueue_attrs(wq, attrs);
+	}
+
+	free_workqueue_attrs(attrs);
+	return ret ?: count;
+}
+
 static struct device_attribute wq_sysfs_unbound_attrs[] = {
 	__ATTR(pool_ids, 0444, wq_pool_ids_show, NULL),
 	__ATTR(nice, 0644, wq_nice_show, wq_nice_store),
 	__ATTR(cpumask, 0644, wq_cpumask_show, wq_cpumask_store),
 	__ATTR(numa, 0644, wq_numa_show, wq_numa_store),
+	__ATTR(priority, 0644, wq_priority_show, wq_priority_store),
 	__ATTR_NULL,
 };
 
@@ -3515,6 +3557,7 @@ fail:
 static void copy_workqueue_attrs(struct workqueue_attrs *to,
 				 const struct workqueue_attrs *from)
 {
+	to->priority = from->priority;
 	to->nice = from->nice;
 	cpumask_copy(to->cpumask, from->cpumask);
 	/*
@@ -3530,7 +3573,7 @@ static u32 wqattrs_hash(const struct workqueue_attrs *attrs)
 {
 	u32 hash = 0;
 
-	hash = jhash_1word(attrs->nice, hash);
+	hash = jhash_2words(attrs->priority, attrs->nice, hash);
 	hash = jhash(cpumask_bits(attrs->cpumask),
 		     BITS_TO_LONGS(nr_cpumask_bits) * sizeof(long), hash);
 	return hash;
@@ -3540,6 +3583,8 @@ static u32 wqattrs_hash(const struct workqueue_attrs *attrs)
 static bool wqattrs_equal(const struct workqueue_attrs *a,
 			  const struct workqueue_attrs *b)
 {
+	if (a->priority != b->priority)
+		return false;
 	if (a->nice != b->nice)
 		return false;
 	if (!cpumask_equal(a->cpumask, b->cpumask))
