patch-2.4.20 linux-2.4.20/drivers/usb/usb-ohci.c

Next file: linux-2.4.20/drivers/usb/usb-ohci.h
Previous file: linux-2.4.20/drivers/usb/usb-midi.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/drivers/usb/usb-ohci.c linux-2.4.20/drivers/usb/usb-ohci.c
@@ -78,6 +78,7 @@
 
 #include "usb-ohci.h"
 
+#include "hcd.h"
 
 #ifdef CONFIG_PMAC_PBOOK
 #include <asm/machdep.h>
@@ -178,7 +179,7 @@
 	kfree (urb_priv);
 }
  
-static void urb_rm_priv_locked (urb_t * urb) 
+static void urb_rm_priv_locked (struct urb * urb) 
 {
 	urb_priv_t * urb_priv = urb->hcpriv;
 	
@@ -212,7 +213,7 @@
 	}
 }
 
-static void urb_rm_priv (urb_t * urb)
+static void urb_rm_priv (struct urb * urb)
 {
 	unsigned long flags;
 
@@ -229,7 +230,7 @@
 /* debug| print the main components of an URB     
  * small: 0) header + data packets 1) just header */
  
-static void urb_print (urb_t * urb, char * str, int small)
+static void urb_print (struct urb * urb, char * str, int small)
 {
 	unsigned int pipe= urb->pipe;
 	
@@ -384,6 +385,8 @@
 	__u32			temp, ndp, i;
 
 	temp = roothub_a (controller);
+	if (temp == ~(u32)0)
+		return;
 	ndp = (temp & RH_A_NDP);
 
 	if (verbose) {
@@ -458,10 +461,10 @@
 
 /* return a request to the completion handler */
  
-static int sohci_return_urb (struct ohci *hc, urb_t * urb)
+static int sohci_return_urb (struct ohci *hc, struct urb * urb)
 {
 	urb_priv_t * urb_priv = urb->hcpriv;
-	urb_t * urbt;
+	struct urb * urbt;
 	unsigned long flags;
 	int i;
 	
@@ -536,7 +539,7 @@
 
 /* get a transfer request */
  
-static int sohci_submit_urb (urb_t * urb)
+static int sohci_submit_urb (struct urb * urb)
 {
 	ohci_t * ohci;
 	ed_t * ed;
@@ -720,7 +723,7 @@
 /* deactivate all TDs and remove the private part of the URB */
 /* interrupt callers must use async unlink mode */
 
-static int sohci_unlink_urb (urb_t * urb)
+static int sohci_unlink_urb (struct urb * urb)
 {
 	unsigned long flags;
 	ohci_t * ohci;
@@ -1295,7 +1298,7 @@
 static void
 td_fill (ohci_t * ohci, unsigned int info,
 	dma_addr_t data, int len,
-	urb_t * urb, int index)
+	struct urb * urb, int index)
 {
 	volatile td_t  * td, * td_pt;
 	urb_priv_t * urb_priv = urb->hcpriv;
@@ -1344,7 +1347,7 @@
  
 /* prepare all TDs of a transfer */
 
-static void td_submit_urb (urb_t * urb)
+static void td_submit_urb (struct urb * urb)
 { 
 	urb_priv_t * urb_priv = urb->hcpriv;
 	ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv;
@@ -1457,7 +1460,7 @@
 {
 	__u32 tdINFO, tdBE, tdCBP;
  	__u16 tdPSW;
- 	urb_t * urb = td->urb;
+ 	struct urb * urb = td->urb;
  	urb_priv_t * urb_priv = urb->hcpriv;
 	int dlen = 0;
 	int cc = 0;
@@ -1498,7 +1501,7 @@
 
 /* handle an urb that is being unlinked */
 
-static void dl_del_urb (urb_t * urb)
+static void dl_del_urb (struct urb * urb)
 {
 	wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait;
 
@@ -1510,6 +1513,8 @@
 			urb->complete (urb);
 	} else {
 		urb->status = -ENOENT;
+		if (urb->complete)
+			urb->complete (urb);
 
 		/* unblock sohci_unlink_urb */
 		if (wait_head)
@@ -1587,7 +1592,7 @@
 		td_p = &ed->hwHeadP;
 
 		for (td = tdHeadP; td != tdTailP; td = td_next) { 
-			urb_t * urb = td->urb;
+			struct urb * urb = td->urb;
 			urb_priv_t * urb_priv = td->urb->hcpriv;
 			
 			td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
@@ -1626,11 +1631,6 @@
 			if (tdHeadP == tdTailP) {
 				if (ed->state == ED_OPER)
 					ep_unlink(ohci, ed);
-				td_free (ohci, tdTailP);
-				ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP);
-				ed->state = ED_NEW;
-				hash_free_ed(ohci, ed);
-				--(usb_to_ohci (ohci->dev[edINFO & 0x7F]))->ed_cnt;
 			} else
    	 			ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP);
    	 	}
@@ -1675,7 +1675,7 @@
   	td_t * td_list_next = NULL;
 	ed_t * ed;
 	int cc = 0;
-	urb_t * urb;
+	struct urb * urb;
 	urb_priv_t * urb_priv;
  	__u32 tdINFO, edHeadP, edTailP;
  	
@@ -1851,7 +1851,7 @@
 {
 	int len; 
 
-	urb_t * urb = (urb_t *) ptr;
+	struct urb * urb = (struct urb *) ptr;
 	ohci_t * ohci = urb->dev->bus->hcpriv;
 
 	if (ohci->disabled)
@@ -1880,7 +1880,7 @@
 
 /* Root Hub INTs are polled by this timer */
 
-static int rh_init_int_timer (urb_t * urb) 
+static int rh_init_int_timer (struct urb * urb) 
 {
 	ohci_t * ohci = urb->dev->bus->hcpriv;
 
@@ -1905,12 +1905,12 @@
 
 /* request to virtual root hub */
 
-static int rh_submit_urb (urb_t * urb)
+static int rh_submit_urb (struct urb * urb)
 {
 	struct usb_device * usb_dev = urb->dev;
 	ohci_t * ohci = usb_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;
@@ -1934,10 +1934,10 @@
 		return 0;
 	}
 
-	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);
 
 	switch (bmRType_bReq) {
 	/* Request Destination:
@@ -2111,7 +2111,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int rh_unlink_urb (urb_t * urb)
+static int rh_unlink_urb (struct urb * urb)
 {
 	ohci_t * ohci = urb->dev->bus->hcpriv;
  
@@ -2144,6 +2144,8 @@
 	int timeout = 30;
 	int smm_timeout = 50; /* 0,5 sec */
 	 	
+#ifndef __hppa__
+	/* PA-RISC doesn't have SMM, but PDC might leave IR set */
 	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
 		writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
 		dbg("USB HC TakeOver from SMM");
@@ -2154,7 +2156,8 @@
 				return -1;
 			}
 		}
-	}	
+	}
+#endif	
 		
 	/* Disable HC interrupts */
 	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
@@ -2218,9 +2221,19 @@
 	writel (mask, &ohci->regs->intrstatus);
 
 #ifdef	OHCI_USE_NPS
-	/* required for AMD-756 and some Mac platforms */
-	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
-		&ohci->regs->roothub.a);
+	if(ohci->flags & OHCI_QUIRK_SUCKYIO)
+	{
+		/* NSC 87560 at least requires different setup .. */
+		writel ((roothub_a (ohci) | RH_A_NOCP) &
+			~(RH_A_OCPM | RH_A_POTPGT | RH_A_PSM | RH_A_NPS),
+			&ohci->regs->roothub.a);
+	}
+	else
+	{
+		/* required for AMD-756 and some Mac platforms */
+		writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+			&ohci->regs->roothub.a);
+	}
 	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
 #endif	/* OHCI_USE_NPS */
 
@@ -2288,9 +2301,19 @@
 	struct ohci_regs * regs = ohci->regs;
  	int ints; 
 
-	if ((ohci->hcca->done_head != 0) && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
+	/* avoid (slow) readl if only WDH happened */
+	if ((ohci->hcca->done_head != 0)
+			&& !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
 		ints =  OHCI_INTR_WDH;
-	} else if ((ints = (readl (&regs->intrstatus) & readl (&regs->intrenable))) == 0) {
+
+	/* cardbus/... hardware gone before remove() */
+	} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+		ohci->disabled++;
+		err ("%s device removed!", ohci->ohci_dev->slot_name);
+		return;
+
+	/* interrupt for some other device? */
+	} else if ((ints &= readl (&regs->intrenable)) == 0) {
 		return;
 	} 
 
@@ -2391,6 +2414,7 @@
 		kfree (ohci);
 		return NULL;
 	}
+	ohci->bus->bus_name = dev->slot_name;
 	ohci->bus->hcpriv = (void *) ohci;
 
 	return ohci;
@@ -2418,8 +2442,9 @@
 	}
 	pci_set_drvdata(ohci->ohci_dev, NULL);
 	if (ohci->bus) {
-		if (ohci->bus->busnum)
+		if (ohci->bus->busnum != -1)
 			usb_deregister_bus (ohci->bus);
+
 		usb_free_bus (ohci->bus);
 	}
 
@@ -2448,7 +2473,6 @@
 	void *mem_base, const struct pci_device_id *id)
 {
 	ohci_t * ohci;
-	u8 latency, limit;
 	char buf[8], *bufp = buf;
 	int ret;
 
@@ -2470,23 +2494,24 @@
 		return ret;
 	}
 	ohci->flags = id->driver_data;
+	
+	/* Check for NSC87560. We have to look at the bridge (fn1) to identify
+	   the USB (fn2). This quirk might apply to more or even all NSC stuff
+	   I don't know.. */
+	   
+	if(dev->vendor == PCI_VENDOR_ID_NS)
+	{
+		struct pci_dev *fn1  = pci_find_slot(dev->bus->number, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
+		if(fn1 && fn1->vendor == PCI_VENDOR_ID_NS && fn1->device == PCI_DEVICE_ID_NS_87560_LIO)
+			ohci->flags |= OHCI_QUIRK_SUCKYIO;
+		
+	}
+	
+	if (ohci->flags & OHCI_QUIRK_SUCKYIO)
+		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);
 		return -ENODEV;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)