|
@@ -284,16 +284,78 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
|
|
return total_copied;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
|
|
|
+static unsigned int copy_to_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 src_addr = 0;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+
|
|
|
+ for (i = 0; i < orig_sgl_count; i++) {
|
|
|
+ src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
|
|
+ KM_IRQ0) + orig_sgl[i].offset;
|
|
|
+ src = src_addr;
|
|
|
+ srclen = orig_sgl[i].length;
|
|
|
+
|
|
|
+ if (bounce_addr == 0)
|
|
|
+ bounce_addr =
|
|
|
+ (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
|
|
+ KM_IRQ0);
|
|
|
+
|
|
|
+ while (srclen) {
|
|
|
+ /* assume bounce offset always == 0 */
|
|
|
+ dest = bounce_addr + bounce_sgl[j].length;
|
|
|
+ destlen = PAGE_SIZE - bounce_sgl[j].length;
|
|
|
+
|
|
|
+ copylen = min(srclen, destlen);
|
|
|
+ memcpy((void *)dest, (void *)src, copylen);
|
|
|
+
|
|
|
+ total_copied += copylen;
|
|
|
+ bounce_sgl[j].length += copylen;
|
|
|
+ srclen -= copylen;
|
|
|
+ src += copylen;
|
|
|
+
|
|
|
+ if (bounce_sgl[j].length == PAGE_SIZE) {
|
|
|
+ /* full..move to next entry */
|
|
|
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
+ j++;
|
|
|
+
|
|
|
+ /* if we need to use another bounce buffer */
|
|
|
+ if (srclen || i != orig_sgl_count - 1)
|
|
|
+ bounce_addr =
|
|
|
+ (unsigned long)kmap_atomic(
|
|
|
+ sg_page((&bounce_sgl[j])), KM_IRQ0);
|
|
|
+
|
|
|
+ } else if (srclen == 0 && i == orig_sgl_count - 1) {
|
|
|
+ /* unmap the last bounce that is < PAGE_SIZE */
|
|
|
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ kunmap_atomic((void *)(src_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_to_bounce_buffer(struct scatterlist *orig_sgl,
|
|
|
- struct scatterlist *bounce_sgl,
|
|
|
- unsigned int orig_sgl_count);
|
|
|
-
|
|
|
static int storvsc_get_chs(struct scsi_device *sdev, struct block_device *bdev,
|
|
|
sector_t capacity, int *info);
|
|
|
|
|
@@ -613,68 +675,6 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
|
|
|
kmem_cache_free(host_dev->request_pool, cmd_request);
|
|
|
}
|
|
|
|
|
|
-/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
|
|
|
-static unsigned int copy_to_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 src_addr = 0;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- local_irq_save(flags);
|
|
|
-
|
|
|
- for (i = 0; i < orig_sgl_count; i++) {
|
|
|
- src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
|
|
- KM_IRQ0) + orig_sgl[i].offset;
|
|
|
- src = src_addr;
|
|
|
- srclen = 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 (srclen) {
|
|
|
- /* assume bounce offset always == 0 */
|
|
|
- dest = bounce_addr + bounce_sgl[j].length;
|
|
|
- destlen = PAGE_SIZE - bounce_sgl[j].length;
|
|
|
-
|
|
|
- copylen = min(srclen, destlen);
|
|
|
- memcpy((void *)dest, (void *)src, copylen);
|
|
|
-
|
|
|
- total_copied += copylen;
|
|
|
- bounce_sgl[j].length += copylen;
|
|
|
- srclen -= copylen;
|
|
|
- src += copylen;
|
|
|
-
|
|
|
- if (bounce_sgl[j].length == PAGE_SIZE) {
|
|
|
- /* full..move to next entry */
|
|
|
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
- j++;
|
|
|
-
|
|
|
- /* if we need to use another bounce buffer */
|
|
|
- if (srclen || i != orig_sgl_count - 1)
|
|
|
- bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
|
|
|
- } else if (srclen == 0 && i == orig_sgl_count - 1) {
|
|
|
- /* unmap the last bounce that is < PAGE_SIZE */
|
|
|
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0);
|
|
|
- }
|
|
|
-
|
|
|
- local_irq_restore(flags);
|
|
|
-
|
|
|
- return total_copied;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* storvsc_queuecommand - Initiate command processing
|
|
|
*/
|