diff options
author | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-02-18 03:51:42 +0100 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-02-18 03:51:42 +0100 |
commit | c58310bf4933986513020fa90b4190c7492995ae (patch) | |
tree | 143f2c7578d02ebef5db8fc57ae69e951ae0e2ee /drivers/scsi/arm/scsi.h | |
parent | [XFS] Added quota targets and removed dmapi directory (diff) | |
parent | Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
download | linux-c58310bf4933986513020fa90b4190c7492995ae.tar.xz linux-c58310bf4933986513020fa90b4190c7492995ae.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
Diffstat (limited to 'drivers/scsi/arm/scsi.h')
-rw-r--r-- | drivers/scsi/arm/scsi.h | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h index bb6550e31926..138a521ba1a8 100644 --- a/drivers/scsi/arm/scsi.h +++ b/drivers/scsi/arm/scsi.h @@ -18,17 +18,32 @@ * The scatter-gather list handling. This contains all * the yucky stuff that needs to be fixed properly. */ + +/* + * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max + * entries of uninitialized memory. SCp is from scsi-ml and has a valid + * (possibly chained) sg-list + */ static inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max) { int bufs = SCp->buffers_residual; + /* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg(). + * and to remove this BUG_ON. Use min() in-its-place + */ BUG_ON(bufs + 1 > max); sg_set_buf(sg, SCp->ptr, SCp->this_residual); - if (bufs) - memcpy(sg + 1, SCp->buffer + 1, - sizeof(struct scatterlist) * bufs); + if (bufs) { + struct scatterlist *src_sg; + unsigned i; + + for_each_sg(sg_next(SCp->buffer), src_sg, bufs, i) + *(++sg) = *src_sg; + sg_mark_end(sg); + } + return bufs + 1; } @@ -36,7 +51,7 @@ static inline int next_SCp(struct scsi_pointer *SCp) { int ret = SCp->buffers_residual; if (ret) { - SCp->buffer++; + SCp->buffer = sg_next(SCp->buffer); SCp->buffers_residual--; SCp->ptr = sg_virt(SCp->buffer); SCp->this_residual = SCp->buffer->length; @@ -68,46 +83,46 @@ static inline void init_SCp(struct scsi_cmnd *SCpnt) { memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); - if (SCpnt->use_sg) { + if (scsi_bufflen(SCpnt)) { unsigned long len = 0; - int buf; - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; - SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; + SCpnt->SCp.buffer = scsi_sglist(SCpnt); + SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1; SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer); SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - SCpnt->SCp.phase = SCpnt->request_bufflen; + SCpnt->SCp.phase = scsi_bufflen(SCpnt); #ifdef BELT_AND_BRACES - /* - * Calculate correct buffer length. Some commands - * come in with the wrong request_bufflen. - */ - for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) - len += SCpnt->SCp.buffer[buf].length; - - if (SCpnt->request_bufflen != len) - printk(KERN_WARNING "scsi%d.%c: bad request buffer " - "length %d, should be %ld\n", SCpnt->device->host->host_no, - '0' + SCpnt->device->id, SCpnt->request_bufflen, len); - SCpnt->request_bufflen = len; + { /* + * Calculate correct buffer length. Some commands + * come in with the wrong scsi_bufflen. + */ + struct scatterlist *sg; + unsigned i, sg_count = scsi_sg_count(SCpnt); + + scsi_for_each_sg(SCpnt, sg, sg_count, i) + len += sg->length; + + if (scsi_bufflen(SCpnt) != len) { + printk(KERN_WARNING + "scsi%d.%c: bad request buffer " + "length %d, should be %ld\n", + SCpnt->device->host->host_no, + '0' + SCpnt->device->id, + scsi_bufflen(SCpnt), len); + /* + * FIXME: Totaly naive fixup. We should abort + * with error + */ + SCpnt->SCp.phase = + min_t(unsigned long, len, + scsi_bufflen(SCpnt)); + } + } #endif } else { - SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; - SCpnt->SCp.phase = SCpnt->request_bufflen; - } - - /* - * If the upper SCSI layers pass a buffer, but zero length, - * we aren't interested in the buffer pointer. - */ - if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { -#if 0 //def BELT_AND_BRACES - printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " - "command ", SCpnt->host->host_no, '0' + SCpnt->target); - __scsi_print_command(SCpnt->cmnd); -#endif SCpnt->SCp.ptr = NULL; + SCpnt->SCp.this_residual = 0; + SCpnt->SCp.phase = 0; } } |