56#define SRP_MAX_I_T_IU_LEN 80
59#define EINFO_SRP_LOGIN_REJ( reason, desc ) \
60 __einfo_uniqify ( EINFO_EPERM, ( (reason) & 0x0f ), desc )
61#define EPERM_UNKNOWN \
62 __einfo_error ( EINFO_EPERM_UNKNOWN )
63#define EINFO_EPERM_UNKNOWN EINFO_SRP_LOGIN_REJ ( \
64 SRP_LOGIN_REJ_REASON_UNKNOWN, \
65 "Unable to establish RDMA channel, no reason specified" )
66#define EPERM_INSUFFICIENT_RESOURCES \
67 __einfo_error ( EINFO_EPERM_INSUFFICIENT_RESOURCES )
68#define EINFO_EPERM_INSUFFICIENT_RESOURCES EINFO_SRP_LOGIN_REJ ( \
69 SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES, \
70 "Insufficient RDMA channel resources" )
71#define EPERM_BAD_MAX_I_T_IU_LEN \
72 __einfo_error ( EINFO_EPERM_BAD_MAX_I_T_IU_LEN )
73#define EINFO_EPERM_BAD_MAX_I_T_IU_LEN EINFO_SRP_LOGIN_REJ ( \
74 SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN, \
75 "Requested maximum initiator to target IU length value too large" )
76#define EPERM_CANNOT_ASSOCIATE \
77 __einfo_error ( EINFO_EPERM_CANNOT_ASSOCIATE )
78#define EINFO_EPERM_CANNOT_ASSOCIATE EINFO_SRP_LOGIN_REJ ( \
79 SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE, \
80 "Unable to associate RDMA channel with specified I_T nexus" )
81#define EPERM_UNSUPPORTED_BUFFER_FORMAT \
82 __einfo_error ( EINFO_EPERM_UNSUPPORTED_BUFFER_FORMAT )
83#define EINFO_EPERM_UNSUPPORTED_BUFFER_FORMAT EINFO_SRP_LOGIN_REJ ( \
84 SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT, \
85 "One or more requested data buffer descriptor formats not supported" )
86#define EPERM_NO_MULTIPLE_CHANNELS \
87 __einfo_error ( EINFO_EPERM_NO_MULTIPLE_CHANNELS )
88#define EINFO_EPERM_NO_MULTIPLE_CHANNELS EINFO_SRP_LOGIN_REJ ( \
89 SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS, \
90 "SRP target does not support multiple RDMA channels per I_T nexus" )
91#define EPERM_NO_MORE_CHANNELS \
92 __einfo_error ( EINFO_EPERM_NO_MORE_CHANNELS )
93#define EINFO_EPERM_NO_MORE_CHANNELS EINFO_SRP_LOGIN_REJ ( \
94 SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS, \
95 "RDMA channel limit reached for this initiator" )
96#define EPERM_LOGIN_REJ( reason_nibble ) \
97 EUNIQ ( EINFO_EPERM, (reason_nibble), EPERM_UNKNOWN, \
98 EPERM_INSUFFICIENT_RESOURCES, EPERM_BAD_MAX_I_T_IU_LEN, \
99 EPERM_CANNOT_ASSOCIATE, EPERM_UNSUPPORTED_BUFFER_FORMAT, \
100 EPERM_NO_MULTIPLE_CHANNELS, EPERM_NO_MORE_CHANNELS )
205 DBGC ( srpdev,
"SRP %p tag %08x closed: %s\n",
275 for ( i = 0 ; i < 65536 ; i++ ) {
304 login_req =
iob_put ( iobuf,
sizeof ( *login_req ) );
305 memset ( login_req, 0,
sizeof ( *login_req ) );
315 DBGC ( srpdev,
"SRP %p tag %08x LOGIN_REQ:\n", srpdev,
tag );
320 DBGC ( srpdev,
"SRP %p tag %08x could not send LOGIN_REQ: "
337 const void *
data,
size_t len ) {
341 if (
len <
sizeof ( *login_rsp ) ) {
342 DBGC ( srpdev,
"SRP %p LOGIN_RSP too short (%zd bytes)\n",
347 DBGC ( srpdev,
"SRP %p tag %08x LOGIN_RSP:\n",
353 DBGC ( srpdev,
"SRP %p logged in\n", srpdev );
370 const void *
data,
size_t len ) {
375 if (
len <
sizeof ( *login_rej ) ) {
376 DBGC ( srpdev,
"SRP %p LOGIN_REJ too short (%zd bytes)\n",
382 DBGC ( srpdev,
"SRP %p tag %08x LOGIN_REJ reason %08x:\n",
410 DBGC ( srpdev,
"SRP %p tag %08x cannot send CMD before "
411 "login completes\n", srpdev,
tag );
432 data_out =
iob_put ( iobuf,
sizeof ( *data_out ) );
442 data_in =
iob_put ( iobuf,
sizeof ( *data_in ) );
454 DBGC ( srpdev,
"SRP %p tag %08x could not send CMD: %s\n",
471 const void *
data,
size_t len ) {
475 const void *response_data;
476 const void *sense_data;
477 size_t response_data_len;
478 size_t sense_data_len;
480 ssize_t data_out_residual_count;
481 ssize_t data_in_residual_count;
485 if ( remaining <
sizeof ( *
rsp ) ) {
486 DBGC ( srpdev,
"SRP %p RSP too short (%zd bytes)\n",
491 remaining -=
sizeof ( *rsp );
492 DBGC2 ( srpdev,
"SRP %p tag %08x RSP stat %02x dores %08x dires "
493 "%08x valid %02x%s%s%s%s%s%s\n",
495 ntohl (
rsp->data_out_residual_count ),
506 if ( remaining < response_data_len ) {
507 DBGC ( srpdev,
"SRP %p RSP overlength response data\n",
512 if ( response_data ) {
513 DBGC2 ( srpdev,
"SRP %p response data:\n", srpdev );
514 DBGC2_HDA ( srpdev, 0, response_data, response_data_len );
516 remaining -= response_data_len;
520 if ( remaining < sense_data_len ) {
521 DBGC ( srpdev,
"SRP %p RSP overlength sense data\n",
527 DBGC2 ( srpdev,
"SRP %p sense data:\n", srpdev );
528 DBGC2_HDA ( srpdev, 0, sense_data, sense_data_len );
530 remaining -= sense_data_len;
535 DBGC ( srpdev,
"SRP %p tag %08x unrecognised RSP\n",
536 srpdev,
ntohl (
rsp->tag.dwords[1] ) );
544 memset ( &response, 0,
sizeof ( response ) );
546 data_out_residual_count =
ntohl (
rsp->data_out_residual_count );
547 data_in_residual_count =
ntohl (
rsp->data_in_residual_count );
549 response.
overrun = data_out_residual_count;
551 response.
overrun = -(data_out_residual_count);
553 response.
overrun = data_in_residual_count;
555 response.
overrun = -(data_in_residual_count);
580 const void *
data,
size_t len ) {
583 DBGC ( srpdev,
"SRP %p tag %08x unrecognised IU type %02x:\n",
622 srpcmd =
zalloc (
sizeof ( *srpcmd ) );
667 DBGC ( srpdev,
"SRP %p IU too short (%zd bytes)\n",
698 DBGC ( srpdev,
"SRP %p closing due to received IU (%s):\n",
713 return ( srpdev->
logged_in ? ~( (
size_t ) 0 ) : 0 );
757 srpdev =
zalloc (
sizeof ( *srpdev ) );
767 DBGC ( srpdev,
"SRP %p %08x%08x%08x%08x->%08x%08x%08x%08x\n", srpdev,
782 DBGC ( srpdev,
"SRP %p could not create SCSI device: %s\n",
#define NULL
NULL pointer (VOID *).
struct arbelprm_rc_send_wqe rc
#define assert(condition)
Assert a condition at run-time.
uint64_t tag
Identity tag.
uint8_t lun
Logical Unit Number.
uint32_t type
Operating system type.
uint8_t data[48]
Additional event data.
uint8_t meta
Metadata flags.
#define __unused
Declare a variable or data structure as unused.
#define DHCP_EB_FEATURE_SRP
SRP protocol.
#define FEATURE_PROTOCOL
Network protocols.
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
#define ENOENT
No such file or directory.
#define EINVAL
Invalid argument.
#define EADDRINUSE
Address already in use.
#define ENOMEM
Not enough space.
#define EBUSY
Device or resource busy.
#define ENOTSUP
Operation not supported.
#define EACCES
Permission denied.
#define SCSI_CDB_DATA(cdb)
printf() parameters for dumping a scsi_cdb
#define SCSI_CDB_FORMAT
printf() format for dumping a scsi_cdb
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
struct ib_cm_common common
uint16_t reason
Rejection reason.
#define cpu_to_be64(value)
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void intf_close(struct interface *intf, int rc)
Close an object interface.
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
#define iob_put(iobuf, len)
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
#define FEATURE(category, text, feature_opt, version)
Declare a feature.
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
#define list_del(list)
Delete an entry from a list.
#define INIT_LIST_HEAD(list)
Initialise a list head.
#define list_empty(list)
Test whether a list is empty.
#define list_add(new, head)
Add a new entry to the head of a list.
void * zalloc(size_t size)
Allocate cleared memory.
uint8_t block[3][8]
DES-encrypted blocks.
static void(* free)(struct refcnt *refcnt))
#define ref_get(refcnt)
Get additional reference to object.
#define ref_put(refcnt)
Drop reference to object.
#define ref_init(refcnt, free)
Initialise a reference counter.
int scsi_open(struct interface *block, struct interface *scsi, struct scsi_lun *lun)
Open SCSI device.
void scsi_response(struct interface *intf, struct scsi_rsp *response)
Report SCSI response.
void scsi_parse_sense(const void *data, size_t len, struct scsi_sns_descriptor *sense)
Parse SCSI sense data.
static struct interface_descriptor srpdev_scsi_desc
SRP device SCSI interface descriptor.
static int srp_cmd(struct srp_device *srpdev, struct scsi_cmd *command, uint32_t tag)
Transmit SRP SCSI command.
static struct srp_device * srpdev_get(struct srp_device *srpdev)
Get reference to SRP device.
static struct srp_command * srpcmd_get(struct srp_command *srpcmd)
Get reference to SRP command.
static int srp_login(struct srp_device *srpdev, union srp_port_id *initiator, union srp_port_id *target, uint32_t tag)
Transmit SRP login request.
static struct srp_command * srp_find_tag(struct srp_device *srpdev, uint32_t tag)
Identify SRP command by tag.
static struct interface_operation srpdev_scsi_op[]
SRP device SCSI interface operations.
static int srp_login_rej(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP login rejection.
static int srpdev_deliver(struct srp_device *srpdev, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive data from SRP socket.
#define SRP_MAX_I_T_IU_LEN
Maximum length of any initiator-to-target IU that we will send.
static void srpcmd_free(struct refcnt *refcnt)
Free SRP command.
static size_t srpdev_window(struct srp_device *srpdev)
Check SRP device flow-control window.
static int srp_login_rsp(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP login response.
static int srp_unrecognised(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP unrecognised response IU.
static void srpdev_put(struct srp_device *srpdev)
Drop reference to SRP device.
static struct interface_operation srpcmd_scsi_op[]
SRP command SCSI interface operations.
static struct interface_descriptor srpdev_socket_desc
SRP device socket interface descriptor.
static void srpcmd_close(struct srp_command *srpcmd, int rc)
Close SRP command.
static void srpcmd_put(struct srp_command *srpcmd)
Drop reference to SRP command.
static void srpdev_close(struct srp_device *srpdev, int rc)
Close SRP device.
#define EPERM_LOGIN_REJ(reason_nibble)
static struct interface_operation srpdev_socket_op[]
SRP device socket interface operations.
static int srp_rsp(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP SCSI response.
int srp_open(struct interface *block, struct interface *socket, union srp_port_id *initiator, union srp_port_id *target, uint32_t memory_handle, struct scsi_lun *lun)
Open SRP device.
static int srpdev_scsi_command(struct srp_device *srpdev, struct interface *parent, struct scsi_cmd *command)
Issue SRP SCSI command.
static int srp_new_tag(struct srp_device *srpdev)
Choose an SRP command tag.
static struct interface_descriptor srpcmd_scsi_desc
SRP command SCSI interface descriptor.
#define SRP_LOGIN_REQ
Type of an SRP login request.
#define SRP_LOGIN_REJ
Type of an SRP login rejection.
#define SRP_TAG_MAGIC
SRP tag magic marker.
#define SRP_LOGIN_REJ_REASON_DEFINED(reason)
SRP login rejection reason is defined.
#define SRP_RSP_VALID_DOOVER
Data-out residual count field is valid and represents an overflow.
#define SRP_RSP_VALID_SNSVALID
Sense data list length field is valid.
static const void * srp_rsp_sense_data(const struct srp_rsp *rsp)
Get sense data portion of SCSI response.
#define SRP_RSP
Type of an SRP SCSI response.
#define SRP_RSP_VALID_DOUNDER
Data-out residual count field is valid and represents an underflow.
#define SRP_RSP_VALID_RSPVALID
Response data list length field is valid.
#define SRP_RSP_VALID_DIOVER
Data-in residual count field is valid and represents an overflow.
#define SRP_LOGIN_REQ_FMT_DDBD
Require direct data buffer descriptor format.
static size_t srp_rsp_response_data_len(const struct srp_rsp *rsp)
Get length of response data portion of SCSI response.
#define SRP_CMD
Type of an SRP SCSI command.
#define SRP_CMD_DI_FMT_DIRECT
Direct data-in buffer format.
#define SRP_RSP_VALID_DIUNDER
Data-in residual count field is valid and represents an underflow.
#define SRP_CMD_DO_FMT_DIRECT
Direct data-out buffer format.
#define SRP_LOGIN_RSP
Type of an SRP login response.
static const void * srp_rsp_response_data(const struct srp_rsp *rsp)
Get response data portion of SCSI response.
static size_t srp_rsp_sense_data_len(const struct srp_rsp *rsp)
Get length of sense data portion of SCSI response.
#define container_of(ptr, type, field)
Get containing structure.
char * strerror(int errno)
Retrieve string representation of error number.
An object interface descriptor.
An object interface operation.
void * data
Start of data.
A doubly-linked list entry (or list head).
A SCSI command information unit.
A SCSI response information unit.
struct scsi_sns_descriptor sense
Autosense data (if any).
uint8_t status
SCSI status code.
ssize_t overrun
Data overrun (or negative underrun).
struct list_head list
List of active commands.
struct refcnt refcnt
Reference count.
struct srp_device * srpdev
SRP device.
struct interface scsi
SCSI command interface.
SRP information unit common fields.
uint32_t memory_handle
RDMA memory handle.
struct interface socket
Underlying data transfer interface.
int logged_in
Login completed successfully.
struct refcnt refcnt
Reference count.
struct interface scsi
SCSI command issuing interface.
struct list_head commands
List of active commands.
An SRP login request information unit.
union srp_port_id target
Target port identifier.
uint16_t required_buffer_formats
Required buffer formats.
union srp_port_id initiator
Initiator port identifier.
uint8_t type
Information unit type.
uint32_t max_i_t_iu_len
Requested maximum initiator to target IU length.
An SRP memory descriptor.
uint64_t address
Virtual address.
uint32_t handle
Memory handle.
size_t xfer_window(struct interface *intf)
Check flow control window.
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Data transfer interfaces.