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 23 static 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 33 static 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 70 einval: 71 CTCM_DBF_DEV(SETUP, ndev, "buff_err"); 72 return -EINVAL; 73 } 74 75 static 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 112 static 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 124 static 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 136 static 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 146 static 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 167 static 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 176 static 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 189 static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write); 190 static DEVICE_ATTR(protocol, 0644, ctcm_proto_show, ctcm_proto_store); 191 static DEVICE_ATTR(type, 0444, ctcm_type_show, NULL); 192 static DEVICE_ATTR(stats, 0644, stats_show, stats_write); 193 194 static 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 202 static struct attribute_group ctcm_attr_group = { 203 .attrs = ctcm_attr, 204 }; 205 const struct attribute_group *ctcm_attr_groups[] = { 206 &ctcm_attr_group, 207 NULL, 208 }; 209