Commit 760c3b3a authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB Storage: Remove non s-g pathway from subdriver READ/WRITE

This patch does what you suggested.  The read/write routines from the
updated subdrivers are changed so they don't bother to differentiate
between transfers that do or do not use scatter-gather.  The low-level
usb_stor_access_xfer_buf routine will Do The Right Thing regardless, and
there probably won't ever be more than a few non s-g calls.  (What about
filesystem I/O requests to access metadata?)

It turns out that in addition to removing some comments and a few tests,
this change allowed me to remove the buffer and use_sg arguments passed to
the read/write routines as well.  So the simplification ended up being a
bit bigger than I expected.

While writing this patch, I noticed spots in several drivers that still
need to be changed -- they slipped past me before.  These drivers handle
things like READ-CAPACITY or REQUEST-SENSE by copying the data directly to
srb->request_buffer, which is obviously wrong if s-g is being used.  I'll
send in changes next week that convert them to use the
usb_stor_set_xfer_buf function.  Like you said, it's going to be handy in
more places than originally intended!
parent a9b6e357
...@@ -89,11 +89,10 @@ datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) { ...@@ -89,11 +89,10 @@ datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) {
static int datafab_read_data(struct us_data *us, static int datafab_read_data(struct us_data *us,
struct datafab_info *info, struct datafab_info *info,
u32 sector, u32 sector,
u32 sectors, u32 sectors)
unsigned char *buffer,
int use_sg)
{ {
unsigned char *command = us->iobuf; unsigned char *command = us->iobuf;
unsigned char *buffer;
unsigned char thistime; unsigned char thistime;
unsigned int totallen, alloclen; unsigned int totallen, alloclen;
int len, result; int len, result;
...@@ -116,18 +115,13 @@ static int datafab_read_data(struct us_data *us, ...@@ -116,18 +115,13 @@ static int datafab_read_data(struct us_data *us,
totallen = sectors * info->ssize; totallen = sectors * info->ssize;
// Since we don't read more than 64 KB at a time, we have to create // Since we don't read more than 64 KB at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the
// same effect.
alloclen = min(totallen, 65536u); alloclen = min(totallen, 65536u);
if (use_sg) { buffer = kmalloc(alloclen, GFP_NOIO);
buffer = kmalloc(alloclen, GFP_NOIO); if (buffer == NULL)
if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_ERROR;
}
do { do {
// loop, never allocate or transfer more than 64k at once // loop, never allocate or transfer more than 64k at once
...@@ -157,24 +151,19 @@ static int datafab_read_data(struct us_data *us, ...@@ -157,24 +151,19 @@ static int datafab_read_data(struct us_data *us,
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
goto leave; goto leave;
// Store the data (s-g) or update the pointer (!s-g) // Store the data in the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &sg_idx, &sg_offset, TO_XFER_BUF);
&sg_idx, &sg_offset, TO_XFER_BUF);
else
buffer += len;
sector += thistime; sector += thistime;
totallen -= len; totallen -= len;
} while (totallen > 0); } while (totallen > 0);
if (use_sg) kfree(buffer);
kfree(buffer);
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
leave: leave:
if (use_sg) kfree(buffer);
kfree(buffer);
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
...@@ -182,12 +171,11 @@ static int datafab_read_data(struct us_data *us, ...@@ -182,12 +171,11 @@ static int datafab_read_data(struct us_data *us,
static int datafab_write_data(struct us_data *us, static int datafab_write_data(struct us_data *us,
struct datafab_info *info, struct datafab_info *info,
u32 sector, u32 sector,
u32 sectors, u32 sectors)
unsigned char *buffer,
int use_sg)
{ {
unsigned char *command = us->iobuf; unsigned char *command = us->iobuf;
unsigned char *reply = us->iobuf; unsigned char *reply = us->iobuf;
unsigned char *buffer;
unsigned char thistime; unsigned char thistime;
unsigned int totallen, alloclen; unsigned int totallen, alloclen;
int len, result; int len, result;
...@@ -210,18 +198,13 @@ static int datafab_write_data(struct us_data *us, ...@@ -210,18 +198,13 @@ static int datafab_write_data(struct us_data *us,
totallen = sectors * info->ssize; totallen = sectors * info->ssize;
// Since we don't write more than 64 KB at a time, we have to create // Since we don't write more than 64 KB at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the
// same effect.
alloclen = min(totallen, 65536u); alloclen = min(totallen, 65536u);
if (use_sg) { buffer = kmalloc(alloclen, GFP_NOIO);
buffer = kmalloc(alloclen, GFP_NOIO); if (buffer == NULL)
if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_ERROR;
}
do { do {
// loop, never allocate or transfer more than 64k at once // loop, never allocate or transfer more than 64k at once
...@@ -230,10 +213,9 @@ static int datafab_write_data(struct us_data *us, ...@@ -230,10 +213,9 @@ static int datafab_write_data(struct us_data *us,
len = min(totallen, alloclen); len = min(totallen, alloclen);
thistime = (len / info->ssize) & 0xff; thistime = (len / info->ssize) & 0xff;
// Get the data from the transfer buffer (s-g) // Get the data from the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &sg_idx, &sg_offset, FROM_XFER_BUF);
&sg_idx, &sg_offset, FROM_XFER_BUF);
command[0] = 0; command[0] = 0;
command[1] = thistime; command[1] = thistime;
...@@ -269,21 +251,15 @@ static int datafab_write_data(struct us_data *us, ...@@ -269,21 +251,15 @@ static int datafab_write_data(struct us_data *us,
goto leave; goto leave;
} }
// Update the transfer buffer pointer (!s-g)
if (!use_sg)
buffer += len;
sector += thistime; sector += thistime;
totallen -= len; totallen -= len;
} while (totallen > 0); } while (totallen > 0);
if (use_sg) kfree(buffer);
kfree(buffer);
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
leave: leave:
if (use_sg) kfree(buffer);
kfree(buffer);
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
...@@ -615,7 +591,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -615,7 +591,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
US_DEBUGP("datafab_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("datafab_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg); return datafab_read_data(us, info, block, blocks);
} }
if (srb->cmnd[0] == READ_12) { if (srb->cmnd[0] == READ_12) {
...@@ -628,7 +604,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -628,7 +604,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
US_DEBUGP("datafab_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("datafab_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
return datafab_read_data(us, info, block, blocks, ptr, srb->use_sg); return datafab_read_data(us, info, block, blocks);
} }
if (srb->cmnd[0] == WRITE_10) { if (srb->cmnd[0] == WRITE_10) {
...@@ -638,7 +614,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -638,7 +614,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
US_DEBUGP("datafab_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("datafab_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg); return datafab_write_data(us, info, block, blocks);
} }
if (srb->cmnd[0] == WRITE_12) { if (srb->cmnd[0] == WRITE_12) {
...@@ -651,7 +627,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -651,7 +627,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
US_DEBUGP("datafab_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("datafab_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
return datafab_write_data(us, info, block, blocks, ptr, srb->use_sg); return datafab_write_data(us, info, block, blocks);
} }
if (srb->cmnd[0] == TEST_UNIT_READY) { if (srb->cmnd[0] == TEST_UNIT_READY) {
......
...@@ -109,11 +109,10 @@ static int jumpshot_get_status(struct us_data *us) ...@@ -109,11 +109,10 @@ static int jumpshot_get_status(struct us_data *us)
static int jumpshot_read_data(struct us_data *us, static int jumpshot_read_data(struct us_data *us,
struct jumpshot_info *info, struct jumpshot_info *info,
u32 sector, u32 sector,
u32 sectors, u32 sectors)
unsigned char *buffer,
int use_sg)
{ {
unsigned char *command = us->iobuf; unsigned char *command = us->iobuf;
unsigned char *buffer;
unsigned char thistime; unsigned char thistime;
unsigned int totallen, alloclen; unsigned int totallen, alloclen;
int len, result; int len, result;
...@@ -130,18 +129,13 @@ static int jumpshot_read_data(struct us_data *us, ...@@ -130,18 +129,13 @@ static int jumpshot_read_data(struct us_data *us,
totallen = sectors * info->ssize; totallen = sectors * info->ssize;
// Since we don't read more than 64 KB at a time, we have to create // Since we don't read more than 64 KB at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the
// same effect.
alloclen = min(totallen, 65536u); alloclen = min(totallen, 65536u);
if (use_sg) { buffer = kmalloc(alloclen, GFP_NOIO);
buffer = kmalloc(alloclen, GFP_NOIO); if (buffer == NULL)
if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_ERROR;
}
do { do {
// loop, never allocate or transfer more than 64k at once // loop, never allocate or transfer more than 64k at once
...@@ -171,24 +165,19 @@ static int jumpshot_read_data(struct us_data *us, ...@@ -171,24 +165,19 @@ static int jumpshot_read_data(struct us_data *us,
US_DEBUGP("jumpshot_read_data: %d bytes\n", len); US_DEBUGP("jumpshot_read_data: %d bytes\n", len);
// Store the data (s-g) or update the pointer (!s-g) // Store the data in the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &sg_idx, &sg_offset, TO_XFER_BUF);
&sg_idx, &sg_offset, TO_XFER_BUF);
else
buffer += len;
sector += thistime; sector += thistime;
totallen -= len; totallen -= len;
} while (totallen > 0); } while (totallen > 0);
if (use_sg) kfree(buffer);
kfree(buffer);
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
leave: leave:
if (use_sg) kfree(buffer);
kfree(buffer);
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
...@@ -196,11 +185,10 @@ static int jumpshot_read_data(struct us_data *us, ...@@ -196,11 +185,10 @@ static int jumpshot_read_data(struct us_data *us,
static int jumpshot_write_data(struct us_data *us, static int jumpshot_write_data(struct us_data *us,
struct jumpshot_info *info, struct jumpshot_info *info,
u32 sector, u32 sector,
u32 sectors, u32 sectors)
unsigned char *buffer,
int use_sg)
{ {
unsigned char *command = us->iobuf; unsigned char *command = us->iobuf;
unsigned char *buffer;
unsigned char thistime; unsigned char thistime;
unsigned int totallen, alloclen; unsigned int totallen, alloclen;
int len, result, waitcount; int len, result, waitcount;
...@@ -217,18 +205,13 @@ static int jumpshot_write_data(struct us_data *us, ...@@ -217,18 +205,13 @@ static int jumpshot_write_data(struct us_data *us,
totallen = sectors * info->ssize; totallen = sectors * info->ssize;
// Since we don't write more than 64 KB at a time, we have to create // Since we don't write more than 64 KB at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the
// same effect.
alloclen = min(totallen, 65536u); alloclen = min(totallen, 65536u);
if (use_sg) { buffer = kmalloc(alloclen, GFP_NOIO);
buffer = kmalloc(alloclen, GFP_NOIO); if (buffer == NULL)
if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR;
return USB_STOR_TRANSPORT_ERROR;
}
do { do {
// loop, never allocate or transfer more than 64k at once // loop, never allocate or transfer more than 64k at once
...@@ -237,10 +220,9 @@ static int jumpshot_write_data(struct us_data *us, ...@@ -237,10 +220,9 @@ static int jumpshot_write_data(struct us_data *us,
len = min(totallen, alloclen); len = min(totallen, alloclen);
thistime = (len / info->ssize) & 0xff; thistime = (len / info->ssize) & 0xff;
// Get the data from the transfer buffer (s-g) // Get the data from the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &sg_idx, &sg_offset, FROM_XFER_BUF);
&sg_idx, &sg_offset, FROM_XFER_BUF);
command[0] = 0; command[0] = 0;
command[1] = thistime; command[1] = thistime;
...@@ -278,21 +260,15 @@ static int jumpshot_write_data(struct us_data *us, ...@@ -278,21 +260,15 @@ static int jumpshot_write_data(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD) if (result != USB_STOR_TRANSPORT_GOOD)
US_DEBUGP("jumpshot_write_data: Gah! Waitcount = 10. Bad write!?\n"); US_DEBUGP("jumpshot_write_data: Gah! Waitcount = 10. Bad write!?\n");
// Update the transfer buffer pointer (!s-g)
if (!use_sg)
buffer += len;
sector += thistime; sector += thistime;
totallen -= len; totallen -= len;
} while (totallen > 0); } while (totallen > 0);
if (use_sg) kfree(buffer);
kfree(buffer);
return result; return result;
leave: leave:
if (use_sg) kfree(buffer);
kfree(buffer);
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
...@@ -546,7 +522,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -546,7 +522,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
US_DEBUGP("jumpshot_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("jumpshot_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
return jumpshot_read_data(us, info, block, blocks, ptr, srb->use_sg); return jumpshot_read_data(us, info, block, blocks);
} }
if (srb->cmnd[0] == READ_12) { if (srb->cmnd[0] == READ_12) {
...@@ -559,7 +535,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -559,7 +535,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
US_DEBUGP("jumpshot_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("jumpshot_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
return jumpshot_read_data(us, info, block, blocks, ptr, srb->use_sg); return jumpshot_read_data(us, info, block, blocks);
} }
if (srb->cmnd[0] == WRITE_10) { if (srb->cmnd[0] == WRITE_10) {
...@@ -569,7 +545,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -569,7 +545,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8])); blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
US_DEBUGP("jumpshot_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("jumpshot_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
return jumpshot_write_data(us, info, block, blocks, ptr, srb->use_sg); return jumpshot_write_data(us, info, block, blocks);
} }
if (srb->cmnd[0] == WRITE_12) { if (srb->cmnd[0] == WRITE_12) {
...@@ -582,7 +558,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -582,7 +558,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9])); ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
US_DEBUGP("jumpshot_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks); US_DEBUGP("jumpshot_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
return jumpshot_write_data(us, info, block, blocks, ptr, srb->use_sg); return jumpshot_write_data(us, info, block, blocks);
} }
......
...@@ -662,31 +662,24 @@ sddr09_read_status(struct us_data *us, unsigned char *status) { ...@@ -662,31 +662,24 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {
static int static int
sddr09_read_data(struct us_data *us, sddr09_read_data(struct us_data *us,
unsigned long address, unsigned long address,
unsigned int sectors, unsigned int sectors) {
unsigned char *buffer,
int use_sg) {
struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
unsigned char *buffer;
unsigned int lba, maxlba, pba; unsigned int lba, maxlba, pba;
unsigned int page, pages; unsigned int page, pages;
unsigned int len, index, offset; unsigned int len, index, offset;
int result; int result;
// Since we only read in one block at a time, we have to create // Since we only read in one block at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
// same effect. buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) {
if (use_sg) { printk("sddr09_read_data: Out of memory\n");
len = min(sectors, (unsigned int) info->blocksize) * return USB_STOR_TRANSPORT_ERROR;
info->pagesize;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) {
printk("sddr09_read_data: Out of memory\n");
return USB_STOR_TRANSPORT_ERROR;
}
} }
// Figure out the initial LBA and page // Figure out the initial LBA and page
...@@ -743,21 +736,16 @@ sddr09_read_data(struct us_data *us, ...@@ -743,21 +736,16 @@ sddr09_read_data(struct us_data *us,
break; break;
} }
// Store the data (s-g) or update the pointer (!s-g) // Store the data in the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &index, &offset, TO_XFER_BUF);
&index, &offset, TO_XFER_BUF);
else
buffer += len;
page = 0; page = 0;
lba++; lba++;
sectors -= pages; sectors -= pages;
} }
if (use_sg) kfree(buffer);
kfree(buffer);
return result; return result;
} }
...@@ -897,14 +885,13 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, ...@@ -897,14 +885,13 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
static int static int
sddr09_write_data(struct us_data *us, sddr09_write_data(struct us_data *us,
unsigned long address, unsigned long address,
unsigned int sectors, unsigned int sectors) {
unsigned char *buffer,
int use_sg) {
struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra; struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
unsigned int lba, page, pages; unsigned int lba, page, pages;
unsigned int pagelen, blocklen; unsigned int pagelen, blocklen;
unsigned char *blockbuffer; unsigned char *blockbuffer;
unsigned char *buffer;
unsigned int len, index, offset; unsigned int len, index, offset;
int result; int result;
...@@ -923,21 +910,15 @@ sddr09_write_data(struct us_data *us, ...@@ -923,21 +910,15 @@ sddr09_write_data(struct us_data *us,
} }
// Since we don't write the user data directly to the device, // Since we don't write the user data directly to the device,
// we have to create a bounce buffer if the transfer uses // we have to create a bounce buffer and move the data a piece
// scatter-gather. We will move the data a piece at a time // at a time between the bounce buffer and the actual transfer buffer.
// between the bounce buffer and the actual transfer buffer.
// If we're not using scatter-gather, we can simply update len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
// the transfer buffer pointer to get the same effect. buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) {
if (use_sg) { printk("sddr09_write_data: Out of memory\n");
len = min(sectors, (unsigned int) info->blocksize) * kfree(blockbuffer);
info->pagesize; return USB_STOR_TRANSPORT_ERROR;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) {
printk("sddr09_write_data: Out of memory\n");
kfree(blockbuffer);
return USB_STOR_TRANSPORT_ERROR;
}
} }
// Figure out the initial LBA and page // Figure out the initial LBA and page
...@@ -954,27 +935,21 @@ sddr09_write_data(struct us_data *us, ...@@ -954,27 +935,21 @@ sddr09_write_data(struct us_data *us,
pages = min(sectors, info->blocksize - page); pages = min(sectors, info->blocksize - page);
len = (pages << info->pageshift); len = (pages << info->pageshift);
// Get the data from the transfer buffer (s-g) // Get the data from the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &index, &offset, FROM_XFER_BUF);
&index, &offset, FROM_XFER_BUF);
result = sddr09_write_lba(us, lba, page, pages, result = sddr09_write_lba(us, lba, page, pages,
buffer, blockbuffer); buffer, blockbuffer);
if (result != USB_STOR_TRANSPORT_GOOD) if (result != USB_STOR_TRANSPORT_GOOD)
break; break;
// Update the transfer buffer pointer (!s-g)
if (!use_sg)
buffer += len;
page = 0; page = 0;
lba++; lba++;
sectors -= pages; sectors -= pages;
} }
if (use_sg) kfree(buffer);
kfree(buffer);
kfree(blockbuffer); kfree(blockbuffer);
return result; return result;
...@@ -1546,7 +1521,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1546,7 +1521,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("READ_10: read page %d pagect %d\n", US_DEBUGP("READ_10: read page %d pagect %d\n",
page, pages); page, pages);
return sddr09_read_data(us, page, pages, ptr, srb->use_sg); return sddr09_read_data(us, page, pages);
} }
if (srb->cmnd[0] == WRITE_10) { if (srb->cmnd[0] == WRITE_10) {
...@@ -1559,7 +1534,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1559,7 +1534,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("WRITE_10: write page %d pagect %d\n", US_DEBUGP("WRITE_10: write page %d pagect %d\n",
page, pages); page, pages);
return sddr09_write_data(us, page, pages, ptr, srb->use_sg); return sddr09_write_data(us, page, pages);
} }
// Pass TEST_UNIT_READY and REQUEST_SENSE through // Pass TEST_UNIT_READY and REQUEST_SENSE through
......
...@@ -153,14 +153,13 @@ static int sddr55_status(struct us_data *us) ...@@ -153,14 +153,13 @@ static int sddr55_status(struct us_data *us)
static int sddr55_read_data(struct us_data *us, static int sddr55_read_data(struct us_data *us,
unsigned int lba, unsigned int lba,
unsigned int page, unsigned int page,
unsigned short sectors, unsigned short sectors) {
unsigned char *buffer,
int use_sg) {
int result = USB_STOR_TRANSPORT_GOOD; int result = USB_STOR_TRANSPORT_GOOD;
unsigned char *command = us->iobuf; unsigned char *command = us->iobuf;
unsigned char *status = us->iobuf; unsigned char *status = us->iobuf;
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
unsigned char *buffer;
unsigned int pba; unsigned int pba;
unsigned long address; unsigned long address;
...@@ -169,20 +168,14 @@ static int sddr55_read_data(struct us_data *us, ...@@ -169,20 +168,14 @@ static int sddr55_read_data(struct us_data *us,
unsigned int len, index, offset; unsigned int len, index, offset;
// Since we only read in one block at a time, we have to create // Since we only read in one block at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the len = min((unsigned int) sectors, (unsigned int) info->blocksize >>
// same effect. info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (use_sg) { if (buffer == NULL)
len = min((unsigned int) sectors, return USB_STOR_TRANSPORT_ERROR; /* out of memory */
(unsigned int) info->blocksize >>
info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR; /* out of memory */
}
index = offset = 0; index = offset = 0;
while (sectors>0) { while (sectors>0) {
...@@ -258,12 +251,9 @@ static int sddr55_read_data(struct us_data *us, ...@@ -258,12 +251,9 @@ static int sddr55_read_data(struct us_data *us,
} }
} }
// Store the data (s-g) or update the pointer (!s-g) // Store the data in the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &index, &offset, TO_XFER_BUF);
&index, &offset, TO_XFER_BUF);
else
buffer += len;
page = 0; page = 0;
lba++; lba++;
...@@ -273,8 +263,7 @@ static int sddr55_read_data(struct us_data *us, ...@@ -273,8 +263,7 @@ static int sddr55_read_data(struct us_data *us,
result = USB_STOR_TRANSPORT_GOOD; result = USB_STOR_TRANSPORT_GOOD;
leave: leave:
if (use_sg) kfree(buffer);
kfree(buffer);
return result; return result;
} }
...@@ -282,14 +271,13 @@ static int sddr55_read_data(struct us_data *us, ...@@ -282,14 +271,13 @@ static int sddr55_read_data(struct us_data *us,
static int sddr55_write_data(struct us_data *us, static int sddr55_write_data(struct us_data *us,
unsigned int lba, unsigned int lba,
unsigned int page, unsigned int page,
unsigned short sectors, unsigned short sectors) {
unsigned char *buffer,
int use_sg) {
int result = USB_STOR_TRANSPORT_GOOD; int result = USB_STOR_TRANSPORT_GOOD;
unsigned char *command = us->iobuf; unsigned char *command = us->iobuf;
unsigned char *status = us->iobuf; unsigned char *status = us->iobuf;
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
unsigned char *buffer;
unsigned int pba; unsigned int pba;
unsigned int new_pba; unsigned int new_pba;
...@@ -306,20 +294,14 @@ static int sddr55_write_data(struct us_data *us, ...@@ -306,20 +294,14 @@ static int sddr55_write_data(struct us_data *us,
} }
// Since we only write one block at a time, we have to create // Since we only write one block at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the len = min((unsigned int) sectors, (unsigned int) info->blocksize >>
// same effect. info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (use_sg) { if (buffer == NULL)
len = min((unsigned int) sectors, return USB_STOR_TRANSPORT_ERROR;
(unsigned int) info->blocksize >>
info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
return USB_STOR_TRANSPORT_ERROR;
}
index = offset = 0; index = offset = 0;
while (sectors > 0) { while (sectors > 0) {
...@@ -336,10 +318,9 @@ static int sddr55_write_data(struct us_data *us, ...@@ -336,10 +318,9 @@ static int sddr55_write_data(struct us_data *us,
info->blocksize - page); info->blocksize - page);
len = pages << info->pageshift; len = pages << info->pageshift;
// Get the data from the transfer buffer (s-g) // Get the data from the transfer buffer
if (use_sg) usb_stor_access_xfer_buf(buffer, len, us->srb,
usb_stor_access_xfer_buf(buffer, len, us->srb, &index, &offset, FROM_XFER_BUF);
&index, &offset, FROM_XFER_BUF);
US_DEBUGP("Write %02X pages, to PBA %04X" US_DEBUGP("Write %02X pages, to PBA %04X"
" (LBA %04X) page %02X\n", " (LBA %04X) page %02X\n",
...@@ -480,9 +461,6 @@ static int sddr55_write_data(struct us_data *us, ...@@ -480,9 +461,6 @@ static int sddr55_write_data(struct us_data *us,
/* update the pba<->lba maps for new_pba */ /* update the pba<->lba maps for new_pba */
info->pba_to_lba[new_pba] = lba % 1000; info->pba_to_lba[new_pba] = lba % 1000;
// Update the transfer buffer pointer (!s-g)
if (!use_sg)
buffer += len;
page = 0; page = 0;
lba++; lba++;
sectors -= pages >> info->smallpageshift; sectors -= pages >> info->smallpageshift;
...@@ -490,8 +468,7 @@ static int sddr55_write_data(struct us_data *us, ...@@ -490,8 +468,7 @@ static int sddr55_write_data(struct us_data *us,
result = USB_STOR_TRANSPORT_GOOD; result = USB_STOR_TRANSPORT_GOOD;
leave: leave:
if (use_sg) kfree(buffer);
kfree(buffer);
return result; return result;
} }
...@@ -963,13 +940,13 @@ int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -963,13 +940,13 @@ int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
" pages %d\n", " pages %d\n",
pba, lba, page, pages); pba, lba, page, pages);
return sddr55_write_data(us, lba, page, pages, ptr, srb->use_sg); return sddr55_write_data(us, lba, page, pages);
} else { } else {
US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X" US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X"
" pages %d\n", " pages %d\n",
pba, lba, page, pages); pba, lba, page, pages);
return sddr55_read_data(us, lba, page, pages, ptr, srb->use_sg); return sddr55_read_data(us, lba, page, pages);
} }
} }
......
...@@ -569,21 +569,15 @@ int usbat_handle_read10(struct us_data *us, ...@@ -569,21 +569,15 @@ int usbat_handle_read10(struct us_data *us,
} }
// Since we only read in one block at a time, we have to create // Since we only read in one block at a time, we have to create
// a bounce buffer if the transfer uses scatter-gather. We will // a bounce buffer and move the data a piece at a time between the
// move the data a piece at a time between the bounce buffer and // bounce buffer and the actual transfer buffer.
// the actual transfer buffer. If we're not using scatter-gather,
// we can simply update the transfer buffer pointer to get the
// same effect.
len = (65535/srb->transfersize) * srb->transfersize; len = (65535/srb->transfersize) * srb->transfersize;
US_DEBUGP("Max read is %d bytes\n", len); US_DEBUGP("Max read is %d bytes\n", len);
len = min(len, srb->request_bufflen); len = min(len, srb->request_bufflen);
if (srb->use_sg) { buffer = kmalloc(len, GFP_NOIO);
buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) // bloody hell!
if (buffer == NULL) // bloody hell! return USB_STOR_TRANSPORT_FAILED;
return USB_STOR_TRANSPORT_FAILED;
} else
buffer = srb->request_buffer;
sector = short_pack(data[7+3], data[7+2]); sector = short_pack(data[7+3], data[7+2]);
sector <<= 16; sector <<= 16;
sector |= short_pack(data[7+5], data[7+4]); sector |= short_pack(data[7+5], data[7+4]);
...@@ -621,12 +615,9 @@ int usbat_handle_read10(struct us_data *us, ...@@ -621,12 +615,9 @@ int usbat_handle_read10(struct us_data *us,
if (result != USB_STOR_TRANSPORT_GOOD) if (result != USB_STOR_TRANSPORT_GOOD)
break; break;
// Store the data (s-g) or update the pointer (!s-g) // Store the data in the transfer buffer
if (srb->use_sg) usb_stor_access_xfer_buf(buffer, len, srb,
usb_stor_access_xfer_buf(buffer, len, srb, &sg_segment, &sg_offset, TO_XFER_BUF);
&sg_segment, &sg_offset, TO_XFER_BUF);
else
buffer += len;
// Update the amount transferred and the sector number // Update the amount transferred and the sector number
...@@ -635,8 +626,7 @@ int usbat_handle_read10(struct us_data *us, ...@@ -635,8 +626,7 @@ int usbat_handle_read10(struct us_data *us,
} // while transferred != srb->request_bufflen } // while transferred != srb->request_bufflen
if (srb->use_sg) kfree(buffer);
kfree(buffer);
return result; return result;
} }
......
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