summaryrefslogtreecommitdiffstats
path: root/block/sed-opal.c
diff options
context:
space:
mode:
authorScott Bauer <scott.bauer@intel.com>2017-09-01 10:53:35 -0400
committerJens Axboe <axboe@kernel.dk>2017-09-11 11:45:52 -0400
commitdbec491b12b52888d120e5be8f15886b3216eb19 (patch)
treeae5c7424d03c6b60d229bd216f0666d12c366eed /block/sed-opal.c
parentf8e9ec16611baa8db77a7d46facd2ba7aa525955 (diff)
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: <jonathan.derrick@intel.com> Signed-off-by: Scott Bauer <scott.bauer@intel.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/sed-opal.c')
-rw-r--r--block/sed-opal.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 9b30ae5ab843..9ed51d0c6b1d 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -80,6 +80,7 @@ struct parsed_resp {
80 80
81struct opal_dev { 81struct opal_dev {
82 bool supported; 82 bool supported;
83 bool mbr_enabled;
83 84
84 void *data; 85 void *data;
85 sec_send_recv *send_recv; 86 sec_send_recv *send_recv;
@@ -283,6 +284,14 @@ static bool check_tper(const void *data)
283 return true; 284 return true;
284} 285}
285 286
287static 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
286static bool check_sum(const void *data) 295static bool check_sum(const void *data)
287{ 296{
288 const struct d0_single_user_mode *sum = data; 297 const struct d0_single_user_mode *sum = data;
@@ -417,6 +426,7 @@ static int opal_discovery0_end(struct opal_dev *dev)
417 u32 hlen = be32_to_cpu(hdr->length); 426 u32 hlen = be32_to_cpu(hdr->length);
418 427
419 print_buffer(dev->resp, hlen); 428 print_buffer(dev->resp, hlen);
429 dev->mbr_enabled = false;
420 430
421 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) { 431 if (hlen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
422 pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n", 432 pr_debug("Discovery length overflows buffer (%zu+%u)/%u\n",
@@ -442,6 +452,8 @@ static int opal_discovery0_end(struct opal_dev *dev)
442 check_geometry(dev, body); 452 check_geometry(dev, body);
443 break; 453 break;
444 case FC_LOCKING: 454 case FC_LOCKING:
455 dev->mbr_enabled = check_mbrenabled(body->features);
456 break;
445 case FC_ENTERPRISE: 457 case FC_ENTERPRISE:
446 case FC_DATASTORE: 458 case FC_DATASTORE:
447 /* some ignored properties */ 459 /* some ignored properties */
@@ -2190,6 +2202,21 @@ static int __opal_lock_unlock(struct opal_dev *dev,
2190 return next(dev); 2202 return next(dev);
2191} 2203}
2192 2204
2205static 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
2193static int opal_lock_unlock(struct opal_dev *dev, 2220static int opal_lock_unlock(struct opal_dev *dev,
2194 struct opal_lock_unlock *lk_unlk) 2221 struct opal_lock_unlock *lk_unlk)
2195{ 2222{
@@ -2345,6 +2372,11 @@ bool opal_unlock_from_suspend(struct opal_dev *dev)
2345 suspend->unlk.session.sum); 2372 suspend->unlk.session.sum);
2346 was_failure = true; 2373 was_failure = true;
2347 } 2374 }
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 }
2348 } 2380 }
2349 mutex_unlock(&dev->dev_lock); 2381 mutex_unlock(&dev->dev_lock);
2350 return was_failure; 2382 return was_failure;