diff options
author | Richard Cochran <richardcochran@gmail.com> | 2012-11-25 20:44:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-26 17:22:14 -0500 |
commit | c7ec0badcc54508d3ab052bb425cc677521a89be (patch) | |
tree | 9f34a5b1194510dba1bb1ff8e294c5726391e2f3 | |
parent | cfd1979e81c72386cb4dad51a957d6f154f23525 (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.c | 22 |
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 | |||
139 | ssize_t ptp_read(struct posix_clock *pc, | 142 | ssize_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 | } |