root/drivers/fpga/dfl-fme-main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ports_num_show
  2. bitstream_id_show
  3. bitstream_metadata_show
  4. cache_size_show
  5. fabric_version_show
  6. socket_id_show
  7. fme_hdr_ioctl_release_port
  8. fme_hdr_ioctl_assign_port
  9. fme_hdr_ioctl
  10. fme_ioctl_check_extension
  11. fme_open
  12. fme_release
  13. fme_ioctl
  14. fme_dev_init
  15. fme_dev_destroy
  16. fme_probe
  17. fme_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Driver for FPGA Management Engine (FME)
   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  *   Joseph Grecco <joe.grecco@intel.com>
  11  *   Enno Luebbers <enno.luebbers@intel.com>
  12  *   Tim Whisonant <tim.whisonant@intel.com>
  13  *   Ananda Ravuri <ananda.ravuri@intel.com>
  14  *   Henry Mitchel <henry.mitchel@intel.com>
  15  */
  16 
  17 #include <linux/kernel.h>
  18 #include <linux/module.h>
  19 #include <linux/uaccess.h>
  20 #include <linux/fpga-dfl.h>
  21 
  22 #include "dfl.h"
  23 #include "dfl-fme.h"
  24 
  25 static ssize_t ports_num_show(struct device *dev,
  26                               struct device_attribute *attr, char *buf)
  27 {
  28         void __iomem *base;
  29         u64 v;
  30 
  31         base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
  32 
  33         v = readq(base + FME_HDR_CAP);
  34 
  35         return scnprintf(buf, PAGE_SIZE, "%u\n",
  36                          (unsigned int)FIELD_GET(FME_CAP_NUM_PORTS, v));
  37 }
  38 static DEVICE_ATTR_RO(ports_num);
  39 
  40 /*
  41  * Bitstream (static FPGA region) identifier number. It contains the
  42  * detailed version and other information of this static FPGA region.
  43  */
  44 static ssize_t bitstream_id_show(struct device *dev,
  45                                  struct device_attribute *attr, char *buf)
  46 {
  47         void __iomem *base;
  48         u64 v;
  49 
  50         base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
  51 
  52         v = readq(base + FME_HDR_BITSTREAM_ID);
  53 
  54         return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
  55 }
  56 static DEVICE_ATTR_RO(bitstream_id);
  57 
  58 /*
  59  * Bitstream (static FPGA region) meta data. It contains the synthesis
  60  * date, seed and other information of this static FPGA region.
  61  */
  62 static ssize_t bitstream_metadata_show(struct device *dev,
  63                                        struct device_attribute *attr, char *buf)
  64 {
  65         void __iomem *base;
  66         u64 v;
  67 
  68         base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
  69 
  70         v = readq(base + FME_HDR_BITSTREAM_MD);
  71 
  72         return scnprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)v);
  73 }
  74 static DEVICE_ATTR_RO(bitstream_metadata);
  75 
  76 static ssize_t cache_size_show(struct device *dev,
  77                                struct device_attribute *attr, char *buf)
  78 {
  79         void __iomem *base;
  80         u64 v;
  81 
  82         base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
  83 
  84         v = readq(base + FME_HDR_CAP);
  85 
  86         return sprintf(buf, "%u\n",
  87                        (unsigned int)FIELD_GET(FME_CAP_CACHE_SIZE, v));
  88 }
  89 static DEVICE_ATTR_RO(cache_size);
  90 
  91 static ssize_t fabric_version_show(struct device *dev,
  92                                    struct device_attribute *attr, char *buf)
  93 {
  94         void __iomem *base;
  95         u64 v;
  96 
  97         base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
  98 
  99         v = readq(base + FME_HDR_CAP);
 100 
 101         return sprintf(buf, "%u\n",
 102                        (unsigned int)FIELD_GET(FME_CAP_FABRIC_VERID, v));
 103 }
 104 static DEVICE_ATTR_RO(fabric_version);
 105 
 106 static ssize_t socket_id_show(struct device *dev,
 107                               struct device_attribute *attr, char *buf)
 108 {
 109         void __iomem *base;
 110         u64 v;
 111 
 112         base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
 113 
 114         v = readq(base + FME_HDR_CAP);
 115 
 116         return sprintf(buf, "%u\n",
 117                        (unsigned int)FIELD_GET(FME_CAP_SOCKET_ID, v));
 118 }
 119 static DEVICE_ATTR_RO(socket_id);
 120 
 121 static struct attribute *fme_hdr_attrs[] = {
 122         &dev_attr_ports_num.attr,
 123         &dev_attr_bitstream_id.attr,
 124         &dev_attr_bitstream_metadata.attr,
 125         &dev_attr_cache_size.attr,
 126         &dev_attr_fabric_version.attr,
 127         &dev_attr_socket_id.attr,
 128         NULL,
 129 };
 130 
 131 static const struct attribute_group fme_hdr_group = {
 132         .attrs = fme_hdr_attrs,
 133 };
 134 
 135 static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
 136                                        unsigned long arg)
 137 {
 138         struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
 139         int port_id;
 140 
 141         if (get_user(port_id, (int __user *)arg))
 142                 return -EFAULT;
 143 
 144         return dfl_fpga_cdev_release_port(cdev, port_id);
 145 }
 146 
 147 static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata,
 148                                       unsigned long arg)
 149 {
 150         struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
 151         int port_id;
 152 
 153         if (get_user(port_id, (int __user *)arg))
 154                 return -EFAULT;
 155 
 156         return dfl_fpga_cdev_assign_port(cdev, port_id);
 157 }
 158 
 159 static long fme_hdr_ioctl(struct platform_device *pdev,
 160                           struct dfl_feature *feature,
 161                           unsigned int cmd, unsigned long arg)
 162 {
 163         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
 164 
 165         switch (cmd) {
 166         case DFL_FPGA_FME_PORT_RELEASE:
 167                 return fme_hdr_ioctl_release_port(pdata, arg);
 168         case DFL_FPGA_FME_PORT_ASSIGN:
 169                 return fme_hdr_ioctl_assign_port(pdata, arg);
 170         }
 171 
 172         return -ENODEV;
 173 }
 174 
 175 static const struct dfl_feature_id fme_hdr_id_table[] = {
 176         {.id = FME_FEATURE_ID_HEADER,},
 177         {0,}
 178 };
 179 
 180 static const struct dfl_feature_ops fme_hdr_ops = {
 181         .ioctl = fme_hdr_ioctl,
 182 };
 183 
 184 static struct dfl_feature_driver fme_feature_drvs[] = {
 185         {
 186                 .id_table = fme_hdr_id_table,
 187                 .ops = &fme_hdr_ops,
 188         },
 189         {
 190                 .id_table = fme_pr_mgmt_id_table,
 191                 .ops = &fme_pr_mgmt_ops,
 192         },
 193         {
 194                 .id_table = fme_global_err_id_table,
 195                 .ops = &fme_global_err_ops,
 196         },
 197         {
 198                 .ops = NULL,
 199         },
 200 };
 201 
 202 static long fme_ioctl_check_extension(struct dfl_feature_platform_data *pdata,
 203                                       unsigned long arg)
 204 {
 205         /* No extension support for now */
 206         return 0;
 207 }
 208 
 209 static int fme_open(struct inode *inode, struct file *filp)
 210 {
 211         struct platform_device *fdev = dfl_fpga_inode_to_feature_dev(inode);
 212         struct dfl_feature_platform_data *pdata = dev_get_platdata(&fdev->dev);
 213         int ret;
 214 
 215         if (WARN_ON(!pdata))
 216                 return -ENODEV;
 217 
 218         ret = dfl_feature_dev_use_begin(pdata);
 219         if (ret)
 220                 return ret;
 221 
 222         dev_dbg(&fdev->dev, "Device File Open\n");
 223         filp->private_data = pdata;
 224 
 225         return 0;
 226 }
 227 
 228 static int fme_release(struct inode *inode, struct file *filp)
 229 {
 230         struct dfl_feature_platform_data *pdata = filp->private_data;
 231         struct platform_device *pdev = pdata->dev;
 232 
 233         dev_dbg(&pdev->dev, "Device File Release\n");
 234         dfl_feature_dev_use_end(pdata);
 235 
 236         return 0;
 237 }
 238 
 239 static long fme_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 240 {
 241         struct dfl_feature_platform_data *pdata = filp->private_data;
 242         struct platform_device *pdev = pdata->dev;
 243         struct dfl_feature *f;
 244         long ret;
 245 
 246         dev_dbg(&pdev->dev, "%s cmd 0x%x\n", __func__, cmd);
 247 
 248         switch (cmd) {
 249         case DFL_FPGA_GET_API_VERSION:
 250                 return DFL_FPGA_API_VERSION;
 251         case DFL_FPGA_CHECK_EXTENSION:
 252                 return fme_ioctl_check_extension(pdata, arg);
 253         default:
 254                 /*
 255                  * Let sub-feature's ioctl function to handle the cmd.
 256                  * Sub-feature's ioctl returns -ENODEV when cmd is not
 257                  * handled in this sub feature, and returns 0 or other
 258                  * error code if cmd is handled.
 259                  */
 260                 dfl_fpga_dev_for_each_feature(pdata, f) {
 261                         if (f->ops && f->ops->ioctl) {
 262                                 ret = f->ops->ioctl(pdev, f, cmd, arg);
 263                                 if (ret != -ENODEV)
 264                                         return ret;
 265                         }
 266                 }
 267         }
 268 
 269         return -EINVAL;
 270 }
 271 
 272 static int fme_dev_init(struct platform_device *pdev)
 273 {
 274         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
 275         struct dfl_fme *fme;
 276 
 277         fme = devm_kzalloc(&pdev->dev, sizeof(*fme), GFP_KERNEL);
 278         if (!fme)
 279                 return -ENOMEM;
 280 
 281         fme->pdata = pdata;
 282 
 283         mutex_lock(&pdata->lock);
 284         dfl_fpga_pdata_set_private(pdata, fme);
 285         mutex_unlock(&pdata->lock);
 286 
 287         return 0;
 288 }
 289 
 290 static void fme_dev_destroy(struct platform_device *pdev)
 291 {
 292         struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
 293         struct dfl_fme *fme;
 294 
 295         mutex_lock(&pdata->lock);
 296         fme = dfl_fpga_pdata_get_private(pdata);
 297         dfl_fpga_pdata_set_private(pdata, NULL);
 298         mutex_unlock(&pdata->lock);
 299 }
 300 
 301 static const struct file_operations fme_fops = {
 302         .owner          = THIS_MODULE,
 303         .open           = fme_open,
 304         .release        = fme_release,
 305         .unlocked_ioctl = fme_ioctl,
 306 };
 307 
 308 static int fme_probe(struct platform_device *pdev)
 309 {
 310         int ret;
 311 
 312         ret = fme_dev_init(pdev);
 313         if (ret)
 314                 goto exit;
 315 
 316         ret = dfl_fpga_dev_feature_init(pdev, fme_feature_drvs);
 317         if (ret)
 318                 goto dev_destroy;
 319 
 320         ret = dfl_fpga_dev_ops_register(pdev, &fme_fops, THIS_MODULE);
 321         if (ret)
 322                 goto feature_uinit;
 323 
 324         return 0;
 325 
 326 feature_uinit:
 327         dfl_fpga_dev_feature_uinit(pdev);
 328 dev_destroy:
 329         fme_dev_destroy(pdev);
 330 exit:
 331         return ret;
 332 }
 333 
 334 static int fme_remove(struct platform_device *pdev)
 335 {
 336         dfl_fpga_dev_ops_unregister(pdev);
 337         dfl_fpga_dev_feature_uinit(pdev);
 338         fme_dev_destroy(pdev);
 339 
 340         return 0;
 341 }
 342 
 343 static const struct attribute_group *fme_dev_groups[] = {
 344         &fme_hdr_group,
 345         &fme_global_err_group,
 346         NULL
 347 };
 348 
 349 static struct platform_driver fme_driver = {
 350         .driver = {
 351                 .name       = DFL_FPGA_FEATURE_DEV_FME,
 352                 .dev_groups = fme_dev_groups,
 353         },
 354         .probe   = fme_probe,
 355         .remove  = fme_remove,
 356 };
 357 
 358 module_platform_driver(fme_driver);
 359 
 360 MODULE_DESCRIPTION("FPGA Management Engine driver");
 361 MODULE_AUTHOR("Intel Corporation");
 362 MODULE_LICENSE("GPL v2");
 363 MODULE_ALIAS("platform:dfl-fme");

/* [<][>][^][v][top][bottom][index][help] */