| From foo@baz Thu Mar 22 14:57:32 CET 2018 |
| From: Sameer Wadgaonkar <sameer.wadgaonkar@unisys.com> |
| Date: Tue, 18 Apr 2017 16:55:25 -0400 |
| Subject: staging: unisys: visorhba: fix s-Par to boot with option CONFIG_VMAP_STACK set to y |
| |
| From: Sameer Wadgaonkar <sameer.wadgaonkar@unisys.com> |
| |
| |
| [ 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 | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/staging/unisys/visorhba/visorhba_main.c |
| +++ b/drivers/staging/unisys/visorhba/visorhba_main.c |
| @@ -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 *cm |
| 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 *cm |
| 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 *cm |
| 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) { |