diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-08-25 20:34:27 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-08-25 20:46:12 -0400 |
commit | 85f1cb60157e06d9e8996b02fad9ba6964523d75 (patch) | |
tree | f4e5ebe8284718a50a67351d4d63b701b1a1e605 /arch | |
parent | 4b46ca701bdcdc19fcf32823f9fcabf8236e4e78 (diff) |
x86: msr: correct return value on partial operations
Return the correct return value when the MSR driver partially
completes a request (we should return the number of bytes actually
read or written, instead of the error code.)
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/msr.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 9c34a1005dba..2e2af5d18191 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
@@ -72,7 +72,8 @@ static ssize_t msr_read(struct file *file, char __user *buf, | |||
72 | u32 data[2]; | 72 | u32 data[2]; |
73 | u32 reg = *ppos; | 73 | u32 reg = *ppos; |
74 | int cpu = iminor(file->f_path.dentry->d_inode); | 74 | int cpu = iminor(file->f_path.dentry->d_inode); |
75 | int err; | 75 | int err = 0; |
76 | ssize_t bytes = 0; | ||
76 | 77 | ||
77 | if (count % 8) | 78 | if (count % 8) |
78 | return -EINVAL; /* Invalid chunk size */ | 79 | return -EINVAL; /* Invalid chunk size */ |
@@ -82,14 +83,17 @@ static ssize_t msr_read(struct file *file, char __user *buf, | |||
82 | if (err) { | 83 | if (err) { |
83 | if (err == -EFAULT) /* Fix idiotic error code */ | 84 | if (err == -EFAULT) /* Fix idiotic error code */ |
84 | err = -EIO; | 85 | err = -EIO; |
85 | return err; | 86 | break; |
87 | } | ||
88 | if (copy_to_user(tmp, &data, 8)) { | ||
89 | err = -EFAULT; | ||
90 | break; | ||
86 | } | 91 | } |
87 | if (copy_to_user(tmp, &data, 8)) | ||
88 | return -EFAULT; | ||
89 | tmp += 2; | 92 | tmp += 2; |
93 | bytes += 8; | ||
90 | } | 94 | } |
91 | 95 | ||
92 | return ((char __user *)tmp) - buf; | 96 | return bytes ? bytes : err; |
93 | } | 97 | } |
94 | 98 | ||
95 | static ssize_t msr_write(struct file *file, const char __user *buf, | 99 | static ssize_t msr_write(struct file *file, const char __user *buf, |
@@ -99,24 +103,28 @@ static ssize_t msr_write(struct file *file, const char __user *buf, | |||
99 | u32 data[2]; | 103 | u32 data[2]; |
100 | u32 reg = *ppos; | 104 | u32 reg = *ppos; |
101 | int cpu = iminor(file->f_path.dentry->d_inode); | 105 | int cpu = iminor(file->f_path.dentry->d_inode); |
102 | int err; | 106 | int err = 0; |
107 | ssize_t bytes = 0; | ||
103 | 108 | ||
104 | if (count % 8) | 109 | if (count % 8) |
105 | return -EINVAL; /* Invalid chunk size */ | 110 | return -EINVAL; /* Invalid chunk size */ |
106 | 111 | ||
107 | for (; count; count -= 8) { | 112 | for (; count; count -= 8) { |
108 | if (copy_from_user(&data, tmp, 8)) | 113 | if (copy_from_user(&data, tmp, 8)) { |
109 | return -EFAULT; | 114 | err = -EFAULT; |
115 | break; | ||
116 | } | ||
110 | err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); | 117 | err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); |
111 | if (err) { | 118 | if (err) { |
112 | if (err == -EFAULT) /* Fix idiotic error code */ | 119 | if (err == -EFAULT) /* Fix idiotic error code */ |
113 | err = -EIO; | 120 | err = -EIO; |
114 | return err; | 121 | break; |
115 | } | 122 | } |
116 | tmp += 2; | 123 | tmp += 2; |
124 | bytes += 8; | ||
117 | } | 125 | } |
118 | 126 | ||
119 | return ((char __user *)tmp) - buf; | 127 | return bytes ? bytes : err; |
120 | } | 128 | } |
121 | 129 | ||
122 | static int msr_open(struct inode *inode, struct file *file) | 130 | static int msr_open(struct inode *inode, struct file *file) |