qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

subsys.c (4223B)


      1 /*
      2  * QEMU NVM Express Subsystem: nvme-subsys
      3  *
      4  * Copyright (c) 2021 Minwoo Im <minwoo.im.dev@gmail.com>
      5  *
      6  * This code is licensed under the GNU GPL v2.  Refer COPYING.
      7  */
      8 
      9 #include "qemu/osdep.h"
     10 #include "qapi/error.h"
     11 
     12 #include "nvme.h"
     13 
     14 static int nvme_subsys_reserve_cntlids(NvmeCtrl *n, int start, int num)
     15 {
     16     NvmeSubsystem *subsys = n->subsys;
     17     NvmeSecCtrlList *list = &n->sec_ctrl_list;
     18     NvmeSecCtrlEntry *sctrl;
     19     int i, cnt = 0;
     20 
     21     for (i = start; i < ARRAY_SIZE(subsys->ctrls) && cnt < num; i++) {
     22         if (!subsys->ctrls[i]) {
     23             sctrl = &list->sec[cnt];
     24             sctrl->scid = cpu_to_le16(i);
     25             subsys->ctrls[i] = SUBSYS_SLOT_RSVD;
     26             cnt++;
     27         }
     28     }
     29 
     30     return cnt;
     31 }
     32 
     33 static void nvme_subsys_unreserve_cntlids(NvmeCtrl *n)
     34 {
     35     NvmeSubsystem *subsys = n->subsys;
     36     NvmeSecCtrlList *list = &n->sec_ctrl_list;
     37     NvmeSecCtrlEntry *sctrl;
     38     int i, cntlid;
     39 
     40     for (i = 0; i < n->params.sriov_max_vfs; i++) {
     41         sctrl = &list->sec[i];
     42         cntlid = le16_to_cpu(sctrl->scid);
     43 
     44         if (cntlid) {
     45             assert(subsys->ctrls[cntlid] == SUBSYS_SLOT_RSVD);
     46             subsys->ctrls[cntlid] = NULL;
     47             sctrl->scid = 0;
     48         }
     49     }
     50 }
     51 
     52 int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp)
     53 {
     54     NvmeSubsystem *subsys = n->subsys;
     55     NvmeSecCtrlEntry *sctrl = nvme_sctrl(n);
     56     int cntlid, nsid, num_rsvd, num_vfs = n->params.sriov_max_vfs;
     57 
     58     if (pci_is_vf(&n->parent_obj)) {
     59         cntlid = le16_to_cpu(sctrl->scid);
     60     } else {
     61         for (cntlid = 0; cntlid < ARRAY_SIZE(subsys->ctrls); cntlid++) {
     62             if (!subsys->ctrls[cntlid]) {
     63                 break;
     64             }
     65         }
     66 
     67         if (cntlid == ARRAY_SIZE(subsys->ctrls)) {
     68             error_setg(errp, "no more free controller id");
     69             return -1;
     70         }
     71 
     72         num_rsvd = nvme_subsys_reserve_cntlids(n, cntlid + 1, num_vfs);
     73         if (num_rsvd != num_vfs) {
     74             nvme_subsys_unreserve_cntlids(n);
     75             error_setg(errp,
     76                        "no more free controller ids for secondary controllers");
     77             return -1;
     78         }
     79     }
     80 
     81     if (!subsys->serial) {
     82         subsys->serial = g_strdup(n->params.serial);
     83     } else if (strcmp(subsys->serial, n->params.serial)) {
     84         error_setg(errp, "invalid controller serial");
     85         return -1;
     86     }
     87 
     88     subsys->ctrls[cntlid] = n;
     89 
     90     for (nsid = 1; nsid < ARRAY_SIZE(subsys->namespaces); nsid++) {
     91         NvmeNamespace *ns = subsys->namespaces[nsid];
     92         if (ns && ns->params.shared && !ns->params.detached) {
     93             nvme_attach_ns(n, ns);
     94         }
     95     }
     96 
     97     return cntlid;
     98 }
     99 
    100 void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n)
    101 {
    102     if (pci_is_vf(&n->parent_obj)) {
    103         subsys->ctrls[n->cntlid] = SUBSYS_SLOT_RSVD;
    104     } else {
    105         subsys->ctrls[n->cntlid] = NULL;
    106         nvme_subsys_unreserve_cntlids(n);
    107     }
    108 
    109     n->cntlid = -1;
    110 }
    111 
    112 static void nvme_subsys_setup(NvmeSubsystem *subsys)
    113 {
    114     const char *nqn = subsys->params.nqn ?
    115         subsys->params.nqn : subsys->parent_obj.id;
    116 
    117     snprintf((char *)subsys->subnqn, sizeof(subsys->subnqn),
    118              "nqn.2019-08.org.qemu:%s", nqn);
    119 }
    120 
    121 static void nvme_subsys_realize(DeviceState *dev, Error **errp)
    122 {
    123     NvmeSubsystem *subsys = NVME_SUBSYS(dev);
    124 
    125     qbus_init(&subsys->bus, sizeof(NvmeBus), TYPE_NVME_BUS, dev, dev->id);
    126 
    127     nvme_subsys_setup(subsys);
    128 }
    129 
    130 static Property nvme_subsystem_props[] = {
    131     DEFINE_PROP_STRING("nqn", NvmeSubsystem, params.nqn),
    132     DEFINE_PROP_END_OF_LIST(),
    133 };
    134 
    135 static void nvme_subsys_class_init(ObjectClass *oc, void *data)
    136 {
    137     DeviceClass *dc = DEVICE_CLASS(oc);
    138 
    139     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
    140 
    141     dc->realize = nvme_subsys_realize;
    142     dc->desc = "Virtual NVMe subsystem";
    143     dc->hotpluggable = false;
    144 
    145     device_class_set_props(dc, nvme_subsystem_props);
    146 }
    147 
    148 static const TypeInfo nvme_subsys_info = {
    149     .name = TYPE_NVME_SUBSYS,
    150     .parent = TYPE_DEVICE,
    151     .class_init = nvme_subsys_class_init,
    152     .instance_size = sizeof(NvmeSubsystem),
    153 };
    154 
    155 static void nvme_subsys_register_types(void)
    156 {
    157     type_register_static(&nvme_subsys_info);
    158 }
    159 
    160 type_init(nvme_subsys_register_types)