30
30
#include <linux/delay.h>
31
31
#include <linux/uio.h>
32
32
#include <linux/vmalloc.h>
33
+ #include <linux/mm.h>
33
34
34
35
/*
35
36
* The SBEFIFO is a pipe-like FSI device for communicating with
@@ -110,7 +111,7 @@ enum sbe_state
110
111
#define SBEFIFO_TIMEOUT_IN_RSP 1000
111
112
112
113
/* Other constants */
113
- #define SBEFIFO_MAX_CMD_LEN PAGE_SIZE
114
+ #define SBEFIFO_MAX_USER_CMD_LEN (0x100000 + PAGE_SIZE)
114
115
#define SBEFIFO_RESET_MAGIC 0x52534554 /* "RSET" */
115
116
116
117
struct sbefifo {
@@ -128,6 +129,7 @@ struct sbefifo {
128
129
struct sbefifo_user {
129
130
struct sbefifo * sbefifo ;
130
131
struct mutex file_lock ;
132
+ void * cmd_page ;
131
133
void * pending_cmd ;
132
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
728
return - ENODEV ;
727
729
if (WARN_ON_ONCE (sbefifo -> magic != SBEFIFO_MAGIC ))
728
730
return - ENODEV ;
729
- if (!resp_len || !command || !response || cmd_len > SBEFIFO_MAX_CMD_LEN )
731
+ if (!resp_len || !command || !response )
730
732
return - EINVAL ;
731
733
732
734
/* Prepare iov iterator */
@@ -751,6 +753,15 @@ EXPORT_SYMBOL_GPL(sbefifo_submit);
751
753
/*
752
754
* Char device interface
753
755
*/
756
+
757
+ static 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
+
754
765
static int sbefifo_user_open (struct inode * inode , struct file * file )
755
766
{
756
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
774
file -> private_data = user ;
764
775
user -> sbefifo = sbefifo ;
765
- user -> pending_cmd = (void * )__get_free_page (GFP_KERNEL );
766
- if (!user -> pending_cmd ) {
776
+ user -> cmd_page = (void * )__get_free_page (GFP_KERNEL );
777
+ if (!user -> cmd_page ) {
767
778
kfree (user );
768
779
return - ENOMEM ;
769
780
}
@@ -816,7 +827,7 @@ static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
816
827
/* Extract the response length */
817
828
rc = len - iov_iter_count (& resp_iter );
818
829
bail :
819
- user -> pending_len = 0 ;
830
+ sbefifo_release_command ( user ) ;
820
831
mutex_unlock (& user -> file_lock );
821
832
return rc ;
822
833
}
@@ -831,13 +842,23 @@ static ssize_t sbefifo_user_write(struct file *file, const char __user *buf,
831
842
if (!user )
832
843
return - EINVAL ;
833
844
sbefifo = user -> sbefifo ;
834
- if (len > SBEFIFO_MAX_CMD_LEN )
845
+ if (len > SBEFIFO_MAX_USER_CMD_LEN )
835
846
return - EINVAL ;
836
847
if (len & 3 )
837
848
return - EINVAL ;
838
849
839
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
862
/* Copy the command into the staging buffer */
842
863
if (copy_from_user (user -> pending_cmd , buf , len )) {
843
864
rc = - EFAULT ;
@@ -863,6 +884,9 @@ static ssize_t sbefifo_user_write(struct file *file, const char __user *buf,
863
884
/* Update the staging buffer size */
864
885
user -> pending_len = len ;
865
886
bail :
887
+ if (!user -> pending_len )
888
+ sbefifo_release_command (user );
889
+
866
890
mutex_unlock (& user -> file_lock );
867
891
868
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
900
if (!user )
877
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
905
kfree (user );
881
906
882
907
return 0 ;
0 commit comments