xref: /openbmc/qemu/hw/net/igbvf.c (revision 445416e3)
13a977deeSAkihiko Odaki /*
23a977deeSAkihiko Odaki  * QEMU Intel 82576 SR/IOV Ethernet Controller Emulation
33a977deeSAkihiko Odaki  *
43a977deeSAkihiko Odaki  * Datasheet:
53a977deeSAkihiko Odaki  * https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eg-gbe-datasheet.pdf
63a977deeSAkihiko Odaki  *
73a977deeSAkihiko Odaki  * Copyright (c) 2020-2023 Red Hat, Inc.
83a977deeSAkihiko Odaki  * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
93a977deeSAkihiko Odaki  * Developed by Daynix Computing LTD (http://www.daynix.com)
103a977deeSAkihiko Odaki  *
113a977deeSAkihiko Odaki  * Authors:
123a977deeSAkihiko Odaki  * Akihiko Odaki <akihiko.odaki@daynix.com>
133a977deeSAkihiko Odaki  * Gal Hammmer <gal.hammer@sap.com>
143a977deeSAkihiko Odaki  * Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
153a977deeSAkihiko Odaki  * Dmitry Fleytman <dmitry@daynix.com>
163a977deeSAkihiko Odaki  * Leonid Bloch <leonid@daynix.com>
173a977deeSAkihiko Odaki  * Yan Vugenfirer <yan@daynix.com>
183a977deeSAkihiko Odaki  *
193a977deeSAkihiko Odaki  * Based on work done by:
203a977deeSAkihiko Odaki  * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
213a977deeSAkihiko Odaki  * Copyright (c) 2008 Qumranet
223a977deeSAkihiko Odaki  * Based on work done by:
233a977deeSAkihiko Odaki  * Copyright (c) 2007 Dan Aloni
243a977deeSAkihiko Odaki  * Copyright (c) 2004 Antony T Curtis
253a977deeSAkihiko Odaki  *
263a977deeSAkihiko Odaki  * This library is free software; you can redistribute it and/or
273a977deeSAkihiko Odaki  * modify it under the terms of the GNU Lesser General Public
283a977deeSAkihiko Odaki  * License as published by the Free Software Foundation; either
293a977deeSAkihiko Odaki  * version 2.1 of the License, or (at your option) any later version.
303a977deeSAkihiko Odaki  *
313a977deeSAkihiko Odaki  * This library is distributed in the hope that it will be useful,
323a977deeSAkihiko Odaki  * but WITHOUT ANY WARRANTY; without even the implied warranty of
333a977deeSAkihiko Odaki  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
343a977deeSAkihiko Odaki  * Lesser General Public License for more details.
353a977deeSAkihiko Odaki  *
363a977deeSAkihiko Odaki  * You should have received a copy of the GNU Lesser General Public
373a977deeSAkihiko Odaki  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
383a977deeSAkihiko Odaki  */
393a977deeSAkihiko Odaki 
403a977deeSAkihiko Odaki #include "qemu/osdep.h"
413a977deeSAkihiko Odaki #include "hw/hw.h"
423a977deeSAkihiko Odaki #include "hw/net/mii.h"
433a977deeSAkihiko Odaki #include "hw/pci/pci_device.h"
443a977deeSAkihiko Odaki #include "hw/pci/pcie.h"
453a977deeSAkihiko Odaki #include "hw/pci/msix.h"
463a977deeSAkihiko Odaki #include "net/eth.h"
473a977deeSAkihiko Odaki #include "net/net.h"
483a977deeSAkihiko Odaki #include "igb_common.h"
493a977deeSAkihiko Odaki #include "igb_core.h"
503a977deeSAkihiko Odaki #include "trace.h"
513a977deeSAkihiko Odaki #include "qapi/error.h"
523a977deeSAkihiko Odaki 
533a977deeSAkihiko Odaki OBJECT_DECLARE_SIMPLE_TYPE(IgbVfState, IGBVF)
543a977deeSAkihiko Odaki 
553a977deeSAkihiko Odaki struct IgbVfState {
563a977deeSAkihiko Odaki     PCIDevice parent_obj;
573a977deeSAkihiko Odaki 
583a977deeSAkihiko Odaki     MemoryRegion mmio;
593a977deeSAkihiko Odaki     MemoryRegion msix;
603a977deeSAkihiko Odaki };
613a977deeSAkihiko Odaki 
623a977deeSAkihiko Odaki static hwaddr vf_to_pf_addr(hwaddr addr, uint16_t vfn, bool write)
633a977deeSAkihiko Odaki {
643a977deeSAkihiko Odaki     switch (addr) {
653a977deeSAkihiko Odaki     case E1000_CTRL:
663a977deeSAkihiko Odaki     case E1000_CTRL_DUP:
673a977deeSAkihiko Odaki         return E1000_PVTCTRL(vfn);
683a977deeSAkihiko Odaki     case E1000_EICS:
693a977deeSAkihiko Odaki         return E1000_PVTEICS(vfn);
703a977deeSAkihiko Odaki     case E1000_EIMS:
713a977deeSAkihiko Odaki         return E1000_PVTEIMS(vfn);
723a977deeSAkihiko Odaki     case E1000_EIMC:
733a977deeSAkihiko Odaki         return E1000_PVTEIMC(vfn);
743a977deeSAkihiko Odaki     case E1000_EIAC:
753a977deeSAkihiko Odaki         return E1000_PVTEIAC(vfn);
763a977deeSAkihiko Odaki     case E1000_EIAM:
773a977deeSAkihiko Odaki         return E1000_PVTEIAM(vfn);
783a977deeSAkihiko Odaki     case E1000_EICR:
793a977deeSAkihiko Odaki         return E1000_PVTEICR(vfn);
803a977deeSAkihiko Odaki     case E1000_EITR(0):
813a977deeSAkihiko Odaki     case E1000_EITR(1):
823a977deeSAkihiko Odaki     case E1000_EITR(2):
833a977deeSAkihiko Odaki         return E1000_EITR(22) + (addr - E1000_EITR(0)) - vfn * 0xC;
843a977deeSAkihiko Odaki     case E1000_IVAR0:
853a977deeSAkihiko Odaki         return E1000_VTIVAR + vfn * 4;
863a977deeSAkihiko Odaki     case E1000_IVAR_MISC:
873a977deeSAkihiko Odaki         return E1000_VTIVAR_MISC + vfn * 4;
883a977deeSAkihiko Odaki     case 0x0F04: /* PBACL */
893a977deeSAkihiko Odaki         return E1000_PBACLR;
903a977deeSAkihiko Odaki     case 0x0F0C: /* PSRTYPE */
913a977deeSAkihiko Odaki         return E1000_PSRTYPE(vfn);
923a977deeSAkihiko Odaki     case E1000_V2PMAILBOX(0):
933a977deeSAkihiko Odaki         return E1000_V2PMAILBOX(vfn);
943a977deeSAkihiko Odaki     case E1000_VMBMEM(0) ... E1000_VMBMEM(0) + 0x3F:
953a977deeSAkihiko Odaki         return addr + vfn * 0x40;
963a977deeSAkihiko Odaki     case E1000_RDBAL_A(0):
973a977deeSAkihiko Odaki         return E1000_RDBAL(vfn);
983a977deeSAkihiko Odaki     case E1000_RDBAL_A(1):
993a977deeSAkihiko Odaki         return E1000_RDBAL(vfn + IGB_MAX_VF_FUNCTIONS);
1003a977deeSAkihiko Odaki     case E1000_RDBAH_A(0):
1013a977deeSAkihiko Odaki         return E1000_RDBAH(vfn);
1023a977deeSAkihiko Odaki     case E1000_RDBAH_A(1):
1033a977deeSAkihiko Odaki         return E1000_RDBAH(vfn + IGB_MAX_VF_FUNCTIONS);
1043a977deeSAkihiko Odaki     case E1000_RDLEN_A(0):
1053a977deeSAkihiko Odaki         return E1000_RDLEN(vfn);
1063a977deeSAkihiko Odaki     case E1000_RDLEN_A(1):
1073a977deeSAkihiko Odaki         return E1000_RDLEN(vfn + IGB_MAX_VF_FUNCTIONS);
1083a977deeSAkihiko Odaki     case E1000_SRRCTL_A(0):
1093a977deeSAkihiko Odaki         return E1000_SRRCTL(vfn);
1103a977deeSAkihiko Odaki     case E1000_SRRCTL_A(1):
1113a977deeSAkihiko Odaki         return E1000_SRRCTL(vfn + IGB_MAX_VF_FUNCTIONS);
1123a977deeSAkihiko Odaki     case E1000_RDH_A(0):
1133a977deeSAkihiko Odaki         return E1000_RDH(vfn);
1143a977deeSAkihiko Odaki     case E1000_RDH_A(1):
1153a977deeSAkihiko Odaki         return E1000_RDH(vfn + IGB_MAX_VF_FUNCTIONS);
1163a977deeSAkihiko Odaki     case E1000_RXCTL_A(0):
1173a977deeSAkihiko Odaki         return E1000_RXCTL(vfn);
1183a977deeSAkihiko Odaki     case E1000_RXCTL_A(1):
1193a977deeSAkihiko Odaki         return E1000_RXCTL(vfn + IGB_MAX_VF_FUNCTIONS);
1203a977deeSAkihiko Odaki     case E1000_RDT_A(0):
1213a977deeSAkihiko Odaki         return E1000_RDT(vfn);
1223a977deeSAkihiko Odaki     case E1000_RDT_A(1):
1233a977deeSAkihiko Odaki         return E1000_RDT(vfn + IGB_MAX_VF_FUNCTIONS);
1243a977deeSAkihiko Odaki     case E1000_RXDCTL_A(0):
1253a977deeSAkihiko Odaki         return E1000_RXDCTL(vfn);
1263a977deeSAkihiko Odaki     case E1000_RXDCTL_A(1):
1273a977deeSAkihiko Odaki         return E1000_RXDCTL(vfn + IGB_MAX_VF_FUNCTIONS);
1283a977deeSAkihiko Odaki     case E1000_RQDPC_A(0):
1293a977deeSAkihiko Odaki         return E1000_RQDPC(vfn);
1303a977deeSAkihiko Odaki     case E1000_RQDPC_A(1):
1313a977deeSAkihiko Odaki         return E1000_RQDPC(vfn + IGB_MAX_VF_FUNCTIONS);
1323a977deeSAkihiko Odaki     case E1000_TDBAL_A(0):
1333a977deeSAkihiko Odaki         return E1000_TDBAL(vfn);
1343a977deeSAkihiko Odaki     case E1000_TDBAL_A(1):
1353a977deeSAkihiko Odaki         return E1000_TDBAL(vfn + IGB_MAX_VF_FUNCTIONS);
1363a977deeSAkihiko Odaki     case E1000_TDBAH_A(0):
1373a977deeSAkihiko Odaki         return E1000_TDBAH(vfn);
1383a977deeSAkihiko Odaki     case E1000_TDBAH_A(1):
1393a977deeSAkihiko Odaki         return E1000_TDBAH(vfn + IGB_MAX_VF_FUNCTIONS);
1403a977deeSAkihiko Odaki     case E1000_TDLEN_A(0):
1413a977deeSAkihiko Odaki         return E1000_TDLEN(vfn);
1423a977deeSAkihiko Odaki     case E1000_TDLEN_A(1):
1433a977deeSAkihiko Odaki         return E1000_TDLEN(vfn + IGB_MAX_VF_FUNCTIONS);
1443a977deeSAkihiko Odaki     case E1000_TDH_A(0):
1453a977deeSAkihiko Odaki         return E1000_TDH(vfn);
1463a977deeSAkihiko Odaki     case E1000_TDH_A(1):
1473a977deeSAkihiko Odaki         return E1000_TDH(vfn + IGB_MAX_VF_FUNCTIONS);
1483a977deeSAkihiko Odaki     case E1000_TXCTL_A(0):
1493a977deeSAkihiko Odaki         return E1000_TXCTL(vfn);
1503a977deeSAkihiko Odaki     case E1000_TXCTL_A(1):
1513a977deeSAkihiko Odaki         return E1000_TXCTL(vfn + IGB_MAX_VF_FUNCTIONS);
1523a977deeSAkihiko Odaki     case E1000_TDT_A(0):
1533a977deeSAkihiko Odaki         return E1000_TDT(vfn);
1543a977deeSAkihiko Odaki     case E1000_TDT_A(1):
1553a977deeSAkihiko Odaki         return E1000_TDT(vfn + IGB_MAX_VF_FUNCTIONS);
1563a977deeSAkihiko Odaki     case E1000_TXDCTL_A(0):
1573a977deeSAkihiko Odaki         return E1000_TXDCTL(vfn);
1583a977deeSAkihiko Odaki     case E1000_TXDCTL_A(1):
1593a977deeSAkihiko Odaki         return E1000_TXDCTL(vfn + IGB_MAX_VF_FUNCTIONS);
1603a977deeSAkihiko Odaki     case E1000_TDWBAL_A(0):
1613a977deeSAkihiko Odaki         return E1000_TDWBAL(vfn);
1623a977deeSAkihiko Odaki     case E1000_TDWBAL_A(1):
1633a977deeSAkihiko Odaki         return E1000_TDWBAL(vfn + IGB_MAX_VF_FUNCTIONS);
1643a977deeSAkihiko Odaki     case E1000_TDWBAH_A(0):
1653a977deeSAkihiko Odaki         return E1000_TDWBAH(vfn);
1663a977deeSAkihiko Odaki     case E1000_TDWBAH_A(1):
1673a977deeSAkihiko Odaki         return E1000_TDWBAH(vfn + IGB_MAX_VF_FUNCTIONS);
1683a977deeSAkihiko Odaki     case E1000_VFGPRC:
1693a977deeSAkihiko Odaki         return E1000_PVFGPRC(vfn);
1703a977deeSAkihiko Odaki     case E1000_VFGPTC:
1713a977deeSAkihiko Odaki         return E1000_PVFGPTC(vfn);
1723a977deeSAkihiko Odaki     case E1000_VFGORC:
1733a977deeSAkihiko Odaki         return E1000_PVFGORC(vfn);
1743a977deeSAkihiko Odaki     case E1000_VFGOTC:
1753a977deeSAkihiko Odaki         return E1000_PVFGOTC(vfn);
1763a977deeSAkihiko Odaki     case E1000_VFMPRC:
1773a977deeSAkihiko Odaki         return E1000_PVFMPRC(vfn);
1783a977deeSAkihiko Odaki     case E1000_VFGPRLBC:
1793a977deeSAkihiko Odaki         return E1000_PVFGPRLBC(vfn);
1803a977deeSAkihiko Odaki     case E1000_VFGPTLBC:
1813a977deeSAkihiko Odaki         return E1000_PVFGPTLBC(vfn);
1823a977deeSAkihiko Odaki     case E1000_VFGORLBC:
1833a977deeSAkihiko Odaki         return E1000_PVFGORLBC(vfn);
1843a977deeSAkihiko Odaki     case E1000_VFGOTLBC:
1853a977deeSAkihiko Odaki         return E1000_PVFGOTLBC(vfn);
1863a977deeSAkihiko Odaki     case E1000_STATUS:
1873a977deeSAkihiko Odaki     case E1000_FRTIMER:
1883a977deeSAkihiko Odaki         if (write) {
1893a977deeSAkihiko Odaki             return HWADDR_MAX;
1903a977deeSAkihiko Odaki         }
1913a977deeSAkihiko Odaki         /* fallthrough */
1923a977deeSAkihiko Odaki     case 0x34E8: /* PBTWAC */
1933a977deeSAkihiko Odaki     case 0x24E8: /* PBRWAC */
1943a977deeSAkihiko Odaki         return addr;
1953a977deeSAkihiko Odaki     }
1963a977deeSAkihiko Odaki 
1973a977deeSAkihiko Odaki     trace_igbvf_wrn_io_addr_unknown(addr);
1983a977deeSAkihiko Odaki 
1993a977deeSAkihiko Odaki     return HWADDR_MAX;
2003a977deeSAkihiko Odaki }
2013a977deeSAkihiko Odaki 
2023a977deeSAkihiko Odaki static void igbvf_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
2033a977deeSAkihiko Odaki     int len)
2043a977deeSAkihiko Odaki {
2053a977deeSAkihiko Odaki     trace_igbvf_write_config(addr, val, len);
2063a977deeSAkihiko Odaki     pci_default_write_config(dev, addr, val, len);
2073a977deeSAkihiko Odaki }
2083a977deeSAkihiko Odaki 
2093a977deeSAkihiko Odaki static uint64_t igbvf_mmio_read(void *opaque, hwaddr addr, unsigned size)
2103a977deeSAkihiko Odaki {
2113a977deeSAkihiko Odaki     PCIDevice *vf = PCI_DEVICE(opaque);
2123a977deeSAkihiko Odaki     PCIDevice *pf = pcie_sriov_get_pf(vf);
2133a977deeSAkihiko Odaki 
2143a977deeSAkihiko Odaki     addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), false);
2153a977deeSAkihiko Odaki     return addr == HWADDR_MAX ? 0 : igb_mmio_read(pf, addr, size);
2163a977deeSAkihiko Odaki }
2173a977deeSAkihiko Odaki 
2183a977deeSAkihiko Odaki static void igbvf_mmio_write(void *opaque, hwaddr addr, uint64_t val,
2193a977deeSAkihiko Odaki     unsigned size)
2203a977deeSAkihiko Odaki {
2213a977deeSAkihiko Odaki     PCIDevice *vf = PCI_DEVICE(opaque);
2223a977deeSAkihiko Odaki     PCIDevice *pf = pcie_sriov_get_pf(vf);
2233a977deeSAkihiko Odaki 
2243a977deeSAkihiko Odaki     addr = vf_to_pf_addr(addr, pcie_sriov_vf_number(vf), true);
2253a977deeSAkihiko Odaki     if (addr != HWADDR_MAX) {
2263a977deeSAkihiko Odaki         igb_mmio_write(pf, addr, val, size);
2273a977deeSAkihiko Odaki     }
2283a977deeSAkihiko Odaki }
2293a977deeSAkihiko Odaki 
2303a977deeSAkihiko Odaki static const MemoryRegionOps mmio_ops = {
2313a977deeSAkihiko Odaki     .read = igbvf_mmio_read,
2323a977deeSAkihiko Odaki     .write = igbvf_mmio_write,
2333a977deeSAkihiko Odaki     .endianness = DEVICE_LITTLE_ENDIAN,
2343a977deeSAkihiko Odaki     .impl = {
2353a977deeSAkihiko Odaki         .min_access_size = 4,
2363a977deeSAkihiko Odaki         .max_access_size = 4,
2373a977deeSAkihiko Odaki     },
2383a977deeSAkihiko Odaki };
2393a977deeSAkihiko Odaki 
2403a977deeSAkihiko Odaki static void igbvf_pci_realize(PCIDevice *dev, Error **errp)
2413a977deeSAkihiko Odaki {
2423a977deeSAkihiko Odaki     IgbVfState *s = IGBVF(dev);
2433a977deeSAkihiko Odaki     int ret;
2443a977deeSAkihiko Odaki     int i;
2453a977deeSAkihiko Odaki 
2463a977deeSAkihiko Odaki     dev->config_write = igbvf_write_config;
2473a977deeSAkihiko Odaki 
2483a977deeSAkihiko Odaki     memory_region_init_io(&s->mmio, OBJECT(dev), &mmio_ops, s, "igbvf-mmio",
2493a977deeSAkihiko Odaki         IGBVF_MMIO_SIZE);
2503a977deeSAkihiko Odaki     pcie_sriov_vf_register_bar(dev, IGBVF_MMIO_BAR_IDX, &s->mmio);
2513a977deeSAkihiko Odaki 
2523a977deeSAkihiko Odaki     memory_region_init(&s->msix, OBJECT(dev), "igbvf-msix", IGBVF_MSIX_SIZE);
2533a977deeSAkihiko Odaki     pcie_sriov_vf_register_bar(dev, IGBVF_MSIX_BAR_IDX, &s->msix);
2543a977deeSAkihiko Odaki 
2553a977deeSAkihiko Odaki     ret = msix_init(dev, IGBVF_MSIX_VEC_NUM, &s->msix, IGBVF_MSIX_BAR_IDX, 0,
2563a977deeSAkihiko Odaki         &s->msix, IGBVF_MSIX_BAR_IDX, 0x2000, 0x70, errp);
2573a977deeSAkihiko Odaki     if (ret) {
2583a977deeSAkihiko Odaki         return;
2593a977deeSAkihiko Odaki     }
2603a977deeSAkihiko Odaki 
2613a977deeSAkihiko Odaki     for (i = 0; i < IGBVF_MSIX_VEC_NUM; i++) {
2623a977deeSAkihiko Odaki         msix_vector_use(dev, i);
2633a977deeSAkihiko Odaki     }
2643a977deeSAkihiko Odaki 
2653a977deeSAkihiko Odaki     if (pcie_endpoint_cap_init(dev, 0xa0) < 0) {
2663a977deeSAkihiko Odaki         hw_error("Failed to initialize PCIe capability");
2673a977deeSAkihiko Odaki     }
2683a977deeSAkihiko Odaki 
2693a977deeSAkihiko Odaki     if (pcie_aer_init(dev, 1, 0x100, 0x40, errp) < 0) {
2703a977deeSAkihiko Odaki         hw_error("Failed to initialize AER capability");
2713a977deeSAkihiko Odaki     }
2723a977deeSAkihiko Odaki 
273*445416e3SAkihiko Odaki     pcie_ari_init(dev, 0x150);
2743a977deeSAkihiko Odaki }
2753a977deeSAkihiko Odaki 
2763a977deeSAkihiko Odaki static void igbvf_pci_uninit(PCIDevice *dev)
2773a977deeSAkihiko Odaki {
2783a977deeSAkihiko Odaki     IgbVfState *s = IGBVF(dev);
2793a977deeSAkihiko Odaki 
2803a977deeSAkihiko Odaki     pcie_aer_exit(dev);
2813a977deeSAkihiko Odaki     pcie_cap_exit(dev);
2823a977deeSAkihiko Odaki     msix_unuse_all_vectors(dev);
2833a977deeSAkihiko Odaki     msix_uninit(dev, &s->msix, &s->msix);
2843a977deeSAkihiko Odaki }
2853a977deeSAkihiko Odaki 
2863a977deeSAkihiko Odaki static void igbvf_class_init(ObjectClass *class, void *data)
2873a977deeSAkihiko Odaki {
2883a977deeSAkihiko Odaki     DeviceClass *dc = DEVICE_CLASS(class);
2893a977deeSAkihiko Odaki     PCIDeviceClass *c = PCI_DEVICE_CLASS(class);
2903a977deeSAkihiko Odaki 
2913a977deeSAkihiko Odaki     c->realize = igbvf_pci_realize;
2923a977deeSAkihiko Odaki     c->exit = igbvf_pci_uninit;
2933a977deeSAkihiko Odaki     c->vendor_id = PCI_VENDOR_ID_INTEL;
2943a977deeSAkihiko Odaki     c->device_id = E1000_DEV_ID_82576_VF;
2953a977deeSAkihiko Odaki     c->revision = 1;
2963a977deeSAkihiko Odaki     c->class_id = PCI_CLASS_NETWORK_ETHERNET;
2973a977deeSAkihiko Odaki 
2983a977deeSAkihiko Odaki     dc->desc = "Intel 82576 Virtual Function";
2993a977deeSAkihiko Odaki     dc->user_creatable = false;
3003a977deeSAkihiko Odaki 
3013a977deeSAkihiko Odaki     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
3023a977deeSAkihiko Odaki }
3033a977deeSAkihiko Odaki 
3043a977deeSAkihiko Odaki static const TypeInfo igbvf_info = {
3053a977deeSAkihiko Odaki     .name = TYPE_IGBVF,
3063a977deeSAkihiko Odaki     .parent = TYPE_PCI_DEVICE,
3073a977deeSAkihiko Odaki     .instance_size = sizeof(IgbVfState),
3083a977deeSAkihiko Odaki     .class_init = igbvf_class_init,
3093a977deeSAkihiko Odaki     .interfaces = (InterfaceInfo[]) {
3103a977deeSAkihiko Odaki         { INTERFACE_PCIE_DEVICE },
3113a977deeSAkihiko Odaki         { }
3123a977deeSAkihiko Odaki     },
3133a977deeSAkihiko Odaki };
3143a977deeSAkihiko Odaki 
3153a977deeSAkihiko Odaki static void igb_register_types(void)
3163a977deeSAkihiko Odaki {
3173a977deeSAkihiko Odaki     type_register_static(&igbvf_info);
3183a977deeSAkihiko Odaki }
3193a977deeSAkihiko Odaki 
3203a977deeSAkihiko Odaki type_init(igb_register_types)
321