0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/types.h>
0020 #include <linux/device.h>
0021 #include <linux/vmalloc.h>
0022 #include <linux/uaccess.h>
0023 #include <linux/fpga/fpga-mgr.h>
0024 #include <linux/fpga/fpga-bridge.h>
0025 #include <linux/fpga/fpga-region.h>
0026 #include <linux/fpga-dfl.h>
0027
0028 #include "dfl.h"
0029 #include "dfl-fme.h"
0030 #include "dfl-fme-pr.h"
0031
0032 static struct dfl_fme_region *
0033 dfl_fme_region_find_by_port_id(struct dfl_fme *fme, int port_id)
0034 {
0035 struct dfl_fme_region *fme_region;
0036
0037 list_for_each_entry(fme_region, &fme->region_list, node)
0038 if (fme_region->port_id == port_id)
0039 return fme_region;
0040
0041 return NULL;
0042 }
0043
0044 static int dfl_fme_region_match(struct device *dev, const void *data)
0045 {
0046 return dev->parent == data;
0047 }
0048
0049 static struct fpga_region *dfl_fme_region_find(struct dfl_fme *fme, int port_id)
0050 {
0051 struct dfl_fme_region *fme_region;
0052 struct fpga_region *region;
0053
0054 fme_region = dfl_fme_region_find_by_port_id(fme, port_id);
0055 if (!fme_region)
0056 return NULL;
0057
0058 region = fpga_region_class_find(NULL, &fme_region->region->dev,
0059 dfl_fme_region_match);
0060 if (!region)
0061 return NULL;
0062
0063 return region;
0064 }
0065
0066 static int fme_pr(struct platform_device *pdev, unsigned long arg)
0067 {
0068 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
0069 void __user *argp = (void __user *)arg;
0070 struct dfl_fpga_fme_port_pr port_pr;
0071 struct fpga_image_info *info;
0072 struct fpga_region *region;
0073 void __iomem *fme_hdr;
0074 struct dfl_fme *fme;
0075 unsigned long minsz;
0076 void *buf = NULL;
0077 size_t length;
0078 int ret = 0;
0079 u64 v;
0080
0081 minsz = offsetofend(struct dfl_fpga_fme_port_pr, buffer_address);
0082
0083 if (copy_from_user(&port_pr, argp, minsz))
0084 return -EFAULT;
0085
0086 if (port_pr.argsz < minsz || port_pr.flags)
0087 return -EINVAL;
0088
0089
0090 fme_hdr = dfl_get_feature_ioaddr_by_id(&pdev->dev,
0091 FME_FEATURE_ID_HEADER);
0092
0093
0094 v = readq(fme_hdr + FME_HDR_CAP);
0095 if (port_pr.port_id >= FIELD_GET(FME_CAP_NUM_PORTS, v)) {
0096 dev_dbg(&pdev->dev, "port number more than maximum\n");
0097 return -EINVAL;
0098 }
0099
0100
0101
0102
0103
0104 length = ALIGN(port_pr.buffer_size, 4);
0105
0106 buf = vmalloc(length);
0107 if (!buf)
0108 return -ENOMEM;
0109
0110 if (copy_from_user(buf,
0111 (void __user *)(unsigned long)port_pr.buffer_address,
0112 port_pr.buffer_size)) {
0113 ret = -EFAULT;
0114 goto free_exit;
0115 }
0116
0117
0118 info = fpga_image_info_alloc(&pdev->dev);
0119 if (!info) {
0120 ret = -ENOMEM;
0121 goto free_exit;
0122 }
0123
0124 info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
0125
0126 mutex_lock(&pdata->lock);
0127 fme = dfl_fpga_pdata_get_private(pdata);
0128
0129 if (!fme) {
0130 ret = -EINVAL;
0131 goto unlock_exit;
0132 }
0133
0134 region = dfl_fme_region_find(fme, port_pr.port_id);
0135 if (!region) {
0136 ret = -EINVAL;
0137 goto unlock_exit;
0138 }
0139
0140 fpga_image_info_free(region->info);
0141
0142 info->buf = buf;
0143 info->count = length;
0144 info->region_id = port_pr.port_id;
0145 region->info = info;
0146
0147 ret = fpga_region_program_fpga(region);
0148
0149
0150
0151
0152
0153
0154 if (region->get_bridges)
0155 fpga_bridges_put(®ion->bridge_list);
0156
0157 put_device(®ion->dev);
0158 unlock_exit:
0159 mutex_unlock(&pdata->lock);
0160 free_exit:
0161 vfree(buf);
0162 return ret;
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172 static struct platform_device *
0173 dfl_fme_create_mgr(struct dfl_feature_platform_data *pdata,
0174 struct dfl_feature *feature)
0175 {
0176 struct platform_device *mgr, *fme = pdata->dev;
0177 struct dfl_fme_mgr_pdata mgr_pdata;
0178 int ret = -ENOMEM;
0179
0180 if (!feature->ioaddr)
0181 return ERR_PTR(-ENODEV);
0182
0183 mgr_pdata.ioaddr = feature->ioaddr;
0184
0185
0186
0187
0188
0189 mgr = platform_device_alloc(DFL_FPGA_FME_MGR, fme->id);
0190 if (!mgr)
0191 return ERR_PTR(ret);
0192
0193 mgr->dev.parent = &fme->dev;
0194
0195 ret = platform_device_add_data(mgr, &mgr_pdata, sizeof(mgr_pdata));
0196 if (ret)
0197 goto create_mgr_err;
0198
0199 ret = platform_device_add(mgr);
0200 if (ret)
0201 goto create_mgr_err;
0202
0203 return mgr;
0204
0205 create_mgr_err:
0206 platform_device_put(mgr);
0207 return ERR_PTR(ret);
0208 }
0209
0210
0211
0212
0213
0214 static void dfl_fme_destroy_mgr(struct dfl_feature_platform_data *pdata)
0215 {
0216 struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata);
0217
0218 platform_device_unregister(priv->mgr);
0219 }
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 static struct dfl_fme_bridge *
0230 dfl_fme_create_bridge(struct dfl_feature_platform_data *pdata, int port_id)
0231 {
0232 struct device *dev = &pdata->dev->dev;
0233 struct dfl_fme_br_pdata br_pdata;
0234 struct dfl_fme_bridge *fme_br;
0235 int ret = -ENOMEM;
0236
0237 fme_br = devm_kzalloc(dev, sizeof(*fme_br), GFP_KERNEL);
0238 if (!fme_br)
0239 return ERR_PTR(ret);
0240
0241 br_pdata.cdev = pdata->dfl_cdev;
0242 br_pdata.port_id = port_id;
0243
0244 fme_br->br = platform_device_alloc(DFL_FPGA_FME_BRIDGE,
0245 PLATFORM_DEVID_AUTO);
0246 if (!fme_br->br)
0247 return ERR_PTR(ret);
0248
0249 fme_br->br->dev.parent = dev;
0250
0251 ret = platform_device_add_data(fme_br->br, &br_pdata, sizeof(br_pdata));
0252 if (ret)
0253 goto create_br_err;
0254
0255 ret = platform_device_add(fme_br->br);
0256 if (ret)
0257 goto create_br_err;
0258
0259 return fme_br;
0260
0261 create_br_err:
0262 platform_device_put(fme_br->br);
0263 return ERR_PTR(ret);
0264 }
0265
0266
0267
0268
0269
0270 static void dfl_fme_destroy_bridge(struct dfl_fme_bridge *fme_br)
0271 {
0272 platform_device_unregister(fme_br->br);
0273 }
0274
0275
0276
0277
0278
0279 static void dfl_fme_destroy_bridges(struct dfl_feature_platform_data *pdata)
0280 {
0281 struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata);
0282 struct dfl_fme_bridge *fbridge, *tmp;
0283
0284 list_for_each_entry_safe(fbridge, tmp, &priv->bridge_list, node) {
0285 list_del(&fbridge->node);
0286 dfl_fme_destroy_bridge(fbridge);
0287 }
0288 }
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 static struct dfl_fme_region *
0301 dfl_fme_create_region(struct dfl_feature_platform_data *pdata,
0302 struct platform_device *mgr,
0303 struct platform_device *br, int port_id)
0304 {
0305 struct dfl_fme_region_pdata region_pdata;
0306 struct device *dev = &pdata->dev->dev;
0307 struct dfl_fme_region *fme_region;
0308 int ret = -ENOMEM;
0309
0310 fme_region = devm_kzalloc(dev, sizeof(*fme_region), GFP_KERNEL);
0311 if (!fme_region)
0312 return ERR_PTR(ret);
0313
0314 region_pdata.mgr = mgr;
0315 region_pdata.br = br;
0316
0317
0318
0319
0320
0321 fme_region->region = platform_device_alloc(DFL_FPGA_FME_REGION, br->id);
0322 if (!fme_region->region)
0323 return ERR_PTR(ret);
0324
0325 fme_region->region->dev.parent = dev;
0326
0327 ret = platform_device_add_data(fme_region->region, ®ion_pdata,
0328 sizeof(region_pdata));
0329 if (ret)
0330 goto create_region_err;
0331
0332 ret = platform_device_add(fme_region->region);
0333 if (ret)
0334 goto create_region_err;
0335
0336 fme_region->port_id = port_id;
0337
0338 return fme_region;
0339
0340 create_region_err:
0341 platform_device_put(fme_region->region);
0342 return ERR_PTR(ret);
0343 }
0344
0345
0346
0347
0348
0349 static void dfl_fme_destroy_region(struct dfl_fme_region *fme_region)
0350 {
0351 platform_device_unregister(fme_region->region);
0352 }
0353
0354
0355
0356
0357
0358 static void dfl_fme_destroy_regions(struct dfl_feature_platform_data *pdata)
0359 {
0360 struct dfl_fme *priv = dfl_fpga_pdata_get_private(pdata);
0361 struct dfl_fme_region *fme_region, *tmp;
0362
0363 list_for_each_entry_safe(fme_region, tmp, &priv->region_list, node) {
0364 list_del(&fme_region->node);
0365 dfl_fme_destroy_region(fme_region);
0366 }
0367 }
0368
0369 static int pr_mgmt_init(struct platform_device *pdev,
0370 struct dfl_feature *feature)
0371 {
0372 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
0373 struct dfl_fme_region *fme_region;
0374 struct dfl_fme_bridge *fme_br;
0375 struct platform_device *mgr;
0376 struct dfl_fme *priv;
0377 void __iomem *fme_hdr;
0378 int ret = -ENODEV, i = 0;
0379 u64 fme_cap, port_offset;
0380
0381 fme_hdr = dfl_get_feature_ioaddr_by_id(&pdev->dev,
0382 FME_FEATURE_ID_HEADER);
0383
0384 mutex_lock(&pdata->lock);
0385 priv = dfl_fpga_pdata_get_private(pdata);
0386
0387
0388 INIT_LIST_HEAD(&priv->region_list);
0389 INIT_LIST_HEAD(&priv->bridge_list);
0390
0391
0392 mgr = dfl_fme_create_mgr(pdata, feature);
0393 if (IS_ERR(mgr)) {
0394 dev_err(&pdev->dev, "fail to create fpga mgr pdev\n");
0395 goto unlock;
0396 }
0397
0398 priv->mgr = mgr;
0399
0400
0401 fme_cap = readq(fme_hdr + FME_HDR_CAP);
0402 for (; i < FIELD_GET(FME_CAP_NUM_PORTS, fme_cap); i++) {
0403 port_offset = readq(fme_hdr + FME_HDR_PORT_OFST(i));
0404 if (!(port_offset & FME_PORT_OFST_IMP))
0405 continue;
0406
0407
0408 fme_br = dfl_fme_create_bridge(pdata, i);
0409 if (IS_ERR(fme_br)) {
0410 ret = PTR_ERR(fme_br);
0411 goto destroy_region;
0412 }
0413
0414 list_add(&fme_br->node, &priv->bridge_list);
0415
0416
0417 fme_region = dfl_fme_create_region(pdata, mgr,
0418 fme_br->br, i);
0419 if (IS_ERR(fme_region)) {
0420 ret = PTR_ERR(fme_region);
0421 goto destroy_region;
0422 }
0423
0424 list_add(&fme_region->node, &priv->region_list);
0425 }
0426 mutex_unlock(&pdata->lock);
0427
0428 return 0;
0429
0430 destroy_region:
0431 dfl_fme_destroy_regions(pdata);
0432 dfl_fme_destroy_bridges(pdata);
0433 dfl_fme_destroy_mgr(pdata);
0434 unlock:
0435 mutex_unlock(&pdata->lock);
0436 return ret;
0437 }
0438
0439 static void pr_mgmt_uinit(struct platform_device *pdev,
0440 struct dfl_feature *feature)
0441 {
0442 struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
0443
0444 mutex_lock(&pdata->lock);
0445
0446 dfl_fme_destroy_regions(pdata);
0447 dfl_fme_destroy_bridges(pdata);
0448 dfl_fme_destroy_mgr(pdata);
0449 mutex_unlock(&pdata->lock);
0450 }
0451
0452 static long fme_pr_ioctl(struct platform_device *pdev,
0453 struct dfl_feature *feature,
0454 unsigned int cmd, unsigned long arg)
0455 {
0456 long ret;
0457
0458 switch (cmd) {
0459 case DFL_FPGA_FME_PORT_PR:
0460 ret = fme_pr(pdev, arg);
0461 break;
0462 default:
0463 ret = -ENODEV;
0464 }
0465
0466 return ret;
0467 }
0468
0469 const struct dfl_feature_id fme_pr_mgmt_id_table[] = {
0470 {.id = FME_FEATURE_ID_PR_MGMT,},
0471 {0}
0472 };
0473
0474 const struct dfl_feature_ops fme_pr_mgmt_ops = {
0475 .init = pr_mgmt_init,
0476 .uinit = pr_mgmt_uinit,
0477 .ioctl = fme_pr_ioctl,
0478 };