* [PATCH] sed-opal: Add STACK_RESET command
@ 2026-03-10 9:53 Milan Broz
2026-03-11 12:49 ` Ondrej Kozina
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Milan Broz @ 2026-03-10 9:53 UTC (permalink / raw)
To: linux-block; +Cc: jonathan.derrick, axboe, okozina, Milan Broz
The TCG Opal device could enter a state where no new session can be
created, blocking even Discovery or PSID reset. While a power cycle
or waiting for the timeout should work, there is another possibility
for recovery: using the Stack Reset command.
The Stack Reset command is defined in the TCG Storage Architecture Core
Specification and is mandatory for all Opal devices (see Section 3.3.6
of the Opal SSC specification).
This patch implements the Stack Reset command. Sending it should clear
all active sessions immediately, allowing subsequent commands to run
successfully. While it is a TCG transport layer command, the Linux
kernel implements only Opal ioctls, so it makes sense to use the
IOC_OPAL ioctl interface.
The Stack Reset takes no arguments; the response can be success or pending.
If the command reports a pending state, userspace can try to repeat it;
in this case, the code returns -EBUSY.
Signed-off-by: Milan Broz <gmazyland@gmail.com>
---
block/opal_proto.h | 20 +++++++++++++++
block/sed-opal.c | 47 +++++++++++++++++++++++++++++++++++
include/linux/sed-opal.h | 1 +
include/uapi/linux/sed-opal.h | 1 +
4 files changed, 69 insertions(+)
diff --git a/block/opal_proto.h b/block/opal_proto.h
index d138785b8198..7c24247aa186 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -19,6 +19,7 @@
enum {
TCG_SECP_00 = 0,
TCG_SECP_01,
+ TCG_SECP_02,
};
/*
@@ -273,6 +274,25 @@ struct opal_header {
struct opal_data_subpacket subpkt;
};
+/*
+ * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
+ * Section: 3.3.4.7.5 STACK_RESET
+ */
+#define OPAL_STACK_RESET 0x0002
+
+struct opal_stack_reset {
+ u8 extendedComID[4];
+ __be32 request_code;
+};
+
+struct opal_stack_reset_response {
+ u8 extendedComID[4];
+ __be32 request_code;
+ u8 reserved0[2];
+ __be16 data_length;
+ __be32 response;
+};
+
#define FC_TPER 0x0001
#define FC_LOCKING 0x0002
#define FC_GEOMETRY 0x0003
diff --git a/block/sed-opal.c b/block/sed-opal.c
index c34d19e91201..79b290d9458a 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -3545,6 +3545,50 @@ static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opa
return ret;
}
+static int opal_stack_reset(struct opal_dev *dev)
+{
+ struct opal_stack_reset *req;
+ struct opal_stack_reset_response *resp;
+ int ret;
+
+ mutex_lock(&dev->dev_lock);
+
+ memset(dev->cmd, 0, IO_BUFFER_LENGTH);
+ req = (struct opal_stack_reset *)dev->cmd;
+ req->extendedComID[0] = dev->comid >> 8;
+ req->extendedComID[1] = dev->comid & 0xFF;
+ req->request_code = cpu_to_be32(OPAL_STACK_RESET);
+
+ ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
+ dev->cmd, IO_BUFFER_LENGTH, true);
+ if (ret) {
+ pr_debug("Error sending stack reset: %d\n", ret);
+ goto out;
+ }
+
+ memset(dev->resp, 0, IO_BUFFER_LENGTH);
+ ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
+ dev->resp, IO_BUFFER_LENGTH, false);
+ if (ret) {
+ pr_debug("Error receiving stack reset response: %d\n", ret);
+ goto out;
+ }
+
+ resp = (struct opal_stack_reset_response *)dev->resp;
+ if (be16_to_cpu(resp->data_length) != 4) {
+ pr_debug("Stack reset pending\n");
+ ret = -EBUSY;
+ goto out;
+ }
+ if (be32_to_cpu(resp->response) != 0) {
+ pr_debug("Stack reset failed: %u\n", be32_to_cpu(resp->response));
+ ret = -EIO;
+ }
+out:
+ mutex_unlock(&dev->dev_lock);
+ return ret;
+}
+
int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
{
void *p;
@@ -3642,6 +3686,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_GET_SUM_STATUS:
ret = opal_get_sum_ranges(dev, p, arg);
break;
+ case IOC_OPAL_STACK_RESET:
+ ret = opal_stack_reset(dev);
+ break;
default:
break;
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index aa006edb612b..0630430cc01a 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -57,6 +57,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_LR_SET_START_LEN:
case IOC_OPAL_ENABLE_DISABLE_LR:
case IOC_OPAL_GET_SUM_STATUS:
+ case IOC_OPAL_STACK_RESET:
return true;
}
return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 9830298ec51c..ef4d3be6ca7f 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -245,5 +245,6 @@ struct opal_revert_lsp {
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
#define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
+#define IOC_OPAL_STACK_RESET _IO('p', 246)
#endif /* _UAPI_SED_OPAL_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] sed-opal: Add STACK_RESET command
2026-03-10 9:53 [PATCH] sed-opal: Add STACK_RESET command Milan Broz
@ 2026-03-11 12:49 ` Ondrej Kozina
2026-03-31 11:59 ` Milan Broz
2026-03-31 13:07 ` Jens Axboe
2 siblings, 0 replies; 4+ messages in thread
From: Ondrej Kozina @ 2026-03-11 12:49 UTC (permalink / raw)
To: linux-block; +Cc: jonathan.derrick, axboe, Milan Broz
On 10/03/2026 10:53, Milan Broz wrote:
Reviewed-by: Ondrej Kozina <okozina@redhat.com>
With regards
Ondrej
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] sed-opal: Add STACK_RESET command
2026-03-10 9:53 [PATCH] sed-opal: Add STACK_RESET command Milan Broz
2026-03-11 12:49 ` Ondrej Kozina
@ 2026-03-31 11:59 ` Milan Broz
2026-03-31 13:07 ` Jens Axboe
2 siblings, 0 replies; 4+ messages in thread
From: Milan Broz @ 2026-03-31 11:59 UTC (permalink / raw)
To: axboe; +Cc: jonathan.derrick, okozina, linux-block
On 3/10/26 10:53 AM, Milan Broz wrote:
> The TCG Opal device could enter a state where no new session can be
> created, blocking even Discovery or PSID reset. While a power cycle
> or waiting for the timeout should work, there is another possibility
> for recovery: using the Stack Reset command.
Hi Jens,
is there any chance to merge this for 7.1 (so it goes together with other
Opal changes)?
Thanks,
Milan
>
> The Stack Reset command is defined in the TCG Storage Architecture Core
> Specification and is mandatory for all Opal devices (see Section 3.3.6
> of the Opal SSC specification).
>
> This patch implements the Stack Reset command. Sending it should clear
> all active sessions immediately, allowing subsequent commands to run
> successfully. While it is a TCG transport layer command, the Linux
> kernel implements only Opal ioctls, so it makes sense to use the
> IOC_OPAL ioctl interface.
>
> The Stack Reset takes no arguments; the response can be success or pending.
> If the command reports a pending state, userspace can try to repeat it;
> in this case, the code returns -EBUSY.
>
> Signed-off-by: Milan Broz <gmazyland@gmail.com>
> ---
> block/opal_proto.h | 20 +++++++++++++++
> block/sed-opal.c | 47 +++++++++++++++++++++++++++++++++++
> include/linux/sed-opal.h | 1 +
> include/uapi/linux/sed-opal.h | 1 +
> 4 files changed, 69 insertions(+)
>
> diff --git a/block/opal_proto.h b/block/opal_proto.h
> index d138785b8198..7c24247aa186 100644
> --- a/block/opal_proto.h
> +++ b/block/opal_proto.h
> @@ -19,6 +19,7 @@
> enum {
> TCG_SECP_00 = 0,
> TCG_SECP_01,
> + TCG_SECP_02,
> };
>
> /*
> @@ -273,6 +274,25 @@ struct opal_header {
> struct opal_data_subpacket subpkt;
> };
>
> +/*
> + * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
> + * Section: 3.3.4.7.5 STACK_RESET
> + */
> +#define OPAL_STACK_RESET 0x0002
> +
> +struct opal_stack_reset {
> + u8 extendedComID[4];
> + __be32 request_code;
> +};
> +
> +struct opal_stack_reset_response {
> + u8 extendedComID[4];
> + __be32 request_code;
> + u8 reserved0[2];
> + __be16 data_length;
> + __be32 response;
> +};
> +
> #define FC_TPER 0x0001
> #define FC_LOCKING 0x0002
> #define FC_GEOMETRY 0x0003
> diff --git a/block/sed-opal.c b/block/sed-opal.c
> index c34d19e91201..79b290d9458a 100644
> --- a/block/sed-opal.c
> +++ b/block/sed-opal.c
> @@ -3545,6 +3545,50 @@ static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opa
> return ret;
> }
>
> +static int opal_stack_reset(struct opal_dev *dev)
> +{
> + struct opal_stack_reset *req;
> + struct opal_stack_reset_response *resp;
> + int ret;
> +
> + mutex_lock(&dev->dev_lock);
> +
> + memset(dev->cmd, 0, IO_BUFFER_LENGTH);
> + req = (struct opal_stack_reset *)dev->cmd;
> + req->extendedComID[0] = dev->comid >> 8;
> + req->extendedComID[1] = dev->comid & 0xFF;
> + req->request_code = cpu_to_be32(OPAL_STACK_RESET);
> +
> + ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
> + dev->cmd, IO_BUFFER_LENGTH, true);
> + if (ret) {
> + pr_debug("Error sending stack reset: %d\n", ret);
> + goto out;
> + }
> +
> + memset(dev->resp, 0, IO_BUFFER_LENGTH);
> + ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
> + dev->resp, IO_BUFFER_LENGTH, false);
> + if (ret) {
> + pr_debug("Error receiving stack reset response: %d\n", ret);
> + goto out;
> + }
> +
> + resp = (struct opal_stack_reset_response *)dev->resp;
> + if (be16_to_cpu(resp->data_length) != 4) {
> + pr_debug("Stack reset pending\n");
> + ret = -EBUSY;
> + goto out;
> + }
> + if (be32_to_cpu(resp->response) != 0) {
> + pr_debug("Stack reset failed: %u\n", be32_to_cpu(resp->response));
> + ret = -EIO;
> + }
> +out:
> + mutex_unlock(&dev->dev_lock);
> + return ret;
> +}
> +
> int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
> {
> void *p;
> @@ -3642,6 +3686,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
> case IOC_OPAL_GET_SUM_STATUS:
> ret = opal_get_sum_ranges(dev, p, arg);
> break;
> + case IOC_OPAL_STACK_RESET:
> + ret = opal_stack_reset(dev);
> + break;
>
> default:
> break;
> diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
> index aa006edb612b..0630430cc01a 100644
> --- a/include/linux/sed-opal.h
> +++ b/include/linux/sed-opal.h
> @@ -57,6 +57,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
> case IOC_OPAL_LR_SET_START_LEN:
> case IOC_OPAL_ENABLE_DISABLE_LR:
> case IOC_OPAL_GET_SUM_STATUS:
> + case IOC_OPAL_STACK_RESET:
> return true;
> }
> return false;
> diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
> index 9830298ec51c..ef4d3be6ca7f 100644
> --- a/include/uapi/linux/sed-opal.h
> +++ b/include/uapi/linux/sed-opal.h
> @@ -245,5 +245,6 @@ struct opal_revert_lsp {
> #define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
> #define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
> #define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
> +#define IOC_OPAL_STACK_RESET _IO('p', 246)
>
> #endif /* _UAPI_SED_OPAL_H */
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] sed-opal: Add STACK_RESET command
2026-03-10 9:53 [PATCH] sed-opal: Add STACK_RESET command Milan Broz
2026-03-11 12:49 ` Ondrej Kozina
2026-03-31 11:59 ` Milan Broz
@ 2026-03-31 13:07 ` Jens Axboe
2 siblings, 0 replies; 4+ messages in thread
From: Jens Axboe @ 2026-03-31 13:07 UTC (permalink / raw)
To: linux-block, Milan Broz; +Cc: jonathan.derrick, okozina
On Tue, 10 Mar 2026 10:53:49 +0100, Milan Broz wrote:
> The TCG Opal device could enter a state where no new session can be
> created, blocking even Discovery or PSID reset. While a power cycle
> or waiting for the timeout should work, there is another possibility
> for recovery: using the Stack Reset command.
>
> The Stack Reset command is defined in the TCG Storage Architecture Core
> Specification and is mandatory for all Opal devices (see Section 3.3.6
> of the Opal SSC specification).
>
> [...]
Applied, thanks!
[1/1] sed-opal: Add STACK_RESET command
commit: 499d2d2f4cf9f16634db47b06dee9676611b897f
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-31 13:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10 9:53 [PATCH] sed-opal: Add STACK_RESET command Milan Broz
2026-03-11 12:49 ` Ondrej Kozina
2026-03-31 11:59 ` Milan Broz
2026-03-31 13:07 ` Jens Axboe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox