ChangeSet 1.1504.2.25, 2003/12/09 11:46:03-08:00, stern@rowland.harvard.edu [PATCH] USB storage: Convert sddr55 to use the new s-g routines This patch changes the sddr55 driver to make it use the new scatter-gather routines. It has not been tested, but perhaps Andries Brouwer will be able to try it out. drivers/usb/storage/sddr55.c | 81 ++++++++++++++++++++++++------------------- 1 files changed, 46 insertions(+), 35 deletions(-) diff -Nru a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c --- a/drivers/usb/storage/sddr55.c Mon Dec 29 14:24:13 2003 +++ b/drivers/usb/storage/sddr55.c Mon Dec 29 14:24:13 2003 @@ -25,7 +25,6 @@ */ #include "transport.h" -#include "raw_bulk.h" #include "protocol.h" #include "usb.h" #include "debug.h" @@ -155,7 +154,7 @@ unsigned int lba, unsigned int page, unsigned short sectors, - unsigned char *content, + unsigned char *buffer, int use_sg) { int result = USB_STOR_TRANSPORT_GOOD; @@ -167,17 +166,20 @@ unsigned long address; unsigned short pages; - unsigned char *buffer = NULL; - unsigned char *ptr; - int len; + unsigned int len, index, offset; - len = sectors * PAGESIZE; + // Since we only read in one block at a time, we have to create + // a bounce buffer if the transfer uses scatter-gather. - buffer = (use_sg ? kmalloc(len, GFP_NOIO) : content); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; /* out of memory */ - - ptr = buffer; + if (use_sg) { + len = min((unsigned int) sectors, + (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; while (sectors>0) { @@ -189,9 +191,9 @@ // Read as many sectors as possible in this block - pages = info->blocksize - page; - if (pages > (sectors << info->smallpageshift)) - pages = (sectors << info->smallpageshift); + pages = min((unsigned int) sectors << info->smallpageshift, + info->blocksize - page); + len = pages << info->pageshift; US_DEBUGP("Read %02X pages, from PBA %04X" " (LBA %04X) page %02X\n", @@ -199,7 +201,7 @@ if (pba == NOT_ALLOCATED) { /* no pba for this lba, fill with zeroes */ - memset (ptr, 0, pages << info->pageshift); + memset (buffer, 0, len); } else { address = (pba << info->blockshift) + page; @@ -228,8 +230,7 @@ /* read data */ result = sddr55_bulk_transport(us, - SCSI_DATA_READ, ptr, - pages<pageshift); + SCSI_DATA_READ, buffer, len); if (result != USB_STOR_XFER_GOOD) { result = USB_STOR_TRANSPORT_ERROR; @@ -252,14 +253,17 @@ goto leave; } } + if (use_sg) + usb_stor_access_xfer_buf(buffer, len, us->srb, + &index, &offset, TO_XFER_BUF); + else + buffer += len; page = 0; lba++; sectors -= pages >> info->smallpageshift; - ptr += (pages << info->pageshift); } - us_copy_to_sgbuf_all(buffer, len, content, use_sg); result = USB_STOR_TRANSPORT_GOOD; leave: @@ -273,7 +277,7 @@ unsigned int lba, unsigned int page, unsigned short sectors, - unsigned char *content, + unsigned char *buffer, int use_sg) { int result = USB_STOR_TRANSPORT_GOOD; @@ -286,9 +290,8 @@ unsigned long address; unsigned short pages; - unsigned char *buffer = NULL; - unsigned char *ptr; - int i, len; + int i; + unsigned int len, index, offset; /* check if we are allowed to write */ if (info->read_only || info->force_read_only) { @@ -296,13 +299,18 @@ return USB_STOR_TRANSPORT_FAILED; } - len = sectors * PAGESIZE; + // Since we only write one block at a time, we have to create + // a bounce buffer if the transfer uses scatter-gather. - buffer = us_copy_from_sgbuf_all(content, len, use_sg); - if (buffer == NULL) - return USB_STOR_TRANSPORT_ERROR; - - ptr = buffer; + if (use_sg) { + len = min((unsigned int) sectors, + (unsigned int) info->blocksize >> + info->smallpageshift) * PAGESIZE; + buffer = kmalloc(len, GFP_NOIO); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; + } + index = offset = 0; while (sectors > 0) { @@ -314,9 +322,12 @@ // Write as many sectors as possible in this block - pages = info->blocksize - page; - if (pages > (sectors << info->smallpageshift)) - pages = (sectors << info->smallpageshift); + pages = min((unsigned int) sectors << info->smallpageshift, + info->blocksize - page); + len = pages << info->pageshift; + if (use_sg) + usb_stor_access_xfer_buf(buffer, len, us->srb, + &index, &offset, FROM_XFER_BUF); US_DEBUGP("Write %02X pages, to PBA %04X" " (LBA %04X) page %02X\n", @@ -400,8 +411,7 @@ /* send the data */ result = sddr55_bulk_transport(us, - SCSI_DATA_WRITE, ptr, - pages<pageshift); + SCSI_DATA_WRITE, buffer, len); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Result for send_data in write_data %d\n", @@ -458,10 +468,11 @@ /* update the pba<->lba maps for new_pba */ info->pba_to_lba[new_pba] = lba % 1000; + if (!use_sg) + buffer += len; page = 0; lba++; sectors -= pages >> info->smallpageshift; - ptr += (pages << info->pageshift); } result = USB_STOR_TRANSPORT_GOOD;