in char/oradax.c [223:358]
static int dax_ccb_exec(struct dax_ctx *ctx, const char __user *buf,
size_t count, loff_t *ppos);
static int dax_ccb_info(u64 ca, struct ccb_info_result *info);
static int dax_ccb_kill(u64 ca, u16 *kill_res);
static struct cdev c_dev;
static struct class *cl;
static dev_t first;
static int max_ccb_version;
static int dax_debug;
module_param(dax_debug, int, 0644);
MODULE_PARM_DESC(dax_debug, "Debug flags");
static int __init dax_attach(void)
{
unsigned long dummy, hv_rv, major, minor, minor_requested, max_ccbs;
struct mdesc_handle *hp = mdesc_grab();
char *prop, *dax_name;
bool found = false;
int len, ret = 0;
u64 pn;
if (hp == NULL) {
dax_err("Unable to grab mdesc");
return -ENODEV;
}
mdesc_for_each_node_by_name(hp, pn, "virtual-device") {
prop = (char *)mdesc_get_property(hp, pn, "name", &len);
if (prop == NULL)
continue;
if (strncmp(prop, "dax", strlen("dax")))
continue;
dax_dbg("Found node 0x%llx = %s", pn, prop);
prop = (char *)mdesc_get_property(hp, pn, "compatible", &len);
if (prop == NULL)
continue;
dax_dbg("Found node 0x%llx = %s", pn, prop);
found = true;
break;
}
if (!found) {
dax_err("No DAX device found");
ret = -ENODEV;
goto done;
}
if (strncmp(prop, DAX2_STR, strlen(DAX2_STR)) == 0) {
dax_name = DAX_NAME "2";
major = DAX2_MAJOR;
minor_requested = DAX2_MINOR;
max_ccb_version = 1;
dax_dbg("MD indicates DAX2 coprocessor");
} else if (strncmp(prop, DAX1_STR, strlen(DAX1_STR)) == 0) {
dax_name = DAX_NAME "1";
major = DAX1_MAJOR;
minor_requested = DAX1_MINOR;
max_ccb_version = 0;
dax_dbg("MD indicates DAX1 coprocessor");
} else {
dax_err("Unknown dax type: %s", prop);
ret = -ENODEV;
goto done;
}
minor = minor_requested;
dax_dbg("Registering DAX HV api with major %ld minor %ld", major,
minor);
if (sun4v_hvapi_register(HV_GRP_DAX, major, &minor)) {
dax_err("hvapi_register failed");
ret = -ENODEV;
goto done;
} else {
dax_dbg("Max minor supported by HV = %ld (major %ld)", minor,
major);
minor = min(minor, minor_requested);
dax_dbg("registered DAX major %ld minor %ld", major, minor);
}
/* submit a zero length ccb array to query coprocessor queue size */
hv_rv = sun4v_ccb_submit(0, 0, HV_CCB_QUERY_CMD, 0, &max_ccbs, &dummy);
if (hv_rv != 0) {
dax_err("get_hwqueue_size failed with status=%ld and max_ccbs=%ld",
hv_rv, max_ccbs);
ret = -ENODEV;
goto done;
}
if (max_ccbs != DAX_MAX_CCBS) {
dax_err("HV reports unsupported max_ccbs=%ld", max_ccbs);
ret = -ENODEV;
goto done;
}
if (alloc_chrdev_region(&first, 0, 1, DAX_NAME) < 0) {
dax_err("alloc_chrdev_region failed");
ret = -ENXIO;
goto done;
}
cl = class_create(THIS_MODULE, DAX_NAME);
if (IS_ERR(cl)) {
dax_err("class_create failed");
ret = PTR_ERR(cl);
goto class_error;
}
if (device_create(cl, NULL, first, NULL, dax_name) == NULL) {
dax_err("device_create failed");
ret = -ENXIO;
goto device_error;
}
cdev_init(&c_dev, &dax_fops);
if (cdev_add(&c_dev, first, 1) == -1) {
dax_err("cdev_add failed");
ret = -ENXIO;
goto cdev_error;
}
pr_info("Attached DAX module\n");
goto done;
cdev_error:
device_destroy(cl, first);
device_error:
class_destroy(cl);
class_error:
unregister_chrdev_region(first, 1);
done:
mdesc_release(hp);
return ret;
}