staging: unisys: visorhba: fix s-Par to boot with option CONFIG_VMAP_STACK set to y
authorSameer Wadgaonkar <sameer.wadgaonkar@unisys.com>
Tue, 18 Apr 2017 20:55:25 +0000 (16:55 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 24 Mar 2018 09:58:44 +0000 (10:58 +0100)
[ Upstream commit 3c2bf0bd08123f3497bd3e84bd9088c937b0cb40 ]

The root issue is that we are not allowed to have items on the
stack being passed to "DMA" like operations. In this case we have
a vmcall and an inline completion of scsi command.

This patch fixes the issue by moving the variables on stack in
do_scsi_nolinuxstat() to heap memory.

Signed-off-by: Sameer Wadgaonkar <sameer.wadgaonkar@unisys.com>
Signed-off-by: David Kershner <david.kershner@unisys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/unisys/visorhba/visorhba_main.c

index c119f20..3f2ccf9 100644 (file)
@@ -792,7 +792,7 @@ static void
 do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
 {
        struct scsi_device *scsidev;
-       unsigned char buf[36];
+       unsigned char *buf;
        struct scatterlist *sg;
        unsigned int i;
        char *this_page;
@@ -807,6 +807,10 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
                if (cmdrsp->scsi.no_disk_result == 0)
                        return;
 
+               buf = kzalloc(sizeof(char) * 36, GFP_KERNEL);
+               if (!buf)
+                       return;
+
                /* Linux scsi code wants a device at Lun 0
                 * to issue report luns, but we don't want
                 * a disk there so we'll present a processor
@@ -820,6 +824,7 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
                if (scsi_sg_count(scsicmd) == 0) {
                        memcpy(scsi_sglist(scsicmd), buf,
                               cmdrsp->scsi.bufflen);
+                       kfree(buf);
                        return;
                }
 
@@ -831,6 +836,7 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd)
                        memcpy(this_page, buf + bufind, sg[i].length);
                        kunmap_atomic(this_page_orig);
                }
+               kfree(buf);
        } else {
                devdata = (struct visorhba_devdata *)scsidev->host->hostdata;
                for_each_vdisk_match(vdisk, devdata, scsidev) {