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 | 45 | #define ALIGN_SIZE 64 /* Should be enough for most CPUs */ |
| 46 | 46 | #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0) /* Out-of-order completions */ |
| 47 | 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 | 50 | struct tcmu_mailbox { |
| 50 | 51 | __u16 version; |
| @@ -62,6 +63,7 @@ struct tcmu_mailbox { · 11 unmodified lines | ||
| 62 | 63 | enum tcmu_opcode { |
| 63 | 64 | TCMU_OP_PAD = 0, |
| 64 | 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 | 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 | 156 | #define TCMU_OP_ALIGN_SIZE sizeof(__u64) |
| 132 | 157 | |
| 133 | 158 | enum tcmu_genl_cmd { |