Commit 9fb10726 authored by Greg Joyce's avatar Greg Joyce Committed by Jens Axboe

block: sed-opal: Implement IOC_OPAL_DISCOVERY

Add IOC_OPAL_DISCOVERY ioctl to return raw discovery data to a SED Opal
application. This allows the application to display drive capabilities
and state.
Signed-off-by: default avatarGreg Joyce <gjoyce@linux.vnet.ibm.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJonathan Derrick <jonathan.derrick@linux.dev>
Acked-by: default avatarJarkko Sakkinen <jarkko@kernel.org>
Link: https://lore.kernel.org/r/20230721211534.3437070-2-gjoyce@linux.vnet.ibm.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 7222657e
...@@ -463,8 +463,11 @@ static int execute_steps(struct opal_dev *dev, ...@@ -463,8 +463,11 @@ static int execute_steps(struct opal_dev *dev,
return error; return error;
} }
static int opal_discovery0_end(struct opal_dev *dev) static int opal_discovery0_end(struct opal_dev *dev, void *data)
{ {
struct opal_discovery *discv_out = data; /* may be NULL */
u8 __user *buf_out;
u64 len_out;
bool found_com_id = false, supported = true, single_user = false; bool found_com_id = false, supported = true, single_user = false;
const struct d0_header *hdr = (struct d0_header *)dev->resp; const struct d0_header *hdr = (struct d0_header *)dev->resp;
const u8 *epos = dev->resp, *cpos = dev->resp; const u8 *epos = dev->resp, *cpos = dev->resp;
...@@ -480,6 +483,15 @@ static int opal_discovery0_end(struct opal_dev *dev) ...@@ -480,6 +483,15 @@ static int opal_discovery0_end(struct opal_dev *dev)
return -EFAULT; return -EFAULT;
} }
if (discv_out) {
buf_out = (u8 __user *)(uintptr_t)discv_out->data;
len_out = min_t(u64, discv_out->size, hlen);
if (buf_out && copy_to_user(buf_out, dev->resp, len_out))
return -EFAULT;
discv_out->size = hlen; /* actual size of data */
}
epos += hlen; /* end of buffer */ epos += hlen; /* end of buffer */
cpos += sizeof(*hdr); /* current position on buffer */ cpos += sizeof(*hdr); /* current position on buffer */
...@@ -565,13 +577,13 @@ static int opal_discovery0(struct opal_dev *dev, void *data) ...@@ -565,13 +577,13 @@ static int opal_discovery0(struct opal_dev *dev, void *data)
if (ret) if (ret)
return ret; return ret;
return opal_discovery0_end(dev); return opal_discovery0_end(dev, data);
} }
static int opal_discovery0_step(struct opal_dev *dev) static int opal_discovery0_step(struct opal_dev *dev)
{ {
const struct opal_step discovery0_step = { const struct opal_step discovery0_step = {
opal_discovery0, opal_discovery0, NULL
}; };
return execute_step(dev, &discovery0_step, 0); return execute_step(dev, &discovery0_step, 0);
...@@ -2435,6 +2447,22 @@ static int opal_secure_erase_locking_range(struct opal_dev *dev, ...@@ -2435,6 +2447,22 @@ static int opal_secure_erase_locking_range(struct opal_dev *dev,
return ret; return ret;
} }
static int opal_get_discv(struct opal_dev *dev, struct opal_discovery *discv)
{
const struct opal_step discovery0_step = {
opal_discovery0, discv
};
int ret = 0;
mutex_lock(&dev->dev_lock);
setup_opal_dev(dev);
ret = execute_step(dev, &discovery0_step, 0);
mutex_unlock(&dev->dev_lock);
if (ret)
return ret;
return discv->size; /* modified to actual length of data */
}
static int opal_erase_locking_range(struct opal_dev *dev, static int opal_erase_locking_range(struct opal_dev *dev,
struct opal_session_info *opal_session) struct opal_session_info *opal_session)
{ {
...@@ -3056,6 +3084,10 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg) ...@@ -3056,6 +3084,10 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
case IOC_OPAL_GET_GEOMETRY: case IOC_OPAL_GET_GEOMETRY:
ret = opal_get_geometry(dev, arg); ret = opal_get_geometry(dev, arg);
break; break;
case IOC_OPAL_DISCOVERY:
ret = opal_get_discv(dev, p);
break;
default: default:
break; break;
} }
......
...@@ -47,6 +47,7 @@ static inline bool is_sed_ioctl(unsigned int cmd) ...@@ -47,6 +47,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
case IOC_OPAL_GET_STATUS: case IOC_OPAL_GET_STATUS:
case IOC_OPAL_GET_LR_STATUS: case IOC_OPAL_GET_LR_STATUS:
case IOC_OPAL_GET_GEOMETRY: case IOC_OPAL_GET_GEOMETRY:
case IOC_OPAL_DISCOVERY:
return true; return true;
} }
return false; return false;
......
...@@ -173,6 +173,11 @@ struct opal_geometry { ...@@ -173,6 +173,11 @@ struct opal_geometry {
__u8 __align[3]; __u8 __align[3];
}; };
struct opal_discovery {
__u64 data;
__u64 size;
};
#define IOC_OPAL_SAVE _IOW('p', 220, struct opal_lock_unlock) #define IOC_OPAL_SAVE _IOW('p', 220, struct opal_lock_unlock)
#define IOC_OPAL_LOCK_UNLOCK _IOW('p', 221, struct opal_lock_unlock) #define IOC_OPAL_LOCK_UNLOCK _IOW('p', 221, struct opal_lock_unlock)
#define IOC_OPAL_TAKE_OWNERSHIP _IOW('p', 222, struct opal_key) #define IOC_OPAL_TAKE_OWNERSHIP _IOW('p', 222, struct opal_key)
...@@ -192,5 +197,6 @@ struct opal_geometry { ...@@ -192,5 +197,6 @@ struct opal_geometry {
#define IOC_OPAL_GET_STATUS _IOR('p', 236, struct opal_status) #define IOC_OPAL_GET_STATUS _IOR('p', 236, struct opal_status)
#define IOC_OPAL_GET_LR_STATUS _IOW('p', 237, struct opal_lr_status) #define IOC_OPAL_GET_LR_STATUS _IOW('p', 237, struct opal_lr_status)
#define IOC_OPAL_GET_GEOMETRY _IOR('p', 238, struct opal_geometry) #define IOC_OPAL_GET_GEOMETRY _IOR('p', 238, struct opal_geometry)
#define IOC_OPAL_DISCOVERY _IOW('p', 239, struct opal_discovery)
#endif /* _UAPI_SED_OPAL_H */ #endif /* _UAPI_SED_OPAL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment