14c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov/* 24c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * Copyright (C) 2007 by Alan Stern 34c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * 44c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * This program is free software; you can redistribute it and/or modify it 54c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * under the terms of the GNU General Public License as published by the 64c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * Free Software Foundation; either version 2 of the License, or (at your 74c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * option) any later version. 84c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * 94c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * This program is distributed in the hope that it will be useful, but 104c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 114c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 124c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * for more details. 134c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * 144c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * You should have received a copy of the GNU General Public License 154c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * along with this program; if not, write to the Free Software Foundation, 164c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 174c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov */ 184c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 194c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov/* this file is part of ehci-hcd.c */ 204c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 214c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 224c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov/* Display the ports dedicated to the companion controller */ 234c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkovstatic ssize_t show_companion(struct device *dev, 244c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov struct device_attribute *attr, 254c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov char *buf) 264c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov{ 274c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov struct ehci_hcd *ehci; 284c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov int nports, index, n; 294c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov int count = PAGE_SIZE; 304c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov char *ptr = buf; 314c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 324c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); 334c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov nports = HCS_N_PORTS(ehci->hcs_params); 344c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 354c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov for (index = 0; index < nports; ++index) { 364c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov if (test_bit(index, &ehci->companion_ports)) { 374c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov n = scnprintf(ptr, count, "%d\n", index + 1); 384c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov ptr += n; 394c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov count -= n; 404c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov } 414c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov } 424c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov return ptr - buf; 434c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov} 444c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 454c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov/* 464c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * Dedicate or undedicate a port to the companion controller. 474c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * Syntax is "[-]portnum", where a leading '-' sign means 484c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov * return control of the port to the EHCI controller. 494c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov */ 504c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkovstatic ssize_t store_companion(struct device *dev, 514c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov struct device_attribute *attr, 524c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov const char *buf, size_t count) 534c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov{ 544c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov struct ehci_hcd *ehci; 554c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov int portnum, new_owner; 564c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 574c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); 584c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov new_owner = PORT_OWNER; /* Owned by companion */ 594c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov if (sscanf(buf, "%d", &portnum) != 1) 604c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov return -EINVAL; 614c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov if (portnum < 0) { 624c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov portnum = - portnum; 634c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov new_owner = 0; /* Owned by EHCI */ 644c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov } 654c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) 664c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov return -ENOENT; 674c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov portnum--; 684c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov if (new_owner) 694c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov set_bit(portnum, &ehci->companion_ports); 704c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov else 714c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov clear_bit(portnum, &ehci->companion_ports); 724c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov set_owner(ehci, portnum, new_owner); 734c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov return count; 744c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov} 754c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkovstatic DEVICE_ATTR(companion, 0644, show_companion, store_companion); 764c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 77cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 78cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov/* 79cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov * Display / Set uframe_periodic_max 80cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov */ 81cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkovstatic ssize_t show_uframe_periodic_max(struct device *dev, 82cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov struct device_attribute *attr, 83cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov char *buf) 84cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov{ 85cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov struct ehci_hcd *ehci; 86cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov int n; 87cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 88cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); 89cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max); 90cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov return n; 91cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov} 92cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 93cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 94cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkovstatic ssize_t store_uframe_periodic_max(struct device *dev, 95cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov struct device_attribute *attr, 96cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov const char *buf, size_t count) 97cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov{ 98cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov struct ehci_hcd *ehci; 99cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov unsigned uframe_periodic_max; 100d0ce5c6b9208c79fc725c578eebdeb5724faf17dAlan Stern unsigned uframe; 101cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov unsigned long flags; 102cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ssize_t ret; 103cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 104cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); 105cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) 106cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov return -EINVAL; 107cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 108cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { 109cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ehci_info(ehci, "rejecting invalid request for " 110cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov "uframe_periodic_max=%u\n", uframe_periodic_max); 111cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov return -EINVAL; 112cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov } 113cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 114cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ret = -EINVAL; 115cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 116cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov /* 117cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov * lock, so that our checking does not race with possible periodic 118cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov * bandwidth allocation through submitting new urbs. 119cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov */ 120cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov spin_lock_irqsave (&ehci->lock, flags); 121cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 122cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov /* 123cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov * for request to decrease max periodic bandwidth, we have to check 124d0ce5c6b9208c79fc725c578eebdeb5724faf17dAlan Stern * to see whether the decrease is possible. 125cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov */ 126cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov if (uframe_periodic_max < ehci->uframe_periodic_max) { 127d0ce5c6b9208c79fc725c578eebdeb5724faf17dAlan Stern u8 allocated_max = 0; 128cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 129d0ce5c6b9208c79fc725c578eebdeb5724faf17dAlan Stern for (uframe = 0; uframe < EHCI_BANDWIDTH_SIZE; ++uframe) 130d0ce5c6b9208c79fc725c578eebdeb5724faf17dAlan Stern allocated_max = max(allocated_max, 131d0ce5c6b9208c79fc725c578eebdeb5724faf17dAlan Stern ehci->bandwidth[uframe]); 132cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 133cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov if (allocated_max > uframe_periodic_max) { 134cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ehci_info(ehci, 135cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov "cannot decrease uframe_periodic_max becase " 136cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov "periodic bandwidth is already allocated " 137cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov "(%u > %u)\n", 138cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov allocated_max, uframe_periodic_max); 139cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov goto out_unlock; 140cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov } 141cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov } 142cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 143cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov /* increasing is always ok */ 144cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 145cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ehci_info(ehci, "setting max periodic bandwidth to %u%% " 146cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov "(== %u usec/uframe)\n", 147cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 100*uframe_periodic_max/125, uframe_periodic_max); 148cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 149cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov if (uframe_periodic_max != 100) 150cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ehci_warn(ehci, "max periodic bandwidth set is non-standard\n"); 151cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 152cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ehci->uframe_periodic_max = uframe_periodic_max; 153cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov ret = count; 154cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 155cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkovout_unlock: 156cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov spin_unlock_irqrestore (&ehci->lock, flags); 157cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov return ret; 158cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov} 159cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkovstatic DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max); 160cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 161cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 1624c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkovstatic inline int create_sysfs_files(struct ehci_hcd *ehci) 1634c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov{ 164cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov struct device *controller = ehci_to_hcd(ehci)->self.controller; 1654c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov int i = 0; 1664c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 1674c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov /* with integrated TT there is no companion! */ 1684c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov if (!ehci_is_TDI(ehci)) 169cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov i = device_create_file(controller, &dev_attr_companion); 170cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov if (i) 171cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov goto out; 172cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 173cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov i = device_create_file(controller, &dev_attr_uframe_periodic_max); 174cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkovout: 1754c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov return i; 1764c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov} 1774c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov 1784c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkovstatic inline void remove_sysfs_files(struct ehci_hcd *ehci) 1794c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov{ 180cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov struct device *controller = ehci_to_hcd(ehci)->self.controller; 181cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 1824c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov /* with integrated TT there is no companion! */ 1834c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov if (!ehci_is_TDI(ehci)) 184cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov device_remove_file(controller, &dev_attr_companion); 185cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov 186cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov device_remove_file(controller, &dev_attr_uframe_periodic_max); 1874c67045bfc2c14a1d3c6040e80eb4a62946282ddKirill Smelkov} 188