Commit 31c6329d authored by Linus Torvalds's avatar Linus Torvalds Committed by Linus Torvalds

Merge bk://linuxusb.bkbits.net/linus-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 5a56fafe 5313eab3
......@@ -106,9 +106,7 @@ MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all device
MODULE_AUTHOR("NAGANO Daisuke <breeze.nagano@nifty.ne.jp>");
MODULE_DESCRIPTION("USB-MIDI driver");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)
MODULE_LICENSE("GPL");
#endif
/* ------------------------------------------------------------------------- */
......
......@@ -74,9 +74,9 @@ static void urb_print (struct urb * urb, char * str, int small)
static inline struct ed *
dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma);
#ifdef OHCI_VERBOSE_DEBUG
/* print non-empty branches of the periodic ed tree */
void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
static void __attribute__ ((unused))
ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
{
int i, j;
u32 *ed_p;
......@@ -101,7 +101,6 @@ void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n",
label, ohci->hcd.self.bus_name);
}
#endif
static void ohci_dump_intr_mask (char *label, __u32 mask)
{
......@@ -241,6 +240,97 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose)
ohci_dump_roothub (controller, 1);
}
static void ohci_dump_td (char *label, struct td *td)
{
u32 tmp = le32_to_cpup (&td->hwINFO);
dbg ("%s td %p; urb %p index %d; hw next td %08x",
label, td,
td->urb, td->index,
le32_to_cpup (&td->hwNextTD));
if ((tmp & TD_ISO) == 0) {
char *toggle, *pid;
u32 cbp, be;
switch (tmp & TD_T) {
case TD_T_DATA0: toggle = "DATA0"; break;
case TD_T_DATA1: toggle = "DATA1"; break;
case TD_T_TOGGLE: toggle = "(CARRY)"; break;
default: toggle = "(?)"; break;
}
switch (tmp & TD_DP) {
case TD_DP_SETUP: pid = "SETUP"; break;
case TD_DP_IN: pid = "IN"; break;
case TD_DP_OUT: pid = "OUT"; break;
default: pid = "(bad pid)"; break;
}
dbg (" info %08x CC=%x %s DI=%d %s %s", tmp,
TD_CC_GET(tmp), /* EC, */ toggle,
(tmp & TD_DI) >> 21, pid,
(tmp & TD_R) ? "R" : "");
cbp = le32_to_cpup (&td->hwCBP);
be = le32_to_cpup (&td->hwBE);
dbg (" cbp %08x be %08x (len %d)", cbp, be,
cbp ? (be + 1 - cbp) : 0);
} else {
unsigned i;
dbg (" info %08x CC=%x DI=%d START=%04x", tmp,
TD_CC_GET(tmp), /* FC, */
(tmp & TD_DI) >> 21,
tmp & 0x0000ffff);
dbg (" bp0 %08x be %08x",
le32_to_cpup (&td->hwCBP) & ~0x0fff,
le32_to_cpup (&td->hwBE));
for (i = 0; i < MAXPSW; i++) {
dbg (" psw [%d] = %2x", i,
le16_to_cpu (td->hwPSW [i]));
}
}
}
/* caller MUST own hcd spinlock if verbose is set! */
static void __attribute__((unused))
ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
{
u32 tmp = ed->hwINFO;
char *type = "";
dbg ("%s: %s, ed %p state 0x%x type %d; next ed %08x",
ohci->hcd.self.bus_name, label,
ed, ed->state, ed->type,
le32_to_cpup (&ed->hwNextED));
switch (tmp & (ED_IN|ED_OUT)) {
case ED_OUT: type = "-OUT"; break;
case ED_IN: type = "-IN"; break;
/* else from TDs ... control */
}
dbg (" info %08x MAX=%d%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp),
0x0fff & (le32_to_cpu (tmp) >> 16),
(tmp & ED_ISO) ? " ISO" : "",
(tmp & ED_SKIP) ? " SKIP" : "",
(tmp & ED_LOWSPEED) ? " LOW" : "",
0x000f & (le32_to_cpu (tmp) >> 7),
type,
0x007f & le32_to_cpu (tmp));
dbg (" tds: head %08x%s%s tail %08x%s",
tmp = le32_to_cpup (&ed->hwHeadP),
(ed->hwHeadP & ED_H) ? " HALT" : "",
(ed->hwHeadP & ED_C) ? " CARRY" : "",
le32_to_cpup (&ed->hwTailP),
verbose ? "" : " (not listing)");
if (verbose) {
struct list_head *tmp;
/* use ed->td_list because HC concurrently modifies
* hwNextTD as it accumulates ed_donelist.
*/
list_for_each (tmp, &ed->td_list) {
struct td *td;
td = list_entry (tmp, struct td, td_list);
ohci_dump_td (" ->", td);
}
}
}
#endif
......@@ -100,7 +100,7 @@
* - lots more testing!!
*/
#define DRIVER_VERSION "2002-Jun-10"
#define DRIVER_VERSION "2002-Jun-15"
#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
......@@ -145,8 +145,8 @@ static int ohci_urb_enqueue (
urb_print (urb, "SUB", usb_pipein (pipe));
#endif
/* every endpoint has a ed, locate and fill it */
if (! (ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags)))
/* every endpoint has a ed, locate and maybe (re)initialize it */
if (! (ed = ed_get (ohci, urb->dev, pipe, urb->interval)))
return -ENOMEM;
/* for the private part of the URB we need the number of TDs (size) */
......@@ -498,6 +498,7 @@ static void ohci_irq (struct usb_hcd *hcd)
struct ohci_regs *regs = ohci->regs;
int ints;
/* we can eliminate a (slow) readl() if _only_ WDH caused this irq */
if ((ohci->hcca->done_head != 0)
&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
ints = OHCI_INTR_WDH;
......
......@@ -221,6 +221,7 @@ ed_alloc (struct ohci_hcd *hc, int mem_flags)
ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma);
if (ed) {
memset (ed, 0, sizeof (*ed));
INIT_LIST_HEAD (&ed->td_list);
ed->dma = dma;
/* hash it for later reverse mapping */
if (!hash_add_ed (hc, ed, mem_flags)) {
......
......@@ -131,8 +131,9 @@ static void intr_resub (struct ohci_hcd *hc, struct urb *urb)
/* search for the right branch to insert an interrupt ed into the int tree
* do some load balancing;
* returns the branch and
* sets the interval to interval = 2^integer (ld (interval))
* returns the branch
* FIXME allow for failure, when there's no bandwidth left;
* and consider iso loads too
*/
static int ep_int_balance (struct ohci_hcd *ohci, int interval, int load)
{
......@@ -152,19 +153,6 @@ static int ep_int_balance (struct ohci_hcd *ohci, int interval, int load)
/*-------------------------------------------------------------------------*/
/* 2^int ( ld (inter)) */
static int ep_2_n_interval (int inter)
{
int i;
for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++)
continue;
return 1 << i;
}
/*-------------------------------------------------------------------------*/
/* the int tree is a binary tree
* in order to process it sequentially the indexes of the branches have
* to be mapped the mapping reverses the bits of a word of num_bits length
......@@ -230,8 +218,7 @@ static int ep_link (struct ohci_hcd *ohci, struct ed *edi)
case PIPE_INTERRUPT:
load = ed->intriso.intr_info.int_load;
interval = ep_2_n_interval (ed->intriso.intr_info.int_period);
ed->interval = interval;
interval = ed->interval;
int_branch = ep_int_balance (ohci, interval, load);
ed->intriso.intr_info.int_branch = int_branch;
......@@ -301,6 +288,7 @@ static void periodic_unlink (
* just the link to the ed is unlinked.
* the link from the ed still points to another operational ed or 0
* so the HC can eventually finish the processing of the unlinked ed
* caller guarantees the ED has no active TDs.
*/
static int start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
{
......@@ -387,84 +375,99 @@ static int start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
/*-------------------------------------------------------------------------*/
/* (re)init an endpoint; this _should_ be done once at the
* usb_set_configuration command, but the USB stack is a bit stateless
* so we do it at every transaction.
* if the state of the ed is ED_NEW then a dummy td is added and the
* state is changed to ED_UNLINK
* in all other cases the state is left unchanged
* the ed info fields are set even though most of them should
* not change
/* get and maybe (re)init an endpoint. init _should_ be done only as part
* of usb_set_configuration() or usb_set_interface() ... but the USB stack
* isn't very stateful, so we re-init whenever the HC isn't looking.
*/
static struct ed *ep_add_ed (
static struct ed *ed_get (
struct ohci_hcd *ohci,
struct usb_device *udev,
unsigned int pipe,
int interval,
int load,
int mem_flags
int interval
) {
struct ohci_hcd *ohci = hcd_to_ohci (udev->bus->hcpriv);
int is_out = !usb_pipein (pipe);
int type = usb_pipetype (pipe);
int bus_msecs = 0;
struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv;
struct td *td;
struct ed *ed;
unsigned ep;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
ep = usb_pipeendpoint (pipe) << 1;
if (!usb_pipecontrol (pipe) && usb_pipeout (pipe))
if (type != PIPE_CONTROL && is_out)
ep |= 1;
if (type == PIPE_INTERRUPT)
bus_msecs = usb_calc_bus_time (udev->speed, !is_out, 0,
usb_maxpacket (udev, pipe, is_out)) / 1000;
spin_lock_irqsave (&ohci->lock, flags);
if (!(ed = dev->ep [ep])) {
ed = ed_alloc (ohci, SLAB_ATOMIC);
if (!ed) {
/* out of memory */
spin_unlock_irqrestore (&ohci->lock, flags);
return NULL;
goto done;
}
dev->ep [ep] = ed;
}
if (ed->state & ED_URB_DEL) {
/* pending unlink request */
spin_unlock_irqrestore (&ohci->lock, flags);
return NULL;
ed = 0;
goto done;
}
if (ed->state == ED_NEW) {
struct td *td;
ed->hwINFO = ED_SKIP;
/* dummy td; end of td list for ed */
td = td_alloc (ohci, SLAB_ATOMIC);
if (!td) {
/* out of memory */
spin_unlock_irqrestore (&ohci->lock, flags);
return NULL;
ed = 0;
goto done;
}
ed->dummy = td;
ed->hwTailP = cpu_to_le32 (td->td_dma);
ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */
ed->state = ED_UNLINK;
ed->type = usb_pipetype (pipe);
ed->type = type;
}
// FIXME: don't do this if it's linked to the HC, or without knowing it's
// safe to clobber state/mode info tied to (previous) config/altsetting.
// (but dev0/ep0, used by set_address, must get clobbered)
ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
| usb_pipeendpoint (pipe) << 7
| (usb_pipeisoc (pipe)? 0x8000: 0)
| (usb_pipecontrol (pipe)
? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
| (udev->speed == USB_SPEED_LOW) << 13
| usb_maxpacket (udev, pipe, usb_pipeout (pipe))
<< 16);
if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
ed->intriso.intr_info.int_period = interval;
ed->intriso.intr_info.int_load = load;
}
/* FIXME: Don't do this without knowing it's safe to clobber this
* state/mode info. Currently the upper layers don't support such
* guarantees; we're lucky changing config/altsetting is rare.
*/
if (ed->state == ED_UNLINK) {
u32 info;
info = usb_pipedevice (pipe);
info |= (ep >> 1) << 7;
info |= usb_maxpacket (udev, pipe, is_out) << 16;
info = cpu_to_le32 (info);
if (udev->speed == USB_SPEED_LOW)
info |= ED_LOWSPEED;
/* control transfers store pids in tds */
if (type != PIPE_CONTROL) {
info |= is_out ? ED_OUT : ED_IN;
if (type == PIPE_ISOCHRONOUS)
info |= ED_ISO;
if (type == PIPE_INTERRUPT) {
ed->intriso.intr_info.int_load = bus_msecs;
if (interval > 32)
interval = 32;
}
}
ed->hwINFO = info;
/* value ignored except on periodic EDs, where
* we know it's already a power of 2
*/
ed->interval = interval;
}
done:
spin_unlock_irqrestore (&ohci->lock, flags);
return ed;
}
......@@ -736,8 +739,8 @@ static void td_done (struct urb *urb, struct td *td)
urb->iso_frame_desc [td->index].status = cc_to_error [cc];
if (cc != 0)
dbg (" urb %p iso TD %d len %d CC %d",
urb, td->index, dlen, cc);
dbg (" urb %p iso TD %p (%d) len %d CC %d",
urb, td, 1 + td->index, dlen, cc);
/* BULK, INT, CONTROL ... drivers see aggregate length/status,
* except that "setup" bytes aren't counted and "short" transfers
......@@ -776,9 +779,13 @@ static void td_done (struct urb *urb, struct td *td)
- td->data_dma;
}
#ifdef VERBOSE_DEBUG
if (cc != 0)
dbg (" urb %p TD %d CC %d, len=%d",
urb, td->index, cc, urb->actual_length);
dbg (" urb %p TD %p (%d) CC %d, len=%d/%d",
urb, td, 1 + td->index, cc,
urb->actual_length,
urb->transfer_buffer_length);
#endif
}
}
......@@ -812,8 +819,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
if (urb_priv && ((td_list->index + 1)
< urb_priv->length)) {
#ifdef OHCI_VERBOSE_DEBUG
dbg ("urb %p TD %d of %d, patch ED",
td_list->urb,
dbg ("urb %p TD %p (%d/%d), patch ED",
td_list->urb, td_list,
1 + td_list->index,
urb_priv->length);
#endif
......
......@@ -19,7 +19,7 @@ struct ed {
#define ED_SKIP __constant_cpu_to_le32(1 << 14)
#define ED_LOWSPEED __constant_cpu_to_le32(1 << 13)
#define ED_OUT __constant_cpu_to_le32(0x01 << 11)
#define ED_IN __constant_cpu_to_le32(0x10 << 11)
#define ED_IN __constant_cpu_to_le32(0x02 << 11)
__u32 hwTailP; /* tail of TD list */
__u32 hwHeadP; /* head of TD list */
#define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */
......@@ -30,24 +30,24 @@ struct ed {
dma_addr_t dma; /* addr of ED */
struct ed *ed_prev; /* for non-interrupt EDs */
struct td *dummy;
struct list_head td_list; /* "shadow list" of our TDs */
u8 state; /* ED_{NEW,UNLINK,OPER} */
#define ED_NEW 0x00 /* unused, no dummy td */
#define ED_UNLINK 0x01 /* dummy td, maybe linked to hc */
#define ED_OPER 0x02 /* dummy td, _is_ linked to hc */
#define ED_URB_DEL 0x08 /* for unlinking; masked in */
u8 type; /* PIPE_{BULK,...} */
u8 interval; /* interrupt, isochronous */
u16 interval; /* interrupt, isochronous */
union {
struct intr_info { /* interrupt */
u8 int_period;
u8 int_branch;
u8 int_load;
} intr_info;
u16 last_iso; /* isochronous */
} intriso;
u8 state; /* ED_{NEW,UNLINK,OPER} */
#define ED_NEW 0x00 /* unused, no dummy td */
#define ED_UNLINK 0x01 /* dummy td, maybe linked to hc */
#define ED_OPER 0x02 /* dummy td, _is_ linked to hc */
#define ED_URB_DEL 0x08 /* for unlinking; masked in */
/* HC may see EDs on rm_list until next frame (frame_no == tick) */
u16 tick;
struct ed *ed_rm_list;
......@@ -108,6 +108,8 @@ struct td {
dma_addr_t td_dma; /* addr of this TD */
dma_addr_t data_dma; /* addr of data it points to */
struct list_head td_list; /* "shadow list", TDs on same ED */
} __attribute__ ((aligned(32))); /* c/b/i need 16; only iso needs 32 */
#define TD_MASK ((u32)~0x1f) /* strip hw status in low addr bits */
......
......@@ -220,10 +220,11 @@ struct kaweth_device
struct urb *rx_urb;
struct urb *tx_urb;
struct urb *irq_urb;
struct sk_buff *tx_skb;
__u8 *firmware_buf;
__u8 scratch[KAWETH_SCRATCH_SIZE];
__u8 tx_buf[KAWETH_BUF_SIZE];
__u8 rx_buf[KAWETH_BUF_SIZE];
__u8 intbuffer[INTBUFFERSIZE];
__u16 packet_filter_bitmap;
......@@ -650,11 +651,13 @@ static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
static void kaweth_usb_transmit_complete(struct urb *urb)
{
struct kaweth_device *kaweth = urb->context;
struct sk_buff *skb = kaweth->tx_skb;
if (unlikely(urb->status != 0))
kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
netif_wake_queue(kaweth->net);
dev_kfree_skb(skb);
}
/****************************************************************
......@@ -663,7 +666,7 @@ static void kaweth_usb_transmit_complete(struct urb *urb)
static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct kaweth_device *kaweth = net->priv;
int count = skb->len;
char *private_header;
int res;
......@@ -679,15 +682,30 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
kaweth_async_set_rx_mode(kaweth);
netif_stop_queue(net);
*((__u16 *)kaweth->tx_buf) = cpu_to_le16(skb->len);
/* We now decide whether we can put our special header into the sk_buff */
if (skb_cloned(skb) || skb_headroom(skb) < 2) {
/* no such luck - we make our own */
struct sk_buff *copied_skb;
copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC);
dev_kfree_skb_any(skb);
skb = copied_skb;
if (!copied_skb) {
kaweth->stats.tx_errors++;
netif_start_queue(net);
spin_unlock(&kaweth->device_lock);
return 0;
}
}
memcpy(kaweth->tx_buf + 2, skb->data, skb->len);
private_header = __skb_push(skb, 2);
*private_header = cpu_to_le16(skb->len);
kaweth->tx_skb = skb;
FILL_BULK_URB(kaweth->tx_urb,
kaweth->dev,
usb_sndbulkpipe(kaweth->dev, 2),
kaweth->tx_buf,
count + 2,
private_header,
skb->len,
kaweth_usb_transmit_complete,
kaweth);
kaweth->end = 0;
......@@ -699,6 +717,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
kaweth->stats.tx_errors++;
netif_start_queue(net);
dev_kfree_skb(skb);
}
else
{
......@@ -707,8 +726,6 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
net->trans_start = jiffies;
}
dev_kfree_skb(skb);
spin_unlock(&kaweth->device_lock);
return 0;
......
......@@ -51,12 +51,6 @@
#include <linux/slab.h>
/*
* kernel thread actions
*/
#define US_ACT_COMMAND 1
#define US_ACT_EXIT 5
/***********************************************************************
* Host functions
......@@ -204,7 +198,7 @@ static int device_reset( Scsi_Cmnd *srb )
US_DEBUGP("device_reset() called\n" );
/* if the device was removed, then we're already reset */
if (atomic_read(&us->sm_state) == US_STATE_DETACHED)
if (!test_bit(DEV_ATTACHED, &us->bitflags))
return SUCCESS;
scsi_unlock(srb->host);
......@@ -235,7 +229,7 @@ static int bus_reset( Scsi_Cmnd *srb )
US_DEBUGP("bus_reset() called\n");
/* if the device has been removed, this worked */
if (atomic_read(&us->sm_state) == US_STATE_DETACHED) {
if (!test_bit(DEV_ATTACHED, &us->bitflags)) {
US_DEBUGP("-- device removed already\n");
return SUCCESS;
}
......@@ -337,8 +331,8 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
/* show the GUID of the device */
SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
SPRINTF(" Attached: %s\n", (atomic_read(&us->sm_state) ==
US_STATE_DETACHED) ? "Yes" : "No");
SPRINTF(" Attached: %s\n", (test_bit(DEV_ATTACHED, &us->bitflags)
? "Yes" : "No"));
/*
* Calculate start of next buffer, and return value.
......
......@@ -99,13 +99,6 @@ MODULE_LICENSE("GPL");
static int my_host_number;
/*
* kernel thread actions
*/
#define US_ACT_COMMAND 1
#define US_ACT_EXIT 5
/* The list of structures and the protective lock for them */
struct us_data *us_list;
struct semaphore us_list_semaphore;
......@@ -426,7 +419,7 @@ static int usb_stor_control_thread(void * __us)
down(&(us->dev_semaphore));
/* our device has gone - pretend not ready */
if (atomic_read(&us->device_state) == US_STATE_DETACHED) {
if (!test_bit(DEV_ATTACHED, &us->bitflags)) {
US_DEBUGP("Request is for removed device\n");
/* For REQUEST_SENSE, it's the data. But
* for anything else, it should look like
......@@ -450,7 +443,7 @@ static int usb_stor_control_thread(void * __us)
sizeof(usb_stor_sense_notready));
us->srb->result = CHECK_CONDITION << 1;
}
} else { /* atomic_read(&us->device_state) == STATE_DETACHED */
} else { /* test_bit(DEV_ATTACHED, &us->bitflags) */
/* Handle those devices which need us to fake
* their inquiry data */
......@@ -557,9 +550,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
unsigned int flags;
struct us_unusual_dev *unusual_dev;
struct us_data *ss = NULL;
#ifdef CONFIG_USB_STORAGE_SDDR09
int result;
#endif
int new_device = 0;
/* these are temporary copies -- we test on these, then put them
* in the us-data structure
......@@ -570,13 +562,13 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
u8 subclass = 0;
u8 protocol = 0;
/* the altsettting on the interface we're probing that matched our
/* the altsetting on the interface we're probing that matched our
* usb_match_id table
*/
struct usb_interface *intf = dev->actconfig->interface;
struct usb_interface_descriptor *altsetting =
intf[ifnum].altsetting + intf[ifnum].act_altsetting;
US_DEBUGP("act_altsettting is %d\n", intf[ifnum].act_altsetting);
US_DEBUGP("act_altsetting is %d\n", intf[ifnum].act_altsetting);
/* clear the temporary strings */
memset(mf, 0, sizeof(mf));
......@@ -663,7 +655,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
return NULL;
}
/* At this point, we're committed to using the device */
/* At this point, we've decided to try to use the device */
usb_get_dev(dev);
/* clear the GUID and fetch the strings */
......@@ -696,7 +688,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
*/
ss = us_list;
while ((ss != NULL) &&
((ss->pusb_dev) || !GUID_EQUAL(guid, ss->guid)))
(test_bit(DEV_ATTACHED, &ss->bitflags) ||
!GUID_EQUAL(guid, ss->guid)))
ss = ss->next;
if (ss != NULL) {
......@@ -710,29 +703,23 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* establish the connection to the new device upon reconnect */
ss->ifnum = ifnum;
ss->pusb_dev = dev;
atomic_set(&ss->device_state, US_STATE_ATTACHED);
set_bit(DEV_ATTACHED, &ss->bitflags);
/* copy over the endpoint data */
if (ep_in)
ss->ep_in = ep_in->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
if (ep_out)
ss->ep_out = ep_out->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
ss->ep_in = ep_in->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
ss->ep_out = ep_out->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
ss->ep_int = ep_int;
/* allocate an IRQ callback if one is needed */
if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) {
usb_put_dev(dev);
return NULL;
}
if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
goto BadDevice;
/* allocate the URB we're going to use */
ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ss->current_urb) {
usb_put_dev(dev);
return NULL;
}
if (!ss->current_urb)
goto BadDevice;
/* Re-Initialize the device if it needs it */
if (unusual_dev && unusual_dev->initFunction)
......@@ -752,14 +739,12 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
return NULL;
}
memset(ss, 0, sizeof(struct us_data));
new_device = 1;
/* allocate the URB we're going to use */
ss->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ss->current_urb) {
kfree(ss);
usb_put_dev(dev);
return NULL;
}
if (!ss->current_urb)
goto BadDevice;
/* Initialize the mutexes only when the struct is new */
init_completion(&(ss->notify));
......@@ -776,12 +761,10 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
ss->unusual_dev = unusual_dev;
/* copy over the endpoint data */
if (ep_in)
ss->ep_in = ep_in->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
if (ep_out)
ss->ep_out = ep_out->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
ss->ep_in = ep_in->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
ss->ep_out = ep_out->bEndpointAddress &
USB_ENDPOINT_NUMBER_MASK;
ss->ep_int = ep_int;
/* establish the connection to the new device */
......@@ -904,12 +887,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
#endif
default:
ss->transport_name = "Unknown";
kfree(ss->current_urb);
kfree(ss);
usb_put_dev(dev);
return NULL;
break;
/* ss->transport_name = "Unknown"; */
goto BadDevice;
}
US_DEBUGP("Transport: %s\n", ss->transport_name);
......@@ -959,22 +938,14 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
#endif
default:
ss->protocol_name = "Unknown";
kfree(ss->current_urb);
kfree(ss);
usb_put_dev(dev);
return NULL;
break;
/* ss->protocol_name = "Unknown"; */
goto BadDevice;
}
US_DEBUGP("Protocol: %s\n", ss->protocol_name);
/* allocate an IRQ callback if one is needed */
if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss)) {
kfree(ss->current_urb);
kfree(ss);
usb_put_dev(dev);
return NULL;
}
if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
goto BadDevice;
/*
* Since this is a new device, we need to generate a scsi
......@@ -1001,16 +972,13 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* start up our control thread */
atomic_set(&ss->sm_state, US_STATE_IDLE);
atomic_set(&ss->device_state, US_STATE_ATTACHED);
set_bit(DEV_ATTACHED, &ss->bitflags);
ss->pid = kernel_thread(usb_stor_control_thread, ss,
CLONE_VM);
if (ss->pid < 0) {
printk(KERN_WARNING USB_STORAGE
"Unable to start control thread\n");
kfree(ss->current_urb);
kfree(ss);
usb_put_dev(dev);
return NULL;
goto BadDevice;
}
/* wait for the thread to start */
......@@ -1018,7 +986,17 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* now register - our detect function will be called */
ss->htmplt.module = THIS_MODULE;
scsi_register_host(&(ss->htmplt));
result = scsi_register_host(&(ss->htmplt));
if (result) {
printk(KERN_WARNING USB_STORAGE
"Unable to register the scsi host\n");
/* tell the control thread to exit */
ss->action = US_ACT_EXIT;
up(&ss->sema);
wait_for_completion(&ss->notify);
goto BadDevice;
}
/* lock access to the data structures */
down(&us_list_semaphore);
......@@ -1038,6 +1016,31 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* return a pointer for the disconnect function */
return ss;
/* we come here if there are any problems */
BadDevice:
US_DEBUGP("storage_probe() failed\n");
down(&ss->irq_urb_sem);
if (ss->irq_urb) {
usb_unlink_urb(ss->irq_urb);
usb_free_urb(ss->irq_urb);
ss->irq_urb = NULL;
}
up(&ss->irq_urb_sem);
if (ss->current_urb) {
usb_unlink_urb(ss->current_urb);
usb_free_urb(ss->current_urb);
ss->current_urb = NULL;
}
clear_bit(DEV_ATTACHED, &ss->bitflags);
ss->pusb_dev = NULL;
if (new_device)
kfree(ss);
else
up(&ss->dev_semaphore);
usb_put_dev(dev);
return NULL;
}
/* Handle a disconnect event from the USB core */
......@@ -1078,7 +1081,7 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
/* mark the device as gone */
usb_put_dev(ss->pusb_dev);
ss->pusb_dev = NULL;
atomic_set(&ss->sm_state, US_STATE_DETACHED);
clear_bit(DEV_ATTACHED, &ss->bitflags);
/* unlock access to the device data structure */
up(&(ss->dev_semaphore));
......
......@@ -103,9 +103,10 @@ struct us_unusual_dev {
#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
/* device attached/detached states */
#define US_STATE_DETACHED 1
#define US_STATE_ATTACHED 2
/* kernel thread actions */
#define US_ACT_COMMAND 1
#define US_ACT_EXIT 5
/* processing state machine states */
#define US_STATE_IDLE 1
......@@ -127,10 +128,9 @@ struct us_data {
/* The device we're working with
* It's important to note:
* (o) you must hold dev_semaphore to change pusb_dev
* (o) device_state should change whenever pusb_dev does
* (o) DEV_ATTACHED in bitflags should change whenever pusb_dev does
*/
struct semaphore dev_semaphore; /* protect pusb_dev */
atomic_t device_state; /* attached or detached */
struct usb_device *pusb_dev; /* this usb_device */
unsigned int flags; /* from filter initially */
......@@ -174,6 +174,7 @@ struct us_data {
struct semaphore ip_waitq; /* for CBI interrupts */
unsigned long bitflags; /* single-bit flags: */
#define IP_WANTED 1 /* is an IRQ expected? */
#define DEV_ATTACHED 2 /* is the dev. attached?*/
/* interrupt communications data */
struct semaphore irq_urb_sem; /* to protect irq_urb */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment