Add device capabilities caching in kernel driver

To not have to fetch the capabilities from the device for each time they
are requested with the UAPI, the kernel driver will now fetch and save
the capabilities during the device initialization and use the saved copy
for the UAPI requests.

With this change, the character device creation in the device
initialization has been moved to be the last step so the capabilities
are fetched and saved before the character device is created.

Change-Id: I57956aedb983fbc1765d45906a1c6182e2cd5b96
diff --git a/kernel/ethosu_device.c b/kernel/ethosu_device.c
index e1dde65..0b6fdfa 100644
--- a/kernel/ethosu_device.c
+++ b/kernel/ethosu_device.c
@@ -264,16 +264,10 @@
 		ret = ethosu_mailbox_version_request(&edev->mailbox);
 		break;
 	case ETHOSU_IOCTL_CAPABILITIES_REQ: {
-		struct ethosu_uapi_device_capabilities uapi;
+		dev_info(dev, "Device ioctl: Capabilities request");
 
-		dev_info(dev,
-			 "Device ioctl: Send capabilities request");
-
-		ret = ethosu_capabilities_request(dev, &edev->mailbox, &uapi);
-		if (ret)
-			break;
-
-		ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
+		ret = copy_to_user(udata, &edev->capabilities,
+				   sizeof(edev->capabilities)) ? -EFAULT : 0;
 		break;
 	}
 	case ETHOSU_IOCTL_PING: {
@@ -464,6 +458,17 @@
 	if (ret)
 		goto device_unregister;
 
+	ethosu_mailbox_ping(&edev->mailbox);
+
+	device_lock(dev);
+	ret = ethosu_capabilities_request(dev, &edev->mailbox,
+					  &edev->capabilities);
+	device_unlock(dev);
+	if (ret) {
+		dev_err(dev, "Failed to get device capabilities: %d", ret);
+		goto deinit_mailbox;
+	}
+
 	/* Create device node */
 	cdev_init(&edev->cdev, &fops);
 	edev->cdev.owner = THIS_MODULE;
@@ -490,8 +495,6 @@
 		 "Created Arm Ethos-U device. name=%s, major=%d, minor=%d",
 		 dev_name(sysdev), MAJOR(devt), MINOR(devt));
 
-	ethosu_mailbox_ping(&edev->mailbox);
-
 	return 0;
 
 del_cdev: