Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/iscsi/icl.c
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
#include <dev/iscsi/icl.h> | #include <dev/iscsi/icl.h> | ||||
#include <icl_conn_if.h> | #include <icl_conn_if.h> | ||||
struct icl_module { | struct icl_module { | ||||
TAILQ_ENTRY(icl_module) im_next; | TAILQ_ENTRY(icl_module) im_next; | ||||
char *im_name; | char *im_name; | ||||
bool im_iser; | bool im_iser; | ||||
int im_priority; | 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 icl_conn *(*im_new_conn)(const char *name, | ||||
struct mtx *lock); | struct mtx *lock); | ||||
}; | }; | ||||
struct icl_softc { | struct icl_softc { | ||||
struct sx sc_lock; | struct sx sc_lock; | ||||
TAILQ_HEAD(, icl_module) sc_modules; | TAILQ_HEAD(, icl_module) sc_modules; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | icl_new_conn(const char *offload, bool iser, const char *name, struct mtx *lock) | ||||
ic = im->im_new_conn(name, lock); | ic = im->im_new_conn(name, lock); | ||||
sx_sunlock(&sc->sc_lock); | sx_sunlock(&sc->sc_lock); | ||||
return (ic); | return (ic); | ||||
} | } | ||||
int | 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; | struct icl_module *im; | ||||
int error; | int error; | ||||
bzero(idl, sizeof(*idl)); | |||||
sx_slock(&sc->sc_lock); | sx_slock(&sc->sc_lock); | ||||
im = icl_find(offload, iser, false); | im = icl_find(offload, iser, false); | ||||
if (im == NULL) { | if (im == NULL) { | ||||
sx_sunlock(&sc->sc_lock); | sx_sunlock(&sc->sc_lock); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
error = im->im_limits(limitp); | error = im->im_limits(idl); | ||||
sx_sunlock(&sc->sc_lock); | 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); | return (error); | ||||
} | } | ||||
int | 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_conn *(*new_conn)(const char *, struct mtx *)) | ||||
{ | { | ||||
struct icl_module *im; | struct icl_module *im; | ||||
sx_xlock(&sc->sc_lock); | sx_xlock(&sc->sc_lock); | ||||
im = icl_find(offload, iser, true); | im = icl_find(offload, iser, true); | ||||
if (im != NULL) { | if (im != NULL) { | ||||
ICL_WARN("offload \"%s\" already registered", offload); | ICL_WARN("offload \"%s\" already registered", offload); | ||||
▲ Show 20 Lines • Show All 88 Lines • Show Last 20 Lines |