diff options
-rw-r--r-- | drivers/target/target_core_user.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 70c143a5c38c..8d9f5f9c32a7 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c | |||
@@ -389,6 +389,20 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t d | |||
389 | return true; | 389 | return true; |
390 | } | 390 | } |
391 | 391 | ||
392 | static inline size_t tcmu_cmd_get_data_length(struct tcmu_cmd *tcmu_cmd) | ||
393 | { | ||
394 | struct se_cmd *se_cmd = tcmu_cmd->se_cmd; | ||
395 | size_t data_length = round_up(se_cmd->data_length, DATA_BLOCK_SIZE); | ||
396 | |||
397 | if (se_cmd->se_cmd_flags & SCF_BIDI) { | ||
398 | BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); | ||
399 | data_length += round_up(se_cmd->t_bidi_data_sg->length, | ||
400 | DATA_BLOCK_SIZE); | ||
401 | } | ||
402 | |||
403 | return data_length; | ||
404 | } | ||
405 | |||
392 | static sense_reason_t | 406 | static sense_reason_t |
393 | tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | 407 | tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) |
394 | { | 408 | { |
@@ -402,7 +416,7 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | |||
402 | uint32_t cmd_head; | 416 | uint32_t cmd_head; |
403 | uint64_t cdb_off; | 417 | uint64_t cdb_off; |
404 | bool copy_to_data_area; | 418 | bool copy_to_data_area; |
405 | size_t data_length; | 419 | size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd); |
406 | DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS); | 420 | DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS); |
407 | 421 | ||
408 | if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) | 422 | if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) |
@@ -428,11 +442,6 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | |||
428 | 442 | ||
429 | mb = udev->mb_addr; | 443 | mb = udev->mb_addr; |
430 | cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ | 444 | cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */ |
431 | data_length = se_cmd->data_length; | ||
432 | if (se_cmd->se_cmd_flags & SCF_BIDI) { | ||
433 | BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents)); | ||
434 | data_length += se_cmd->t_bidi_data_sg->length; | ||
435 | } | ||
436 | if ((command_size > (udev->cmdr_size / 2)) || | 445 | if ((command_size > (udev->cmdr_size / 2)) || |
437 | data_length > udev->data_size) { | 446 | data_length > udev->data_size) { |
438 | pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu " | 447 | pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu " |
@@ -502,11 +511,14 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd) | |||
502 | entry->req.iov_dif_cnt = 0; | 511 | entry->req.iov_dif_cnt = 0; |
503 | 512 | ||
504 | /* Handle BIDI commands */ | 513 | /* Handle BIDI commands */ |
505 | iov_cnt = 0; | 514 | if (se_cmd->se_cmd_flags & SCF_BIDI) { |
506 | alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg, | 515 | iov_cnt = 0; |
507 | se_cmd->t_bidi_data_nents, &iov, &iov_cnt, false); | 516 | iov++; |
508 | entry->req.iov_bidi_cnt = iov_cnt; | 517 | alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg, |
509 | 518 | se_cmd->t_bidi_data_nents, &iov, &iov_cnt, | |
519 | false); | ||
520 | entry->req.iov_bidi_cnt = iov_cnt; | ||
521 | } | ||
510 | /* cmd's data_bitmap is what changed in process */ | 522 | /* cmd's data_bitmap is what changed in process */ |
511 | bitmap_xor(tcmu_cmd->data_bitmap, old_bitmap, udev->data_bitmap, | 523 | bitmap_xor(tcmu_cmd->data_bitmap, old_bitmap, udev->data_bitmap, |
512 | DATA_BLOCK_BITS); | 524 | DATA_BLOCK_BITS); |