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