Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 May 2016 13:38:29 +0000 (UTC)
From:      Zbigniew Bodek <zbb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r299446 - head/sys/dev/vnic
Message-ID:  <201605111338.u4BDcTwO073872@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zbb
Date: Wed May 11 13:38:29 2016
New Revision: 299446
URL: https://svnweb.freebsd.org/changeset/base/299446

Log:
  Fix deadlock in VNIC when using single CPU only
  
  Number of free Tx descriptors does not need to be locked since
  it can be modified atomically between SND and CQ tasks.
  It will also block Tx routine from sending packets while CQ will not
  be able to free descriptors.
  
  Obtained from:	Semihalf
  Sponsored by:	Cavium
  Differential Revision: https://reviews.freebsd.org/D6266

Modified:
  head/sys/dev/vnic/nicvf_queues.c

Modified: head/sys/dev/vnic/nicvf_queues.c
==============================================================================
--- head/sys/dev/vnic/nicvf_queues.c	Wed May 11 13:23:56 2016	(r299445)
+++ head/sys/dev/vnic/nicvf_queues.c	Wed May 11 13:38:29 2016	(r299446)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/sockio.h>
 #include <sys/socket.h>
+#include <sys/stdatomic.h>
 #include <sys/cpuset.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
@@ -691,7 +692,7 @@ nicvf_rcv_pkt_handler(struct nicvf *nic,
 	return (0);
 }
 
-static int
+static void
 nicvf_snd_pkt_handler(struct nicvf *nic, struct cmp_queue *cq,
     struct cqe_send_t *cqe_tx, int cqe_type)
 {
@@ -702,15 +703,10 @@ nicvf_snd_pkt_handler(struct nicvf *nic,
 
 	mbuf = NULL;
 	sq = &nic->qs->sq[cqe_tx->sq_idx];
-	/* Avoid blocking here since we hold a non-sleepable NICVF_CMP_LOCK */
-	if (NICVF_TX_TRYLOCK(sq) == 0)
-		return (EAGAIN);
 
 	hdr = (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, cqe_tx->sqe_ptr);
-	if (hdr->subdesc_type != SQ_DESC_TYPE_HEADER) {
-		NICVF_TX_UNLOCK(sq);
-		return (0);
-	}
+	if (hdr->subdesc_type != SQ_DESC_TYPE_HEADER)
+		return;
 
 	dprintf(nic->dev,
 	    "%s Qset #%d SQ #%d SQ ptr #%d subdesc count %d\n",
@@ -728,9 +724,6 @@ nicvf_snd_pkt_handler(struct nicvf *nic,
 	}
 
 	nicvf_check_cqe_tx_errs(nic, cq, cqe_tx);
-
-	NICVF_TX_UNLOCK(sq);
-	return (0);
 }
 
 static int
@@ -788,16 +781,8 @@ nicvf_cq_intr_handler(struct nicvf *nic,
 			work_done++;
 			break;
 		case CQE_TYPE_SEND:
-			cmp_err = nicvf_snd_pkt_handler(nic, cq,
-			    (void *)cq_desc, CQE_TYPE_SEND);
-			if (__predict_false(cmp_err != 0)) {
-				/*
-				 * Ups. Cannot finish now.
-				 * Let's try again later.
-				 */
-				goto done;
-			}
-
+			nicvf_snd_pkt_handler(nic, cq, (void *)cq_desc,
+			    CQE_TYPE_SEND);
 			tx_done++;
 			break;
 		case CQE_TYPE_INVALID:
@@ -1085,7 +1070,7 @@ nicvf_init_snd_queue(struct nicvf *nic, 
 
 	sq->desc = sq->dmem.base;
 	sq->head = sq->tail = 0;
-	sq->free_cnt = q_len - 1;
+	atomic_store_rel_int(&sq->free_cnt, q_len - 1);
 	sq->thresh = SND_QUEUE_THRESH;
 	sq->idx = qidx;
 	sq->nic = nic;
@@ -1676,7 +1661,7 @@ nicvf_get_sq_desc(struct snd_queue *sq, 
 	int qentry;
 
 	qentry = sq->tail;
-	sq->free_cnt -= desc_cnt;
+	atomic_subtract_int(&sq->free_cnt, desc_cnt);
 	sq->tail += desc_cnt;
 	sq->tail &= (sq->dmem.q_len - 1);
 
@@ -1688,7 +1673,7 @@ static void
 nicvf_put_sq_desc(struct snd_queue *sq, int desc_cnt)
 {
 
-	sq->free_cnt += desc_cnt;
+	atomic_add_int(&sq->free_cnt, desc_cnt);
 	sq->head += desc_cnt;
 	sq->head &= (sq->dmem.q_len - 1);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605111338.u4BDcTwO073872>