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

Merge kroah.com:/home/greg/linux/BK/bleeding_edge-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 49cda8eb bcee5ba0
...@@ -189,7 +189,7 @@ void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd ) ...@@ -189,7 +189,7 @@ void usb_stor_print_Scsi_Cmnd( Scsi_Cmnd* cmd )
US_DEBUGP("Buffer has %d scatterlists.\n", cmd->use_sg ); US_DEBUGP("Buffer has %d scatterlists.\n", cmd->use_sg );
for ( i=0; i<cmd->use_sg; i++ ) for ( i=0; i<cmd->use_sg; i++ )
{ {
char *adr = page_address(sg[i].page) + sg[i].offset; char *adr = sg_address(sg[i]);
US_DEBUGP("Length of scatterlist %d is %d.\n",i,sg[i].length); US_DEBUGP("Length of scatterlist %d is %d.\n",i,sg[i].length);
US_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x\n" US_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x\n"
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include "scsi.h" #include "usb.h"
#define USB_STORAGE "usb-storage: " #define USB_STORAGE "usb-storage: "
......
...@@ -148,11 +148,11 @@ static void us_transfer_freecom(Scsi_Cmnd *srb, struct us_data* us, int transfer ...@@ -148,11 +148,11 @@ static void us_transfer_freecom(Scsi_Cmnd *srb, struct us_data* us, int transfer
if (transfer_amount - total_transferred >= if (transfer_amount - total_transferred >=
sg[i].length) { sg[i].length) {
result = usb_stor_transfer_partial(us, result = usb_stor_transfer_partial(us,
page_address(sg[i].page) + sg[i].offset, sg[i].length); sg_address(sg[i]), sg[i].length);
total_transferred += sg[i].length; total_transferred += sg[i].length;
} else { } else {
result = usb_stor_transfer_partial(us, result = usb_stor_transfer_partial(us,
page_address(sg[i].page) + sg[i].offset, sg_address(sg[i]),
transfer_amount - total_transferred); transfer_amount - total_transferred);
total_transferred += transfer_amount - total_transferred; total_transferred += transfer_amount - total_transferred;
} }
......
...@@ -425,7 +425,8 @@ static int isd200_transfer_partial( struct us_data *us, ...@@ -425,7 +425,8 @@ static int isd200_transfer_partial( struct us_data *us,
/* if we stall, we need to clear it before we go on */ /* if we stall, we need to clear it before we go on */
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
usb_stor_clear_halt(us, pipe); if (usb_stor_clear_halt(us, pipe) < 0)
return ISD200_TRANSPORT_FAILED;
} }
/* did we send all the data? */ /* did we send all the data? */
...@@ -501,13 +502,13 @@ static void isd200_transfer( struct us_data *us, Scsi_Cmnd *srb ) ...@@ -501,13 +502,13 @@ static void isd200_transfer( struct us_data *us, Scsi_Cmnd *srb )
sg[i].length) { sg[i].length) {
result = isd200_transfer_partial(us, result = isd200_transfer_partial(us,
srb->sc_data_direction, srb->sc_data_direction,
page_address(sg[i].page) + sg[i].offset, sg_address(sg[i]),
sg[i].length); sg[i].length);
total_transferred += sg[i].length; total_transferred += sg[i].length;
} else } else
result = isd200_transfer_partial(us, result = isd200_transfer_partial(us,
srb->sc_data_direction, srb->sc_data_direction,
page_address(sg[i].page) + sg[i].offset, sg_address(sg[i]),
transfer_amount - total_transferred); transfer_amount - total_transferred);
/* if we get an error, end the loop here */ /* if we get an error, end the loop here */
...@@ -589,7 +590,8 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb, ...@@ -589,7 +590,8 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
else if (result == -EPIPE) { else if (result == -EPIPE) {
/* if we stall, we need to clear it before we go on */ /* if we stall, we need to clear it before we go on */
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
usb_stor_clear_halt(us, pipe); if (usb_stor_clear_halt(us, pipe) < 0)
return ISD200_TRANSPORT_ERROR;
} else if (result) } else if (result)
return ISD200_TRANSPORT_ERROR; return ISD200_TRANSPORT_ERROR;
...@@ -621,7 +623,8 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb, ...@@ -621,7 +623,8 @@ int isd200_Bulk_transport( struct us_data *us, Scsi_Cmnd *srb,
/* did the attempt to read the CSW fail? */ /* did the attempt to read the CSW fail? */
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
usb_stor_clear_halt(us, pipe); if (usb_stor_clear_halt(us, pipe) < 0)
return ISD200_TRANSPORT_ERROR;
/* get the status again */ /* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n"); US_DEBUGP("Attempting to get CSW (2nd try)...\n");
...@@ -824,7 +827,7 @@ void isd200_invoke_transport( struct us_data *us, ...@@ -824,7 +827,7 @@ void isd200_invoke_transport( struct us_data *us,
case ISD200_TRANSPORT_GOOD: case ISD200_TRANSPORT_GOOD:
/* Indicate a good result */ /* Indicate a good result */
srb->result = GOOD; srb->result = GOOD << 1;
break; break;
case ISD200_TRANSPORT_ABORTED: case ISD200_TRANSPORT_ABORTED:
...@@ -946,15 +949,6 @@ int isd200_write_config( struct us_data *us ) ...@@ -946,15 +949,6 @@ int isd200_write_config( struct us_data *us )
US_DEBUGP(" ISD200 Config Data was written successfully\n"); US_DEBUGP(" ISD200 Config Data was written successfully\n");
} else { } else {
US_DEBUGP(" Request to write ISD200 Config Data failed!\n"); US_DEBUGP(" Request to write ISD200 Config Data failed!\n");
/* STALL must be cleared when they are detected */
if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n");
result = usb_stor_clear_halt(us,
usb_sndctrlpipe(us->pusb_dev, 0));
US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
}
retStatus = ISD200_ERROR; retStatus = ISD200_ERROR;
} }
...@@ -1000,15 +994,6 @@ int isd200_read_config( struct us_data *us ) ...@@ -1000,15 +994,6 @@ int isd200_read_config( struct us_data *us )
#endif #endif
} else { } else {
US_DEBUGP(" Request to get ISD200 Config Data failed!\n"); US_DEBUGP(" Request to get ISD200 Config Data failed!\n");
/* STALL must be cleared when they are detected */
if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n");
result = usb_stor_clear_halt(us,
usb_sndctrlpipe(us->pusb_dev, 0));
US_DEBUGP("-- usb_stor_clear_halt() returns %d\n", result);
}
retStatus = ISD200_ERROR; retStatus = ISD200_ERROR;
} }
...@@ -1271,7 +1256,7 @@ int isd200_get_inquiry_data( struct us_data *us ) ...@@ -1271,7 +1256,7 @@ int isd200_get_inquiry_data( struct us_data *us )
/* ATA Command Identify successful */ /* ATA Command Identify successful */
int i; int i;
__u16 *src, *dest; __u16 *src, *dest;
ata_fix_driveid(&info->drive); ide_fix_driveid(&info->drive);
US_DEBUGP(" Identify Data Structure:\n"); US_DEBUGP(" Identify Data Structure:\n");
US_DEBUGP(" config = 0x%x\n", info->drive.config); US_DEBUGP(" config = 0x%x\n", info->drive.config);
...@@ -1409,10 +1394,10 @@ void isd200_data_copy(Scsi_Cmnd *srb, char * src, int length) ...@@ -1409,10 +1394,10 @@ void isd200_data_copy(Scsi_Cmnd *srb, char * src, int length)
/* transfer the lesser of the next buffer or the /* transfer the lesser of the next buffer or the
* remaining data */ * remaining data */
if (len - total >= sg[i].length) { if (len - total >= sg[i].length) {
memcpy(page_address(sg[i].page) + sg[i].offset, src + total, sg[i].length); memcpy(sg_address(sg[i]), src + total, sg[i].length);
total += sg[i].length; total += sg[i].length;
} else { } else {
memcpy(page_address(sg[i].page) + sg[i].offset, src + total, len - total); memcpy(sg_address(sg[i]), src + total, len - total);
total = len; total = len;
} }
} }
...@@ -1462,7 +1447,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1462,7 +1447,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
/* copy InquiryData */ /* copy InquiryData */
isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen); isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen);
srb->result = GOOD; srb->result = GOOD << 1;
sendToTransport = FALSE; sendToTransport = FALSE;
break; break;
...@@ -1482,7 +1467,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1482,7 +1467,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Media Status not supported, just report okay\n"); US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = GOOD; srb->result = GOOD << 1;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1503,7 +1488,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1503,7 +1488,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Media Status not supported, just report okay\n"); US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = GOOD; srb->result = GOOD << 1;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1529,7 +1514,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1529,7 +1514,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = sizeof(struct read_capacity_data); srb->request_bufflen = sizeof(struct read_capacity_data);
isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen); isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen);
srb->result = GOOD; srb->result = GOOD << 1;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1613,7 +1598,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1613,7 +1598,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Not removeable media, just report okay\n"); US_DEBUGP(" Not removeable media, just report okay\n");
srb->result = GOOD; srb->result = GOOD << 1;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1642,7 +1627,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1642,7 +1627,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Nothing to do, just report okay\n"); US_DEBUGP(" Nothing to do, just report okay\n");
srb->result = GOOD; srb->result = GOOD << 1;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
......
...@@ -65,7 +65,7 @@ find_data_location(Scsi_Cmnd *srb) { ...@@ -65,7 +65,7 @@ find_data_location(Scsi_Cmnd *srb) {
struct scatterlist *sg; struct scatterlist *sg;
sg = (struct scatterlist *) srb->request_buffer; sg = (struct scatterlist *) srb->request_buffer;
return (void *) page_address(sg[0].page) + sg[0].offset; return (void *) sg_address(sg[0]);
} else } else
return (void *) srb->request_buffer; return (void *) srb->request_buffer;
} }
......
...@@ -67,12 +67,9 @@ usb_storage_send_control(struct us_data *us, ...@@ -67,12 +67,9 @@ usb_storage_send_control(struct us_data *us,
// Check the return code for the command. // Check the return code for the command.
if (result < 0) { if (result < 0) {
/* a stall is a fatal condition from the device */ /* a stall indicates a protocol error */
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n"); US_DEBUGP("-- Stall on control pipe\n");
result = usb_stor_clear_halt(us, pipe);
US_DEBUGP("-- usb_stor_clear_halt() returns %d\n",
result);
return USB_STOR_TRANSPORT_FAILED; return USB_STOR_TRANSPORT_FAILED;
} }
...@@ -102,7 +99,8 @@ usb_storage_raw_bulk(struct us_data *us, int direction, unsigned char *data, ...@@ -102,7 +99,8 @@ usb_storage_raw_bulk(struct us_data *us, int direction, unsigned char *data,
US_DEBUGP("EPIPE: clearing endpoint halt for" US_DEBUGP("EPIPE: clearing endpoint halt for"
" pipe 0x%x, stalled at %d bytes\n", " pipe 0x%x, stalled at %d bytes\n",
pipe, *act_len); pipe, *act_len);
usb_stor_clear_halt(us, pipe); if (usb_stor_clear_halt(us, pipe) < 0)
return US_BULK_TRANSFER_FAILED;
/* return US_BULK_TRANSFER_SHORT; */ /* return US_BULK_TRANSFER_SHORT; */
} }
...@@ -191,7 +189,7 @@ usb_storage_bulk_transport(struct us_data *us, int direction, ...@@ -191,7 +189,7 @@ usb_storage_bulk_transport(struct us_data *us, int direction,
unsigned char *buf; unsigned char *buf;
unsigned int length; unsigned int length;
buf = page_address(sg[i].page) + sg[i].offset; buf = sg_address(sg[i]);
length = len-transferred; length = len-transferred;
if (length > sg[i].length) if (length > sg[i].length)
length = sg[i].length; length = sg[i].length;
...@@ -261,7 +259,7 @@ us_copy_from_sgbuf(unsigned char *content, int len, ...@@ -261,7 +259,7 @@ us_copy_from_sgbuf(unsigned char *content, int len,
unsigned char *ptr; unsigned char *ptr;
unsigned int length, room; unsigned int length, room;
ptr = page_address(sg[i].page) + sg[i].offset + *offset; ptr = sg_address(sg[i]) + *offset;
room = sg[i].length - *offset; room = sg[i].length - *offset;
length = len - transferred; length = len - transferred;
...@@ -310,7 +308,7 @@ us_copy_to_sgbuf(unsigned char *buffer, int buflen, ...@@ -310,7 +308,7 @@ us_copy_to_sgbuf(unsigned char *buffer, int buflen,
unsigned char *ptr; unsigned char *ptr;
unsigned int length, room; unsigned int length, room;
ptr = page_address(sg[i].page) + sg[i].offset + *offset; ptr = sg_address(sg[i]) + *offset;
room = sg[i].length - *offset; room = sg[i].length - *offset;
length = buflen - transferred; length = buflen - transferred;
......
...@@ -563,8 +563,8 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ) ...@@ -563,8 +563,8 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
/* copy one byte */ /* copy one byte */
{ {
char *src = page_address(sg[sb].page) + sg[sb].offset + si; char *src = sg_address(sg[sb]) + si;
char *dst = page_address(sg[db].page) + sg[db].offset + di; char *dst = sg_address(sg[db]) + di;
*dst = *src; *dst = *src;
} }
...@@ -605,7 +605,7 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ) ...@@ -605,7 +605,7 @@ int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
break; break;
} }
*(char*)(page_address(sg[db].page) + sg[db].offset) = 0; *(char*)(sg_address(sg[db])) = 0;
/* get next destination */ /* get next destination */
if ( sg[db].length-1 == di ) if ( sg[db].length-1 == di )
...@@ -756,8 +756,8 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ) ...@@ -756,8 +756,8 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
/* copy one byte */ /* copy one byte */
{ {
char *src = page_address(sg[sb].page) + sg[sb].offset + si; char *src = sg_address(sg[sb]) + si;
char *dst = page_address(sg[db].page) + sg[db].offset + di; char *dst = sg_address(sg[db]) + di;
*dst = *src; *dst = *src;
} }
...@@ -798,7 +798,7 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ) ...@@ -798,7 +798,7 @@ int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
} }
{ {
char *dst = page_address(sg[db].page) + sg[db].offset + di; char *dst = sg_address(sg[db]) + di;
*dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
} }
...@@ -852,17 +852,14 @@ void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* t ...@@ -852,17 +852,14 @@ void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* t
if ( element < USB_STOR_SCSI_SENSE_HDRSZ ) if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
{ {
/* fill in the pointers for both header types */ /* fill in the pointers for both header types */
the6->array[element] = page_address(sg[i].page) + the6->array[element] = sg_address(sg[i]) + j;
sg[i].offset + j; the10->array[element] = sg_address(sg[i]) + j;
the10->array[element] = page_address(sg[i].page) +
sg[i].offset + j;
} }
else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
{ {
/* only the longer headers still cares now */ /* only the longer headers still cares now */
the10->array[element] = page_address(sg[i].page) + the10->array[element] = sg_address(sg[i]) + j;
sg[i].offset + j;
} }
/* increase element counter */ /* increase element counter */
......
...@@ -1091,25 +1091,23 @@ sddr09_read_map(struct us_data *us) { ...@@ -1091,25 +1091,23 @@ sddr09_read_map(struct us_data *us) {
return 0; return 0;
for (i=0; i<alloc_blocks; i++) { for (i=0; i<alloc_blocks; i++) {
if (i<alloc_blocks-1) { int alloc_req = (i < alloc_blocks-1 ? 1 << 17 : alloc_len);
char *vaddr = kmalloc(1 << 17, GFP_NOIO); char *vaddr = kmalloc(alloc_req, GFP_NOIO);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3)
sg[i].page = virt_to_page(vaddr); sg[i].page = virt_to_page(vaddr);
sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK); sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK);
sg[i].length = (1<<17); #else
} else { sg[i].address = vaddr;
char *vaddr = kmalloc(alloc_len, GFP_NOIO); #endif
sg[i].page = virt_to_page(vaddr); sg[i].length = alloc_req;
sg[i].offset = ((unsigned long)vaddr & ~PAGE_MASK); alloc_len -= alloc_req;
sg[i].length = alloc_len;
}
alloc_len -= sg[i].length;
} }
for (i=0; i<alloc_blocks; i++) for (i=0; i<alloc_blocks; i++)
if (sg[i].page == NULL) { if (sg[i].page == NULL) {
for (i=0; i<alloc_blocks; i++) for (i=0; i<alloc_blocks; i++)
if (sg[i].page != NULL) if (sg[i].page != NULL)
kfree(page_address(sg[i].page) + sg[i].offset); kfree(sg_address(sg[i]));
kfree(sg); kfree(sg);
return 0; return 0;
} }
...@@ -1120,7 +1118,7 @@ sddr09_read_map(struct us_data *us) { ...@@ -1120,7 +1118,7 @@ sddr09_read_map(struct us_data *us) {
(unsigned char *)sg, alloc_blocks); (unsigned char *)sg, alloc_blocks);
if (result != USB_STOR_TRANSPORT_GOOD) { if (result != USB_STOR_TRANSPORT_GOOD) {
for (i=0; i<alloc_blocks; i++) for (i=0; i<alloc_blocks; i++)
kfree(page_address(sg[i].page) + sg[i].offset); kfree(sg_address(sg[i]));
kfree(sg); kfree(sg);
return -1; return -1;
} }
...@@ -1136,7 +1134,7 @@ sddr09_read_map(struct us_data *us) { ...@@ -1136,7 +1134,7 @@ sddr09_read_map(struct us_data *us) {
info->lba_to_pba = NULL; info->lba_to_pba = NULL;
info->pba_to_lba = NULL; info->pba_to_lba = NULL;
for (i=0; i<alloc_blocks; i++) for (i=0; i<alloc_blocks; i++)
kfree(page_address(sg[i].page) + sg[i].offset); kfree(sg_address(sg[i]));
kfree(sg); kfree(sg);
return 0; return 0;
} }
...@@ -1144,7 +1142,7 @@ sddr09_read_map(struct us_data *us) { ...@@ -1144,7 +1142,7 @@ sddr09_read_map(struct us_data *us) {
for (i = 0; i < numblocks; i++) for (i = 0; i < numblocks; i++)
info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF; info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF;
ptr = page_address(sg[0].page)+sg[0].offset; ptr = sg_address(sg[0]);
/* /*
* Define lba-pba translation table * Define lba-pba translation table
...@@ -1153,8 +1151,7 @@ sddr09_read_map(struct us_data *us) { ...@@ -1153,8 +1151,7 @@ sddr09_read_map(struct us_data *us) {
// scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11) // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
for (i=0; i<numblocks; i++) { for (i=0; i<numblocks; i++) {
ptr = page_address(sg[i>>11].page) + ptr = sg_address(sg[i>>11]) + ((i&0x7ff)<<6);
sg[i>>11].offset + ((i&0x7ff)<<6);
if (i == 0 || i == 1) { if (i == 0 || i == 1) {
info->pba_to_lba[i] = UNUSABLE; info->pba_to_lba[i] = UNUSABLE;
...@@ -1264,7 +1261,7 @@ sddr09_read_map(struct us_data *us) { ...@@ -1264,7 +1261,7 @@ sddr09_read_map(struct us_data *us) {
US_DEBUGP("Found %d LBA's\n", lbact); US_DEBUGP("Found %d LBA's\n", lbact);
for (i=0; i<alloc_blocks; i++) for (i=0; i<alloc_blocks; i++)
kfree(page_address(sg[i].page) + sg[i].offset); kfree(sg_address(sg[i]));
kfree(sg); kfree(sg);
return 0; return 0;
} }
......
...@@ -348,10 +348,13 @@ int usbat_rw_block_test(struct us_data *us, ...@@ -348,10 +348,13 @@ int usbat_rw_block_test(struct us_data *us,
* the bulk output pipe only the first time. * the bulk output pipe only the first time.
*/ */
if (direction==SCSI_DATA_READ && i==0) if (direction==SCSI_DATA_READ && i==0) {
usb_stor_clear_halt(us, if (usb_stor_clear_halt(us,
usb_sndbulkpipe(us->pusb_dev, usb_sndbulkpipe(us->pusb_dev,
us->ep_out)); us->ep_out)) < 0)
return USB_STOR_TRANSPORT_ERROR;
}
/* /*
* Read status: is the device angry, or just busy? * Read status: is the device angry, or just busy?
*/ */
......
...@@ -349,8 +349,8 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb) ...@@ -349,8 +349,8 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
* all the complex logic above, let's find them and eliminate them. * all the complex logic above, let's find them and eliminate them.
*/ */
if (len != srb->request_bufflen) { if (len != srb->request_bufflen) {
printk("USB len=%d, request_bufflen=%d\n", len, srb->request_bufflen); printk(KERN_ERR "USB len=%d, request_bufflen=%d\n", len, srb->request_bufflen);
show_trace(NULL); printk(KERN_ERR "Fix this -- future 2.5 kernels will not work if this is not fixed!\n");
} }
return len; return len;
...@@ -370,16 +370,20 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb) ...@@ -370,16 +370,20 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
* as those occurring during device-specific initialization, must be handled * as those occurring during device-specific initialization, must be handled
* by a separate code path.) * by a separate code path.)
* *
* The abort function first sets the machine state, then acquires the lock * The abort function first sets the machine state, then atomically
* on the current_urb before checking if it needs to be aborted. * tests-and-clears the CAN_CANCEL bit in us->flags to see if the current_urb
* needs to be aborted.
* *
* When a function submits the current_urb, it must first grab the * The submit function first verifies that the submission completed without
* current_urb_sem to prevent the abort function from trying to cancel the * errors, and only then sets the CAN_CANCEL bit. This prevents the abort
* URB while the submit call is underway. After a function submits the * function from trying to cancel the URB while the submit call is underway.
* current_urb, it -MUST- test the state to see if we got aborted just before * Next, the submit function must test the state to see if we got aborted
* the submission. If so, it's essential to abort the URB if it's still in * before the submission or before setting the CAN_CANCEL bit. If so, it's
* progress. Either way, the function must then release the lock and wait * essential to abort the URB if it hasn't been cancelled already (i.e.,
* for the URB to finish. * if the CAN_CANCEL bit is still set). Either way, the function must then
* wait for the URB to finish. Note that because the USB_ASYNC_UNLINK flag
* is set, the URB can still be in progress even after a call to
* usb_unlink_urb() returns.
* *
* (It's also permissible, but not necessary, to test the state -before- * (It's also permissible, but not necessary, to test the state -before-
* submitting the URB. Doing so would prevent an unnecessary submission if * submitting the URB. Doing so would prevent an unnecessary submission if
...@@ -389,7 +393,7 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb) ...@@ -389,7 +393,7 @@ unsigned int usb_stor_transfer_length(Scsi_Cmnd *srb)
* *
* The idea is that (1) once the state is changed to ABORTING, either the * The idea is that (1) once the state is changed to ABORTING, either the
* aborting function or the submitting function is guaranteed to call * aborting function or the submitting function is guaranteed to call
* usb_unlink_urb() for an active URB, and (2) current_urb_sem prevents * usb_unlink_urb() for an active URB, and (2) test_and_clear_bit() prevents
* usb_unlink_urb() from being called more than once or from being called * usb_unlink_urb() from being called more than once or from being called
* during usb_submit_urb(). * during usb_submit_urb().
*/ */
...@@ -424,28 +428,30 @@ static int usb_stor_msg_common(struct us_data *us) ...@@ -424,28 +428,30 @@ static int usb_stor_msg_common(struct us_data *us)
us->current_urb->error_count = 0; us->current_urb->error_count = 0;
us->current_urb->transfer_flags = USB_ASYNC_UNLINK; us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
/* lock and submit the URB */ /* submit the URB */
down(&(us->current_urb_sem));
status = usb_submit_urb(us->current_urb, GFP_NOIO); status = usb_submit_urb(us->current_urb, GFP_NOIO);
if (status) { if (status) {
/* something went wrong */ /* something went wrong */
up(&(us->current_urb_sem));
return status; return status;
} }
/* since the URB has been submitted successfully, it's now okay
* to cancel it */
set_bit(US_FLIDX_CAN_CANCEL, &us->flags);
/* has the current command been aborted? */ /* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
/* cancel the URB, if it hasn't been cancelled already */ /* cancel the URB, if it hasn't been cancelled already */
if (us->current_urb->status == -EINPROGRESS) { if (test_and_clear_bit(US_FLIDX_CAN_CANCEL, &us->flags)) {
US_DEBUGP("-- cancelling URB\n"); US_DEBUGP("-- cancelling URB\n");
usb_unlink_urb(us->current_urb); usb_unlink_urb(us->current_urb);
} }
} }
up(&(us->current_urb_sem));
/* wait for the completion of the URB */ /* wait for the completion of the URB */
wait_for_completion(&urb_done); wait_for_completion(&urb_done);
clear_bit(US_FLIDX_CAN_CANCEL, &us->flags);
/* return the URB status */ /* return the URB status */
return us->current_urb->status; return us->current_urb->status;
...@@ -565,7 +571,8 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length) ...@@ -565,7 +571,8 @@ int usb_stor_transfer_partial(struct us_data *us, char *buf, int length)
/* if we stall, we need to clear it before we go on */ /* if we stall, we need to clear it before we go on */
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
usb_stor_clear_halt(us, pipe); if (usb_stor_clear_halt(us, pipe) < 0)
return US_BULK_TRANSFER_FAILED;
} }
/* did we abort this command? */ /* did we abort this command? */
...@@ -635,11 +642,11 @@ void usb_stor_transfer(Scsi_Cmnd *srb, struct us_data* us) ...@@ -635,11 +642,11 @@ void usb_stor_transfer(Scsi_Cmnd *srb, struct us_data* us)
if (transfer_amount - total_transferred >= if (transfer_amount - total_transferred >=
sg[i].length) { sg[i].length) {
result = usb_stor_transfer_partial(us, result = usb_stor_transfer_partial(us,
page_address(sg[i].page) + sg[i].offset, sg[i].length); sg_address(sg[i]), sg[i].length);
total_transferred += sg[i].length; total_transferred += sg[i].length;
} else } else
result = usb_stor_transfer_partial(us, result = usb_stor_transfer_partial(us,
page_address(sg[i].page) + sg[i].offset, sg_address(sg[i]),
transfer_amount - total_transferred); transfer_amount - total_transferred);
/* if we get an error, end the loop here */ /* if we get an error, end the loop here */
...@@ -867,15 +874,13 @@ void usb_stor_abort_transport(struct us_data *us) ...@@ -867,15 +874,13 @@ void usb_stor_abort_transport(struct us_data *us)
/* If the state machine is blocked waiting for an URB or an IRQ, /* 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. Note that we guarantee with /* If we have an URB pending, cancel it. The test_and_clear_bit()
* the current_urb_sem that if a URB has just been submitted, it * call guarantees that if a URB has just been submitted, it
* won't be cancelled more than once. */ * won't be cancelled more than once. */
down(&(us->current_urb_sem)); if (test_and_clear_bit(US_FLIDX_CAN_CANCEL, &us->flags)) {
if (us->current_urb->status == -EINPROGRESS) {
US_DEBUGP("-- cancelling URB\n"); US_DEBUGP("-- cancelling URB\n");
usb_unlink_urb(us->current_urb); usb_unlink_urb(us->current_urb);
} }
up(&(us->current_urb_sem));
/* If we are waiting for an IRQ, simulate it */ /* If we are waiting for an IRQ, simulate it */
if (test_bit(US_FLIDX_IP_WANTED, &us->flags)) { if (test_bit(US_FLIDX_IP_WANTED, &us->flags)) {
...@@ -993,18 +998,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -993,18 +998,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
return US_BULK_TRANSFER_ABORTED; return US_BULK_TRANSFER_ABORTED;
} }
/* STALL must be cleared when it is detected */ /* a stall indicates a protocol error */
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n"); US_DEBUGP("-- Stall on control pipe\n");
result = usb_stor_clear_halt(us,
usb_sndctrlpipe(us->pusb_dev, 0));
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_control_msg(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
return USB_STOR_TRANSPORT_FAILED; return USB_STOR_TRANSPORT_FAILED;
} }
...@@ -1110,17 +1106,9 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1110,17 +1106,9 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
return US_BULK_TRANSFER_ABORTED; return US_BULK_TRANSFER_ABORTED;
} }
/* a stall is a fatal condition from the device */ /* a stall indicates a protocol error */
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n"); US_DEBUGP("-- Stall on control pipe\n");
result = usb_stor_clear_halt(us,
usb_sndctrlpipe(us->pusb_dev, 0));
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
return USB_STOR_TRANSPORT_FAILED; return USB_STOR_TRANSPORT_FAILED;
} }
...@@ -1178,15 +1166,6 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -1178,15 +1166,6 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
if (result == 1) if (result == 1)
return data; return data;
/* if we get a STALL, clear the stall */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
/* Use usb_clear_halt() because this is not a
* scsi queued-command */
usb_clear_halt(us->pusb_dev, pipe);
}
/* return the default -- no LUNs */ /* return the default -- no LUNs */
return 0; return 0;
} }
...@@ -1241,6 +1220,8 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1241,6 +1220,8 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED; return US_BULK_TRANSFER_ABORTED;
} }
if (result < 0)
return USB_STOR_TRANSPORT_ERROR;
result = -EPIPE; result = -EPIPE;
} else if (result) { } else if (result) {
/* unknown error -- we've got a problem */ /* unknown error -- we've got a problem */
...@@ -1289,6 +1270,8 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1289,6 +1270,8 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n"); US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED; return US_BULK_TRANSFER_ABORTED;
} }
if (result < 0)
return USB_STOR_TRANSPORT_ERROR;
/* get the status again */ /* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n"); US_DEBUGP("Attempting to get CSW (2nd try)...\n");
......
...@@ -283,13 +283,13 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, ...@@ -283,13 +283,13 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
if (us->srb->use_sg) { if (us->srb->use_sg) {
sg = (struct scatterlist *)us->srb->request_buffer; sg = (struct scatterlist *)us->srb->request_buffer;
for (i=0; i<us->srb->use_sg; i++) for (i=0; i<us->srb->use_sg; i++)
memset(page_address(sg[i].page) + sg[i].offset, 0, sg[i].length); memset(sg_address(sg[i]), 0, sg[i].length);
for (i=0, transferred=0; for (i=0, transferred=0;
i<us->srb->use_sg && transferred < len; i<us->srb->use_sg && transferred < len;
i++) { i++) {
amt = sg[i].length > len-transferred ? amt = sg[i].length > len-transferred ?
len-transferred : sg[i].length; len-transferred : sg[i].length;
memcpy(page_address(sg[i].page) + sg[i].offset, data+transferred, amt); memcpy(sg_address(sg[i]), data+transferred, amt);
transferred -= amt; transferred -= amt;
} }
} else { } else {
...@@ -724,8 +724,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -724,8 +724,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
US_DEBUGP("Result from usb_set_configuration is %d\n", result); US_DEBUGP("Result from usb_set_configuration is %d\n", result);
if (result == -EPIPE) { if (result == -EPIPE) {
US_DEBUGP("-- clearing stall on control interface\n"); US_DEBUGP("-- stall on control interface\n");
usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
} else if (result != 0) { } else if (result != 0) {
/* it's not a stall, but another error -- time to bail */ /* it's not a stall, but another error -- time to bail */
US_DEBUGP("-- Unknown error. Rejecting device\n"); US_DEBUGP("-- Unknown error. Rejecting device\n");
...@@ -825,7 +824,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -825,7 +824,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
init_completion(&(ss->notify)); init_completion(&(ss->notify));
init_MUTEX_LOCKED(&(ss->ip_waitq)); init_MUTEX_LOCKED(&(ss->ip_waitq));
init_MUTEX(&(ss->irq_urb_sem)); init_MUTEX(&(ss->irq_urb_sem));
init_MUTEX(&(ss->current_urb_sem));
init_MUTEX_LOCKED(&(ss->dev_semaphore)); init_MUTEX_LOCKED(&(ss->dev_semaphore));
/* copy over the subclass and protocol data */ /* copy over the subclass and protocol data */
......
...@@ -106,6 +106,7 @@ struct us_unusual_dev { ...@@ -106,6 +106,7 @@ struct us_unusual_dev {
#define US_FL_DEV_ATTACHED 0x00010000 /* is the device attached? */ #define US_FL_DEV_ATTACHED 0x00010000 /* is the device attached? */
#define US_FLIDX_IP_WANTED 17 /* 0x00020000 is an IRQ expected? */ #define US_FLIDX_IP_WANTED 17 /* 0x00020000 is an IRQ expected? */
#define US_FLIDX_CAN_CANCEL 18 /* 0x00040000 okay to cancel current_urb? */
/* processing state machine states */ /* processing state machine states */
...@@ -177,7 +178,6 @@ struct us_data { ...@@ -177,7 +178,6 @@ struct us_data {
unsigned char irqdata[2]; /* data from USB IRQ */ unsigned char irqdata[2]; /* data from USB IRQ */
/* control and bulk communications data */ /* control and bulk communications data */
struct semaphore current_urb_sem; /* protect current_urb */
struct urb *current_urb; /* non-int USB requests */ struct urb *current_urb; /* non-int USB requests */
struct usb_ctrlrequest *dr; /* control requests */ struct usb_ctrlrequest *dr; /* control requests */
...@@ -206,7 +206,6 @@ extern void fill_inquiry_response(struct us_data *us, ...@@ -206,7 +206,6 @@ extern void fill_inquiry_response(struct us_data *us,
* single queue element srb for write access */ * single queue element srb for write access */
#define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_unlock(host) spin_unlock_irq(host->host_lock)
#define scsi_lock(host) spin_lock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock)
#define sg_address(psg) (page_address((psg).page) + (psg).offset)
#define sg_address(psg) (page_address((psg)->page) + (psg)->offset)
#endif #endif
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