summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2016-08-18 09:21:36 +0000
committermav <mav@FreeBSD.org>2016-08-18 09:21:36 +0000
commit29e4107d3317a4b25f35d262e54517eb0fd95d32 (patch)
tree56a472d724ddd7593ba072a4a98df40f9fce989c
parentad4fb0ae15889c5d0259102fbb35bda445f93ce5 (diff)
downloadFreeBSD-src-29e4107d3317a4b25f35d262e54517eb0fd95d32.zip
FreeBSD-src-29e4107d3317a4b25f35d262e54517eb0fd95d32.tar.gz
MFC r302490: Create separate RX taskqueue for each qp.
-rw-r--r--sys/dev/ntb/ntb_transport.c47
1 files changed, 20 insertions, 27 deletions
diff --git a/sys/dev/ntb/ntb_transport.c b/sys/dev/ntb/ntb_transport.c
index b1e447c..17d2cb7 100644
--- a/sys/dev/ntb/ntb_transport.c
+++ b/sys/dev/ntb/ntb_transport.c
@@ -158,6 +158,7 @@ struct ntb_transport_qp {
/* ntb_rx_q_lock: synchronize access to rx_XXXX_q */
struct mtx ntb_rx_q_lock;
struct task rxc_db_work;
+ struct taskqueue *rxc_tq;
caddr_t rx_buff;
ntb_q_idx_t rx_index;
ntb_q_idx_t rx_max_entry;
@@ -200,6 +201,7 @@ struct ntb_transport_mw {
};
struct ntb_transport_ctx {
+ device_t dev;
device_t ntb;
struct ntb_transport_mw *mw_vec;
struct ntb_transport_qp *qp_vec;
@@ -337,6 +339,7 @@ ntb_transport_attach(device_t dev)
int rc;
unsigned i;
+ nt->dev = dev;
nt->ntb = ntb;
nt->mw_count = NTB_MW_COUNT(ntb);
nt->mw_vec = malloc(nt->mw_count * sizeof(*nt->mw_vec), M_NTB_T,
@@ -497,6 +500,10 @@ ntb_transport_init_queue(struct ntb_transport_ctx *nt, unsigned int qp_num)
mtx_init(&qp->ntb_tx_free_q_lock, "ntb tx free q", NULL, MTX_SPIN);
mtx_init(&qp->tx_lock, "ntb transport tx", NULL, MTX_DEF);
TASK_INIT(&qp->rxc_db_work, 0, ntb_transport_rxc_db, qp);
+ qp->rxc_tq = taskqueue_create("ntbt_rx", M_WAITOK,
+ taskqueue_thread_enqueue, &qp->rxc_tq);
+ taskqueue_start_threads(&qp->rxc_tq, 1, PI_NET, "%s rx%d",
+ device_get_nameunit(nt->dev), qp_num);
STAILQ_INIT(&qp->rx_post_q);
STAILQ_INIT(&qp->rx_pend_q);
@@ -516,7 +523,8 @@ ntb_transport_free_queue(struct ntb_transport_qp *qp)
callout_drain(&qp->link_work);
NTB_DB_SET_MASK(qp->ntb, 1ull << qp->qp_num);
- taskqueue_drain(taskqueue_swi, &qp->rxc_db_work);
+ taskqueue_drain_all(qp->rxc_tq);
+ taskqueue_free(qp->rxc_tq);
qp->cb_data = NULL;
qp->rx_handler = NULL;
@@ -779,35 +787,18 @@ static void
ntb_transport_rxc_db(void *arg, int pending __unused)
{
struct ntb_transport_qp *qp = arg;
- ntb_q_idx_t i;
int rc;
- /*
- * Limit the number of packets processed in a single interrupt to
- * provide fairness to others
- */
CTR0(KTR_NTB, "RX: transport_rx");
- for (i = 0; i < qp->rx_max_entry; i++) {
- rc = ntb_process_rxc(qp);
- if (rc != 0) {
- CTR0(KTR_NTB, "RX: process_rxc failed");
- break;
- }
- }
+again:
+ while ((rc = ntb_process_rxc(qp)) == 0)
+ ;
+ CTR1(KTR_NTB, "RX: process_rxc returned %d", rc);
- if (i == qp->rx_max_entry)
- taskqueue_enqueue(taskqueue_swi, &qp->rxc_db_work);
- else if ((NTB_DB_READ(qp->ntb) & (1ull << qp->qp_num)) != 0) {
- /* If db is set, clear it and read it back to commit clear. */
+ if ((NTB_DB_READ(qp->ntb) & (1ull << qp->qp_num)) != 0) {
+ /* If db is set, clear it and check queue once more. */
NTB_DB_CLEAR(qp->ntb, 1ull << qp->qp_num);
- (void)NTB_DB_READ(qp->ntb);
-
- /*
- * An interrupt may have arrived between finishing
- * ntb_process_rxc and clearing the doorbell bit: there might
- * be some more work to do.
- */
- taskqueue_enqueue(taskqueue_swi, &qp->rxc_db_work);
+ goto again;
}
}
@@ -969,12 +960,14 @@ ntb_transport_doorbell_callback(void *data, uint32_t vector)
BIT_NAND(QP_SETSIZE, &db_bits, &nt->qp_bitmap_free);
vec_mask = NTB_DB_VECTOR_MASK(nt->ntb, vector);
+ if ((vec_mask & (vec_mask - 1)) != 0)
+ vec_mask &= NTB_DB_READ(nt->ntb);
while (vec_mask != 0) {
qp_num = ffsll(vec_mask) - 1;
if (test_bit(qp_num, &db_bits)) {
qp = &nt->qp_vec[qp_num];
- taskqueue_enqueue(taskqueue_swi, &qp->rxc_db_work);
+ taskqueue_enqueue(qp->rxc_tq, &qp->rxc_db_work);
}
vec_mask &= ~(1ull << qp_num);
@@ -1223,7 +1216,7 @@ ntb_qp_link_work(void *arg)
if (qp->event_handler != NULL)
qp->event_handler(qp->cb_data, NTB_LINK_UP);
- taskqueue_enqueue(taskqueue_swi, &qp->rxc_db_work);
+ taskqueue_enqueue(qp->rxc_tq, &qp->rxc_db_work);
} else if (nt->link_is_up)
callout_reset(&qp->link_work,
NTB_LINK_DOWN_TIMEOUT * hz / 1000, ntb_qp_link_work, qp);
OpenPOWER on IntegriCloud