linux/drivers/s390/net/ctcm_sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright IBM Corp. 2007, 2007
   4 * Authors:     Peter Tiedemann (ptiedem@de.ibm.com)
   5 *
   6 */
   7
   8#undef DEBUG
   9#undef DEBUGDATA
  10#undef DEBUGCCW
  11
  12#define KMSG_COMPONENT "ctcm"
  13#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  14
  15#include <linux/device.h>
  16#include <linux/sysfs.h>
  17#include <linux/slab.h>
  18#include "ctcm_main.h"
  19
  20/*
  21 * sysfs attributes
  22 */
  23
  24static ssize_t ctcm_buffer_show(struct device *dev,
  25                                struct device_attribute *attr, char *buf)
  26{
  27        struct ctcm_priv *priv = dev_get_drvdata(dev);
  28
  29        if (!priv)
  30                return -ENODEV;
  31        return sprintf(buf, "%d\n", priv->buffer_size);
  32}
  33
  34static ssize_t ctcm_buffer_write(struct device *dev,
  35                struct device_attribute *attr, const char *buf, size_t count)
  36{
  37        struct net_device *ndev;
  38        unsigned int bs1;
  39        struct ctcm_priv *priv = dev_get_drvdata(dev);
  40        int rc;
  41
  42        ndev = priv->channel[CTCM_READ]->netdev;
  43        if (!(priv && priv->channel[CTCM_READ] && ndev)) {
  44                CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
  45                return -ENODEV;
  46        }
  47
  48        rc = kstrtouint(buf, 0, &bs1);
  49        if (rc)
  50                goto einval;
  51        if (bs1 > CTCM_BUFSIZE_LIMIT)
  52                                        goto einval;
  53        if (bs1 < (576 + LL_HEADER_LENGTH + 2))
  54                                        goto einval;
  55        priv->buffer_size = bs1;        /* just to overwrite the default */
  56
  57        if ((ndev->flags & IFF_RUNNING) &&
  58            (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
  59                                        goto einval;
  60
  61        priv->channel[CTCM_READ]->max_bufsize = bs1;
  62        priv->channel[CTCM_WRITE]->max_bufsize = bs1;
  63        if (!(ndev->flags & IFF_RUNNING))
  64                ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
  65        priv->channel[CTCM_READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
  66        priv->channel[CTCM_WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
  67
  68        CTCM_DBF_DEV(SETUP, ndev, buf);
  69        return count;
  70
  71einval:
  72        CTCM_DBF_DEV(SETUP, ndev, "buff_err");
  73        return -EINVAL;
  74}
  75
  76static void ctcm_print_statistics(struct ctcm_priv *priv)
  77{
  78        char *sbuf;
  79        char *p;
  80
  81        if (!priv)
  82                return;
  83        sbuf = kmalloc(2048, GFP_KERNEL);
  84        if (sbuf == NULL)
  85                return;
  86        p = sbuf;
  87
  88        p += sprintf(p, "  Device FSM state: %s\n",
  89                     fsm_getstate_str(priv->fsm));
  90        p += sprintf(p, "  RX channel FSM state: %s\n",
  91                     fsm_getstate_str(priv->channel[CTCM_READ]->fsm));
  92        p += sprintf(p, "  TX channel FSM state: %s\n",
  93                     fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm));
  94        p += sprintf(p, "  Max. TX buffer used: %ld\n",
  95                     priv->channel[WRITE]->prof.maxmulti);
  96        p += sprintf(p, "  Max. chained SKBs: %ld\n",
  97                     priv->channel[WRITE]->prof.maxcqueue);
  98        p += sprintf(p, "  TX single write ops: %ld\n",
  99                     priv->channel[WRITE]->prof.doios_single);
 100        p += sprintf(p, "  TX multi write ops: %ld\n",
 101                     priv->channel[WRITE]->prof.doios_multi);
 102        p += sprintf(p, "  Netto bytes written: %ld\n",
 103                     priv->channel[WRITE]->prof.txlen);
 104        p += sprintf(p, "  Max. TX IO-time: %u\n",
 105                     jiffies_to_usecs(priv->channel[WRITE]->prof.tx_time));
 106
 107        printk(KERN_INFO "Statistics for %s:\n%s",
 108                                priv->channel[CTCM_WRITE]->netdev->name, sbuf);
 109        kfree(sbuf);
 110        return;
 111}
 112
 113static ssize_t stats_show(struct device *dev,
 114                          struct device_attribute *attr, char *buf)
 115{
 116        struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
 117        struct ctcm_priv *priv = dev_get_drvdata(dev);
 118
 119        if (!priv || gdev->state != CCWGROUP_ONLINE)
 120                return -ENODEV;
 121        ctcm_print_statistics(priv);
 122        return sprintf(buf, "0\n");
 123}
 124
 125static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
 126                                const char *buf, size_t count)
 127{
 128        struct ctcm_priv *priv = dev_get_drvdata(dev);
 129        if (!priv)
 130                return -ENODEV;
 131        /* Reset statistics */
 132        memset(&priv->channel[WRITE]->prof, 0,
 133                                sizeof(priv->channel[CTCM_WRITE]->prof));
 134        return count;
 135}
 136
 137static ssize_t ctcm_proto_show(struct device *dev,
 138                                struct device_attribute *attr, char *buf)
 139{
 140        struct ctcm_priv *priv = dev_get_drvdata(dev);
 141        if (!priv)
 142                return -ENODEV;
 143
 144        return sprintf(buf, "%d\n", priv->protocol);
 145}
 146
 147static ssize_t ctcm_proto_store(struct device *dev,
 148                struct device_attribute *attr, const char *buf, size_t count)
 149{
 150        int value, rc;
 151        struct ctcm_priv *priv = dev_get_drvdata(dev);
 152
 153        if (!priv)
 154                return -ENODEV;
 155        rc = kstrtoint(buf, 0, &value);
 156        if (rc ||
 157            !((value == CTCM_PROTO_S390)  ||
 158              (value == CTCM_PROTO_LINUX) ||
 159              (value == CTCM_PROTO_MPC) ||
 160              (value == CTCM_PROTO_OS390)))
 161                return -EINVAL;
 162        priv->protocol = value;
 163        CTCM_DBF_DEV(SETUP, dev, buf);
 164
 165        return count;
 166}
 167
 168static const char *ctcm_type[] = {
 169        "not a channel",
 170        "CTC/A",
 171        "FICON channel",
 172        "ESCON channel",
 173        "unknown channel type",
 174        "unsupported channel type",
 175};
 176
 177static ssize_t ctcm_type_show(struct device *dev,
 178                                struct device_attribute *attr, char *buf)
 179{
 180        struct ccwgroup_device *cgdev;
 181
 182        cgdev = to_ccwgroupdev(dev);
 183        if (!cgdev)
 184                return -ENODEV;
 185
 186        return sprintf(buf, "%s\n",
 187                        ctcm_type[cgdev->cdev[0]->id.driver_info]);
 188}
 189
 190static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
 191static DEVICE_ATTR(protocol, 0644, ctcm_proto_show, ctcm_proto_store);
 192static DEVICE_ATTR(type, 0444, ctcm_type_show, NULL);
 193static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
 194
 195static struct attribute *ctcm_attr[] = {
 196        &dev_attr_protocol.attr,
 197        &dev_attr_type.attr,
 198        &dev_attr_buffer.attr,
 199        &dev_attr_stats.attr,
 200        NULL,
 201};
 202
 203static struct attribute_group ctcm_attr_group = {
 204        .attrs = ctcm_attr,
 205};
 206const struct attribute_group *ctcm_attr_groups[] = {
 207        &ctcm_attr_group,
 208        NULL,
 209};
 210