|
@@ -219,15 +219,77 @@ cleanup:
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/* Assume the original sgl has enough room */
|
|
|
+static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
|
|
+ struct scatterlist *bounce_sgl,
|
|
|
+ unsigned int orig_sgl_count)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ int j = 0;
|
|
|
+ unsigned long src, dest;
|
|
|
+ unsigned int srclen, destlen, copylen;
|
|
|
+ unsigned int total_copied = 0;
|
|
|
+ unsigned long bounce_addr = 0;
|
|
|
+ unsigned long dest_addr = 0;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+
|
|
|
+ for (i = 0; i < orig_sgl_count; i++) {
|
|
|
+ dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
|
|
+ KM_IRQ0) + orig_sgl[i].offset;
|
|
|
+ dest = dest_addr;
|
|
|
+ destlen = orig_sgl[i].length;
|
|
|
+
|
|
|
+ if (bounce_addr == 0)
|
|
|
+ bounce_addr =
|
|
|
+ (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
|
|
+ KM_IRQ0);
|
|
|
+
|
|
|
+ while (destlen) {
|
|
|
+ src = bounce_addr + bounce_sgl[j].offset;
|
|
|
+ srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
|
|
|
+
|
|
|
+ copylen = min(srclen, destlen);
|
|
|
+ memcpy((void *)dest, (void *)src, copylen);
|
|
|
+
|
|
|
+ total_copied += copylen;
|
|
|
+ bounce_sgl[j].offset += copylen;
|
|
|
+ destlen -= copylen;
|
|
|
+ dest += copylen;
|
|
|
+
|
|
|
+ if (bounce_sgl[j].offset == bounce_sgl[j].length) {
|
|
|
+ /* full */
|
|
|
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
+ j++;
|
|
|
+
|
|
|
+ /* if we need to use another bounce buffer */
|
|
|
+ if (destlen || i != orig_sgl_count - 1)
|
|
|
+ bounce_addr =
|
|
|
+ (unsigned long)kmap_atomic(
|
|
|
+ sg_page((&bounce_sgl[j])), KM_IRQ0);
|
|
|
+ } else if (destlen == 0 && i == orig_sgl_count - 1) {
|
|
|
+ /* unmap the last bounce that is < PAGE_SIZE */
|
|
|
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
|
|
|
+ KM_IRQ0);
|
|
|
+ }
|
|
|
+
|
|
|
+ local_irq_restore(flags);
|
|
|
+
|
|
|
+ return total_copied;
|
|
|
+}
|
|
|
+
|
|
|
/* Static decl */
|
|
|
static int storvsc_probe(struct hv_device *dev);
|
|
|
static int storvsc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd);
|
|
|
static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd);
|
|
|
static int storvsc_remove(struct hv_device *dev);
|
|
|
|
|
|
-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
|
|
- struct scatterlist *bounce_sgl,
|
|
|
- unsigned int orig_sgl_count);
|
|
|
static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
|
|
struct scatterlist *bounce_sgl,
|
|
|
unsigned int orig_sgl_count);
|
|
@@ -613,67 +675,6 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
|
|
return total_copied;
|
|
|
}
|
|
|
|
|
|
-/* Assume the original sgl has enough room */
|
|
|
-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
|
|
- struct scatterlist *bounce_sgl,
|
|
|
- unsigned int orig_sgl_count)
|
|
|
-{
|
|
|
- int i;
|
|
|
- int j = 0;
|
|
|
- unsigned long src, dest;
|
|
|
- unsigned int srclen, destlen, copylen;
|
|
|
- unsigned int total_copied = 0;
|
|
|
- unsigned long bounce_addr = 0;
|
|
|
- unsigned long dest_addr = 0;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- local_irq_save(flags);
|
|
|
-
|
|
|
- for (i = 0; i < orig_sgl_count; i++) {
|
|
|
- dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
|
|
- KM_IRQ0) + orig_sgl[i].offset;
|
|
|
- dest = dest_addr;
|
|
|
- destlen = orig_sgl[i].length;
|
|
|
- /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */
|
|
|
-
|
|
|
- if (bounce_addr == 0)
|
|
|
- bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
|
|
|
-
|
|
|
- while (destlen) {
|
|
|
- src = bounce_addr + bounce_sgl[j].offset;
|
|
|
- srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
|
|
|
-
|
|
|
- copylen = min(srclen, destlen);
|
|
|
- memcpy((void *)dest, (void *)src, copylen);
|
|
|
-
|
|
|
- total_copied += copylen;
|
|
|
- bounce_sgl[j].offset += copylen;
|
|
|
- destlen -= copylen;
|
|
|
- dest += copylen;
|
|
|
-
|
|
|
- if (bounce_sgl[j].offset == bounce_sgl[j].length) {
|
|
|
- /* full */
|
|
|
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
- j++;
|
|
|
-
|
|
|
- /* if we need to use another bounce buffer */
|
|
|
- if (destlen || i != orig_sgl_count - 1)
|
|
|
- bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
|
|
|
- } else if (destlen == 0 && i == orig_sgl_count - 1) {
|
|
|
- /* unmap the last bounce that is < PAGE_SIZE */
|
|
|
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
|
|
|
- KM_IRQ0);
|
|
|
- }
|
|
|
-
|
|
|
- local_irq_restore(flags);
|
|
|
-
|
|
|
- return total_copied;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* storvsc_queuecommand - Initiate command processing
|
|
|
*/
|