aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/target/target_core_user.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index ac37ce6be15c..9a1b314f6482 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -236,16 +236,26 @@ static inline size_t head_to_end(size_t head, size_t size)
236 * 236 *
237 * Called with ring lock held. 237 * Called with ring lock held.
238 */ 238 */
239static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_needed, size_t data_needed) 239static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t data_needed)
240{ 240{
241 struct tcmu_mailbox *mb = udev->mb_addr; 241 struct tcmu_mailbox *mb = udev->mb_addr;
242 size_t space; 242 size_t space;
243 u32 cmd_head; 243 u32 cmd_head;
244 size_t cmd_needed;
244 245
245 tcmu_flush_dcache_range(mb, sizeof(*mb)); 246 tcmu_flush_dcache_range(mb, sizeof(*mb));
246 247
247 cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ 248 cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
248 249
250 /*
251 * If cmd end-of-ring space is too small then we need space for a NOP plus
252 * original cmd - cmds are internally contiguous.
253 */
254 if (head_to_end(cmd_head, udev->cmdr_size) >= cmd_size)
255 cmd_needed = cmd_size;
256 else
257 cmd_needed = cmd_size + head_to_end(cmd_head, udev->cmdr_size);
258
249 space = spc_free(cmd_head, udev->cmdr_last_cleaned, udev->cmdr_size); 259 space = spc_free(cmd_head, udev->cmdr_last_cleaned, udev->cmdr_size);
250 if (space < cmd_needed) { 260 if (space < cmd_needed) {
251 pr_debug("no cmd space: %u %u %u\n", cmd_head, 261 pr_debug("no cmd space: %u %u %u\n", cmd_head,
@@ -268,9 +278,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
268 struct tcmu_dev *udev = tcmu_cmd->tcmu_dev; 278 struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
269 struct se_cmd *se_cmd = tcmu_cmd->se_cmd; 279 struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
270 size_t base_command_size, command_size; 280 size_t base_command_size, command_size;
271 size_t cmdr_space_needed;
272 struct tcmu_mailbox *mb; 281 struct tcmu_mailbox *mb;
273 size_t pad_size;
274 struct tcmu_cmd_entry *entry; 282 struct tcmu_cmd_entry *entry;
275 int i; 283 int i;
276 struct scatterlist *sg; 284 struct scatterlist *sg;
@@ -307,17 +315,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
307 "cmd/data ring buffers\n", command_size, tcmu_cmd->data_length, 315 "cmd/data ring buffers\n", command_size, tcmu_cmd->data_length,
308 udev->cmdr_size, udev->data_size); 316 udev->cmdr_size, udev->data_size);
309 317
310 /* 318 while (!is_ring_space_avail(udev, command_size, tcmu_cmd->data_length)) {
311 * Cmd end-of-ring space is too small so we need space for a NOP plus
312 * original cmd - cmds are internally contiguous.
313 */
314 if (head_to_end(cmd_head, udev->cmdr_size) >= command_size)
315 pad_size = 0;
316 else
317 pad_size = head_to_end(cmd_head, udev->cmdr_size);
318 cmdr_space_needed = command_size + pad_size;
319
320 while (!is_ring_space_avail(udev, cmdr_space_needed, tcmu_cmd->data_length)) {
321 int ret; 319 int ret;
322 DEFINE_WAIT(__wait); 320 DEFINE_WAIT(__wait);
323 321
@@ -338,7 +336,10 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
338 cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ 336 cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
339 } 337 }
340 338
341 if (pad_size) { 339 /* Insert a PAD if end-of-ring space is too small */
340 if (head_to_end(cmd_head, udev->cmdr_size) < command_size) {
341 size_t pad_size = head_to_end(cmd_head, udev->cmdr_size);
342
342 entry = (void *) mb + CMDR_OFF + cmd_head; 343 entry = (void *) mb + CMDR_OFF + cmd_head;
343 tcmu_flush_dcache_range(entry, sizeof(*entry)); 344 tcmu_flush_dcache_range(entry, sizeof(*entry));
344 tcmu_hdr_set_op(&entry->hdr, TCMU_OP_PAD); 345 tcmu_hdr_set_op(&entry->hdr, TCMU_OP_PAD);