Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pds_core: initial framework for pds_core PF driver

This is the initial PCI driver framework for the new pds_core device
driver and its family of devices. This does the very basics of
registering for the new PF PCI device 1dd8:100c, setting up debugfs
entries, and registering with devlink.

Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Shannon Nelson and committed by
David S. Miller
55435ea7 25c800b2

+993
+35
Documentation/networking/device_drivers/ethernet/amd/pds_core.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + ======================================================== 4 + Linux Driver for the AMD/Pensando(R) DSC adapter family 5 + ======================================================== 6 + 7 + Copyright(c) 2023 Advanced Micro Devices, Inc 8 + 9 + Identifying the Adapter 10 + ======================= 11 + 12 + To find if one or more AMD/Pensando PCI Core devices are installed on the 13 + host, check for the PCI devices:: 14 + 15 + # lspci -d 1dd8:100c 16 + b5:00.0 Processing accelerators: Pensando Systems Device 100c 17 + b6:00.0 Processing accelerators: Pensando Systems Device 100c 18 + 19 + If such devices are listed as above, then the pds_core.ko driver should find 20 + and configure them for use. There should be log entries in the kernel 21 + messages such as these:: 22 + 23 + $ dmesg | grep pds_core 24 + pds_core 0000:b5:00.0: 252.048 Gb/s available PCIe bandwidth (16.0 GT/s PCIe x16 link) 25 + pds_core 0000:b5:00.0: FW: 1.60.0-73 26 + pds_core 0000:b6:00.0: 252.048 Gb/s available PCIe bandwidth (16.0 GT/s PCIe x16 link) 27 + pds_core 0000:b6:00.0: FW: 1.60.0-73 28 + 29 + Support 30 + ======= 31 + 32 + For general Linux networking support, please use the netdev mailing 33 + list, which is monitored by AMD/Pensando personnel:: 34 + 35 + netdev@vger.kernel.org
+1
Documentation/networking/device_drivers/ethernet/index.rst
··· 14 14 3com/vortex 15 15 amazon/ena 16 16 altera/altera_tse 17 + amd/pds_core 17 18 aquantia/atlantic 18 19 chelsio/cxgb 19 20 cirrus/cs89x0
+8
drivers/net/ethernet/amd/pds_core/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright (c) 2023 Advanced Micro Devices, Inc. 3 + 4 + obj-$(CONFIG_PDS_CORE) := pds_core.o 5 + 6 + pds_core-y := main.o 7 + 8 + pds_core-$(CONFIG_DEBUG_FS) += debugfs.o
+56
drivers/net/ethernet/amd/pds_core/core.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright(c) 2023 Advanced Micro Devices, Inc */ 3 + 4 + #ifndef _PDSC_H_ 5 + #define _PDSC_H_ 6 + 7 + #include <linux/debugfs.h> 8 + #include <net/devlink.h> 9 + 10 + #include <linux/pds/pds_common.h> 11 + #include <linux/pds/pds_core_if.h> 12 + 13 + #define PDSC_DRV_DESCRIPTION "AMD/Pensando Core Driver" 14 + 15 + struct pdsc_dev_bar { 16 + void __iomem *vaddr; 17 + phys_addr_t bus_addr; 18 + unsigned long len; 19 + int res_index; 20 + }; 21 + 22 + /* No state flags set means we are in a steady running state */ 23 + enum pdsc_state_flags { 24 + PDSC_S_FW_DEAD, /* stopped, wait on startup or recovery */ 25 + PDSC_S_INITING_DRIVER, /* initial startup from probe */ 26 + PDSC_S_STOPPING_DRIVER, /* driver remove */ 27 + 28 + /* leave this as last */ 29 + PDSC_S_STATE_SIZE 30 + }; 31 + 32 + struct pdsc { 33 + struct pci_dev *pdev; 34 + struct dentry *dentry; 35 + struct device *dev; 36 + struct pdsc_dev_bar bars[PDS_CORE_BARS_MAX]; 37 + int hw_index; 38 + int uid; 39 + 40 + unsigned long state; 41 + 42 + struct pds_core_dev_info_regs __iomem *info_regs; 43 + struct pds_core_dev_cmd_regs __iomem *cmd_regs; 44 + struct pds_core_intr __iomem *intr_ctrl; 45 + u64 __iomem *intr_status; 46 + u64 __iomem *db_pages; 47 + dma_addr_t phy_db_pages; 48 + u64 __iomem *kern_dbpage; 49 + }; 50 + 51 + void pdsc_debugfs_create(void); 52 + void pdsc_debugfs_destroy(void); 53 + void pdsc_debugfs_add_dev(struct pdsc *pdsc); 54 + void pdsc_debugfs_del_dev(struct pdsc *pdsc); 55 + 56 + #endif /* _PDSC_H_ */
+31
drivers/net/ethernet/amd/pds_core/debugfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2023 Advanced Micro Devices, Inc */ 3 + 4 + #include <linux/pci.h> 5 + 6 + #include "core.h" 7 + 8 + static struct dentry *pdsc_dir; 9 + 10 + void pdsc_debugfs_create(void) 11 + { 12 + pdsc_dir = debugfs_create_dir(PDS_CORE_DRV_NAME, NULL); 13 + } 14 + 15 + void pdsc_debugfs_destroy(void) 16 + { 17 + debugfs_remove_recursive(pdsc_dir); 18 + } 19 + 20 + void pdsc_debugfs_add_dev(struct pdsc *pdsc) 21 + { 22 + pdsc->dentry = debugfs_create_dir(pci_name(pdsc->pdev), pdsc_dir); 23 + 24 + debugfs_create_ulong("state", 0400, pdsc->dentry, &pdsc->state); 25 + } 26 + 27 + void pdsc_debugfs_del_dev(struct pdsc *pdsc) 28 + { 29 + debugfs_remove_recursive(pdsc->dentry); 30 + pdsc->dentry = NULL; 31 + }
+277
drivers/net/ethernet/amd/pds_core/main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) 2023 Advanced Micro Devices, Inc */ 3 + 4 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 5 + 6 + #include <linux/pci.h> 7 + 8 + #include <linux/pds/pds_common.h> 9 + 10 + #include "core.h" 11 + 12 + MODULE_DESCRIPTION(PDSC_DRV_DESCRIPTION); 13 + MODULE_AUTHOR("Advanced Micro Devices, Inc"); 14 + MODULE_LICENSE("GPL"); 15 + 16 + /* Supported devices */ 17 + static const struct pci_device_id pdsc_id_table[] = { 18 + { PCI_VDEVICE(PENSANDO, PCI_DEVICE_ID_PENSANDO_CORE_PF) }, 19 + { 0, } /* end of table */ 20 + }; 21 + MODULE_DEVICE_TABLE(pci, pdsc_id_table); 22 + 23 + static void pdsc_unmap_bars(struct pdsc *pdsc) 24 + { 25 + struct pdsc_dev_bar *bars = pdsc->bars; 26 + unsigned int i; 27 + 28 + for (i = 0; i < PDS_CORE_BARS_MAX; i++) { 29 + if (bars[i].vaddr) 30 + pci_iounmap(pdsc->pdev, bars[i].vaddr); 31 + } 32 + } 33 + 34 + static int pdsc_map_bars(struct pdsc *pdsc) 35 + { 36 + struct pdsc_dev_bar *bar = pdsc->bars; 37 + struct pci_dev *pdev = pdsc->pdev; 38 + struct device *dev = pdsc->dev; 39 + struct pdsc_dev_bar *bars; 40 + unsigned int i, j; 41 + int num_bars = 0; 42 + int err; 43 + u32 sig; 44 + 45 + bars = pdsc->bars; 46 + 47 + /* Since the PCI interface in the hardware is configurable, 48 + * we need to poke into all the bars to find the set we're 49 + * expecting. 50 + */ 51 + for (i = 0, j = 0; i < PDS_CORE_BARS_MAX; i++) { 52 + if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM)) 53 + continue; 54 + 55 + bars[j].len = pci_resource_len(pdev, i); 56 + bars[j].bus_addr = pci_resource_start(pdev, i); 57 + bars[j].res_index = i; 58 + 59 + /* only map the whole bar 0 */ 60 + if (j > 0) { 61 + bars[j].vaddr = NULL; 62 + } else { 63 + bars[j].vaddr = pci_iomap(pdev, i, bars[j].len); 64 + if (!bars[j].vaddr) { 65 + dev_err(dev, "Cannot map BAR %d, aborting\n", i); 66 + return -ENODEV; 67 + } 68 + } 69 + 70 + j++; 71 + } 72 + num_bars = j; 73 + 74 + /* BAR0: dev_cmd and interrupts */ 75 + if (num_bars < 1) { 76 + dev_err(dev, "No bars found\n"); 77 + err = -EFAULT; 78 + goto err_out; 79 + } 80 + 81 + if (bar->len < PDS_CORE_BAR0_SIZE) { 82 + dev_err(dev, "Resource bar size %lu too small\n", bar->len); 83 + err = -EFAULT; 84 + goto err_out; 85 + } 86 + 87 + pdsc->info_regs = bar->vaddr + PDS_CORE_BAR0_DEV_INFO_REGS_OFFSET; 88 + pdsc->cmd_regs = bar->vaddr + PDS_CORE_BAR0_DEV_CMD_REGS_OFFSET; 89 + pdsc->intr_status = bar->vaddr + PDS_CORE_BAR0_INTR_STATUS_OFFSET; 90 + pdsc->intr_ctrl = bar->vaddr + PDS_CORE_BAR0_INTR_CTRL_OFFSET; 91 + 92 + sig = ioread32(&pdsc->info_regs->signature); 93 + if (sig != PDS_CORE_DEV_INFO_SIGNATURE) { 94 + dev_err(dev, "Incompatible firmware signature %x", sig); 95 + err = -EFAULT; 96 + goto err_out; 97 + } 98 + 99 + /* BAR1: doorbells */ 100 + bar++; 101 + if (num_bars < 2) { 102 + dev_err(dev, "Doorbell bar missing\n"); 103 + err = -EFAULT; 104 + goto err_out; 105 + } 106 + 107 + pdsc->db_pages = bar->vaddr; 108 + pdsc->phy_db_pages = bar->bus_addr; 109 + 110 + return 0; 111 + 112 + err_out: 113 + pdsc_unmap_bars(pdsc); 114 + return err; 115 + } 116 + 117 + static int pdsc_init_vf(struct pdsc *vf) 118 + { 119 + return -1; 120 + } 121 + 122 + static int pdsc_init_pf(struct pdsc *pdsc) 123 + { 124 + struct devlink *dl; 125 + int err; 126 + 127 + pcie_print_link_status(pdsc->pdev); 128 + 129 + err = pci_request_regions(pdsc->pdev, PDS_CORE_DRV_NAME); 130 + if (err) { 131 + dev_err(pdsc->dev, "Cannot request PCI regions: %pe\n", 132 + ERR_PTR(err)); 133 + return err; 134 + } 135 + 136 + err = pdsc_map_bars(pdsc); 137 + if (err) 138 + goto err_out_release_regions; 139 + 140 + dl = priv_to_devlink(pdsc); 141 + devl_lock(dl); 142 + devl_register(dl); 143 + devl_unlock(dl); 144 + 145 + return 0; 146 + 147 + err_out_release_regions: 148 + pci_release_regions(pdsc->pdev); 149 + 150 + return err; 151 + } 152 + 153 + static const struct devlink_ops pdsc_dl_ops = { 154 + }; 155 + 156 + static const struct devlink_ops pdsc_dl_vf_ops = { 157 + }; 158 + 159 + static DEFINE_IDA(pdsc_ida); 160 + 161 + static int pdsc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 162 + { 163 + struct device *dev = &pdev->dev; 164 + const struct devlink_ops *ops; 165 + struct devlink *dl; 166 + struct pdsc *pdsc; 167 + bool is_pf; 168 + int err; 169 + 170 + is_pf = !pdev->is_virtfn; 171 + ops = is_pf ? &pdsc_dl_ops : &pdsc_dl_vf_ops; 172 + dl = devlink_alloc(ops, sizeof(struct pdsc), dev); 173 + if (!dl) 174 + return -ENOMEM; 175 + pdsc = devlink_priv(dl); 176 + 177 + pdsc->pdev = pdev; 178 + pdsc->dev = &pdev->dev; 179 + set_bit(PDSC_S_INITING_DRIVER, &pdsc->state); 180 + pci_set_drvdata(pdev, pdsc); 181 + pdsc_debugfs_add_dev(pdsc); 182 + 183 + err = ida_alloc(&pdsc_ida, GFP_KERNEL); 184 + if (err < 0) { 185 + dev_err(pdsc->dev, "%s: id alloc failed: %pe\n", 186 + __func__, ERR_PTR(err)); 187 + goto err_out_free_devlink; 188 + } 189 + pdsc->uid = err; 190 + 191 + /* Query system for DMA addressing limitation for the device. */ 192 + err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(PDS_CORE_ADDR_LEN)); 193 + if (err) { 194 + dev_err(dev, "Unable to obtain 64-bit DMA for consistent allocations, aborting: %pe\n", 195 + ERR_PTR(err)); 196 + goto err_out_free_ida; 197 + } 198 + 199 + err = pci_enable_device(pdev); 200 + if (err) { 201 + dev_err(dev, "Cannot enable PCI device: %pe\n", ERR_PTR(err)); 202 + goto err_out_free_ida; 203 + } 204 + pci_set_master(pdev); 205 + 206 + if (is_pf) 207 + err = pdsc_init_pf(pdsc); 208 + else 209 + err = pdsc_init_vf(pdsc); 210 + if (err) { 211 + dev_err(dev, "Cannot init device: %pe\n", ERR_PTR(err)); 212 + goto err_out_clear_master; 213 + } 214 + 215 + clear_bit(PDSC_S_INITING_DRIVER, &pdsc->state); 216 + return 0; 217 + 218 + err_out_clear_master: 219 + pci_clear_master(pdev); 220 + pci_disable_device(pdev); 221 + err_out_free_ida: 222 + ida_free(&pdsc_ida, pdsc->uid); 223 + err_out_free_devlink: 224 + pdsc_debugfs_del_dev(pdsc); 225 + devlink_free(dl); 226 + 227 + return err; 228 + } 229 + 230 + static void pdsc_remove(struct pci_dev *pdev) 231 + { 232 + struct pdsc *pdsc = pci_get_drvdata(pdev); 233 + struct devlink *dl; 234 + 235 + /* Unhook the registrations first to be sure there 236 + * are no requests while we're stopping. 237 + */ 238 + dl = priv_to_devlink(pdsc); 239 + devl_lock(dl); 240 + devl_unregister(dl); 241 + devl_unlock(dl); 242 + 243 + pdsc_unmap_bars(pdsc); 244 + pci_release_regions(pdev); 245 + 246 + pci_clear_master(pdev); 247 + pci_disable_device(pdev); 248 + 249 + ida_free(&pdsc_ida, pdsc->uid); 250 + pdsc_debugfs_del_dev(pdsc); 251 + devlink_free(dl); 252 + } 253 + 254 + static struct pci_driver pdsc_driver = { 255 + .name = PDS_CORE_DRV_NAME, 256 + .id_table = pdsc_id_table, 257 + .probe = pdsc_probe, 258 + .remove = pdsc_remove, 259 + }; 260 + 261 + static int __init pdsc_init_module(void) 262 + { 263 + if (strcmp(KBUILD_MODNAME, PDS_CORE_DRV_NAME)) 264 + return -EINVAL; 265 + 266 + pdsc_debugfs_create(); 267 + return pci_register_driver(&pdsc_driver); 268 + } 269 + 270 + static void __exit pdsc_cleanup_module(void) 271 + { 272 + pci_unregister_driver(&pdsc_driver); 273 + pdsc_debugfs_destroy(); 274 + } 275 + 276 + module_init(pdsc_init_module); 277 + module_exit(pdsc_cleanup_module);
+14
include/linux/pds/pds_common.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) OR BSD-2-Clause */ 2 + /* Copyright(c) 2023 Advanced Micro Devices, Inc. */ 3 + 4 + #ifndef _PDS_COMMON_H_ 5 + #define _PDS_COMMON_H_ 6 + 7 + #define PDS_CORE_DRV_NAME "pds_core" 8 + 9 + /* the device's internal addressing uses up to 52 bits */ 10 + #define PDS_CORE_ADDR_LEN 52 11 + #define PDS_CORE_ADDR_MASK (BIT_ULL(PDS_ADDR_LEN) - 1) 12 + #define PDS_PAGE_SIZE 4096 13 + 14 + #endif /* _PDS_COMMON_H_ */
+571
include/linux/pds/pds_core_if.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) OR BSD-2-Clause */ 2 + /* Copyright(c) 2023 Advanced Micro Devices, Inc. */ 3 + 4 + #ifndef _PDS_CORE_IF_H_ 5 + #define _PDS_CORE_IF_H_ 6 + 7 + #define PCI_VENDOR_ID_PENSANDO 0x1dd8 8 + #define PCI_DEVICE_ID_PENSANDO_CORE_PF 0x100c 9 + #define PCI_DEVICE_ID_VIRTIO_NET_TRANS 0x1000 10 + #define PCI_DEVICE_ID_PENSANDO_IONIC_ETH_VF 0x1003 11 + #define PCI_DEVICE_ID_PENSANDO_VDPA_VF 0x100b 12 + #define PDS_CORE_BARS_MAX 4 13 + #define PDS_CORE_PCI_BAR_DBELL 1 14 + 15 + /* Bar0 */ 16 + #define PDS_CORE_DEV_INFO_SIGNATURE 0x44455649 /* 'DEVI' */ 17 + #define PDS_CORE_BAR0_SIZE 0x8000 18 + #define PDS_CORE_BAR0_DEV_INFO_REGS_OFFSET 0x0000 19 + #define PDS_CORE_BAR0_DEV_CMD_REGS_OFFSET 0x0800 20 + #define PDS_CORE_BAR0_DEV_CMD_DATA_REGS_OFFSET 0x0c00 21 + #define PDS_CORE_BAR0_INTR_STATUS_OFFSET 0x1000 22 + #define PDS_CORE_BAR0_INTR_CTRL_OFFSET 0x2000 23 + #define PDS_CORE_DEV_CMD_DONE 0x00000001 24 + 25 + #define PDS_CORE_DEVCMD_TIMEOUT 5 26 + 27 + #define PDS_CORE_CLIENT_ID 0 28 + #define PDS_CORE_ASIC_TYPE_CAPRI 0 29 + 30 + /* 31 + * enum pds_core_cmd_opcode - Device commands 32 + */ 33 + enum pds_core_cmd_opcode { 34 + /* Core init */ 35 + PDS_CORE_CMD_NOP = 0, 36 + PDS_CORE_CMD_IDENTIFY = 1, 37 + PDS_CORE_CMD_RESET = 2, 38 + PDS_CORE_CMD_INIT = 3, 39 + 40 + PDS_CORE_CMD_FW_DOWNLOAD = 4, 41 + PDS_CORE_CMD_FW_CONTROL = 5, 42 + 43 + /* SR/IOV commands */ 44 + PDS_CORE_CMD_VF_GETATTR = 60, 45 + PDS_CORE_CMD_VF_SETATTR = 61, 46 + PDS_CORE_CMD_VF_CTRL = 62, 47 + 48 + /* Add commands before this line */ 49 + PDS_CORE_CMD_MAX, 50 + PDS_CORE_CMD_COUNT 51 + }; 52 + 53 + /* 54 + * enum pds_core_status_code - Device command return codes 55 + */ 56 + enum pds_core_status_code { 57 + PDS_RC_SUCCESS = 0, /* Success */ 58 + PDS_RC_EVERSION = 1, /* Incorrect version for request */ 59 + PDS_RC_EOPCODE = 2, /* Invalid cmd opcode */ 60 + PDS_RC_EIO = 3, /* I/O error */ 61 + PDS_RC_EPERM = 4, /* Permission denied */ 62 + PDS_RC_EQID = 5, /* Bad qid */ 63 + PDS_RC_EQTYPE = 6, /* Bad qtype */ 64 + PDS_RC_ENOENT = 7, /* No such element */ 65 + PDS_RC_EINTR = 8, /* operation interrupted */ 66 + PDS_RC_EAGAIN = 9, /* Try again */ 67 + PDS_RC_ENOMEM = 10, /* Out of memory */ 68 + PDS_RC_EFAULT = 11, /* Bad address */ 69 + PDS_RC_EBUSY = 12, /* Device or resource busy */ 70 + PDS_RC_EEXIST = 13, /* object already exists */ 71 + PDS_RC_EINVAL = 14, /* Invalid argument */ 72 + PDS_RC_ENOSPC = 15, /* No space left or alloc failure */ 73 + PDS_RC_ERANGE = 16, /* Parameter out of range */ 74 + PDS_RC_BAD_ADDR = 17, /* Descriptor contains a bad ptr */ 75 + PDS_RC_DEV_CMD = 18, /* Device cmd attempted on AdminQ */ 76 + PDS_RC_ENOSUPP = 19, /* Operation not supported */ 77 + PDS_RC_ERROR = 29, /* Generic error */ 78 + PDS_RC_ERDMA = 30, /* Generic RDMA error */ 79 + PDS_RC_EVFID = 31, /* VF ID does not exist */ 80 + PDS_RC_BAD_FW = 32, /* FW file is invalid or corrupted */ 81 + PDS_RC_ECLIENT = 33, /* No such client id */ 82 + }; 83 + 84 + /** 85 + * struct pds_core_drv_identity - Driver identity information 86 + * @drv_type: Driver type (enum pds_core_driver_type) 87 + * @os_dist: OS distribution, numeric format 88 + * @os_dist_str: OS distribution, string format 89 + * @kernel_ver: Kernel version, numeric format 90 + * @kernel_ver_str: Kernel version, string format 91 + * @driver_ver_str: Driver version, string format 92 + */ 93 + struct pds_core_drv_identity { 94 + __le32 drv_type; 95 + __le32 os_dist; 96 + char os_dist_str[128]; 97 + __le32 kernel_ver; 98 + char kernel_ver_str[32]; 99 + char driver_ver_str[32]; 100 + }; 101 + 102 + #define PDS_DEV_TYPE_MAX 16 103 + /** 104 + * struct pds_core_dev_identity - Device identity information 105 + * @version: Version of device identify 106 + * @type: Identify type (0 for now) 107 + * @state: Device state 108 + * @rsvd: Word boundary padding 109 + * @nlifs: Number of LIFs provisioned 110 + * @nintrs: Number of interrupts provisioned 111 + * @ndbpgs_per_lif: Number of doorbell pages per LIF 112 + * @intr_coal_mult: Interrupt coalescing multiplication factor 113 + * Scale user-supplied interrupt coalescing 114 + * value in usecs to device units using: 115 + * device units = usecs * mult / div 116 + * @intr_coal_div: Interrupt coalescing division factor 117 + * Scale user-supplied interrupt coalescing 118 + * value in usecs to device units using: 119 + * device units = usecs * mult / div 120 + * @vif_types: How many of each VIF device type is supported 121 + */ 122 + struct pds_core_dev_identity { 123 + u8 version; 124 + u8 type; 125 + u8 state; 126 + u8 rsvd; 127 + __le32 nlifs; 128 + __le32 nintrs; 129 + __le32 ndbpgs_per_lif; 130 + __le32 intr_coal_mult; 131 + __le32 intr_coal_div; 132 + __le16 vif_types[PDS_DEV_TYPE_MAX]; 133 + }; 134 + 135 + #define PDS_CORE_IDENTITY_VERSION_1 1 136 + 137 + /** 138 + * struct pds_core_dev_identify_cmd - Driver/device identify command 139 + * @opcode: Opcode PDS_CORE_CMD_IDENTIFY 140 + * @ver: Highest version of identify supported by driver 141 + * 142 + * Expects to find driver identification info (struct pds_core_drv_identity) 143 + * in cmd_regs->data. Driver should keep the devcmd interface locked 144 + * while preparing the driver info. 145 + */ 146 + struct pds_core_dev_identify_cmd { 147 + u8 opcode; 148 + u8 ver; 149 + }; 150 + 151 + /** 152 + * struct pds_core_dev_identify_comp - Device identify command completion 153 + * @status: Status of the command (enum pds_core_status_code) 154 + * @ver: Version of identify returned by device 155 + * 156 + * Device identification info (struct pds_core_dev_identity) can be found 157 + * in cmd_regs->data. Driver should keep the devcmd interface locked 158 + * while reading the results. 159 + */ 160 + struct pds_core_dev_identify_comp { 161 + u8 status; 162 + u8 ver; 163 + }; 164 + 165 + /** 166 + * struct pds_core_dev_reset_cmd - Device reset command 167 + * @opcode: Opcode PDS_CORE_CMD_RESET 168 + * 169 + * Resets and clears all LIFs, VDevs, and VIFs on the device. 170 + */ 171 + struct pds_core_dev_reset_cmd { 172 + u8 opcode; 173 + }; 174 + 175 + /** 176 + * struct pds_core_dev_reset_comp - Reset command completion 177 + * @status: Status of the command (enum pds_core_status_code) 178 + */ 179 + struct pds_core_dev_reset_comp { 180 + u8 status; 181 + }; 182 + 183 + /* 184 + * struct pds_core_dev_init_data - Pointers and info needed for the Core 185 + * initialization PDS_CORE_CMD_INIT command. The in and out structs are 186 + * overlays on the pds_core_dev_cmd_regs.data space for passing data down 187 + * to the firmware on init, and then returning initialization results. 188 + */ 189 + struct pds_core_dev_init_data_in { 190 + __le64 adminq_q_base; 191 + __le64 adminq_cq_base; 192 + __le64 notifyq_cq_base; 193 + __le32 flags; 194 + __le16 intr_index; 195 + u8 adminq_ring_size; 196 + u8 notifyq_ring_size; 197 + }; 198 + 199 + struct pds_core_dev_init_data_out { 200 + __le32 core_hw_index; 201 + __le32 adminq_hw_index; 202 + __le32 notifyq_hw_index; 203 + u8 adminq_hw_type; 204 + u8 notifyq_hw_type; 205 + }; 206 + 207 + /** 208 + * struct pds_core_dev_init_cmd - Core device initialize 209 + * @opcode: opcode PDS_CORE_CMD_INIT 210 + * 211 + * Initializes the core device and sets up the AdminQ and NotifyQ. 212 + * Expects to find initialization data (struct pds_core_dev_init_data_in) 213 + * in cmd_regs->data. Driver should keep the devcmd interface locked 214 + * while preparing the driver info. 215 + */ 216 + struct pds_core_dev_init_cmd { 217 + u8 opcode; 218 + }; 219 + 220 + /** 221 + * struct pds_core_dev_init_comp - Core init completion 222 + * @status: Status of the command (enum pds_core_status_code) 223 + * 224 + * Initialization result data (struct pds_core_dev_init_data_in) 225 + * is found in cmd_regs->data. 226 + */ 227 + struct pds_core_dev_init_comp { 228 + u8 status; 229 + }; 230 + 231 + /** 232 + * struct pds_core_fw_download_cmd - Firmware download command 233 + * @opcode: opcode 234 + * @rsvd: Word boundary padding 235 + * @addr: DMA address of the firmware buffer 236 + * @offset: offset of the firmware buffer within the full image 237 + * @length: number of valid bytes in the firmware buffer 238 + */ 239 + struct pds_core_fw_download_cmd { 240 + u8 opcode; 241 + u8 rsvd[3]; 242 + __le32 offset; 243 + __le64 addr; 244 + __le32 length; 245 + }; 246 + 247 + /** 248 + * struct pds_core_fw_download_comp - Firmware download completion 249 + * @status: Status of the command (enum pds_core_status_code) 250 + */ 251 + struct pds_core_fw_download_comp { 252 + u8 status; 253 + }; 254 + 255 + /** 256 + * enum pds_core_fw_control_oper - FW control operations 257 + * @PDS_CORE_FW_INSTALL_ASYNC: Install firmware asynchronously 258 + * @PDS_CORE_FW_INSTALL_STATUS: Firmware installation status 259 + * @PDS_CORE_FW_ACTIVATE_ASYNC: Activate firmware asynchronously 260 + * @PDS_CORE_FW_ACTIVATE_STATUS: Firmware activate status 261 + * @PDS_CORE_FW_UPDATE_CLEANUP: Cleanup any firmware update leftovers 262 + * @PDS_CORE_FW_GET_BOOT: Return current active firmware slot 263 + * @PDS_CORE_FW_SET_BOOT: Set active firmware slot for next boot 264 + * @PDS_CORE_FW_GET_LIST: Return list of installed firmware images 265 + */ 266 + enum pds_core_fw_control_oper { 267 + PDS_CORE_FW_INSTALL_ASYNC = 0, 268 + PDS_CORE_FW_INSTALL_STATUS = 1, 269 + PDS_CORE_FW_ACTIVATE_ASYNC = 2, 270 + PDS_CORE_FW_ACTIVATE_STATUS = 3, 271 + PDS_CORE_FW_UPDATE_CLEANUP = 4, 272 + PDS_CORE_FW_GET_BOOT = 5, 273 + PDS_CORE_FW_SET_BOOT = 6, 274 + PDS_CORE_FW_GET_LIST = 7, 275 + }; 276 + 277 + enum pds_core_fw_slot { 278 + PDS_CORE_FW_SLOT_INVALID = 0, 279 + PDS_CORE_FW_SLOT_A = 1, 280 + PDS_CORE_FW_SLOT_B = 2, 281 + PDS_CORE_FW_SLOT_GOLD = 3, 282 + }; 283 + 284 + /** 285 + * struct pds_core_fw_control_cmd - Firmware control command 286 + * @opcode: opcode 287 + * @rsvd: Word boundary padding 288 + * @oper: firmware control operation (enum pds_core_fw_control_oper) 289 + * @slot: slot to operate on (enum pds_core_fw_slot) 290 + */ 291 + struct pds_core_fw_control_cmd { 292 + u8 opcode; 293 + u8 rsvd[3]; 294 + u8 oper; 295 + u8 slot; 296 + }; 297 + 298 + /** 299 + * struct pds_core_fw_control_comp - Firmware control copletion 300 + * @status: Status of the command (enum pds_core_status_code) 301 + * @rsvd: Word alignment space 302 + * @slot: Slot number (enum pds_core_fw_slot) 303 + * @rsvd1: Struct padding 304 + * @color: Color bit 305 + */ 306 + struct pds_core_fw_control_comp { 307 + u8 status; 308 + u8 rsvd[3]; 309 + u8 slot; 310 + u8 rsvd1[10]; 311 + u8 color; 312 + }; 313 + 314 + struct pds_core_fw_name_info { 315 + #define PDS_CORE_FWSLOT_BUFLEN 8 316 + #define PDS_CORE_FWVERS_BUFLEN 32 317 + char slotname[PDS_CORE_FWSLOT_BUFLEN]; 318 + char fw_version[PDS_CORE_FWVERS_BUFLEN]; 319 + }; 320 + 321 + struct pds_core_fw_list_info { 322 + #define PDS_CORE_FWVERS_LIST_LEN 16 323 + u8 num_fw_slots; 324 + struct pds_core_fw_name_info fw_names[PDS_CORE_FWVERS_LIST_LEN]; 325 + } __packed; 326 + 327 + enum pds_core_vf_attr { 328 + PDS_CORE_VF_ATTR_SPOOFCHK = 1, 329 + PDS_CORE_VF_ATTR_TRUST = 2, 330 + PDS_CORE_VF_ATTR_MAC = 3, 331 + PDS_CORE_VF_ATTR_LINKSTATE = 4, 332 + PDS_CORE_VF_ATTR_VLAN = 5, 333 + PDS_CORE_VF_ATTR_RATE = 6, 334 + PDS_CORE_VF_ATTR_STATSADDR = 7, 335 + }; 336 + 337 + /** 338 + * enum pds_core_vf_link_status - Virtual Function link status 339 + * @PDS_CORE_VF_LINK_STATUS_AUTO: Use link state of the uplink 340 + * @PDS_CORE_VF_LINK_STATUS_UP: Link always up 341 + * @PDS_CORE_VF_LINK_STATUS_DOWN: Link always down 342 + */ 343 + enum pds_core_vf_link_status { 344 + PDS_CORE_VF_LINK_STATUS_AUTO = 0, 345 + PDS_CORE_VF_LINK_STATUS_UP = 1, 346 + PDS_CORE_VF_LINK_STATUS_DOWN = 2, 347 + }; 348 + 349 + /** 350 + * struct pds_core_vf_setattr_cmd - Set VF attributes on the NIC 351 + * @opcode: Opcode 352 + * @attr: Attribute type (enum pds_core_vf_attr) 353 + * @vf_index: VF index 354 + * @macaddr: mac address 355 + * @vlanid: vlan ID 356 + * @maxrate: max Tx rate in Mbps 357 + * @spoofchk: enable address spoof checking 358 + * @trust: enable VF trust 359 + * @linkstate: set link up or down 360 + * @stats: stats addr struct 361 + * @stats.pa: set DMA address for VF stats 362 + * @stats.len: length of VF stats space 363 + * @pad: force union to specific size 364 + */ 365 + struct pds_core_vf_setattr_cmd { 366 + u8 opcode; 367 + u8 attr; 368 + __le16 vf_index; 369 + union { 370 + u8 macaddr[6]; 371 + __le16 vlanid; 372 + __le32 maxrate; 373 + u8 spoofchk; 374 + u8 trust; 375 + u8 linkstate; 376 + struct { 377 + __le64 pa; 378 + __le32 len; 379 + } stats; 380 + u8 pad[60]; 381 + } __packed; 382 + }; 383 + 384 + struct pds_core_vf_setattr_comp { 385 + u8 status; 386 + u8 attr; 387 + __le16 vf_index; 388 + __le16 comp_index; 389 + u8 rsvd[9]; 390 + u8 color; 391 + }; 392 + 393 + /** 394 + * struct pds_core_vf_getattr_cmd - Get VF attributes from the NIC 395 + * @opcode: Opcode 396 + * @attr: Attribute type (enum pds_core_vf_attr) 397 + * @vf_index: VF index 398 + */ 399 + struct pds_core_vf_getattr_cmd { 400 + u8 opcode; 401 + u8 attr; 402 + __le16 vf_index; 403 + }; 404 + 405 + struct pds_core_vf_getattr_comp { 406 + u8 status; 407 + u8 attr; 408 + __le16 vf_index; 409 + union { 410 + u8 macaddr[6]; 411 + __le16 vlanid; 412 + __le32 maxrate; 413 + u8 spoofchk; 414 + u8 trust; 415 + u8 linkstate; 416 + __le64 stats_pa; 417 + u8 pad[11]; 418 + } __packed; 419 + u8 color; 420 + }; 421 + 422 + enum pds_core_vf_ctrl_opcode { 423 + PDS_CORE_VF_CTRL_START_ALL = 0, 424 + PDS_CORE_VF_CTRL_START = 1, 425 + }; 426 + 427 + /** 428 + * struct pds_core_vf_ctrl_cmd - VF control command 429 + * @opcode: Opcode for the command 430 + * @ctrl_opcode: VF control operation type 431 + * @vf_index: VF Index. It is unused if op START_ALL is used. 432 + */ 433 + 434 + struct pds_core_vf_ctrl_cmd { 435 + u8 opcode; 436 + u8 ctrl_opcode; 437 + __le16 vf_index; 438 + }; 439 + 440 + /** 441 + * struct pds_core_vf_ctrl_comp - VF_CTRL command completion. 442 + * @status: Status of the command (enum pds_core_status_code) 443 + */ 444 + struct pds_core_vf_ctrl_comp { 445 + u8 status; 446 + }; 447 + 448 + /* 449 + * union pds_core_dev_cmd - Overlay of core device command structures 450 + */ 451 + union pds_core_dev_cmd { 452 + u8 opcode; 453 + u32 words[16]; 454 + 455 + struct pds_core_dev_identify_cmd identify; 456 + struct pds_core_dev_init_cmd init; 457 + struct pds_core_dev_reset_cmd reset; 458 + struct pds_core_fw_download_cmd fw_download; 459 + struct pds_core_fw_control_cmd fw_control; 460 + 461 + struct pds_core_vf_setattr_cmd vf_setattr; 462 + struct pds_core_vf_getattr_cmd vf_getattr; 463 + struct pds_core_vf_ctrl_cmd vf_ctrl; 464 + }; 465 + 466 + /* 467 + * union pds_core_dev_comp - Overlay of core device completion structures 468 + */ 469 + union pds_core_dev_comp { 470 + u8 status; 471 + u8 bytes[16]; 472 + 473 + struct pds_core_dev_identify_comp identify; 474 + struct pds_core_dev_reset_comp reset; 475 + struct pds_core_dev_init_comp init; 476 + struct pds_core_fw_download_comp fw_download; 477 + struct pds_core_fw_control_comp fw_control; 478 + 479 + struct pds_core_vf_setattr_comp vf_setattr; 480 + struct pds_core_vf_getattr_comp vf_getattr; 481 + struct pds_core_vf_ctrl_comp vf_ctrl; 482 + }; 483 + 484 + /** 485 + * struct pds_core_dev_hwstamp_regs - Hardware current timestamp registers 486 + * @tick_low: Low 32 bits of hardware timestamp 487 + * @tick_high: High 32 bits of hardware timestamp 488 + */ 489 + struct pds_core_dev_hwstamp_regs { 490 + u32 tick_low; 491 + u32 tick_high; 492 + }; 493 + 494 + /** 495 + * struct pds_core_dev_info_regs - Device info register format (read-only) 496 + * @signature: Signature value of 0x44455649 ('DEVI') 497 + * @version: Current version of info 498 + * @asic_type: Asic type 499 + * @asic_rev: Asic revision 500 + * @fw_status: Firmware status 501 + * bit 0 - 1 = fw running 502 + * bit 4-7 - 4 bit generation number, changes on fw restart 503 + * @fw_heartbeat: Firmware heartbeat counter 504 + * @serial_num: Serial number 505 + * @fw_version: Firmware version 506 + * @oprom_regs: oprom_regs to store oprom debug enable/disable and bmp 507 + * @rsvd_pad1024: Struct padding 508 + * @hwstamp: Hardware current timestamp registers 509 + * @rsvd_pad2048: Struct padding 510 + */ 511 + struct pds_core_dev_info_regs { 512 + #define PDS_CORE_DEVINFO_FWVERS_BUFLEN 32 513 + #define PDS_CORE_DEVINFO_SERIAL_BUFLEN 32 514 + u32 signature; 515 + u8 version; 516 + u8 asic_type; 517 + u8 asic_rev; 518 + #define PDS_CORE_FW_STS_F_STOPPED 0x00 519 + #define PDS_CORE_FW_STS_F_RUNNING 0x01 520 + #define PDS_CORE_FW_STS_F_GENERATION 0xF0 521 + u8 fw_status; 522 + __le32 fw_heartbeat; 523 + char fw_version[PDS_CORE_DEVINFO_FWVERS_BUFLEN]; 524 + char serial_num[PDS_CORE_DEVINFO_SERIAL_BUFLEN]; 525 + u8 oprom_regs[32]; /* reserved */ 526 + u8 rsvd_pad1024[916]; 527 + struct pds_core_dev_hwstamp_regs hwstamp; /* on 1k boundary */ 528 + u8 rsvd_pad2048[1016]; 529 + } __packed; 530 + 531 + /** 532 + * struct pds_core_dev_cmd_regs - Device command register format (read-write) 533 + * @doorbell: Device Cmd Doorbell, write-only 534 + * Write a 1 to signal device to process cmd 535 + * @done: Command completed indicator, poll for completion 536 + * bit 0 == 1 when command is complete 537 + * @cmd: Opcode-specific command bytes 538 + * @comp: Opcode-specific response bytes 539 + * @rsvd: Struct padding 540 + * @data: Opcode-specific side-data 541 + */ 542 + struct pds_core_dev_cmd_regs { 543 + u32 doorbell; 544 + u32 done; 545 + union pds_core_dev_cmd cmd; 546 + union pds_core_dev_comp comp; 547 + u8 rsvd[48]; 548 + u32 data[478]; 549 + } __packed; 550 + 551 + /** 552 + * struct pds_core_dev_regs - Device register format for bar 0 page 0 553 + * @info: Device info registers 554 + * @devcmd: Device command registers 555 + */ 556 + struct pds_core_dev_regs { 557 + struct pds_core_dev_info_regs info; 558 + struct pds_core_dev_cmd_regs devcmd; 559 + } __packed; 560 + 561 + #ifndef __CHECKER__ 562 + static_assert(sizeof(struct pds_core_drv_identity) <= 1912); 563 + static_assert(sizeof(struct pds_core_dev_identity) <= 1912); 564 + static_assert(sizeof(union pds_core_dev_cmd) == 64); 565 + static_assert(sizeof(union pds_core_dev_comp) == 16); 566 + static_assert(sizeof(struct pds_core_dev_info_regs) == 2048); 567 + static_assert(sizeof(struct pds_core_dev_cmd_regs) == 2048); 568 + static_assert(sizeof(struct pds_core_dev_regs) == 4096); 569 + #endif /* __CHECKER__ */ 570 + 571 + #endif /* _PDS_CORE_IF_H_ */