diff options
| -rw-r--r-- | drivers/target/target_core_user.c | 31 |
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 | */ |
| 239 | static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_needed, size_t data_needed) | 239 | static 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); |
