From: "Mikael Starvik" USB driver patches. * Compiles for >= 2.6.11. * Use I/O and DMA allocators. * Replace restore_flags etc. Signed-off-by: Mikael Starvik Signed-off-by: Andrew Morton --- drivers/usb/Kconfig | 1 drivers/usb/host/hc_crisv10.c | 175 ++++++++++++++++++++++++++---------------- 2 files changed, 110 insertions(+), 66 deletions(-) diff -puN drivers/usb/host/hc_crisv10.c~cris-update-16-17-usb drivers/usb/host/hc_crisv10.c --- 25/drivers/usb/host/hc_crisv10.c~cris-update-16-17-usb 2005-06-25 14:20:06.000000000 -0700 +++ 25-akpm/drivers/usb/host/hc_crisv10.c 2005-06-25 14:20:06.000000000 -0700 @@ -24,6 +24,7 @@ #include #include #include +#include #include /* Ugly include because we don't live with the other host drivers. */ @@ -36,7 +37,7 @@ #define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR #define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR -static const char *usb_hcd_version = "$Revision: 1.2 $"; +static const char *usb_hcd_version = "$Revision: 1.4 $"; #undef KERN_DEBUG #define KERN_DEBUG "" @@ -367,11 +368,14 @@ static inline struct urb *urb_list_first /* Adds an urb_entry last in the list for this epid. */ static inline void urb_list_add(struct urb *urb, int epid) { + unsigned long flags; urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG); assert(urb_entry); urb_entry->urb = urb; + spin_lock_irqsave(&urb_list_lock, flags); list_add_tail(&urb_entry->list, &urb_list[epid]); + spin_unlock_irqrestore(&urb_list_lock, flags); } /* Search through the list for an element that contains this urb. (The list @@ -398,22 +402,28 @@ static inline urb_entry_t *__urb_list_en /* Delete an urb from the list. */ static inline void urb_list_del(struct urb *urb, int epid) { + unsigned long flags; urb_entry_t *urb_entry = __urb_list_entry(urb, epid); assert(urb_entry); /* Delete entry and free. */ + spin_lock_irqsave(&urb_list_lock, flags); list_del(&urb_entry->list); kfree(urb_entry); + spin_unlock_irqrestore(&urb_list_lock, flags); } /* Move an urb to the end of the list. */ static inline void urb_list_move_last(struct urb *urb, int epid) { + unsigned long flags; urb_entry_t *urb_entry = __urb_list_entry(urb, epid); assert(urb_entry); + spin_lock_irqsave(&urb_list_lock, flags); list_del(&urb_entry->list); list_add_tail(&urb_entry->list, &urb_list[epid]); + spin_unlock_irqrestore(&urb_list_lock, flags); } /* Get the next urb in the list. */ @@ -651,12 +661,11 @@ static inline void __dump_ept_data(int e return; } - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); + local_irq_restore(flags); printk("\nR_USB_EPT_DATA = 0x%x for epid %d :\n", r_usb_ept_data, epid); if (r_usb_ept_data == 0) { @@ -1109,8 +1118,7 @@ static int etrax_usb_setup_epid(struct u out_traffic = usb_pipeout(urb->pipe); } - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); @@ -1132,7 +1140,7 @@ static int etrax_usb_setup_epid(struct u IO_FIELD(R_USB_EPT_DATA, dev, devnum); } - restore_flags(flags); + local_irq_restore(flags); if (out_traffic) { set_bit(epid, (void *)&epid_out_traffic); @@ -1159,15 +1167,14 @@ static void etrax_usb_free_epid(int epid return; } - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)); /* This will, among other things, set the valid field to 0. */ *R_USB_EPT_DATA = 0; - restore_flags(flags); + local_irq_restore(flags); clear_bit(epid, (void *)&epid_usage_bitmask); @@ -1203,14 +1210,13 @@ static int etrax_usb_lookup_epid(struct if (test_bit(i, (void *)&epid_usage_bitmask) && test_bit(i, (void *)&epid_out_traffic) == out_traffic) { - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i); nop(); if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { data = *R_USB_EPT_DATA_ISO; - restore_flags(flags); + local_irq_restore(flags); if ((IO_MASK(R_USB_EPT_DATA_ISO, valid) & data) && (IO_EXTRACT(R_USB_EPT_DATA_ISO, dev, data) == devnum) && @@ -1223,7 +1229,7 @@ static int etrax_usb_lookup_epid(struct } } else { data = *R_USB_EPT_DATA; - restore_flags(flags); + local_irq_restore(flags); if ((IO_MASK(R_USB_EPT_DATA, valid) & data) && (IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) && @@ -1277,11 +1283,6 @@ static int etrax_usb_submit_urb(struct u return -EMSGSIZE; } - if (urb->timeout) { - /* FIXME. */ - warn("urb->timeout specified, ignoring."); - } - hc = (etrax_hc_t*)urb->dev->bus->hcpriv; if (usb_pipedevice(urb->pipe) == hc->rh.devnum) { @@ -1357,18 +1358,17 @@ static int etrax_usb_unlink_urb(struct u unlink_urb should not be used frequently anyway. */ - save_flags(flags); - cli(); + local_irq_save(flags); if (!urb->dev || !urb->dev->bus) { - restore_flags(flags); + local_irq_restore(flags); return -ENODEV; } if (!urb->hcpriv) { /* This happens if a device driver calls unlink on an urb that was never submitted (lazy driver) or if the urb was completed while unlink was being called. */ - restore_flags(flags); + local_irq_restore(flags); return 0; } if (urb->transfer_flags & URB_ASYNC_UNLINK) { @@ -1402,7 +1402,7 @@ static int etrax_usb_unlink_urb(struct u int ret; ret = etrax_rh_unlink_urb(urb); DBFEXIT; - restore_flags(flags); + local_irq_restore(flags); return ret; } else if (usb_pipetype(urb->pipe) == PIPE_BULK) { @@ -1554,7 +1554,7 @@ static int etrax_usb_unlink_urb(struct u if (urb_list_empty(epid)) { etrax_usb_free_epid(epid); } - restore_flags(flags); + local_irq_restore(flags); /* Must be done before calling completion handler. */ kfree(urb_priv); @@ -1614,8 +1614,7 @@ static irqreturn_t etrax_usb_tx_interrup *R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do); /* The complete callback gets called so we cli. */ - save_flags(flags); - cli(); + local_irq_save(flags); for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { if ((TxCtrlEPList[epid].sub == 0) || @@ -1643,7 +1642,7 @@ static irqreturn_t etrax_usb_tx_interrup } } } - restore_flags(flags); + local_irq_restore(flags); } if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) { dbg_intr("dma8_sub2_descr (INTR) intr."); @@ -1772,8 +1771,7 @@ static void etrax_usb_isoc_descr_interru for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); epid_done = 0; @@ -1831,7 +1829,7 @@ static void etrax_usb_isoc_descr_interru epid_done = 1; } } - restore_flags(flags); + local_irq_restore(flags); } kmem_cache_free(isoc_compl_cache, comp_data); @@ -1861,8 +1859,7 @@ static irqreturn_t etrax_usb_rx_interrup one rx descriptor. */ /* The reason we cli here is that we call the driver's callback functions. */ - save_flags(flags); - cli(); + local_irq_save(flags); while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) { @@ -2056,7 +2053,7 @@ static irqreturn_t etrax_usb_rx_interrup myNextRxDesc = phys_to_virt(myNextRxDesc->next); } - restore_flags(flags); + local_irq_restore(flags); DBFEXIT; @@ -2228,8 +2225,7 @@ static void etrax_usb_add_to_bulk_sb_lis urb->hcpriv = urb_priv; /* Reset toggle bits and reset error count. */ - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); @@ -2292,7 +2288,7 @@ static void etrax_usb_add_to_bulk_sb_lis TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); /* Everything is set up, safe to enable interrupts again. */ - restore_flags(flags); + local_irq_restore(flags); /* If the DMA bulk channel isn't running, we need to restart it if it has stopped at the last EP descriptor (DMA stopped because there was @@ -2351,8 +2347,7 @@ static void etrax_usb_complete_bulk_urb( /* FIXME: Is there something of the things below we shouldn't do if there was an error? Like, maybe we shouldn't toggle the toggle bits, or maybe we shouldn't insert more traffic. */ - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); @@ -2369,7 +2364,7 @@ static void etrax_usb_complete_bulk_urb( usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); } - restore_flags(flags); + local_irq_restore(flags); /* Remember to free the SBs. */ etrax_remove_from_sb_list(urb); @@ -2527,7 +2522,7 @@ static void etrax_usb_add_to_ctrl_sb_lis before the mandatory IN (status) token, hence the reordered SB list */ sb_desc_setup->next = virt_to_phys(sb_desc_status); - if (urb->transfer_buffer) { + if ((0 < urb->transfer_buffer_length) && urb->transfer_buffer) { dbg_ctrl("This OUT transfer has an extra data stage"); @@ -2600,8 +2595,7 @@ static void etrax_usb_add_to_ctrl_sb_lis /* Reset toggle bits and reset error count, remember to di and ei */ /* Warning: it is possible that this locking doesn't work with bottom-halves */ - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); @@ -2621,7 +2615,7 @@ static void etrax_usb_add_to_ctrl_sb_lis /* Since we use the rx interrupt to complete ctrl urbs, we can enable interrupts now (i.e. we don't check the sub pointer on an eot interrupt like we do for bulk traffic). */ - restore_flags(flags); + local_irq_restore(flags); /* Assert that the EP descriptor is disabled. */ assert(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable))); @@ -2935,15 +2929,14 @@ static void etrax_usb_check_error_isoc_e the epid without testing if for it in R_USB_EPID_ATTN. */ - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); /* Note that although there are separate R_USB_EPT_DATA and R_USB_EPT_DATA_ISO registers, they are located at the same address and are of the same size. In other words, this read should be ok for isoc also. */ r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); + local_irq_restore(flags); error_code = IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data); @@ -3210,10 +3203,9 @@ static void etrax_usb_complete_isoc_urb( TxIsocEPList[epid].sub = 0; TxIsocEPList[epid].hw_len = 0; - save_flags(flags); - cli(); + local_irq_save(flags); etrax_usb_free_epid(epid); - restore_flags(flags); + local_irq_restore(flags); } urb->hcpriv = 0; @@ -3300,8 +3292,7 @@ static irqreturn_t etrax_usb_hc_interrup DBFENTER; /* Read critical registers into local variables, do kmalloc afterwards. */ - save_flags(flags); - cli(); + local_irq_save(flags); irq_mask = *R_USB_IRQ_MASK_READ; /* Reading R_USB_STATUS clears the ctl_status interrupt. Note that R_USB_STATUS @@ -3321,7 +3312,7 @@ static irqreturn_t etrax_usb_hc_interrup /* Note: the lower 11 bits contain the actual frame number, sent with each sof. */ fm_number = *R_USB_FM_NUMBER; - restore_flags(flags); + local_irq_restore(flags); reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, SLAB_ATOMIC); @@ -3399,12 +3390,11 @@ void etrax_usb_hc_isoc_eof_interrupt(voi /* Disable interrupts to block the isoc out descriptor interrupt handler from being called while the isoc EPID list is being checked. */ - save_flags(flags); - cli(); + local_irq_save(flags); if (TxIsocEPList[epid].sub == 0) { /* Nothing here to see. */ - restore_flags(flags); + local_irq_restore(flags); continue; } @@ -3412,7 +3402,7 @@ void etrax_usb_hc_isoc_eof_interrupt(voi urb = urb_list_first(epid); if (urb == 0) { warn("Ignoring NULL urb"); - restore_flags(flags); + local_irq_restore(flags); continue; } if (usb_pipein(urb->pipe)) { @@ -3439,7 +3429,7 @@ void etrax_usb_hc_isoc_eof_interrupt(voi } } } - restore_flags(flags); + local_irq_restore(flags); } DBFEXIT; @@ -3503,12 +3493,11 @@ void etrax_usb_hc_bulk_eot_interrupt(int continue; } - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); + local_irq_restore(flags); if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) { @@ -3563,15 +3552,14 @@ void etrax_usb_hc_epid_attn_interrupt(us unsigned long flags; int error_code; - save_flags(flags); - cli(); + local_irq_save(flags); *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); nop(); /* Note that although there are separate R_USB_EPT_DATA and R_USB_EPT_DATA_ISO registers, they are located at the same address and are of the same size. In other words, this read should be ok for isoc also. */ r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); + local_irq_restore(flags); /* First some sanity checks. */ if (epid == INVALID_EPID) { @@ -4291,6 +4279,10 @@ etrax_usb_buffer_free(struct usb_bus *bu static struct device fake_device; +static struct device_driver etrax_usb_driver = { + .name = (char *) "ETRAX 100LX", +}; + static int __init etrax_usb_hc_init(void) { static etrax_hc_t *hc; @@ -4302,6 +4294,22 @@ static int __init etrax_usb_hc_init(void info("ETRAX 100LX USB-HCD %s (c) 2001-2003 Axis Communications AB\n", usb_hcd_version); +#ifdef CONFIG_ETRAX_USB_HOST_PORT1 + if (cris_request_io_interface(if_usb_1, "ETRAX100LX USB-HCD")) { + printk(KERN_CRIT "usb-host: request IO interface usb%d failed", 1); + return -EBUSY; + } +#endif +#ifdef CONFIG_ETRAX_USB_HOST_PORT2 + if (cris_request_io_interface(if_usb_2, "ETRAX100LX USB-HCD")) { +#ifdef CONFIG_ETRAX_USB_HOST_PORT1 + cris_free_io_interface(if_usb_1); +#endif + printk(KERN_CRIT "usb-host: request IO interface usb%d failed", 2); + return -EBUSY; + } +#endif + hc = kmalloc(sizeof(etrax_hc_t), GFP_KERNEL); assert(hc != NULL); @@ -4385,6 +4393,28 @@ static int __init etrax_usb_hc_init(void bulk_eot_timer.function = etrax_usb_bulk_eot_timer_func; add_timer(&bulk_eot_timer); + /* This code should really be moved */ + + if (cris_request_dma(USB_TX_DMA_NBR, + "ETRAX 100LX built-in USB (Tx)", + DMA_VERBOSE_ON_ERROR, + dma_usb)) { + err("Could not allocate DMA ch 8 for USB"); + etrax_usb_hc_cleanup(); + DBFEXIT; + return -1; + } + + if (cris_request_dma(USB_RX_DMA_NBR, + "ETRAX 100LX built-in USB (Rx)", + DMA_VERBOSE_ON_ERROR, + dma_usb)) { + err("Could not allocate DMA ch 9 for USB"); + etrax_usb_hc_cleanup(); + DBFEXIT; + return -1; + } + /* Set up the data structures for USB traffic. Note that this must be done before any interrupt that relies on sane DMA list occurrs. */ init_rx_buffers(); @@ -4398,6 +4428,9 @@ static int __init etrax_usb_hc_init(void kobject_add(&fake_device.kobj); kobject_hotplug(&fake_device.kobj, KOBJ_ADD); hc->bus->controller = &fake_device; + kobject_set_name(&etrax_usb_driver.kobj, "etrax_usb_driver"); + kobject_register(&etrax_usb_driver.kobj); + hc->bus->controller->driver = &etrax_usb_driver; usb_register_bus(hc->bus); *R_IRQ_MASK2_SET = @@ -4529,7 +4562,7 @@ static int __init etrax_usb_hc_init(void usb_rh->speed = USB_SPEED_FULL; usb_rh->devnum = 1; hc->bus->devnum_next = 2; - usb_rh->ep0.desc.wMaxPacketSize = __const_cpu_to_le16(64); + usb_rh->ep0.desc.wMaxPacketSize = 64; usb_get_device_descriptor(usb_rh, USB_DT_DEVICE_SIZE); usb_new_device(usb_rh); @@ -4538,7 +4571,7 @@ static int __init etrax_usb_hc_init(void return 0; } -static void etrax_usb_hc_cleanup(void) +static void __exit etrax_usb_hc_cleanup(void) { DBFENTER; @@ -4546,6 +4579,16 @@ static void etrax_usb_hc_cleanup(void) free_irq(ETRAX_USB_RX_IRQ, NULL); free_irq(ETRAX_USB_TX_IRQ, NULL); + cris_free_dma(USB_TX_DMA_NBR, "ETRAX 100LX built-in USB (Tx)"); + cris_free_dma(USB_RX_DMA_NBR, "ETRAX 100LX built-in USB (Rx)"); + +#ifdef CONFIG_ETRAX_USB_HOST_PORT2 + cris_free_io_interface(if_usb_2); +#endif +#ifdef CONFIG_ETRAX_USB_HOST_PORT1 + cris_free_io_interface(if_usb_1); +#endif + usb_deregister_bus(etrax_usb_bus); /* FIXME: call kmem_cache_destroy here? */ diff -puN drivers/usb/Kconfig~cris-update-16-17-usb drivers/usb/Kconfig --- 25/drivers/usb/Kconfig~cris-update-16-17-usb 2005-06-25 14:20:06.000000000 -0700 +++ 25-akpm/drivers/usb/Kconfig 2005-06-25 14:20:06.000000000 -0700 @@ -11,6 +11,7 @@ config USB_ARCH_HAS_HCD boolean default y if USB_ARCH_HAS_OHCI default y if ARM # SL-811 + default y if ETRAXFS default PCI # many non-PCI SOC chips embed OHCI _