patch-2.4.20 linux-2.4.20/drivers/usb/uhci.c
Next file: linux-2.4.20/drivers/usb/uhci.h
Previous file: linux-2.4.20/drivers/usb/tiglusb.h
Back to the patch index
Back to the overall index
- Lines: 248
- Date:
Thu Nov 28 15:53:15 2002
- Orig file:
linux-2.4.19/drivers/usb/uhci.c
- Orig date:
Fri Aug 2 17:39:45 2002
diff -urN linux-2.4.19/drivers/usb/uhci.c linux-2.4.20/drivers/usb/uhci.c
@@ -57,6 +57,8 @@
#include <linux/pm.h>
+#include "hcd.h"
+
/*
* Version Information
*/
@@ -100,6 +102,11 @@
#define IDLE_TIMEOUT (HZ / 20) /* 50 ms */
#define FSBR_DELAY (HZ / 20) /* 50 ms */
+/* When we timeout an idle transfer for FSBR, we'll switch it over to */
+/* depth first traversal. We'll do it in groups of this number of TD's */
+/* to make sure it doesn't hog all of the bandwidth */
+#define DEPTH_INTERVAL 5
+
#define MAX_URB_LOOP 2048 /* Maximum number of linked URB's */
/*
@@ -115,12 +122,20 @@
return 0;
}
+/*
+ * Technically, updating td->status here is a race, but it's not really a
+ * problem. The worst that can happen is that we set the IOC bit again
+ * generating a spurios interrupt. We could fix this by creating another
+ * QH and leaving the IOC bit always set, but then we would have to play
+ * games with the FSBR code to make sure we get the correct order in all
+ * the cases. I don't think it's worth the effort
+ */
static inline void uhci_set_next_interrupt(struct uhci *uhci)
{
unsigned long flags;
spin_lock_irqsave(&uhci->frame_list_lock, flags);
- set_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
+ uhci->skel_term_td->status |= TD_CTRL_IOC;
spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
}
@@ -129,7 +144,7 @@
unsigned long flags;
spin_lock_irqsave(&uhci->frame_list_lock, flags);
- clear_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
+ uhci->skel_term_td->status &= ~TD_CTRL_IOC;
spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
}
@@ -474,9 +489,9 @@
tmp = tmp->next;
if (toggle)
- set_bit(TD_TOKEN_TOGGLE, &td->info);
+ td->info |= TD_TOKEN_TOGGLE;
else
- clear_bit(TD_TOKEN_TOGGLE, &td->info);
+ td->info &= ~TD_TOKEN_TOGGLE;
toggle ^= 1;
}
@@ -649,7 +664,7 @@
if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
- urb->setup_packet, sizeof(devrequest),
+ urb->setup_packet, sizeof(struct usb_ctrlrequest),
PCI_DMA_TODEVICE);
if (!urbp->setup_packet_dma_handle)
return NULL;
@@ -724,7 +739,7 @@
if (urbp->setup_packet_dma_handle) {
pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
- sizeof(devrequest), PCI_DMA_TODEVICE);
+ sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
urbp->setup_packet_dma_handle = 0;
}
@@ -857,7 +872,7 @@
return -ENOMEM;
/* Alternate Data0/1 (start with Data1) */
- destination ^= 1 << TD_TOKEN_TOGGLE;
+ destination ^= TD_TOKEN_TOGGLE;
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | ((pktsze - 1) << 21),
@@ -884,7 +899,7 @@
else
destination |= USB_PID_OUT;
- destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */
+ destination |= TD_TOKEN_TOGGLE; /* End in Data1 */
status &= ~TD_CTRL_SPD;
@@ -953,14 +968,6 @@
tmp = tmp->next;
- if (urbp->fsbr_timeout && (td->status & TD_CTRL_IOC) &&
- !(td->status & TD_CTRL_ACTIVE)) {
- uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
- urbp->fsbr_timeout = 0;
- urbp->fsbrtime = jiffies;
- clear_bit(TD_CTRL_IOC_BIT, &td->status);
- }
-
status = uhci_status_bits(td->status);
if (status & TD_CTRL_ACTIVE)
return -EINPROGRESS;
@@ -1097,7 +1104,7 @@
if (!td)
return -ENOMEM;
- destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+ destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT);
destination |= ((urb->transfer_buffer_length - 1) << 21);
usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
@@ -1127,14 +1134,6 @@
tmp = tmp->next;
- if (urbp->fsbr_timeout && (td->status & TD_CTRL_IOC) &&
- !(td->status & TD_CTRL_ACTIVE)) {
- uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
- urbp->fsbr_timeout = 0;
- urbp->fsbrtime = jiffies;
- clear_bit(TD_CTRL_IOC_BIT, &td->status);
- }
-
status = uhci_status_bits(td->status);
if (status & TD_CTRL_ACTIVE)
return -EINPROGRESS;
@@ -1198,8 +1197,8 @@
td = list_entry(urbp->td_list.next, struct uhci_td, list);
td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
- td->info &= ~(1 << TD_TOKEN_TOGGLE);
- td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+ td->info &= ~TD_TOKEN_TOGGLE;
+ td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT);
usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
out:
@@ -1255,7 +1254,7 @@
uhci_fill_td(td, status, destination |
(((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
+ usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
data += pktsze;
@@ -1283,7 +1282,7 @@
uhci_fill_td(td, status, destination |
(UHCI_NULL_DATA_SIZE << 21) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
+ usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
@@ -1830,11 +1829,18 @@
{
struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
struct list_head *head, *tmp;
+ int count = 0;
uhci_dec_fsbr(uhci, urb);
urbp->fsbr_timeout = 1;
+ /*
+ * Ideally we would want to fix qh->element as well, but it's
+ * read/write by the HC, so that can introduce a race. It's not
+ * really worth the hassle
+ */
+
head = &urbp->td_list;
tmp = head->next;
while (tmp != head) {
@@ -1842,10 +1848,15 @@
tmp = tmp->next;
- if (td->status & TD_CTRL_ACTIVE) {
- set_bit(TD_CTRL_IOC_BIT, &td->status);
- break;
- }
+ /*
+ * Make sure we don't do the last one (since it'll have the
+ * TERM bit set) as well as we skip every so many TD's to
+ * make sure it doesn't hog the bandwidth
+ */
+ if (tmp != head && (count % DEPTH_INTERVAL) == (DEPTH_INTERVAL - 1))
+ td->link |= UHCI_PTR_DEPTH;
+
+ count++;
}
return 0;
@@ -2073,7 +2084,7 @@
{
struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
unsigned int pipe = urb->pipe;
- devrequest *cmd = (devrequest *)urb->setup_packet;
+ struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet;
void *data = urb->transfer_buffer;
int leni = urb->transfer_buffer_length;
int len = 0;
@@ -2096,10 +2107,10 @@
return -EINPROGRESS;
}
- bmRType_bReq = cmd->requesttype | cmd->request << 8;
- wValue = le16_to_cpu(cmd->value);
- wIndex = le16_to_cpu(cmd->index);
- wLength = le16_to_cpu(cmd->length);
+ bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
+ wValue = le16_to_cpu(cmd->wValue);
+ wIndex = le16_to_cpu(cmd->wIndex);
+ wLength = le16_to_cpu(cmd->wLength);
for (i = 0; i < 8; i++)
uhci->rh.c_p_r[i] = 0;
@@ -2340,7 +2351,7 @@
if (urbp->setup_packet_dma_handle)
pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
- sizeof(devrequest), PCI_DMA_TODEVICE);
+ sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
status = urbp->status;
if (!resubmit_interrupt || killed)
@@ -2788,6 +2799,7 @@
}
uhci->bus = bus;
+ bus->bus_name = dev->slot_name;
bus->hcpriv = uhci;
usb_register_bus(uhci->bus);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)