Skip to content

Commit 499d2d2

Browse files
mbrozaxboe
authored andcommitted
sed-opal: Add STACK_RESET command
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 <[email protected]> Reviewed-by: Ondrej Kozina <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 75e7544 commit 499d2d2

4 files changed

Lines changed: 69 additions & 0 deletions

File tree

block/opal_proto.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
enum {
2020
TCG_SECP_00 = 0,
2121
TCG_SECP_01,
22+
TCG_SECP_02,
2223
};
2324

2425
/*
@@ -273,6 +274,25 @@ struct opal_header {
273274
struct opal_data_subpacket subpkt;
274275
};
275276

277+
/*
278+
* TCG_Storage_Architecture_Core_Spec_v2.01_r1.00
279+
* Section: 3.3.4.7.5 STACK_RESET
280+
*/
281+
#define OPAL_STACK_RESET 0x0002
282+
283+
struct opal_stack_reset {
284+
u8 extendedComID[4];
285+
__be32 request_code;
286+
};
287+
288+
struct opal_stack_reset_response {
289+
u8 extendedComID[4];
290+
__be32 request_code;
291+
u8 reserved0[2];
292+
__be16 data_length;
293+
__be32 response;
294+
};
295+
276296
#define FC_TPER 0x0001
277297
#define FC_LOCKING 0x0002
278298
#define FC_GEOMETRY 0x0003

block/sed-opal.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3545,6 +3545,50 @@ static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opa
35453545
return ret;
35463546
}
35473547

3548+
static int opal_stack_reset(struct opal_dev *dev)
3549+
{
3550+
struct opal_stack_reset *req;
3551+
struct opal_stack_reset_response *resp;
3552+
int ret;
3553+
3554+
mutex_lock(&dev->dev_lock);
3555+
3556+
memset(dev->cmd, 0, IO_BUFFER_LENGTH);
3557+
req = (struct opal_stack_reset *)dev->cmd;
3558+
req->extendedComID[0] = dev->comid >> 8;
3559+
req->extendedComID[1] = dev->comid & 0xFF;
3560+
req->request_code = cpu_to_be32(OPAL_STACK_RESET);
3561+
3562+
ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
3563+
dev->cmd, IO_BUFFER_LENGTH, true);
3564+
if (ret) {
3565+
pr_debug("Error sending stack reset: %d\n", ret);
3566+
goto out;
3567+
}
3568+
3569+
memset(dev->resp, 0, IO_BUFFER_LENGTH);
3570+
ret = dev->send_recv(dev->data, dev->comid, TCG_SECP_02,
3571+
dev->resp, IO_BUFFER_LENGTH, false);
3572+
if (ret) {
3573+
pr_debug("Error receiving stack reset response: %d\n", ret);
3574+
goto out;
3575+
}
3576+
3577+
resp = (struct opal_stack_reset_response *)dev->resp;
3578+
if (be16_to_cpu(resp->data_length) != 4) {
3579+
pr_debug("Stack reset pending\n");
3580+
ret = -EBUSY;
3581+
goto out;
3582+
}
3583+
if (be32_to_cpu(resp->response) != 0) {
3584+
pr_debug("Stack reset failed: %u\n", be32_to_cpu(resp->response));
3585+
ret = -EIO;
3586+
}
3587+
out:
3588+
mutex_unlock(&dev->dev_lock);
3589+
return ret;
3590+
}
3591+
35483592
int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
35493593
{
35503594
void *p;
@@ -3642,6 +3686,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
36423686
case IOC_OPAL_GET_SUM_STATUS:
36433687
ret = opal_get_sum_ranges(dev, p, arg);
36443688
break;
3689+
case IOC_OPAL_STACK_RESET:
3690+
ret = opal_stack_reset(dev);
3691+
break;
36453692

36463693
default:
36473694
break;

include/linux/sed-opal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
5757
case IOC_OPAL_LR_SET_START_LEN:
5858
case IOC_OPAL_ENABLE_DISABLE_LR:
5959
case IOC_OPAL_GET_SUM_STATUS:
60+
case IOC_OPAL_STACK_RESET:
6061
return true;
6162
}
6263
return false;

include/uapi/linux/sed-opal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,5 +245,6 @@ struct opal_revert_lsp {
245245
#define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup)
246246
#define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup)
247247
#define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges)
248+
#define IOC_OPAL_STACK_RESET _IO('p', 246)
248249

249250
#endif /* _UAPI_SED_OPAL_H */

0 commit comments

Comments
 (0)