root/drivers/usb/host/ehci-sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. companion_show
  2. companion_store
  3. uframe_periodic_max_show
  4. uframe_periodic_max_store
  5. create_sysfs_files
  6. remove_sysfs_files

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright (C) 2007 by Alan Stern
   4  */
   5 
   6 /* this file is part of ehci-hcd.c */
   7 
   8 
   9 /* Display the ports dedicated to the companion controller */
  10 static ssize_t companion_show(struct device *dev,
  11                               struct device_attribute *attr,
  12                               char *buf)
  13 {
  14         struct ehci_hcd         *ehci;
  15         int                     nports, index, n;
  16         int                     count = PAGE_SIZE;
  17         char                    *ptr = buf;
  18 
  19         ehci = hcd_to_ehci(dev_get_drvdata(dev));
  20         nports = HCS_N_PORTS(ehci->hcs_params);
  21 
  22         for (index = 0; index < nports; ++index) {
  23                 if (test_bit(index, &ehci->companion_ports)) {
  24                         n = scnprintf(ptr, count, "%d\n", index + 1);
  25                         ptr += n;
  26                         count -= n;
  27                 }
  28         }
  29         return ptr - buf;
  30 }
  31 
  32 /*
  33  * Dedicate or undedicate a port to the companion controller.
  34  * Syntax is "[-]portnum", where a leading '-' sign means
  35  * return control of the port to the EHCI controller.
  36  */
  37 static ssize_t companion_store(struct device *dev,
  38                                struct device_attribute *attr,
  39                                const char *buf, size_t count)
  40 {
  41         struct ehci_hcd         *ehci;
  42         int                     portnum, new_owner;
  43 
  44         ehci = hcd_to_ehci(dev_get_drvdata(dev));
  45         new_owner = PORT_OWNER;         /* Owned by companion */
  46         if (sscanf(buf, "%d", &portnum) != 1)
  47                 return -EINVAL;
  48         if (portnum < 0) {
  49                 portnum = - portnum;
  50                 new_owner = 0;          /* Owned by EHCI */
  51         }
  52         if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
  53                 return -ENOENT;
  54         portnum--;
  55         if (new_owner)
  56                 set_bit(portnum, &ehci->companion_ports);
  57         else
  58                 clear_bit(portnum, &ehci->companion_ports);
  59         set_owner(ehci, portnum, new_owner);
  60         return count;
  61 }
  62 static DEVICE_ATTR_RW(companion);
  63 
  64 
  65 /*
  66  * Display / Set uframe_periodic_max
  67  */
  68 static ssize_t uframe_periodic_max_show(struct device *dev,
  69                                         struct device_attribute *attr,
  70                                         char *buf)
  71 {
  72         struct ehci_hcd         *ehci;
  73         int                     n;
  74 
  75         ehci = hcd_to_ehci(dev_get_drvdata(dev));
  76         n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max);
  77         return n;
  78 }
  79 
  80 
  81 static ssize_t uframe_periodic_max_store(struct device *dev,
  82                                         struct device_attribute *attr,
  83                                         const char *buf, size_t count)
  84 {
  85         struct ehci_hcd         *ehci;
  86         unsigned                uframe_periodic_max;
  87         unsigned                uframe;
  88         unsigned long           flags;
  89         ssize_t                 ret;
  90 
  91         ehci = hcd_to_ehci(dev_get_drvdata(dev));
  92         if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
  93                 return -EINVAL;
  94 
  95         if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
  96                 ehci_info(ehci, "rejecting invalid request for "
  97                                 "uframe_periodic_max=%u\n", uframe_periodic_max);
  98                 return -EINVAL;
  99         }
 100 
 101         ret = -EINVAL;
 102 
 103         /*
 104          * lock, so that our checking does not race with possible periodic
 105          * bandwidth allocation through submitting new urbs.
 106          */
 107         spin_lock_irqsave (&ehci->lock, flags);
 108 
 109         /*
 110          * for request to decrease max periodic bandwidth, we have to check
 111          * to see whether the decrease is possible.
 112          */
 113         if (uframe_periodic_max < ehci->uframe_periodic_max) {
 114                 u8              allocated_max = 0;
 115 
 116                 for (uframe = 0; uframe < EHCI_BANDWIDTH_SIZE; ++uframe)
 117                         allocated_max = max(allocated_max,
 118                                         ehci->bandwidth[uframe]);
 119 
 120                 if (allocated_max > uframe_periodic_max) {
 121                         ehci_info(ehci,
 122                                 "cannot decrease uframe_periodic_max because "
 123                                 "periodic bandwidth is already allocated "
 124                                 "(%u > %u)\n",
 125                                 allocated_max, uframe_periodic_max);
 126                         goto out_unlock;
 127                 }
 128         }
 129 
 130         /* increasing is always ok */
 131 
 132         ehci_info(ehci, "setting max periodic bandwidth to %u%% "
 133                         "(== %u usec/uframe)\n",
 134                         100*uframe_periodic_max/125, uframe_periodic_max);
 135 
 136         if (uframe_periodic_max != 100)
 137                 ehci_warn(ehci, "max periodic bandwidth set is non-standard\n");
 138 
 139         ehci->uframe_periodic_max = uframe_periodic_max;
 140         ret = count;
 141 
 142 out_unlock:
 143         spin_unlock_irqrestore (&ehci->lock, flags);
 144         return ret;
 145 }
 146 static DEVICE_ATTR_RW(uframe_periodic_max);
 147 
 148 
 149 static inline int create_sysfs_files(struct ehci_hcd *ehci)
 150 {
 151         struct device   *controller = ehci_to_hcd(ehci)->self.controller;
 152         int     i = 0;
 153 
 154         /* with integrated TT there is no companion! */
 155         if (!ehci_is_TDI(ehci))
 156                 i = device_create_file(controller, &dev_attr_companion);
 157         if (i)
 158                 goto out;
 159 
 160         i = device_create_file(controller, &dev_attr_uframe_periodic_max);
 161 out:
 162         return i;
 163 }
 164 
 165 static inline void remove_sysfs_files(struct ehci_hcd *ehci)
 166 {
 167         struct device   *controller = ehci_to_hcd(ehci)->self.controller;
 168 
 169         /* with integrated TT there is no companion! */
 170         if (!ehci_is_TDI(ehci))
 171                 device_remove_file(controller, &dev_attr_companion);
 172 
 173         device_remove_file(controller, &dev_attr_uframe_periodic_max);
 174 }

/* [<][>][^][v][top][bottom][index][help] */