Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <gmazyland@gmail.com>
Reviewed-by: Ondrej Kozina <okozina@redhat.com>
Link: https://patch.msgid.link/20260310095349.411287-1-gmazyland@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Milan Broz and committed by
Jens Axboe
499d2d2f 75e75445

+69
+20
block/opal_proto.h
··· 19 19 enum { 20 20 TCG_SECP_00 = 0, 21 21 TCG_SECP_01, 22 + TCG_SECP_02, 22 23 }; 23 24 24 25 /* ··· 272 271 struct opal_compacket cp; 273 272 struct opal_packet pkt; 274 273 struct opal_data_subpacket subpkt; 274 + }; 275 + 276 + /* 277 + * TCG_Storage_Architecture_Core_Spec_v2.01_r1.00 278 + * Section: 3.3.4.7.5 STACK_RESET 279 + */ 280 + #define OPAL_STACK_RESET 0x0002 281 + 282 + struct opal_stack_reset { 283 + u8 extendedComID[4]; 284 + __be32 request_code; 285 + }; 286 + 287 + struct opal_stack_reset_response { 288 + u8 extendedComID[4]; 289 + __be32 request_code; 290 + u8 reserved0[2]; 291 + __be16 data_length; 292 + __be32 response; 275 293 }; 276 294 277 295 #define FC_TPER 0x0001
+47
block/sed-opal.c
··· 3545 3545 return ret; 3546 3546 } 3547 3547 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 + 3548 3592 int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg) 3549 3593 { 3550 3594 void *p; ··· 3685 3641 break; 3686 3642 case IOC_OPAL_GET_SUM_STATUS: 3687 3643 ret = opal_get_sum_ranges(dev, p, arg); 3644 + break; 3645 + case IOC_OPAL_STACK_RESET: 3646 + ret = opal_stack_reset(dev); 3688 3647 break; 3689 3648 3690 3649 default:
+1
include/linux/sed-opal.h
··· 57 57 case IOC_OPAL_LR_SET_START_LEN: 58 58 case IOC_OPAL_ENABLE_DISABLE_LR: 59 59 case IOC_OPAL_GET_SUM_STATUS: 60 + case IOC_OPAL_STACK_RESET: 60 61 return true; 61 62 } 62 63 return false;
+1
include/uapi/linux/sed-opal.h
··· 245 245 #define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup) 246 246 #define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup) 247 247 #define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges) 248 + #define IOC_OPAL_STACK_RESET _IO('p', 246) 248 249 249 250 #endif /* _UAPI_SED_OPAL_H */