1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Driver for FPGA Management Engine (FME) Partial Reconfiguration 4 * 5 * Copyright (C) 2017-2018 Intel Corporation, Inc. 6 * 7 * Authors: 8 * Kang Luwei <luwei.kang@intel.com> 9 * Xiao Guangrong <guangrong.xiao@linux.intel.com> 10 * Wu Hao <hao.wu@intel.com> 11 * Joseph Grecco <joe.grecco@intel.com> 12 * Enno Luebbers <enno.luebbers@intel.com> 13 * Tim Whisonant <tim.whisonant@intel.com> 14 * Ananda Ravuri <ananda.ravuri@intel.com> 15 * Christopher Rauer <christopher.rauer@intel.com> 16 * Henry Mitchel <henry.mitchel@intel.com> 17 */ 18 19 #include <linux/types.h> 20 #include <linux/device.h> 21 #include <linux/vmalloc.h> 22 #include <linux/uaccess.h> 23 #include <linux/fpga/fpga-mgr.h> 24 #include <linux/fpga/fpga-bridge.h> 25 #include <linux/fpga/fpga-region.h> 26 #include <linux/fpga-dfl.h> 27 28 #include "dfl.h" 29 #include "dfl-fme.h" 30 #include "dfl-fme-pr.h" 31 32 static struct dfl_fme_region * 33 dfl_fme_region_find_by_port_id(struct dfl_fme *fme, int port_id) 34 { 35 struct dfl_fme_region *fme_region; 36 37 list_for_each_entry(fme_region, &fme->region_list, node) 38 if (fme_region->port_id == port_id) 39 return fme_region; 40 41 return NULL; 42 } 43 44 static int dfl_fme_region_match(struct device *dev, const void *data) 45 { 46 return dev->parent == data; 47 } 48 49 static struct fpga_region *dfl_fme_region_find(struct dfl_fme *fme, int port_id) 50 { 51 struct dfl_fme_region *fme_region; 52 struct fpga_region *region; 53 54 fme_region = dfl_fme_region_find_by_port_id(fme, port_id); 55 if (!fme_region) 56 return NULL; 57 58 region = fpga_region_class_find(NULL, &fme_region->region->dev, 59 dfl_fme_region_match); 60 if (!region) 61 return NULL; 62 63 return region; 64 } 65 66 static int fme_pr(struct platform_device *pdev, unsigned long arg) 67 { 68 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 69 void __user *argp = (void __user *)arg; 70 struct dfl_fpga_fme_port_pr port_pr; 71 struct fpga_image_info *info; 72 struct fpga_region *region; 73 void __iomem *fme_hdr; 74 struct dfl_fme *fme; 75 unsigned long minsz; 76 void *buf = NULL; 77 int ret = 0; 78 u64 v; 79 80 minsz = offsetofend(struct dfl_fpga_fme_port_pr, buffer_address); 81 82 if (copy_from_user(&port_pr, argp, minsz)) 83 return -EFAULT; 84 85 if (port_pr.argsz < minsz || port_pr.flags) 86 return -EINVAL; 87 88 if (!IS_ALIGNED(port_pr.buffer_size, 4)) 89 return -EINVAL; 90 91 /* get fme header region */ 92 fme_hdr = dfl_get_feature_ioaddr_by_id(&pdev->dev, 93 FME_FEATURE_ID_HEADER); 94 95 /* check port id */ 96 v = readq(fme_hdr + FME_HDR_CAP); 97 if (port_pr.port_id >= FIELD_GET(FME_CAP_NUM_PORTS, v)) { 98 dev_dbg(&pdev->dev, "port number more than maximum\n"); 99 return -EINVAL; 100 } 101 102 if (!access_ok((void __user *)(unsigned long)port_pr.buffer_address, 103 port_pr.buffer_size)) 104 return -EFAULT; 105 106 buf = vmalloc(port_pr.buffer_size); 107 if (!buf) 108 return -ENOMEM; 109 110 if (copy_from_user(buf, 111 (void __user *)(unsigned long)port_pr.buffer_address, 112 port_pr.buffer_size)) { 113 ret = -EFAULT; 114 goto free_exit; 115 } 116 117 /* prepare fpga_image_info for PR */ 118 info = fpga_image_info_alloc(&pdev->dev); 119 if (!info) { 120 ret = -ENOMEM; 121 goto free_exit; 122 } 123 124 info->flags |= FPGA_MGR_PARTIAL_RECONFIG; 125 126 mutex_lock(&pdata->lock); 127 fme = dfl_fpga_pdata_get_private(pdata); 128 /* fme device has been unregistered. */ 129 if (!fme) { 130 ret = -EINVAL; 131 goto unlock_exit; 132 } 133 134 region = dfl_fme_region_find(fme, port_pr.port_id); 135 if (!region) { 136 ret = -EINVAL; 137 goto unlock_exit; 138 } 139 140 fpga_image_info_free(region->info); 141 142 info->buf = buf; 143 info->count = port_pr.buffer_size; 144 info->region_id = port_pr.port_id; 145 region->info = info; 146 147 ret = fpga_region_program_fpga(region); 148 149 /* 150 * it allows userspace to reset the PR region's logic by disabling and 151 * reenabling the bridge to clear things out between accleration runs. 152 * so no need to hold the bridges after partial reconfiguration. 153 */ 154 if (region->get_bridges) 155 fpga_bridges_put(®ion->bridge_list); 156 157 put_device(®ion->dev); 158 unlock_exit: 159 mutex_unlock(&pdata->lock); 160 free_exit: 161 vfree(buf); 162 if (copy_to_user((void __user *)arg, &port_pr, minsz)) 163 return -EFAULT; 164 165 return ret; 166 } 167 168 /** 169 * dfl_fme_create_mgr - create fpga mgr platform device as child device 170 * 171 * @pdata: fme platform_device's pdata 172 * 173 * Return: mgr platform device if successful, and error code otherwise. 174 */ 175 static struct platform_device * 176 dfl_fme_create_mgr(struct dfl_feature_platform_data *pdata, 177 struct dfl_feature *feature) 178 { 179 struct platform_device *mgr, *fme = pdata->dev; 180 struct dfl_fme_mgr_pdata mgr_pdata; 181 int ret = -ENOMEM; 182 183 if (!feature->ioaddr) 184 return ERR_PTR(-ENODEV); 185 186 mgr_pdata.ioaddr = feature->ioaddr; 187 188 /* 189 * Each FME has only one fpga-mgr, so allocate platform device using 190 * the same FME platform device id. 191 */ 192 mgr = platform_device_alloc(DFL_FPGA_FME_MGR, fme->id); 193 if (!mgr) 194 return ERR_PTR(ret); 195 196 mgr->dev.parent = &fme->dev; 197 198 ret = platform_device_add_data(mgr, &mgr_pdata, sizeof(mgr_pdata)); 199 if (ret) 200 goto create_mgr_err; 201 202 ret = platform_device_add(mgr); 203 if (ret) 204 goto create_mgr_err; 205 206 return mgr; 207 208 create_mgr_err: 209 platform_device_put(mgr); 210 return ERR_PTR(ret); 211 } 212 213 /** 214 * dfl_fme_destroy_mgr - destroy fpga mgr platform device 215 * @pdata: fme platform device's pdata 216 */ 217 static void dfl_fme_destroy_mgr(struct dfl_feature_platform_data *pdata) 218 { 219 struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata); 220 221 platform_device_unregister(priv->mgr); 222 } 223 224 /** 225 * dfl_fme_create_bridge - create fme fpga bridge platform device as child 226 * 227 * @pdata: fme platform device's pdata 228 * @port_id: port id for the bridge to be created. 229 * 230 * Return: bridge platform device if successful, and error code otherwise. 231 */ 232 static struct dfl_fme_bridge * 233 dfl_fme_create_bridge(struct dfl_feature_platform_data *pdata, int port_id) 234 { 235 struct device *dev = &pdata->dev->dev; 236 struct dfl_fme_br_pdata br_pdata; 237 struct dfl_fme_bridge *fme_br; 238 int ret = -ENOMEM; 239 240 fme_br = devm_kzalloc(dev, sizeof(*fme_br), GFP_KERNEL); 241 if (!fme_br) 242 return ERR_PTR(ret); 243 244 br_pdata.cdev = pdata->dfl_cdev; 245 br_pdata.port_id = port_id; 246 247 fme_br->br = platform_device_alloc(DFL_FPGA_FME_BRIDGE, 248 PLATFORM_DEVID_AUTO); 249 if (!fme_br->br) 250 return ERR_PTR(ret); 251 252 fme_br->br->dev.parent = dev; 253 254 ret = platform_device_add_data(fme_br->br, &br_pdata, sizeof(br_pdata)); 255 if (ret) 256 goto create_br_err; 257 258 ret = platform_device_add(fme_br->br); 259 if (ret) 260 goto create_br_err; 261 262 return fme_br; 263 264 create_br_err: 265 platform_device_put(fme_br->br); 266 return ERR_PTR(ret); 267 } 268 269 /** 270 * dfl_fme_destroy_bridge - destroy fpga bridge platform device 271 * @fme_br: fme bridge to destroy 272 */ 273 static void dfl_fme_destroy_bridge(struct dfl_fme_bridge *fme_br) 274 { 275 platform_device_unregister(fme_br->br); 276 } 277 278 /** 279 * dfl_fme_destroy_bridge - destroy all fpga bridge platform device 280 * @pdata: fme platform device's pdata 281 */ 282 static void dfl_fme_destroy_bridges(struct dfl_feature_platform_data *pdata) 283 { 284 struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata); 285 struct dfl_fme_bridge *fbridge, *tmp; 286 287 list_for_each_entry_safe(fbridge, tmp, &priv->bridge_list, node) { 288 list_del(&fbridge->node); 289 dfl_fme_destroy_bridge(fbridge); 290 } 291 } 292 293 /** 294 * dfl_fme_create_region - create fpga region platform device as child 295 * 296 * @pdata: fme platform device's pdata 297 * @mgr: mgr platform device needed for region 298 * @br: br platform device needed for region 299 * @port_id: port id 300 * 301 * Return: fme region if successful, and error code otherwise. 302 */ 303 static struct dfl_fme_region * 304 dfl_fme_create_region(struct dfl_feature_platform_data *pdata, 305 struct platform_device *mgr, 306 struct platform_device *br, int port_id) 307 { 308 struct dfl_fme_region_pdata region_pdata; 309 struct device *dev = &pdata->dev->dev; 310 struct dfl_fme_region *fme_region; 311 int ret = -ENOMEM; 312 313 fme_region = devm_kzalloc(dev, sizeof(*fme_region), GFP_KERNEL); 314 if (!fme_region) 315 return ERR_PTR(ret); 316 317 region_pdata.mgr = mgr; 318 region_pdata.br = br; 319 320 /* 321 * Each FPGA device may have more than one port, so allocate platform 322 * device using the same port platform device id. 323 */ 324 fme_region->region = platform_device_alloc(DFL_FPGA_FME_REGION, br->id); 325 if (!fme_region->region) 326 return ERR_PTR(ret); 327 328 fme_region->region->dev.parent = dev; 329 330 ret = platform_device_add_data(fme_region->region, ®ion_pdata, 331 sizeof(region_pdata)); 332 if (ret) 333 goto create_region_err; 334 335 ret = platform_device_add(fme_region->region); 336 if (ret) 337 goto create_region_err; 338 339 fme_region->port_id = port_id; 340 341 return fme_region; 342 343 create_region_err: 344 platform_device_put(fme_region->region); 345 return ERR_PTR(ret); 346 } 347 348 /** 349 * dfl_fme_destroy_region - destroy fme region 350 * @fme_region: fme region to destroy 351 */ 352 static void dfl_fme_destroy_region(struct dfl_fme_region *fme_region) 353 { 354 platform_device_unregister(fme_region->region); 355 } 356 357 /** 358 * dfl_fme_destroy_regions - destroy all fme regions 359 * @pdata: fme platform device's pdata 360 */ 361 static void dfl_fme_destroy_regions(struct dfl_feature_platform_data *pdata) 362 { 363 struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata); 364 struct dfl_fme_region *fme_region, *tmp; 365 366 list_for_each_entry_safe(fme_region, tmp, &priv->region_list, node) { 367 list_del(&fme_region->node); 368 dfl_fme_destroy_region(fme_region); 369 } 370 } 371 372 static int pr_mgmt_init(struct platform_device *pdev, 373 struct dfl_feature *feature) 374 { 375 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 376 struct dfl_fme_region *fme_region; 377 struct dfl_fme_bridge *fme_br; 378 struct platform_device *mgr; 379 struct dfl_fme *priv; 380 void __iomem *fme_hdr; 381 int ret = -ENODEV, i = 0; 382 u64 fme_cap, port_offset; 383 384 fme_hdr = dfl_get_feature_ioaddr_by_id(&pdev->dev, 385 FME_FEATURE_ID_HEADER); 386 387 mutex_lock(&pdata->lock); 388 priv = dfl_fpga_pdata_get_private(pdata); 389 390 /* Initialize the region and bridge sub device list */ 391 INIT_LIST_HEAD(&priv->region_list); 392 INIT_LIST_HEAD(&priv->bridge_list); 393 394 /* Create fpga mgr platform device */ 395 mgr = dfl_fme_create_mgr(pdata, feature); 396 if (IS_ERR(mgr)) { 397 dev_err(&pdev->dev, "fail to create fpga mgr pdev\n"); 398 goto unlock; 399 } 400 401 priv->mgr = mgr; 402 403 /* Read capability register to check number of regions and bridges */ 404 fme_cap = readq(fme_hdr + FME_HDR_CAP); 405 for (; i < FIELD_GET(FME_CAP_NUM_PORTS, fme_cap); i++) { 406 port_offset = readq(fme_hdr + FME_HDR_PORT_OFST(i)); 407 if (!(port_offset & FME_PORT_OFST_IMP)) 408 continue; 409 410 /* Create bridge for each port */ 411 fme_br = dfl_fme_create_bridge(pdata, i); 412 if (IS_ERR(fme_br)) { 413 ret = PTR_ERR(fme_br); 414 goto destroy_region; 415 } 416 417 list_add(&fme_br->node, &priv->bridge_list); 418 419 /* Create region for each port */ 420 fme_region = dfl_fme_create_region(pdata, mgr, 421 fme_br->br, i); 422 if (IS_ERR(fme_region)) { 423 ret = PTR_ERR(fme_region); 424 goto destroy_region; 425 } 426 427 list_add(&fme_region->node, &priv->region_list); 428 } 429 mutex_unlock(&pdata->lock); 430 431 return 0; 432 433 destroy_region: 434 dfl_fme_destroy_regions(pdata); 435 dfl_fme_destroy_bridges(pdata); 436 dfl_fme_destroy_mgr(pdata); 437 unlock: 438 mutex_unlock(&pdata->lock); 439 return ret; 440 } 441 442 static void pr_mgmt_uinit(struct platform_device *pdev, 443 struct dfl_feature *feature) 444 { 445 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); 446 447 mutex_lock(&pdata->lock); 448 449 dfl_fme_destroy_regions(pdata); 450 dfl_fme_destroy_bridges(pdata); 451 dfl_fme_destroy_mgr(pdata); 452 mutex_unlock(&pdata->lock); 453 } 454 455 static long fme_pr_ioctl(struct platform_device *pdev, 456 struct dfl_feature *feature, 457 unsigned int cmd, unsigned long arg) 458 { 459 long ret; 460 461 switch (cmd) { 462 case DFL_FPGA_FME_PORT_PR: 463 ret = fme_pr(pdev, arg); 464 break; 465 default: 466 ret = -ENODEV; 467 } 468 469 return ret; 470 } 471 472 const struct dfl_feature_ops pr_mgmt_ops = { 473 .init = pr_mgmt_init, 474 .uinit = pr_mgmt_uinit, 475 .ioctl = fme_pr_ioctl, 476 }; 477