qemu

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

pcie_root_port.c (5146B)


      1 /*
      2  * Base class for PCI Express Root Ports
      3  *
      4  * Copyright (C) 2017 Red Hat Inc
      5  *
      6  * Authors:
      7  *   Marcel Apfelbaum <marcel@redhat.com>
      8  *
      9  * Most of the code was migrated from hw/pci-bridge/ioh3420.
     10  *
     11  * This work is licensed under the terms of the GNU GPL, version 2 or later.
     12  * See the COPYING file in the top-level directory.
     13  */
     14 
     15 #include "qemu/osdep.h"
     16 #include "qapi/error.h"
     17 #include "qemu/module.h"
     18 #include "hw/pci/pcie_port.h"
     19 #include "hw/qdev-properties.h"
     20 
     21 static void rp_aer_vector_update(PCIDevice *d)
     22 {
     23     PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
     24 
     25     if (rpc->aer_vector) {
     26         pcie_aer_root_set_vector(d, rpc->aer_vector(d));
     27     }
     28 }
     29 
     30 static void rp_write_config(PCIDevice *d, uint32_t address,
     31                             uint32_t val, int len)
     32 {
     33     uint32_t root_cmd =
     34         pci_get_long(d->config + d->exp.aer_cap + PCI_ERR_ROOT_COMMAND);
     35     uint16_t slt_ctl, slt_sta;
     36 
     37     pcie_cap_slot_get(d, &slt_ctl, &slt_sta);
     38 
     39     pci_bridge_write_config(d, address, val, len);
     40     rp_aer_vector_update(d);
     41     pcie_cap_slot_write_config(d, slt_ctl, slt_sta, address, val, len);
     42     pcie_aer_write_config(d, address, val, len);
     43     pcie_aer_root_write_config(d, address, val, len, root_cmd);
     44 }
     45 
     46 static void rp_reset(DeviceState *qdev)
     47 {
     48     PCIDevice *d = PCI_DEVICE(qdev);
     49 
     50     rp_aer_vector_update(d);
     51     pcie_cap_root_reset(d);
     52     pcie_cap_deverr_reset(d);
     53     pcie_cap_slot_reset(d);
     54     pcie_cap_arifwd_reset(d);
     55     pcie_acs_reset(d);
     56     pcie_aer_root_reset(d);
     57     pci_bridge_reset(qdev);
     58     pci_bridge_disable_base_limit(d);
     59 }
     60 
     61 static void rp_realize(PCIDevice *d, Error **errp)
     62 {
     63     PCIEPort *p = PCIE_PORT(d);
     64     PCIESlot *s = PCIE_SLOT(d);
     65     PCIDeviceClass *dc = PCI_DEVICE_GET_CLASS(d);
     66     PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
     67     int rc;
     68 
     69     pci_config_set_interrupt_pin(d->config, 1);
     70     if (d->cap_present & QEMU_PCIE_CAP_CXL) {
     71         pci_bridge_initfn(d, TYPE_CXL_BUS);
     72     } else {
     73         pci_bridge_initfn(d, TYPE_PCIE_BUS);
     74     }
     75     pcie_port_init_reg(d);
     76 
     77     rc = pci_bridge_ssvid_init(d, rpc->ssvid_offset, dc->vendor_id,
     78                                rpc->ssid, errp);
     79     if (rc < 0) {
     80         error_append_hint(errp, "Can't init SSV ID, error %d\n", rc);
     81         goto err_bridge;
     82     }
     83 
     84     if (rpc->interrupts_init) {
     85         rc = rpc->interrupts_init(d, errp);
     86         if (rc < 0) {
     87             goto err_bridge;
     88         }
     89     }
     90 
     91     rc = pcie_cap_init(d, rpc->exp_offset, PCI_EXP_TYPE_ROOT_PORT,
     92                        p->port, errp);
     93     if (rc < 0) {
     94         error_append_hint(errp, "Can't add Root Port capability, "
     95                           "error %d\n", rc);
     96         goto err_int;
     97     }
     98 
     99     pcie_cap_arifwd_init(d);
    100     pcie_cap_deverr_init(d);
    101     pcie_cap_slot_init(d, s);
    102     pcie_cap_root_init(d);
    103 
    104     pcie_chassis_create(s->chassis);
    105     rc = pcie_chassis_add_slot(s);
    106     if (rc < 0) {
    107         error_setg(errp, "Can't add chassis slot, error %d", rc);
    108         goto err_pcie_cap;
    109     }
    110 
    111     rc = pcie_aer_init(d, PCI_ERR_VER, rpc->aer_offset,
    112                        PCI_ERR_SIZEOF, errp);
    113     if (rc < 0) {
    114         goto err;
    115     }
    116     pcie_aer_root_init(d);
    117     rp_aer_vector_update(d);
    118 
    119     if (rpc->acs_offset && !s->disable_acs) {
    120         pcie_acs_init(d, rpc->acs_offset);
    121     }
    122     return;
    123 
    124 err:
    125     pcie_chassis_del_slot(s);
    126 err_pcie_cap:
    127     pcie_cap_exit(d);
    128 err_int:
    129     if (rpc->interrupts_uninit) {
    130         rpc->interrupts_uninit(d);
    131     }
    132 err_bridge:
    133     pci_bridge_exitfn(d);
    134 }
    135 
    136 static void rp_exit(PCIDevice *d)
    137 {
    138     PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(d);
    139     PCIESlot *s = PCIE_SLOT(d);
    140 
    141     pcie_aer_exit(d);
    142     pcie_chassis_del_slot(s);
    143     pcie_cap_exit(d);
    144     if (rpc->interrupts_uninit) {
    145         rpc->interrupts_uninit(d);
    146     }
    147     pci_bridge_exitfn(d);
    148 }
    149 
    150 static Property rp_props[] = {
    151     DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
    152                     QEMU_PCIE_SLTCAP_PCP_BITNR, true),
    153     DEFINE_PROP_BOOL("disable-acs", PCIESlot, disable_acs, false),
    154     DEFINE_PROP_END_OF_LIST()
    155 };
    156 
    157 static void rp_instance_post_init(Object *obj)
    158 {
    159     PCIESlot *s = PCIE_SLOT(obj);
    160 
    161     if (!s->speed) {
    162         s->speed = QEMU_PCI_EXP_LNK_2_5GT;
    163     }
    164 
    165     if (!s->width) {
    166         s->width = QEMU_PCI_EXP_LNK_X1;
    167     }
    168 }
    169 
    170 static void rp_class_init(ObjectClass *klass, void *data)
    171 {
    172     DeviceClass *dc = DEVICE_CLASS(klass);
    173     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    174 
    175     k->is_bridge = true;
    176     k->config_write = rp_write_config;
    177     k->realize = rp_realize;
    178     k->exit = rp_exit;
    179     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    180     dc->reset = rp_reset;
    181     device_class_set_props(dc, rp_props);
    182 }
    183 
    184 static const TypeInfo rp_info = {
    185     .name          = TYPE_PCIE_ROOT_PORT,
    186     .parent        = TYPE_PCIE_SLOT,
    187     .instance_post_init = rp_instance_post_init,
    188     .class_init    = rp_class_init,
    189     .abstract      = true,
    190     .class_size = sizeof(PCIERootPortClass),
    191     .interfaces = (InterfaceInfo[]) {
    192         { INTERFACE_PCIE_DEVICE },
    193         { }
    194     },
    195 };
    196 
    197 static void rp_register_types(void)
    198 {
    199     type_register_static(&rp_info);
    200 }
    201 
    202 type_init(rp_register_types)