This patch implements the tmr_notify callback for tcmu. When the callback is called, tcmu checks the list of aborted commands it received as parameter: - aborted commands in the qfull_queue are removed from the queue and target_complete_command is called - from the cmd_ids of aborted commands currently uncompleted in cmd ring it creates a list of aborted cmd_ids. Finally a TMR notification is written to cmd ring containing TMR type and cmd_id list. If there is no space in ring, the TMR notification is queued on a TMR specific queue. The TMR specific queue 'tmr_queue' can be seen as a extension of the cmd ring. At the end of each iexecution of tcmu_complete_commands() we check whether tmr_queue contains TMRs and try to move them onto the ring. If tmr_queue is not empty after that, we don't call run_qfull_queue() because commands must not overtake TMRs. This way we guarantee that cmd_ids in TMR notification received by userspace either match an active, not yet completed command or are no longer valid due to userspace having complete some cmd_ids meanwhile. New commands that were assigned to an aborted cmd_id will always appear on the cmd ring _after_ the TMR.
Showing the changes to include/uapi/linux (1 of 2 files). Show all
Unified · Split
| @@ -45,6 +45,7 @@ · 44 unmodified lines | |||
| 45 | #define ALIGN_SIZE 64 /* Should be enough for most CPUs */ | 45 | #define ALIGN_SIZE 64 /* Should be enough for most CPUs */ |
| 46 | #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0) /* Out-of-order completions */ | 46 | #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0) /* Out-of-order completions */ |
| 47 | #define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1) /* Read data length */ | 47 | #define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1) /* Read data length */ |
| 48 | #define TCMU_MAILBOX_FLAG_CAP_TMR (1 << 2) /* TMR notifications */ | ||
| 48 | 49 | ||
| 49 | struct tcmu_mailbox { | 50 | struct tcmu_mailbox { |
| 50 | __u16 version; | 51 | __u16 version; |
| @@ -62,6 +63,7 @@ struct tcmu_mailbox { · 11 unmodified lines | |||
| 62 | enum tcmu_opcode { | 63 | enum tcmu_opcode { |
| 63 | TCMU_OP_PAD = 0, | 64 | TCMU_OP_PAD = 0, |
| 64 | TCMU_OP_CMD, | 65 | TCMU_OP_CMD, |
| 66 | TCMU_OP_TMR, | ||
| 65 | }; | 67 | }; |
| 66 | 68 | ||
| 67 | /* | 69 | /* |
| @@ -128,6 +130,29 @@ struct tcmu_cmd_entry { · 60 unmodified lines | |||
| 128 | 130 | ||
| 129 | } __packed; | 131 | } __packed; |
| 130 | 132 | ||
| 133 | struct tcmu_tmr_entry { | ||
| 134 | struct tcmu_cmd_entry_hdr hdr; | ||
| 135 | |||
| 136 | #define TCMU_TMR_UNKNOWN 0 | ||
| 137 | #define TCMU_TMR_ABORT_TASK 1 | ||
| 138 | #define TCMU_TMR_ABORT_TASK_SET 2 | ||
| 139 | #define TCMU_TMR_CLEAR_ACA 3 | ||
| 140 | #define TCMU_TMR_CLEAR_TASK_SET 4 | ||
| 141 | #define TCMU_TMR_LUN_RESET 5 | ||
| 142 | #define TCMU_TMR_TARGET_WARM_RESET 6 | ||
| 143 | #define TCMU_TMR_TARGET_COLD_RESET 7 | ||
| 144 | /* Pseudo reset due to received PR OUT */ | ||
| 145 | #define TCMU_TMR_LUN_RESET_PRO 128 | ||
| 146 | __u8 tmr_type; | ||
| 147 | |||
| 148 | __u8 __pad1; | ||
| 149 | __u16 __pad2; | ||
| 150 | __u32 cmd_cnt; | ||
| 151 | __u64 __pad3; | ||
| 152 | __u64 __pad4; | ||
| 153 | __u16 cmd_ids[0]; | ||
| 154 | } __packed; | ||
| 155 | |||
| 131 | #define TCMU_OP_ALIGN_SIZE sizeof(__u64) | 156 | #define TCMU_OP_ALIGN_SIZE sizeof(__u64) |
| 132 | 157 | ||
| 133 | enum tcmu_genl_cmd { | 158 | enum tcmu_genl_cmd { |