conn->c_next_tx_seq = 1;
spin_lock_init(&conn->c_send_lock);
+ atomic_set(&conn->c_send_generation, 1);
INIT_LIST_HEAD(&conn->c_send_queue);
INIT_LIST_HEAD(&conn->c_retrans);
struct rds_cong_map *c_fcong;
spinlock_t c_send_lock; /* protect send ring */
+ atomic_t c_send_generation;
struct rds_message *c_xmit_rm;
unsigned long c_xmit_sg;
unsigned int c_xmit_hdr_off;
unsigned int tmp;
struct scatterlist *sg;
int ret = 0;
+ int gen = 0;
LIST_HEAD(to_be_dropped);
restart:
if (conn->c_trans->xmit_prepare)
conn->c_trans->xmit_prepare(conn);
+ gen = atomic_inc_return(&conn->c_send_generation);
+
/*
* spin trying to push headers and data down the connection until
* the connection doesn't make forward progress.
if (ret == 0) {
/* A simple bit test would be way faster than taking the
* spin lock */
- spin_lock_irqsave(&conn->c_lock, flags);
+ smp_mb();
if (!list_empty(&conn->c_send_queue)) {
rds_stats_inc(s_send_lock_queue_raced);
- spin_unlock_irqrestore(&conn->c_lock, flags);
- goto restart;
+ if (gen == atomic_read(&conn->c_send_generation)) {
+ goto restart;
+ }
}
- spin_unlock_irqrestore(&conn->c_lock, flags);
}
out:
return ret;