Skip to content

Commit ba1fc75

Browse files
committed
Cleanup multi-poller
1 parent ef6d632 commit ba1fc75

File tree

7 files changed

+120
-115
lines changed

7 files changed

+120
-115
lines changed

hw/femu/bbssd/ftl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ static void *ftl_thread(void *arg)
876876
ssd->to_poller = n->to_poller;
877877

878878
while (1) {
879-
for (i = 1; i <= n->num_poller; i++) {
879+
for (i = 1; i <= n->nr_pollers; i++) {
880880
if (!ssd->to_ftl[i] || !femu_ring_count(ssd->to_ftl[i]))
881881
continue;
882882

hw/femu/femu.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ static void nvme_clear_ctrl(FemuCtrl *n, bool shutdown)
2121
nvme_clear_virq(n);
2222
}
2323

24-
for (int i = 0; i <= n->num_io_queues; i++) {
24+
for (int i = 0; i <= n->nr_io_queues; i++) {
2525
if (n->sq[i] != NULL) {
2626
nvme_free_sq(n->sq[i], n);
2727
}
2828
}
29-
for (int i = 0; i <= n->num_io_queues; i++) {
29+
for (int i = 0; i <= n->nr_io_queues; i++) {
3030
if (n->cq[i] != NULL) {
3131
nvme_free_cq(n->cq[i], n);
3232
}
@@ -293,7 +293,7 @@ static const MemoryRegionOps nvme_mmio_ops = {
293293
static int nvme_check_constraints(FemuCtrl *n)
294294
{
295295
if ((n->num_namespaces == 0 || n->num_namespaces > NVME_MAX_NUM_NAMESPACES)
296-
|| (n->num_io_queues < 1 || n->num_io_queues > NVME_MAX_QS) ||
296+
|| (n->nr_io_queues < 1 || n->nr_io_queues > NVME_MAX_QS) ||
297297
(n->db_stride > NVME_MAX_STRIDE) ||
298298
(n->max_q_ents < 1) ||
299299
(n->max_sqes > NVME_MAX_QUEUE_ES || n->max_cqes > NVME_MAX_QUEUE_ES ||
@@ -429,14 +429,14 @@ static void nvme_init_ctrl(FemuCtrl *n)
429429
n->features.temp_thresh = 0x14d;
430430
n->features.err_rec = 0;
431431
n->features.volatile_wc = n->vwc;
432-
n->features.num_io_queues = ((n->num_io_queues - 1) | ((n->num_io_queues -
432+
n->features.nr_io_queues = ((n->nr_io_queues - 1) | ((n->nr_io_queues -
433433
1) << 16));
434434
n->features.int_coalescing = n->intc_thresh | (n->intc_time << 8);
435435
n->features.write_atomicity = 0;
436436
n->features.async_config = 0x0;
437437
n->features.sw_prog_marker = 0;
438438

439-
for (i = 0; i <= n->num_io_queues; i++) {
439+
for (i = 0; i <= n->nr_io_queues; i++) {
440440
n->features.int_vector_config[i] = i | (n->intc << 16);
441441
}
442442

@@ -487,7 +487,7 @@ static void nvme_init_pci(FemuCtrl *n)
487487
n->reg_size);
488488
pci_register_bar(&n->parent_obj, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
489489
PCI_BASE_ADDRESS_MEM_TYPE_64, &n->iomem);
490-
if (msix_init_exclusive_bar(&n->parent_obj, n->num_io_queues + 1, 4, NULL)) {
490+
if (msix_init_exclusive_bar(&n->parent_obj, n->nr_io_queues + 1, 4, NULL)) {
491491
return;
492492
}
493493
msi_init(&n->parent_obj, 0x50, 32, true, false, NULL);
@@ -540,16 +540,16 @@ static void femu_realize(PCIDevice *pci_dev, Error **errp)
540540

541541
n->completed = 0;
542542
n->start_time = time(NULL);
543-
n->reg_size = pow2ceil(0x1004 + 2 * (n->num_io_queues + 1) * 4);
543+
n->reg_size = pow2ceil(0x1004 + 2 * (n->nr_io_queues + 1) * 4);
544544
n->ns_size = bs_size / (uint64_t)n->num_namespaces;
545545

546-
/* Coperd: [1..num_io_queues] are used as IO queues */
547-
n->sq = g_malloc0(sizeof(*n->sq) * (n->num_io_queues + 1));
548-
n->cq = g_malloc0(sizeof(*n->cq) * (n->num_io_queues + 1));
546+
/* Coperd: [1..nr_io_queues] are used as IO queues */
547+
n->sq = g_malloc0(sizeof(*n->sq) * (n->nr_io_queues + 1));
548+
n->cq = g_malloc0(sizeof(*n->cq) * (n->nr_io_queues + 1));
549549
n->namespaces = g_malloc0(sizeof(*n->namespaces) * n->num_namespaces);
550550
n->elpes = g_malloc0(sizeof(*n->elpes) * (n->elpe + 1));
551551
n->aer_reqs = g_malloc0(sizeof(*n->aer_reqs) * (n->aerl + 1));
552-
n->features.int_vector_config = g_malloc0(sizeof(*n->features.int_vector_config) * (n->num_io_queues + 1));
552+
n->features.int_vector_config = g_malloc0(sizeof(*n->features.int_vector_config) * (n->nr_io_queues + 1));
553553

554554
nvme_init_pci(n);
555555
nvme_init_ctrl(n);
@@ -564,13 +564,14 @@ static void femu_realize(PCIDevice *pci_dev, Error **errp)
564564

565565
static void nvme_destroy_poller(FemuCtrl *n)
566566
{
567+
int i;
567568
femu_debug("Destroying NVMe poller !!\n");
568569

569-
for (int i = 1; i <= n->num_poller; i++) {
570+
for (i = 1; i <= n->nr_pollers; i++) {
570571
qemu_thread_join(&n->poller[i]);
571572
}
572573

573-
for (int i = 1; i <= n->num_poller; i++) {
574+
for (i = 1; i <= n->nr_pollers; i++) {
574575
pqueue_free(n->pq[i]);
575576
femu_ring_free(n->to_poller[i]);
576577
femu_ring_free(n->to_ftl[i]);
@@ -610,7 +611,7 @@ static Property femu_props[] = {
610611
DEFINE_PROP_STRING("serial", FemuCtrl, serial),
611612
DEFINE_PROP_UINT32("devsz_mb", FemuCtrl, memsz, 1024), /* in MB */
612613
DEFINE_PROP_UINT32("namespaces", FemuCtrl, num_namespaces, 1),
613-
DEFINE_PROP_UINT32("queues", FemuCtrl, num_io_queues, 8),
614+
DEFINE_PROP_UINT32("queues", FemuCtrl, nr_io_queues, 8),
614615
DEFINE_PROP_UINT32("entries", FemuCtrl, max_q_ents, 0x7ff),
615616
DEFINE_PROP_UINT8("multipoller_enabled", FemuCtrl, multipoller_enabled, 0),
616617
DEFINE_PROP_UINT8("max_cqes", FemuCtrl, max_cqes, 0x4),

hw/femu/intr.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ static void nvme_clear_guest_notifier(FemuCtrl *n)
5050
{
5151
NvmeCQueue *cq;
5252

53-
for (uint32_t qid = 1; qid <= n->num_io_queues; qid++) {
53+
for (uint32_t qid = 1; qid <= n->nr_io_queues; qid++) {
5454
cq = n->cq[qid];
5555
if (!cq) {
5656
break;
@@ -74,7 +74,7 @@ static int nvme_vector_unmask(PCIDevice *dev, unsigned vector, MSIMessage msg)
7474
EventNotifier *e;
7575
int ret;
7676

77-
for (uint32_t qid = 1; qid <= n->num_io_queues; qid++) {
77+
for (uint32_t qid = 1; qid <= n->nr_io_queues; qid++) {
7878
cq = n->cq[qid];
7979
if (!cq) {
8080
continue;
@@ -110,7 +110,7 @@ static void nvme_vector_mask(PCIDevice *dev, unsigned vector)
110110
EventNotifier *e;
111111
int ret;
112112

113-
for (uint32_t qid = 1; qid <= n->num_io_queues; qid++) {
113+
for (uint32_t qid = 1; qid <= n->nr_io_queues; qid++) {
114114
cq = n->cq[qid];
115115
if (!cq) {
116116
continue;
@@ -135,7 +135,7 @@ static void nvme_vector_poll(PCIDevice *dev, unsigned int vector_start, unsigned
135135
EventNotifier *e;
136136
uint32_t vector;
137137

138-
for (uint32_t qid = 1; qid <= n->num_io_queues; qid++) {
138+
for (uint32_t qid = 1; qid <= n->nr_io_queues; qid++) {
139139
cq = n->cq[qid];
140140
if (!cq) {
141141
continue;

hw/femu/nvme-admin.c

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static uint16_t nvme_create_cq(FemuCtrl *n, NvmeCmd *cmd)
158158
if (!prp1) {
159159
return NVME_INVALID_FIELD | NVME_DNR;
160160
}
161-
if (vector > n->num_io_queues) {
161+
if (vector > n->nr_io_queues) {
162162
return NVME_INVALID_IRQ_VECTOR | NVME_DNR;
163163
}
164164
if (!(NVME_CQ_FLAGS_PC(qflags)) && NVME_CAP_CQR(n->bar.cap)) {
@@ -206,18 +206,96 @@ static uint16_t nvme_del_cq(FemuCtrl *n, NvmeCmd *cmd)
206206
return NVME_SUCCESS;
207207
}
208208

209+
static int cmp_pri(pqueue_pri_t next, pqueue_pri_t curr)
210+
{
211+
return (next > curr);
212+
}
213+
214+
static pqueue_pri_t get_pri(void *a)
215+
{
216+
return ((NvmeRequest *)a)->expire_time;
217+
}
218+
219+
static void set_pri(void *a, pqueue_pri_t pri)
220+
{
221+
((NvmeRequest *)a)->expire_time = pri;
222+
}
223+
224+
static size_t get_pos(void *a)
225+
{
226+
return ((NvmeRequest *)a)->pos;
227+
}
228+
229+
static void set_pos(void *a, size_t pos)
230+
{
231+
((NvmeRequest *)a)->pos = pos;
232+
}
233+
234+
static void nvme_init_poller(FemuCtrl *n)
235+
{
236+
int i;
237+
238+
n->should_isr = g_malloc0(sizeof(bool) * (n->nr_io_queues + 1));
239+
240+
n->nr_pollers = n->multipoller_enabled ? n->nr_io_queues : 1;
241+
/* Coperd: we put NvmeRequest into these rings */
242+
n->to_ftl = g_malloc0(sizeof(struct rte_ring *) * (n->nr_pollers + 1));
243+
for (i = 1; i <= n->nr_pollers; i++) {
244+
n->to_ftl[i] = femu_ring_create(FEMU_RING_TYPE_MP_SC, FEMU_MAX_INF_REQS);
245+
if (!n->to_ftl[i]) {
246+
femu_err("Failed to create ring (n->to_ftl) ...\n");
247+
abort();
248+
}
249+
assert(rte_ring_empty(n->to_ftl[i]));
250+
}
251+
252+
n->to_poller = g_malloc0(sizeof(struct rte_ring *) * (n->nr_pollers + 1));
253+
for (i = 1; i <= n->nr_pollers; i++) {
254+
n->to_poller[i] = femu_ring_create(FEMU_RING_TYPE_MP_SC, FEMU_MAX_INF_REQS);
255+
if (!n->to_poller[i]) {
256+
femu_err("Failed to create ring (n->to_poller) ...\n");
257+
abort();
258+
}
259+
assert(rte_ring_empty(n->to_poller[i]));
260+
}
261+
262+
n->pq = g_malloc0(sizeof(pqueue_t *) * (n->nr_pollers + 1));
263+
for (i = 1; i <= n->nr_pollers; i++) {
264+
n->pq[i] = pqueue_init(FEMU_MAX_INF_REQS, cmp_pri, get_pri, set_pri,
265+
get_pos, set_pos);
266+
if (!n->pq[i]) {
267+
femu_err("Failed to create pqueue (n->pq) ...\n");
268+
abort();
269+
}
270+
}
271+
272+
n->poller = g_malloc0(sizeof(QemuThread) * (n->nr_pollers + 1));
273+
NvmePollerThreadArgument *args = malloc(sizeof(NvmePollerThreadArgument) *
274+
(n->nr_pollers + 1));
275+
for (i = 1; i <= n->nr_pollers; i++) {
276+
args[i].n = n;
277+
args[i].index = i;
278+
qemu_thread_create(&n->poller[i], "femu-nvme-poller", nvme_poller,
279+
&args[i], QEMU_THREAD_JOINABLE);
280+
femu_debug("femu-nvme-poller [%d] created ...\n", i - 1);
281+
}
282+
}
283+
209284
static uint16_t nvme_set_db_memory(FemuCtrl *n, const NvmeCmd *cmd)
210285
{
211286
uint64_t dbs_addr = le64_to_cpu(cmd->dptr.prp1);
212287
uint64_t eis_addr = le64_to_cpu(cmd->dptr.prp2);
213288
uint8_t stride = n->db_stride;
214289
int dbbuf_entry_sz = 1 << (2 + stride);
215290
AddressSpace *as = pci_get_address_space(&n->parent_obj);
291+
int i;
292+
293+
216294
dma_addr_t dbs_tlen = n->page_size, eis_tlen = n->page_size;
217295

218296
/* Addresses should not be NULL and should be page aligned. */
219-
if (dbs_addr == 0 || dbs_addr & (n->page_size - 1) ||
220-
eis_addr == 0 || eis_addr & (n->page_size - 1)) {
297+
if (dbs_addr == 0 || dbs_addr & (n->page_size - 1) || eis_addr == 0 ||
298+
eis_addr & (n->page_size - 1)) {
221299
return NVME_INVALID_FIELD | NVME_DNR;
222300
}
223301

@@ -226,7 +304,7 @@ static uint16_t nvme_set_db_memory(FemuCtrl *n, const NvmeCmd *cmd)
226304
n->dbs_addr_hva = (uint64_t)dma_memory_map(as, dbs_addr, &dbs_tlen, 0, MEMTXATTRS_UNSPECIFIED);
227305
n->eis_addr_hva = (uint64_t)dma_memory_map(as, eis_addr, &eis_tlen, 0, MEMTXATTRS_UNSPECIFIED);
228306

229-
for (int i = 1; i <= n->num_io_queues; i++) {
307+
for (i = 1; i <= n->nr_io_queues; i++) {
230308
NvmeSQueue *sq = n->sq[i];
231309
NvmeCQueue *cq = n->cq[i];
232310

@@ -252,8 +330,8 @@ static uint16_t nvme_set_db_memory(FemuCtrl *n, const NvmeCmd *cmd)
252330

253331
assert(n->dataplane_started == false);
254332
if (!n->poller_on) {
255-
/* Coperd: make sure this only run once across all controller resets */
256-
nvme_create_poller(n);
333+
/* Coperd: make sure this only runs once across all controller resets */
334+
nvme_init_poller(n);
257335
n->poller_on = true;
258336
}
259337
n->dataplane_started = true;
@@ -570,8 +648,8 @@ static uint16_t nvme_get_feature(FemuCtrl *n, NvmeCmd *cmd, NvmeCqe *cqe)
570648
MIN(sizeof(*rt), (dw11 & 0x3f) * sizeof(*rt)),
571649
prp1, prp2);
572650
case NVME_NUMBER_OF_QUEUES:
573-
cqe->n.result = cpu_to_le32((n->num_io_queues - 1) |
574-
((n->num_io_queues - 1) << 16));
651+
cqe->n.result = cpu_to_le32((n->nr_io_queues - 1) |
652+
((n->nr_io_queues - 1) << 16));
575653
break;
576654
case NVME_TEMPERATURE_THRESHOLD:
577655
cqe->n.result = cpu_to_le32(n->features.temp_thresh);
@@ -586,7 +664,7 @@ static uint16_t nvme_get_feature(FemuCtrl *n, NvmeCmd *cmd, NvmeCqe *cqe)
586664
cqe->n.result = cpu_to_le32(n->features.int_coalescing);
587665
break;
588666
case NVME_INTERRUPT_VECTOR_CONF:
589-
if ((dw11 & 0xffff) > n->num_io_queues) {
667+
if ((dw11 & 0xffff) > n->nr_io_queues) {
590668
return NVME_INVALID_FIELD | NVME_DNR;
591669
}
592670
cqe->n.result = cpu_to_le32(n->features.int_vector_config[dw11 & 0xffff]);
@@ -633,9 +711,9 @@ static uint16_t nvme_set_feature(FemuCtrl *n, NvmeCmd *cmd, NvmeCqe *cqe)
633711
MIN(sizeof(*rt), (dw11 & 0x3f) * sizeof(*rt)),
634712
prp1, prp2);
635713
case NVME_NUMBER_OF_QUEUES:
636-
/* Coperd: num_io_queues is 0-based */
637-
cqe->n.result = cpu_to_le32((n->num_io_queues - 1) |
638-
((n->num_io_queues - 1) << 16));
714+
/* Coperd: nr_io_queues is 0-based */
715+
cqe->n.result = cpu_to_le32((n->nr_io_queues - 1) |
716+
((n->nr_io_queues - 1) << 16));
639717
break;
640718
case NVME_TEMPERATURE_THRESHOLD:
641719
n->features.temp_thresh = dw11;
@@ -656,7 +734,7 @@ static uint16_t nvme_set_feature(FemuCtrl *n, NvmeCmd *cmd, NvmeCqe *cqe)
656734
n->features.int_coalescing = dw11;
657735
break;
658736
case NVME_INTERRUPT_VECTOR_CONF:
659-
if ((dw11 & 0xffff) > n->num_io_queues) {
737+
if ((dw11 & 0xffff) > n->nr_io_queues) {
660738
return NVME_INVALID_FIELD | NVME_DNR;
661739
}
662740
n->features.int_vector_config[dw11 & 0xffff] = dw11 & 0x1ffff;

0 commit comments

Comments
 (0)