18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2016 Chelsio Communications, Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "cxgbit.h"
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_cistatic void
98c2ecf20Sopenharmony_cicxgbit_set_one_ppod(struct cxgbi_pagepod *ppod,
108c2ecf20Sopenharmony_ci		    struct cxgbi_task_tag_info *ttinfo,
118c2ecf20Sopenharmony_ci		    struct scatterlist **sg_pp, unsigned int *sg_off)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	struct scatterlist *sg = sg_pp ? *sg_pp : NULL;
148c2ecf20Sopenharmony_ci	unsigned int offset = sg_off ? *sg_off : 0;
158c2ecf20Sopenharmony_ci	dma_addr_t addr = 0UL;
168c2ecf20Sopenharmony_ci	unsigned int len = 0;
178c2ecf20Sopenharmony_ci	int i;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	memcpy(ppod, &ttinfo->hdr, sizeof(struct cxgbi_pagepod_hdr));
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	if (sg) {
228c2ecf20Sopenharmony_ci		addr = sg_dma_address(sg);
238c2ecf20Sopenharmony_ci		len = sg_dma_len(sg);
248c2ecf20Sopenharmony_ci	}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	for (i = 0; i < PPOD_PAGES_MAX; i++) {
278c2ecf20Sopenharmony_ci		if (sg) {
288c2ecf20Sopenharmony_ci			ppod->addr[i] = cpu_to_be64(addr + offset);
298c2ecf20Sopenharmony_ci			offset += PAGE_SIZE;
308c2ecf20Sopenharmony_ci			if (offset == (len + sg->offset)) {
318c2ecf20Sopenharmony_ci				offset = 0;
328c2ecf20Sopenharmony_ci				sg = sg_next(sg);
338c2ecf20Sopenharmony_ci				if (sg) {
348c2ecf20Sopenharmony_ci					addr = sg_dma_address(sg);
358c2ecf20Sopenharmony_ci					len = sg_dma_len(sg);
368c2ecf20Sopenharmony_ci				}
378c2ecf20Sopenharmony_ci			}
388c2ecf20Sopenharmony_ci		} else {
398c2ecf20Sopenharmony_ci			ppod->addr[i] = 0ULL;
408c2ecf20Sopenharmony_ci		}
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	/*
448c2ecf20Sopenharmony_ci	 * the fifth address needs to be repeated in the next ppod, so do
458c2ecf20Sopenharmony_ci	 * not move sg
468c2ecf20Sopenharmony_ci	 */
478c2ecf20Sopenharmony_ci	if (sg_pp) {
488c2ecf20Sopenharmony_ci		*sg_pp = sg;
498c2ecf20Sopenharmony_ci		*sg_off = offset;
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	if (offset == len) {
538c2ecf20Sopenharmony_ci		offset = 0;
548c2ecf20Sopenharmony_ci		if (sg) {
558c2ecf20Sopenharmony_ci			sg = sg_next(sg);
568c2ecf20Sopenharmony_ci			if (sg)
578c2ecf20Sopenharmony_ci				addr = sg_dma_address(sg);
588c2ecf20Sopenharmony_ci		}
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci	ppod->addr[i] = sg ? cpu_to_be64(addr + offset) : 0ULL;
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic struct sk_buff *
648c2ecf20Sopenharmony_cicxgbit_ppod_init_idata(struct cxgbit_device *cdev, struct cxgbi_ppm *ppm,
658c2ecf20Sopenharmony_ci		       unsigned int idx, unsigned int npods, unsigned int tid)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	struct ulp_mem_io *req;
688c2ecf20Sopenharmony_ci	struct ulptx_idata *idata;
698c2ecf20Sopenharmony_ci	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ppm->llimit;
708c2ecf20Sopenharmony_ci	unsigned int dlen = npods << PPOD_SIZE_SHIFT;
718c2ecf20Sopenharmony_ci	unsigned int wr_len = roundup(sizeof(struct ulp_mem_io) +
728c2ecf20Sopenharmony_ci				sizeof(struct ulptx_idata) + dlen, 16);
738c2ecf20Sopenharmony_ci	struct sk_buff *skb;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	skb  = alloc_skb(wr_len, GFP_KERNEL);
768c2ecf20Sopenharmony_ci	if (!skb)
778c2ecf20Sopenharmony_ci		return NULL;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	req = __skb_put(skb, wr_len);
808c2ecf20Sopenharmony_ci	INIT_ULPTX_WR(req, wr_len, 0, tid);
818c2ecf20Sopenharmony_ci	req->wr.wr_hi = htonl(FW_WR_OP_V(FW_ULPTX_WR) |
828c2ecf20Sopenharmony_ci		FW_WR_ATOMIC_V(0));
838c2ecf20Sopenharmony_ci	req->cmd = htonl(ULPTX_CMD_V(ULP_TX_MEM_WRITE) |
848c2ecf20Sopenharmony_ci		ULP_MEMIO_ORDER_V(0) |
858c2ecf20Sopenharmony_ci		T5_ULP_MEMIO_IMM_V(1));
868c2ecf20Sopenharmony_ci	req->dlen = htonl(ULP_MEMIO_DATA_LEN_V(dlen >> 5));
878c2ecf20Sopenharmony_ci	req->lock_addr = htonl(ULP_MEMIO_ADDR_V(pm_addr >> 5));
888c2ecf20Sopenharmony_ci	req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16));
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	idata = (struct ulptx_idata *)(req + 1);
918c2ecf20Sopenharmony_ci	idata->cmd_more = htonl(ULPTX_CMD_V(ULP_TX_SC_IMM));
928c2ecf20Sopenharmony_ci	idata->len = htonl(dlen);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return skb;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic int
988c2ecf20Sopenharmony_cicxgbit_ppod_write_idata(struct cxgbi_ppm *ppm, struct cxgbit_sock *csk,
998c2ecf20Sopenharmony_ci			struct cxgbi_task_tag_info *ttinfo, unsigned int idx,
1008c2ecf20Sopenharmony_ci			unsigned int npods, struct scatterlist **sg_pp,
1018c2ecf20Sopenharmony_ci			unsigned int *sg_off)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	struct cxgbit_device *cdev = csk->com.cdev;
1048c2ecf20Sopenharmony_ci	struct sk_buff *skb;
1058c2ecf20Sopenharmony_ci	struct ulp_mem_io *req;
1068c2ecf20Sopenharmony_ci	struct ulptx_idata *idata;
1078c2ecf20Sopenharmony_ci	struct cxgbi_pagepod *ppod;
1088c2ecf20Sopenharmony_ci	unsigned int i;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	skb = cxgbit_ppod_init_idata(cdev, ppm, idx, npods, csk->tid);
1118c2ecf20Sopenharmony_ci	if (!skb)
1128c2ecf20Sopenharmony_ci		return -ENOMEM;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	req = (struct ulp_mem_io *)skb->data;
1158c2ecf20Sopenharmony_ci	idata = (struct ulptx_idata *)(req + 1);
1168c2ecf20Sopenharmony_ci	ppod = (struct cxgbi_pagepod *)(idata + 1);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	for (i = 0; i < npods; i++, ppod++)
1198c2ecf20Sopenharmony_ci		cxgbit_set_one_ppod(ppod, ttinfo, sg_pp, sg_off);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	__skb_queue_tail(&csk->ppodq, skb);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	return 0;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic int
1278c2ecf20Sopenharmony_cicxgbit_ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbit_sock *csk,
1288c2ecf20Sopenharmony_ci		   struct cxgbi_task_tag_info *ttinfo)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	unsigned int pidx = ttinfo->idx;
1318c2ecf20Sopenharmony_ci	unsigned int npods = ttinfo->npods;
1328c2ecf20Sopenharmony_ci	unsigned int i, cnt;
1338c2ecf20Sopenharmony_ci	struct scatterlist *sg = ttinfo->sgl;
1348c2ecf20Sopenharmony_ci	unsigned int offset = 0;
1358c2ecf20Sopenharmony_ci	int ret = 0;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	for (i = 0; i < npods; i += cnt, pidx += cnt) {
1388c2ecf20Sopenharmony_ci		cnt = npods - i;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci		if (cnt > ULPMEM_IDATA_MAX_NPPODS)
1418c2ecf20Sopenharmony_ci			cnt = ULPMEM_IDATA_MAX_NPPODS;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci		ret = cxgbit_ppod_write_idata(ppm, csk, ttinfo, pidx, cnt,
1448c2ecf20Sopenharmony_ci					      &sg, &offset);
1458c2ecf20Sopenharmony_ci		if (ret < 0)
1468c2ecf20Sopenharmony_ci			break;
1478c2ecf20Sopenharmony_ci	}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	return ret;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic int cxgbit_ddp_sgl_check(struct scatterlist *sg,
1538c2ecf20Sopenharmony_ci				unsigned int nents)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	unsigned int last_sgidx = nents - 1;
1568c2ecf20Sopenharmony_ci	unsigned int i;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	for (i = 0; i < nents; i++, sg = sg_next(sg)) {
1598c2ecf20Sopenharmony_ci		unsigned int len = sg->length + sg->offset;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci		if ((sg->offset & 0x3) || (i && sg->offset) ||
1628c2ecf20Sopenharmony_ci		    ((i != last_sgidx) && (len != PAGE_SIZE))) {
1638c2ecf20Sopenharmony_ci			return -EINVAL;
1648c2ecf20Sopenharmony_ci		}
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	return 0;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic int
1718c2ecf20Sopenharmony_cicxgbit_ddp_reserve(struct cxgbit_sock *csk, struct cxgbi_task_tag_info *ttinfo,
1728c2ecf20Sopenharmony_ci		   unsigned int xferlen)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	struct cxgbit_device *cdev = csk->com.cdev;
1758c2ecf20Sopenharmony_ci	struct cxgbi_ppm *ppm = cdev2ppm(cdev);
1768c2ecf20Sopenharmony_ci	struct scatterlist *sgl = ttinfo->sgl;
1778c2ecf20Sopenharmony_ci	unsigned int sgcnt = ttinfo->nents;
1788c2ecf20Sopenharmony_ci	unsigned int sg_offset = sgl->offset;
1798c2ecf20Sopenharmony_ci	int ret;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	if ((xferlen < DDP_THRESHOLD) || (!sgcnt)) {
1828c2ecf20Sopenharmony_ci		pr_debug("ppm 0x%p, pgidx %u, xfer %u, sgcnt %u, NO ddp.\n",
1838c2ecf20Sopenharmony_ci			 ppm, ppm->tformat.pgsz_idx_dflt,
1848c2ecf20Sopenharmony_ci			 xferlen, ttinfo->nents);
1858c2ecf20Sopenharmony_ci		return -EINVAL;
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	if (cxgbit_ddp_sgl_check(sgl, sgcnt) < 0)
1898c2ecf20Sopenharmony_ci		return -EINVAL;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	ttinfo->nr_pages = (xferlen + sgl->offset +
1928c2ecf20Sopenharmony_ci			    (1 << PAGE_SHIFT) - 1) >> PAGE_SHIFT;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	/*
1958c2ecf20Sopenharmony_ci	 * the ddp tag will be used for the ttt in the outgoing r2t pdu
1968c2ecf20Sopenharmony_ci	 */
1978c2ecf20Sopenharmony_ci	ret = cxgbi_ppm_ppods_reserve(ppm, ttinfo->nr_pages, 0, &ttinfo->idx,
1988c2ecf20Sopenharmony_ci				      &ttinfo->tag, 0);
1998c2ecf20Sopenharmony_ci	if (ret < 0)
2008c2ecf20Sopenharmony_ci		return ret;
2018c2ecf20Sopenharmony_ci	ttinfo->npods = ret;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	sgl->offset = 0;
2048c2ecf20Sopenharmony_ci	ret = dma_map_sg(&ppm->pdev->dev, sgl, sgcnt, DMA_FROM_DEVICE);
2058c2ecf20Sopenharmony_ci	sgl->offset = sg_offset;
2068c2ecf20Sopenharmony_ci	if (!ret) {
2078c2ecf20Sopenharmony_ci		pr_debug("%s: 0x%x, xfer %u, sgl %u dma mapping err.\n",
2088c2ecf20Sopenharmony_ci			 __func__, 0, xferlen, sgcnt);
2098c2ecf20Sopenharmony_ci		goto rel_ppods;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	cxgbi_ppm_make_ppod_hdr(ppm, ttinfo->tag, csk->tid, sgl->offset,
2138c2ecf20Sopenharmony_ci				xferlen, &ttinfo->hdr);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	ret = cxgbit_ddp_set_map(ppm, csk, ttinfo);
2168c2ecf20Sopenharmony_ci	if (ret < 0) {
2178c2ecf20Sopenharmony_ci		__skb_queue_purge(&csk->ppodq);
2188c2ecf20Sopenharmony_ci		dma_unmap_sg(&ppm->pdev->dev, sgl, sgcnt, DMA_FROM_DEVICE);
2198c2ecf20Sopenharmony_ci		goto rel_ppods;
2208c2ecf20Sopenharmony_ci	}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	return 0;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cirel_ppods:
2258c2ecf20Sopenharmony_ci	cxgbi_ppm_ppod_release(ppm, ttinfo->idx);
2268c2ecf20Sopenharmony_ci	return -EINVAL;
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_civoid
2308c2ecf20Sopenharmony_cicxgbit_get_r2t_ttt(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2318c2ecf20Sopenharmony_ci		   struct iscsi_r2t *r2t)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	struct cxgbit_sock *csk = conn->context;
2348c2ecf20Sopenharmony_ci	struct cxgbit_device *cdev = csk->com.cdev;
2358c2ecf20Sopenharmony_ci	struct cxgbit_cmd *ccmd = iscsit_priv_cmd(cmd);
2368c2ecf20Sopenharmony_ci	struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo;
2378c2ecf20Sopenharmony_ci	int ret = -EINVAL;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	if ((!ccmd->setup_ddp) ||
2408c2ecf20Sopenharmony_ci	    (!test_bit(CSK_DDP_ENABLE, &csk->com.flags)))
2418c2ecf20Sopenharmony_ci		goto out;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	ccmd->setup_ddp = false;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	ttinfo->sgl = cmd->se_cmd.t_data_sg;
2468c2ecf20Sopenharmony_ci	ttinfo->nents = cmd->se_cmd.t_data_nents;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	ret = cxgbit_ddp_reserve(csk, ttinfo, cmd->se_cmd.data_length);
2498c2ecf20Sopenharmony_ci	if (ret < 0) {
2508c2ecf20Sopenharmony_ci		pr_debug("csk 0x%p, cmd 0x%p, xfer len %u, sgcnt %u no ddp.\n",
2518c2ecf20Sopenharmony_ci			 csk, cmd, cmd->se_cmd.data_length, ttinfo->nents);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci		ttinfo->sgl = NULL;
2548c2ecf20Sopenharmony_ci		ttinfo->nents = 0;
2558c2ecf20Sopenharmony_ci	} else {
2568c2ecf20Sopenharmony_ci		ccmd->release = true;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ciout:
2598c2ecf20Sopenharmony_ci	pr_debug("cdev 0x%p, cmd 0x%p, tag 0x%x\n", cdev, cmd, ttinfo->tag);
2608c2ecf20Sopenharmony_ci	r2t->targ_xfer_tag = ttinfo->tag;
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_civoid cxgbit_unmap_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	struct cxgbit_cmd *ccmd = iscsit_priv_cmd(cmd);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	if (ccmd->release) {
2688c2ecf20Sopenharmony_ci		if (cmd->se_cmd.se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
2698c2ecf20Sopenharmony_ci			put_page(sg_page(&ccmd->sg));
2708c2ecf20Sopenharmony_ci		} else {
2718c2ecf20Sopenharmony_ci			struct cxgbit_sock *csk = conn->context;
2728c2ecf20Sopenharmony_ci			struct cxgbit_device *cdev = csk->com.cdev;
2738c2ecf20Sopenharmony_ci			struct cxgbi_ppm *ppm = cdev2ppm(cdev);
2748c2ecf20Sopenharmony_ci			struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci			/* Abort the TCP conn if DDP is not complete to
2778c2ecf20Sopenharmony_ci			 * avoid any possibility of DDP after freeing
2788c2ecf20Sopenharmony_ci			 * the cmd.
2798c2ecf20Sopenharmony_ci			 */
2808c2ecf20Sopenharmony_ci			if (unlikely(cmd->write_data_done !=
2818c2ecf20Sopenharmony_ci				     cmd->se_cmd.data_length))
2828c2ecf20Sopenharmony_ci				cxgbit_abort_conn(csk);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci			if (unlikely(ttinfo->sgl)) {
2858c2ecf20Sopenharmony_ci				dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl,
2868c2ecf20Sopenharmony_ci					     ttinfo->nents, DMA_FROM_DEVICE);
2878c2ecf20Sopenharmony_ci				ttinfo->nents = 0;
2888c2ecf20Sopenharmony_ci				ttinfo->sgl = NULL;
2898c2ecf20Sopenharmony_ci			}
2908c2ecf20Sopenharmony_ci			cxgbi_ppm_ppod_release(ppm, ttinfo->idx);
2918c2ecf20Sopenharmony_ci		}
2928c2ecf20Sopenharmony_ci		ccmd->release = false;
2938c2ecf20Sopenharmony_ci	}
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ciint cxgbit_ddp_init(struct cxgbit_device *cdev)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	struct cxgb4_lld_info *lldi = &cdev->lldi;
2998c2ecf20Sopenharmony_ci	struct net_device *ndev = cdev->lldi.ports[0];
3008c2ecf20Sopenharmony_ci	struct cxgbi_tag_format tformat;
3018c2ecf20Sopenharmony_ci	int ret, i;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	if (!lldi->vr->iscsi.size) {
3048c2ecf20Sopenharmony_ci		pr_warn("%s, iscsi NOT enabled, check config!\n", ndev->name);
3058c2ecf20Sopenharmony_ci		return -EACCES;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	memset(&tformat, 0, sizeof(struct cxgbi_tag_format));
3098c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++)
3108c2ecf20Sopenharmony_ci		tformat.pgsz_order[i] = (lldi->iscsi_pgsz_order >> (i << 3))
3118c2ecf20Sopenharmony_ci					 & 0xF;
3128c2ecf20Sopenharmony_ci	cxgbi_tagmask_check(lldi->iscsi_tagmask, &tformat);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	ret = cxgbi_ppm_init(lldi->iscsi_ppm, cdev->lldi.ports[0],
3158c2ecf20Sopenharmony_ci			     cdev->lldi.pdev, &cdev->lldi, &tformat,
3168c2ecf20Sopenharmony_ci			     lldi->vr->iscsi.size, lldi->iscsi_llimit,
3178c2ecf20Sopenharmony_ci			     lldi->vr->iscsi.start, 2,
3188c2ecf20Sopenharmony_ci			     lldi->vr->ppod_edram.start,
3198c2ecf20Sopenharmony_ci			     lldi->vr->ppod_edram.size);
3208c2ecf20Sopenharmony_ci	if (ret >= 0) {
3218c2ecf20Sopenharmony_ci		struct cxgbi_ppm *ppm = (struct cxgbi_ppm *)(*lldi->iscsi_ppm);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci		if ((ppm->tformat.pgsz_idx_dflt < DDP_PGIDX_MAX) &&
3248c2ecf20Sopenharmony_ci		    (ppm->ppmax >= 1024))
3258c2ecf20Sopenharmony_ci			set_bit(CDEV_DDP_ENABLE, &cdev->flags);
3268c2ecf20Sopenharmony_ci		ret = 0;
3278c2ecf20Sopenharmony_ci	}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	return ret;
3308c2ecf20Sopenharmony_ci}
331