scsi: target: cxgbit: Unmap DMA buffer before calling target_execute_cmd()
authorVarun Prakash <varun@chelsio.com>
Wed, 14 Apr 2021 12:39:09 +0000 (18:09 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sat, 15 May 2021 02:28:17 +0000 (22:28 -0400)
Instead of calling dma_unmap_sg() after completing WRITE I/O, call
dma_unmap_sg() before calling target_execute_cmd() to sync the DMA buffer.

Link: https://lore.kernel.org/r/1618403949-3443-1-git-send-email-varun@chelsio.com
Cc: <stable@vger.kernel.org> # 5.4+
Signed-off-by: Varun Prakash <varun@chelsio.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/target/iscsi/cxgbit/cxgbit_ddp.c
drivers/target/iscsi/cxgbit/cxgbit_target.c

index af35251232eb30f9546703328988fdcea06e16dd..b044999ad002bae82f88e55f22cd05ae70ef3adc 100644 (file)
@@ -265,12 +265,13 @@ void cxgbit_unmap_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
        struct cxgbit_cmd *ccmd = iscsit_priv_cmd(cmd);
 
        if (ccmd->release) {
-               struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo;
-
-               if (ttinfo->sgl) {
+               if (cmd->se_cmd.se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
+                       put_page(sg_page(&ccmd->sg));
+               } else {
                        struct cxgbit_sock *csk = conn->context;
                        struct cxgbit_device *cdev = csk->com.cdev;
                        struct cxgbi_ppm *ppm = cdev2ppm(cdev);
+                       struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo;
 
                        /* Abort the TCP conn if DDP is not complete to
                         * avoid any possibility of DDP after freeing
@@ -280,14 +281,14 @@ void cxgbit_unmap_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                                     cmd->se_cmd.data_length))
                                cxgbit_abort_conn(csk);
 
+                       if (unlikely(ttinfo->sgl)) {
+                               dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl,
+                                            ttinfo->nents, DMA_FROM_DEVICE);
+                               ttinfo->nents = 0;
+                               ttinfo->sgl = NULL;
+                       }
                        cxgbi_ppm_ppod_release(ppm, ttinfo->idx);
-
-                       dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl,
-                                    ttinfo->nents, DMA_FROM_DEVICE);
-               } else {
-                       put_page(sg_page(&ccmd->sg));
                }
-
                ccmd->release = false;
        }
 }
index b926e1d6c7b8e540f2078bc491cd7e0fc6bfe457..282297ffc4044b2ed489da59e785e1fe1cab80f5 100644 (file)
@@ -997,17 +997,18 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
        struct scatterlist *sg_start;
        struct iscsi_conn *conn = csk->conn;
        struct iscsi_cmd *cmd = NULL;
+       struct cxgbit_cmd *ccmd;
+       struct cxgbi_task_tag_info *ttinfo;
        struct cxgbit_lro_pdu_cb *pdu_cb = cxgbit_rx_pdu_cb(csk->skb);
        struct iscsi_data *hdr = (struct iscsi_data *)pdu_cb->hdr;
        u32 data_offset = be32_to_cpu(hdr->offset);
-       u32 data_len = pdu_cb->dlen;
+       u32 data_len = ntoh24(hdr->dlength);
        int rc, sg_nents, sg_off;
        bool dcrc_err = false;
 
        if (pdu_cb->flags & PDUCBF_RX_DDP_CMP) {
                u32 offset = be32_to_cpu(hdr->offset);
                u32 ddp_data_len;
-               u32 payload_length = ntoh24(hdr->dlength);
                bool success = false;
 
                cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, 0);
@@ -1022,7 +1023,7 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
                cmd->data_sn = be32_to_cpu(hdr->datasn);
 
                rc = __iscsit_check_dataout_hdr(conn, (unsigned char *)hdr,
-                                               cmd, payload_length, &success);
+                                               cmd, data_len, &success);
                if (rc < 0)
                        return rc;
                else if (!success)
@@ -1060,6 +1061,20 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
                cxgbit_skb_copy_to_sg(csk->skb, sg_start, sg_nents, skip);
        }
 
+       ccmd = iscsit_priv_cmd(cmd);
+       ttinfo = &ccmd->ttinfo;
+
+       if (ccmd->release && ttinfo->sgl &&
+           (cmd->se_cmd.data_length == (cmd->write_data_done + data_len))) {
+               struct cxgbit_device *cdev = csk->com.cdev;
+               struct cxgbi_ppm *ppm = cdev2ppm(cdev);
+
+               dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl, ttinfo->nents,
+                            DMA_FROM_DEVICE);
+               ttinfo->nents = 0;
+               ttinfo->sgl = NULL;
+       }
+
 check_payload:
 
        rc = iscsit_check_dataout_payload(cmd, hdr, dcrc_err);