Merge branch 'WIP.sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/kernel/linux-starfive.git] / drivers / target / iscsi / cxgbit / cxgbit_target.c
index 0c3e8fc..bdcc8b4 100644 (file)
@@ -164,12 +164,14 @@ cxgbit_tx_data_wr(struct cxgbit_sock *csk, struct sk_buff *skb, u32 dlen,
                  u32 len, u32 credits, u32 compl)
 {
        struct fw_ofld_tx_data_wr *req;
+       const struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
        u32 submode = cxgbit_skcb_submode(skb);
        u32 wr_ulp_mode = 0;
        u32 hdr_size = sizeof(*req);
        u32 opcode = FW_OFLD_TX_DATA_WR;
        u32 immlen = 0;
-       u32 force = TX_FORCE_V(!submode);
+       u32 force = is_t5(lldi->adapter_type) ? TX_FORCE_V(!submode) :
+                   T6_TX_FORCE_F;
 
        if (cxgbit_skcb_flags(skb) & SKCBF_TX_ISO) {
                opcode = FW_ISCSI_TX_DATA_WR;
@@ -245,7 +247,7 @@ void cxgbit_push_tx_frames(struct cxgbit_sock *csk)
                }
                __skb_unlink(skb, &csk->txq);
                set_wr_txq(skb, CPL_PRIORITY_DATA, csk->txq_idx);
-               skb->csum = credits_needed + flowclen16;
+               skb->csum = (__force __wsum)(credits_needed + flowclen16);
                csk->wr_cred -= credits_needed;
                csk->wr_una_cred += credits_needed;
 
@@ -653,26 +655,6 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
        u32 max_npdu, max_iso_npdu;
 
        if (conn->login->leading_connection) {
-               param = iscsi_find_param_from_key(DATASEQUENCEINORDER,
-                                                 conn->param_list);
-               if (!param) {
-                       pr_err("param not found key %s\n", DATASEQUENCEINORDER);
-                       return -1;
-               }
-
-               if (strcmp(param->value, YES))
-                       return 0;
-
-               param = iscsi_find_param_from_key(DATAPDUINORDER,
-                                                 conn->param_list);
-               if (!param) {
-                       pr_err("param not found key %s\n", DATAPDUINORDER);
-                       return -1;
-               }
-
-               if (strcmp(param->value, YES))
-                       return 0;
-
                param = iscsi_find_param_from_key(MAXBURSTLENGTH,
                                                  conn->param_list);
                if (!param) {
@@ -683,11 +665,6 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
                if (kstrtou32(param->value, 0, &mbl) < 0)
                        return -1;
        } else {
-               if (!conn->sess->sess_ops->DataSequenceInOrder)
-                       return 0;
-               if (!conn->sess->sess_ops->DataPDUInOrder)
-                       return 0;
-
                mbl = conn->sess->sess_ops->MaxBurstLength;
        }
 
@@ -706,6 +683,53 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
        return 0;
 }
 
+/*
+ * cxgbit_seq_pdu_inorder()
+ * @csk: pointer to cxgbit socket structure
+ *
+ * This function checks whether data sequence and data
+ * pdu are in order.
+ *
+ * Return: returns -1 on error, 0 if data sequence and
+ * data pdu are in order, 1 if data sequence or data pdu
+ * is not in order.
+ */
+static int cxgbit_seq_pdu_inorder(struct cxgbit_sock *csk)
+{
+       struct iscsi_conn *conn = csk->conn;
+       struct iscsi_param *param;
+
+       if (conn->login->leading_connection) {
+               param = iscsi_find_param_from_key(DATASEQUENCEINORDER,
+                                                 conn->param_list);
+               if (!param) {
+                       pr_err("param not found key %s\n", DATASEQUENCEINORDER);
+                       return -1;
+               }
+
+               if (strcmp(param->value, YES))
+                       return 1;
+
+               param = iscsi_find_param_from_key(DATAPDUINORDER,
+                                                 conn->param_list);
+               if (!param) {
+                       pr_err("param not found key %s\n", DATAPDUINORDER);
+                       return -1;
+               }
+
+               if (strcmp(param->value, YES))
+                       return 1;
+
+       } else {
+               if (!conn->sess->sess_ops->DataSequenceInOrder)
+                       return 1;
+               if (!conn->sess->sess_ops->DataPDUInOrder)
+                       return 1;
+       }
+
+       return 0;
+}
+
 static int cxgbit_set_params(struct iscsi_conn *conn)
 {
        struct cxgbit_sock *csk = conn->context;
@@ -732,11 +756,24 @@ static int cxgbit_set_params(struct iscsi_conn *conn)
        }
 
        if (!erl) {
+               int ret;
+
+               ret = cxgbit_seq_pdu_inorder(csk);
+               if (ret < 0) {
+                       return -1;
+               } else if (ret > 0) {
+                       if (is_t5(cdev->lldi.adapter_type))
+                               goto enable_ddp;
+                       else
+                               goto enable_digest;
+               }
+
                if (test_bit(CDEV_ISO_ENABLE, &cdev->flags)) {
                        if (cxgbit_set_iso_npdu(csk))
                                return -1;
                }
 
+enable_ddp:
                if (test_bit(CDEV_DDP_ENABLE, &cdev->flags)) {
                        if (cxgbit_setup_conn_pgidx(csk,
                                                    ppm->tformat.pgsz_idx_dflt))
@@ -745,6 +782,7 @@ static int cxgbit_set_params(struct iscsi_conn *conn)
                }
        }
 
+enable_digest:
        if (cxgbit_set_digest(csk))
                return -1;
 
@@ -985,11 +1023,36 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
        int rc, sg_nents, sg_off;
        bool dcrc_err = false;
 
-       rc = iscsit_check_dataout_hdr(conn, (unsigned char *)hdr, &cmd);
-       if (rc < 0)
-               return rc;
-       else if (!cmd)
-               return 0;
+       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);
+               if (!cmd)
+                       return 0;
+
+               ddp_data_len = offset - cmd->write_data_done;
+               atomic_long_add(ddp_data_len, &conn->sess->rx_data_octets);
+
+               cmd->write_data_done = offset;
+               cmd->next_burst_len = ddp_data_len;
+               cmd->data_sn = be32_to_cpu(hdr->datasn);
+
+               rc = __iscsit_check_dataout_hdr(conn, (unsigned char *)hdr,
+                                               cmd, payload_length, &success);
+               if (rc < 0)
+                       return rc;
+               else if (!success)
+                       return 0;
+       } else {
+               rc = iscsit_check_dataout_hdr(conn, (unsigned char *)hdr, &cmd);
+               if (rc < 0)
+                       return rc;
+               else if (!cmd)
+                       return 0;
+       }
 
        if (pdu_cb->flags & PDUCBF_RX_DCRC_ERR) {
                pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
@@ -1353,6 +1416,9 @@ static void cxgbit_lro_hskb_reset(struct cxgbit_sock *csk)
        for (i = 0; i < ssi->nr_frags; i++)
                put_page(skb_frag_page(&ssi->frags[i]));
        ssi->nr_frags = 0;
+       skb->data_len = 0;
+       skb->truesize -= skb->len;
+       skb->len = 0;
 }
 
 static void
@@ -1366,39 +1432,42 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx)
        unsigned int len = 0;
 
        if (pdu_cb->flags & PDUCBF_RX_HDR) {
-               hpdu_cb->flags = pdu_cb->flags;
+               u8 hfrag_idx = hssi->nr_frags;
+
+               hpdu_cb->flags |= pdu_cb->flags;
                hpdu_cb->seq = pdu_cb->seq;
                hpdu_cb->hdr = pdu_cb->hdr;
                hpdu_cb->hlen = pdu_cb->hlen;
 
-               memcpy(&hssi->frags[0], &ssi->frags[pdu_cb->hfrag_idx],
+               memcpy(&hssi->frags[hfrag_idx], &ssi->frags[pdu_cb->hfrag_idx],
                       sizeof(skb_frag_t));
 
-               get_page(skb_frag_page(&hssi->frags[0]));
-               hssi->nr_frags = 1;
-               hpdu_cb->frags = 1;
-               hpdu_cb->hfrag_idx = 0;
+               get_page(skb_frag_page(&hssi->frags[hfrag_idx]));
+               hssi->nr_frags++;
+               hpdu_cb->frags++;
+               hpdu_cb->hfrag_idx = hfrag_idx;
 
-               len = hssi->frags[0].size;
-               hskb->len = len;
-               hskb->data_len = len;
-               hskb->truesize = len;
+               len = hssi->frags[hfrag_idx].size;
+               hskb->len += len;
+               hskb->data_len += len;
+               hskb->truesize += len;
        }
 
        if (pdu_cb->flags & PDUCBF_RX_DATA) {
-               u8 hfrag_idx = 1, i;
+               u8 dfrag_idx = hssi->nr_frags, i;
 
                hpdu_cb->flags |= pdu_cb->flags;
+               hpdu_cb->dfrag_idx = dfrag_idx;
 
                len = 0;
-               for (i = 0; i < pdu_cb->nr_dfrags; hfrag_idx++, i++) {
-                       memcpy(&hssi->frags[hfrag_idx],
+               for (i = 0; i < pdu_cb->nr_dfrags; dfrag_idx++, i++) {
+                       memcpy(&hssi->frags[dfrag_idx],
                               &ssi->frags[pdu_cb->dfrag_idx + i],
                               sizeof(skb_frag_t));
 
-                       get_page(skb_frag_page(&hssi->frags[hfrag_idx]));
+                       get_page(skb_frag_page(&hssi->frags[dfrag_idx]));
 
-                       len += hssi->frags[hfrag_idx].size;
+                       len += hssi->frags[dfrag_idx].size;
 
                        hssi->nr_frags++;
                        hpdu_cb->frags++;
@@ -1407,7 +1476,6 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx)
                hpdu_cb->dlen = pdu_cb->dlen;
                hpdu_cb->doffset = hpdu_cb->hlen;
                hpdu_cb->nr_dfrags = pdu_cb->nr_dfrags;
-               hpdu_cb->dfrag_idx = 1;
                hskb->len += len;
                hskb->data_len += len;
                hskb->truesize += len;
@@ -1492,10 +1560,15 @@ static int cxgbit_rx_lro_skb(struct cxgbit_sock *csk, struct sk_buff *skb)
 
 static int cxgbit_rx_skb(struct cxgbit_sock *csk, struct sk_buff *skb)
 {
+       struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
        int ret = -1;
 
-       if (likely(cxgbit_skcb_flags(skb) & SKCBF_RX_LRO))
-               ret = cxgbit_rx_lro_skb(csk, skb);
+       if (likely(cxgbit_skcb_flags(skb) & SKCBF_RX_LRO)) {
+               if (is_t5(lldi->adapter_type))
+                       ret = cxgbit_rx_lro_skb(csk, skb);
+               else
+                       ret = cxgbit_process_lro_skb(csk, skb);
+       }
 
        __kfree_skb(skb);
        return ret;