55 #define SRP_MAX_I_T_IU_LEN 80 58 #define EINFO_SRP_LOGIN_REJ( reason, desc ) \ 59 __einfo_uniqify ( EINFO_EPERM, ( (reason) & 0x0f ), desc ) 60 #define EPERM_UNKNOWN \ 61 __einfo_error ( EINFO_EPERM_UNKNOWN ) 62 #define EINFO_EPERM_UNKNOWN EINFO_SRP_LOGIN_REJ ( \ 63 SRP_LOGIN_REJ_REASON_UNKNOWN, \ 64 "Unable to establish RDMA channel, no reason specified" ) 65 #define EPERM_INSUFFICIENT_RESOURCES \ 66 __einfo_error ( EINFO_EPERM_INSUFFICIENT_RESOURCES ) 67 #define EINFO_EPERM_INSUFFICIENT_RESOURCES EINFO_SRP_LOGIN_REJ ( \ 68 SRP_LOGIN_REJ_REASON_INSUFFICIENT_RESOURCES, \ 69 "Insufficient RDMA channel resources" ) 70 #define EPERM_BAD_MAX_I_T_IU_LEN \ 71 __einfo_error ( EINFO_EPERM_BAD_MAX_I_T_IU_LEN ) 72 #define EINFO_EPERM_BAD_MAX_I_T_IU_LEN EINFO_SRP_LOGIN_REJ ( \ 73 SRP_LOGIN_REJ_REASON_BAD_MAX_I_T_IU_LEN, \ 74 "Requested maximum initiator to target IU length value too large" ) 75 #define EPERM_CANNOT_ASSOCIATE \ 76 __einfo_error ( EINFO_EPERM_CANNOT_ASSOCIATE ) 77 #define EINFO_EPERM_CANNOT_ASSOCIATE EINFO_SRP_LOGIN_REJ ( \ 78 SRP_LOGIN_REJ_REASON_CANNOT_ASSOCIATE, \ 79 "Unable to associate RDMA channel with specified I_T nexus" ) 80 #define EPERM_UNSUPPORTED_BUFFER_FORMAT \ 81 __einfo_error ( EINFO_EPERM_UNSUPPORTED_BUFFER_FORMAT ) 82 #define EINFO_EPERM_UNSUPPORTED_BUFFER_FORMAT EINFO_SRP_LOGIN_REJ ( \ 83 SRP_LOGIN_REJ_REASON_UNSUPPORTED_BUFFER_FORMAT, \ 84 "One or more requested data buffer descriptor formats not supported" ) 85 #define EPERM_NO_MULTIPLE_CHANNELS \ 86 __einfo_error ( EINFO_EPERM_NO_MULTIPLE_CHANNELS ) 87 #define EINFO_EPERM_NO_MULTIPLE_CHANNELS EINFO_SRP_LOGIN_REJ ( \ 88 SRP_LOGIN_REJ_REASON_NO_MULTIPLE_CHANNELS, \ 89 "SRP target does not support multiple RDMA channels per I_T nexus" ) 90 #define EPERM_NO_MORE_CHANNELS \ 91 __einfo_error ( EINFO_EPERM_NO_MORE_CHANNELS ) 92 #define EINFO_EPERM_NO_MORE_CHANNELS EINFO_SRP_LOGIN_REJ ( \ 93 SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS, \ 94 "RDMA channel limit reached for this initiator" ) 95 #define EPERM_LOGIN_REJ( reason_nibble ) \ 96 EUNIQ ( EINFO_EPERM, (reason_nibble), EPERM_UNKNOWN, \ 97 EPERM_INSUFFICIENT_RESOURCES, EPERM_BAD_MAX_I_T_IU_LEN, \ 98 EPERM_CANNOT_ASSOCIATE, EPERM_UNSUPPORTED_BUFFER_FORMAT, \ 99 EPERM_NO_MULTIPLE_CHANNELS, EPERM_NO_MORE_CHANNELS ) 204 DBGC ( srpdev,
"SRP %p tag %08x closed: %s\n",
274 for ( i = 0 ; i < 65536 ; i++ ) {
303 login_req =
iob_put ( iobuf,
sizeof ( *login_req ) );
304 memset ( login_req, 0,
sizeof ( *login_req ) );
314 DBGC ( srpdev,
"SRP %p tag %08x LOGIN_REQ:\n", srpdev,
tag );
319 DBGC ( srpdev,
"SRP %p tag %08x could not send LOGIN_REQ: " 336 const void *
data,
size_t len ) {
340 if (
len <
sizeof ( *login_rsp ) ) {
341 DBGC ( srpdev,
"SRP %p LOGIN_RSP too short (%zd bytes)\n",
345 DBGC ( srpdev,
"SRP %p tag %08x LOGIN_RSP:\n",
351 DBGC ( srpdev,
"SRP %p logged in\n", srpdev );
368 const void *
data,
size_t len ) {
373 if (
len <
sizeof ( *login_rej ) ) {
374 DBGC ( srpdev,
"SRP %p LOGIN_REJ too short (%zd bytes)\n",
379 DBGC ( srpdev,
"SRP %p tag %08x LOGIN_REJ reason %08x:\n",
407 DBGC ( srpdev,
"SRP %p tag %08x cannot send CMD before " 408 "login completes\n", srpdev,
tag );
429 data_out =
iob_put ( iobuf,
sizeof ( *data_out ) );
439 data_in =
iob_put ( iobuf,
sizeof ( *data_in ) );
451 DBGC ( srpdev,
"SRP %p tag %08x could not send CMD: %s\n",
468 const void *
data,
size_t len ) {
472 ssize_t data_out_residual_count;
473 ssize_t data_in_residual_count;
476 if ( (
len <
sizeof ( *
rsp ) ) ||
477 (
len < (
sizeof ( *
rsp ) +
480 DBGC ( srpdev,
"SRP %p RSP too short (%zd bytes)\n",
484 DBGC2 ( srpdev,
"SRP %p tag %08x RSP stat %02x dores %08x dires " 485 "%08x valid %02x%s%s%s%s%s%s\n",
487 ntohl (
rsp->data_out_residual_count ),
499 DBGC ( srpdev,
"SRP %p tag %08x unrecognised RSP\n",
500 srpdev,
ntohl (
rsp->tag.dwords[1] ) );
508 memset ( &response, 0,
sizeof ( response ) );
510 data_out_residual_count =
ntohl (
rsp->data_out_residual_count );
511 data_in_residual_count =
ntohl (
rsp->data_in_residual_count );
513 response.
overrun = data_out_residual_count;
515 response.
overrun = -(data_out_residual_count);
517 response.
overrun = data_in_residual_count;
519 response.
overrun = -(data_in_residual_count);
545 const void *
data,
size_t len ) {
548 DBGC ( srpdev,
"SRP %p tag %08x unrecognised IU type %02x:\n",
587 srpcmd =
zalloc (
sizeof ( *srpcmd ) );
631 if (
iob_len ( iobuf ) <
sizeof ( *common ) ) {
632 DBGC ( srpdev,
"SRP %p IU too short (%zd bytes)\n",
662 DBGC ( srpdev,
"SRP %p closing due to received IU (%s):\n",
677 return ( srpdev->
logged_in ? ~( (
size_t ) 0 ) : 0 );
721 srpdev =
zalloc (
sizeof ( *srpdev ) );
731 DBGC ( srpdev,
"SRP %p %08x%08x%08x%08x->%08x%08x%08x%08x\n", srpdev,
746 DBGC ( srpdev,
"SRP %p could not create SCSI device: %s\n",
static void srpdev_close(struct srp_device *srpdev, int rc)
Close SRP device.
void scsi_parse_sense(const void *data, size_t len, struct scsi_sns_descriptor *sense)
Parse SCSI sense data.
union srp_port_id initiator
Initiator port identifier.
#define EINVAL
Invalid argument.
An object interface operation.
#define SRP_LOGIN_REQ_FMT_DDBD
Require direct data buffer descriptor format.
struct arbelprm_rc_send_wqe rc
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
void intf_close(struct interface *intf, int rc)
Close an object interface.
#define iob_put(iobuf, len)
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
uint8_t type
Information unit type.
struct refcnt refcnt
Reference count.
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
SRP information unit common fields.
#define EBUSY
Device or resource busy.
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.
#define SRP_RSP
Type of an SRP SCSI response.
An SRP login request information unit.
#define SRP_TAG_MAGIC
SRP tag magic marker.
#define SRP_MAX_I_T_IU_LEN
Maximum length of any initiator-to-target IU that we will send.
struct srp_device * srpdev
SRP device.
#define FEATURE_PROTOCOL
Network protocols.
uint64_t address
Virtual address.
#define list_add(new, head)
Add a new entry to the head of a list.
static struct interface_descriptor srpdev_socket_desc
SRP device socket interface descriptor.
#define ref_init(refcnt, free)
Initialise a reference counter.
static struct interface_operation srpcmd_scsi_op[]
SRP command SCSI interface operations.
#define SRP_RSP_VALID_DIUNDER
Data-in residual count field is valid and represents an underflow.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
uint32_t type
Operating system type.
#define EADDRINUSE
Address already in use.
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
#define SRP_LOGIN_REJ
Type of an SRP login rejection.
#define SRP_RSP_VALID_SNSVALID
Sense data list length field is valid.
static void srpdev_put(struct srp_device *srpdev)
Drop reference to SRP device.
#define ENOENT
No such file or directory.
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
static int srpdev_scsi_command(struct srp_device *srpdev, struct interface *parent, struct scsi_cmd *command)
Issue SRP SCSI command.
#define SRP_LOGIN_REJ_REASON_DEFINED(reason)
SRP login rejection reason is defined.
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
#define EACCES
Permission denied.
#define SRP_RSP_VALID_DOOVER
Data-out residual count field is valid and represents an overflow.
int scsi_open(struct interface *block, struct interface *scsi, struct scsi_lun *lun)
Open SCSI device.
struct list_head list
List of active commands.
size_t xfer_window(struct interface *intf)
Check flow control window.
#define DHCP_EB_FEATURE_SRP
SRP protocol.
static int srp_login_rsp(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP login response.
#define ENOTSUP
Operation not supported.
A doubly-linked list entry (or list head)
Data transfer interfaces.
#define list_empty(list)
Test whether a list is empty.
static void srpcmd_put(struct srp_command *srpcmd)
Drop reference to SRP command.
struct list_head commands
List of active commands.
#define SRP_CMD_DI_FMT_DIRECT
Direct data-in buffer format.
#define list_del(list)
Delete an entry from a list.
#define SRP_CMD
Type of an SRP SCSI command.
#define SRP_LOGIN_RSP
Type of an SRP login response.
#define ENOMEM
Not enough space.
static void srpcmd_free(struct refcnt *refcnt)
Free SRP command.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static struct interface_operation srpdev_scsi_op[]
SRP device SCSI interface operations.
#define SRP_CMD_DO_FMT_DIRECT
Direct data-out buffer format.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
A SCSI response information unit.
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
#define __unused
Declare a variable or data structure as unused.
static size_t srp_rsp_sense_data_len(const struct srp_rsp *rsp)
Get length of sense data portion of SCSI response.
static struct interface_descriptor srpcmd_scsi_desc
SRP command SCSI interface descriptor.
uint8_t lun
Logical Unit Number.
static int srp_unrecognised(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP unrecognised response IU.
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
static int srp_new_tag(struct srp_device *srpdev)
Choose an SRP command tag.
uint32_t handle
Memory handle.
static struct srp_command * srp_find_tag(struct srp_device *srpdev, uint32_t tag)
Identify SRP command by tag.
static size_t srp_rsp_response_data_len(const struct srp_rsp *rsp)
Get length of response data portion of SCSI response.
An object interface descriptor.
char * strerror(int errno)
Retrieve string representation of error number.
static void(* free)(struct refcnt *refcnt))
void * zalloc(size_t size)
Allocate cleared memory.
uint32_t memory_handle
RDMA memory handle.
#define ref_get(refcnt)
Get additional reference to object.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
uint8_t status
SCSI status code.
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
static int srp_cmd(struct srp_device *srpdev, struct scsi_cmd *command, uint32_t tag)
Transmit SRP SCSI command.
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
static int srp_login_rej(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP login rejection.
#define SCSI_CDB_DATA(cdb)
printf() parameters for dumping a scsi_cdb
static struct interface_descriptor srpdev_scsi_desc
SRP device SCSI interface descriptor.
union srp_port_id target
Target port identifier.
uint16_t required_buffer_formats
Required buffer formats.
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.
struct ib_cm_common common
struct interface scsi
SCSI command interface.
static size_t srpdev_window(struct srp_device *srpdev)
Check SRP device flow-control window.
static struct srp_device * srpdev_get(struct srp_device *srpdev)
Get reference to SRP device.
struct refcnt refcnt
Reference count.
void scsi_response(struct interface *intf, struct scsi_rsp *response)
Report SCSI response.
A SCSI command information unit.
static int srp_rsp(struct srp_device *srpdev, const void *data, size_t len)
Receive SRP SCSI response.
#define INIT_LIST_HEAD(list)
Initialise a list head.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
struct interface scsi
SCSI command issuing interface.
int logged_in
Login completed successfully.
#define SCSI_CDB_FORMAT
printf() format for dumping a scsi_cdb
uint8_t block[3][8]
DES-encrypted blocks.
#define SRP_RSP_VALID_DOUNDER
Data-out residual count field is valid and represents an underflow.
struct scsi_sns_descriptor sense
Autosense data (if any)
void * data
Start of data.
#define SRP_RSP_VALID_DIOVER
Data-in residual count field is valid and represents an overflow.
struct interface socket
Underlying data transfer interface.
static struct interface_operation srpdev_socket_op[]
SRP device socket interface operations.
#define cpu_to_be64(value)
uint8_t data[48]
Additional event data.
uint16_t reason
Rejection reason.
An SRP memory descriptor.
static int srpdev_deliver(struct srp_device *srpdev, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive data from SRP socket.
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
static struct srp_command * srpcmd_get(struct srp_command *srpcmd)
Get reference to SRP command.
#define EPERM_LOGIN_REJ(reason_nibble)
#define SRP_LOGIN_REQ
Type of an SRP login request.
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
uint64_t tag
Identity tag.
uint32_t max_i_t_iu_len
Requested maximum initiator to target IU length.
#define NULL
NULL pointer (VOID *)
FEATURE(FEATURE_PROTOCOL, "SRP", DHCP_EB_FEATURE_SRP, 1)
#define SRP_RSP_VALID_RSPVALID
Response data list length field is valid.
static void srpcmd_close(struct srp_command *srpcmd, int rc)
Close SRP command.
static const void * srp_rsp_sense_data(const struct srp_rsp *rsp)
Get sense data portion of SCSI response.
ssize_t overrun
Data overrun (or negative underrun)
#define ref_put(refcnt)
Drop reference to object.
void * memset(void *dest, int character, size_t len) __nonnull