projects
/
firefly-linux-kernel-4.4.55.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[firefly-linux-kernel-4.4.55.git]
/
drivers
/
tty
/
tty_buffer.c
diff --git
a/drivers/tty/tty_buffer.c
b/drivers/tty/tty_buffer.c
index 5a3fa89138801ea63907ec102fbb589b36d7201c..a660ab181cca7357c59c7256303628eb8bb929a9 100644
(file)
--- a/
drivers/tty/tty_buffer.c
+++ b/
drivers/tty/tty_buffer.c
@@
-242,7
+242,10
@@
void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld)
atomic_inc(&buf->priority);
mutex_lock(&buf->lock);
atomic_inc(&buf->priority);
mutex_lock(&buf->lock);
- while ((next = buf->head->next) != NULL) {
+ /* paired w/ release in __tty_buffer_request_room; ensures there are
+ * no pending memory accesses to the freed buffer
+ */
+ while ((next = smp_load_acquire(&buf->head->next)) != NULL) {
tty_buffer_free(port, buf->head);
buf->head = next;
}
tty_buffer_free(port, buf->head);
buf->head = next;
}
@@
-290,7
+293,10
@@
static int __tty_buffer_request_room(struct tty_port *port, size_t size,
if (n != NULL) {
n->flags = flags;
buf->tail = n;
if (n != NULL) {
n->flags = flags;
buf->tail = n;
- b->commit = b->used;
+ /* paired w/ acquire in flush_to_ldisc(); ensures
+ * flush_to_ldisc() sees buffer data.
+ */
+ smp_store_release(&b->commit, b->used);
/* paired w/ acquire in flush_to_ldisc(); ensures the
* latest commit value can be read before the head is
* advanced to the next buffer
/* paired w/ acquire in flush_to_ldisc(); ensures the
* latest commit value can be read before the head is
* advanced to the next buffer
@@
-393,7
+399,10
@@
void tty_schedule_flip(struct tty_port *port)
{
struct tty_bufhead *buf = &port->buf;
{
struct tty_bufhead *buf = &port->buf;
- buf->tail->commit = buf->tail->used;
+ /* paired w/ acquire in flush_to_ldisc(); ensures
+ * flush_to_ldisc() sees buffer data.
+ */
+ smp_store_release(&buf->tail->commit, buf->tail->used);
schedule_work(&buf->work);
}
EXPORT_SYMBOL(tty_schedule_flip);
schedule_work(&buf->work);
}
EXPORT_SYMBOL(tty_schedule_flip);
@@
-467,7
+476,7
@@
static void flush_to_ldisc(struct work_struct *work)
struct tty_struct *tty;
struct tty_ldisc *disc;
struct tty_struct *tty;
struct tty_ldisc *disc;
- tty =
port->itty
;
+ tty =
READ_ONCE(port->itty)
;
if (tty == NULL)
return;
if (tty == NULL)
return;
@@
-491,7
+500,10
@@
static void flush_to_ldisc(struct work_struct *work)
* is advancing to the next buffer
*/
next = smp_load_acquire(&head->next);
* is advancing to the next buffer
*/
next = smp_load_acquire(&head->next);
- count = head->commit - head->read;
+ /* paired w/ release in __tty_buffer_request_room() or in
+ * tty_buffer_flush(); ensures we see the committed buffer data
+ */
+ count = smp_load_acquire(&head->commit) - head->read;
if (!count) {
if (next == NULL) {
check_other_closed(tty);
if (!count) {
if (next == NULL) {
check_other_closed(tty);