@@ -153,7 +153,7 @@ struct tcmu_cmd {
/* Can't use se_cmd when cleaning up expired cmds, because if
cmd has been completed then accessing se_cmd is off limits */
- uint32_t dbi_len;
+ uint32_t dbi_cnt;
uint32_t dbi_cur;
uint32_t *dbi;
@@ -255,7 +255,7 @@ static bool tcmu_get_empty_blocks(struct tcmu_dev *udev,
int i;
tcmu_cmd_reset_dbi_cur(tcmu_cmd);
- for (i = 0; i < tcmu_cmd->dbi_len; i++) {
+ for (i = 0; i < tcmu_cmd->dbi_cnt; i++) {
if (!tcmu_get_empty_block(udev, tcmu_cmd))
goto err;
}
@@ -263,7 +263,7 @@ static bool tcmu_get_empty_blocks(struct tcmu_dev *udev,
err:
pr_debug("no blocks: only %u blocks available, but ask for %u\n",
- tcmu_cmd->dbi_len, tcmu_cmd->dbi_cur);
+ tcmu_cmd->dbi_cnt, tcmu_cmd->dbi_cur);
tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cur);
udev->waiting_global = true;
return false;
@@ -286,25 +286,29 @@ static inline void tcmu_free_cmd(struct tcmu_cmd *tcmu_cmd)
kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
}
-static inline uint32_t tcmu_cmd_get_dbi_len(struct se_cmd *se_cmd)
+static inline uint32_t tcmu_cmd_get_data_length(struct se_cmd *se_cmd)
{
size_t data_length = round_up(se_cmd->data_length, DATA_BLOCK_SIZE);
- uint32_t dbi_len;
if (se_cmd->se_cmd_flags & SCF_BIDI)
data_length += round_up(se_cmd->t_bidi_data_sg->length,
DATA_BLOCK_SIZE);
- dbi_len = data_length / DATA_BLOCK_SIZE;
+ return data_length;
+}
+
+static inline uint32_t tcmu_cmd_get_dbi_cnt(struct se_cmd *se_cmd)
+{
+ size_t data_length = tcmu_cmd_get_data_length(se_cmd);
- return dbi_len;
+ return data_length / DATA_BLOCK_SIZE;
}
static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
{
struct se_device *se_dev = se_cmd->se_dev;
struct tcmu_dev *udev = TCMU_DEV(se_dev);
- uint32_t dbi_len = tcmu_cmd_get_dbi_len(se_cmd);
+ uint32_t dbi_cnt = tcmu_cmd_get_dbi_cnt(se_cmd);
struct tcmu_cmd *tcmu_cmd;
int cmd_id;
@@ -319,8 +323,8 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
msecs_to_jiffies(udev->cmd_time_out);
tcmu_cmd_reset_dbi_cur(tcmu_cmd);
- tcmu_cmd->dbi_len = dbi_len;
- tcmu_cmd->dbi = kcalloc(dbi_len, sizeof(uint32_t), GFP_KERNEL);
+ tcmu_cmd->dbi_cnt = dbi_cnt;
+ tcmu_cmd->dbi = kcalloc(dbi_cnt, sizeof(uint32_t), GFP_KERNEL);
if (!tcmu_cmd->dbi) {
kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
return NULL;
@@ -572,13 +576,27 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
return true;
}
+static inline void tcmu_cmd_get_cmd_size(struct tcmu_cmd *tcmu_cmd,
+ size_t *base_size, size_t *cmd_size)
+{
+ struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
+
+ *base_size = max(offsetof(struct tcmu_cmd_entry,
+ req.iov[tcmu_cmd->dbi_cnt]),
+ sizeof(struct tcmu_cmd_entry));
+
+ *cmd_size = round_up(scsi_command_size(se_cmd->t_task_cdb),
+ TCMU_OP_ALIGN_SIZE) + *base_size;
+ WARN_ON(*cmd_size & (TCMU_OP_ALIGN_SIZE-1));
+}
+
static sense_reason_t
tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
{
struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
size_t base_command_size, command_size;
- struct tcmu_mailbox *mb;
+ struct tcmu_mailbox *mb = udev->mb_addr;
struct tcmu_cmd_entry *entry;
struct iovec *iov;
int iov_cnt, ret;
@@ -590,6 +608,8 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags))
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ if (se_cmd->se_cmd_flags & SCF_BIDI)
+ BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
/*
* Must be a certain minimum size for response sense info, but
* also may be larger if the iov array is large.
@@ -597,33 +617,19 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
* We prepare way too many iovs for potential uses here, because it's
* expensive to tell how many regions are freed in the bitmap
*/
- base_command_size = max(offsetof(struct tcmu_cmd_entry,
- req.iov[tcmu_cmd->dbi_len]),
- sizeof(struct tcmu_cmd_entry));
- command_size = base_command_size
- + round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE);
-
- WARN_ON(command_size & (TCMU_OP_ALIGN_SIZE-1));
-
- spin_lock_irq(&udev->cmdr_lock);
-
- mb = udev->mb_addr;
- cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
- data_length = round_up(se_cmd->data_length, DATA_BLOCK_SIZE);
- if (se_cmd->se_cmd_flags & SCF_BIDI) {
- BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
- data_length += round_up(se_cmd->t_bidi_data_sg->length,
- DATA_BLOCK_SIZE);
- }
+ tcmu_cmd_get_cmd_size(tcmu_cmd, &base_command_size, &command_size);
+ data_length = tcmu_cmd_get_data_length(se_cmd);
if ((command_size > (udev->cmdr_size / 2)) ||
data_length > udev->data_size) {
pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu "
"cmd ring/data area\n", command_size, data_length,
udev->cmdr_size, udev->data_size);
- spin_unlock_irq(&udev->cmdr_lock);
return TCM_INVALID_CDB_FIELD;
}
+ spin_lock_irq(&udev->cmdr_lock);
+
+ cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
while (!is_ring_space_avail(udev, tcmu_cmd, command_size, data_length)) {
int ret;
DEFINE_WAIT(__wait);
@@ -791,7 +797,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
out:
cmd->se_cmd = NULL;
- tcmu_cmd_free_data(cmd, cmd->dbi_len);
+ tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
tcmu_free_cmd(cmd);
}