diff options
-rw-r--r-- | net/rds/connection.c | 1 | ||||
-rw-r--r-- | net/rds/rds.h | 1 | ||||
-rw-r--r-- | net/rds/send.c | 11 |
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 | ||
117 | restart: | 118 | restart: |
@@ -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 | } |
370 | out: | 373 | out: |
371 | return ret; | 374 | return ret; |