static int dax_ccb_exec()

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;
}