Hi Matt,
I've just added both sets of patches to CVS.
regards,
Stephen.
[antonia] ~/unix/linux-usb/storage > patch -p4 <~/temp
patching file scsiglue.c
Hunk #1 succeeded at 4 with fuzz 1.
patching file transport.c
patching file usb.c
patching file usb.h
Hunk #1 succeeded at 4 with fuzz 1.
[antonia] ~/unix/linux-usb/storage > patch -p4 < ~/temp
patching file debug.h
On Sat, 25 May 2002, Matthew Dharm wrote:
> So, my first BK patch. Once you figure out these tools, it's really not
> that bad... but the problem is the initial learning curve and the high
> shoot-yourself-in-the-foot potential.
>
> Greg, this won't compile without the next changeset (which I'm about to
> send). I figured that sending this via e-mail was going to be better than
> attempting a 'bk push' (will that even work)? This is based on a clone of
> your usb-2.5 tree... and I'm not even sure that's the right starting point.
>
> What will happen if I try to 'bk push' this back to linuxusb.bitmover.net?
> Will it even let me do that? I don't want to try it without some feedback
> telling me it's okay, as I don't want to risk messing up a remote
> repository -- I've already had to wipe and start over with my local
> repositories a few times....
>
> This material is _not_ in the CVS repository. It would be nice if someone
> would update CVS apropriately.
>
> Matt
>
> # This is a BitKeeper generated patch for the following project:
> # Project Name: greg k-h's linux 2.5 USB kernel tree
> # This patch format is intended for GNU patch command version 2.5 or higher.
> # This patch includes the following deltas:
> # ChangeSet 1.561 -> 1.562
> # drivers/usb/storage/scsiglue.c 1.11 -> 1.12
> # drivers/usb/storage/transport.c 1.17 -> 1.18
> # drivers/usb/storage/usb.h 1.5 -> 1.6
> # drivers/usb/storage/usb.c 1.16 -> 1.17
> #
> # The following is the BitKeeper ChangeSet Log
> # --------------------------------------------
> # 02/05/25 [EMAIL PROTECTED] 1.562
> # Cleanup of abort mechanism. This version should be much more crash resistant
>(dare I say crash-proof?)
> # --------------------------------------------
> #
> diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
> --- a/drivers/usb/storage/scsiglue.c Sat May 25 17:30:49 2002
> +++ b/drivers/usb/storage/scsiglue.c Sat May 25 17:30:49 2002
> @@ -4,7 +4,7 @@
> * $Id: scsiglue.c,v 1.26 2002/04/22 03:39:43 mdharm Exp $
> *
> * Current development and maintenance by:
> - * (c) 1999, 2000 Matthew Dharm ([EMAIL PROTECTED])
> + * (c) 1999-2002 Matthew Dharm ([EMAIL PROTECTED])
> *
> * Developed with the assistance of:
> * (c) 2000 David L. Brown, Jr. ([EMAIL PROTECTED])
> @@ -56,9 +56,6 @@
> */
>
> #define US_ACT_COMMAND 1
> -#define US_ACT_DEVICE_RESET 2
> -#define US_ACT_BUS_RESET 3
> -#define US_ACT_HOST_RESET 4
> #define US_ACT_EXIT 5
>
> /***********************************************************************
> diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
> --- a/drivers/usb/storage/transport.c Sat May 25 17:30:49 2002
> +++ b/drivers/usb/storage/transport.c Sat May 25 17:30:49 2002
> @@ -351,6 +351,29 @@
> * Data transfer routines
> ***********************************************************************/
>
> +/*
> + * This is subtle, so pay attention:
> + * ---------------------------------
> + * We're very concered about races with a command abort. Hanging this code is
> + * a sure fire way to hang the kernel.
> + *
> + * The abort function first sets the machine state, then tries to acquire the
> + * lock on the current_urb to abort it.
> + *
> + * Once a function grabs the current_urb_sem, then it -MUST- test the state to
> + * see if we just got aborted before the lock was grabbed. If so, it's
> + * essential to release the lock and return.
> + *
> + * The idea is that, once the current_urb_sem is held, the state can't really
> + * change anymore without also engaging the usb_unlink_urb() call _after_ the
> + * URB is actually submitted.
> + *
> + * So, we've guaranteed that (after the sm_state test), if we do submit the
> + * URB it will get aborted when we release the current_urb_sem. And we've
> + * also guaranteed that if the abort code was called before we held the
> + * current_urb_sem, we can safely get out before the URB is submitted.
> + */
> +
> /* This is the completion handler which will wake us up when an URB
> * completes.
> */
> @@ -363,6 +386,9 @@
>
> /* This is the common part of the URB message submission code
> * This function expects the current_urb_sem to be held upon entry.
> + *
> + * All URBs from the usb-storage driver _must_ pass through this function
> + * (or something like it) for the abort mechanisms to work properly.
> */
> static int usb_stor_msg_common(struct us_data *us)
> {
> @@ -385,16 +411,6 @@
> return status;
> }
>
> - /* has the current command been aborted? */
> - if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
> -
> - /* avoid a race with usb_stor_abort_transport():
> - * if the abort took place before we submitted
> - * the URB, we must cancel it ourselves */
> - if (us->current_urb->status == -EINPROGRESS)
> - usb_unlink_urb(us->current_urb);
> - }
> -
> /* wait for the completion of the URB */
> up(&(us->current_urb_sem));
> wait_for_completion(&urb_done);
> @@ -428,6 +444,12 @@
> /* lock the URB */
> down(&(us->current_urb_sem));
>
> + /* has the current command been aborted? */
> + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
> + up(&(us->current_urb_sem));
> + return 0;
> + }
> +
> /* fill the URB */
> FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe,
> (unsigned char*) &dr, data, size,
> @@ -456,6 +478,12 @@
> /* lock the URB */
> down(&(us->current_urb_sem));
>
> + /* has the current command been aborted? */
> + if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
> + up(&(us->current_urb_sem));
> + return 0;
> + }
> +
> /* fill the URB */
> FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len,
> usb_stor_blocking_completion, NULL);
> @@ -823,24 +851,31 @@
>
> /* If the current state is wrong or if there's
> * no srb, then there's nothing to do */
> - if ( !(state == US_STATE_RUNNING || state == US_STATE_RESETTING)
> - || !us->srb) {
> - US_DEBUGP("-- invalid current state\n");
> - return;
> - }
> + ASSERT((state == US_STATE_RUNNING || state == US_STATE_RESETTING));
> + ASSERT(us->srb);
> +
> + /* set state to abort */
> atomic_set(&us->sm_state, US_STATE_ABORTING);
>
> /* If the state machine is blocked waiting for an URB or an IRQ,
> - * let's wake it up */
> + * let's wake it up */
>
> - /* if we have an URB pending, cancel it */
> + /* If we have an URB pending, cancel it. Note that we guarantee with
> + * the current_urb_sem that either (a) an URB has just been submitted,
> + * or (b) the URB will never get submitted. But, because of the use
> + * of us->sm_state and current_urb_sem, we can't get an URB sumbitted
> + * _after_ we set the state to US_STATE_ABORTING and this section of
> + * code runs. Thus we avoid deadlocks.
> + */
> + down(&(us->current_urb_sem));
> if (us->current_urb->status == -EINPROGRESS) {
> US_DEBUGP("-- cancelling URB\n");
> usb_unlink_urb(us->current_urb);
> }
> + up(&(us->current_urb_sem));
>
> - /* if we are waiting for an IRQ, simulate it */
> - else if (test_bit(IP_WANTED, &us->bitflags)) {
> + /* If we are waiting for an IRQ, simulate it */
> + if (test_bit(IP_WANTED, &us->bitflags)) {
> US_DEBUGP("-- simulating missing IRQ\n");
> usb_stor_CBI_irq(us->irq_urb);
> }
> diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
> --- a/drivers/usb/storage/usb.c Sat May 25 17:30:49 2002
> +++ b/drivers/usb/storage/usb.c Sat May 25 17:30:49 2002
> @@ -102,9 +102,6 @@
> */
>
> #define US_ACT_COMMAND 1
> -#define US_ACT_DEVICE_RESET 2
> -#define US_ACT_BUS_RESET 3
> -#define US_ACT_HOST_RESET 4
> #define US_ACT_EXIT 5
>
> /* The list of structures and the protective lock for them */
> @@ -341,10 +338,12 @@
> for(;;) {
> struct Scsi_Host *host;
> US_DEBUGP("*** thread sleeping.\n");
> + atomic_set(&us->sm_state, US_STATE_IDLE);
> if(down_interruptible(&us->sema))
> break;
>
> US_DEBUGP("*** thread awakened.\n");
> + atomic_set(&us->sm_state, US_STATE_RUNNING);
>
> /* lock access to the queue element */
> spin_lock_irq(&us->queue_exclusion);
> @@ -358,145 +357,131 @@
> /* release the queue lock as fast as possible */
> spin_unlock_irq(&us->queue_exclusion);
>
> - switch (action) {
> - case US_ACT_COMMAND:
> - /* reject the command if the direction indicator
> - * is UNKNOWN
> - */
> - if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
> - US_DEBUGP("UNKNOWN data direction\n");
> - us->srb->result = DID_ERROR << 16;
> - scsi_lock(host);
> - us->srb->scsi_done(us->srb);
> - us->srb = NULL;
> - scsi_unlock(host);
> - break;
> - }
> + /* exit if we get a signal to exit */
> + if (action == US_ACT_EXIT) {
> + US_DEBUGP("-- US_ACT_EXIT command received\n");
> + break;
> + }
>
> - /* reject if target != 0 or if LUN is higher than
> - * the maximum known LUN
> - */
> - if (us->srb->target &&
> - !(us->flags & US_FL_SCM_MULT_TARG)) {
> - US_DEBUGP("Bad target number (%d/%d)\n",
> - us->srb->target, us->srb->lun);
> - us->srb->result = DID_BAD_TARGET << 16;
> -
> - scsi_lock(host);
> - us->srb->scsi_done(us->srb);
> - us->srb = NULL;
> - scsi_unlock(host);
> - break;
> - }
> + ASSERT (action == US_ACT_COMMAND);
>
> - if (us->srb->lun > us->max_lun) {
> - US_DEBUGP("Bad LUN (%d/%d)\n",
> - us->srb->target, us->srb->lun);
> - us->srb->result = DID_BAD_TARGET << 16;
> -
> - scsi_lock(host);
> - us->srb->scsi_done(us->srb);
> - us->srb = NULL;
> - scsi_unlock(host);
> - break;
> - }
> -
> - /* handle those devices which can't do a START_STOP */
> - if ((us->srb->cmnd[0] == START_STOP) &&
> - (us->flags & US_FL_START_STOP)) {
> - US_DEBUGP("Skipping START_STOP command\n");
> - us->srb->result = GOOD << 1;
> + /* reject the command if the direction indicator
> + * is UNKNOWN
> + */
> + if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
> + US_DEBUGP("UNKNOWN data direction\n");
> + us->srb->result = DID_ERROR << 16;
> + scsi_lock(host);
> + us->srb->scsi_done(us->srb);
> + us->srb = NULL;
> + scsi_unlock(host);
> + continue;
> + }
>
> - scsi_lock(host);
> - us->srb->scsi_done(us->srb);
> - us->srb = NULL;
> - scsi_unlock(host);
> - break;
> - }
> + /* reject if target != 0 or if LUN is higher than
> + * the maximum known LUN
> + */
> + if (us->srb->target &&
> + !(us->flags & US_FL_SCM_MULT_TARG)) {
> + US_DEBUGP("Bad target number (%d/%d)\n",
> + us->srb->target, us->srb->lun);
> + us->srb->result = DID_BAD_TARGET << 16;
> +
> + scsi_lock(host);
> + us->srb->scsi_done(us->srb);
> + us->srb = NULL;
> + scsi_unlock(host);
> + continue;
> + }
> +
> + if (us->srb->lun > us->max_lun) {
> + US_DEBUGP("Bad LUN (%d/%d)\n",
> + us->srb->target, us->srb->lun);
> + us->srb->result = DID_BAD_TARGET << 16;
> +
> + scsi_lock(host);
> + us->srb->scsi_done(us->srb);
> + us->srb = NULL;
> + scsi_unlock(host);
> + continue;
> + }
> +
> + /* handle those devices which can't do a START_STOP */
> + if ((us->srb->cmnd[0] == START_STOP) &&
> + (us->flags & US_FL_START_STOP)) {
> + US_DEBUGP("Skipping START_STOP command\n");
> + us->srb->result = GOOD << 1;
> +
> + scsi_lock(host);
> + us->srb->scsi_done(us->srb);
> + us->srb = NULL;
> + scsi_unlock(host);
> + continue;
> + }
>
> - /* lock the device pointers */
> - down(&(us->dev_semaphore));
> + /* lock the device pointers */
> + down(&(us->dev_semaphore));
>
> - /* our device has gone - pretend not ready */
> - if (atomic_read(&us->sm_state) == US_STATE_DETACHED) {
> - US_DEBUGP("Request is for removed device\n");
> - /* For REQUEST_SENSE, it's the data. But
> - * for anything else, it should look like
> - * we auto-sensed for it.
> - */
> - if (us->srb->cmnd[0] == REQUEST_SENSE) {
> - memcpy(us->srb->request_buffer,
> - usb_stor_sense_notready,
> - sizeof(usb_stor_sense_notready));
> - us->srb->result = GOOD << 1;
> - } else if(us->srb->cmnd[0] == INQUIRY) {
> - unsigned char data_ptr[36] = {
> - 0x20, 0x80, 0x02, 0x02,
> - 0x1F, 0x00, 0x00, 0x00};
> - US_DEBUGP("Faking INQUIRY command for
>disconnected device\n");
> - fill_inquiry_response(us, data_ptr, 36);
> - us->srb->result = GOOD << 1;
> - } else {
> - memcpy(us->srb->sense_buffer,
> - usb_stor_sense_notready,
> - sizeof(usb_stor_sense_notready));
> - us->srb->result = CHECK_CONDITION << 1;
> - }
> - } else { /* atomic_read(&us->sm_state) == STATE_DETACHED */
> -
> - /* Handle those devices which need us to fake
> - * their inquiry data */
> - if ((us->srb->cmnd[0] == INQUIRY) &&
> - (us->flags & US_FL_FIX_INQUIRY)) {
> - unsigned char data_ptr[36] = {
> - 0x00, 0x80, 0x02, 0x02,
> - 0x1F, 0x00, 0x00, 0x00};
> -
> - US_DEBUGP("Faking INQUIRY command\n");
> - fill_inquiry_response(us, data_ptr, 36);
> - us->srb->result = GOOD << 1;
> - } else {
> - /* we've got a command, let's do it! */
> - US_DEBUG(usb_stor_show_command(us->srb));
> - atomic_set(&us->sm_state, US_STATE_RUNNING);
> - us->proto_handler(us->srb, us);
> - atomic_set(&us->sm_state, US_STATE_IDLE);
> - }
> + /* our device has gone - pretend not ready */
> + if (atomic_read(&us->device_state) == US_STATE_DETACHED) {
> + US_DEBUGP("Request is for removed device\n");
> + /* For REQUEST_SENSE, it's the data. But
> + * for anything else, it should look like
> + * we auto-sensed for it.
> + */
> + if (us->srb->cmnd[0] == REQUEST_SENSE) {
> + memcpy(us->srb->request_buffer,
> + usb_stor_sense_notready,
> + sizeof(usb_stor_sense_notready));
> + us->srb->result = GOOD << 1;
> + } else if(us->srb->cmnd[0] == INQUIRY) {
> + unsigned char data_ptr[36] = {
> + 0x20, 0x80, 0x02, 0x02,
> + 0x1F, 0x00, 0x00, 0x00};
> + US_DEBUGP("Faking INQUIRY command for disconnected
>device\n");
> + fill_inquiry_response(us, data_ptr, 36);
> + us->srb->result = GOOD << 1;
> + } else {
> + memcpy(us->srb->sense_buffer,
> + usb_stor_sense_notready,
> + sizeof(usb_stor_sense_notready));
> + us->srb->result = CHECK_CONDITION << 1;
> }
> + } else { /* atomic_read(&us->device_state) == STATE_DETACHED */
>
> - /* unlock the device pointers */
> - up(&(us->dev_semaphore));
> + /* Handle those devices which need us to fake
> + * their inquiry data */
> + if ((us->srb->cmnd[0] == INQUIRY) &&
> + (us->flags & US_FL_FIX_INQUIRY)) {
> + unsigned char data_ptr[36] = {
> + 0x00, 0x80, 0x02, 0x02,
> + 0x1F, 0x00, 0x00, 0x00};
>
> - /* indicate that the command is done */
> - if (us->srb->result != DID_ABORT << 16) {
> - US_DEBUGP("scsi cmd done, result=0x%x\n",
> - us->srb->result);
> - scsi_lock(host);
> - us->srb->scsi_done(us->srb);
> - us->srb = NULL;
> - scsi_unlock(host);
> + US_DEBUGP("Faking INQUIRY command\n");
> + fill_inquiry_response(us, data_ptr, 36);
> + us->srb->result = GOOD << 1;
> } else {
> - US_DEBUGP("scsi command aborted\n");
> - us->srb = NULL;
> - complete(&(us->notify));
> + /* we've got a command, let's do it! */
> + US_DEBUG(usb_stor_show_command(us->srb));
> + us->proto_handler(us->srb, us);
> }
> - break;
> -
> - case US_ACT_DEVICE_RESET:
> - break;
> -
> - case US_ACT_BUS_RESET:
> - break;
> -
> - case US_ACT_HOST_RESET:
> - break;
> + }
>
> - } /* end switch on action */
> + /* unlock the device pointers */
> + up(&(us->dev_semaphore));
>
> - /* exit if we get a signal to exit */
> - if (action == US_ACT_EXIT) {
> - US_DEBUGP("-- US_ACT_EXIT command received\n");
> - break;
> + /* indicate that the command is done */
> + if (us->srb->result != DID_ABORT << 16) {
> + US_DEBUGP("scsi cmd done, result=0x%x\n",
> + us->srb->result);
> + scsi_lock(host);
> + us->srb->scsi_done(us->srb);
> + us->srb = NULL;
> + scsi_unlock(host);
> + } else {
> + US_DEBUGP("scsi command aborted\n");
> + us->srb = NULL;
> + complete(&(us->notify));
> }
> } /* for (;;) */
>
> @@ -722,7 +707,7 @@
> /* establish the connection to the new device upon reconnect */
> ss->ifnum = ifnum;
> ss->pusb_dev = dev;
> - atomic_set(&ss->sm_state, US_STATE_IDLE);
> + atomic_set(&ss->device_state, US_STATE_ATTACHED);
>
> /* copy over the endpoint data */
> if (ep_in)
> @@ -1013,6 +998,7 @@
>
> /* start up our control thread */
> atomic_set(&ss->sm_state, US_STATE_IDLE);
> + atomic_set(&ss->device_state, US_STATE_ATTACHED);
> ss->pid = kernel_thread(usb_stor_control_thread, ss,
> CLONE_VM);
> if (ss->pid < 0) {
> diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
> --- a/drivers/usb/storage/usb.h Sat May 25 17:30:49 2002
> +++ b/drivers/usb/storage/usb.h Sat May 25 17:30:49 2002
> @@ -4,7 +4,7 @@
> * $Id: usb.h,v 1.21 2002/04/21 02:57:59 mdharm Exp $
> *
> * Current development and maintenance by:
> - * (c) 1999, 2000 Matthew Dharm ([EMAIL PROTECTED])
> + * (c) 1999-2002 Matthew Dharm ([EMAIL PROTECTED])
> *
> * Initial work by:
> * (c) 1999 Michael Gee ([EMAIL PROTECTED])
> @@ -102,11 +102,15 @@
> #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
> #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
>
> -#define US_STATE_DETACHED 1 /* State machine states */
> -#define US_STATE_IDLE 2
> -#define US_STATE_RUNNING 3
> -#define US_STATE_RESETTING 4
> -#define US_STATE_ABORTING 5
> +/* device attached/detached states */
> +#define US_STATE_DETACHED 1
> +#define US_STATE_ATTACHED 2
> +
> +/* processing state machine states */
> +#define US_STATE_IDLE 1
> +#define US_STATE_RUNNING 2
> +#define US_STATE_RESETTING 3
> +#define US_STATE_ABORTING 4
>
> #define USB_STOR_STRING_LEN 32
>
> @@ -119,8 +123,13 @@
> struct us_data {
> struct us_data *next; /* next device */
>
> - /* the device we're working with */
> + /* 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
> + */
> 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 */
>
>
--
/------------------------------------+-------------------------\
|Stephen J. Gowdy | SLAC, MailStop 34, |
|http://www.slac.stanford.edu/~gowdy/ | 2575 Sand Hill Road, |
|http://calendar.yahoo.com/gowdy | Menlo Park CA 94025, USA |
|EMail: [EMAIL PROTECTED] | Tel: +1 650 926 3144 |
\------------------------------------+-------------------------/
_______________________________________________________________
Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas -- http://devcon.sprintpcs.com/adp/index.cfm
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel