aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Cochran <richardcochran@gmail.com>2012-11-25 20:44:34 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-26 17:22:14 -0500
commitc7ec0badcc54508d3ab052bb425cc677521a89be (patch)
tree9f34a5b1194510dba1bb1ff8e294c5726391e2f3
parentcfd1979e81c72386cb4dad51a957d6f154f23525 (diff)
ptp: reduce stack usage when reading external time stamps
This patch removes the large buffer from the stack of the read file operation and replaces it with a kmalloced buffer. Signed-off-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/ptp/ptp_chardev.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 4f8ae8057a7e..9d7542efb175 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -21,6 +21,7 @@
21#include <linux/posix-clock.h> 21#include <linux/posix-clock.h>
22#include <linux/poll.h> 22#include <linux/poll.h>
23#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/slab.h>
24 25
25#include "ptp_private.h" 26#include "ptp_private.h"
26 27
@@ -136,20 +137,23 @@ unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
136 return queue_cnt(&ptp->tsevq) ? POLLIN : 0; 137 return queue_cnt(&ptp->tsevq) ? POLLIN : 0;
137} 138}
138 139
140#define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))
141
139ssize_t ptp_read(struct posix_clock *pc, 142ssize_t ptp_read(struct posix_clock *pc,
140 uint rdflags, char __user *buf, size_t cnt) 143 uint rdflags, char __user *buf, size_t cnt)
141{ 144{
142 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); 145 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
143 struct timestamp_event_queue *queue = &ptp->tsevq; 146 struct timestamp_event_queue *queue = &ptp->tsevq;
144 struct ptp_extts_event event[PTP_BUF_TIMESTAMPS]; 147 struct ptp_extts_event *event;
145 unsigned long flags; 148 unsigned long flags;
146 size_t qcnt, i; 149 size_t qcnt, i;
150 int result;
147 151
148 if (cnt % sizeof(struct ptp_extts_event) != 0) 152 if (cnt % sizeof(struct ptp_extts_event) != 0)
149 return -EINVAL; 153 return -EINVAL;
150 154
151 if (cnt > sizeof(event)) 155 if (cnt > EXTTS_BUFSIZE)
152 cnt = sizeof(event); 156 cnt = EXTTS_BUFSIZE;
153 157
154 cnt = cnt / sizeof(struct ptp_extts_event); 158 cnt = cnt / sizeof(struct ptp_extts_event);
155 159
@@ -167,6 +171,12 @@ ssize_t ptp_read(struct posix_clock *pc,
167 return -ENODEV; 171 return -ENODEV;
168 } 172 }
169 173
174 event = kmalloc(EXTTS_BUFSIZE, GFP_KERNEL);
175 if (!event) {
176 mutex_unlock(&ptp->tsevq_mux);
177 return -ENOMEM;
178 }
179
170 spin_lock_irqsave(&queue->lock, flags); 180 spin_lock_irqsave(&queue->lock, flags);
171 181
172 qcnt = queue_cnt(queue); 182 qcnt = queue_cnt(queue);
@@ -185,8 +195,10 @@ ssize_t ptp_read(struct posix_clock *pc,
185 195
186 mutex_unlock(&ptp->tsevq_mux); 196 mutex_unlock(&ptp->tsevq_mux);
187 197
198 result = cnt;
188 if (copy_to_user(buf, event, cnt)) 199 if (copy_to_user(buf, event, cnt))
189 return -EFAULT; 200 result = -EFAULT;
190 201
191 return cnt; 202 kfree(event);
203 return result;
192} 204}