|
@@ -293,7 +293,10 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
|
|
if (n != NULL) {
|
|
if (n != NULL) {
|
|
n->flags = flags;
|
|
n->flags = flags;
|
|
buf->tail = n;
|
|
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
|
|
/* paired w/ acquire in flush_to_ldisc(); ensures the
|
|
* latest commit value can be read before the head is
|
|
* latest commit value can be read before the head is
|
|
* advanced to the next buffer
|
|
* advanced to the next buffer
|
|
@@ -396,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);
|
|
schedule_work(&buf->work);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(tty_schedule_flip);
|
|
EXPORT_SYMBOL(tty_schedule_flip);
|
|
@@ -494,7 +500,10 @@ static void flush_to_ldisc(struct work_struct *work)
|
|
* is advancing to the next buffer
|
|
* is advancing to the next buffer
|
|
*/
|
|
*/
|
|
next = smp_load_acquire(&head->next);
|
|
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 (!count) {
|
|
if (next == NULL) {
|
|
if (next == NULL) {
|
|
check_other_closed(tty);
|
|
check_other_closed(tty);
|