Skip to content

Commit dbec491

Browse files
Scott Baueraxboe
authored andcommitted
block: sed-opal: Set MBRDone on S3 resume path if TPER is MBREnabled
Users who are booting off their Opal enabled drives are having issues when they have a shadow MBR set up after s3/resume cycle. When the Drive has a shadow MBR setup the MBRDone flag is set to false upon power loss (S3/S4/S5). When the MBRDone flag is false I/O to LBA 0 -> LBA_END_MBR are remapped to the shadow mbr of the drive. If the drive contains useful data in the 0 -> end_mbr range upon s3 resume the user can never get to that data as the drive will keep remapping it to the MBR. To fix this when we unlock on S3 resume, we need to tell the drive that we're done with the shadow mbr (even though we didnt use it) by setting true to MBRDone. This way the drive will stop the remapping and the user can access their data. Acked-by Jon Derrick: <[email protected]> Signed-off-by: Scott Bauer <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent f8e9ec1 commit dbec491

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

block/opal_proto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ enum opal_response_token {
4646
#define GENERIC_HOST_SESSION_NUM 0x41
4747

4848
#define TPER_SYNC_SUPPORTED 0x01
49+
#define MBR_ENABLED_MASK 0x10
4950

5051
#define TINY_ATOM_DATA_MASK 0x3F
5152
#define TINY_ATOM_SIGNED 0x40

block/sed-opal.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct parsed_resp {
8080

8181
struct opal_dev {
8282
bool supported;
83+
bool mbr_enabled;
8384

8485
void *data;
8586
sec_send_recv *send_recv;
@@ -283,6 +284,14 @@ static bool check_tper(const void *data)
283284
return true;
284285
}
285286

287+
static bool check_mbrenabled(const void *data)
288+
{
289+
const struct d0_locking_features *lfeat = data;
290+
u8 sup_feat = lfeat->supported_features;
291+
292+
return !!(sup_feat & MBR_ENABLED_MASK);
293+
}
294+
286295
static bool check_sum(const void *data)
287296
{
288297
const struct d0_single_user_mode *sum = data;
@@ -417,6 +426,7 @@ static int opal_discovery0_end(struct opal_dev *dev)
417426
u32 hlen = be32_to_cpu(hdr->length);
418427

419428
print_buffer(dev->resp, hlen);
429+
dev->mbr_enabled = false;
420430

421431
if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
422432
pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n",
@@ -442,6 +452,8 @@ static int opal_discovery0_end(struct opal_dev *dev)
442452
check_geometry(dev, body);
443453
break;
444454
case FC_LOCKING:
455+
dev->mbr_enabled = check_mbrenabled(body->features);
456+
break;
445457
case FC_ENTERPRISE:
446458
case FC_DATASTORE:
447459
/* some ignored properties */
@@ -2190,6 +2202,21 @@ static int __opal_lock_unlock(struct opal_dev *dev,
21902202
return next(dev);
21912203
}
21922204

2205+
static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
2206+
{
2207+
u8 mbr_done_tf = 1;
2208+
const struct opal_step mbrdone_step [] = {
2209+
{ opal_discovery0, },
2210+
{ start_admin1LSP_opal_session, key },
2211+
{ set_mbr_done, &mbr_done_tf },
2212+
{ end_opal_session, },
2213+
{ NULL, }
2214+
};
2215+
2216+
dev->steps = mbrdone_step;
2217+
return next(dev);
2218+
}
2219+
21932220
static int opal_lock_unlock(struct opal_dev *dev,
21942221
struct opal_lock_unlock *lk_unlk)
21952222
{
@@ -2345,6 +2372,11 @@ bool opal_unlock_from_suspend(struct opal_dev *dev)
23452372
suspend->unlk.session.sum);
23462373
was_failure = true;
23472374
}
2375+
if (dev->mbr_enabled) {
2376+
ret = __opal_set_mbr_done(dev, &suspend->unlk.session.opal_key);
2377+
if (ret)
2378+
pr_debug("Failed to set MBR Done in S3 resume\n");
2379+
}
23482380
}
23492381
mutex_unlock(&dev->dev_lock);
23502382
return was_failure;

0 commit comments

Comments
 (0)