aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/target/tcmu-design.txt43
-rw-r--r--drivers/target/target_core_user.c46
-rw-r--r--include/uapi/linux/target_core_user.h44
3 files changed, 89 insertions, 44 deletions
diff --git a/Documentation/target/tcmu-design.txt b/Documentation/target/tcmu-design.txt
index 5518465290bf..43e94ea6d2ca 100644
--- a/Documentation/target/tcmu-design.txt
+++ b/Documentation/target/tcmu-design.txt
@@ -138,27 +138,40 @@ signals the kernel via a 4-byte write(). When cmd_head equals
138cmd_tail, the ring is empty -- no commands are currently waiting to be 138cmd_tail, the ring is empty -- no commands are currently waiting to be
139processed by userspace. 139processed by userspace.
140 140
141TCMU commands start with a common header containing "len_op", a 32-bit 141TCMU commands are 8-byte aligned. They start with a common header
142value that stores the length, as well as the opcode in the lowest 142containing "len_op", a 32-bit value that stores the length, as well as
143unused bits. Currently only two opcodes are defined, TCMU_OP_PAD and 143the opcode in the lowest unused bits. It also contains cmd_id and
144TCMU_OP_CMD. When userspace encounters a command with PAD opcode, it 144flags fields for setting by the kernel (kflags) and userspace
145should skip ahead by the bytes in "length". (The kernel inserts PAD 145(uflags).
146entries to ensure each CMD entry fits contigously into the circular 146
147buffer.) 147Currently only two opcodes are defined, TCMU_OP_CMD and TCMU_OP_PAD.
148 148
149When userspace handles a CMD, it finds the SCSI CDB (Command Data 149When the opcode is CMD, the entry in the command ring is a struct
150Block) via tcmu_cmd_entry.req.cdb_off. This is an offset from the 150tcmu_cmd_entry. Userspace finds the SCSI CDB (Command Data Block) via
151start of the overall shared memory region, not the entry. The data 151tcmu_cmd_entry.req.cdb_off. This is an offset from the start of the
152in/out buffers are accessible via tht req.iov[] array. Note that 152overall shared memory region, not the entry. The data in/out buffers
153each iov.iov_base is also an offset from the start of the region. 153are accessible via tht req.iov[] array. iov_cnt contains the number of
154 154entries in iov[] needed to describe either the Data-In or Data-Out
155TCMU currently does not support BIDI operations. 155buffers. For bidirectional commands, iov_cnt specifies how many iovec
156entries cover the Data-Out area, and iov_bidi_count specifies how many
157iovec entries immediately after that in iov[] cover the Data-In
158area. Just like other fields, iov.iov_base is an offset from the start
159of the region.
156 160
157When completing a command, userspace sets rsp.scsi_status, and 161When completing a command, userspace sets rsp.scsi_status, and
158rsp.sense_buffer if necessary. Userspace then increments 162rsp.sense_buffer if necessary. Userspace then increments
159mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the 163mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
160kernel via the UIO method, a 4-byte write to the file descriptor. 164kernel via the UIO method, a 4-byte write to the file descriptor.
161 165
166When the opcode is PAD, userspace only updates cmd_tail as above --
167it's a no-op. (The kernel inserts PAD entries to ensure each CMD entry
168is contiguous within the command ring.)
169
170More opcodes may be added in the future. If userspace encounters an
171opcode it does not handle, it must set UNKNOWN_OP bit (bit 0) in
172hdr.uflags, update cmd_tail, and proceed with processing additional
173commands, if any.
174
162The Data Area: 175The Data Area:
163 176
164This is shared-memory space after the command ring. The organization 177This is shared-memory space after the command ring. The organization
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 1fbf304a9491..dbc872a6c981 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -344,8 +344,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
344 344
345 entry = (void *) mb + CMDR_OFF + cmd_head; 345 entry = (void *) mb + CMDR_OFF + cmd_head;
346 tcmu_flush_dcache_range(entry, sizeof(*entry)); 346 tcmu_flush_dcache_range(entry, sizeof(*entry));
347 tcmu_hdr_set_op(&entry->hdr, TCMU_OP_PAD); 347 tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_PAD);
348 tcmu_hdr_set_len(&entry->hdr, pad_size); 348 tcmu_hdr_set_len(&entry->hdr.len_op, pad_size);
349 entry->hdr.cmd_id = 0; /* not used for PAD */
350 entry->hdr.kflags = 0;
351 entry->hdr.uflags = 0;
349 352
350 UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size); 353 UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size);
351 354
@@ -355,9 +358,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
355 358
356 entry = (void *) mb + CMDR_OFF + cmd_head; 359 entry = (void *) mb + CMDR_OFF + cmd_head;
357 tcmu_flush_dcache_range(entry, sizeof(*entry)); 360 tcmu_flush_dcache_range(entry, sizeof(*entry));
358 tcmu_hdr_set_op(&entry->hdr, TCMU_OP_CMD); 361 tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_CMD);
359 tcmu_hdr_set_len(&entry->hdr, command_size); 362 tcmu_hdr_set_len(&entry->hdr.len_op, command_size);
360 entry->cmd_id = tcmu_cmd->cmd_id; 363 entry->hdr.cmd_id = tcmu_cmd->cmd_id;
364 entry->hdr.kflags = 0;
365 entry->hdr.uflags = 0;
361 366
362 /* 367 /*
363 * Fix up iovecs, and handle if allocation in data ring wrapped. 368 * Fix up iovecs, and handle if allocation in data ring wrapped.
@@ -407,6 +412,8 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
407 kunmap_atomic(from); 412 kunmap_atomic(from);
408 } 413 }
409 entry->req.iov_cnt = iov_cnt; 414 entry->req.iov_cnt = iov_cnt;
415 entry->req.iov_bidi_cnt = 0;
416 entry->req.iov_dif_cnt = 0;
410 417
411 /* All offsets relative to mb_addr, not start of entry! */ 418 /* All offsets relative to mb_addr, not start of entry! */
412 cdb_off = CMDR_OFF + cmd_head + base_command_size; 419 cdb_off = CMDR_OFF + cmd_head + base_command_size;
@@ -464,6 +471,17 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
464 return; 471 return;
465 } 472 }
466 473
474 if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
475 UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
476 pr_warn("TCMU: Userspace set UNKNOWN_OP flag on se_cmd %p\n",
477 cmd->se_cmd);
478 transport_generic_request_failure(cmd->se_cmd,
479 TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE);
480 cmd->se_cmd = NULL;
481 kmem_cache_free(tcmu_cmd_cache, cmd);
482 return;
483 }
484
467 if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) { 485 if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) {
468 memcpy(se_cmd->sense_buffer, entry->rsp.sense_buffer, 486 memcpy(se_cmd->sense_buffer, entry->rsp.sense_buffer,
469 se_cmd->scsi_sense_length); 487 se_cmd->scsi_sense_length);
@@ -542,14 +560,16 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
542 560
543 tcmu_flush_dcache_range(entry, sizeof(*entry)); 561 tcmu_flush_dcache_range(entry, sizeof(*entry));
544 562
545 if (tcmu_hdr_get_op(&entry->hdr) == TCMU_OP_PAD) { 563 if (tcmu_hdr_get_op(entry->hdr.len_op) == TCMU_OP_PAD) {
546 UPDATE_HEAD(udev->cmdr_last_cleaned, tcmu_hdr_get_len(&entry->hdr), udev->cmdr_size); 564 UPDATE_HEAD(udev->cmdr_last_cleaned,
565 tcmu_hdr_get_len(entry->hdr.len_op),
566 udev->cmdr_size);
547 continue; 567 continue;
548 } 568 }
549 WARN_ON(tcmu_hdr_get_op(&entry->hdr) != TCMU_OP_CMD); 569 WARN_ON(tcmu_hdr_get_op(entry->hdr.len_op) != TCMU_OP_CMD);
550 570
551 spin_lock(&udev->commands_lock); 571 spin_lock(&udev->commands_lock);
552 cmd = idr_find(&udev->commands, entry->cmd_id); 572 cmd = idr_find(&udev->commands, entry->hdr.cmd_id);
553 if (cmd) 573 if (cmd)
554 idr_remove(&udev->commands, cmd->cmd_id); 574 idr_remove(&udev->commands, cmd->cmd_id);
555 spin_unlock(&udev->commands_lock); 575 spin_unlock(&udev->commands_lock);
@@ -562,7 +582,9 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
562 582
563 tcmu_handle_completion(cmd, entry); 583 tcmu_handle_completion(cmd, entry);
564 584
565 UPDATE_HEAD(udev->cmdr_last_cleaned, tcmu_hdr_get_len(&entry->hdr), udev->cmdr_size); 585 UPDATE_HEAD(udev->cmdr_last_cleaned,
586 tcmu_hdr_get_len(entry->hdr.len_op),
587 udev->cmdr_size);
566 588
567 handled++; 589 handled++;
568 } 590 }
@@ -840,14 +862,14 @@ static int tcmu_configure_device(struct se_device *dev)
840 udev->data_size = TCMU_RING_SIZE - CMDR_SIZE; 862 udev->data_size = TCMU_RING_SIZE - CMDR_SIZE;
841 863
842 mb = udev->mb_addr; 864 mb = udev->mb_addr;
843 mb->version = 1; 865 mb->version = TCMU_MAILBOX_VERSION;
844 mb->cmdr_off = CMDR_OFF; 866 mb->cmdr_off = CMDR_OFF;
845 mb->cmdr_size = udev->cmdr_size; 867 mb->cmdr_size = udev->cmdr_size;
846 868
847 WARN_ON(!PAGE_ALIGNED(udev->data_off)); 869 WARN_ON(!PAGE_ALIGNED(udev->data_off));
848 WARN_ON(udev->data_size % PAGE_SIZE); 870 WARN_ON(udev->data_size % PAGE_SIZE);
849 871
850 info->version = "1"; 872 info->version = xstr(TCMU_MAILBOX_VERSION);
851 873
852 info->mem[0].name = "tcm-user command & data buffer"; 874 info->mem[0].name = "tcm-user command & data buffer";
853 info->mem[0].addr = (phys_addr_t) udev->mb_addr; 875 info->mem[0].addr = (phys_addr_t) udev->mb_addr;
diff --git a/include/uapi/linux/target_core_user.h b/include/uapi/linux/target_core_user.h
index b483d1909d3e..b67f99d3c520 100644
--- a/include/uapi/linux/target_core_user.h
+++ b/include/uapi/linux/target_core_user.h
@@ -6,7 +6,7 @@
6#include <linux/types.h> 6#include <linux/types.h>
7#include <linux/uio.h> 7#include <linux/uio.h>
8 8
9#define TCMU_VERSION "1.0" 9#define TCMU_VERSION "2.0"
10 10
11/* 11/*
12 * Ring Design 12 * Ring Design
@@ -39,9 +39,13 @@
39 * should process the next packet the same way, and so on. 39 * should process the next packet the same way, and so on.
40 */ 40 */
41 41
42#define TCMU_MAILBOX_VERSION 1 42#define TCMU_MAILBOX_VERSION 2
43#define ALIGN_SIZE 64 /* Should be enough for most CPUs */ 43#define ALIGN_SIZE 64 /* Should be enough for most CPUs */
44 44
45/* See https://gcc.gnu.org/onlinedocs/cpp/Stringification.html */
46#define xstr(s) str(s)
47#define str(s) #s
48
45struct tcmu_mailbox { 49struct tcmu_mailbox {
46 __u16 version; 50 __u16 version;
47 __u16 flags; 51 __u16 flags;
@@ -64,31 +68,36 @@ enum tcmu_opcode {
64 * Only a few opcodes, and length is 8-byte aligned, so use low bits for opcode. 68 * Only a few opcodes, and length is 8-byte aligned, so use low bits for opcode.
65 */ 69 */
66struct tcmu_cmd_entry_hdr { 70struct tcmu_cmd_entry_hdr {
67 __u32 len_op; 71 __u32 len_op;
72 __u16 cmd_id;
73 __u8 kflags;
74#define TCMU_UFLAG_UNKNOWN_OP 0x1
75 __u8 uflags;
76
68} __packed; 77} __packed;
69 78
70#define TCMU_OP_MASK 0x7 79#define TCMU_OP_MASK 0x7
71 80
72static inline enum tcmu_opcode tcmu_hdr_get_op(struct tcmu_cmd_entry_hdr *hdr) 81static inline enum tcmu_opcode tcmu_hdr_get_op(__u32 len_op)
73{ 82{
74 return hdr->len_op & TCMU_OP_MASK; 83 return len_op & TCMU_OP_MASK;
75} 84}
76 85
77static inline void tcmu_hdr_set_op(struct tcmu_cmd_entry_hdr *hdr, enum tcmu_opcode op) 86static inline void tcmu_hdr_set_op(__u32 *len_op, enum tcmu_opcode op)
78{ 87{
79 hdr->len_op &= ~TCMU_OP_MASK; 88 *len_op &= ~TCMU_OP_MASK;
80 hdr->len_op |= (op & TCMU_OP_MASK); 89 *len_op |= (op & TCMU_OP_MASK);
81} 90}
82 91
83static inline __u32 tcmu_hdr_get_len(struct tcmu_cmd_entry_hdr *hdr) 92static inline __u32 tcmu_hdr_get_len(__u32 len_op)
84{ 93{
85 return hdr->len_op & ~TCMU_OP_MASK; 94 return len_op & ~TCMU_OP_MASK;
86} 95}
87 96
88static inline void tcmu_hdr_set_len(struct tcmu_cmd_entry_hdr *hdr, __u32 len) 97static inline void tcmu_hdr_set_len(__u32 *len_op, __u32 len)
89{ 98{
90 hdr->len_op &= TCMU_OP_MASK; 99 *len_op &= TCMU_OP_MASK;
91 hdr->len_op |= len; 100 *len_op |= len;
92} 101}
93 102
94/* Currently the same as SCSI_SENSE_BUFFERSIZE */ 103/* Currently the same as SCSI_SENSE_BUFFERSIZE */
@@ -97,13 +106,14 @@ static inline void tcmu_hdr_set_len(struct tcmu_cmd_entry_hdr *hdr, __u32 len)
97struct tcmu_cmd_entry { 106struct tcmu_cmd_entry {
98 struct tcmu_cmd_entry_hdr hdr; 107 struct tcmu_cmd_entry_hdr hdr;
99 108
100 uint16_t cmd_id;
101 uint16_t __pad1;
102
103 union { 109 union {
104 struct { 110 struct {
111 uint32_t iov_cnt;
112 uint32_t iov_bidi_cnt;
113 uint32_t iov_dif_cnt;
105 uint64_t cdb_off; 114 uint64_t cdb_off;
106 uint64_t iov_cnt; 115 uint64_t __pad1;
116 uint64_t __pad2;
107 struct iovec iov[0]; 117 struct iovec iov[0];
108 } req; 118 } req;
109 struct { 119 struct {