Merge "platform: msm: fix PFT char device major number"
diff --git a/drivers/platform/msm/pft.c b/drivers/platform/msm/pft.c
index 6132ba3..20e7249 100644
--- a/drivers/platform/msm/pft.c
+++ b/drivers/platform/msm/pft.c
@@ -49,6 +49,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/cdev.h>
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/cred.h>
@@ -90,7 +91,7 @@
 #define PFT_REQUESTED_MAJOR	213
 
 /* PFT driver name */
-#define PFT_DEVICE_NAME	"pft"
+#define DEVICE_NAME	"pft"
 
 /* Maximum registered applications */
 #define PFT_MAX_APPS	1000
@@ -143,6 +144,9 @@
  * after the key is removed from the encryption hardware.
  */
 struct pft_device {
+	struct cdev cdev;
+	dev_t device_no;
+	struct class *driver_class;
 	int open_count;
 	int major;
 	enum pft_state state;
@@ -214,11 +218,11 @@
 }
 
 /**
- * ptf_set_response() - set response error code.
+ * pft_set_response() - set response error code.
  *
  * @error_code: The error code to return on response.
  */
-static inline void ptf_set_response(u32 error_code)
+static inline void pft_set_response(u32 error_code)
 {
 	pft_dev->response.error_code = error_code;
 }
@@ -1315,13 +1319,13 @@
 
 	if (size != expected_size) {
 		pr_err("Invalid buffer size\n");
-		ptf_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
+		pft_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
 		return -EINVAL;
 	}
 
 	if (state >= PFT_STATE_MAX_INDEX) {
 		pr_err("Invalid state %d\n", command->set_state.state);
-		ptf_set_response(PFT_CMD_RESP_INVALID_STATE);
+		pft_set_response(PFT_CMD_RESP_INVALID_STATE);
 		return 0;
 	}
 
@@ -1336,11 +1340,11 @@
 	case PFT_STATE_KEY_LOADED:
 	case PFT_STATE_KEY_REMOVED:
 		pft_dev->state = command->set_state.state;
-		ptf_set_response(PFT_CMD_RESP_SUCCESS);
+		pft_set_response(PFT_CMD_RESP_SUCCESS);
 		break;
 	default:
 		pr_err("Invalid state %d\n", command->set_state.state);
-		ptf_set_response(PFT_CMD_RESP_INVALID_STATE);
+		pft_set_response(PFT_CMD_RESP_INVALID_STATE);
 		break;
 	}
 
@@ -1393,14 +1397,14 @@
 	if (size != expected_size) {
 		pr_err("invalid command size %d expected %d.\n",
 		       size, expected_size);
-		ptf_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
+		pft_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
 		return -EINVAL;
 	}
 
 	if (pft_dev->state != (u32) PFT_STATE_KEY_LOADED) {
 		pr_err("Key not loaded, state [%d], In-place-encryption is not allowed.\n",
 		       pft_dev->state);
-		ptf_set_response(PFT_CMD_RESP_GENERAL_ERROR);
+		pft_set_response(PFT_CMD_RESP_GENERAL_ERROR);
 		return 0;
 	}
 
@@ -1409,7 +1413,7 @@
 		pr_err("file %s in-place-encryption in progress.\n",
 		       file_to_filename(pft_dev->inplace_file));
 		/* @todo - use new error code */
-		ptf_set_response(PFT_CMD_RESP_INPLACE_FILE_IS_OPEN);
+		pft_set_response(PFT_CMD_RESP_INPLACE_FILE_IS_OPEN);
 		return 0;
 	}
 
@@ -1418,14 +1422,14 @@
 
 	if (filp == NULL) {
 		pr_err("failed to find file by fd %d.\n", fd);
-		ptf_set_response(PFT_CMD_RESP_GENERAL_ERROR);
+		pft_set_response(PFT_CMD_RESP_GENERAL_ERROR);
 		return 0;
 	}
 
 	/* Verify the file is not already open by other than PFM */
 	if (!filp->f_path.dentry || !filp->f_path.dentry->d_inode) {
 		pr_err("failed to get inode of inplace-file.\n");
-		ptf_set_response(PFT_CMD_RESP_GENERAL_ERROR);
+		pft_set_response(PFT_CMD_RESP_GENERAL_ERROR);
 		return 0;
 	}
 
@@ -1434,7 +1438,7 @@
 	if (writecount > 1) {
 		pr_err("file %s is opened %d times for write.\n",
 		       file_to_filename(filp), writecount);
-		ptf_set_response(PFT_CMD_RESP_GENERAL_ERROR);
+		pft_set_response(PFT_CMD_RESP_INPLACE_FILE_IS_OPEN);
 		return 0;
 	}
 
@@ -1447,7 +1451,7 @@
 	if (pft_is_encrypted_file(filp->f_dentry)) {
 		pr_err("file %s is already encrypted.\n",
 		       file_to_filename(filp));
-		ptf_set_response(PFT_CMD_RESP_GENERAL_ERROR);
+		pft_set_response(PFT_CMD_RESP_GENERAL_ERROR);
 		return 0;
 	}
 
@@ -1468,11 +1472,11 @@
 	if (!rc) {
 		pr_debug("tagged file %s to be encrypted.\n",
 			 file_to_filename(pft_dev->inplace_file));
-		ptf_set_response(PFT_CMD_RESP_SUCCESS);
+		pft_set_response(PFT_CMD_RESP_SUCCESS);
 	} else {
 		pr_err("failed to tag file %s for encryption.\n",
 			file_to_filename(pft_dev->inplace_file));
-		ptf_set_response(PFT_CMD_RESP_GENERAL_ERROR);
+		pft_set_response(PFT_CMD_RESP_GENERAL_ERROR);
 	}
 
 	return 0;
@@ -1499,7 +1503,7 @@
 	if (items_count > PFT_MAX_APPS) {
 		pr_err("Number of apps [%d] > max apps [%d]\n",
 		       items_count , PFT_MAX_APPS);
-		ptf_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
+		pft_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
 		return -EINVAL;
 	}
 
@@ -1511,7 +1515,7 @@
 	if (size != expected_size) {
 		pr_err("invalid command size %d expected %d.\n",
 		       size, expected_size);
-		ptf_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
+		pft_set_response(PFT_CMD_RESP_INVALID_CMD_PARAMS);
 		return -EINVAL;
 	}
 
@@ -1533,7 +1537,7 @@
 
 	if (!buf) {
 		pr_err("malloc failure\n");
-		ptf_set_response(PFT_CMD_RESP_GENERAL_ERROR);
+		pft_set_response(PFT_CMD_RESP_GENERAL_ERROR);
 		mutex_unlock(&pft_dev->lock);
 		return 0;
 	}
@@ -1543,7 +1547,7 @@
 	pr_debug("uid_count = %d\n", pft_dev->uid_count);
 	for (i = 0; i < pft_dev->uid_count; i++)
 		pft_dev->uid_table[i] = command->update_app_list.table[i];
-	ptf_set_response(PFT_CMD_RESP_SUCCESS);
+	pft_set_response(PFT_CMD_RESP_SUCCESS);
 	mutex_unlock(&pft_dev->lock);
 
 	return 0;
@@ -1583,7 +1587,7 @@
 		break;
 	default:
 		pr_err("Invalid command_op_code %u\n", command->opcode);
-		ptf_set_response(PFT_CMD_RESP_INVALID_COMMAND);
+		pft_set_response(PFT_CMD_RESP_INVALID_COMMAND);
 		return 0;
 	}
 
@@ -1706,12 +1710,71 @@
 	.release = pft_device_release,
 };
 
+static int __init pft_register_chardev(void)
+{
+	int rc;
+	unsigned baseminor = 0;
+	unsigned count = 1;
+	struct device *class_dev;
+
+	rc = alloc_chrdev_region(&pft_dev->device_no, baseminor, count,
+				 DEVICE_NAME);
+	if (rc < 0) {
+		pr_err("alloc_chrdev_region failed %d\n", rc);
+		return rc;
+	}
+
+	pft_dev->driver_class = class_create(THIS_MODULE, DEVICE_NAME);
+	if (IS_ERR(pft_dev->driver_class)) {
+		rc = -ENOMEM;
+		pr_err("class_create failed %d\n", rc);
+		goto exit_unreg_chrdev_region;
+	}
+
+	class_dev = device_create(pft_dev->driver_class, NULL,
+				  pft_dev->device_no, NULL,
+				  DEVICE_NAME);
+	if (!class_dev) {
+		pr_err("class_device_create failed %d\n", rc);
+		rc = -ENOMEM;
+		goto exit_destroy_class;
+	}
+
+	cdev_init(&pft_dev->cdev, &fops);
+	pft_dev->cdev.owner = THIS_MODULE;
+
+	rc = cdev_add(&pft_dev->cdev, MKDEV(MAJOR(pft_dev->device_no), 0), 1);
+	if (rc < 0) {
+		pr_err("cdev_add failed %d\n", rc);
+		goto exit_destroy_device;
+	}
+
+	return 0;
+
+exit_destroy_device:
+	device_destroy(pft_dev->driver_class, pft_dev->device_no);
+exit_destroy_class:
+	class_destroy(pft_dev->driver_class);
+exit_unreg_chrdev_region:
+	unregister_chrdev_region(pft_dev->device_no, 1);
+	return rc;
+}
+
+static void __exit pft_unregister_chrdev(void)
+{
+	cdev_del(&pft_dev->cdev);
+	device_destroy(pft_dev->driver_class, pft_dev->device_no);
+	class_destroy(pft_dev->driver_class);
+	unregister_chrdev_region(pft_dev->device_no, 1);
+
+}
+
 static void __exit pft_exit(void)
 {
 	if (pft_dev == NULL)
 		return;
 
-	unregister_chrdev(pft_dev->major, PFT_DEVICE_NAME);
+	pft_unregister_chrdev();
 
 	kfree(pft_dev->uid_table);
 	kfree(pft_dev);
@@ -1719,6 +1782,7 @@
 
 static int __init pft_init(void)
 {
+	int ret;
 	struct pft_device *dev = NULL;
 
 	dev = kzalloc(sizeof(struct pft_device), GFP_KERNEL);
@@ -1731,14 +1795,13 @@
 	INIT_LIST_HEAD(&dev->open_file_list);
 	mutex_init(&dev->lock);
 
-	dev->major = register_chrdev(PFT_REQUESTED_MAJOR, PFT_DEVICE_NAME,
-				     &fops);
-	if (IS_ERR_VALUE(dev->major)) {
-		pr_err("Registering the character device with major %d failed with %d\n",
-		       PFT_REQUESTED_MAJOR, dev->major);
+	pft_dev = dev;
+
+	ret = pft_register_chardev();
+	if (ret) {
+		pr_err("create character device failed.\n");
 		goto fail;
 	}
-	pft_dev = dev;
 
 	pr_info("Drivr initialized successfully %s %s.n", __DATE__, __TIME__);