Merge tag 'gpio-fixes-for-v5.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / scsi / storvsc_drv.c
index 20595c0..9a0bba5 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/device.h>
 #include <linux/hyperv.h>
 #include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
@@ -1336,6 +1338,7 @@ static void storvsc_on_channel_callback(void *context)
                                        continue;
                                }
                                request = (struct storvsc_cmd_request *)scsi_cmd_priv(scmnd);
+                               scsi_dma_unmap(scmnd);
                        }
 
                        storvsc_on_receive(stor_device, packet, request);
@@ -1749,9 +1752,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        struct hv_host_device *host_dev = shost_priv(host);
        struct hv_device *dev = host_dev->dev;
        struct storvsc_cmd_request *cmd_request = scsi_cmd_priv(scmnd);
-       int i;
        struct scatterlist *sgl;
-       unsigned int sg_count;
        struct vmscsi_request *vm_srb;
        struct vmbus_packet_mpb_array  *payload;
        u32 payload_sz;
@@ -1824,17 +1825,17 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length);
 
        sgl = (struct scatterlist *)scsi_sglist(scmnd);
-       sg_count = scsi_sg_count(scmnd);
 
        length = scsi_bufflen(scmnd);
        payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb;
        payload_sz = sizeof(cmd_request->mpb);
 
-       if (sg_count) {
-               unsigned int hvpgoff, hvpfns_to_add;
+       if (scsi_sg_count(scmnd)) {
                unsigned long offset_in_hvpg = offset_in_hvpage(sgl->offset);
                unsigned int hvpg_count = HVPFN_UP(offset_in_hvpg + length);
-               u64 hvpfn;
+               struct scatterlist *sg;
+               unsigned long hvpfn, hvpfns_to_add;
+               int j, i = 0, sg_count;
 
                if (hvpg_count > MAX_PAGE_BUFFER_COUNT) {
 
@@ -1848,21 +1849,24 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
                payload->range.len = length;
                payload->range.offset = offset_in_hvpg;
 
+               sg_count = scsi_dma_map(scmnd);
+               if (sg_count < 0) {
+                       ret = SCSI_MLQUEUE_DEVICE_BUSY;
+                       goto err_free_payload;
+               }
 
-               for (i = 0; sgl != NULL; sgl = sg_next(sgl)) {
+               for_each_sg(sgl, sg, sg_count, j) {
                        /*
-                        * Init values for the current sgl entry. hvpgoff
-                        * and hvpfns_to_add are in units of Hyper-V size
-                        * pages. Handling the PAGE_SIZE != HV_HYP_PAGE_SIZE
-                        * case also handles values of sgl->offset that are
-                        * larger than PAGE_SIZE. Such offsets are handled
-                        * even on other than the first sgl entry, provided
-                        * they are a multiple of PAGE_SIZE.
+                        * Init values for the current sgl entry. hvpfns_to_add
+                        * is in units of Hyper-V size pages. Handling the
+                        * PAGE_SIZE != HV_HYP_PAGE_SIZE case also handles
+                        * values of sgl->offset that are larger than PAGE_SIZE.
+                        * Such offsets are handled even on other than the first
+                        * sgl entry, provided they are a multiple of PAGE_SIZE.
                         */
-                       hvpgoff = HVPFN_DOWN(sgl->offset);
-                       hvpfn = page_to_hvpfn(sg_page(sgl)) + hvpgoff;
-                       hvpfns_to_add = HVPFN_UP(sgl->offset + sgl->length) -
-                                               hvpgoff;
+                       hvpfn = HVPFN_DOWN(sg_dma_address(sg));
+                       hvpfns_to_add = HVPFN_UP(sg_dma_address(sg) +
+                                                sg_dma_len(sg)) - hvpfn;
 
                        /*
                         * Fill the next portion of the PFN array with
@@ -1872,7 +1876,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
                         * the PFN array is filled.
                         */
                        while (hvpfns_to_add--)
-                               payload->range.pfn_array[i++] = hvpfn++;
+                               payload->range.pfn_array[i++] = hvpfn++;
                }
        }
 
@@ -1884,13 +1888,18 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        put_cpu();
 
        if (ret == -EAGAIN) {
-               if (payload_sz > sizeof(cmd_request->mpb))
-                       kfree(payload);
                /* no more space */
-               return SCSI_MLQUEUE_DEVICE_BUSY;
+               ret = SCSI_MLQUEUE_DEVICE_BUSY;
+               goto err_free_payload;
        }
 
        return 0;
+
+err_free_payload:
+       if (payload_sz > sizeof(cmd_request->mpb))
+               kfree(payload);
+
+       return ret;
 }
 
 static struct scsi_host_template scsi_driver = {
@@ -2016,6 +2025,7 @@ static int storvsc_probe(struct hv_device *device,
        stor_device->vmscsi_size_delta = sizeof(struct vmscsi_win8_extension);
        spin_lock_init(&stor_device->lock);
        hv_set_drvdata(device, stor_device);
+       dma_set_min_align_mask(&device->device, HV_HYP_PAGE_SIZE - 1);
 
        stor_device->port_number = host->host_no;
        ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size, is_fc);