Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f6f31a0 authored by Jens Axboe's avatar Jens Axboe
Browse files

USB storage: sg chaining support



[PATCH] USB storage: sg chaining support

Modify usb_stor_access_xfer_buf() to take a pointer to an sg
entry pointer, so we can keep track of that instead of passing
around an integer index (which we can't use when dealing with
multiple scatterlist arrays).

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 53d412fc
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -798,12 +798,13 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
{
	unsigned char *buffer;
	u16 lba, max_lba;
	unsigned int page, len, index, offset;
	unsigned int page, len, offset;
	unsigned int blockshift = MEDIA_INFO(us).blockshift;
	unsigned int pageshift = MEDIA_INFO(us).pageshift;
	unsigned int blocksize = MEDIA_INFO(us).blocksize;
	unsigned int pagesize = MEDIA_INFO(us).pagesize;
	unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
	struct scatterlist *sg;
	int result;

	/*
@@ -827,7 +828,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
	max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift);

	result = USB_STOR_TRANSPORT_GOOD;
	index = offset = 0;
	offset = 0;
	sg = NULL;

	while (sectors > 0) {
		unsigned int zone = lba / uzonesize; /* integer division */
@@ -873,7 +875,7 @@ static int alauda_read_data(struct us_data *us, unsigned long address,

		/* Store the data in the transfer buffer */
		usb_stor_access_xfer_buf(buffer, len, us->srb,
				&index, &offset, TO_XFER_BUF);
				&sg, &offset, TO_XFER_BUF);

		page = 0;
		lba++;
@@ -891,11 +893,12 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
		unsigned int sectors)
{
	unsigned char *buffer, *blockbuffer;
	unsigned int page, len, index, offset;
	unsigned int page, len, offset;
	unsigned int blockshift = MEDIA_INFO(us).blockshift;
	unsigned int pageshift = MEDIA_INFO(us).pageshift;
	unsigned int blocksize = MEDIA_INFO(us).blocksize;
	unsigned int pagesize = MEDIA_INFO(us).pagesize;
	struct scatterlist *sg;
	u16 lba, max_lba;
	int result;

@@ -929,7 +932,8 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
	max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift);

	result = USB_STOR_TRANSPORT_GOOD;
	index = offset = 0;
	offset = 0;
	sg = NULL;

	while (sectors > 0) {
		/* Write as many sectors as possible in this block */
@@ -946,7 +950,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address,

		/* Get the data from the transfer buffer */
		usb_stor_access_xfer_buf(buffer, len, us->srb,
				&index, &offset, FROM_XFER_BUF);
				&sg, &offset, FROM_XFER_BUF);

		result = alauda_write_lba(us, lba, page, pages, buffer,
			blockbuffer);
+6 −4
Original line number Diff line number Diff line
@@ -98,7 +98,8 @@ static int datafab_read_data(struct us_data *us,
	unsigned char  thistime;
	unsigned int totallen, alloclen;
	int len, result;
	unsigned int sg_idx = 0, sg_offset = 0;
	unsigned int sg_offset = 0;
	struct scatterlist *sg = NULL;

	// we're working in LBA mode.  according to the ATA spec, 
	// we can support up to 28-bit addressing.  I don't know if Datafab
@@ -155,7 +156,7 @@ static int datafab_read_data(struct us_data *us,

		// Store the data in the transfer buffer
		usb_stor_access_xfer_buf(buffer, len, us->srb,
				 &sg_idx, &sg_offset, TO_XFER_BUF);
				 &sg, &sg_offset, TO_XFER_BUF);

		sector += thistime;
		totallen -= len;
@@ -181,7 +182,8 @@ static int datafab_write_data(struct us_data *us,
	unsigned char thistime;
	unsigned int totallen, alloclen;
	int len, result;
	unsigned int sg_idx = 0, sg_offset = 0;
	unsigned int sg_offset = 0;
	struct scatterlist *sg = NULL;

	// we're working in LBA mode.  according to the ATA spec, 
	// we can support up to 28-bit addressing.  I don't know if Datafab
@@ -217,7 +219,7 @@ static int datafab_write_data(struct us_data *us,

		// Get the data from the transfer buffer
		usb_stor_access_xfer_buf(buffer, len, us->srb,
				&sg_idx, &sg_offset, FROM_XFER_BUF);
				&sg, &sg_offset, FROM_XFER_BUF);

		command[0] = 0;
		command[1] = thistime;
+6 −4
Original line number Diff line number Diff line
@@ -119,7 +119,8 @@ static int jumpshot_read_data(struct us_data *us,
	unsigned char  thistime;
	unsigned int totallen, alloclen;
	int len, result;
	unsigned int sg_idx = 0, sg_offset = 0;
	unsigned int sg_offset = 0;
	struct scatterlist *sg = NULL;

	// we're working in LBA mode.  according to the ATA spec, 
	// we can support up to 28-bit addressing.  I don't know if Jumpshot
@@ -170,7 +171,7 @@ static int jumpshot_read_data(struct us_data *us,

		// Store the data in the transfer buffer
		usb_stor_access_xfer_buf(buffer, len, us->srb,
				 &sg_idx, &sg_offset, TO_XFER_BUF);
				 &sg, &sg_offset, TO_XFER_BUF);

		sector += thistime;
		totallen -= len;
@@ -195,7 +196,8 @@ static int jumpshot_write_data(struct us_data *us,
	unsigned char  thistime;
	unsigned int totallen, alloclen;
	int len, result, waitcount;
	unsigned int sg_idx = 0, sg_offset = 0;
	unsigned int sg_offset = 0;
	struct scatterlist *sg = NULL;

	// we're working in LBA mode.  according to the ATA spec, 
	// we can support up to 28-bit addressing.  I don't know if Jumpshot
@@ -225,7 +227,7 @@ static int jumpshot_write_data(struct us_data *us,

		// Get the data from the transfer buffer
		usb_stor_access_xfer_buf(buffer, len, us->srb,
				&sg_idx, &sg_offset, FROM_XFER_BUF);
				&sg, &sg_offset, FROM_XFER_BUF);

		command[0] = 0;
		command[1] = thistime;
+11 −9
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
 * pick up from where this one left off. */

unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
	unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
	unsigned int *offset, enum xfer_buf_dir dir)
{
	unsigned int cnt;
@@ -184,16 +184,17 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
	 * located in high memory -- then kmap() will map it to a temporary
	 * position in the kernel's virtual address space. */
	} else {
		struct scatterlist *sg =
				(struct scatterlist *) srb->request_buffer
				+ *index;
		struct scatterlist *sg = *sgptr;

		if (!sg)
			sg = (struct scatterlist *) srb->request_buffer;

		/* This loop handles a single s-g list entry, which may
		 * include multiple pages.  Find the initial page structure
		 * and the starting offset within the page, and update
		 * the *offset and *index values for the next loop. */
		cnt = 0;
		while (cnt < buflen && *index < srb->use_sg) {
		while (cnt < buflen) {
			struct page *page = sg->page +
					((sg->offset + *offset) >> PAGE_SHIFT);
			unsigned int poff =
@@ -209,8 +210,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,

				/* Transfer continues to next s-g entry */
				*offset = 0;
				++*index;
				++sg;
				sg = sg_next(sg);
			}

			/* Transfer the data for all the pages in this
@@ -234,6 +234,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
				sglen -= plen;
			}
		}
		*sgptr = sg;
	}

	/* Return the amount actually transferred */
@@ -245,9 +246,10 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
void usb_stor_set_xfer_buf(unsigned char *buffer,
	unsigned int buflen, struct scsi_cmnd *srb)
{
	unsigned int index = 0, offset = 0;
	unsigned int offset = 0;
	struct scatterlist *sg = NULL;

	usb_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
	usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
			TO_XFER_BUF);
	if (buflen < srb->request_bufflen)
		srb->resid = srb->request_bufflen - buflen;
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*,
enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};

extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
	unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **,
	unsigned int *offset, enum xfer_buf_dir dir);

extern void usb_stor_set_xfer_buf(unsigned char *buffer,
Loading