@@ -471,6 +471,126 @@ static void zns_finalize_zoned_write(NvmeNamespace *ns, NvmeRequest *req,
471471 }
472472}
473473
474+ // Add some function
475+ // --------------------------------
476+ static inline struct zns_ch * get_ch (struct zns_ssd * zns , struct ppa * ppa )
477+ {
478+ return & (zns -> ch [ppa -> g .ch ]);
479+ }
480+
481+ static inline struct zns_fc * get_fc (struct zns_ssd * zns , struct ppa * ppa )
482+ {
483+ struct zns_ch * ch = get_ch (zns , ppa );
484+ return & (ch -> fc [ppa -> g .fc ]);
485+ }
486+
487+ static inline struct zns_blk * get_blk (struct zns_ssd * zns , struct ppa * ppa )
488+ {
489+ struct zns_fc * fc = get_fc (zns , ppa );
490+ return & (fc -> blk [ppa -> g .blk ]);
491+ }
492+
493+ static inline uint64_t zone_slba (FemuCtrl * n , uint32_t zone_idx )
494+ {
495+ return (zone_idx ) * n -> zone_size ;
496+ }
497+
498+ static inline void check_addr (int a , int max )
499+ {
500+ assert (a >= 0 && a < max );
501+ }
502+
503+ static void advance_read_pointer (FemuCtrl * n )
504+ {
505+ struct zns_ssd * zns = n -> zns ;
506+ struct write_pointer * wpp = & zns -> wp ;
507+ uint8_t num_ch = zns -> num_ch ;
508+ uint8_t num_lun = zns -> num_lun ;
509+
510+ //printf("NUM CH: %"PRIu64"\n", wpp->ch);
511+ check_addr (wpp -> ch , num_ch );
512+ wpp -> ch ++ ;
513+ if (wpp -> ch == num_ch ) {
514+ wpp -> ch = 0 ;
515+ check_addr (wpp -> lun , num_lun );
516+ wpp -> lun ++ ;
517+ if (wpp -> lun == num_lun ) {
518+ wpp -> lun = 0 ;
519+
520+ assert (wpp -> ch == 0 );
521+ assert (wpp -> lun == 0 );
522+ }
523+ }
524+ }
525+
526+ static inline struct ppa lpn_to_ppa (FemuCtrl * n , NvmeNamespace * ns , uint64_t lpn )
527+ {
528+
529+ uint32_t zone_idx = zns_zone_idx (ns , (lpn * 4096 ));
530+
531+ struct zns_ssd * zns = n -> zns ;
532+ struct write_pointer * wpp = & zns -> wp ;
533+ //uint64_t num_ch = zns->num_ch;
534+ //uint64_t num_lun = zns->num_lun;
535+ struct ppa ppa = {0 };
536+
537+ //printf("OFFSET: %"PRIu64"\n\n", offset);
538+ //wpp->ch,lun
539+ ppa .g .ch = wpp -> ch ;
540+ ppa .g .fc = wpp -> lun ;
541+ ppa .g .blk = zone_idx ;
542+
543+ return ppa ;
544+ }
545+
546+ static uint64_t zns_advance_status (FemuCtrl * n , struct nand_cmd * ncmd ,
547+ struct ppa * ppa )
548+ {
549+ int c = ncmd -> cmd ;
550+
551+ struct zns_ssd * zns = n -> zns ;
552+ uint64_t nand_stime ;
553+ uint64_t req_stime = (ncmd -> stime == 0 ) ? \
554+ qemu_clock_get_ns (QEMU_CLOCK_REALTIME ) : ncmd -> stime ;
555+
556+ struct zns_fc * fc = get_fc (zns , ppa );
557+
558+ uint64_t lat = 0 ;
559+ uint64_t read_delay = n -> zns_params .zns_read ;
560+ uint64_t write_delay = n -> zns_params .zns_write ;
561+ uint64_t erase_delay = 2000000 ;
562+ //200 us for write
563+ switch (c ) {
564+ case NAND_READ :
565+ nand_stime = (fc -> next_fc_avail_time < req_stime ) ? req_stime : \
566+ fc -> next_fc_avail_time ;
567+
568+ fc -> next_fc_avail_time = nand_stime + read_delay ;
569+ lat = fc -> next_fc_avail_time - req_stime ;
570+
571+ break ;
572+ case NAND_WRITE :
573+ nand_stime = (fc -> next_fc_avail_time < req_stime ) ? req_stime : \
574+ fc -> next_fc_avail_time ;
575+ fc -> next_fc_avail_time = nand_stime + write_delay ;
576+ lat = fc -> next_fc_avail_time - req_stime ;
577+
578+ break ;
579+ case NAND_ERASE :
580+ nand_stime = (fc -> next_fc_avail_time < req_stime ) ? req_stime : \
581+ fc -> next_fc_avail_time ;
582+ fc -> next_fc_avail_time = nand_stime + erase_delay ;
583+ lat = fc -> next_fc_avail_time - req_stime ;
584+
585+ break ;
586+ default :
587+ //lat = 0;
588+ ;
589+ }
590+ return lat ;
591+ }
592+ //----------------------------------
593+
474594static uint64_t zns_advance_zone_wp (NvmeNamespace * ns , NvmeZone * zone ,
475595 uint32_t nlb )
476596{
@@ -502,6 +622,7 @@ struct zns_zone_reset_ctx {
502622static void zns_aio_zone_reset_cb (NvmeRequest * req , NvmeZone * zone )
503623{
504624 NvmeNamespace * ns = req -> ns ;
625+ FemuCtrl * n = ns -> ctrl ;
505626
506627 /* FIXME, We always assume reset SUCCESS */
507628 switch (zns_get_zone_state (zone )) {
@@ -520,6 +641,25 @@ static void zns_aio_zone_reset_cb(NvmeRequest *req, NvmeZone *zone)
520641 default :
521642 break ;
522643 }
644+
645+ struct zns_ssd * zns = n -> zns ;
646+ uint64_t num_ch = zns -> num_ch ;
647+ uint64_t num_lun = zns -> num_lun ;
648+ struct ppa ppa ;
649+
650+ for (int ch = 0 ; ch < num_ch ; ch ++ ){
651+ for (int lun = 0 ; lun < num_lun ; lun ++ ) {
652+ ppa .g .ch = ch ;
653+ ppa .g .fc = lun ;
654+ ppa .g .blk = zns_zone_idx (ns , zone -> d .zslba );
655+
656+ struct nand_cmd erase ;
657+ erase .cmd = NAND_ERASE ;
658+ erase .stime = 0 ;
659+ zns_advance_status (n , & erase , & ppa );
660+
661+ }
662+ }
523663}
524664
525665typedef uint16_t (* op_handler_t )(NvmeNamespace * , NvmeZone * , NvmeZoneState ,
@@ -1172,6 +1312,29 @@ static uint16_t zns_read(FemuCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
11721312 data_offset = zns_l2b (ns , slba );
11731313
11741314 backend_rw (n -> mbe , & req -> qsg , & data_offset , req -> is_write );
1315+
1316+ uint64_t slpn = (slba )/4096 ;
1317+ uint64_t elpn = (slba + nlb - 1 )/4096 ;
1318+
1319+ uint64_t lpn ;
1320+ struct ppa ppa ;
1321+ uint64_t sublat ,maxlat = 0 ;
1322+
1323+ for (lpn = slpn ; lpn <= elpn ; lpn ++ ) {
1324+ ppa = lpn_to_ppa (n , ns , lpn );
1325+ advance_read_pointer (n );
1326+
1327+ struct nand_cmd read ;
1328+ read .cmd = NAND_READ ;
1329+ read .stime = req -> stime ;
1330+
1331+ sublat = zns_advance_status (n , & read , & ppa );
1332+ maxlat = (sublat > maxlat ) ? sublat : maxlat ;
1333+ }
1334+
1335+ req -> reqlat = maxlat ;
1336+ req -> expire_time += maxlat ;
1337+
11751338 return NVME_SUCCESS ;
11761339
11771340err :
@@ -1223,10 +1386,31 @@ static uint16_t zns_write(FemuCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
12231386 if (status ) {
12241387 goto err ;
12251388 }
1226-
1389+
12271390 backend_rw (n -> mbe , & req -> qsg , & data_offset , req -> is_write );
12281391 zns_finalize_zoned_write (ns , req , false);
1392+
1393+ uint64_t slpn = (slba )/4096 ;
1394+ uint64_t elpn = (slba + nlb - 1 )/4096 ;
1395+
1396+ uint64_t lpn ;
1397+ struct ppa ppa ;
1398+ uint64_t sublat ,maxlat = 0 ;
1399+
1400+ for (lpn = slpn ; lpn <= elpn ; lpn ++ ) {
1401+ ppa = lpn_to_ppa (n , ns , lpn );
1402+ advance_read_pointer (n );
12291403
1404+ struct nand_cmd write ;
1405+ write .cmd = NAND_WRITE ;
1406+ write .stime = req -> stime ;
1407+
1408+ sublat = zns_advance_status (n , & write , & ppa );
1409+ maxlat = (sublat > maxlat ) ? sublat : maxlat ;
1410+ }
1411+
1412+ req -> reqlat = maxlat ;
1413+ req -> expire_time += maxlat ;
12301414 return NVME_SUCCESS ;
12311415
12321416err :
@@ -1271,6 +1455,51 @@ static void zns_set_ctrl(FemuCtrl *n)
12711455 pci_config_set_device_id (pci_conf , 0x5845 );
12721456}
12731457
1458+ // Add zns init ch, zns init flash and zns init block
1459+ // ----------------------------
1460+ static void zns_init_blk (struct zns_blk * blk )
1461+ {
1462+ blk -> next_blk_avail_time = 0 ;
1463+ }
1464+
1465+ static void zns_init_fc (struct zns_fc * fc )
1466+ {
1467+ fc -> blk = g_malloc0 (sizeof (struct zns_blk ) * 32 );
1468+ for (int i = 0 ; i < 32 ; i ++ ) {
1469+ zns_init_blk (& fc -> blk [i ]);
1470+ }
1471+ fc -> next_fc_avail_time = 0 ;
1472+ }
1473+
1474+ static void zns_init_ch (struct zns_ch * ch , uint8_t num_lun )
1475+ {
1476+ ch -> fc = g_malloc0 (sizeof (struct zns_fc ) * num_lun );
1477+ for (int i = 0 ; i < num_lun ; i ++ ) {
1478+ zns_init_fc (& ch -> fc [i ]);
1479+ }
1480+ ch -> next_ch_avail_time = 0 ;
1481+ }
1482+
1483+ static void zns_init_params (FemuCtrl * n )
1484+ {
1485+ struct zns_ssd * id_zns ;
1486+
1487+ id_zns = g_malloc0 (sizeof (struct zns_ssd ));
1488+ id_zns -> num_ch = n -> zns_params .zns_num_ch ;
1489+ id_zns -> num_lun = n -> zns_params .zns_num_lun ;
1490+ id_zns -> ch = g_malloc0 (sizeof (struct zns_ch ) * id_zns -> num_ch );
1491+ for (int i = 0 ; i < id_zns -> num_ch ; i ++ ) {
1492+ zns_init_ch (& id_zns -> ch [i ], id_zns -> num_lun );
1493+ }
1494+
1495+ id_zns -> wp .ch = 0 ;
1496+ id_zns -> wp .lun = 0 ;
1497+ n -> zns = id_zns ;
1498+ }
1499+
1500+ // ---------------------------------------
1501+
1502+
12741503static int zns_init_zone_cap (FemuCtrl * n )
12751504{
12761505 n -> zoned = true;
@@ -1281,7 +1510,7 @@ static int zns_init_zone_cap(FemuCtrl *n)
12811510 n -> max_active_zones = 0 ;
12821511 n -> max_open_zones = 0 ;
12831512 n -> zd_extension_size = 0 ;
1284-
1513+
12851514 return 0 ;
12861515}
12871516
@@ -1316,6 +1545,8 @@ static void zns_init(FemuCtrl *n, Error **errp)
13161545 }
13171546
13181547 zns_init_zone_identify (n , ns , 0 );
1548+
1549+ zns_init_params (n );
13191550}
13201551
13211552static void zns_exit (FemuCtrl * n )
0 commit comments