xref: /qemu/hw/nvme/subsys.c (revision a859eb9f8f64e116671048a43a07d87bc6527a55)
1eb2e8974SMinwoo Im /*
2eb2e8974SMinwoo Im  * QEMU NVM Express Subsystem: nvme-subsys
3eb2e8974SMinwoo Im  *
4eb2e8974SMinwoo Im  * Copyright (c) 2021 Minwoo Im <minwoo.im.dev@gmail.com>
5eb2e8974SMinwoo Im  *
6eb2e8974SMinwoo Im  * This code is licensed under the GNU GPL v2.  Refer COPYING.
7eb2e8974SMinwoo Im  */
8eb2e8974SMinwoo Im 
9eb2e8974SMinwoo Im #include "qemu/osdep.h"
10eb2e8974SMinwoo Im #include "qapi/error.h"
117ef37c1cSKlaus Jensen 
12eb2e8974SMinwoo Im #include "nvme.h"
13eb2e8974SMinwoo Im 
14e36a261dSMinwoo Im int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp)
15e36a261dSMinwoo Im {
16e36a261dSMinwoo Im     NvmeSubsystem *subsys = n->subsys;
179fc6e86eSHannes Reinecke     int cntlid, nsid;
18e36a261dSMinwoo Im 
19e36a261dSMinwoo Im     for (cntlid = 0; cntlid < ARRAY_SIZE(subsys->ctrls); cntlid++) {
20e36a261dSMinwoo Im         if (!subsys->ctrls[cntlid]) {
21e36a261dSMinwoo Im             break;
22e36a261dSMinwoo Im         }
23e36a261dSMinwoo Im     }
24e36a261dSMinwoo Im 
25e36a261dSMinwoo Im     if (cntlid == ARRAY_SIZE(subsys->ctrls)) {
26e36a261dSMinwoo Im         error_setg(errp, "no more free controller id");
27e36a261dSMinwoo Im         return -1;
28e36a261dSMinwoo Im     }
29e36a261dSMinwoo Im 
30*a859eb9fSKlaus Jensen     if (!subsys->serial) {
31*a859eb9fSKlaus Jensen         subsys->serial = g_strdup(n->params.serial);
32*a859eb9fSKlaus Jensen     } else if (strcmp(subsys->serial, n->params.serial)) {
33*a859eb9fSKlaus Jensen         error_setg(errp, "invalid controller serial");
34*a859eb9fSKlaus Jensen         return -1;
35*a859eb9fSKlaus Jensen     }
36*a859eb9fSKlaus Jensen 
37e36a261dSMinwoo Im     subsys->ctrls[cntlid] = n;
38e36a261dSMinwoo Im 
399fc6e86eSHannes Reinecke     for (nsid = 1; nsid < ARRAY_SIZE(subsys->namespaces); nsid++) {
409fc6e86eSHannes Reinecke         NvmeNamespace *ns = subsys->namespaces[nsid];
419fc6e86eSHannes Reinecke         if (ns && ns->params.shared && !ns->params.detached) {
429fc6e86eSHannes Reinecke             nvme_attach_ns(n, ns);
439fc6e86eSHannes Reinecke         }
449fc6e86eSHannes Reinecke     }
459fc6e86eSHannes Reinecke 
46e36a261dSMinwoo Im     return cntlid;
47e36a261dSMinwoo Im }
48e36a261dSMinwoo Im 
49b0fde9e8SKlaus Jensen void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n)
50b0fde9e8SKlaus Jensen {
51b0fde9e8SKlaus Jensen     subsys->ctrls[n->cntlid] = NULL;
529fc6e86eSHannes Reinecke     n->cntlid = -1;
53b0fde9e8SKlaus Jensen }
54b0fde9e8SKlaus Jensen 
55eb2e8974SMinwoo Im static void nvme_subsys_setup(NvmeSubsystem *subsys)
56eb2e8974SMinwoo Im {
57eb2e8974SMinwoo Im     const char *nqn = subsys->params.nqn ?
58eb2e8974SMinwoo Im         subsys->params.nqn : subsys->parent_obj.id;
59eb2e8974SMinwoo Im 
60eb2e8974SMinwoo Im     snprintf((char *)subsys->subnqn, sizeof(subsys->subnqn),
61eb2e8974SMinwoo Im              "nqn.2019-08.org.qemu:%s", nqn);
62eb2e8974SMinwoo Im }
63eb2e8974SMinwoo Im 
64eb2e8974SMinwoo Im static void nvme_subsys_realize(DeviceState *dev, Error **errp)
65eb2e8974SMinwoo Im {
66eb2e8974SMinwoo Im     NvmeSubsystem *subsys = NVME_SUBSYS(dev);
67eb2e8974SMinwoo Im 
68d637e1dcSPeter Maydell     qbus_init(&subsys->bus, sizeof(NvmeBus), TYPE_NVME_BUS, dev, dev->id);
695ffbaeedSKlaus Jensen 
70eb2e8974SMinwoo Im     nvme_subsys_setup(subsys);
71eb2e8974SMinwoo Im }
72eb2e8974SMinwoo Im 
73eb2e8974SMinwoo Im static Property nvme_subsystem_props[] = {
74eb2e8974SMinwoo Im     DEFINE_PROP_STRING("nqn", NvmeSubsystem, params.nqn),
75eb2e8974SMinwoo Im     DEFINE_PROP_END_OF_LIST(),
76eb2e8974SMinwoo Im };
77eb2e8974SMinwoo Im 
78eb2e8974SMinwoo Im static void nvme_subsys_class_init(ObjectClass *oc, void *data)
79eb2e8974SMinwoo Im {
80eb2e8974SMinwoo Im     DeviceClass *dc = DEVICE_CLASS(oc);
81eb2e8974SMinwoo Im 
82eb2e8974SMinwoo Im     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
83eb2e8974SMinwoo Im 
84eb2e8974SMinwoo Im     dc->realize = nvme_subsys_realize;
85eb2e8974SMinwoo Im     dc->desc = "Virtual NVMe subsystem";
86cc6fb6bcSKlaus Jensen     dc->hotpluggable = false;
87eb2e8974SMinwoo Im 
88eb2e8974SMinwoo Im     device_class_set_props(dc, nvme_subsystem_props);
89eb2e8974SMinwoo Im }
90eb2e8974SMinwoo Im 
91eb2e8974SMinwoo Im static const TypeInfo nvme_subsys_info = {
92eb2e8974SMinwoo Im     .name = TYPE_NVME_SUBSYS,
93eb2e8974SMinwoo Im     .parent = TYPE_DEVICE,
94eb2e8974SMinwoo Im     .class_init = nvme_subsys_class_init,
95eb2e8974SMinwoo Im     .instance_size = sizeof(NvmeSubsystem),
96eb2e8974SMinwoo Im };
97eb2e8974SMinwoo Im 
98eb2e8974SMinwoo Im static void nvme_subsys_register_types(void)
99eb2e8974SMinwoo Im {
100eb2e8974SMinwoo Im     type_register_static(&nvme_subsys_info);
101eb2e8974SMinwoo Im }
102eb2e8974SMinwoo Im 
103eb2e8974SMinwoo Im type_init(nvme_subsys_register_types)
104