aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/rds/connection.c1
-rw-r--r--net/rds/rds.h1
-rw-r--r--net/rds/send.c11
3 files changed, 9 insertions, 4 deletions
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 56aebe444ad3..7e4e9dfdbc0b 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -147,6 +147,7 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
147 conn->c_next_tx_seq = 1; 147 conn->c_next_tx_seq = 1;
148 148
149 spin_lock_init(&conn->c_send_lock); 149 spin_lock_init(&conn->c_send_lock);
150 atomic_set(&conn->c_send_generation, 1);
150 INIT_LIST_HEAD(&conn->c_send_queue); 151 INIT_LIST_HEAD(&conn->c_send_queue);
151 INIT_LIST_HEAD(&conn->c_retrans); 152 INIT_LIST_HEAD(&conn->c_retrans);
152 153
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 2f19d49fac9c..b57cb50c1f22 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -92,6 +92,7 @@ struct rds_connection {
92 struct rds_cong_map *c_fcong; 92 struct rds_cong_map *c_fcong;
93 93
94 spinlock_t c_send_lock; /* protect send ring */ 94 spinlock_t c_send_lock; /* protect send ring */
95 atomic_t c_send_generation;
95 struct rds_message *c_xmit_rm; 96 struct rds_message *c_xmit_rm;
96 unsigned long c_xmit_sg; 97 unsigned long c_xmit_sg;
97 unsigned int c_xmit_hdr_off; 98 unsigned int c_xmit_hdr_off;
diff --git a/net/rds/send.c b/net/rds/send.c
index de5693cdcefb..663fd60b40cf 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -112,6 +112,7 @@ int rds_send_xmit(struct rds_connection *conn)
112 unsigned int tmp; 112 unsigned int tmp;
113 struct scatterlist *sg; 113 struct scatterlist *sg;
114 int ret = 0; 114 int ret = 0;
115 int gen = 0;
115 LIST_HEAD(to_be_dropped); 116 LIST_HEAD(to_be_dropped);
116 117
117restart: 118restart:
@@ -134,6 +135,8 @@ restart:
134 if (conn->c_trans->xmit_prepare) 135 if (conn->c_trans->xmit_prepare)
135 conn->c_trans->xmit_prepare(conn); 136 conn->c_trans->xmit_prepare(conn);
136 137
138 gen = atomic_inc_return(&conn->c_send_generation);
139
137 /* 140 /*
138 * spin trying to push headers and data down the connection until 141 * spin trying to push headers and data down the connection until
139 * the connection doesn't make forward progress. 142 * the connection doesn't make forward progress.
@@ -359,13 +362,13 @@ restart:
359 if (ret == 0) { 362 if (ret == 0) {
360 /* A simple bit test would be way faster than taking the 363 /* A simple bit test would be way faster than taking the
361 * spin lock */ 364 * spin lock */
362 spin_lock_irqsave(&conn->c_lock, flags); 365 smp_mb();
363 if (!list_empty(&conn->c_send_queue)) { 366 if (!list_empty(&conn->c_send_queue)) {
364 rds_stats_inc(s_send_lock_queue_raced); 367 rds_stats_inc(s_send_lock_queue_raced);
365 spin_unlock_irqrestore(&conn->c_lock, flags); 368 if (gen == atomic_read(&conn->c_send_generation)) {
366 goto restart; 369 goto restart;
370 }
367 } 371 }
368 spin_unlock_irqrestore(&conn->c_lock, flags);
369 } 372 }
370out: 373out:
371 return ret; 374 return ret;