linux/drivers/staging/xroeframer/sysfs_xroe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2018 Xilinx, Inc.
   4 *
   5 * Vasileios Bimpikas <vasileios.bimpikas@xilinx.com>
   6 */
   7#include <linux/init.h>
   8#include <linux/kobject.h>
   9#include <linux/module.h>
  10#include <linux/stat.h>
  11#include <linux/string.h>
  12#include <linux/sysfs.h>
  13#include "xroe_framer.h"
  14
  15enum { XROE_SIZE_MAX = 15 };
  16static int xroe_size;
  17static char xroe_tmp[XROE_SIZE_MAX];
  18
  19/**
  20 * version_show - Returns the block's revision number
  21 * @kobj:       The kernel object of the entry
  22 * @attr:       The attributes of the kernel object
  23 * @buff:       The buffer containing the revision string
  24 *
  25 * Returns the block's major, minor & version revision numbers
  26 * in a %d.%d.%d format
  27 *
  28 * Return: XROE_SIZE_MAX on success
  29 */
  30static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr,
  31                            char *buff)
  32{
  33        u32 major_rev;
  34        u32 minor_rev;
  35        u32 version_rev;
  36
  37        major_rev = utils_sysfs_show_wrapper(CFG_MAJOR_REVISION_ADDR,
  38                                             CFG_MAJOR_REVISION_OFFSET,
  39                                             CFG_MAJOR_REVISION_MASK, kobj);
  40        minor_rev = utils_sysfs_show_wrapper(CFG_MINOR_REVISION_ADDR,
  41                                             CFG_MINOR_REVISION_OFFSET,
  42                                             CFG_MINOR_REVISION_MASK, kobj);
  43        version_rev = utils_sysfs_show_wrapper(CFG_VERSION_REVISION_ADDR,
  44                                               CFG_VERSION_REVISION_OFFSET,
  45                                               CFG_VERSION_REVISION_MASK, kobj);
  46        sprintf(buff, "%d.%d.%d\n", major_rev, minor_rev, version_rev);
  47        return XROE_SIZE_MAX;
  48}
  49
  50/**
  51 * version_store - Writes to the framer version sysfs entry (not permitted)
  52 * @kobj:       The kernel object of the entry
  53 * @attr:       The attributes of the kernel object
  54 * @buff:       The buffer containing the revision string
  55 * @count:      The number of characters typed by the user
  56 *
  57 * Writes to the framer version sysfs entry (not permitted)
  58 *
  59 * Return: 0
  60 */
  61static ssize_t version_store(struct  kobject *kobj, struct kobj_attribute *attr,
  62                             const char *buff, size_t count)
  63{
  64        return 0;
  65}
  66
  67/**
  68 * enable_show - Returns the framer's enable status
  69 * @kobj:       The kernel object of the entry
  70 * @attr:       The attributes of the kernel object
  71 * @buff:       The buffer containing the enable status
  72 *
  73 * Reads and writes the framer's enable status to the sysfs entry
  74 *
  75 * Return: XROE_SIZE_MAX on success
  76 */
  77static ssize_t enable_show(struct kobject *kobj, struct kobj_attribute *attr,
  78                           char *buff)
  79{
  80        u32 enable;
  81
  82        enable = utils_sysfs_show_wrapper(CFG_MASTER_INT_ENABLE_ADDR,
  83                                          CFG_MASTER_INT_ENABLE_OFFSET,
  84                                          CFG_MASTER_INT_ENABLE_MASK, kobj);
  85        if (enable)
  86                sprintf(buff, "true\n");
  87        else
  88                sprintf(buff, "false\n");
  89        return XROE_SIZE_MAX;
  90}
  91
  92/**
  93 * version_store - Writes to the framer's enable status register
  94 * @kobj:       The kernel object of the entry
  95 * @attr:       The attributes of the kernel object
  96 * @buff:       The buffer containing the enable status
  97 * @count:      The number of characters typed by the user
  98 *
  99 * Reads the user input and accordingly writes the framer's enable status
 100 * to the sysfs entry
 101 *
 102 * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
 103 */
 104static ssize_t enable_store(struct kobject *kobj, struct kobj_attribute *attr,
 105                            const char *buff, size_t count)
 106{
 107        u32 enable = 0;
 108
 109        xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
 110        strncpy(xroe_tmp, buff, xroe_size);
 111        if (strncmp(xroe_tmp, "true", xroe_size) == 0)
 112                enable = 1;
 113        else if (strncmp(xroe_tmp, "false", xroe_size) == 0)
 114                enable = 0;
 115        utils_sysfs_store_wrapper(CFG_MASTER_INT_ENABLE_ADDR,
 116                                  CFG_MASTER_INT_ENABLE_OFFSET,
 117                                  CFG_MASTER_INT_ENABLE_MASK, enable, kobj);
 118        return xroe_size;
 119}
 120
 121/**
 122 * framer_restart_show - Returns the framer's restart status
 123 * @kobj:       The kernel object of the entry
 124 * @attr:       The attributes of the kernel object
 125 * @buff:       The buffer containing the restart status
 126 *
 127 * Reads and writes the framer's restart status to the sysfs entry
 128 *
 129 * Return: XROE_SIZE_MAX on success
 130 */
 131static ssize_t framer_restart_show(struct kobject *kobj,
 132                                   struct kobj_attribute *attr, char *buff)
 133{
 134        u32 restart;
 135
 136        restart = utils_sysfs_show_wrapper(FRAM_DISABLE_ADDR,
 137                                           FRAM_DISABLE_OFFSET,
 138                                           FRAM_DISABLE_MASK, kobj);
 139        if (restart)
 140                sprintf(buff, "true\n");
 141
 142        else
 143                sprintf(buff, "false\n");
 144
 145        return XROE_SIZE_MAX;
 146}
 147
 148/**
 149 * framer_restart_store - Writes to the framer's restart status register
 150 * @kobj:       The kernel object of the entry
 151 * @attr:       The attributes of the kernel object
 152 * @buff:       The buffer containing the restart status
 153 * @count:      The number of characters typed by the user
 154 *
 155 * Reads the user input and accordingly writes the framer's restart status
 156 * to the sysfs entry
 157 *
 158 * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
 159 */
 160static ssize_t framer_restart_store(struct  kobject *kobj,
 161                                    struct kobj_attribute *attr,
 162                                    const char *buff, size_t count)
 163{
 164        u32 restart = 0;
 165
 166        xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
 167        strncpy(xroe_tmp, buff, xroe_size);
 168        if (strncmp(xroe_tmp, "true", xroe_size) == 0)
 169                restart = 0x01;
 170        else if (strncmp(xroe_tmp, "false", xroe_size) == 0)
 171                restart = 0x00;
 172        utils_sysfs_store_wrapper(FRAM_DISABLE_ADDR, FRAM_DISABLE_OFFSET,
 173                                  FRAM_DISABLE_MASK, restart, kobj);
 174        return xroe_size;
 175}
 176
 177/**
 178 * deframer_restart_show - Returns the deframer's restart status
 179 * @kobj:       The kernel object of the entry
 180 * @attr:       The attributes of the kernel object
 181 * @buff:       The buffer containing the restart status
 182 *
 183 * Reads and writes the deframer's restart status to the sysfs entry
 184 *
 185 * Return: XROE_SIZE_MAX on success
 186 */
 187static ssize_t deframer_restart_show(struct kobject *kobj,
 188                                     struct kobj_attribute *attr, char *buff)
 189{
 190        u32 offset = DEFM_RESTART_OFFSET;
 191        u32 mask = DEFM_RESTART_MASK;
 192        u32 buffer = 0;
 193        u32 restart = 0;
 194        void __iomem *working_address = ((u8 *)lp->base_addr
 195        + DEFM_RESTART_ADDR);
 196
 197        buffer = ioread32(working_address);
 198        restart = (buffer & mask) >> offset;
 199
 200        if (restart)
 201                sprintf(buff, "true\n");
 202
 203        else
 204                sprintf(buff, "false\n");
 205
 206        return XROE_SIZE_MAX;
 207}
 208
 209/**
 210 * deframer_restart_store - Writes to the deframer's restart status register
 211 * @kobj:       The kernel object of the entry
 212 * @attr:       The attributes of the kernel object
 213 * @buff:       The buffer containing the restart status
 214 * @count:      The number of characters typed by the user
 215 *
 216 * Reads the user input and accordingly writes the deframer's restart status
 217 * to the sysfs entry
 218 *
 219 * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
 220 */
 221static ssize_t deframer_restart_store(struct kobject *kobj,
 222                                      struct kobj_attribute *attr,
 223                                      const char *buff, size_t count)
 224{
 225        u32 offset = DEFM_RESTART_OFFSET;
 226        u32 mask = DEFM_RESTART_MASK;
 227        void __iomem *working_address = ((u8 *)lp->base_addr
 228        + DEFM_RESTART_ADDR);
 229        u32 restart = 0;
 230
 231        xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
 232        strncpy(xroe_tmp, buff, xroe_size);
 233        if (strncmp(xroe_tmp, "true", xroe_size) == 0) {
 234                restart = 0x01;
 235                utils_write32withmask(working_address, restart,
 236                                      mask, offset);
 237        } else if (strncmp(xroe_tmp, "false", xroe_size) == 0) {
 238                restart = 0x00;
 239                utils_write32withmask(working_address, restart,
 240                                      mask, offset);
 241        }
 242
 243        return xroe_size;
 244}
 245
 246/**
 247 * xxv_reset_show - Returns the XXV's reset status
 248 * @kobj:       The kernel object of the entry
 249 * @attr:       The attributes of the kernel object
 250 * @buff:       The buffer containing the reset status
 251 *
 252 * Reads and writes the XXV's reset status to the sysfs entry
 253 *
 254 * Return: XROE_SIZE_MAX on success
 255 */
 256static ssize_t xxv_reset_show(struct kobject *kobj, struct kobj_attribute *attr,
 257                              char *buff)
 258{
 259        u32 offset = CFG_USER_RW_OUT_OFFSET;
 260        u32 mask = CFG_USER_RW_OUT_MASK;
 261        u32 buffer = 0;
 262        u32 restart = 0;
 263        void __iomem *working_address = ((u8 *)lp->base_addr +
 264        CFG_USER_RW_OUT_ADDR);
 265
 266        buffer = ioread32(working_address);
 267        restart = (buffer & mask) >> offset;
 268        if (restart)
 269                sprintf(buff, "true\n");
 270        else
 271                sprintf(buff, "false\n");
 272        return XROE_SIZE_MAX;
 273}
 274
 275/**
 276 * xxv_reset_store - Writes to the XXV's reset register
 277 * @kobj:       The kernel object of the entry
 278 * @attr:       The attributes of the kernel object
 279 * @buff:       The buffer containing the reset status
 280 * @count:      The number of characters typed by the user
 281 *
 282 * Reads the user input and accordingly writes the XXV's reset status
 283 * to the sysfs entry
 284 *
 285 * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
 286 */
 287static ssize_t xxv_reset_store(struct  kobject *kobj,
 288                               struct kobj_attribute *attr,
 289                               const char *buff, size_t count)
 290{
 291        u32 offset = CFG_USER_RW_OUT_OFFSET;
 292        u32 mask = CFG_USER_RW_OUT_MASK;
 293        void __iomem *working_address = ((u8 *)lp->base_addr +
 294        CFG_USER_RW_OUT_ADDR);
 295        u32 restart = 0;
 296
 297        xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
 298        strncpy(xroe_tmp, buff, xroe_size);
 299
 300        if (strncmp(xroe_tmp, "true", xroe_size) == 0) {
 301                restart = 0x01;
 302                utils_write32withmask(working_address, restart,
 303                                      mask, offset);
 304        } else if (strncmp(xroe_tmp, "false", xroe_size) == 0) {
 305                restart = 0x00;
 306                utils_write32withmask(working_address, restart,
 307                                      mask, offset);
 308        }
 309        return xroe_size;
 310}
 311
 312/**
 313 * framing_show - Returns the current framing
 314 * @kobj:       The kernel object of the entry
 315 * @attr:       The attributes of the kernel object
 316 * @buff:       The buffer containing the reset status
 317 *
 318 * Reads and writes the current framing type to the sysfs entry
 319 *
 320 * Return: XROE_SIZE_MAX on success
 321 */
 322static ssize_t framing_show(struct kobject *kobj, struct kobj_attribute *attr,
 323                            char *buff)
 324{
 325        u32 offset = (DEFM_DATA_PKT_MESSAGE_TYPE_ADDR +
 326        DEFM_DATA_PKT_MESSAGE_TYPE_OFFSET);
 327        u8 buffer = 0;
 328        u8 framing = 0xff;
 329        void __iomem *working_address = ((u8 *)lp->base_addr + offset);
 330
 331        buffer = ioread8(working_address);
 332        framing = buffer;
 333        if (framing == 0)
 334                sprintf(buff, "eCPRI\n");
 335        else if (framing == 1)
 336                sprintf(buff, "1914.3\n");
 337        return XROE_SIZE_MAX;
 338}
 339
 340/**
 341 * framing_store - Writes to the current framing register
 342 * @kobj:       The kernel object of the entry
 343 * @attr:       The attributes of the kernel object
 344 * @buff:       The buffer containing the reset status
 345 * @count:      The number of characters typed by the user
 346 *
 347 * Reads the user input and accordingly writes the current framing
 348 * to the sysfs entry
 349 *
 350 * Return: XROE_SIZE_MAX or the value of "count", if that's lesser, on success
 351 */
 352static ssize_t framing_store(struct kobject *kobj, struct kobj_attribute *attr,
 353                             const char *buff, size_t count)
 354{
 355        u32 offset = (DEFM_DATA_PKT_MESSAGE_TYPE_ADDR +
 356        DEFM_DATA_PKT_MESSAGE_TYPE_OFFSET);
 357        void __iomem *working_address = ((u8 *)lp->base_addr + offset);
 358
 359        xroe_size = min_t(size_t, count, (size_t)XROE_SIZE_MAX);
 360        strncpy(xroe_tmp, buff, xroe_size);
 361        if (strncmp(xroe_tmp, "eCPRI", xroe_size) == 0)
 362                iowrite8(0, working_address);
 363        else if (strncmp(xroe_tmp, "1914.3", xroe_size) == 0)
 364                iowrite8(1, working_address);
 365        return xroe_size;
 366}
 367
 368/* TODO Use DEVICE_ATTR/_RW/_RO macros */
 369
 370static struct kobj_attribute version_attribute =
 371        __ATTR(version, 0444, version_show, version_store);
 372
 373static struct kobj_attribute enable_attribute =
 374        __ATTR(enable, 0660, enable_show, enable_store);
 375
 376static struct kobj_attribute framer_restart =
 377        __ATTR(framer_restart, 0660, framer_restart_show, framer_restart_store);
 378
 379static struct kobj_attribute deframer_restart =
 380        __ATTR(deframer_restart, 0660, deframer_restart_show,
 381               deframer_restart_store);
 382
 383static struct kobj_attribute xxv_reset =
 384        __ATTR(xxv_reset, 0660, xxv_reset_show, xxv_reset_store);
 385
 386static struct kobj_attribute framing_attribute =
 387        __ATTR(framing, 0660, framing_show, framing_store);
 388
 389static struct attribute *attrs[] = {
 390        &version_attribute.attr,
 391        &enable_attribute.attr,
 392        &framer_restart.attr,
 393        &deframer_restart.attr,
 394        &xxv_reset.attr,
 395        &framing_attribute.attr,
 396        NULL,
 397};
 398
 399static struct attribute_group attr_group = {
 400        .attrs = attrs,
 401};
 402
 403struct kobject *root_xroe_kobj;
 404
 405/**
 406 * xroe_sysfs_init - Creates the xroe sysfs directory and entries
 407 *
 408 * Return: 0 on success, negative value in case of failure to
 409 * create the sysfs group
 410 *
 411 * Creates the xroe sysfs directory and entries, as well as the
 412 * subdirectories for IPv4, IPv6 & UDP
 413 */
 414int xroe_sysfs_init(void)
 415{
 416        int ret;
 417
 418        root_xroe_kobj = kobject_create_and_add("xroe", kernel_kobj);
 419        if (!root_xroe_kobj)
 420                return -ENOMEM;
 421        ret = sysfs_create_group(root_xroe_kobj, &attr_group);
 422        if (ret)
 423                kobject_put(root_xroe_kobj);
 424        ret = xroe_sysfs_ipv4_init();
 425        if (ret)
 426                return ret;
 427        ret = xroe_sysfs_ipv6_init();
 428        if (ret)
 429                return ret;
 430        ret = xroe_sysfs_udp_init();
 431        if (ret)
 432                return ret;
 433        ret = xroe_sysfs_stats_init();
 434        return ret;
 435}
 436
 437/**
 438 * xroe_sysfs_exit - Deletes the xroe sysfs directory and entries
 439 *
 440 * Deletes the xroe sysfs directory and entries, as well as the
 441 * subdirectories for IPv4, IPv6 & UDP
 442 *
 443 */
 444void xroe_sysfs_exit(void)
 445{
 446        int i;
 447
 448        xroe_sysfs_ipv4_exit();
 449        xroe_sysfs_ipv6_exit();
 450        xroe_sysfs_udp_exit();
 451        xroe_sysfs_stats_exit();
 452        for (i = 0; i < MAX_NUM_ETH_PORTS; i++)
 453                kobject_put(kobj_eth_ports[i]);
 454        kobject_put(kobj_framer);
 455        kobject_put(root_xroe_kobj);
 456}
 457
 458/**
 459 * utils_write32withmask - Writes a masked 32-bit value
 460 * @working_address:    The starting address to write
 461 * @value:                      The value to be written
 462 * @mask:                       The mask to be used
 463 * @offset:                     The offset from the provided starting address
 464 *
 465 * Writes a 32-bit value to the provided address with the input mask
 466 *
 467 * Return: 0 on success
 468 */
 469int utils_write32withmask(void __iomem *working_address, u32 value,
 470                          u32 mask, u32 offset)
 471{
 472        u32 read_register_value = 0;
 473        u32 register_value_to_write = 0;
 474        u32 delta = 0, buffer = 0;
 475
 476        read_register_value = ioread32(working_address);
 477        buffer = (value << offset);
 478        register_value_to_write = read_register_value & ~mask;
 479        delta = buffer & mask;
 480        register_value_to_write |= delta;
 481        iowrite32(register_value_to_write, working_address);
 482        return 0;
 483}
 484
 485/**
 486 * utils_sysfs_path_to_eth_port_num - Get the current ethernet port
 487 * @kobj:       The kobject of the entry calling the function
 488 *
 489 * Extracts the number of the current ethernet port instance
 490 *
 491 * Return: The number of the ethernet port instance (0 - MAX_NUM_ETH_PORTS) on
 492 * success, -1 otherwise
 493 */
 494static int utils_sysfs_path_to_eth_port_num(struct kobject *kobj)
 495{
 496        char *current_path = NULL;
 497        int port;
 498        int ret;
 499
 500        current_path = kobject_get_path(kobj, GFP_KERNEL);
 501        ret = sscanf(current_path, "/kernel/xroe/framer/eth_port_%d/", &port);
 502        /* if sscanf() returns 0, no fields were assigned, therefore no
 503         * adjustments will be made for port number
 504         */
 505        if (ret == 0)
 506                port = 0;
 507//      printk(KERN_ALERT "current_path: %s port: %d\n", current_path, port);
 508        kfree(current_path);
 509        return port;
 510}
 511
 512/**
 513 * utils_sysfs_store_wrapper - Wraps the storing function for sysfs entries
 514 * @address:    The address of the register to be written
 515 * @offset:     The offset from the address of the register
 516 * @mask:       The mask to be used on the value to be written
 517 * @value:      The value to be written to the register
 518 * @kobj:       The kobject of the entry calling the function
 519 *
 520 * Wraps the core functionality of all "store" functions of sysfs entries.
 521 * After calculating the ethernet port number (in N/A cases, it's 0), the value
 522 * is written to the designated register
 523 *
 524 */
 525void utils_sysfs_store_wrapper(u32 address, u32 offset, u32 mask, u32 value,
 526                               struct kobject *kobj)
 527{
 528        int port;
 529        void __iomem *working_address;
 530
 531        port = utils_sysfs_path_to_eth_port_num(kobj);
 532        working_address = (void __iomem *)(lp->base_addr +
 533                          (address + (0x100 * port)));
 534        utils_write32withmask(working_address, value, mask, offset);
 535}
 536
 537/**
 538 * utils_sysfs_store_wrapper - Wraps the storing function for sysfs entries
 539 * @address:    The address of the register to be read
 540 * @offset:     The offset from the address of the register
 541 * @mask:       The mask to be used on the value to be read
 542 * @kobj:       The kobject of the entry calling the function
 543 *
 544 * Wraps the core functionality of all "show" functions of sysfs entries.
 545 * After calculating the ethernet port number (in N/A cases, it's 0), the value
 546 * is read from the designated register and returned.
 547 *
 548 * Return: The value designated by the address, offset and mask
 549 */
 550u32 utils_sysfs_show_wrapper(u32 address, u32 offset, u32 mask,
 551                             struct kobject *kobj)
 552{
 553        int port;
 554        void __iomem *working_address;
 555        u32 buffer;
 556
 557        port = utils_sysfs_path_to_eth_port_num(kobj);
 558        working_address = (void __iomem *)(lp->base_addr +
 559                          (address + (0x100 * port)));
 560        buffer = ioread32(working_address);
 561        return (buffer & mask) >> offset;
 562}
 563