aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-08-08 02:37:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-08-08 02:37:53 -0400
commit6d33b3069ed84be9b8430ccc7705d0e747542a4f (patch)
tree495801abfd12692d4f9d0b0bffc234ee299baa4c
parenta39284ae9d2ad09975c8ae33f1bd0f05fbfbf6ee (diff)
parent15e2a7218c2788d79c5633336d17cb9428c221e7 (diff)
Merge tag 'fsi-updates-2018-08-08' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/linux-fsi into char-misc-next
Ben writes: FSI Updates for 4.19 This adds two FSI fixes: - Fix a NULL dereference in the scom driver - Fix a command buffer size issue in the sbefifo driver that breaks some operations with POWER system debugger (cronus)
-rw-r--r--drivers/fsi/fsi-sbefifo.c39
-rw-r--r--drivers/fsi/fsi-scom.c1
2 files changed, 33 insertions, 7 deletions
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 7550497da8ef..ae861342626e 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -30,6 +30,7 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/uio.h> 31#include <linux/uio.h>
32#include <linux/vmalloc.h> 32#include <linux/vmalloc.h>
33#include <linux/mm.h>
33 34
34/* 35/*
35 * The SBEFIFO is a pipe-like FSI device for communicating with 36 * The SBEFIFO is a pipe-like FSI device for communicating with
@@ -110,7 +111,7 @@ enum sbe_state
110#define SBEFIFO_TIMEOUT_IN_RSP 1000 111#define SBEFIFO_TIMEOUT_IN_RSP 1000
111 112
112/* Other constants */ 113/* Other constants */
113#define SBEFIFO_MAX_CMD_LEN PAGE_SIZE 114#define SBEFIFO_MAX_USER_CMD_LEN (0x100000 + PAGE_SIZE)
114#define SBEFIFO_RESET_MAGIC 0x52534554 /* "RSET" */ 115#define SBEFIFO_RESET_MAGIC 0x52534554 /* "RSET" */
115 116
116struct sbefifo { 117struct sbefifo {
@@ -128,6 +129,7 @@ struct sbefifo {
128struct sbefifo_user { 129struct sbefifo_user {
129 struct sbefifo *sbefifo; 130 struct sbefifo *sbefifo;
130 struct mutex file_lock; 131 struct mutex file_lock;
132 void *cmd_page;
131 void *pending_cmd; 133 void *pending_cmd;
132 size_t pending_len; 134 size_t pending_len;
133}; 135};
@@ -726,7 +728,7 @@ int sbefifo_submit(struct device *dev, const __be32 *command, size_t cmd_len,
726 return -ENODEV; 728 return -ENODEV;
727 if (WARN_ON_ONCE(sbefifo->magic != SBEFIFO_MAGIC)) 729 if (WARN_ON_ONCE(sbefifo->magic != SBEFIFO_MAGIC))
728 return -ENODEV; 730 return -ENODEV;
729 if (!resp_len || !command || !response || cmd_len > SBEFIFO_MAX_CMD_LEN) 731 if (!resp_len || !command || !response)
730 return -EINVAL; 732 return -EINVAL;
731 733
732 /* Prepare iov iterator */ 734 /* Prepare iov iterator */
@@ -751,6 +753,15 @@ EXPORT_SYMBOL_GPL(sbefifo_submit);
751/* 753/*
752 * Char device interface 754 * Char device interface
753 */ 755 */
756
757static void sbefifo_release_command(struct sbefifo_user *user)
758{
759 if (is_vmalloc_addr(user->pending_cmd))
760 vfree(user->pending_cmd);
761 user->pending_cmd = NULL;
762 user->pending_len = 0;
763}
764
754static int sbefifo_user_open(struct inode *inode, struct file *file) 765static int sbefifo_user_open(struct inode *inode, struct file *file)
755{ 766{
756 struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev); 767 struct sbefifo *sbefifo = container_of(inode->i_cdev, struct sbefifo, cdev);
@@ -762,8 +773,8 @@ static int sbefifo_user_open(struct inode *inode, struct file *file)
762 773
763 file->private_data = user; 774 file->private_data = user;
764 user->sbefifo = sbefifo; 775 user->sbefifo = sbefifo;
765 user->pending_cmd = (void *)__get_free_page(GFP_KERNEL); 776 user->cmd_page = (void *)__get_free_page(GFP_KERNEL);
766 if (!user->pending_cmd) { 777 if (!user->cmd_page) {
767 kfree(user); 778 kfree(user);
768 return -ENOMEM; 779 return -ENOMEM;
769 } 780 }
@@ -816,7 +827,7 @@ static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
816 /* Extract the response length */ 827 /* Extract the response length */
817 rc = len - iov_iter_count(&resp_iter); 828 rc = len - iov_iter_count(&resp_iter);
818 bail: 829 bail:
819 user->pending_len = 0; 830 sbefifo_release_command(user);
820 mutex_unlock(&user->file_lock); 831 mutex_unlock(&user->file_lock);
821 return rc; 832 return rc;
822} 833}
@@ -831,13 +842,23 @@ static ssize_t sbefifo_user_write(struct file *file, const char __user *buf,
831 if (!user) 842 if (!user)
832 return -EINVAL; 843 return -EINVAL;
833 sbefifo = user->sbefifo; 844 sbefifo = user->sbefifo;
834 if (len > SBEFIFO_MAX_CMD_LEN) 845 if (len > SBEFIFO_MAX_USER_CMD_LEN)
835 return -EINVAL; 846 return -EINVAL;
836 if (len & 3) 847 if (len & 3)
837 return -EINVAL; 848 return -EINVAL;
838 849
839 mutex_lock(&user->file_lock); 850 mutex_lock(&user->file_lock);
840 851
852 /* Can we use the pre-allocate buffer ? If not, allocate */
853 if (len <= PAGE_SIZE)
854 user->pending_cmd = user->cmd_page;
855 else
856 user->pending_cmd = vmalloc(len);
857 if (!user->pending_cmd) {
858 rc = -ENOMEM;
859 goto bail;
860 }
861
841 /* Copy the command into the staging buffer */ 862 /* Copy the command into the staging buffer */
842 if (copy_from_user(user->pending_cmd, buf, len)) { 863 if (copy_from_user(user->pending_cmd, buf, len)) {
843 rc = -EFAULT; 864 rc = -EFAULT;
@@ -863,6 +884,9 @@ static ssize_t sbefifo_user_write(struct file *file, const char __user *buf,
863 /* Update the staging buffer size */ 884 /* Update the staging buffer size */
864 user->pending_len = len; 885 user->pending_len = len;
865 bail: 886 bail:
887 if (!user->pending_len)
888 sbefifo_release_command(user);
889
866 mutex_unlock(&user->file_lock); 890 mutex_unlock(&user->file_lock);
867 891
868 /* And that's it, we'll issue the command on a read */ 892 /* And that's it, we'll issue the command on a read */
@@ -876,7 +900,8 @@ static int sbefifo_user_release(struct inode *inode, struct file *file)
876 if (!user) 900 if (!user)
877 return -EINVAL; 901 return -EINVAL;
878 902
879 free_page((unsigned long)user->pending_cmd); 903 sbefifo_release_command(user);
904 free_page((unsigned long)user->cmd_page);
880 kfree(user); 905 kfree(user);
881 906
882 return 0; 907 return 0;
diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
index 0f303a700f69..df94021dd9d1 100644
--- a/drivers/fsi/fsi-scom.c
+++ b/drivers/fsi/fsi-scom.c
@@ -598,6 +598,7 @@ static int scom_probe(struct device *dev)
598 kfree(scom); 598 kfree(scom);
599 return -ENODEV; 599 return -ENODEV;
600 } 600 }
601 scom->fsi_dev = fsi_dev;
601 602
602 /* Create chardev for userspace access */ 603 /* Create chardev for userspace access */
603 scom->dev.type = &fsi_cdev_type; 604 scom->dev.type = &fsi_cdev_type;