diff mbox series

[04/26] qedf: Simplify s/g list mapping.

Message ID 20190305105901.13185-5-skashyap@marvell.com (mailing list archive)
State Superseded
Headers show
Series qedf: Misc fixes for the driver. | expand

Commit Message

Saurav Kashyap March 5, 2019, 10:58 a.m. UTC
From: Chad Dupuis <cdupuis@marvell.com>

When mapping the pages from a scatter/gather list from the SCSI layer we
only need to follow these rules:

o Max SGEs for each I/O request is 256
o No size limit on each SGE
o No need to split OS provided SGEs to 4K before sending to firmware.
o Slow SGE is applicable only when:
  - There are > 8 SGEs and any middle SGE is less than a page size (4K)

Make necessary changes so that driver follows these rules.
applicable only for Write requests (not for Read requests)
No need to check SGE address alignment requirements
(first, middle or last) before declaring slow SGE

Signed-off-by: Chad Dupuis <cdupuis@marvell.com>
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
---
 drivers/scsi/qedf/qedf.h         |   8 +--
 drivers/scsi/qedf/qedf_debugfs.c |   2 -
 drivers/scsi/qedf/qedf_io.c      | 124 ++++++++++++---------------------------
 3 files changed, 40 insertions(+), 94 deletions(-)

Comments

kernel test robot March 17, 2019, 1:14 p.m. UTC | #1
Hi Saurav,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on v5.0 next-20190306]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Saurav-Kashyap/qedf-Misc-fixes-for-the-driver/20190305-205913
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'


sparse warnings: (new ones prefixed by >>)

   include/linux/slab.h:664:13: sparse: undefined identifier '__builtin_mul_overflow'
   drivers/scsi/qedf/qedf_io.c:469:42: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] lo @@    got unsignrestricted __le32 [usertype] lo @@
   drivers/scsi/qedf/qedf_io.c:469:42:    expected restricted __le32 [usertype] lo
   drivers/scsi/qedf/qedf_io.c:469:42:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:470:43: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] hi @@    got unsignrestricted __le32 [usertype] hi @@
   drivers/scsi/qedf/qedf_io.c:470:43:    expected restricted __le32 [usertype] hi
   drivers/scsi/qedf/qedf_io.c:470:43:    got unsigned int [unsigned] [usertype] <noident>
>> drivers/scsi/qedf/qedf_io.c:471:38: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] sge_len @@    got unsigned int [unsrestricted __le32 [usertype] sge_len @@
   drivers/scsi/qedf/qedf_io.c:471:38:    expected restricted __le32 [usertype] sge_len
   drivers/scsi/qedf/qedf_io.c:471:38:    got unsigned int [unsigned] [assigned] [usertype] sg_len
   drivers/scsi/qedf/qedf_io.c:598:59: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] lo @@    got unsignrestricted __le32 [usertype] lo @@
   drivers/scsi/qedf/qedf_io.c:598:59:    expected restricted __le32 [usertype] lo
   drivers/scsi/qedf/qedf_io.c:598:59:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:600:59: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] hi @@    got unsignrestricted __le32 [usertype] hi @@
   drivers/scsi/qedf/qedf_io.c:600:59:    expected restricted __le32 [usertype] hi
   drivers/scsi/qedf/qedf_io.c:600:59:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:612:40: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] lo @@    got unsignrestricted __le32 [usertype] lo @@
   drivers/scsi/qedf/qedf_io.c:612:40:    expected restricted __le32 [usertype] lo
   drivers/scsi/qedf/qedf_io.c:612:40:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:613:40: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] hi @@    got unsignrestricted __le32 [usertype] hi @@
   drivers/scsi/qedf/qedf_io.c:613:40:    expected restricted __le32 [usertype] hi
   drivers/scsi/qedf/qedf_io.c:613:40:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:621:33: sparse: incorrect type in assignment (different base types) @@    expected unsigned int [unsigned] <noident> @@    got restrunsigned int [unsigned] <noident> @@
   drivers/scsi/qedf/qedf_io.c:621:33:    expected unsigned int [unsigned] <noident>
   drivers/scsi/qedf/qedf_io.c:621:33:    got restricted __be32 [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:677:26: sparse: incorrect type in assignment (different base types) @@    expected restricted __be16 [usertype] fh_ox_id @@    got unsignedrestricted __be16 [usertype] fh_ox_id @@
   drivers/scsi/qedf/qedf_io.c:677:26:    expected restricted __be16 [usertype] fh_ox_id
   drivers/scsi/qedf/qedf_io.c:677:26:    got unsigned short [unsigned] [usertype] xid
   drivers/scsi/qedf/qedf_io.c:681:31: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [addressable] [usertype] parameter @@    got e32 [addressable] [usertype] parameter @@
   drivers/scsi/qedf/qedf_io.c:681:31:    expected restricted __le32 [addressable] [usertype] parameter
   drivers/scsi/qedf/qedf_io.c:681:31:    got restricted __be32 [usertype] fh_parm_offset
   drivers/scsi/qedf/qedf_io.c:686:27: sparse: incorrect type in assignment (different base types) @@    expected restricted __le16 [addressable] [assigned] [usertype] rx_id @@    got sable] [assigned] [usertype] rx_id @@
   drivers/scsi/qedf/qedf_io.c:686:27:    expected restricted __le16 [addressable] [assigned] [usertype] rx_id
   drivers/scsi/qedf/qedf_io.c:686:27:    got restricted __be16 [usertype] fh_rx_id
   drivers/scsi/qedf/qedf_io.c:687:27: sparse: incorrect type in assignment (different base types) @@    expected restricted __le16 [addressable] [assigned] [usertype] ox_id @@    got sable] [assigned] [usertype] ox_id @@
   drivers/scsi/qedf/qedf_io.c:687:27:    expected restricted __le16 [addressable] [assigned] [usertype] ox_id
   drivers/scsi/qedf/qedf_io.c:687:27:    got restricted __be16 [usertype] fh_ox_id
   drivers/scsi/qedf/qedf_io.c:691:45: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [addressable] [assigned] [usertype] lo @@    got addressable] [assigned] [usertype] lo @@
   drivers/scsi/qedf/qedf_io.c:691:45:    expected restricted __le32 [addressable] [assigned] [usertype] lo
   drivers/scsi/qedf/qedf_io.c:691:45:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:692:45: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [addressable] [assigned] [usertype] hi @@    got addressable] [assigned] [usertype] hi @@
   drivers/scsi/qedf/qedf_io.c:692:45:    expected restricted __le32 [addressable] [assigned] [usertype] hi
   drivers/scsi/qedf/qedf_io.c:692:45:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:700:45: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [addressable] [assigned] [usertype] lo @@    got addressable] [assigned] [usertype] lo @@
   drivers/scsi/qedf/qedf_io.c:700:45:    expected restricted __le32 [addressable] [assigned] [usertype] lo
   drivers/scsi/qedf/qedf_io.c:700:45:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:701:45: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [addressable] [assigned] [usertype] hi @@    got addressable] [assigned] [usertype] hi @@
   drivers/scsi/qedf/qedf_io.c:701:45:    expected restricted __le32 [addressable] [assigned] [usertype] hi
   drivers/scsi/qedf/qedf_io.c:701:45:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:746:23: sparse: incorrect type in assignment (different base types) @@    expected restricted __le16 [assigned] [usertype] sq_prod @@    got tricted __le16 [assigned] [usertype] sq_prod @@
   drivers/scsi/qedf/qedf_io.c:746:23:    expected restricted __le16 [assigned] [usertype] sq_prod
   drivers/scsi/qedf/qedf_io.c:746:23:    got unsigned short [unsigned] [usertype] fw_sq_prod_idx
   drivers/scsi/qedf/qedf_io.c:989:35: sparse: incorrect type in assignment (different base types) @@    expected unsigned int [unsigned] [usertype] fcp_resid @@    got ed int [unsigned] [usertype] fcp_resid @@
   drivers/scsi/qedf/qedf_io.c:989:35:    expected unsigned int [unsigned] [usertype] fcp_resid
   drivers/scsi/qedf/qedf_io.c:989:35:    got restricted __le32 [usertype] fcp_resid
   drivers/scsi/qedf/qedf_io.c:997:29: sparse: incorrect type in assignment (different base types) @@    expected int [signed] fcp_rsp_len @@    got restricted __le3int [signed] fcp_rsp_len @@
   drivers/scsi/qedf/qedf_io.c:997:29:    expected int [signed] fcp_rsp_len
   drivers/scsi/qedf/qedf_io.c:997:29:    got restricted __le32 [usertype] fcp_rsp_len
   drivers/scsi/qedf/qedf_io.c:1001:29: sparse: incorrect type in assignment (different base types) @@    expected int [signed] fcp_sns_len @@    got restricted __le3int [signed] fcp_sns_len @@
   drivers/scsi/qedf/qedf_io.c:1001:29:    expected int [signed] fcp_sns_len
   drivers/scsi/qedf/qedf_io.c:1001:29:    got restricted __le32 [usertype] fcp_sns_len
   drivers/scsi/qedf/qedf_io.c:1162:48: sparse: restricted __le16 degrades to integer
   drivers/scsi/qedf/qedf_io.c:1164:52: sparse: restricted __le16 degrades to integer
   drivers/scsi/qedf/qedf_io.c:1277:9: sparse: cast to restricted __le32
   drivers/scsi/qedf/qedf_io.c:1277:9: sparse: cast from restricted __le16
   drivers/scsi/qedf/qedf_io.c:1285:15: sparse: cast from restricted __le32
   drivers/scsi/qedf/qedf_io.c:1286:14: sparse: cast from restricted __le32
   drivers/scsi/qedf/qedf_io.c:1300:52: sparse: incorrect type in assignment (different base types) @@    expected unsigned int [unsigned] [usertype] rx_buf_off @@    got ed int [unsigned] [usertype] rx_buf_off @@
   drivers/scsi/qedf/qedf_io.c:1300:52:    expected unsigned int [unsigned] [usertype] rx_buf_off
   drivers/scsi/qedf/qedf_io.c:1300:52:    got restricted __le32 [usertype] rx_buf_off
   drivers/scsi/qedf/qedf_io.c:1302:52: sparse: incorrect type in assignment (different base types) @@    expected unsigned int [unsigned] [usertype] tx_buf_off @@    got ed int [unsigned] [usertype] tx_buf_off @@
   drivers/scsi/qedf/qedf_io.c:1302:52:    expected unsigned int [unsigned] [usertype] tx_buf_off
   drivers/scsi/qedf/qedf_io.c:1302:52:    got restricted __le32 [usertype] tx_buf_off
   drivers/scsi/qedf/qedf_io.c:1304:47: sparse: incorrect type in assignment (different base types) @@    expected unsigned int [unsigned] [usertype] rx_id @@    got ed int [unsigned] [usertype] rx_id @@
   drivers/scsi/qedf/qedf_io.c:1304:47:    expected unsigned int [unsigned] [usertype] rx_id
   drivers/scsi/qedf/qedf_io.c:1304:47:    got restricted __le16 [usertype] rx_id
   drivers/scsi/qedf/qedf_io.c:1340:9: sparse: cast to restricted __le32
   drivers/scsi/qedf/qedf_io.c:1340:9: sparse: cast from restricted __le16
   drivers/scsi/qedf/qedf_io.c:1699:32: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] lo @@    got unsignrestricted __le32 [usertype] lo @@
   drivers/scsi/qedf/qedf_io.c:1699:32:    expected restricted __le32 [usertype] lo
   drivers/scsi/qedf/qedf_io.c:1699:32:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:1700:32: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] hi @@    got unsignrestricted __le32 [usertype] hi @@
   drivers/scsi/qedf/qedf_io.c:1700:32:    expected restricted __le32 [usertype] hi
   drivers/scsi/qedf/qedf_io.c:1700:32:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:1701:28: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] sge_len @@    got e] sge_len @@
   drivers/scsi/qedf/qedf_io.c:1701:28:    expected restricted __le32 [usertype] sge_len
   drivers/scsi/qedf/qedf_io.c:1701:28:    got int
   drivers/scsi/qedf/qedf_io.c:1710:33: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] lo @@    got unsignrestricted __le32 [usertype] lo @@
   drivers/scsi/qedf/qedf_io.c:1710:33:    expected restricted __le32 [usertype] lo
   drivers/scsi/qedf/qedf_io.c:1710:33:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:1711:33: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] hi @@    got unsignrestricted __le32 [usertype] hi @@
   drivers/scsi/qedf/qedf_io.c:1711:33:    expected restricted __le32 [usertype] hi
   drivers/scsi/qedf/qedf_io.c:1711:33:    got unsigned int [unsigned] [usertype] <noident>
   drivers/scsi/qedf/qedf_io.c:1712:29: sparse: incorrect type in assignment (different base types) @@    expected restricted __le32 [usertype] sge_len @@    got e] sge_len @@
   drivers/scsi/qedf/qedf_io.c:1712:29:    expected restricted __le32 [usertype] sge_len
   drivers/scsi/qedf/qedf_io.c:1712:29:    got int
   drivers/scsi/qedf/qedf_io.c:2032:53: sparse: incorrect type in initializer (different base types) @@    expected unsigned short [unsigned] [usertype] pktlen @@    got  short [unsigned] [usertype] pktlen @@
   drivers/scsi/qedf/qedf_io.c:2032:53:    expected unsigned short [unsigned] [usertype] pktlen
   drivers/scsi/qedf/qedf_io.c:2032:53:    got restricted __le16 [usertype] pkt_len
   drivers/scsi/qedf/qedf_io.c:2089:20: sparse: incorrect type in assignment (different base types) @@    expected unsigned int [unsigned] [usertype] fr_crc @@    got ed int [unsigned] [usertype] fr_crc @@
   drivers/scsi/qedf/qedf_io.c:2089:20:    expected unsigned int [unsigned] [usertype] fr_crc
   drivers/scsi/qedf/qedf_io.c:2089:20:    got restricted __le32 [usertype] <noident>
   include/linux/slab.h:664:13: sparse: call with no type!

vim +471 drivers/scsi/qedf/qedf_io.c

   430	
   431	static int qedf_map_sg(struct qedf_ioreq *io_req)
   432	{
   433		struct scsi_cmnd *sc = io_req->sc_cmd;
   434		struct Scsi_Host *host = sc->device->host;
   435		struct fc_lport *lport = shost_priv(host);
   436		struct qedf_ctx *qedf = lport_priv(lport);
   437		struct scsi_sge *bd = io_req->bd_tbl->bd_tbl;
   438		struct scatterlist *sg;
   439		int byte_count = 0;
   440		int sg_count = 0;
   441		int bd_count = 0;
   442		u32 sg_len;
   443		u64 addr, end_addr;
   444		int i = 0;
   445	
   446		sg_count = dma_map_sg(&qedf->pdev->dev, scsi_sglist(sc),
   447		    scsi_sg_count(sc), sc->sc_data_direction);
   448		sg = scsi_sglist(sc);
   449	
   450		io_req->sge_type = QEDF_IOREQ_UNKNOWN_SGE;
   451	
   452		if (sg_count <= 8 || io_req->io_req_flags == QEDF_READ)
   453			io_req->sge_type = QEDF_IOREQ_FAST_SGE;
   454	
   455		scsi_for_each_sg(sc, sg, sg_count, i) {
   456			sg_len = (u32)sg_dma_len(sg);
   457			addr = (u64)sg_dma_address(sg);
   458			end_addr = (u64)(addr + sg_len);
   459	
   460			/*
   461			 * Intermediate s/g element so check if start and end address
   462			 * is page aligned.  Only required for writes and only if the
   463			 * number of scatter/gather elements is 8 or more.
   464			 */
   465			if (io_req->sge_type == QEDF_IOREQ_UNKNOWN_SGE && (i) &&
   466			    (i != (sg_count - 1)) && sg_len < QEDF_PAGE_SIZE)
   467				io_req->sge_type = QEDF_IOREQ_SLOW_SGE;
   468	
 > 469			bd[bd_count].sge_addr.lo = U64_LO(addr);
   470			bd[bd_count].sge_addr.hi  = U64_HI(addr);
 > 471			bd[bd_count].sge_len = sg_len;
   472	
   473			bd_count++;
   474			byte_count += sg_len;
   475		}
   476	
   477		/* To catch a case where FAST and SLOW nothing is set, set FAST */
   478		if (io_req->sge_type == QEDF_IOREQ_UNKNOWN_SGE)
   479			io_req->sge_type = QEDF_IOREQ_FAST_SGE;
   480	
   481		if (byte_count != scsi_bufflen(sc))
   482			QEDF_ERR(&(qedf->dbg_ctx), "byte_count = %d != "
   483				  "scsi_bufflen = %d, task_id = 0x%x.\n", byte_count,
   484				   scsi_bufflen(sc), io_req->xid);
   485	
   486		return bd_count;
   487	}
   488	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Martin K. Petersen March 19, 2019, 12:01 a.m. UTC | #2
Saurav/Chad: Please look into this. Thanks!

> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on mkp-scsi/for-next]
> [also build test WARNING on v5.0 next-20190306]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url:    https://github.com/0day-ci/linux/commits/Saurav-Kashyap/qedf-Misc-fixes-for-the-driver/20190305-205913
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
> reproduce:
>         # apt-get install sparse
>         make ARCH=x86_64 allmodconfig
>         make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
Saurav Kashyap March 22, 2019, 6:12 a.m. UTC | #3
Hi Martin,
I will provide an update patch list soon.

Thanks,
~Saurav

-----Original Message-----
From: "Martin K. Petersen" <martin.petersen@oracle.com>
Organization: Oracle Corporation
Date: Tuesday, 19 March 2019 at 5:32 AM
To: Saurav Kashyap <skashyap@marvell.com>, Chad Dupuis <cdupuis@marvell.com>
Cc: "kbuild-all@01.org" <kbuild-all@01.org>, "martin.petersen@oracle.com" <martin.petersen@oracle.com>, "QLogic-Storage-Upstream@cavium.com" <QLogic-Storage-Upstream@cavium.com>, "linux-scsi@vger.kernel.org" <linux-scsi@vger.kernel.org>, kbuild test robot <lkp@intel.com>
Subject: Re: [PATCH 04/26] qedf: Simplify s/g list mapping.

    
    Saurav/Chad: Please look into this. Thanks!
    
    > Thank you for the patch! Perhaps something to improve:
    >
    > [auto build test WARNING on mkp-scsi/for-next]
    > [also build test WARNING on v5.0 next-20190306]
    > [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
    >
    > url:    https://github.com/0day-ci/linux/commits/Saurav-Kashyap/qedf-Misc-fixes-for-the-driver/20190305-205913
    > base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
    > reproduce:
    >         # apt-get install sparse
    >         make ARCH=x86_64 allmodconfig
    >         make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
    
    -- 
    Martin K. Petersen	Oracle Linux Engineering
diff mbox series

Patch

diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h
index 8e75c21..4080af8 100644
--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -102,7 +102,6 @@  struct qedf_ioreq {
 	struct list_head link;
 	uint16_t xid;
 	struct scsi_cmnd *sc_cmd;
-	bool use_slowpath; /* Use slow SGL for this I/O */
 #define QEDF_SCSI_CMD		1
 #define QEDF_TASK_MGMT_CMD	2
 #define QEDF_ABTS		3
@@ -152,9 +151,9 @@  struct qedf_ioreq {
 	int fp_idx;
 	unsigned int cpu;
 	unsigned int int_cpu;
-#define QEDF_IOREQ_SLOW_SGE		0
-#define QEDF_IOREQ_SINGLE_SGE		1
-#define QEDF_IOREQ_FAST_SGE		2
+#define QEDF_IOREQ_UNKNOWN_SGE		1
+#define QEDF_IOREQ_SLOW_SGE		2
+#define QEDF_IOREQ_FAST_SGE		3
 	u8 sge_type;
 	struct delayed_work rrq_work;
 
@@ -366,7 +365,6 @@  struct qedf_ctx {
 
 	u32 slow_sge_ios;
 	u32 fast_sge_ios;
-	u32 single_sge_ios;
 
 	uint8_t	*grcdump;
 	uint32_t grcdump_size;
diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c
index a32d8ee..6ae78dd 100644
--- a/drivers/scsi/qedf/qedf_debugfs.c
+++ b/drivers/scsi/qedf/qedf_debugfs.c
@@ -303,7 +303,6 @@ 
 	seq_printf(s, "cmg_mgr free io_reqs: %d\n",
 	    atomic_read(&qedf->cmd_mgr->free_list_cnt));
 	seq_printf(s, "slow SGEs: %d\n", qedf->slow_sge_ios);
-	seq_printf(s, "single SGEs: %d\n", qedf->single_sge_ios);
 	seq_printf(s, "fast SGEs: %d\n\n", qedf->fast_sge_ios);
 
 	seq_puts(s, "Offloaded ports:\n\n");
@@ -361,7 +360,6 @@ 
 
 	/* Clear stat counters exposed by 'stats' node */
 	qedf->slow_sge_ios = 0;
-	qedf->single_sge_ios = 0;
 	qedf->fast_sge_ios = 0;
 
 	return count;
diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index da728d2..d7480f1 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -428,29 +428,6 @@  void qedf_release_cmd(struct kref *ref)
 	clear_bit(QEDF_CMD_OUTSTANDING, &io_req->flags);
 }
 
-static int qedf_split_bd(struct qedf_ioreq *io_req, u64 addr, int sg_len,
-	int bd_index)
-{
-	struct scsi_sge *bd = io_req->bd_tbl->bd_tbl;
-	int frag_size, sg_frags;
-
-	sg_frags = 0;
-	while (sg_len) {
-		if (sg_len > QEDF_BD_SPLIT_SZ)
-			frag_size = QEDF_BD_SPLIT_SZ;
-		else
-			frag_size = sg_len;
-		bd[bd_index + sg_frags].sge_addr.lo = U64_LO(addr);
-		bd[bd_index + sg_frags].sge_addr.hi = U64_HI(addr);
-		bd[bd_index + sg_frags].sge_len = (uint16_t)frag_size;
-
-		addr += (u64)frag_size;
-		sg_frags++;
-		sg_len -= frag_size;
-	}
-	return sg_frags;
-}
-
 static int qedf_map_sg(struct qedf_ioreq *io_req)
 {
 	struct scsi_cmnd *sc = io_req->sc_cmd;
@@ -462,75 +439,45 @@  static int qedf_map_sg(struct qedf_ioreq *io_req)
 	int byte_count = 0;
 	int sg_count = 0;
 	int bd_count = 0;
-	int sg_frags;
-	unsigned int sg_len;
+	u32 sg_len;
 	u64 addr, end_addr;
-	int i;
+	int i = 0;
 
 	sg_count = dma_map_sg(&qedf->pdev->dev, scsi_sglist(sc),
 	    scsi_sg_count(sc), sc->sc_data_direction);
-
 	sg = scsi_sglist(sc);
 
-	/*
-	 * New condition to send single SGE as cached-SGL with length less
-	 * than 64k.
-	 */
-	if ((sg_count == 1) && (sg_dma_len(sg) <=
-	    QEDF_MAX_SGLEN_FOR_CACHESGL)) {
-		sg_len = sg_dma_len(sg);
-		addr = (u64)sg_dma_address(sg);
-
-		bd[bd_count].sge_addr.lo = (addr & 0xffffffff);
-		bd[bd_count].sge_addr.hi = (addr >> 32);
-		bd[bd_count].sge_len = (u16)sg_len;
+	io_req->sge_type = QEDF_IOREQ_UNKNOWN_SGE;
 
-		return ++bd_count;
-	}
+	if (sg_count <= 8 || io_req->io_req_flags == QEDF_READ)
+		io_req->sge_type = QEDF_IOREQ_FAST_SGE;
 
 	scsi_for_each_sg(sc, sg, sg_count, i) {
-		sg_len = sg_dma_len(sg);
+		sg_len = (u32)sg_dma_len(sg);
 		addr = (u64)sg_dma_address(sg);
 		end_addr = (u64)(addr + sg_len);
 
 		/*
-		 * First s/g element in the list so check if the end_addr
-		 * is paged aligned. Also check to make sure the length is
-		 * at least page size.
-		 */
-		if ((i == 0) && (sg_count > 1) &&
-		    ((end_addr % QEDF_PAGE_SIZE) ||
-		    sg_len < QEDF_PAGE_SIZE))
-			io_req->use_slowpath = true;
-		/*
-		 * Last s/g element so check if the start address is paged
-		 * aligned.
-		 */
-		else if ((i == (sg_count - 1)) && (sg_count > 1) &&
-		    (addr % QEDF_PAGE_SIZE))
-			io_req->use_slowpath = true;
-		/*
 		 * Intermediate s/g element so check if start and end address
-		 * is page aligned.
+		 * is page aligned.  Only required for writes and only if the
+		 * number of scatter/gather elements is 8 or more.
 		 */
-		else if ((i != 0) && (i != (sg_count - 1)) &&
-		    ((addr % QEDF_PAGE_SIZE) || (end_addr % QEDF_PAGE_SIZE)))
-			io_req->use_slowpath = true;
+		if (io_req->sge_type == QEDF_IOREQ_UNKNOWN_SGE && (i) &&
+		    (i != (sg_count - 1)) && sg_len < QEDF_PAGE_SIZE)
+			io_req->sge_type = QEDF_IOREQ_SLOW_SGE;
 
-		if (sg_len > QEDF_MAX_BD_LEN) {
-			sg_frags = qedf_split_bd(io_req, addr, sg_len,
-			    bd_count);
-		} else {
-			sg_frags = 1;
-			bd[bd_count].sge_addr.lo = U64_LO(addr);
-			bd[bd_count].sge_addr.hi  = U64_HI(addr);
-			bd[bd_count].sge_len = (uint16_t)sg_len;
-		}
+		bd[bd_count].sge_addr.lo = U64_LO(addr);
+		bd[bd_count].sge_addr.hi  = U64_HI(addr);
+		bd[bd_count].sge_len = sg_len;
 
-		bd_count += sg_frags;
+		bd_count++;
 		byte_count += sg_len;
 	}
 
+	/* To catch a case where FAST and SLOW nothing is set, set FAST */
+	if (io_req->sge_type == QEDF_IOREQ_UNKNOWN_SGE)
+		io_req->sge_type = QEDF_IOREQ_FAST_SGE;
+
 	if (byte_count != scsi_bufflen(sc))
 		QEDF_ERR(&(qedf->dbg_ctx), "byte_count = %d != "
 			  "scsi_bufflen = %d, task_id = 0x%x.\n", byte_count,
@@ -655,8 +602,10 @@  static void  qedf_init_task(struct qedf_rport *fcport, struct fc_lport *lport,
 		io_req->sgl_task_params->num_sges = bd_count;
 		io_req->sgl_task_params->total_buffer_size =
 		    scsi_bufflen(io_req->sc_cmd);
-		io_req->sgl_task_params->small_mid_sge =
-			io_req->use_slowpath;
+		if (io_req->sge_type == QEDF_IOREQ_SLOW_SGE)
+			io_req->sgl_task_params->small_mid_sge = 1;
+		else
+			io_req->sgl_task_params->small_mid_sge = 0;
 	}
 
 	/* Fill in physical address of sense buffer */
@@ -679,16 +628,10 @@  static void  qedf_init_task(struct qedf_rport *fcport, struct fc_lport *lport,
 				    io_req->task_retry_identifier, fcp_cmnd);
 
 	/* Increment SGL type counters */
-	if (bd_count == 1) {
-		qedf->single_sge_ios++;
-		io_req->sge_type = QEDF_IOREQ_SINGLE_SGE;
-	} else if (io_req->use_slowpath) {
+	if (io_req->sge_type == QEDF_IOREQ_SLOW_SGE)
 		qedf->slow_sge_ios++;
-		io_req->sge_type = QEDF_IOREQ_SLOW_SGE;
-	} else {
+	else
 		qedf->fast_sge_ios++;
-		io_req->sge_type = QEDF_IOREQ_FAST_SGE;
-	}
 }
 
 void qedf_init_mp_task(struct qedf_ioreq *io_req,
@@ -770,9 +713,6 @@  void qedf_init_mp_task(struct qedf_ioreq *io_req,
 						     &task_fc_hdr,
 						     &tx_sgl_task_params,
 						     &rx_sgl_task_params, 0);
-
-	/* Midpath requests always consume 1 SGE */
-	qedf->single_sge_ios++;
 }
 
 /* Presumed that fcport->rport_lock is held */
@@ -872,7 +812,7 @@  int qedf_post_io_req(struct qedf_rport *fcport, struct qedf_ioreq *io_req)
 	/* Initialize rest of io_req fileds */
 	io_req->data_xfer_len = scsi_bufflen(sc_cmd);
 	sc_cmd->SCp.ptr = (char *)io_req;
-	io_req->use_slowpath = false; /* Assume fast SGL by default */
+	io_req->sge_type = QEDF_IOREQ_FAST_SGE; /* Assume fast SGL by default */
 
 	/* Record which cpu this request is associated with */
 	io_req->cpu = smp_processor_id();
@@ -942,7 +882,17 @@  int qedf_post_io_req(struct qedf_rport *fcport, struct qedf_ioreq *io_req)
 	int rc = 0;
 	int rval;
 	unsigned long flags = 0;
-
+	int num_sgs = 0;
+
+	num_sgs = scsi_sg_count(sc_cmd);
+	if (scsi_sg_count(sc_cmd) > QEDF_MAX_BDS_PER_CMD) {
+		QEDF_ERR(&qedf->dbg_ctx,
+			 "Number of SG elements %d exceeds what hardware limitation of %d.\n",
+			 num_sgs, QEDF_MAX_BDS_PER_CMD);
+		sc_cmd->result = DID_ERROR;
+		sc_cmd->scsi_done(sc_cmd);
+		return 0;
+	}
 
 	if (test_bit(QEDF_UNLOADING, &qedf->flags) ||
 	    test_bit(QEDF_DBG_STOP_IO, &qedf->flags)) {