diff options
Diffstat (limited to 'net/sctp/outqueue.c')
| -rw-r--r-- | net/sctp/outqueue.c | 38 | 
1 files changed, 12 insertions, 26 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 94df75877869..59268f6e2c36 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -208,8 +208,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)  	INIT_LIST_HEAD(&q->retransmit);  	INIT_LIST_HEAD(&q->sacked);  	INIT_LIST_HEAD(&q->abandoned); - -	q->empty = 1;  }  /* Free the outqueue structure and any related pending chunks. @@ -332,7 +330,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)  				SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);  			else  				SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS); -			q->empty = 0;  			break;  		}  	} else { @@ -446,6 +443,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,  				transport->rto_pending = 0;  			} +			chunk->resent = 1; +  			/* Move the chunk to the retransmit queue. The chunks  			 * on the retransmit queue are always kept in order.  			 */ @@ -652,7 +651,6 @@ redo:  			if (chunk->fast_retransmit == SCTP_NEED_FRTX)  				chunk->fast_retransmit = SCTP_DONT_FRTX; -			q->empty = 0;  			q->asoc->stats.rtxchunks++;  			break;  		} @@ -1063,8 +1061,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)  			sctp_transport_reset_timers(transport); -			q->empty = 0; -  			/* Only let one DATA chunk get bundled with a  			 * COOKIE-ECHO chunk.  			 */ @@ -1273,29 +1269,17 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)  		 "advertised peer ack point:0x%x\n", __func__, asoc, ctsn,  		 asoc->adv_peer_ack_point); -	/* See if all chunks are acked. -	 * Make sure the empty queue handler will get run later. -	 */ -	q->empty = (list_empty(&q->out_chunk_list) && -		    list_empty(&q->retransmit)); -	if (!q->empty) -		goto finish; - -	list_for_each_entry(transport, transport_list, transports) { -		q->empty = q->empty && list_empty(&transport->transmitted); -		if (!q->empty) -			goto finish; -	} - -	pr_debug("%s: sack queue is empty\n", __func__); -finish: -	return q->empty; +	return sctp_outq_is_empty(q);  } -/* Is the outqueue empty?  */ +/* Is the outqueue empty? + * The queue is empty when we have not pending data, no in-flight data + * and nothing pending retransmissions. + */  int sctp_outq_is_empty(const struct sctp_outq *q)  { -	return q->empty; +	return q->out_qlen == 0 && q->outstanding_bytes == 0 && +	       list_empty(&q->retransmit);  }  /******************************************************************** @@ -1375,6 +1359,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,  				 * instance).  				 */  				if (!tchunk->tsn_gap_acked && +				    !tchunk->resent &&  				    tchunk->rtt_in_progress) {  					tchunk->rtt_in_progress = 0;  					rtt = jiffies - tchunk->sent_at; @@ -1391,7 +1376,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,  			 */  			if (!tchunk->tsn_gap_acked) {  				tchunk->tsn_gap_acked = 1; -				*highest_new_tsn_in_sack = tsn; +				if (TSN_lt(*highest_new_tsn_in_sack, tsn)) +					*highest_new_tsn_in_sack = tsn;  				bytes_acked += sctp_data_size(tchunk);  				if (!tchunk->transport)  					migrate_bytes += sctp_data_size(tchunk);  | 
