summaryrefslogtreecommitdiff
path: root/drivers/infiniband/ulp
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-21 11:48:54 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-21 11:48:54 -0700
commit21bd0802cd3f58b656065f1be236694c40588c3a (patch)
tree08f3479623310d779023b5a8cd4290e53d1e37d7 /drivers/infiniband/ulp
parent35748ddd3b2c91555bd86b8cf88edc90e7317e57 (diff)
parent8049741ac93acd3a590dac070e12571fddf0e294 (diff)
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull RDMA updates from Jason Gunthorpe: "About the normal size, still a lot of AI bug fixes and so on, but some interesting new functionality too: - Assorted locking, bounds-checking, cleanup, and error-path fixes across UCMA/CMA, bng_re, bnxt_re, cxgb4, EFA, ERDMA, HFI1, HNS, ionic, iRDMA, mlx4/mlx5, RXE, SIW, SRP/SRPT, and iSER target. - netlink report for max # of supported resources - get_zeroed_page()/etc removal - Robust udata for ionic - Allow unique RDMA device names per network namespace - Completion counters and v2 admit queue support for EFA - UC QP support for MANA - Completion timestamps for ionic - Harden uverbs data validation and resource lifetime handling, fixing several core use-after-free conditions. - bnxt_re toggle-page ownership and lifetime bug fixes - dmabuf SRQ support for mlx5" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (160 commits) RDMA/ucma: Allow path records to exactly fit the output buffer RDMA/uverbs: Guard legacy bundles without method_elm RDMA/efa: Add support for 128B admin v2 SQ entry RDMA/efa: Generalize the admin SQ RDMA/efa: Decouple admin command payload from admin header RDMA/rxe: Fix OOB in free_rd_atomic_resources() RDMA/cma: Fix WARNING in res_to_rt RDMA/cxgb4: Free debugfs on registration failure RDMA/cxgb4: Cancel reg_work before freeing device on remove RDMA/ucma: Lock the handler in ucma_set_ib_path() RDMA/ucma: Lock the handler in ucma_write_cm_event() RDMA/erdma: restrict the driver to little-endian systems RDMA/ionic: Embed counter driver data in rdma_counter allocation RDMA/ionic: Cap eq_count to the eth driver's interrupt vector budget RDMA/siw: Fix use-after-free in siw_accept() IB/isert: post the full-feature receive buffers after session registration IB/isert: delay the final Login Response until the session is registered RDMA/srp: fix heap information leak on a truncated SRP_CRED_REQ RDMA/erdma: Hold QP references for AE and CM processing RDMA/erdma: Hold CQ references when processing EQ events ...
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c10
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c3
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c5
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c92
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h1
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c11
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv.c11
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c63
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c30
10 files changed, 154 insertions, 74 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 57fec88a1629..ed0592898384 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1071,8 +1071,7 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_
struct ib_qp *tx_qp;
if (dev->features & NETIF_F_SG)
- attr.cap.max_send_sge = min_t(u32, priv->ca->attrs.max_send_sge,
- MAX_SKB_FRAGS + 1);
+ attr.cap.max_send_sge = min(priv->ca->attrs.max_send_sge, MAX_SKB_FRAGS + 1);
tx_qp = ib_create_qp(priv->pd, &attr);
tx->max_send_sge = attr.cap.max_send_sge;
@@ -1582,7 +1581,8 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
int ipoib_cm_dev_init(struct net_device *dev)
{
struct ipoib_dev_priv *priv = ipoib_priv(dev);
- int max_srq_sge, i;
+ u32 max_srq_sge;
+ int i;
u8 addr;
INIT_LIST_HEAD(&priv->cm.passive_ids);
@@ -1600,9 +1600,9 @@ int ipoib_cm_dev_init(struct net_device *dev)
skb_queue_head_init(&priv->cm.skb_queue);
- ipoib_dbg(priv, "max_srq_sge=%d\n", priv->ca->attrs.max_srq_sge);
+ ipoib_dbg(priv, "max_srq_sge=%u\n", priv->ca->attrs.max_srq_sge);
- max_srq_sge = min_t(int, IPOIB_CM_RX_SG, priv->ca->attrs.max_srq_sge);
+ max_srq_sge = min(priv->ca->attrs.max_srq_sge, IPOIB_CM_RX_SG);
ipoib_cm_create_srq(dev, max_srq_sge);
if (ipoib_cm_has_srq(dev)) {
priv->cm.max_cm_mtu = max_srq_sge * PAGE_SIZE - 0x10;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 16a015b67206..6c14246befb1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -2783,6 +2783,7 @@ err_client:
err_sa:
ib_sa_unregister_client(&ipoib_sa_client);
destroy_workqueue(ipoib_workqueue);
+ rcu_barrier();
err_fs:
ipoib_unregister_debugfs();
@@ -2800,6 +2801,7 @@ static void __exit ipoib_cleanup_module(void)
ib_sa_unregister_client(&ipoib_sa_client);
ipoib_unregister_debugfs();
destroy_workqueue(ipoib_workqueue);
+ rcu_barrier();
}
module_init(ipoib_init_module);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 3ed1ea566690..2490696a1aab 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -147,8 +147,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
.cap = {
.max_send_wr = ipoib_sendq_size,
.max_recv_wr = ipoib_recvq_size,
- .max_send_sge = min_t(u32, priv->ca->attrs.max_send_sge,
- MAX_SKB_FRAGS + 1),
+ .max_send_sge = min(priv->ca->attrs.max_send_sge, MAX_SKB_FRAGS + 1),
.max_recv_sge = IPOIB_UD_RX_SG
},
.sq_sig_type = IB_SIGNAL_ALL_WR,
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index f03b3bb3c0c4..55fe68e5b837 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -244,8 +244,7 @@ static int iser_create_ib_conn_res(struct ib_conn *ib_conn)
max_send_wr = ISER_QP_SIG_MAX_REQ_DTOS + 1;
else
max_send_wr = ISER_QP_MAX_REQ_DTOS + 1;
- max_send_wr = min_t(unsigned int, max_send_wr,
- (unsigned int)ib_dev->attrs.max_qp_wr);
+ max_send_wr = min(max_send_wr, ib_dev->attrs.max_qp_wr);
cq_size = max_send_wr + ISER_QP_MAX_RECV_DTOS;
ib_conn->cq = ib_cq_pool_get(ib_dev, cq_size, -1, IB_POLL_SOFTIRQ);
@@ -589,7 +588,7 @@ static void iser_route_handler(struct rdma_cm_id *cma_id)
goto failure;
memset(&conn_param, 0, sizeof conn_param);
- conn_param.responder_resources = ib_dev->attrs.max_qp_rd_atom;
+ conn_param.responder_resources = min(ib_dev->attrs.max_qp_rd_atom, U8_MAX);
conn_param.initiator_depth = 1;
conn_param.retry_count = 7;
conn_param.rnr_retry_count = 6;
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 1015a51f750a..5087ea983071 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -59,6 +59,8 @@ static void isert_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static void isert_send_done(struct ib_cq *cq, struct ib_wc *wc);
static void isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc);
static void isert_login_send_done(struct ib_cq *cq, struct ib_wc *wc);
+static void isert_unmap_tx_desc(struct iser_tx_desc *tx_desc,
+ struct ib_device *ib_dev);
static int isert_sg_tablesize_set(const char *val, const struct kernel_param *kp)
{
@@ -214,9 +216,9 @@ isert_create_device_ib_res(struct isert_device *device)
struct ib_device *ib_dev = device->ib_device;
int ret;
- isert_dbg("devattr->max_send_sge: %d devattr->max_recv_sge %d\n",
+ isert_dbg("devattr->max_send_sge: %u devattr->max_recv_sge %u\n",
ib_dev->attrs.max_send_sge, ib_dev->attrs.max_recv_sge);
- isert_dbg("devattr->max_sge_rd: %d\n", ib_dev->attrs.max_sge_rd);
+ isert_dbg("devattr->max_sge_rd: %u\n", ib_dev->attrs.max_sge_rd);
device->pd = ib_alloc_pd(ib_dev, 0);
if (IS_ERR(device->pd)) {
@@ -381,8 +383,7 @@ isert_set_nego_params(struct isert_conn *isert_conn,
struct ib_device_attr *attr = &isert_conn->device->ib_device->attrs;
/* Set max inflight RDMA READ requests */
- isert_conn->initiator_depth = min_t(u8, param->initiator_depth,
- attr->max_qp_init_rd_atom);
+ isert_conn->initiator_depth = min(param->initiator_depth, attr->max_qp_init_rd_atom);
isert_dbg("Using initiator_depth: %u\n", isert_conn->initiator_depth);
if (param->private_data) {
@@ -496,6 +497,8 @@ isert_connect_release(struct isert_conn *isert_conn)
if (isert_conn->qp)
isert_destroy_qp(isert_conn);
+ isert_unmap_tx_desc(&isert_conn->login_tx_desc, device->ib_device);
+
if (isert_conn->login_desc)
isert_free_login_buf(isert_conn);
@@ -943,27 +946,16 @@ isert_put_login_tx(struct iscsit_conn *conn, struct iscsi_login *login,
}
if (!login->login_failed) {
if (login->login_complete) {
- ret = isert_alloc_rx_descriptors(isert_conn);
- if (ret)
- return ret;
-
- ret = isert_post_recvm(isert_conn,
- ISERT_QP_MAX_RECV_DTOS);
- if (ret)
- return ret;
-
- /* Now we are in FULL_FEATURE phase */
- mutex_lock(&isert_conn->mutex);
- isert_conn->state = ISER_CONN_FULL_FEATURE;
- mutex_unlock(&isert_conn->mutex);
- goto post_send;
+ /* Posted and sent from isert_get_rx_pdu(). */
+ isert_conn->login_rsp_pending = true;
+ return 0;
}
ret = isert_login_post_recv(isert_conn);
if (ret)
return ret;
}
-post_send:
+
ret = isert_login_post_send(isert_conn, tx_desc);
if (ret)
return ret;
@@ -971,6 +963,21 @@ post_send:
return 0;
}
+static int
+isert_check_login_req(struct isert_conn *isert_conn)
+{
+ struct iscsi_hdr *hdr = isert_get_iscsi_hdr(isert_conn->login_desc);
+ u32 dlength = ntoh24(hdr->dlength);
+
+ if (unlikely(dlength > (u32)isert_conn->login_req_len)) {
+ isert_dbg("login PDU declares %u data bytes but only %d were received\n",
+ dlength, isert_conn->login_req_len);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static void
isert_rx_login_req(struct isert_conn *isert_conn)
{
@@ -1333,6 +1340,21 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
ISER_RX_SIZE, DMA_FROM_DEVICE);
+ /*
+ * The data segment length declared in the BHS is attacker controlled
+ * and is used further down to read that many bytes out of the fixed
+ * size receive descriptor, so it has to be checked against the number
+ * of bytes that were actually received. Comparing without subtracting
+ * also rejects PDUs shorter than the iSER and iSCSI headers, which
+ * would otherwise be parsed out of stale descriptor contents.
+ */
+ if (unlikely(wc->byte_len < ISER_HEADERS_LEN + ntoh24(hdr->dlength))) {
+ isert_err("PDU declares %u data bytes but only %u bytes were received\n",
+ ntoh24(hdr->dlength), wc->byte_len);
+ iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
+ return;
+ }
+
isert_dbg("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n",
rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags,
(int)(wc->byte_len - ISER_HEADERS_LEN));
@@ -1394,8 +1416,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc)
if (isert_conn->conn) {
struct iscsi_login *login = isert_conn->conn->conn_login;
- if (login && !login->first_request)
+ if (login && !login->first_request) {
+ if (isert_check_login_req(isert_conn))
+ return;
+
isert_rx_login_req(isert_conn);
+ }
}
mutex_lock(&isert_conn->mutex);
@@ -2360,6 +2386,10 @@ isert_get_login_rx(struct iscsit_conn *conn, struct iscsi_login *login)
if (!login->first_request)
return 0;
+ ret = isert_check_login_req(isert_conn);
+ if (ret)
+ return ret;
+
isert_rx_login_req(isert_conn);
isert_info("before login_comp conn: %p\n", conn);
@@ -2585,8 +2615,30 @@ static void isert_free_conn(struct iscsit_conn *conn)
static void isert_get_rx_pdu(struct iscsit_conn *conn)
{
+ struct isert_conn *isert_conn = conn->context;
struct completion comp;
+ /* The login timeout timer can fail the login after isert_put_login_tx(). */
+ if (!isert_conn->login_rsp_pending)
+ return;
+
+ isert_conn->login_rsp_pending = false;
+
+ /* The session is registered by now; see isert_put_login_tx(). */
+ if (isert_alloc_rx_descriptors(isert_conn))
+ return;
+
+ if (isert_post_recvm(isert_conn, ISERT_QP_MAX_RECV_DTOS))
+ return;
+
+ /* Now we are in FULL_FEATURE phase */
+ mutex_lock(&isert_conn->mutex);
+ isert_conn->state = ISER_CONN_FULL_FEATURE;
+ mutex_unlock(&isert_conn->mutex);
+
+ if (isert_login_post_send(isert_conn, &isert_conn->login_tx_desc))
+ return;
+
init_completion(&comp);
wait_for_completion_interruptible(&comp);
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h
index 0b2dfd6e7e27..0bac5aa66c80 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.h
+++ b/drivers/infiniband/ulp/isert/ib_isert.h
@@ -178,6 +178,7 @@ struct isert_conn {
struct completion login_comp;
struct completion login_req_comp;
struct iser_tx_desc login_tx_desc;
+ bool login_rsp_pending;
struct rdma_cm_id *cm_id;
struct ib_qp *qp;
struct ib_cq *cq;
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index d34d7e5f34d6..7b2c51ae614f 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -1675,8 +1675,7 @@ static int create_con_cq_qp(struct rtrs_clt_con *con)
* + 2 for drain and heartbeat
* in case qp gets into error state.
*/
- max_send_wr =
- min_t(int, wr_limit, SERVICE_CON_QUEUE_DEPTH * 2 + 2);
+ max_send_wr = min(wr_limit, SERVICE_CON_QUEUE_DEPTH * 2 + 2);
max_recv_wr = max_send_wr;
} else {
/*
@@ -1692,11 +1691,9 @@ static int create_con_cq_qp(struct rtrs_clt_con *con)
wr_limit = clt_path->s.dev->ib_dev->attrs.max_qp_wr;
/* Shared between connections */
clt_path->s.dev_ref++;
- max_send_wr = min_t(int, wr_limit,
- /* QD * (REQ + RSP + FR REGS or INVS) + drain */
- clt_path->queue_depth * 4 + 1);
- max_recv_wr = min_t(int, wr_limit,
- clt_path->queue_depth * 3 + 1);
+ /* QD * (REQ + RSP + FR REGS or INVS) + drain */
+ max_send_wr = min(wr_limit, clt_path->queue_depth * 4 + 1);
+ max_recv_wr = min(wr_limit, clt_path->queue_depth * 3 + 1);
max_send_sge = 2;
}
atomic_set(&con->c.sq_wr_avail, max_send_wr);
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index 7d8e4422cc57..5314599d29fe 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -1740,21 +1740,16 @@ static int create_con(struct rtrs_srv_path *srv_path,
* All receive and all send (each requiring invalidate)
* + 2 for drain and heartbeat
*/
- max_send_wr = min_t(int, wr_limit,
- SERVICE_CON_QUEUE_DEPTH * 2 + 2);
+ max_send_wr = min(wr_limit, SERVICE_CON_QUEUE_DEPTH * 2 + 2);
max_recv_wr = max_send_wr;
s->signal_interval = min_not_zero(srv->queue_depth,
(size_t)SERVICE_CON_QUEUE_DEPTH);
} else {
/* when always_invlaidate enalbed, we need linv+rinv+mr+imm */
if (always_invalidate)
- max_send_wr =
- min_t(int, wr_limit,
- srv->queue_depth * (1 + 4) + 1);
+ max_send_wr = min(wr_limit, srv->queue_depth * (1 + 4) + 1);
else
- max_send_wr =
- min_t(int, wr_limit,
- srv->queue_depth * (1 + 2) + 1);
+ max_send_wr = min(wr_limit, srv->queue_depth * (1 + 2) + 1);
max_recv_wr = srv->queue_depth + 1;
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index acbd787de265..6b429ef63f8f 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -557,7 +557,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
init_attr->cap.max_send_wr = m * target->queue_size;
init_attr->cap.max_recv_wr = target->queue_size + 1;
init_attr->cap.max_recv_sge = 1;
- init_attr->cap.max_send_sge = min(SRP_MAX_SGE, attr->max_send_sge);
+ init_attr->cap.max_send_sge = min(attr->max_send_sge, SRP_MAX_SGE);
init_attr->sq_sig_type = IB_SIGNAL_REQ_WR;
init_attr->qp_type = IB_QPT_RC;
init_attr->send_cq = send_cq;
@@ -1945,7 +1945,8 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp,
ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
if (rsp->tag == ch->tsk_mgmt_tag) {
ch->tsk_mgmt_status = -1;
- if (be32_to_cpu(rsp->resp_data_len) >= 4)
+ if (be32_to_cpu(rsp->resp_data_len) >= 4 &&
+ byte_len >= sizeof(*rsp) + 4)
ch->tsk_mgmt_status = rsp->data[3];
complete(&ch->tsk_mgmt_done);
} else {
@@ -2045,13 +2046,20 @@ static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
}
static void srp_process_cred_req(struct srp_rdma_ch *ch,
- struct srp_cred_req *req)
+ struct srp_cred_req *req, u32 byte_len)
{
- struct srp_cred_rsp rsp = {
- .opcode = SRP_CRED_RSP,
- .tag = req->tag,
- };
- s32 delta = be32_to_cpu(req->req_lim_delta);
+ struct srp_cred_rsp rsp = { .opcode = SRP_CRED_RSP };
+ s32 delta;
+
+ if (byte_len < sizeof(*req)) {
+ shost_printk(KERN_ERR, ch->target->scsi_host, PFX
+ "dropping truncated SRP_CRED_REQ (%u bytes received, %zu expected)\n",
+ byte_len, sizeof(*req));
+ return;
+ }
+
+ rsp.tag = req->tag;
+ delta = be32_to_cpu(req->req_lim_delta);
if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
shost_printk(KERN_ERR, ch->target->scsi_host, PFX
@@ -2059,14 +2067,21 @@ static void srp_process_cred_req(struct srp_rdma_ch *ch,
}
static void srp_process_aer_req(struct srp_rdma_ch *ch,
- struct srp_aer_req *req)
+ struct srp_aer_req *req, u32 byte_len)
{
struct srp_target_port *target = ch->target;
- struct srp_aer_rsp rsp = {
- .opcode = SRP_AER_RSP,
- .tag = req->tag,
- };
- s32 delta = be32_to_cpu(req->req_lim_delta);
+ struct srp_aer_rsp rsp = { .opcode = SRP_AER_RSP };
+ s32 delta;
+
+ if (byte_len < sizeof(*req)) {
+ shost_printk(KERN_ERR, target->scsi_host, PFX
+ "dropping truncated SRP_AER_REQ (%u bytes received, %zu expected)\n",
+ byte_len, sizeof(*req));
+ return;
+ }
+
+ rsp.tag = req->tag;
+ delta = be32_to_cpu(req->req_lim_delta);
shost_printk(KERN_ERR, target->scsi_host, PFX
"ignoring AER for LUN %llu\n", scsilun_to_int(&req->lun));
@@ -2108,11 +2123,11 @@ static void srp_recv_done(struct ib_cq *cq, struct ib_wc *wc)
break;
case SRP_CRED_REQ:
- srp_process_cred_req(ch, iu->buf);
+ srp_process_cred_req(ch, iu->buf, wc->byte_len);
break;
case SRP_AER_REQ:
- srp_process_aer_req(ch, iu->buf);
+ srp_process_aer_req(ch, iu->buf, wc->byte_len);
break;
case SRP_T_LOGOUT:
@@ -3189,10 +3204,24 @@ static struct attribute *srp_class_attrs[];
ATTRIBUTE_GROUPS(srp_class);
+/*
+ * SRP hosts are named after their ib device, so tag the class by the ib
+ * device's net namespace.
+ */
+static const struct ns_common *srp_net_namespace(const struct device *dev)
+{
+ struct srp_host *host = container_of(dev, struct srp_host, dev);
+ struct net *net = rdma_dev_net(host->srp_dev->dev);
+
+ return net ? to_ns_common(net) : NULL;
+}
+
static struct class srp_class = {
.name = "infiniband_srp",
.dev_groups = srp_class_groups,
- .dev_release = srp_release_dev
+ .dev_release = srp_release_dev,
+ .ns_type = &net_ns_type_operations,
+ .namespace = srp_net_namespace,
};
/**
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index f66cfd70c263..7197d95f2216 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -77,8 +77,8 @@ module_param(srp_max_req_size, int, 0444);
MODULE_PARM_DESC(srp_max_req_size,
"Maximum size of SRP request messages in bytes.");
-static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
-module_param(srpt_srq_size, int, 0444);
+static unsigned int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
+module_param(srpt_srq_size, uint, 0444);
MODULE_PARM_DESC(srpt_srq_size,
"Shared receive queue (SRQ) size.");
@@ -405,8 +405,7 @@ static void srpt_get_ioc(struct srpt_port *sport, u32 slot,
if (sdev->use_srq)
send_queue_depth = sdev->srq_size;
else
- send_queue_depth = min(MAX_SRPT_RQ_SIZE,
- sdev->device->attrs.max_qp_wr);
+ send_queue_depth = min(sdev->device->attrs.max_qp_wr, MAX_SRPT_RQ_SIZE);
memset(iocp, 0, sizeof(*iocp));
strcpy(iocp->id_string, SRPT_ID_STRING);
@@ -960,6 +959,7 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx,
struct srpt_rdma_ch *ch = ioctx->ch;
struct scatterlist *prev = NULL;
unsigned prev_nents;
+ u8 n_rdma, n_rw_ctx;
int ret, i;
if (nbufs == 1) {
@@ -970,6 +970,9 @@ static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx,
return -ENOMEM;
}
+ n_rw_ctx = ioctx->n_rw_ctx;
+ n_rdma = ioctx->n_rdma;
+
for (i = ioctx->n_rw_ctx; i < nbufs; i++, db++) {
struct srpt_rw_ctx *ctx = &ioctx->rw_ctxs[i];
u64 remote_addr = be64_to_cpu(db->va);
@@ -1016,6 +1019,9 @@ unwind:
}
if (ioctx->rw_ctxs != &ioctx->s_rw_ctx)
kfree(ioctx->rw_ctxs);
+ ioctx->rw_ctxs = NULL;
+ ioctx->n_rw_ctx = n_rw_ctx;
+ ioctx->n_rdma = n_rdma;
return ret;
}
@@ -1596,7 +1602,7 @@ static void srpt_handle_cmd(struct srpt_rdma_ch *ch,
rc = target_init_cmd(cmd, ch->sess, &send_ioctx->sense_data[0],
scsilun_to_int(&srp_cmd->lun), data_len,
- TCM_SIMPLE_TAG, dir, TARGET_SCF_ACK_KREF);
+ cmd->sam_task_attr, dir, TARGET_SCF_ACK_KREF);
if (rc != 0) {
pr_debug("target_submit_cmd() returned %d for tag %#llx\n", rc,
srp_cmd->tag);
@@ -1851,7 +1857,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
struct srpt_port *sport = ch->sport;
struct srpt_device *sdev = sport->sdev;
const struct ib_device_attr *attrs = &sdev->device->attrs;
- int sq_size = sport->port_attrib.srp_sq_size;
+ u32 sq_size = sport->port_attrib.srp_sq_size;
int i, ret;
WARN_ON(ch->rq_size < 1);
@@ -1912,13 +1918,13 @@ retry:
bool retry = sq_size > MIN_SRPT_SQ_SIZE;
if (retry) {
- pr_debug("failed to create queue pair with sq_size = %d (%d) - retrying\n",
+ pr_debug("failed to create queue pair with sq_size = %u (%d) - retrying\n",
sq_size, ret);
ib_cq_pool_put(ch->cq, ch->cq_size);
sq_size = max(sq_size / 2, MIN_SRPT_SQ_SIZE);
goto retry;
} else {
- pr_err("failed to create queue pair with sq_size = %d (%d)\n",
+ pr_err("failed to create queue pair with sq_size = %u (%d)\n",
sq_size, ret);
goto err_destroy_cq;
}
@@ -1926,7 +1932,7 @@ retry:
atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr);
- pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %d ch= %p\n",
+ pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %u ch= %p\n",
__func__, ch->cq->cqe, qp_init->cap.max_send_sge,
qp_init->cap.max_send_wr, ch);
@@ -2299,7 +2305,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
* depth to avoid that the initiator driver has to report QUEUE_FULL
* to the SCSI mid-layer.
*/
- ch->rq_size = min(MAX_SRPT_RQ_SIZE, sdev->device->attrs.max_qp_wr);
+ ch->rq_size = min(sdev->device->attrs.max_qp_wr, MAX_SRPT_RQ_SIZE);
spin_lock_init(&ch->spinlock);
ch->state = CH_CONNECTING;
INIT_LIST_HEAD(&ch->cmd_wait_list);
@@ -3137,7 +3143,7 @@ static int srpt_alloc_srq(struct srpt_device *sdev)
return PTR_ERR(srq);
}
- pr_debug("create SRQ #wr= %d max_allow=%d dev= %s\n", sdev->srq_size,
+ pr_debug("create SRQ #wr= %d max_allow=%u dev= %s\n", sdev->srq_size,
sdev->device->attrs.max_srq_wr, dev_name(&device->dev));
sdev->req_buf_cache = srpt_cache_get(srp_max_req_size);
@@ -3952,7 +3958,7 @@ static int __init srpt_init_module(void)
if (srpt_srq_size < MIN_SRPT_SRQ_SIZE
|| srpt_srq_size > MAX_SRPT_SRQ_SIZE) {
- pr_err("invalid value %d for kernel module parameter srpt_srq_size -- must be in the range [%d..%d].\n",
+ pr_err("invalid value %u for kernel module parameter srpt_srq_size -- must be in the range [%d..%d].\n",
srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE);
goto out;
}