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