Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * RapidIO sysfs attributes and support
0004  *
0005  * Copyright 2005 MontaVista Software, Inc.
0006  * Matt Porter <mporter@kernel.crashing.org>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/rio.h>
0011 #include <linux/rio_drv.h>
0012 #include <linux/stat.h>
0013 #include <linux/capability.h>
0014 
0015 #include "rio.h"
0016 
0017 /* Sysfs support */
0018 #define rio_config_attr(field, format_string)                   \
0019 static ssize_t                              \
0020 field##_show(struct device *dev, struct device_attribute *attr, char *buf)          \
0021 {                                   \
0022     struct rio_dev *rdev = to_rio_dev(dev);             \
0023                                     \
0024     return sprintf(buf, format_string, rdev->field);        \
0025 }                                   \
0026 static DEVICE_ATTR_RO(field);
0027 
0028 rio_config_attr(did, "0x%04x\n");
0029 rio_config_attr(vid, "0x%04x\n");
0030 rio_config_attr(device_rev, "0x%08x\n");
0031 rio_config_attr(asm_did, "0x%04x\n");
0032 rio_config_attr(asm_vid, "0x%04x\n");
0033 rio_config_attr(asm_rev, "0x%04x\n");
0034 rio_config_attr(destid, "0x%04x\n");
0035 rio_config_attr(hopcount, "0x%02x\n");
0036 
0037 static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf)
0038 {
0039     struct rio_dev *rdev = to_rio_dev(dev);
0040     char *str = buf;
0041     int i;
0042 
0043     for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
0044             i++) {
0045         if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
0046             continue;
0047         str +=
0048             sprintf(str, "%04x %02x\n", i,
0049                 rdev->rswitch->route_table[i]);
0050     }
0051 
0052     return (str - buf);
0053 }
0054 static DEVICE_ATTR_RO(routes);
0055 
0056 static ssize_t lprev_show(struct device *dev,
0057               struct device_attribute *attr, char *buf)
0058 {
0059     struct rio_dev *rdev = to_rio_dev(dev);
0060 
0061     return sprintf(buf, "%s\n",
0062             (rdev->prev) ? rio_name(rdev->prev) : "root");
0063 }
0064 static DEVICE_ATTR_RO(lprev);
0065 
0066 static ssize_t lnext_show(struct device *dev,
0067               struct device_attribute *attr, char *buf)
0068 {
0069     struct rio_dev *rdev = to_rio_dev(dev);
0070     char *str = buf;
0071     int i;
0072 
0073     if (rdev->pef & RIO_PEF_SWITCH) {
0074         for (i = 0; i < RIO_GET_TOTAL_PORTS(rdev->swpinfo); i++) {
0075             if (rdev->rswitch->nextdev[i])
0076                 str += sprintf(str, "%s\n",
0077                     rio_name(rdev->rswitch->nextdev[i]));
0078             else
0079                 str += sprintf(str, "null\n");
0080         }
0081     }
0082 
0083     return str - buf;
0084 }
0085 static DEVICE_ATTR_RO(lnext);
0086 
0087 static ssize_t modalias_show(struct device *dev,
0088                  struct device_attribute *attr, char *buf)
0089 {
0090     struct rio_dev *rdev = to_rio_dev(dev);
0091 
0092     return sprintf(buf, "rapidio:v%04Xd%04Xav%04Xad%04X\n",
0093                rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did);
0094 }
0095 static DEVICE_ATTR_RO(modalias);
0096 
0097 static struct attribute *rio_dev_attrs[] = {
0098     &dev_attr_did.attr,
0099     &dev_attr_vid.attr,
0100     &dev_attr_device_rev.attr,
0101     &dev_attr_asm_did.attr,
0102     &dev_attr_asm_vid.attr,
0103     &dev_attr_asm_rev.attr,
0104     &dev_attr_lprev.attr,
0105     &dev_attr_destid.attr,
0106     &dev_attr_modalias.attr,
0107 
0108     /* Switch-only attributes */
0109     &dev_attr_routes.attr,
0110     &dev_attr_lnext.attr,
0111     &dev_attr_hopcount.attr,
0112     NULL,
0113 };
0114 
0115 static ssize_t
0116 rio_read_config(struct file *filp, struct kobject *kobj,
0117         struct bin_attribute *bin_attr,
0118         char *buf, loff_t off, size_t count)
0119 {
0120     struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
0121     unsigned int size = 0x100;
0122     loff_t init_off = off;
0123     u8 *data = (u8 *) buf;
0124 
0125     /* Several chips lock up trying to read undefined config space */
0126     if (capable(CAP_SYS_ADMIN))
0127         size = RIO_MAINT_SPACE_SZ;
0128 
0129     if (off >= size)
0130         return 0;
0131     if (off + count > size) {
0132         size -= off;
0133         count = size;
0134     } else {
0135         size = count;
0136     }
0137 
0138     if ((off & 1) && size) {
0139         u8 val;
0140         rio_read_config_8(dev, off, &val);
0141         data[off - init_off] = val;
0142         off++;
0143         size--;
0144     }
0145 
0146     if ((off & 3) && size > 2) {
0147         u16 val;
0148         rio_read_config_16(dev, off, &val);
0149         data[off - init_off] = (val >> 8) & 0xff;
0150         data[off - init_off + 1] = val & 0xff;
0151         off += 2;
0152         size -= 2;
0153     }
0154 
0155     while (size > 3) {
0156         u32 val;
0157         rio_read_config_32(dev, off, &val);
0158         data[off - init_off] = (val >> 24) & 0xff;
0159         data[off - init_off + 1] = (val >> 16) & 0xff;
0160         data[off - init_off + 2] = (val >> 8) & 0xff;
0161         data[off - init_off + 3] = val & 0xff;
0162         off += 4;
0163         size -= 4;
0164     }
0165 
0166     if (size >= 2) {
0167         u16 val;
0168         rio_read_config_16(dev, off, &val);
0169         data[off - init_off] = (val >> 8) & 0xff;
0170         data[off - init_off + 1] = val & 0xff;
0171         off += 2;
0172         size -= 2;
0173     }
0174 
0175     if (size > 0) {
0176         u8 val;
0177         rio_read_config_8(dev, off, &val);
0178         data[off - init_off] = val;
0179         off++;
0180         --size;
0181     }
0182 
0183     return count;
0184 }
0185 
0186 static ssize_t
0187 rio_write_config(struct file *filp, struct kobject *kobj,
0188          struct bin_attribute *bin_attr,
0189          char *buf, loff_t off, size_t count)
0190 {
0191     struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
0192     unsigned int size = count;
0193     loff_t init_off = off;
0194     u8 *data = (u8 *) buf;
0195 
0196     if (off >= RIO_MAINT_SPACE_SZ)
0197         return 0;
0198     if (off + count > RIO_MAINT_SPACE_SZ) {
0199         size = RIO_MAINT_SPACE_SZ - off;
0200         count = size;
0201     }
0202 
0203     if ((off & 1) && size) {
0204         rio_write_config_8(dev, off, data[off - init_off]);
0205         off++;
0206         size--;
0207     }
0208 
0209     if ((off & 3) && (size > 2)) {
0210         u16 val = data[off - init_off + 1];
0211         val |= (u16) data[off - init_off] << 8;
0212         rio_write_config_16(dev, off, val);
0213         off += 2;
0214         size -= 2;
0215     }
0216 
0217     while (size > 3) {
0218         u32 val = data[off - init_off + 3];
0219         val |= (u32) data[off - init_off + 2] << 8;
0220         val |= (u32) data[off - init_off + 1] << 16;
0221         val |= (u32) data[off - init_off] << 24;
0222         rio_write_config_32(dev, off, val);
0223         off += 4;
0224         size -= 4;
0225     }
0226 
0227     if (size >= 2) {
0228         u16 val = data[off - init_off + 1];
0229         val |= (u16) data[off - init_off] << 8;
0230         rio_write_config_16(dev, off, val);
0231         off += 2;
0232         size -= 2;
0233     }
0234 
0235     if (size) {
0236         rio_write_config_8(dev, off, data[off - init_off]);
0237         off++;
0238         --size;
0239     }
0240 
0241     return count;
0242 }
0243 
0244 static struct bin_attribute rio_config_attr = {
0245     .attr = {
0246          .name = "config",
0247          .mode = S_IRUGO | S_IWUSR,
0248          },
0249     .size = RIO_MAINT_SPACE_SZ,
0250     .read = rio_read_config,
0251     .write = rio_write_config,
0252 };
0253 
0254 static struct bin_attribute *rio_dev_bin_attrs[] = {
0255     &rio_config_attr,
0256     NULL,
0257 };
0258 
0259 static umode_t rio_dev_is_attr_visible(struct kobject *kobj,
0260                        struct attribute *attr, int n)
0261 {
0262     struct rio_dev *rdev = to_rio_dev(kobj_to_dev(kobj));
0263     umode_t mode = attr->mode;
0264 
0265     if (!(rdev->pef & RIO_PEF_SWITCH) &&
0266         (attr == &dev_attr_routes.attr ||
0267          attr == &dev_attr_lnext.attr ||
0268          attr == &dev_attr_hopcount.attr)) {
0269         /*
0270          * Hide switch-specific attributes for a non-switch device.
0271          */
0272         mode = 0;
0273     }
0274 
0275     return mode;
0276 }
0277 
0278 static const struct attribute_group rio_dev_group = {
0279     .attrs      = rio_dev_attrs,
0280     .is_visible = rio_dev_is_attr_visible,
0281     .bin_attrs  = rio_dev_bin_attrs,
0282 };
0283 
0284 const struct attribute_group *rio_dev_groups[] = {
0285     &rio_dev_group,
0286     NULL,
0287 };
0288 
0289 static ssize_t scan_store(struct bus_type *bus, const char *buf, size_t count)
0290 {
0291     long val;
0292     int rc;
0293 
0294     if (kstrtol(buf, 0, &val) < 0)
0295         return -EINVAL;
0296 
0297     if (val == RIO_MPORT_ANY) {
0298         rc = rio_init_mports();
0299         goto exit;
0300     }
0301 
0302     if (val < 0 || val >= RIO_MAX_MPORTS)
0303         return -EINVAL;
0304 
0305     rc = rio_mport_scan((int)val);
0306 exit:
0307     if (!rc)
0308         rc = count;
0309 
0310     return rc;
0311 }
0312 static BUS_ATTR_WO(scan);
0313 
0314 static struct attribute *rio_bus_attrs[] = {
0315     &bus_attr_scan.attr,
0316     NULL,
0317 };
0318 
0319 static const struct attribute_group rio_bus_group = {
0320     .attrs = rio_bus_attrs,
0321 };
0322 
0323 const struct attribute_group *rio_bus_groups[] = {
0324     &rio_bus_group,
0325     NULL,
0326 };
0327 
0328 static ssize_t
0329 port_destid_show(struct device *dev, struct device_attribute *attr,
0330          char *buf)
0331 {
0332     struct rio_mport *mport = to_rio_mport(dev);
0333 
0334     if (mport)
0335         return sprintf(buf, "0x%04x\n", mport->host_deviceid);
0336     else
0337         return -ENODEV;
0338 }
0339 static DEVICE_ATTR_RO(port_destid);
0340 
0341 static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr,
0342                char *buf)
0343 {
0344     struct rio_mport *mport = to_rio_mport(dev);
0345 
0346     if (mport)
0347         return sprintf(buf, "%u\n", mport->sys_size);
0348     else
0349         return -ENODEV;
0350 }
0351 static DEVICE_ATTR_RO(sys_size);
0352 
0353 static struct attribute *rio_mport_attrs[] = {
0354     &dev_attr_port_destid.attr,
0355     &dev_attr_sys_size.attr,
0356     NULL,
0357 };
0358 
0359 static const struct attribute_group rio_mport_group = {
0360     .attrs = rio_mport_attrs,
0361 };
0362 
0363 const struct attribute_group *rio_mport_groups[] = {
0364     &rio_mport_group,
0365     NULL,
0366 };