aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorNavdeep Parhar <np@FreeBSD.org>2016-08-25 05:22:53 +0000
committerNavdeep Parhar <np@FreeBSD.org>2016-08-25 05:22:53 +0000
commit97b84d344d4a7bb9e34703948e31be5247318a71 (patch)
tree956a2021fa5a85180b18e0c435a8cdcba6356718 /sys/dev
parent02d99265593c8c13ae08eaa7a962531bcd9889a0 (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/cxgbe/cxgbei/icl_cxgbei.c7
-rw-r--r--sys/dev/iscsi/icl.c37
-rw-r--r--sys/dev/iscsi/icl.h14
-rw-r--r--sys/dev/iscsi/icl_soft.c4
-rw-r--r--sys/dev/iscsi/iscsi.c46
-rw-r--r--sys/dev/iscsi/iscsi.h7
-rw-r--r--sys/dev/iscsi/iscsi_ioctl.h22
-rw-r--r--sys/dev/iser/icl_iser.c4
8 files changed, 99 insertions, 42 deletions
diff --git a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
index 8f29452196fe..288e8e692a9b 100644
--- a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
+++ b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c
@@ -832,10 +832,13 @@ icl_cxgbei_conn_transfer_done(struct icl_conn *ic, void *prv)
}
static int
-icl_cxgbei_limits(size_t *limitp)
+icl_cxgbei_limits(struct icl_drv_limits *idl)
{
- *limitp = CXGBEI_MAX_DSL;
+ idl->idl_max_recv_data_segment_length = CXGBEI_MAX_DSL;
+ idl->idl_max_send_data_segment_length = CXGBEI_MAX_DSL;
+ idl->idl_max_burst_length = 2 * 1024 * 1024;
+ idl->idl_first_burst_length = CXGBEI_MAX_DSL;
return (0);
}
diff --git a/sys/dev/iscsi/icl.c b/sys/dev/iscsi/icl.c
index 2823074f2104..9a20b54a1f83 100644
--- a/sys/dev/iscsi/icl.c
+++ b/sys/dev/iscsi/icl.c
@@ -59,7 +59,7 @@ struct icl_module {
char *im_name;
bool im_iser;
int im_priority;
- int (*im_limits)(size_t *limitp);
+ int (*im_limits)(struct icl_drv_limits *idl);
struct icl_conn *(*im_new_conn)(const char *name,
struct mtx *lock);
};
@@ -182,11 +182,12 @@ icl_new_conn(const char *offload, bool iser, const char *name, struct mtx *lock)
}
int
-icl_limits(const char *offload, bool iser, size_t *limitp)
+icl_limits(const char *offload, bool iser, struct icl_drv_limits *idl)
{
struct icl_module *im;
int error;
+ bzero(idl, sizeof(*idl));
sx_slock(&sc->sc_lock);
im = icl_find(offload, iser, false);
if (im == NULL) {
@@ -194,14 +195,42 @@ icl_limits(const char *offload, bool iser, size_t *limitp)
return (ENXIO);
}
- error = im->im_limits(limitp);
+ error = im->im_limits(idl);
sx_sunlock(&sc->sc_lock);
+ /*
+ * Validate the limits provided by the driver against values allowed by
+ * the iSCSI RFC. 0 means iscsid/ctld should pick a reasonable value.
+ *
+ * Note that max_send_dsl is an internal implementation detail and not
+ * part of the RFC.
+ */
+#define OUT_OF_RANGE(x, lo, hi) ((x) != 0 && ((x) < (lo) || (x) > (hi)))
+ if (error == 0 &&
+ (OUT_OF_RANGE(idl->idl_max_recv_data_segment_length, 512, 16777215) ||
+ OUT_OF_RANGE(idl->idl_max_send_data_segment_length, 512, 16777215) ||
+ OUT_OF_RANGE(idl->idl_max_burst_length, 512, 16777215) ||
+ OUT_OF_RANGE(idl->idl_first_burst_length, 512, 16777215))) {
+ error = EINVAL;
+ }
+#undef OUT_OF_RANGE
+
+ /*
+ * If both first_burst and max_burst are provided then first_burst must
+ * not exceed max_burst.
+ */
+ if (error == 0 && idl->idl_first_burst_length > 0 &&
+ idl->idl_max_burst_length > 0 &&
+ idl->idl_first_burst_length > idl->idl_max_burst_length) {
+ error = EINVAL;
+ }
+
return (error);
}
int
-icl_register(const char *offload, bool iser, int priority, int (*limits)(size_t *),
+icl_register(const char *offload, bool iser, int priority,
+ int (*limits)(struct icl_drv_limits *),
struct icl_conn *(*new_conn)(const char *, struct mtx *))
{
struct icl_module *im;
diff --git a/sys/dev/iscsi/icl.h b/sys/dev/iscsi/icl.h
index 292fa6006657..0a1ee9414e4f 100644
--- a/sys/dev/iscsi/icl.h
+++ b/sys/dev/iscsi/icl.h
@@ -126,12 +126,20 @@ struct icl_conn {
void *ic_prv0;
};
+struct icl_drv_limits {
+ int idl_max_recv_data_segment_length;
+ int idl_max_send_data_segment_length;
+ int idl_max_burst_length;
+ int idl_first_burst_length;
+ int spare[4];
+};
+
struct icl_conn *icl_new_conn(const char *offload, bool iser, const char *name,
struct mtx *lock);
-int icl_limits(const char *offload, bool iser, size_t *limitp);
-
+int icl_limits(const char *offload, bool iser,
+ struct icl_drv_limits *idl);
int icl_register(const char *offload, bool iser, int priority,
- int (*limits)(size_t *),
+ int (*limits)(struct icl_drv_limits *),
struct icl_conn *(*new_conn)(const char *, struct mtx *));
int icl_unregister(const char *offload, bool rdma);
diff --git a/sys/dev/iscsi/icl_soft.c b/sys/dev/iscsi/icl_soft.c
index 4efae9fd9712..230a41456796 100644
--- a/sys/dev/iscsi/icl_soft.c
+++ b/sys/dev/iscsi/icl_soft.c
@@ -1474,10 +1474,10 @@ icl_soft_conn_transfer_done(struct icl_conn *ic, void *prv)
}
static int
-icl_soft_limits(size_t *limitp)
+icl_soft_limits(struct icl_drv_limits *idl)
{
- *limitp = 128 * 1024;
+ idl->idl_max_recv_data_segment_length = 128 * 1024;
return (0);
}
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index 5364584816c2..57b60bb8423f 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -1204,8 +1204,8 @@ iscsi_pdu_handle_r2t(struct icl_pdu *response)
for (;;) {
len = total_len;
- if (len > is->is_max_data_segment_length)
- len = is->is_max_data_segment_length;
+ if (len > is->is_max_send_data_segment_length)
+ len = is->is_max_send_data_segment_length;
if (off + len > csio->dxfer_len) {
ISCSI_SESSION_WARN(is, "target requested invalid "
@@ -1313,6 +1313,7 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
struct iscsi_daemon_request *request)
{
struct iscsi_session *is;
+ struct icl_drv_limits idl;
int error;
sx_slock(&sc->sc_lock);
@@ -1352,10 +1353,9 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
request->idr_tsih = 0; /* New or reinstated session. */
memcpy(&request->idr_conf, &is->is_conf,
sizeof(request->idr_conf));
-
+
error = icl_limits(is->is_conf.isc_offload,
- is->is_conf.isc_iser,
- &request->idr_limits.isl_max_data_segment_length);
+ is->is_conf.isc_iser, &idl);
if (error != 0) {
ISCSI_SESSION_WARN(is, "icl_limits for offload \"%s\" "
"failed with error %d", is->is_conf.isc_offload,
@@ -1363,6 +1363,14 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
sx_sunlock(&sc->sc_lock);
return (error);
}
+ request->idr_limits.isl_max_recv_data_segment_length =
+ idl.idl_max_recv_data_segment_length;
+ request->idr_limits.isl_max_send_data_segment_length =
+ idl.idl_max_recv_data_segment_length;
+ request->idr_limits.isl_max_burst_length =
+ idl.idl_max_burst_length;
+ request->idr_limits.isl_first_burst_length =
+ idl.idl_first_burst_length;
sx_sunlock(&sc->sc_lock);
return (0);
@@ -1417,12 +1425,10 @@ iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc,
is->is_initial_r2t = handoff->idh_initial_r2t;
is->is_immediate_data = handoff->idh_immediate_data;
- /*
- * Cap MaxRecvDataSegmentLength obtained from the target to the maximum
- * size supported by our ICL module.
- */
- is->is_max_data_segment_length = min(ic->ic_max_data_segment_length,
- handoff->idh_max_data_segment_length);
+ is->is_max_recv_data_segment_length =
+ handoff->idh_max_recv_data_segment_length;
+ is->is_max_send_data_segment_length =
+ handoff->idh_max_send_data_segment_length;
is->is_max_burst_length = handoff->idh_max_burst_length;
is->is_first_burst_length = handoff->idh_first_burst_length;
@@ -1634,7 +1640,7 @@ iscsi_ioctl_daemon_send(struct iscsi_softc *sc,
return (EIO);
datalen = ids->ids_data_segment_len;
- if (datalen > ISCSI_MAX_DATA_SEGMENT_LENGTH)
+ if (datalen > is->is_max_send_data_segment_length)
return (EINVAL);
if (datalen > 0) {
data = malloc(datalen, M_ISCSI, M_WAITOK);
@@ -1933,12 +1939,15 @@ iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl)
else
iss.iss_data_digest = ISCSI_DIGEST_NONE;
- iss.iss_max_data_segment_length = is->is_max_data_segment_length;
+ iss.iss_max_send_data_segment_length =
+ is->is_max_send_data_segment_length;
+ iss.iss_max_recv_data_segment_length =
+ is->is_max_recv_data_segment_length;
iss.iss_max_burst_length = is->is_max_burst_length;
iss.iss_first_burst_length = is->is_first_burst_length;
iss.iss_immediate_data = is->is_immediate_data;
iss.iss_connected = is->is_connected;
-
+
error = copyout(&iss, isl->isl_pstates + i, sizeof(iss));
if (error != 0) {
sx_sunlock(&sc->sc_lock);
@@ -2259,12 +2268,13 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
len = csio->dxfer_len;
//ISCSI_SESSION_DEBUG(is, "adding %zd of immediate data", len);
if (len > is->is_first_burst_length) {
- ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_first_burst_length);
+ ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len, is->is_first_burst_length);
len = is->is_first_burst_length;
}
- if (len > is->is_max_data_segment_length) {
- ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_max_data_segment_length);
- len = is->is_max_data_segment_length;
+ if (len > is->is_max_send_data_segment_length) {
+ ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len,
+ is->is_max_send_data_segment_length);
+ len = is->is_max_send_data_segment_length;
}
error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT);
diff --git a/sys/dev/iscsi/iscsi.h b/sys/dev/iscsi/iscsi.h
index 3225649cc464..d5bd79ab4140 100644
--- a/sys/dev/iscsi/iscsi.h
+++ b/sys/dev/iscsi/iscsi.h
@@ -62,12 +62,13 @@ struct iscsi_session {
int is_header_digest;
int is_data_digest;
int is_initial_r2t;
- size_t is_max_burst_length;
- size_t is_first_burst_length;
+ int is_max_burst_length;
+ int is_first_burst_length;
uint8_t is_isid[6];
uint16_t is_tsih;
bool is_immediate_data;
- size_t is_max_data_segment_length;
+ int is_max_recv_data_segment_length;
+ int is_max_send_data_segment_length;
char is_target_alias[ISCSI_ALIAS_LEN];
TAILQ_HEAD(, iscsi_outstanding) is_outstanding;
diff --git a/sys/dev/iscsi/iscsi_ioctl.h b/sys/dev/iscsi/iscsi_ioctl.h
index a494cd558ed1..3767c45f99df 100644
--- a/sys/dev/iscsi/iscsi_ioctl.h
+++ b/sys/dev/iscsi/iscsi_ioctl.h
@@ -76,8 +76,12 @@ struct iscsi_session_conf {
* iscsid(8) must obey those when negotiating operational parameters.
*/
struct iscsi_session_limits {
- size_t isl_max_data_segment_length;
- int isl_spare[8];
+ size_t isl_spare0;
+ int isl_max_recv_data_segment_length;
+ int isl_max_send_data_segment_length;
+ int isl_max_burst_length;
+ int isl_first_burst_length;
+ int isl_spare[4];
};
/*
@@ -89,14 +93,15 @@ struct iscsi_session_state {
char iss_target_alias[ISCSI_ALIAS_LEN];
int iss_header_digest;
int iss_data_digest;
- int iss_max_data_segment_length;
+ int iss_max_recv_data_segment_length;
int iss_max_burst_length;
int iss_first_burst_length;
int iss_immediate_data;
int iss_connected;
char iss_reason[ISCSI_REASON_LEN];
char iss_offload[ISCSI_OFFLOAD_LEN];
- int iss_spare[4];
+ int iss_max_send_data_segment_length;
+ int iss_spare[3];
};
/*
@@ -122,12 +127,13 @@ struct iscsi_daemon_handoff {
uint32_t idh_statsn;
int idh_header_digest;
int idh_data_digest;
- size_t idh_max_data_segment_length;
- size_t idh_max_burst_length;
- size_t idh_first_burst_length;
+ size_t spare[3];
int idh_immediate_data;
int idh_initial_r2t;
- int idh_spare[4];
+ int idh_max_recv_data_segment_length;
+ int idh_max_send_data_segment_length;
+ int idh_max_burst_length;
+ int idh_first_burst_length;
};
struct iscsi_daemon_fail {
diff --git a/sys/dev/iser/icl_iser.c b/sys/dev/iser/icl_iser.c
index a7c29d761035..0ebaee5977b0 100644
--- a/sys/dev/iser/icl_iser.c
+++ b/sys/dev/iser/icl_iser.c
@@ -483,9 +483,9 @@ iser_conn_task_done(struct icl_conn *ic, void *prv)
}
static int
-iser_limits(size_t *limitp)
+iser_limits(struct icl_drv_limits *idl)
{
- *limitp = 128 * 1024;
+ idl->idl_max_recv_data_segment_length = 128 * 1024;
return (0);
}