@@ -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+
209284static 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