* [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure
@ 2026-09-11 8:40 M Nikhil
0 siblings, 0 replies; 4+ messages in thread
From: M Nikhil @ 2026-09-11 8:40 UTC (permalink / raw)
To: linux-s390; +Cc: M Nikhil
The zfcp_fsf_ct_els data structure is updated to replace the sg_req and
sg_resp members, which are of type struct scatterlist, with request and
response sg_table instances.
These sg_table structure reference the corresponding scatterlists
(sg_req and sg_resp) maintained in struct zfcp_fc_req.
These changes allows to track the original and mapped scatterlist nents
once zfcp is converted to use DMA-API for mapping the sg lists.
Signed-off-by: M Nikhil <nikh1092@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Reference-ID: SAN2402
---
drivers/s390/scsi/zfcp_dbf.c | 16 ++++++++--------
drivers/s390/scsi/zfcp_fc.c | 36 ++++++++++++++++++++++++------------
drivers/s390/scsi/zfcp_fsf.c | 6 ++++--
drivers/s390/scsi/zfcp_fsf.h | 9 +++++----
4 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 4217b74baa38..4232b1474a2f 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -581,9 +581,9 @@ void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id)
if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL)))
return;
- length = (u16)zfcp_qdio_real_bytes(ct_els->req);
- zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ,
- length, fsf->req_id, d_id, length);
+ length = (u16)zfcp_qdio_real_bytes(ct_els->sgt_req.sgl);
+ zfcp_dbf_san(tag, dbf, "san_req", ct_els->sgt_req.sgl,
+ ZFCP_DBF_SAN_REQ, length, fsf->req_id, d_id, length);
}
static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
@@ -591,9 +591,9 @@ static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
u16 len)
{
struct zfcp_fsf_ct_els *ct_els = fsf->data;
- struct fc_ct_hdr *reqh = sg_virt(ct_els->req);
+ struct fc_ct_hdr *reqh = sg_virt(ct_els->sgt_req.sgl);
struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
- struct scatterlist *resp_entry = ct_els->resp;
+ struct scatterlist *resp_entry = ct_els->sgt_resp.sgl;
struct fc_ct_hdr *resph;
struct fc_gpn_ft_resp *acc;
int max_entries, x, last = 0;
@@ -662,9 +662,9 @@ void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf)
if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL)))
return;
- length = (u16)zfcp_qdio_real_bytes(ct_els->resp);
- zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES,
- length, fsf->req_id, ct_els->d_id,
+ length = (u16)zfcp_qdio_real_bytes(ct_els->sgt_resp.sgl);
+ zfcp_dbf_san(tag, dbf, "san_res", ct_els->sgt_resp.sgl,
+ ZFCP_DBF_SAN_RES, length, fsf->req_id, ct_els->d_id,
zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length));
}
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 05d081297879..1fb6f2c3b607 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -393,10 +393,12 @@ static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
fc_req->ct_els.port = port;
fc_req->ct_els.handler = zfcp_fc_complete;
fc_req->ct_els.handler_data = &completion;
- fc_req->ct_els.req = &fc_req->sg_req;
- fc_req->ct_els.resp = &fc_req->sg_rsp;
+ fc_req->ct_els.sgt_req.sgl = &fc_req->sg_req;
+ fc_req->ct_els.sgt_resp.sgl = &fc_req->sg_rsp;
sg_init_one(&fc_req->sg_req, gid_pn_req, sizeof(*gid_pn_req));
sg_init_one(&fc_req->sg_rsp, gid_pn_rsp, sizeof(*gid_pn_rsp));
+ fc_req->ct_els.sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ fc_req->ct_els.sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
zfcp_fc_ct_ns_init(&gid_pn_req->ct_hdr,
FC_NS_GID_PN, ZFCP_FC_CT_SIZE_PAGE);
@@ -558,12 +560,14 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
return -ENOMEM;
fc_req->ct_els.port = port;
- fc_req->ct_els.req = &fc_req->sg_req;
- fc_req->ct_els.resp = &fc_req->sg_rsp;
+ fc_req->ct_els.sgt_req.sgl = &fc_req->sg_req;
+ fc_req->ct_els.sgt_resp.sgl = &fc_req->sg_rsp;
sg_init_one(&fc_req->sg_req, &fc_req->u.adisc.req,
sizeof(struct fc_els_adisc));
sg_init_one(&fc_req->sg_rsp, &fc_req->u.adisc.rsp,
sizeof(struct fc_els_adisc));
+ fc_req->ct_els.sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ fc_req->ct_els.sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
fc_req->ct_els.handler = zfcp_fc_adisc_handler;
fc_req->ct_els.handler_data = fc_req;
@@ -706,8 +710,10 @@ static int zfcp_fc_send_gpn_ft(struct zfcp_fc_req *fc_req,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -865,8 +871,10 @@ static int zfcp_fc_gspn(struct zfcp_adapter *adapter,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -924,8 +932,10 @@ static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -1090,8 +1100,10 @@ int zfcp_fc_exec_bsg_job(struct bsg_job *job)
if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN))
return -EINVAL;
- ct_els->req = job->request_payload.sg_list;
- ct_els->resp = job->reply_payload.sg_list;
+ ct_els->sgt_req.sgl = job->request_payload.sg_list;
+ ct_els->sgt_resp.sgl = job->reply_payload.sg_list;
+ ct_els->sgt_req.orig_nents = sg_nents(ct_els->sgt_req.sgl);
+ ct_els->sgt_resp.orig_nents = sg_nents(ct_els->sgt_resp.sgl);
ct_els->handler_data = job;
switch (bsg_request->msgcode) {
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index d407f16e77ef..a3b99839da9e 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1242,7 +1242,8 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
}
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
- ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
+ ret = zfcp_fsf_setup_ct_els(req, ct->sgt_req.sgl, ct->sgt_resp.sgl,
+ timeout);
if (ret)
goto failed_send;
@@ -1342,7 +1343,8 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
if (!zfcp_adapter_multi_buffer_active(adapter))
zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
- ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
+ ret = zfcp_fsf_setup_ct_els(req, els->sgt_req.sgl, els->sgt_resp.sgl,
+ timeout);
if (ret)
goto failed_send;
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 4b92e85ec71d..22e7fd933a78 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -487,8 +487,9 @@ struct zfcp_blk_drv_data {
/**
* struct zfcp_fsf_ct_els - zfcp data for ct or els request
- * @req: scatter-gather list for request, points to &zfcp_fc_req.sg_req or BSG
- * @resp: scatter-gather list for response, points to &zfcp_fc_req.sg_rsp or BSG
+ * @sgt_req: sg_table for request, its sgl points to &zfcp_fc_req.sg_req or BSG
+ * @sgt_resp: sg_table for response, its sgl points to &zfcp_fc_req.sg_resp
+ * or BSG
* @handler: handler function (called for response to the request)
* @handler_data: data passed to handler function
* @port: Optional pointer to port for zfcp internal ELS (only test link ADISC)
@@ -496,8 +497,8 @@ struct zfcp_blk_drv_data {
* @d_id: Destination ID of either open WKA port for CT or of D_ID for ELS
*/
struct zfcp_fsf_ct_els {
- struct scatterlist *req;
- struct scatterlist *resp;
+ struct sg_table sgt_req;
+ struct sg_table sgt_resp;
void (*handler)(void *);
void *handler_data;
struct zfcp_port *port;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v12 0/2] zfcp: Use DMA streaming API to map I/O
@ 2026-09-21 14:30 M Nikhil
2026-09-21 14:30 ` [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure M Nikhil
0 siblings, 1 reply; 4+ messages in thread
From: M Nikhil @ 2026-09-21 14:30 UTC (permalink / raw)
To: linux-s390, sashiko-reviews; +Cc: M Nikhil
In the existing zFCP driver, virtual addresses are translated directly
into bus (physical addresses) for DMA operations on all I/O buffers
passing from zFCP driver to the device.
Need for using DMA-API in zFCP driver:
In a Secure Execution environment, the host must ensure that device DMA
accesses are restricted to non-guest-private, page-sized memory blocks.
This prevents I/O failures that can occur when a device attempts to
access guest-private memory. Therefore, guest memory pages must be
prepared by the hypervisor before they become accessible to an I/O
device.
To support this requirement, the host Linux kernel must be reliably
informed whenever a memory region becomes eligible for device DMA access
and when that access must be revoked. This information must be
maintained correctly at least at page size granularity. To satisfy these
requirements, all I/O buffers used by the zFCP driver should be mapped
through the DMA API.
DMA API Integration in zFCP:
The zFCP driver is updated to use the DMA streaming API's to map all the
I/O buffers which will be passed to the device.
All zFCP I/O buffers (QTCB, SRB, CT/ELS and SCSI I/O) are represented as
scatter-gather lists and mapped through DMA API using dma_map_sgtable().
Once the DMA transfer is complete, the corresponding mappings are
released using dma_unmap_sgtable().
By routing all device-visible memory through the DMA mapping layer, the
driver ensures that:
1. DMA access is properly authorized before use.
2. DMA is revoked after use.
3. Secure Execution memory restrictions are honored.
Changes on the github can be found at:
https://github.ibm.com/M-Nikhil/linux/commits/zfcp_dma_api_implementation_io_path_version12
M Nikhil (2):
zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure
zfcp: Use DMA streaming API to map I/O
drivers/s390/scsi/zfcp_aux.c | 16 +++
drivers/s390/scsi/zfcp_dbf.c | 16 +--
drivers/s390/scsi/zfcp_def.h | 4 +
drivers/s390/scsi/zfcp_ext.h | 10 +-
drivers/s390/scsi/zfcp_fc.c | 36 +++--
drivers/s390/scsi/zfcp_fsf.c | 260 ++++++++++++++++++++++++++++------
drivers/s390/scsi/zfcp_fsf.h | 9 +-
drivers/s390/scsi/zfcp_qdio.c | 37 +++--
drivers/s390/scsi/zfcp_qdio.h | 27 ++--
9 files changed, 321 insertions(+), 94 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure
2026-09-21 14:30 [PATCH v12 0/2] zfcp: Use DMA streaming API to map I/O M Nikhil
@ 2026-09-21 14:30 ` M Nikhil
0 siblings, 0 replies; 4+ messages in thread
From: M Nikhil @ 2026-09-21 14:30 UTC (permalink / raw)
To: linux-s390, sashiko-reviews; +Cc: M Nikhil
The zfcp_fsf_ct_els data structure is updated to replace the sg_req and
sg_resp members, which are of type struct scatterlist, with request and
response sg_table instances.
These sg_table structure reference the corresponding scatterlists
(sg_req and sg_resp) maintained in struct zfcp_fc_req.
These changes allows to track the original and mapped scatterlist nents
once zfcp is converted to use DMA-API for mapping the sg lists.
Signed-off-by: M Nikhil <nikh1092@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Reference-ID: SAN2402
---
drivers/s390/scsi/zfcp_dbf.c | 16 ++++++++--------
drivers/s390/scsi/zfcp_fc.c | 36 ++++++++++++++++++++++++------------
drivers/s390/scsi/zfcp_fsf.c | 6 ++++--
drivers/s390/scsi/zfcp_fsf.h | 9 +++++----
4 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 4217b74baa38..4232b1474a2f 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -581,9 +581,9 @@ void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id)
if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL)))
return;
- length = (u16)zfcp_qdio_real_bytes(ct_els->req);
- zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ,
- length, fsf->req_id, d_id, length);
+ length = (u16)zfcp_qdio_real_bytes(ct_els->sgt_req.sgl);
+ zfcp_dbf_san(tag, dbf, "san_req", ct_els->sgt_req.sgl,
+ ZFCP_DBF_SAN_REQ, length, fsf->req_id, d_id, length);
}
static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
@@ -591,9 +591,9 @@ static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
u16 len)
{
struct zfcp_fsf_ct_els *ct_els = fsf->data;
- struct fc_ct_hdr *reqh = sg_virt(ct_els->req);
+ struct fc_ct_hdr *reqh = sg_virt(ct_els->sgt_req.sgl);
struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
- struct scatterlist *resp_entry = ct_els->resp;
+ struct scatterlist *resp_entry = ct_els->sgt_resp.sgl;
struct fc_ct_hdr *resph;
struct fc_gpn_ft_resp *acc;
int max_entries, x, last = 0;
@@ -662,9 +662,9 @@ void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf)
if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL)))
return;
- length = (u16)zfcp_qdio_real_bytes(ct_els->resp);
- zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES,
- length, fsf->req_id, ct_els->d_id,
+ length = (u16)zfcp_qdio_real_bytes(ct_els->sgt_resp.sgl);
+ zfcp_dbf_san(tag, dbf, "san_res", ct_els->sgt_resp.sgl,
+ ZFCP_DBF_SAN_RES, length, fsf->req_id, ct_els->d_id,
zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length));
}
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 05d081297879..1fb6f2c3b607 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -393,10 +393,12 @@ static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
fc_req->ct_els.port = port;
fc_req->ct_els.handler = zfcp_fc_complete;
fc_req->ct_els.handler_data = &completion;
- fc_req->ct_els.req = &fc_req->sg_req;
- fc_req->ct_els.resp = &fc_req->sg_rsp;
+ fc_req->ct_els.sgt_req.sgl = &fc_req->sg_req;
+ fc_req->ct_els.sgt_resp.sgl = &fc_req->sg_rsp;
sg_init_one(&fc_req->sg_req, gid_pn_req, sizeof(*gid_pn_req));
sg_init_one(&fc_req->sg_rsp, gid_pn_rsp, sizeof(*gid_pn_rsp));
+ fc_req->ct_els.sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ fc_req->ct_els.sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
zfcp_fc_ct_ns_init(&gid_pn_req->ct_hdr,
FC_NS_GID_PN, ZFCP_FC_CT_SIZE_PAGE);
@@ -558,12 +560,14 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
return -ENOMEM;
fc_req->ct_els.port = port;
- fc_req->ct_els.req = &fc_req->sg_req;
- fc_req->ct_els.resp = &fc_req->sg_rsp;
+ fc_req->ct_els.sgt_req.sgl = &fc_req->sg_req;
+ fc_req->ct_els.sgt_resp.sgl = &fc_req->sg_rsp;
sg_init_one(&fc_req->sg_req, &fc_req->u.adisc.req,
sizeof(struct fc_els_adisc));
sg_init_one(&fc_req->sg_rsp, &fc_req->u.adisc.rsp,
sizeof(struct fc_els_adisc));
+ fc_req->ct_els.sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ fc_req->ct_els.sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
fc_req->ct_els.handler = zfcp_fc_adisc_handler;
fc_req->ct_els.handler_data = fc_req;
@@ -706,8 +710,10 @@ static int zfcp_fc_send_gpn_ft(struct zfcp_fc_req *fc_req,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -865,8 +871,10 @@ static int zfcp_fc_gspn(struct zfcp_adapter *adapter,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -924,8 +932,10 @@ static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -1090,8 +1100,10 @@ int zfcp_fc_exec_bsg_job(struct bsg_job *job)
if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN))
return -EINVAL;
- ct_els->req = job->request_payload.sg_list;
- ct_els->resp = job->reply_payload.sg_list;
+ ct_els->sgt_req.sgl = job->request_payload.sg_list;
+ ct_els->sgt_resp.sgl = job->reply_payload.sg_list;
+ ct_els->sgt_req.orig_nents = sg_nents(ct_els->sgt_req.sgl);
+ ct_els->sgt_resp.orig_nents = sg_nents(ct_els->sgt_resp.sgl);
ct_els->handler_data = job;
switch (bsg_request->msgcode) {
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index d407f16e77ef..a3b99839da9e 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1242,7 +1242,8 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
}
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
- ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
+ ret = zfcp_fsf_setup_ct_els(req, ct->sgt_req.sgl, ct->sgt_resp.sgl,
+ timeout);
if (ret)
goto failed_send;
@@ -1342,7 +1343,8 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
if (!zfcp_adapter_multi_buffer_active(adapter))
zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
- ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
+ ret = zfcp_fsf_setup_ct_els(req, els->sgt_req.sgl, els->sgt_resp.sgl,
+ timeout);
if (ret)
goto failed_send;
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 4b92e85ec71d..22e7fd933a78 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -487,8 +487,9 @@ struct zfcp_blk_drv_data {
/**
* struct zfcp_fsf_ct_els - zfcp data for ct or els request
- * @req: scatter-gather list for request, points to &zfcp_fc_req.sg_req or BSG
- * @resp: scatter-gather list for response, points to &zfcp_fc_req.sg_rsp or BSG
+ * @sgt_req: sg_table for request, its sgl points to &zfcp_fc_req.sg_req or BSG
+ * @sgt_resp: sg_table for response, its sgl points to &zfcp_fc_req.sg_resp
+ * or BSG
* @handler: handler function (called for response to the request)
* @handler_data: data passed to handler function
* @port: Optional pointer to port for zfcp internal ELS (only test link ADISC)
@@ -496,8 +497,8 @@ struct zfcp_blk_drv_data {
* @d_id: Destination ID of either open WKA port for CT or of D_ID for ELS
*/
struct zfcp_fsf_ct_els {
- struct scatterlist *req;
- struct scatterlist *resp;
+ struct sg_table sgt_req;
+ struct sg_table sgt_resp;
void (*handler)(void *);
void *handler_data;
struct zfcp_port *port;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v12 0/2] zfcp: Use DMA streaming API to map I/O
@ 2026-09-24 6:09 M Nikhil
2026-09-24 6:09 ` [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure M Nikhil
0 siblings, 1 reply; 4+ messages in thread
From: M Nikhil @ 2026-09-24 6:09 UTC (permalink / raw)
To: linux-s390, sashiko-reviews; +Cc: M Nikhil
In the existing zFCP driver, virtual addresses are translated directly
into bus (physical addresses) for DMA operations on all I/O buffers
passing from zFCP driver to the device.
Need for using DMA-API in zFCP driver:
In a Secure Execution environment, the host must ensure that device DMA
accesses are restricted to non-guest-private, page-sized memory blocks.
This prevents I/O failures that can occur when a device attempts to
access guest-private memory. Therefore, guest memory pages must be
prepared by the hypervisor before they become accessible to an I/O
device.
To support this requirement, the host Linux kernel must be reliably
informed whenever a memory region becomes eligible for device DMA access
and when that access must be revoked. This information must be
maintained correctly at least at page size granularity. To satisfy these
requirements, all I/O buffers used by the zFCP driver should be mapped
through the DMA API.
DMA API Integration in zFCP:
The zFCP driver is updated to use the DMA streaming API's to map all the
I/O buffers which will be passed to the device.
All zFCP I/O buffers (QTCB, SRB, CT/ELS and SCSI I/O) are represented as
scatter-gather lists and mapped through DMA API using dma_map_sgtable().
Once the DMA transfer is complete, the corresponding mappings are
released using dma_unmap_sgtable().
By routing all device-visible memory through the DMA mapping layer, the
driver ensures that:
1. DMA access is properly authorized before use.
2. DMA is revoked after use.
3. Secure Execution memory restrictions are honored.
M Nikhil (2):
zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure
zfcp: Use DMA streaming API to map I/O
drivers/s390/scsi/zfcp_aux.c | 16 +++
drivers/s390/scsi/zfcp_dbf.c | 16 +--
drivers/s390/scsi/zfcp_def.h | 4 +
drivers/s390/scsi/zfcp_ext.h | 10 +-
drivers/s390/scsi/zfcp_fc.c | 36 +++--
drivers/s390/scsi/zfcp_fsf.c | 260 ++++++++++++++++++++++++++++------
drivers/s390/scsi/zfcp_fsf.h | 9 +-
drivers/s390/scsi/zfcp_qdio.c | 37 +++--
drivers/s390/scsi/zfcp_qdio.h | 27 ++--
9 files changed, 321 insertions(+), 94 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure
2026-09-24 6:09 [PATCH v12 0/2] zfcp: Use DMA streaming API to map I/O M Nikhil
@ 2026-09-24 6:09 ` M Nikhil
2026-09-24 6:19 ` sashiko-bot
0 siblings, 1 reply; 4+ messages in thread
From: M Nikhil @ 2026-09-24 6:09 UTC (permalink / raw)
To: linux-s390, sashiko-reviews; +Cc: M Nikhil
The zfcp_fsf_ct_els data structure is updated to replace the sg_req and
sg_resp members, which are of type struct scatterlist, with request and
response sg_table instances.
These sg_table structure reference the corresponding scatterlists
(sg_req and sg_resp) maintained in struct zfcp_fc_req.
These changes allows to track the original and mapped scatterlist nents
once zfcp is converted to use DMA-API for mapping the sg lists.
Signed-off-by: M Nikhil <nikh1092@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
---
drivers/s390/scsi/zfcp_dbf.c | 16 ++++++++--------
drivers/s390/scsi/zfcp_fc.c | 36 ++++++++++++++++++++++++------------
drivers/s390/scsi/zfcp_fsf.c | 6 ++++--
drivers/s390/scsi/zfcp_fsf.h | 9 +++++----
4 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 81fb8af408e9..f7e737e076bf 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -617,9 +617,9 @@ void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id)
if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL)))
return;
- length = (u16)zfcp_qdio_real_bytes(ct_els->req);
- zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ,
- length, fsf->req_id, d_id, length);
+ length = (u16)zfcp_qdio_real_bytes(ct_els->sgt_req.sgl);
+ zfcp_dbf_san(tag, dbf, "san_req", ct_els->sgt_req.sgl,
+ ZFCP_DBF_SAN_REQ, length, fsf->req_id, d_id, length);
}
static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
@@ -627,9 +627,9 @@ static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
u16 len)
{
struct zfcp_fsf_ct_els *ct_els = fsf->data;
- struct fc_ct_hdr *reqh = sg_virt(ct_els->req);
+ struct fc_ct_hdr *reqh = sg_virt(ct_els->sgt_req.sgl);
struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
- struct scatterlist *resp_entry = ct_els->resp;
+ struct scatterlist *resp_entry = ct_els->sgt_resp.sgl;
struct fc_ct_hdr *resph;
struct fc_gpn_ft_resp *acc;
int max_entries, x, last = 0;
@@ -698,9 +698,9 @@ void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf)
if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL)))
return;
- length = (u16)zfcp_qdio_real_bytes(ct_els->resp);
- zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES,
- length, fsf->req_id, ct_els->d_id,
+ length = (u16)zfcp_qdio_real_bytes(ct_els->sgt_resp.sgl);
+ zfcp_dbf_san(tag, dbf, "san_res", ct_els->sgt_resp.sgl,
+ ZFCP_DBF_SAN_RES, length, fsf->req_id, ct_els->d_id,
zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length));
}
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 05d081297879..1fb6f2c3b607 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -393,10 +393,12 @@ static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
fc_req->ct_els.port = port;
fc_req->ct_els.handler = zfcp_fc_complete;
fc_req->ct_els.handler_data = &completion;
- fc_req->ct_els.req = &fc_req->sg_req;
- fc_req->ct_els.resp = &fc_req->sg_rsp;
+ fc_req->ct_els.sgt_req.sgl = &fc_req->sg_req;
+ fc_req->ct_els.sgt_resp.sgl = &fc_req->sg_rsp;
sg_init_one(&fc_req->sg_req, gid_pn_req, sizeof(*gid_pn_req));
sg_init_one(&fc_req->sg_rsp, gid_pn_rsp, sizeof(*gid_pn_rsp));
+ fc_req->ct_els.sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ fc_req->ct_els.sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
zfcp_fc_ct_ns_init(&gid_pn_req->ct_hdr,
FC_NS_GID_PN, ZFCP_FC_CT_SIZE_PAGE);
@@ -558,12 +560,14 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
return -ENOMEM;
fc_req->ct_els.port = port;
- fc_req->ct_els.req = &fc_req->sg_req;
- fc_req->ct_els.resp = &fc_req->sg_rsp;
+ fc_req->ct_els.sgt_req.sgl = &fc_req->sg_req;
+ fc_req->ct_els.sgt_resp.sgl = &fc_req->sg_rsp;
sg_init_one(&fc_req->sg_req, &fc_req->u.adisc.req,
sizeof(struct fc_els_adisc));
sg_init_one(&fc_req->sg_rsp, &fc_req->u.adisc.rsp,
sizeof(struct fc_els_adisc));
+ fc_req->ct_els.sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ fc_req->ct_els.sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
fc_req->ct_els.handler = zfcp_fc_adisc_handler;
fc_req->ct_els.handler_data = fc_req;
@@ -706,8 +710,10 @@ static int zfcp_fc_send_gpn_ft(struct zfcp_fc_req *fc_req,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -865,8 +871,10 @@ static int zfcp_fc_gspn(struct zfcp_adapter *adapter,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -924,8 +932,10 @@ static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
ct_els->handler = zfcp_fc_complete;
ct_els->handler_data = &completion;
- ct_els->req = &fc_req->sg_req;
- ct_els->resp = &fc_req->sg_rsp;
+ ct_els->sgt_req.sgl = &fc_req->sg_req;
+ ct_els->sgt_resp.sgl = &fc_req->sg_rsp;
+ ct_els->sgt_req.orig_nents = sg_nents(&fc_req->sg_req);
+ ct_els->sgt_resp.orig_nents = sg_nents(&fc_req->sg_rsp);
ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
ZFCP_FC_CTELS_TMO);
@@ -1090,8 +1100,10 @@ int zfcp_fc_exec_bsg_job(struct bsg_job *job)
if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN))
return -EINVAL;
- ct_els->req = job->request_payload.sg_list;
- ct_els->resp = job->reply_payload.sg_list;
+ ct_els->sgt_req.sgl = job->request_payload.sg_list;
+ ct_els->sgt_resp.sgl = job->reply_payload.sg_list;
+ ct_els->sgt_req.orig_nents = sg_nents(ct_els->sgt_req.sgl);
+ ct_els->sgt_resp.orig_nents = sg_nents(ct_els->sgt_resp.sgl);
ct_els->handler_data = job;
switch (bsg_request->msgcode) {
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index d407f16e77ef..a3b99839da9e 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1242,7 +1242,8 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port,
}
req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
- ret = zfcp_fsf_setup_ct_els(req, ct->req, ct->resp, timeout);
+ ret = zfcp_fsf_setup_ct_els(req, ct->sgt_req.sgl, ct->sgt_resp.sgl,
+ timeout);
if (ret)
goto failed_send;
@@ -1342,7 +1343,8 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id,
if (!zfcp_adapter_multi_buffer_active(adapter))
zfcp_qdio_sbal_limit(qdio, &req->qdio_req, 2);
- ret = zfcp_fsf_setup_ct_els(req, els->req, els->resp, timeout);
+ ret = zfcp_fsf_setup_ct_els(req, els->sgt_req.sgl, els->sgt_resp.sgl,
+ timeout);
if (ret)
goto failed_send;
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 4b92e85ec71d..22e7fd933a78 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -487,8 +487,9 @@ struct zfcp_blk_drv_data {
/**
* struct zfcp_fsf_ct_els - zfcp data for ct or els request
- * @req: scatter-gather list for request, points to &zfcp_fc_req.sg_req or BSG
- * @resp: scatter-gather list for response, points to &zfcp_fc_req.sg_rsp or BSG
+ * @sgt_req: sg_table for request, its sgl points to &zfcp_fc_req.sg_req or BSG
+ * @sgt_resp: sg_table for response, its sgl points to &zfcp_fc_req.sg_resp
+ * or BSG
* @handler: handler function (called for response to the request)
* @handler_data: data passed to handler function
* @port: Optional pointer to port for zfcp internal ELS (only test link ADISC)
@@ -496,8 +497,8 @@ struct zfcp_blk_drv_data {
* @d_id: Destination ID of either open WKA port for CT or of D_ID for ELS
*/
struct zfcp_fsf_ct_els {
- struct scatterlist *req;
- struct scatterlist *resp;
+ struct sg_table sgt_req;
+ struct sg_table sgt_resp;
void (*handler)(void *);
void *handler_data;
struct zfcp_port *port;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-24 6:19 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-11 8:40 [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure M Nikhil
-- strict thread matches above, loose matches on Subject: below --
2026-09-21 14:30 [PATCH v12 0/2] zfcp: Use DMA streaming API to map I/O M Nikhil
2026-09-21 14:30 ` [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure M Nikhil
2026-09-24 6:09 [PATCH v12 0/2] zfcp: Use DMA streaming API to map I/O M Nikhil
2026-09-24 6:09 ` [PATCH v12 1/2] zfcp: Replace sg-list with sg_table in zfcp_fsf_ct_els structure M Nikhil
2026-09-24 6:19 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox