1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 4 #include <asm/unaligned.h> 5 #include <linux/pci.h> 6 #include <linux/types.h> 7 #include <net/devlink.h> 8 9 #include "fbnic.h" 10 11 #define FBNIC_SN_STR_LEN 24 12 13 static int fbnic_devlink_info_get(struct devlink *devlink, 14 struct devlink_info_req *req, 15 struct netlink_ext_ack *extack) 16 { 17 struct fbnic_dev *fbd = devlink_priv(devlink); 18 int err; 19 20 if (fbd->dsn) { 21 unsigned char serial[FBNIC_SN_STR_LEN]; 22 u8 dsn[8]; 23 24 put_unaligned_be64(fbd->dsn, dsn); 25 err = snprintf(serial, FBNIC_SN_STR_LEN, "%8phD", dsn); 26 if (err < 0) 27 return err; 28 29 err = devlink_info_serial_number_put(req, serial); 30 if (err) 31 return err; 32 } 33 34 return 0; 35 } 36 37 static const struct devlink_ops fbnic_devlink_ops = { 38 .info_get = fbnic_devlink_info_get, 39 }; 40 41 void fbnic_devlink_free(struct fbnic_dev *fbd) 42 { 43 struct devlink *devlink = priv_to_devlink(fbd); 44 45 devlink_free(devlink); 46 } 47 48 struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev) 49 { 50 void __iomem * const *iomap_table; 51 struct devlink *devlink; 52 struct fbnic_dev *fbd; 53 54 devlink = devlink_alloc(&fbnic_devlink_ops, sizeof(struct fbnic_dev), 55 &pdev->dev); 56 if (!devlink) 57 return NULL; 58 59 fbd = devlink_priv(devlink); 60 pci_set_drvdata(pdev, fbd); 61 fbd->dev = &pdev->dev; 62 63 iomap_table = pcim_iomap_table(pdev); 64 fbd->uc_addr0 = iomap_table[0]; 65 fbd->uc_addr4 = iomap_table[4]; 66 67 fbd->dsn = pci_get_dsn(pdev); 68 fbd->mps = pcie_get_mps(pdev); 69 fbd->readrq = pcie_get_readrq(pdev); 70 71 fbd->mac_addr_boundary = FBNIC_RPC_TCAM_MACDA_DEFAULT_BOUNDARY; 72 73 return fbd; 74 } 75 76 void fbnic_devlink_register(struct fbnic_dev *fbd) 77 { 78 struct devlink *devlink = priv_to_devlink(fbd); 79 80 devlink_register(devlink); 81 } 82 83 void fbnic_devlink_unregister(struct fbnic_dev *fbd) 84 { 85 struct devlink *devlink = priv_to_devlink(fbd); 86 87 devlink_unregister(devlink); 88 } 89