# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.651 -> 1.652 # drivers/usb/hcd.h 1.2 -> 1.3 # drivers/usb/usb-ohci.c 1.28 -> 1.29 # drivers/usb/uhci.c 1.30 -> 1.31 # drivers/usb/hc_sl811.c 1.1 -> 1.2 # include/linux/usb.h 1.15 -> 1.16 # drivers/usb/devices.c 1.7 -> 1.8 # drivers/usb/usb-uhci.c 1.26 -> 1.27 # drivers/usb/hcd.c 1.4 -> 1.5 # drivers/usb/hub.c 1.17 -> 1.18 # drivers/usb/usb.c 1.23 -> 1.24 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/09/12 david-b@pacbell.net 1.652 # [PATCH] usbcore updates # # This basically lets the latest 2.5 ehci-hcd driver compile # in a 2.4 kernel by slightly enriching the API exposed # by usbcore: # # - Some symbols were renamed; in 2.4 transitional APIs, # drivers can prefer these #defines to the older symbols: # * URB_SHORT_NOT_OK ... use instead of USB_DISABLE_SPD # * usb_iso_packet_descriptor ... needs "usb_" prefix # - usb_make_path() support (topological/physical/stable ids) # * bus->bus_name (provided during hcd init) # * dev->devpath (save what hub code threw away) # - bandwidth related symbols out of # * they're only provided for hcds # * exported/updated usb_calc_bandwidth() # - some stuff that only hcd drivers will care about # * internal symbols (and urb->*_dma, internal until 2.5) # * remove pci latency bogosity # # Note that the 2.5 HCDs won't yet _work_ yet if anyone brings # them back to 2.4 (note the FIXMEs in this patch, and there's # a bit more). But this a big step towards making it possible # to have the same (host controller) drivers running on both # kernels, and can help some of other usb device drivers too. # -------------------------------------------- # diff -Nru a/drivers/usb/devices.c b/drivers/usb/devices.c --- a/drivers/usb/devices.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/devices.c Thu Sep 12 16:25:44 2002 @@ -61,6 +61,8 @@ #include #include +#include "hcd.h" + #define MAX_TOPO_LEVEL 6 /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ diff -Nru a/drivers/usb/hc_sl811.c b/drivers/usb/hc_sl811.c --- a/drivers/usb/hc_sl811.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/hc_sl811.c Thu Sep 12 16:25:44 2002 @@ -1162,6 +1162,7 @@ } hci->bus = bus; + bus->bus_name = "sl811"; bus->hcpriv = (void *) hci; return hci; diff -Nru a/drivers/usb/hcd.c b/drivers/usb/hcd.c --- a/drivers/usb/hcd.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/hcd.c Thu Sep 12 16:25:44 2002 @@ -56,7 +56,8 @@ * USB Host Controller Driver framework * * Plugs into usbcore (usb_bus) and lets HCDs share code, minimizing - * HCD-specific behaviors/bugs. + * HCD-specific behaviors/bugs. Think of it as the "upper level" of + * some drivers, where the "lower level" is hardware-specific. * * This does error checks, tracks devices and urbs, and delegates to a * "hc_driver" only for code (and data) that really needs to know about @@ -78,6 +79,9 @@ * Roman Weissgaerber, Rory Bolt, ... * * HISTORY: + * 2002-sept Merge some 2.5 updates so we can share hardware level HCD + * code between the 2.4.20+ and 2.5 trees. + * 2002-feb merge to 2.4.19 * 2001-12-12 Initial patch version for Linux 2.5.1 kernel. */ @@ -583,7 +587,6 @@ struct hc_driver *driver; unsigned long resource, len; void *base; - u8 latency, limit; struct usb_bus *bus; struct usb_hcd *hcd; int retval, region; @@ -662,15 +665,6 @@ hcd->pdev = dev; info ("%s @ %s, %s", hcd->description, dev->slot_name, dev->name); - pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); - if (latency) { - pci_read_config_byte (dev, PCI_MAX_LAT, &limit); - if (limit && limit < latency) { - dbg ("PCI latency reduced to max %d", limit); - pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit); - } - } - #ifndef __sparc__ sprintf (buf, "%d", dev->irq); #else @@ -701,7 +695,8 @@ goto clean_3; } hcd->bus = bus; - hcd->bus_name = dev->slot_name; + hcd->bus_name = dev->slot_name; /* prefer bus->bus_name */ + bus->bus_name = dev->slot_name; hcd->product_desc = dev->name; bus->hcpriv = (void *) hcd; @@ -1072,6 +1067,8 @@ if (urb->transfer_buffer_length < 0) return -EINVAL; + // FIXME set urb->transfer_dma and/or setup_dma + if (urb->next) { warn ("use explicit queuing not urb->next"); return -EINVAL; @@ -1462,6 +1459,8 @@ if (urb->status) dbg ("giveback urb %p status %d len %d", urb, urb->status, urb->actual_length); + + // FIXME unmap urb->transfer_dma and/or setup_dma /* pass ownership to the completion handler */ urb->complete (urb); diff -Nru a/drivers/usb/hcd.h b/drivers/usb/hcd.h --- a/drivers/usb/hcd.h Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/hcd.h Thu Sep 12 16:25:44 2002 @@ -153,6 +153,7 @@ #ifdef CONFIG_PCI +struct pci_device_id; extern int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id); extern void usb_hcd_pci_remove (struct pci_dev *dev); @@ -206,6 +207,54 @@ /*-------------------------------------------------------------------------*/ +/* + * Generic bandwidth allocation constants/support + */ +#define FRAME_TIME_USECS 1000L +#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ + /* Trying not to use worst-case bit-stuffing + of (7/6 * 8 * bytecount) = 9.33 * bytecount */ + /* bytecount = data payload byte count */ + +#define NS_TO_US(ns) ((ns + 500L) / 1000L) + /* convert & round nanoseconds to microseconds */ + +extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, + int bustime, int isoc); +extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, + int isoc); + +/* + * Full/low speed bandwidth allocation constants/support. + */ +#define BW_HOST_DELAY 1000L /* nanoseconds */ +#define BW_HUB_LS_SETUP 333L /* nanoseconds */ + /* 4 full-speed bit times (est.) */ + +#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ +#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) +#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) + +extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); + +/* + * Ceiling microseconds (typical) for that many bytes at high speed + * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed + * to preallocate bandwidth) + */ +#define USB2_HOST_DELAY 5 /* nsec, guess */ +#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \ + + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + + USB2_HOST_DELAY) +#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \ + + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + + USB2_HOST_DELAY) + +extern long usb_calc_bus_time (int speed, int is_input, + int isoc, int bytecount); + +/*-------------------------------------------------------------------------*/ + /* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ // bleech -- resurfaced in 2.4.11 or 2.4.12 #define bitmap DeviceRemovable @@ -217,3 +266,20 @@ #define RUN_CONTEXT (in_irq () ? "in_irq" \ : (in_interrupt () ? "in_interrupt" : "can sleep")) + +/* 2.5 changes ... */ + +#ifndef container_of +#define container_of list_entry +#endif + +#define usb_get_urb(x) (x) +#define usb_put_urb(x) + +static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) + { return hcd->bus; } + +static inline void +usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe) + { } + diff -Nru a/drivers/usb/hub.c b/drivers/usb/hub.c --- a/drivers/usb/hub.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/hub.c Thu Sep 12 16:25:44 2002 @@ -678,7 +678,6 @@ struct usb_device *dev; unsigned int delay = HUB_SHORT_RESET_TIME; int i; - char *portstr, *tempstr; dbg("port %d, portstatus %x, change %x, %s", port + 1, portstatus, portchange, portspeed (portstatus)); @@ -706,11 +705,9 @@ down(&usb_address0_sem); - tempstr = kmalloc(1024, GFP_KERNEL); - portstr = kmalloc(1024, GFP_KERNEL); - for (i = 0; i < HUB_PROBE_TRIES; i++) { - struct usb_device *pdev, *cdev; + struct usb_device *pdev; + int len; /* Allocate a new device struct */ dev = usb_alloc_dev(hub, hub->bus); @@ -740,32 +737,28 @@ dev->ttport = port + 1; } - /* Create a readable topology string */ - cdev = dev; + /* Save readable and stable topology id, distinguishing + * devices by location for diagnostics, tools, etc. The + * string is a path along hub ports, from the root. Each + * device's id will be stable until USB is re-cabled, and + * hubs are often labeled with these port numbers. + * + * Initial size: ".NN" times five hubs + NUL = 16 bytes max + * (quite rare, since most hubs have 4-6 ports). + */ pdev = dev->parent; - if (portstr && tempstr) { - portstr[0] = 0; - while (pdev) { - int port; - - for (port = 0; port < pdev->maxchild; port++) - if (pdev->children[port] == cdev) - break; - - strcpy(tempstr, portstr); - if (!strlen(tempstr)) - sprintf(portstr, "%d", port + 1); - else - sprintf(portstr, "%d/%s", port + 1, tempstr); - - cdev = pdev; - pdev = pdev->parent; - } - info("USB new device connect on bus%d/%s, assigned device number %d", - dev->bus->busnum, portstr, dev->devnum); - } else - info("USB new device connect on bus%d, assigned device number %d", - dev->bus->busnum, dev->devnum); + if (pdev->devpath [0] != '0') /* parent not root? */ + len = snprintf (dev->devpath, sizeof dev->devpath, + "%s.%d", pdev->devpath, port + 1); + /* root == "0", root port 2 == "2", port 3 that hub "2.3" */ + else + len = snprintf (dev->devpath, sizeof dev->devpath, + "%d", port + 1); + if (len == sizeof dev->devpath) + warn ("devpath size! usb/%03d/%03d path %s", + dev->bus->busnum, dev->devnum, dev->devpath); + info("new USB device %s-%s, assigned address %d", + dev->bus->bus_name, dev->devpath, dev->devnum); /* Run it through the hoops (find a driver, etc) */ if (!usb_new_device(dev)) @@ -782,10 +775,6 @@ usb_hub_port_disable(hub, port); done: up(&usb_address0_sem); - if (portstr) - kfree(portstr); - if (tempstr) - kfree(tempstr); } static void usb_hub_events(void) diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c --- a/drivers/usb/uhci.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/uhci.c Thu Sep 12 16:25:44 2002 @@ -57,6 +57,8 @@ #include +#include "hcd.h" + /* * Version Information */ @@ -2797,6 +2799,7 @@ } uhci->bus = bus; + bus->bus_name = dev->slot_name; bus->hcpriv = uhci; usb_register_bus(uhci->bus); diff -Nru a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c --- a/drivers/usb/usb-ohci.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/usb-ohci.c Thu Sep 12 16:25:44 2002 @@ -78,6 +78,7 @@ #include "usb-ohci.h" +#include "hcd.h" #ifdef CONFIG_PMAC_PBOOK #include @@ -2413,6 +2414,7 @@ kfree (ohci); return NULL; } + ohci->bus->bus_name = dev->slot_name; ohci->bus->hcpriv = (void *) ohci; return ohci; @@ -2470,7 +2472,6 @@ void *mem_base, const struct pci_device_id *id) { ohci_t * ohci; - u8 latency, limit; char buf[8], *bufp = buf; int ret; @@ -2509,20 +2510,6 @@ printk (KERN_INFO __FILE__ ": Using NSC SuperIO setup\n"); if (ohci->flags & OHCI_QUIRK_AMD756) printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n"); - - /* bad pci latencies can contribute to overruns */ - pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); - if (latency) { - pci_read_config_byte (dev, PCI_MAX_LAT, &limit); - if (limit && limit < latency) { - dbg ("PCI latency reduced to max %d", limit); - pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit); - ohci->pci_latency = limit; - } else { - /* it might already have been reduced */ - ohci->pci_latency = latency; - } - } if (hc_reset (ohci) < 0) { hc_release_ohci (ohci); diff -Nru a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c --- a/drivers/usb/usb-uhci.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/usb-uhci.c Thu Sep 12 16:25:44 2002 @@ -59,6 +59,8 @@ #include "usb-uhci.h" #include "usb-uhci-debug.h" +#include "hcd.h" + /* * Version Information */ @@ -2952,6 +2954,7 @@ } s->bus = bus; + bus->bus_name = dev->slot_name; bus->hcpriv = s; /* UHCI specs says devices must have 2 ports, but goes on to say */ diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c --- a/drivers/usb/usb.c Thu Sep 12 16:25:44 2002 +++ b/drivers/usb/usb.c Thu Sep 12 16:25:44 2002 @@ -38,6 +38,8 @@ #endif #include +#include "hcd.h" + static const int usb_bandwidth_option = #ifdef CONFIG_USB_BANDWIDTH 1; @@ -218,42 +220,51 @@ } /* - * usb_calc_bus_time: - * - * returns (approximate) USB bus time in nanoseconds for a USB transaction. + * usb_calc_bus_time - approximate periodic transaction time in nanoseconds + * @speed: from dev->speed; USB_SPEED_{LOW,FULL,HIGH} + * @is_input: true iff the transaction sends data to the host + * @isoc: true for isochronous transactions, false for interrupt ones + * @bytecount: how many bytes in the transaction. + * + * Returns approximate bus time in nanoseconds for a periodic transaction. + * See USB 2.0 spec section 5.11.3; only periodic transfers need to be + * scheduled in software, this function is only used for such scheduling. */ -static long usb_calc_bus_time (int low_speed, int input_dir, int isoc, int bytecount) +long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) { unsigned long tmp; - if (low_speed) /* no isoc. here */ - { - if (input_dir) - { + switch (speed) { + case USB_SPEED_LOW: /* INTR only */ + if (is_input) { tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); - } - else - { + } else { tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); } + case USB_SPEED_FULL: /* ISOC or INTR */ + if (isoc) { + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); + } else { + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (9107L + BW_HOST_DELAY + tmp); + } + case USB_SPEED_HIGH: /* ISOC or INTR */ + // FIXME adjust for input vs output + if (isoc) + tmp = HS_USECS (bytecount); + else + tmp = HS_USECS_ISO (bytecount); + return tmp; + default: + dbg ("bogus device speed!"); + return -1; } - - /* for full-speed: */ - - if (!isoc) /* Input or Output */ - { - tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (9107L + BW_HOST_DELAY + tmp); - } /* end not Isoc */ - - /* for isoc: */ - - tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); } + /* * usb_check_bandwidth(): * @@ -285,7 +296,7 @@ unsigned int pipe = urb->pipe; long bustime; - bustime = usb_calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe), + bustime = usb_calc_bus_time (dev->speed, usb_pipein(pipe), usb_pipeisoc(pipe), usb_maxpacket(dev, pipe, usb_pipeout(pipe))); if (usb_pipeisoc(pipe)) bustime = NS_TO_US(bustime) / urb->number_of_packets; @@ -939,6 +950,9 @@ usb_bus_get(bus); + if (!parent) + dev->devpath [0] = '0'; + dev->bus = bus; dev->parent = parent; atomic_set(&dev->refcnt, 1); @@ -1699,7 +1713,8 @@ *pdev = NULL; - info("USB disconnect on device %d", dev->devnum); + info("USB disconnect on device %s-%s address %d", + dev->bus->bus_name, dev->devpath, dev->devnum); if (dev->actconfig) { for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { @@ -2393,6 +2408,7 @@ EXPORT_SYMBOL(usb_connect); EXPORT_SYMBOL(usb_disconnect); +EXPORT_SYMBOL(usb_calc_bus_time); EXPORT_SYMBOL(usb_check_bandwidth); EXPORT_SYMBOL(usb_claim_bandwidth); EXPORT_SYMBOL(usb_release_bandwidth); diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Thu Sep 12 16:25:44 2002 +++ b/include/linux/usb.h Thu Sep 12 16:25:44 2002 @@ -437,6 +437,7 @@ * urb->transfer_flags: */ #define USB_DISABLE_SPD 0x0001 +#define URB_SHORT_NOT_OK USB_DISABLE_SPD #define USB_ISO_ASAP 0x0002 #define USB_ASYNC_UNLINK 0x0008 #define USB_QUEUE_BULK 0x0010 @@ -454,6 +455,8 @@ unsigned int status; }; +#define usb_iso_packet_descriptor iso_packet_descriptor + struct urb; typedef void (*usb_complete_t)(struct urb *); @@ -468,10 +471,12 @@ int status; // returned status unsigned int transfer_flags; // USB_DISABLE_SPD | USB_ISO_ASAP | etc. void *transfer_buffer; // associated data buffer + dma_addr_t transfer_dma; // dma addr for transfer_buffer int transfer_buffer_length; // data buffer length int actual_length; // actual data buffer length int bandwidth; // bandwidth for this transfer request (INT or ISO) unsigned char *setup_packet; // setup packet (control only) + dma_addr_t setup_dma; // dma addr for setup_packet // int start_frame; // start frame (iso/irq only) int number_of_packets; // number of packets in this request (iso) @@ -723,6 +728,7 @@ */ struct usb_bus { int busnum; /* Bus number (in order of reg) */ + char *bus_name; /* stable id (PCI slot_name etc) */ #ifdef DEVNUM_ROUND_ROBIN int devnum_next; /* Next open device number in round-robin allocation */ @@ -771,7 +777,8 @@ #define USB_MAXCHILDREN (16) struct usb_device { - int devnum; /* Device number on USB bus */ + int devnum; /* Address on USB bus */ + char devpath [16]; /* Use in messages: /port/port/... */ enum { USB_SPEED_UNKNOWN = 0, /* enumerating */ @@ -846,10 +853,6 @@ extern void usb_inc_dev_use(struct usb_device *); #define usb_dec_dev_use usb_free_dev -extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); -extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc); -extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc); - extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); extern int usb_root_hub_string(int id, int serial, char *type, __u8 *data, int len); @@ -860,6 +863,42 @@ int usb_get_current_frame_number (struct usb_device *usb_dev); + +/** + * usb_make_path - returns stable device path in the usb tree + * @dev: the device whose path is being constructed + * @buf: where to put the string + * @size: how big is "buf"? + * + * Returns length of the string (> 0) or negative if size was too small. + * + * This identifier is intended to be "stable", reflecting physical paths in + * hardware such as physical bus addresses for host controllers or ports on + * USB hubs. That makes it stay the same until systems are physically + * reconfigured, by re-cabling a tree of USB devices or by moving USB host + * controllers. Adding and removing devices, including virtual root hubs + * in host controller driver modules, does not change these path identifers; + * neither does rebooting or re-enumerating. These are more useful identifiers + * than changeable ("unstable") ones like bus numbers or device addresses. + * (The stability of the id depends on stability of the bus_name associated + * with the bus the device uses; that is normally stable.) + * + * With a partial exception for devices connected to USB 2.0 root hubs, these + * identifiers are also predictable. So long as the device tree isn't changed, + * plugging any USB device into a given hub port always gives it the same path. + * Because of the use of "companion" controllers, devices connected to ports on + * USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are + * high speed, and a different one if they are full or low speed. + */ +static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size) +{ + int actual; + actual = snprintf (buf, size, "usb-%s-%s", + dev->bus->bus_name, dev->devpath); + return (actual >= size) ? -1 : actual; +} + + /* * Calling this entity a "pipe" is glorifying it. A USB pipe * is something embarrassingly simple: it basically consists @@ -984,26 +1023,6 @@ #define usb_get_extra_descriptor(ifpoint,type,ptr)\ __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,type,(void**)ptr) - -/* - * Some USB bandwidth allocation constants. - */ -#define BW_HOST_DELAY 1000L /* nanoseconds */ -#define BW_HUB_LS_SETUP 333L /* nanoseconds */ - /* 4 full-speed bit times (est.) */ - -#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ -#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) -#define FRAME_TIME_USECS 1000L -#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) - -#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ - /* Trying not to use worst-case bit-stuffing - of (7/6 * 8 * bytecount) = 9.33 * bytecount */ - /* bytecount = data payload byte count */ - -#define NS_TO_US(ns) ((ns + 500L) / 1000L) - /* convert & round nanoseconds to microseconds */ /* * Debugging helpers..