Put some limit checking on dma segments so that
authorzorko <zorko@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 23 Feb 2009 23:18:25 +0000 (23:18 +0000)
committerzorko <zorko@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Mon, 23 Feb 2009 23:18:25 +0000 (23:18 +0000)
we don't, somehow, inadvertantly overrun the total
number of queue entries for a command + continuation
segments.

git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@680 d57e44dd-8a1f-0410-8b47-8ef2f437770f

qla_isp/common/ispmbox.h
qla_isp/linux/isp_pci.c

index 09d6ddb..f3b1647 100644 (file)
@@ -2548,4 +2548,19 @@ typedef struct {
 #define        ISP24XX_ABTS_RSP_SUBCODE        0x31
 
 #define        ISP24XX_NO_TASK                 0xffffffff
+
+/*
+ * Miscellaneous
+ *
+ * These are the limits of the number of dma segments we
+ * can deal with based not on the size of the segment counter
+ * (which is 16 bits), but on the size of the number of 
+ * queue entries field (which is 8 bits). We assume no
+ * segments in the first queue entry, so we can either
+ * have 7 dma segments per continuation entry or 5
+ * (for 64 bit dma).. multiplying out by 254....
+ */
+#define        ISP_NSEG_MAX    1778
+#define        ISP_NSEG64_MAX  1270
+
 #endif /* _ISPMBOX_H */
index 3ed717f..e0ce9a6 100644 (file)
@@ -1627,7 +1627,17 @@ isp_pci_dmasetup_tgt(ispsoftc_t *isp, tmd_xact_t *xact, void *fqe)
         sg = NULL;
         nseg = 0;
     }
-
+    if (isp->isp_osinfo.is_64bit_dma) {
+        if (nseg >= ISP_NSEG64_MAX) {
+            isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
+            xact->td_error = -EFAULT;
+            return (CMD_COMPLETE);
+        }
+    } else if (nseg >= ISP_NSEG_MAX) {
+        isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX);
+        xact->td_error = -EFAULT;
+        return (CMD_COMPLETE);
+    }
     ret = isp_send_tgt_cmd(isp, fqe, sg, nseg, xact->td_xfrlen, ddir, xact->td_cmd->cd_sense, TMD_SENSELEN);
     if (ret == CMD_QUEUED) {
         int bin;
@@ -1729,6 +1739,17 @@ isp_pci_dmasetup(ispsoftc_t *isp, Scsi_Cmnd *Cmnd, void *fqe)
         sg = NULL;
         nseg = 0;
     }
+    if (isp->isp_osinfo.is_64bit_dma) {
+        if (nseg >= ISP_NSEG64_MAX) {
+            isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
+            XS_SETERR(Cmnd, HBA_BOTCH);
+            return (CMD_COMPLETE);
+        }
+    } else if (nseg >= ISP_NSEG_MAX) {
+        isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX);
+        XS_SETERR(Cmnd, HBA_BOTCH);
+        return (CMD_COMPLETE);
+    }
     ret = isp_send_cmd(isp, fqe, sg, nseg, XS_XFRLEN(Cmnd), ddir);
     if (ret == CMD_QUEUED) {
         int bin;