Changeset View
Changeset View
Standalone View
Standalone View
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->max_recv_data_segment_length, 512, 16777215) || | |||||
OUT_OF_RANGE(idl->max_send_data_segment_length, 512, 16777215) || | |||||
OUT_OF_RANGE(idl->max_burst_length, 512, 16777215) || | |||||
OUT_OF_RANGE(idl->first_burst_length, 512, 16777215))) { | |||||
error = EINVAL; | |||||
trasz: Shouldn't this be a KASSERT? I mean, from what I understand it's the kernel code that returns… | |||||
Not Done Inline ActionsI'm going to change cxgbei in the near future to report different limits based on the type of card in the system, and maybe even have user-tunable knobs (in cxgbei, not global) to have it report different limits. np: I'm going to change cxgbei in the near future to report different limits based on the type of… | |||||
Not Done Inline ActionsOkay, but my point is: can't cxgbei, and other ICL modules, be trusted to not return invalid values to the stack? trasz: Okay, but my point is: can't cxgbei, and other ICL modules, be trusted to not return invalid… | |||||
Not Done Inline ActionsIf a driver makes these limits user-tunable within some bounds (I'm thinking of doing this eventually in cxgbei) then it makes sense to catch illegal values. The range checks could be in the driver(s) or in one central place for all. Putting them in one place is better imho. np: If a driver makes these limits user-tunable within some bounds (I'm thinking of doing this… | |||||
} | |||||
#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->first_burst_length > 0 && | |||||
idl->max_burst_length > 0 && | |||||
idl->first_burst_length > 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 |
Shouldn't this be a KASSERT? I mean, from what I understand it's the kernel code that returns those; it can be expected to provide valid ones.