Commit a98b28b1 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge bk://kernel.bkbits.net/acme/usb-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 832b5fae 25d1aa56
...@@ -59,3 +59,6 @@ obj-$(CONFIG_USB_TEST) += misc/ ...@@ -59,3 +59,6 @@ obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_TIGL) += misc/ obj-$(CONFIG_USB_TIGL) += misc/
obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_NET2280) += gadget/
obj-$(CONFIG_USB_ZERO) += gadget/
obj-$(CONFIG_USB_ETH) += gadget/
...@@ -1199,12 +1199,18 @@ int usb_physical_reset_device(struct usb_device *dev) ...@@ -1199,12 +1199,18 @@ int usb_physical_reset_device(struct usb_device *dev)
if (port < 0) if (port < 0)
return -ENOENT; return -ENOENT;
descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
if (!descriptor) {
return -ENOMEM;
}
down(&usb_address0_sem); down(&usb_address0_sem);
/* Send a reset to the device */ /* Send a reset to the device */
if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) { if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) {
usb_hub_port_disable(parent, port); usb_hub_port_disable(parent, port);
up(&usb_address0_sem); up(&usb_address0_sem);
kfree(descriptor);
return(-ENODEV); return(-ENODEV);
} }
...@@ -1214,6 +1220,7 @@ int usb_physical_reset_device(struct usb_device *dev) ...@@ -1214,6 +1220,7 @@ int usb_physical_reset_device(struct usb_device *dev)
err("USB device not accepting new address (error=%d)", ret); err("USB device not accepting new address (error=%d)", ret);
usb_hub_port_disable(parent, port); usb_hub_port_disable(parent, port);
up(&usb_address0_sem); up(&usb_address0_sem);
kfree(descriptor);
return ret; return ret;
} }
...@@ -1231,10 +1238,7 @@ int usb_physical_reset_device(struct usb_device *dev) ...@@ -1231,10 +1238,7 @@ int usb_physical_reset_device(struct usb_device *dev)
* If nothing changed, we reprogram the configuration and then * If nothing changed, we reprogram the configuration and then
* the alternate settings. * the alternate settings.
*/ */
descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
if (!descriptor) {
return -ENOMEM;
}
ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor, ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor,
sizeof(*descriptor)); sizeof(*descriptor));
if (ret < 0) { if (ret < 0) {
......
...@@ -22,63 +22,54 @@ static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATU ...@@ -22,63 +22,54 @@ static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATU
#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__) #define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
/* global variables */ static Scsi_Host_Template hpusbscsi_scsi_host_template = {
.module = THIS_MODULE,
struct list_head hpusbscsi_devices; .name = "hpusbscsi",
//LIST_HEAD(hpusbscsi_devices); .proc_name = "hpusbscsi",
.queuecommand = hpusbscsi_scsi_queuecommand,
/* USB related parts */ .eh_abort_handler = hpusbscsi_scsi_abort,
.eh_host_reset_handler = hpusbscsi_scsi_host_reset,
.sg_tablesize = SG_ALL,
.can_queue = 1,
.this_id = -1,
.cmd_per_lun = 1,
.use_clustering = 1,
.emulated = 1,
};
static int static int
hpusbscsi_usb_probe (struct usb_interface *intf, hpusbscsi_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *altsetting = intf->altsetting;
struct hpusbscsi *new; struct hpusbscsi *new;
struct usb_device *dev = interface_to_usbdev (intf); int error = -ENOMEM;
struct usb_host_interface *altsetting =
&(intf->altsetting[0]);
int i, result; int i, result;
/* basic check */
if (altsetting->desc.bNumEndpoints != 3) { if (altsetting->desc.bNumEndpoints != 3) {
printk (KERN_ERR "Wrong number of endpoints\n"); printk (KERN_ERR "Wrong number of endpoints\n");
return -ENODEV; return -ENODEV;
} }
/* descriptor allocation */ new = kmalloc(sizeof(struct hpusbscsi), GFP_KERNEL);
if (!new)
new =
(struct hpusbscsi *) kmalloc (sizeof (struct hpusbscsi),
GFP_KERNEL);
if (new == NULL)
return -ENOMEM; return -ENOMEM;
DEBUG ("Allocated memory\n"); memset(new, 0, sizeof(struct hpusbscsi));
memset (new, 0, sizeof (struct hpusbscsi));
new->dataurb = usb_alloc_urb(0, GFP_KERNEL); new->dataurb = usb_alloc_urb(0, GFP_KERNEL);
if (!new->dataurb) { if (!new->dataurb)
kfree (new); goto out_kfree;
return -ENOMEM;
}
new->controlurb = usb_alloc_urb(0, GFP_KERNEL); new->controlurb = usb_alloc_urb(0, GFP_KERNEL);
if (!new->controlurb) { if (!new->controlurb)
usb_free_urb (new->dataurb); goto out_free_dataurb;
kfree (new);
return -ENOMEM;
}
new->dev = dev;
init_waitqueue_head (&new->pending);
init_waitqueue_head (&new->deathrow);
INIT_LIST_HEAD (&new->lh);
new->dev = dev;
init_waitqueue_head(&new->pending);
init_waitqueue_head(&new->deathrow);
/* finding endpoints */ error = -ENODEV;
for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
if ( if ((altsetting->endpoint[i].desc.
(altsetting->endpoint[i].desc.
bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK) { USB_ENDPOINT_XFER_BULK) {
if (altsetting->endpoint[i].desc. if (altsetting->endpoint[i].desc.
...@@ -97,57 +88,71 @@ hpusbscsi_usb_probe (struct usb_interface *intf, ...@@ -97,57 +88,71 @@ hpusbscsi_usb_probe (struct usb_interface *intf,
new->ep_int = new->ep_int =
altsetting->endpoint[i].desc. altsetting->endpoint[i].desc.
bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
new->interrupt_interval= altsetting->endpoint[i].desc.bInterval; new->interrupt_interval= altsetting->endpoint[i].desc.
bInterval;
} }
} }
/* USB initialisation magic for the simple case */ /* USB initialisation magic for the simple case */
result = usb_set_interface(dev, altsetting->desc.bInterfaceNumber, 0);
result = usb_set_interface (dev, altsetting->desc.bInterfaceNumber, 0);
switch (result) { switch (result) {
case 0: /* no error */ case 0: /* no error */
break; break;
default: default:
printk (KERN_ERR "unknown error %d from usb_set_interface\n", printk(KERN_ERR "unknown error %d from usb_set_interface\n",
result); result);
goto err_out; goto out_free_controlurb;
} }
/* making a template for the scsi layer to fake detection of a scsi device */ /* build and submit an interrupt URB for status byte handling */
usb_fill_int_urb(new->controlurb, new->dev,
usb_rcvintpipe(new->dev, new->ep_int),
&new->scsi_state_byte, 1,
control_interrupt_callback,new,
new->interrupt_interval);
if (usb_submit_urb(new->controlurb, GFP_KERNEL) < 0)
goto out_free_controlurb;
memcpy (&(new->ctempl), &hpusbscsi_scsi_host_template, /* In host->hostdata we store a pointer to desc */
sizeof (hpusbscsi_scsi_host_template)); new->host = scsi_register(&hpusbscsi_scsi_host_template, sizeof(new));
(struct hpusbscsi *) new->ctempl.proc_dir = new; if (!new->host)
new->ctempl.module = THIS_MODULE; goto out_unlink_controlurb;
if (scsi_register_host(&new->ctempl)) new->host->hostdata[0] = (unsigned long)new;
goto err_out; scsi_add_host(new->host, &intf->dev);
new->sense_command[0] = REQUEST_SENSE; new->sense_command[0] = REQUEST_SENSE;
new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH; new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
/* adding to list for module unload */
list_add (&hpusbscsi_devices, &new->lh);
usb_set_intfdata(intf, new); usb_set_intfdata(intf, new);
return 0; return 0;
err_out: out_unlink_controlurb:
usb_free_urb (new->controlurb); usb_unlink_urb(new->controlurb);
usb_free_urb (new->dataurb); out_free_controlurb:
kfree (new); usb_free_urb(new->controlurb);
return -ENODEV; out_free_dataurb:
usb_free_urb(new->dataurb);
out_kfree:
kfree(new);
return error;
} }
static void static void
hpusbscsi_usb_disconnect (struct usb_interface *intf) hpusbscsi_usb_disconnect(struct usb_interface *intf)
{ {
struct hpusbscsi *desc = usb_get_intfdata(intf); struct hpusbscsi *desc = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
if (desc)
scsi_remove_host(desc->host);
usb_unlink_urb(desc->controlurb); usb_unlink_urb(desc->controlurb);
scsi_unregister(desc->host);
usb_free_urb(desc->controlurb);
usb_free_urb(desc->dataurb);
kfree(desc);
} }
static struct usb_device_id hpusbscsi_usb_ids[] = { static struct usb_device_id hpusbscsi_usb_ids[] = {
...@@ -178,101 +183,21 @@ static struct usb_driver hpusbscsi_usb_driver = { ...@@ -178,101 +183,21 @@ static struct usb_driver hpusbscsi_usb_driver = {
/* module initialisation */ /* module initialisation */
int __init static int __init
hpusbscsi_init (void) hpusbscsi_init (void)
{ {
int result; return usb_register(&hpusbscsi_usb_driver);
INIT_LIST_HEAD (&hpusbscsi_devices);
DEBUG ("Driver loaded\n");
if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
printk (KERN_ERR "hpusbscsi: driver registration failed\n");
return -1;
} else {
return 0;
}
} }
void __exit static void __exit
hpusbscsi_exit (void) hpusbscsi_exit (void)
{ {
struct list_head *tmp; usb_deregister(&hpusbscsi_usb_driver);
struct list_head *old;
struct hpusbscsi * o;
for (tmp = hpusbscsi_devices.next; tmp != &hpusbscsi_devices;/*nothing */) {
old = tmp;
tmp = tmp->next;
o = (struct hpusbscsi *)old;
usb_unlink_urb(o->controlurb);
scsi_unregister_host(&o->ctempl);
usb_free_urb(o->controlurb);
usb_free_urb(o->dataurb);
kfree(old);
}
usb_deregister (&hpusbscsi_usb_driver);
} }
module_init (hpusbscsi_init); module_init (hpusbscsi_init);
module_exit (hpusbscsi_exit); module_exit (hpusbscsi_exit);
/* interface to the scsi layer */
static int
hpusbscsi_scsi_detect (struct SHT *sht)
{
/* Whole function stolen from usb-storage */
struct hpusbscsi *desc = (struct hpusbscsi *) sht->proc_dir;
/* What a hideous hack! */
char local_name[48];
/* set up the name of our subdirectory under /proc/scsi/ */
sprintf (local_name, "hpusbscsi-%d", desc->number);
sht->proc_name = kmalloc (strlen (local_name) + 1, GFP_KERNEL);
/* FIXME: where is this freed ? */
if (!sht->proc_name) {
return 0;
}
strcpy (sht->proc_name, local_name);
sht->proc_dir = NULL;
/* build and submit an interrupt URB for status byte handling */
usb_fill_int_urb(desc->controlurb,
desc->dev,
usb_rcvintpipe(desc->dev,desc->ep_int),
&desc->scsi_state_byte,
1,
control_interrupt_callback,
desc,
desc->interrupt_interval
);
if ( 0 > usb_submit_urb(desc->controlurb, GFP_KERNEL)) {
kfree(sht->proc_name);
return 0;
}
/* In host->hostdata we store a pointer to desc */
desc->host = scsi_register (sht, sizeof (desc));
if (desc->host == NULL) {
kfree (sht->proc_name);
usb_unlink_urb(desc->controlurb);
return 0;
}
desc->host->hostdata[0] = (unsigned long) desc;
return 1;
}
static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback) static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
{ {
struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]); struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
......
...@@ -13,7 +13,6 @@ typedef void (*scsi_callback)(Scsi_Cmnd *); ...@@ -13,7 +13,6 @@ typedef void (*scsi_callback)(Scsi_Cmnd *);
struct hpusbscsi struct hpusbscsi
{ {
struct list_head lh;
struct usb_device *dev; /* NULL indicates unplugged device */ struct usb_device *dev; /* NULL indicates unplugged device */
int ep_out; int ep_out;
int ep_in; int ep_in;
...@@ -36,7 +35,6 @@ struct hpusbscsi ...@@ -36,7 +35,6 @@ struct hpusbscsi
int state; int state;
int current_data_pipe; int current_data_pipe;
Scsi_Host_Template ctempl;
u8 sense_command[SENSE_COMMAND_SIZE]; u8 sense_command[SENSE_COMMAND_SIZE];
u8 scsi_state_byte; u8 scsi_state_byte;
}; };
...@@ -52,7 +50,6 @@ static const unsigned char scsi_command_direction[256/8] = { ...@@ -52,7 +50,6 @@ static const unsigned char scsi_command_direction[256/8] = {
#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1) #define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
static int hpusbscsi_scsi_detect (struct SHT * sht);
static void simple_command_callback(struct urb *u, struct pt_regs *regs); static void simple_command_callback(struct urb *u, struct pt_regs *regs);
static void scatter_gather_callback(struct urb *u, struct pt_regs *regs); static void scatter_gather_callback(struct urb *u, struct pt_regs *regs);
static void simple_payload_callback (struct urb *u, struct pt_regs *regs); static void simple_payload_callback (struct urb *u, struct pt_regs *regs);
...@@ -64,25 +61,6 @@ static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb); ...@@ -64,25 +61,6 @@ static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb); static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
static void issue_request_sense (struct hpusbscsi *hpusbscsi); static void issue_request_sense (struct hpusbscsi *hpusbscsi);
static Scsi_Host_Template hpusbscsi_scsi_host_template = {
.name = "hpusbscsi",
.detect = hpusbscsi_scsi_detect,
// .release = hpusbscsi_scsi_release,
.queuecommand = hpusbscsi_scsi_queuecommand,
.eh_abort_handler = hpusbscsi_scsi_abort,
.eh_host_reset_handler = hpusbscsi_scsi_host_reset,
.sg_tablesize = SG_ALL,
.can_queue = 1,
.this_id = -1,
.cmd_per_lun = 1,
.present = 0,
.unchecked_isa_dma = FALSE,
.use_clustering = TRUE,
.emulated = TRUE
};
/* defines for internal driver state */ /* defines for internal driver state */
#define HP_STATE_FREE 0 /*ready for next request */ #define HP_STATE_FREE 0 /*ready for next request */
#define HP_STATE_BEGINNING 1 /*command being transferred */ #define HP_STATE_BEGINNING 1 /*command being transferred */
......
...@@ -327,76 +327,6 @@ static inline void mts_urb_abort(struct mts_desc* desc) { ...@@ -327,76 +327,6 @@ static inline void mts_urb_abort(struct mts_desc* desc) {
usb_unlink_urb( desc->urb ); usb_unlink_urb( desc->urb );
} }
static struct mts_desc * mts_list; /* list of active scanners */
struct semaphore mts_list_semaphore;
/* Internal list operations */
static
void mts_remove_nolock( struct mts_desc* to_remove )
{
MTS_DEBUG( "removing 0x%x from list\n",
(int)to_remove );
lock_kernel();
mts_urb_abort(to_remove);
MTS_DEBUG_GOT_HERE();
if ( to_remove != mts_list ) {
MTS_DEBUG_GOT_HERE();
if (to_remove->prev && to_remove->next)
to_remove->prev->next = to_remove->next;
} else {
MTS_DEBUG_GOT_HERE();
mts_list = to_remove->next;
if (mts_list) {
MTS_DEBUG_GOT_HERE();
mts_list->prev = 0;
}
}
if ( to_remove->next ) {
MTS_DEBUG_GOT_HERE();
to_remove->next->prev = to_remove->prev;
}
MTS_DEBUG_GOT_HERE();
scsi_unregister_host(&to_remove->ctempl);
unlock_kernel();
usb_free_urb(to_remove->urb);
kfree( to_remove );
}
static
void mts_add_nolock( struct mts_desc* to_add )
{
MTS_DEBUG( "adding 0x%x to list\n", (int)to_add );
to_add->prev = 0;
to_add->next = mts_list;
if ( mts_list ) {
mts_list->prev = to_add;
}
mts_list = to_add;
}
/* SCSI driver interface */
/* scsi related functions - dummies for now mostly */
static int mts_scsi_release(struct Scsi_Host *psh)
{
MTS_DEBUG_GOT_HERE();
return 0;
}
static int mts_scsi_abort (Scsi_Cmnd *srb) static int mts_scsi_abort (Scsi_Cmnd *srb)
{ {
struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
...@@ -419,54 +349,6 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb) ...@@ -419,54 +349,6 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb)
return 0; /* RANT why here 0 and not SUCCESS */ return 0; /* RANT why here 0 and not SUCCESS */
} }
/* the core of the scsi part */
/* faking a detection - which can't fail :-) */
static int mts_scsi_detect (struct SHT * sht)
{
/* Whole function stolen from usb-storage */
struct mts_desc * desc = (struct mts_desc *)sht->proc_dir;
/* What a hideous hack! */
char local_name[48];
MTS_DEBUG_GOT_HERE();
/* set up the name of our subdirectory under /proc/scsi/ */
sprintf(local_name, "microtek-%d", desc->host_number);
sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
/* FIXME: where is this freed ? */
if (!sht->proc_name) {
MTS_ERROR( "unable to allocate memory for proc interface!!\n" );
return 0;
}
strcpy(sht->proc_name, local_name);
sht->proc_dir = NULL;
/* In host->hostdata we store a pointer to desc */
desc->host = scsi_register(sht, sizeof(desc));
if (desc->host == NULL) {
MTS_ERROR("Cannot register due to low memory");
kfree(sht->proc_name);
return 0;
}
desc->host->hostdata[0] = (unsigned long)desc;
/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
return 1;
}
/* Main entrypoint: SCSI commands are dispatched to here */
static static
int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ); int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
...@@ -744,52 +626,22 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ) ...@@ -744,52 +626,22 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
out: out:
return err; return err;
} }
/*
* this defines our 'host'
*/
/* NOTE: This is taken from usb-storage, should be right. */
static Scsi_Host_Template mts_scsi_host_template = { static Scsi_Host_Template mts_scsi_host_template = {
.module = THIS_MODULE,
.name = "microtekX6", .name = "microtekX6",
.detect = mts_scsi_detect, .proc_name = "microtekX6",
.release = mts_scsi_release,
.queuecommand = mts_scsi_queuecommand, .queuecommand = mts_scsi_queuecommand,
.eh_abort_handler = mts_scsi_abort, .eh_abort_handler = mts_scsi_abort,
.eh_host_reset_handler =mts_scsi_host_reset, .eh_host_reset_handler = mts_scsi_host_reset,
.sg_tablesize = SG_ALL, .sg_tablesize = SG_ALL,
.can_queue = 1, .can_queue = 1,
.this_id = -1, .this_id = -1,
.cmd_per_lun = 1, .cmd_per_lun = 1,
.present = 0, .use_clustering = 1,
.unchecked_isa_dma = FALSE, .emulated = 1,
.use_clustering = TRUE,
.emulated = TRUE
}; };
/* USB layer driver interface implementation */
static void mts_usb_disconnect (struct usb_interface *intf)
{
struct mts_desc* to_remove = usb_get_intfdata(intf);
MTS_DEBUG_GOT_HERE();
usb_set_intfdata(intf, NULL);
if (to_remove) {
/* leave the list - lock it */
down(&mts_list_semaphore);
mts_remove_nolock(to_remove);
up(&mts_list_semaphore);
}
}
struct vendor_product struct vendor_product
{ {
char* name; char* name;
...@@ -837,7 +689,7 @@ static struct usb_device_id mts_usb_ids [] = ...@@ -837,7 +689,7 @@ static struct usb_device_id mts_usb_ids [] =
MODULE_DEVICE_TABLE (usb, mts_usb_ids); MODULE_DEVICE_TABLE (usb, mts_usb_ids);
static int mts_usb_probe (struct usb_interface *intf, static int mts_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
int i; int i;
...@@ -930,39 +782,23 @@ static int mts_usb_probe (struct usb_interface *intf, ...@@ -930,39 +782,23 @@ static int mts_usb_probe (struct usb_interface *intf,
} }
/* allocating a new descriptor */ new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL); if (!new_desc)
if (new_desc == NULL) goto out;
{
MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
return -ENOMEM;
}
memset( new_desc, 0, sizeof(*new_desc) ); memset(new_desc, 0, sizeof(*new_desc));
new_desc->urb = usb_alloc_urb(0, GFP_KERNEL); new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!new_desc->urb) { if (!new_desc->urb)
kfree(new_desc); goto out_kfree;
return -ENOMEM;
}
/* initialising that descriptor */
new_desc->usb_dev = dev; new_desc->usb_dev = dev;
init_MUTEX(&new_desc->lock); init_MUTEX(&new_desc->lock);
if(mts_list){
new_desc->host_number = mts_list->host_number+1;
} else {
new_desc->host_number = 0;
}
/* endpoints */ /* endpoints */
new_desc->ep_out = ep_out; new_desc->ep_out = ep_out;
new_desc->ep_response = ep_in_set[0]; new_desc->ep_response = ep_in_set[0];
new_desc->ep_image = ep_in_set[1]; new_desc->ep_image = ep_in_set[1];
if ( new_desc->ep_out != MTS_EP_OUT ) if ( new_desc->ep_out != MTS_EP_OUT )
MTS_WARNING( "will this work? Command EP is not usually %d\n", MTS_WARNING( "will this work? Command EP is not usually %d\n",
(int)new_desc->ep_out ); (int)new_desc->ep_out );
...@@ -975,87 +811,48 @@ static int mts_usb_probe (struct usb_interface *intf, ...@@ -975,87 +811,48 @@ static int mts_usb_probe (struct usb_interface *intf,
MTS_WARNING( "will this work? Image data EP is not usually %d\n", MTS_WARNING( "will this work? Image data EP is not usually %d\n",
(int)new_desc->ep_image ); (int)new_desc->ep_image );
new_desc->host = scsi_register(&mts_scsi_host_template,
sizeof(new_desc));
if (!new_desc->host)
goto out_free_urb;
/* Initialize the host template based on the default one */ new_desc->host->hostdata[0] = (unsigned long)new_desc;
memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template)); scsi_add_host(new_desc->host, NULL);
/* HACK from usb-storage - this is needed for scsi detection */
(struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */
MTS_DEBUG("registering SCSI module\n"); usb_set_intfdata(intf, new_desc);
return 0;
new_desc->ctempl.module = THIS_MODULE;
result = scsi_register_host(&new_desc->ctempl);
/* Will get hit back in microtek_detect by this func */
if ( result )
{
MTS_ERROR( "error %d from scsi_register_host! Help!\n",
(int)result );
/* FIXME: need more cleanup? */ out_free_urb:
kfree( new_desc ); usb_free_urb(new_desc->urb);
out_kfree:
kfree(new_desc);
out:
return -ENOMEM; return -ENOMEM;
} }
MTS_DEBUG_GOT_HERE();
/* FIXME: the bomb is armed, must the host be registered under lock ? */
/* join the list - lock it */
down(&mts_list_semaphore);
mts_add_nolock( new_desc );
up(&mts_list_semaphore); static void mts_usb_disconnect (struct usb_interface *intf)
{
struct mts_desc *desc = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
MTS_DEBUG("completed probe and exiting happily\n"); scsi_remove_host(desc->host);
usb_unlink_urb(desc->urb);
scsi_unregister(desc->host);
usb_set_intfdata(intf, new_desc); usb_free_urb(desc->urb);
return 0; kfree(desc);
} }
static int __init microtek_drv_init(void)
/* get us noticed by the rest of the kernel */
int __init microtek_drv_init(void)
{ {
int result; return usb_register(&mts_usb_driver);
MTS_DEBUG_GOT_HERE();
init_MUTEX(&mts_list_semaphore);
if ((result = usb_register(&mts_usb_driver)) < 0) {
MTS_DEBUG("usb_register returned %d\n", result );
return -1;
} else {
MTS_DEBUG("driver registered.\n");
}
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
} }
void __exit microtek_drv_exit(void) static void __exit microtek_drv_exit(void)
{ {
struct mts_desc* next;
MTS_DEBUG_GOT_HERE();
usb_deregister(&mts_usb_driver); usb_deregister(&mts_usb_driver);
down(&mts_list_semaphore);
while (mts_list) {
/* keep track of where the next one is */
next = mts_list->next;
mts_remove_nolock( mts_list );
/* advance the list pointer */
mts_list = next;
}
up(&mts_list_semaphore);
} }
module_init(microtek_drv_init); module_init(microtek_drv_init);
......
...@@ -38,9 +38,6 @@ struct mts_desc { ...@@ -38,9 +38,6 @@ struct mts_desc {
u8 ep_image; u8 ep_image;
struct Scsi_Host * host; struct Scsi_Host * host;
Scsi_Host_Template ctempl;
int host_number;
struct semaphore lock; struct semaphore lock;
struct urb *urb; struct urb *urb;
......
...@@ -171,9 +171,11 @@ static int usb_storage_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) ...@@ -171,9 +171,11 @@ static int usb_storage_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
/* This is always called with scsi_lock(srb->host) held */ /* This is always called with scsi_lock(srb->host) held */
static int usb_storage_command_abort( Scsi_Cmnd *srb ) static int usb_storage_command_abort( Scsi_Cmnd *srb )
{ {
struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; struct Scsi_Host *host = srb->device->host;
struct us_data *us = (struct us_data *) host->hostdata[0];
int state = atomic_read(&us->sm_state);
US_DEBUGP("command_abort() called\n"); US_DEBUGP("%s called\n", __FUNCTION__);
/* Is this command still active? */ /* Is this command still active? */
if (us->srb != srb) { if (us->srb != srb) {
...@@ -181,7 +183,31 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb ) ...@@ -181,7 +183,31 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb )
return FAILED; return FAILED;
} }
return usb_stor_abort_transport(us); /* Normally the current state is RUNNING. If the control thread
* hasn't even started processing this command, the state will be
* IDLE. Anything else is a bug. */
if (state != US_STATE_RUNNING && state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
return FAILED;
}
/* Set state to ABORTING, set the ABORTING bit, and release the lock */
atomic_set(&us->sm_state, US_STATE_ABORTING);
set_bit(US_FLIDX_ABORTING, &us->flags);
scsi_unlock(host);
/* If the state was RUNNING, stop an ongoing USB transfer */
if (state == US_STATE_RUNNING)
usb_stor_stop_transport(us);
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
/* Reacquire the lock and allow USB transfers to resume */
scsi_lock(host);
clear_bit(US_FLIDX_ABORTING, &us->flags);
return SUCCESS;
} }
/* This invokes the transport reset mechanism to reset the state of the /* This invokes the transport reset mechanism to reset the state of the
......
This diff is collapsed.
...@@ -156,22 +156,18 @@ extern int usb_stor_Bulk_max_lun(struct us_data*); ...@@ -156,22 +156,18 @@ extern int usb_stor_Bulk_max_lun(struct us_data*);
extern int usb_stor_Bulk_reset(struct us_data*); extern int usb_stor_Bulk_reset(struct us_data*);
extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*); extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
extern int usb_stor_abort_transport(struct us_data*); extern void usb_stor_stop_transport(struct us_data*);
extern int usb_stor_bulk_msg(struct us_data *us, void *data,
unsigned int pipe, unsigned int len, unsigned int *act_len);
extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size); void *data, u16 size);
extern int usb_stor_interrupt_msg(struct us_data *us, void *data,
unsigned int len, unsigned int *act_len);
extern int usb_stor_clear_halt(struct us_data*, unsigned int pipe); extern int usb_stor_clear_halt(struct us_data*, unsigned int pipe);
extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size); void *data, u16 size);
extern int usb_stor_intr_transfer(struct us_data *us, void *buf, extern int usb_stor_intr_transfer(struct us_data *us, void *buf,
unsigned int length, unsigned int *act_len); unsigned int length);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len); void *buf, unsigned int length, unsigned int *act_len);
extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
......
...@@ -314,32 +314,17 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, ...@@ -314,32 +314,17 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk> * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/ */
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"ASAHI PENTAX", "Pentax",
"PENTAX OPTIO 430", "Optio 2/3/400",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"ASAHI PENTAX",
"PENTAX OPTIO 430",
US_SC_8070, US_PR_CBI, NULL, US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ), US_FL_FIX_INQUIRY ),
/* Pentax Optio S digital camera /* Submitted by Per Winkvist <per.winkvist@uk.com> */
* submitted by Stefan M. Brandl <smb@smbnet.de> UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
*/
UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff,
"Pentax", "Pentax",
"Optio S", "Optio S",
US_SC_8070, US_PR_CB, NULL, US_SC_8070, US_PR_CBI, NULL,
US_FL_MODE_XLATE|US_FL_FIX_INQUIRY), US_FL_FIX_INQUIRY ),
#ifdef CONFIG_USB_STORAGE_ISD200 #ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110,
...@@ -639,26 +624,6 @@ UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x0001, ...@@ -639,26 +624,6 @@ UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x0001,
US_SC_SCSI, US_PR_BULK, NULL, US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE | US_FL_START_STOP | US_FL_FIX_INQUIRY ), US_FL_MODE_XLATE | US_FL_START_STOP | US_FL_FIX_INQUIRY ),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"Pentax",
"Optio 2/3/400",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Brian Hall <brihall@pcisys.net> /* Submitted by Brian Hall <brihall@pcisys.net>
* Needed for START_STOP flag */ * Needed for START_STOP flag */
UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100, UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100,
......
...@@ -887,11 +887,8 @@ static int storage_probe(struct usb_interface *intf, ...@@ -887,11 +887,8 @@ static int storage_probe(struct usb_interface *intf,
/* set the hostdata to prepare for scanning */ /* set the hostdata to prepare for scanning */
us->host->hostdata[0] = (unsigned long)us; us->host->hostdata[0] = (unsigned long)us;
/* associate this host with our interface */
scsi_set_device(us->host, &intf->dev);
/* now add the host */ /* now add the host */
result = scsi_add_host(us->host, NULL); result = scsi_add_host(us->host, &intf->dev);
if (result) { if (result) {
printk(KERN_WARNING USB_STORAGE printk(KERN_WARNING USB_STORAGE
"Unable to add the scsi host\n"); "Unable to add the scsi host\n");
...@@ -942,16 +939,13 @@ static void storage_disconnect(struct usb_interface *intf) ...@@ -942,16 +939,13 @@ static void storage_disconnect(struct usb_interface *intf)
sdev->online = 0; sdev->online = 0;
scsi_unlock(us->host); scsi_unlock(us->host);
/* prevent new USB transfers and stop the current command */
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
usb_stor_stop_transport(us);
/* lock device access -- no need to unlock, as we're going away */ /* lock device access -- no need to unlock, as we're going away */
down(&(us->dev_semaphore)); down(&(us->dev_semaphore));
/* Complete all pending commands with * cmd->result = DID_ERROR << 16.
* Since we only queue one command at a time, this is pretty easy. */
if (us->srb) {
us->srb->result = DID_ERROR << 16;
us->srb->scsi_done(us->srb);
}
/* TODO: somehow, wait for the device to /* TODO: somehow, wait for the device to
* be 'idle' (tasklet completion) */ * be 'idle' (tasklet completion) */
......
...@@ -67,7 +67,7 @@ struct us_unusual_dev { ...@@ -67,7 +67,7 @@ struct us_unusual_dev {
unsigned int flags; unsigned int flags;
}; };
/* Flag definitions */ /* Flag definitions: these entries are static */
#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ #define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for #define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for
Win/MacOS compatibility */ Win/MacOS compatibility */
...@@ -77,8 +77,13 @@ struct us_unusual_dev { ...@@ -77,8 +77,13 @@ struct us_unusual_dev {
#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ #define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
#define US_FLIDX_CAN_CANCEL 18 /* 0x00040000 okay to cancel current_urb? */ /* Dynamic flag definitions: used in set_bit() etc. */
#define US_FLIDX_CANCEL_SG 19 /* 0x00080000 okay to cancel current_sg? */ #define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
#define US_FLIDX_SG_ACTIVE 19 /* 0x00080000 current_sg is in use */
#define US_FLIDX_ABORTING 20 /* 0x00100000 abort is in progress */
#define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */
#define DONT_SUBMIT ((1UL << US_FLIDX_ABORTING) || \
(1UL << US_FLIDX_DISCONNECTING))
/* processing state machine states */ /* processing state machine states */
......
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