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

Configure Feed

Select the types of activity you want to include in your feed.

pds_fwctl: initial driver framework

Initial files for adding a new fwctl driver for the AMD/Pensando PDS
devices. This sets up a simple auxiliary_bus driver that registers
with fwctl subsystem. It expects that a pds_core device has set up
the auxiliary_device pds_core.fwctl

Link: https://patch.msgid.link/r/20250320194412.67983-5-shannon.nelson@amd.com
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

authored by

Shannon Nelson and committed by
Jason Gunthorpe
4d09dd11 7e9dd0d1

+306
+7
MAINTAINERS
··· 9576 9576 S: Maintained 9577 9577 F: drivers/fwctl/mlx5/ 9578 9578 9579 + FWCTL PDS DRIVER 9580 + M: Brett Creeley <brett.creeley@amd.com> 9581 + R: Shannon Nelson <shannon.nelson@amd.com> 9582 + L: linux-kernel@vger.kernel.org 9583 + S: Maintained 9584 + F: drivers/fwctl/pds/ 9585 + 9579 9586 GALAXYCORE GC0308 CAMERA SENSOR DRIVER 9580 9587 M: Sebastian Reichel <sre@kernel.org> 9581 9588 L: linux-media@vger.kernel.org
+10
drivers/fwctl/Kconfig
··· 20 20 mainstream kernel. 21 21 22 22 If you don't know what to do here, say N. 23 + 24 + config FWCTL_PDS 25 + tristate "AMD/Pensando pds fwctl driver" 26 + depends on PDS_CORE 27 + help 28 + The pds_fwctl driver provides an fwctl interface for a user process 29 + to access the debug and configuration information of the AMD/Pensando 30 + DSC hardware family. 31 + 32 + If you don't know what to do here, say N. 23 33 endif
+1
drivers/fwctl/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 obj-$(CONFIG_FWCTL) += fwctl.o 3 3 obj-$(CONFIG_FWCTL_MLX5) += mlx5/ 4 + obj-$(CONFIG_FWCTL_PDS) += pds/ 4 5 5 6 fwctl-y += main.o
+4
drivers/fwctl/pds/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_FWCTL_PDS) += pds_fwctl.o 3 + 4 + pds_fwctl-y += main.o
+168
drivers/fwctl/pds/main.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright(c) Advanced Micro Devices, Inc */ 3 + 4 + #include <linux/module.h> 5 + #include <linux/auxiliary_bus.h> 6 + #include <linux/pci.h> 7 + #include <linux/vmalloc.h> 8 + 9 + #include <uapi/fwctl/fwctl.h> 10 + #include <uapi/fwctl/pds.h> 11 + #include <linux/fwctl.h> 12 + 13 + #include <linux/pds/pds_common.h> 14 + #include <linux/pds/pds_core_if.h> 15 + #include <linux/pds/pds_adminq.h> 16 + #include <linux/pds/pds_auxbus.h> 17 + 18 + struct pdsfc_uctx { 19 + struct fwctl_uctx uctx; 20 + u32 uctx_caps; 21 + }; 22 + 23 + struct pdsfc_dev { 24 + struct fwctl_device fwctl; 25 + struct pds_auxiliary_dev *padev; 26 + u32 caps; 27 + struct pds_fwctl_ident ident; 28 + }; 29 + 30 + static int pdsfc_open_uctx(struct fwctl_uctx *uctx) 31 + { 32 + struct pdsfc_dev *pdsfc = container_of(uctx->fwctl, struct pdsfc_dev, fwctl); 33 + struct pdsfc_uctx *pdsfc_uctx = container_of(uctx, struct pdsfc_uctx, uctx); 34 + 35 + pdsfc_uctx->uctx_caps = pdsfc->caps; 36 + 37 + return 0; 38 + } 39 + 40 + static void pdsfc_close_uctx(struct fwctl_uctx *uctx) 41 + { 42 + } 43 + 44 + static void *pdsfc_info(struct fwctl_uctx *uctx, size_t *length) 45 + { 46 + struct pdsfc_uctx *pdsfc_uctx = container_of(uctx, struct pdsfc_uctx, uctx); 47 + struct fwctl_info_pds *info; 48 + 49 + info = kzalloc(sizeof(*info), GFP_KERNEL); 50 + if (!info) 51 + return ERR_PTR(-ENOMEM); 52 + 53 + info->uctx_caps = pdsfc_uctx->uctx_caps; 54 + 55 + return info; 56 + } 57 + 58 + static int pdsfc_identify(struct pdsfc_dev *pdsfc) 59 + { 60 + struct device *dev = &pdsfc->fwctl.dev; 61 + union pds_core_adminq_comp comp = {0}; 62 + union pds_core_adminq_cmd cmd; 63 + struct pds_fwctl_ident *ident; 64 + dma_addr_t ident_pa; 65 + int err; 66 + 67 + ident = dma_alloc_coherent(dev->parent, sizeof(*ident), &ident_pa, GFP_KERNEL); 68 + if (!ident) { 69 + dev_err(dev, "Failed to map ident buffer\n"); 70 + return -ENOMEM; 71 + } 72 + 73 + cmd = (union pds_core_adminq_cmd) { 74 + .fwctl_ident = { 75 + .opcode = PDS_FWCTL_CMD_IDENT, 76 + .version = 0, 77 + .len = cpu_to_le32(sizeof(*ident)), 78 + .ident_pa = cpu_to_le64(ident_pa), 79 + } 80 + }; 81 + 82 + err = pds_client_adminq_cmd(pdsfc->padev, &cmd, sizeof(cmd), &comp, 0); 83 + if (err) 84 + dev_err(dev, "Failed to send adminq cmd opcode: %u err: %d\n", 85 + cmd.fwctl_ident.opcode, err); 86 + else 87 + pdsfc->ident = *ident; 88 + 89 + dma_free_coherent(dev->parent, sizeof(*ident), ident, ident_pa); 90 + 91 + return err; 92 + } 93 + 94 + static void *pdsfc_fw_rpc(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, 95 + void *in, size_t in_len, size_t *out_len) 96 + { 97 + return NULL; 98 + } 99 + 100 + static const struct fwctl_ops pdsfc_ops = { 101 + .device_type = FWCTL_DEVICE_TYPE_PDS, 102 + .uctx_size = sizeof(struct pdsfc_uctx), 103 + .open_uctx = pdsfc_open_uctx, 104 + .close_uctx = pdsfc_close_uctx, 105 + .info = pdsfc_info, 106 + .fw_rpc = pdsfc_fw_rpc, 107 + }; 108 + 109 + static int pdsfc_probe(struct auxiliary_device *adev, 110 + const struct auxiliary_device_id *id) 111 + { 112 + struct pds_auxiliary_dev *padev = 113 + container_of(adev, struct pds_auxiliary_dev, aux_dev); 114 + struct device *dev = &adev->dev; 115 + struct pdsfc_dev *pdsfc; 116 + int err; 117 + 118 + pdsfc = fwctl_alloc_device(&padev->vf_pdev->dev, &pdsfc_ops, 119 + struct pdsfc_dev, fwctl); 120 + if (!pdsfc) 121 + return dev_err_probe(dev, -ENOMEM, "Failed to allocate fwctl device struct\n"); 122 + pdsfc->padev = padev; 123 + 124 + err = pdsfc_identify(pdsfc); 125 + if (err) { 126 + fwctl_put(&pdsfc->fwctl); 127 + return dev_err_probe(dev, err, "Failed to identify device\n"); 128 + } 129 + 130 + err = fwctl_register(&pdsfc->fwctl); 131 + if (err) { 132 + fwctl_put(&pdsfc->fwctl); 133 + return dev_err_probe(dev, err, "Failed to register device\n"); 134 + } 135 + 136 + auxiliary_set_drvdata(adev, pdsfc); 137 + 138 + return 0; 139 + } 140 + 141 + static void pdsfc_remove(struct auxiliary_device *adev) 142 + { 143 + struct pdsfc_dev *pdsfc = auxiliary_get_drvdata(adev); 144 + 145 + fwctl_unregister(&pdsfc->fwctl); 146 + fwctl_put(&pdsfc->fwctl); 147 + } 148 + 149 + static const struct auxiliary_device_id pdsfc_id_table[] = { 150 + {.name = PDS_CORE_DRV_NAME "." PDS_DEV_TYPE_FWCTL_STR }, 151 + {} 152 + }; 153 + MODULE_DEVICE_TABLE(auxiliary, pdsfc_id_table); 154 + 155 + static struct auxiliary_driver pdsfc_driver = { 156 + .name = "pds_fwctl", 157 + .probe = pdsfc_probe, 158 + .remove = pdsfc_remove, 159 + .id_table = pdsfc_id_table, 160 + }; 161 + 162 + module_auxiliary_driver(pdsfc_driver); 163 + 164 + MODULE_IMPORT_NS("FWCTL"); 165 + MODULE_DESCRIPTION("pds fwctl driver"); 166 + MODULE_AUTHOR("Shannon Nelson <shannon.nelson@amd.com>"); 167 + MODULE_AUTHOR("Brett Creeley <brett.creeley@amd.com>"); 168 + MODULE_LICENSE("GPL");
+83
include/linux/pds/pds_adminq.h
··· 1179 1179 u8 status; 1180 1180 }; 1181 1181 1182 + enum pds_fwctl_cmd_opcode { 1183 + PDS_FWCTL_CMD_IDENT = 70, 1184 + }; 1185 + 1186 + /** 1187 + * struct pds_fwctl_cmd - Firmware control command structure 1188 + * @opcode: Opcode 1189 + * @rsvd: Reserved 1190 + * @ep: Endpoint identifier 1191 + * @op: Operation identifier 1192 + */ 1193 + struct pds_fwctl_cmd { 1194 + u8 opcode; 1195 + u8 rsvd[3]; 1196 + __le32 ep; 1197 + __le32 op; 1198 + } __packed; 1199 + 1200 + /** 1201 + * struct pds_fwctl_comp - Firmware control completion structure 1202 + * @status: Status of the firmware control operation 1203 + * @rsvd: Reserved 1204 + * @comp_index: Completion index in little-endian format 1205 + * @rsvd2: Reserved 1206 + * @color: Color bit indicating the state of the completion 1207 + */ 1208 + struct pds_fwctl_comp { 1209 + u8 status; 1210 + u8 rsvd; 1211 + __le16 comp_index; 1212 + u8 rsvd2[11]; 1213 + u8 color; 1214 + } __packed; 1215 + 1216 + /** 1217 + * struct pds_fwctl_ident_cmd - Firmware control identification command structure 1218 + * @opcode: Operation code for the command 1219 + * @rsvd: Reserved 1220 + * @version: Interface version 1221 + * @rsvd2: Reserved 1222 + * @len: Length of the identification data 1223 + * @ident_pa: Physical address of the identification data 1224 + */ 1225 + struct pds_fwctl_ident_cmd { 1226 + u8 opcode; 1227 + u8 rsvd; 1228 + u8 version; 1229 + u8 rsvd2; 1230 + __le32 len; 1231 + __le64 ident_pa; 1232 + } __packed; 1233 + 1234 + /* future feature bits here 1235 + * enum pds_fwctl_features { 1236 + * }; 1237 + * (compilers don't like empty enums) 1238 + */ 1239 + 1240 + /** 1241 + * struct pds_fwctl_ident - Firmware control identification structure 1242 + * @features: Supported features (enum pds_fwctl_features) 1243 + * @version: Interface version 1244 + * @rsvd: Reserved 1245 + * @max_req_sz: Maximum request size 1246 + * @max_resp_sz: Maximum response size 1247 + * @max_req_sg_elems: Maximum number of request SGs 1248 + * @max_resp_sg_elems: Maximum number of response SGs 1249 + */ 1250 + struct pds_fwctl_ident { 1251 + __le64 features; 1252 + u8 version; 1253 + u8 rsvd[3]; 1254 + __le32 max_req_sz; 1255 + __le32 max_resp_sz; 1256 + u8 max_req_sg_elems; 1257 + u8 max_resp_sg_elems; 1258 + } __packed; 1259 + 1182 1260 union pds_core_adminq_cmd { 1183 1261 u8 opcode; 1184 1262 u8 bytes[64]; ··· 1294 1216 struct pds_lm_dirty_enable_cmd lm_dirty_enable; 1295 1217 struct pds_lm_dirty_disable_cmd lm_dirty_disable; 1296 1218 struct pds_lm_dirty_seq_ack_cmd lm_dirty_seq_ack; 1219 + 1220 + struct pds_fwctl_cmd fwctl; 1221 + struct pds_fwctl_ident_cmd fwctl_ident; 1297 1222 }; 1298 1223 1299 1224 union pds_core_adminq_comp { ··· 1324 1243 1325 1244 struct pds_lm_state_size_comp lm_state_size; 1326 1245 struct pds_lm_dirty_status_comp lm_dirty_status; 1246 + 1247 + struct pds_fwctl_comp fwctl; 1327 1248 }; 1328 1249 1329 1250 #ifndef __CHECKER__
+1
include/uapi/fwctl/fwctl.h
··· 44 44 FWCTL_DEVICE_TYPE_ERROR = 0, 45 45 FWCTL_DEVICE_TYPE_MLX5 = 1, 46 46 FWCTL_DEVICE_TYPE_CXL = 2, 47 + FWCTL_DEVICE_TYPE_PDS = 4, 47 48 }; 48 49 49 50 /**
+32
include/uapi/fwctl/pds.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + /* Copyright(c) Advanced Micro Devices, Inc */ 3 + 4 + /* 5 + * fwctl interface info for pds_fwctl 6 + */ 7 + 8 + #ifndef _UAPI_FWCTL_PDS_H_ 9 + #define _UAPI_FWCTL_PDS_H_ 10 + 11 + #include <linux/types.h> 12 + 13 + /** 14 + * struct fwctl_info_pds 15 + * @uctx_caps: bitmap of firmware capabilities 16 + * 17 + * Return basic information about the FW interface available. 18 + */ 19 + struct fwctl_info_pds { 20 + __u32 uctx_caps; 21 + }; 22 + 23 + /** 24 + * enum pds_fwctl_capabilities 25 + * @PDS_FWCTL_QUERY_CAP: firmware can be queried for information 26 + * @PDS_FWCTL_SEND_CAP: firmware can be sent commands 27 + */ 28 + enum pds_fwctl_capabilities { 29 + PDS_FWCTL_QUERY_CAP = 0, 30 + PDS_FWCTL_SEND_CAP, 31 + }; 32 + #endif /* _UAPI_FWCTL_PDS_H_ */