aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDennis Dalessandro <dennis.dalessandro@intel.com>2016-05-19 08:26:24 -0400
committerDoug Ledford <dledford@redhat.com>2016-05-26 11:35:06 -0400
commit8d970cf991a6c38a5566572979487b906d643740 (patch)
treee538a501c86b9e7803461b3476d6175e01b65692
parentac56f162d4586885238da05131c4e6bbdb536d4e (diff)
IB/hfi1: Add ioctl() interface for user commands
IOCTL is more suited to what user space commands need to do than the write() interface. Add IOCTL definitions for all existing write commands and the handling for those. The write() interface will be removed in a follow on patch. Reviewed-by: Mitko Haralanov <mitko.haralanov@intel.com> Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/staging/rdma/hfi1/common.h5
-rw-r--r--drivers/staging/rdma/hfi1/file_ops.c204
-rw-r--r--include/uapi/rdma/hfi/hfi1_user.h45
3 files changed, 253 insertions, 1 deletions
diff --git a/drivers/staging/rdma/hfi1/common.h b/drivers/staging/rdma/hfi1/common.h
index e9b6bb322025..fcc9c217a97a 100644
--- a/drivers/staging/rdma/hfi1/common.h
+++ b/drivers/staging/rdma/hfi1/common.h
@@ -178,7 +178,8 @@
178 HFI1_CAP_PKEY_CHECK | \ 178 HFI1_CAP_PKEY_CHECK | \
179 HFI1_CAP_NO_INTEGRITY) 179 HFI1_CAP_NO_INTEGRITY)
180 180
181#define HFI1_USER_SWVERSION ((HFI1_USER_SWMAJOR << 16) | HFI1_USER_SWMINOR) 181#define HFI1_USER_SWVERSION ((HFI1_USER_SWMAJOR << HFI1_SWMAJOR_SHIFT) | \
182 HFI1_USER_SWMINOR)
182 183
183#ifndef HFI1_KERN_TYPE 184#ifndef HFI1_KERN_TYPE
184#define HFI1_KERN_TYPE 0 185#define HFI1_KERN_TYPE 0
@@ -349,6 +350,8 @@ struct hfi1_message_header {
349#define HFI1_BECN_MASK 1 350#define HFI1_BECN_MASK 1
350#define HFI1_BECN_SMASK BIT(HFI1_BECN_SHIFT) 351#define HFI1_BECN_SMASK BIT(HFI1_BECN_SHIFT)
351 352
353#define HFI1_PSM_IOC_BASE_SEQ 0x0
354
352static inline __u64 rhf_to_cpu(const __le32 *rbuf) 355static inline __u64 rhf_to_cpu(const __le32 *rbuf)
353{ 356{
354 return __le64_to_cpu(*((__le64 *)rbuf)); 357 return __le64_to_cpu(*((__le64 *)rbuf));
diff --git a/drivers/staging/rdma/hfi1/file_ops.c b/drivers/staging/rdma/hfi1/file_ops.c
index 322e55f7b4b4..a338238bef92 100644
--- a/drivers/staging/rdma/hfi1/file_ops.c
+++ b/drivers/staging/rdma/hfi1/file_ops.c
@@ -96,6 +96,8 @@ static int user_event_ack(struct hfi1_ctxtdata *, int, unsigned long);
96static int set_ctxt_pkey(struct hfi1_ctxtdata *, unsigned, u16); 96static int set_ctxt_pkey(struct hfi1_ctxtdata *, unsigned, u16);
97static int manage_rcvq(struct hfi1_ctxtdata *, unsigned, int); 97static int manage_rcvq(struct hfi1_ctxtdata *, unsigned, int);
98static int vma_fault(struct vm_area_struct *, struct vm_fault *); 98static int vma_fault(struct vm_area_struct *, struct vm_fault *);
99static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
100 unsigned long arg);
99 101
100static const struct file_operations hfi1_file_ops = { 102static const struct file_operations hfi1_file_ops = {
101 .owner = THIS_MODULE, 103 .owner = THIS_MODULE,
@@ -103,6 +105,7 @@ static const struct file_operations hfi1_file_ops = {
103 .write_iter = hfi1_write_iter, 105 .write_iter = hfi1_write_iter,
104 .open = hfi1_file_open, 106 .open = hfi1_file_open,
105 .release = hfi1_file_close, 107 .release = hfi1_file_close,
108 .unlocked_ioctl = hfi1_file_ioctl,
106 .poll = hfi1_poll, 109 .poll = hfi1_poll,
107 .mmap = hfi1_file_mmap, 110 .mmap = hfi1_file_mmap,
108 .llseek = noop_llseek, 111 .llseek = noop_llseek,
@@ -175,6 +178,207 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
175 return fp->private_data ? 0 : -ENOMEM; 178 return fp->private_data ? 0 : -ENOMEM;
176} 179}
177 180
181static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
182 unsigned long arg)
183{
184 struct hfi1_filedata *fd = fp->private_data;
185 struct hfi1_ctxtdata *uctxt = fd->uctxt;
186 struct hfi1_user_info uinfo;
187 struct hfi1_tid_info tinfo;
188 int ret = 0;
189 unsigned long addr;
190 int uval = 0;
191 unsigned long ul_uval = 0;
192 u16 uval16 = 0;
193
194 if (cmd != HFI1_IOCTL_ASSIGN_CTXT &&
195 cmd != HFI1_IOCTL_GET_VERS &&
196 !uctxt)
197 return -EINVAL;
198
199 switch (cmd) {
200 case HFI1_IOCTL_ASSIGN_CTXT:
201 if (copy_from_user(&uinfo,
202 (struct hfi1_user_info __user *)arg,
203 sizeof(uinfo)))
204 return -EFAULT;
205
206 ret = assign_ctxt(fp, &uinfo);
207 if (ret < 0)
208 return ret;
209 setup_ctxt(fp);
210 if (ret)
211 return ret;
212 ret = user_init(fp);
213 break;
214 case HFI1_IOCTL_CTXT_INFO:
215 ret = get_ctxt_info(fp, (void __user *)(unsigned long)arg,
216 sizeof(struct hfi1_ctxt_info));
217 break;
218 case HFI1_IOCTL_USER_INFO:
219 ret = get_base_info(fp, (void __user *)(unsigned long)arg,
220 sizeof(struct hfi1_base_info));
221 break;
222 case HFI1_IOCTL_CREDIT_UPD:
223 if (uctxt && uctxt->sc)
224 sc_return_credits(uctxt->sc);
225 break;
226
227 case HFI1_IOCTL_TID_UPDATE:
228 if (copy_from_user(&tinfo,
229 (struct hfi11_tid_info __user *)arg,
230 sizeof(tinfo)))
231 return -EFAULT;
232
233 ret = hfi1_user_exp_rcv_setup(fp, &tinfo);
234 if (!ret) {
235 /*
236 * Copy the number of tidlist entries we used
237 * and the length of the buffer we registered.
238 * These fields are adjacent in the structure so
239 * we can copy them at the same time.
240 */
241 addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
242 if (copy_to_user((void __user *)addr, &tinfo.tidcnt,
243 sizeof(tinfo.tidcnt) +
244 sizeof(tinfo.length)))
245 ret = -EFAULT;
246 }
247 break;
248
249 case HFI1_IOCTL_TID_FREE:
250 if (copy_from_user(&tinfo,
251 (struct hfi11_tid_info __user *)arg,
252 sizeof(tinfo)))
253 return -EFAULT;
254
255 ret = hfi1_user_exp_rcv_clear(fp, &tinfo);
256 if (ret)
257 break;
258 addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
259 if (copy_to_user((void __user *)addr, &tinfo.tidcnt,
260 sizeof(tinfo.tidcnt)))
261 ret = -EFAULT;
262 break;
263
264 case HFI1_IOCTL_TID_INVAL_READ:
265 if (copy_from_user(&tinfo,
266 (struct hfi11_tid_info __user *)arg,
267 sizeof(tinfo)))
268 return -EFAULT;
269
270 ret = hfi1_user_exp_rcv_invalid(fp, &tinfo);
271 if (ret)
272 break;
273 addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
274 if (copy_to_user((void __user *)addr, &tinfo.tidcnt,
275 sizeof(tinfo.tidcnt)))
276 ret = -EFAULT;
277 break;
278
279 case HFI1_IOCTL_RECV_CTRL:
280 ret = get_user(uval, (int __user *)arg);
281 if (ret != 0)
282 return -EFAULT;
283 ret = manage_rcvq(uctxt, fd->subctxt, uval);
284 break;
285
286 case HFI1_IOCTL_POLL_TYPE:
287 ret = get_user(uval, (int __user *)arg);
288 if (ret != 0)
289 return -EFAULT;
290 uctxt->poll_type = (typeof(uctxt->poll_type))uval;
291 break;
292
293 case HFI1_IOCTL_ACK_EVENT:
294 ret = get_user(ul_uval, (unsigned long __user *)arg);
295 if (ret != 0)
296 return -EFAULT;
297 ret = user_event_ack(uctxt, fd->subctxt, ul_uval);
298 break;
299
300 case HFI1_IOCTL_SET_PKEY:
301 ret = get_user(uval16, (u16 __user *)arg);
302 if (ret != 0)
303 return -EFAULT;
304 if (HFI1_CAP_IS_USET(PKEY_CHECK))
305 ret = set_ctxt_pkey(uctxt, fd->subctxt, uval16);
306 else
307 return -EPERM;
308 break;
309
310 case HFI1_IOCTL_CTXT_RESET: {
311 struct send_context *sc;
312 struct hfi1_devdata *dd;
313
314 if (!uctxt || !uctxt->dd || !uctxt->sc)
315 return -EINVAL;
316
317 /*
318 * There is no protection here. User level has to
319 * guarantee that no one will be writing to the send
320 * context while it is being re-initialized.
321 * If user level breaks that guarantee, it will break
322 * it's own context and no one else's.
323 */
324 dd = uctxt->dd;
325 sc = uctxt->sc;
326 /*
327 * Wait until the interrupt handler has marked the
328 * context as halted or frozen. Report error if we time
329 * out.
330 */
331 wait_event_interruptible_timeout(
332 sc->halt_wait, (sc->flags & SCF_HALTED),
333 msecs_to_jiffies(SEND_CTXT_HALT_TIMEOUT));
334 if (!(sc->flags & SCF_HALTED))
335 return -ENOLCK;
336
337 /*
338 * If the send context was halted due to a Freeze,
339 * wait until the device has been "unfrozen" before
340 * resetting the context.
341 */
342 if (sc->flags & SCF_FROZEN) {
343 wait_event_interruptible_timeout(
344 dd->event_queue,
345 !(ACCESS_ONCE(dd->flags) & HFI1_FROZEN),
346 msecs_to_jiffies(SEND_CTXT_HALT_TIMEOUT));
347 if (dd->flags & HFI1_FROZEN)
348 return -ENOLCK;
349
350 if (dd->flags & HFI1_FORCED_FREEZE)
351 /*
352 * Don't allow context reset if we are into
353 * forced freeze
354 */
355 return -ENODEV;
356
357 sc_disable(sc);
358 ret = sc_enable(sc);
359 hfi1_rcvctrl(dd, HFI1_RCVCTRL_CTXT_ENB,
360 uctxt->ctxt);
361 } else {
362 ret = sc_restart(sc);
363 }
364 if (!ret)
365 sc_return_credits(sc);
366 break;
367 }
368
369 case HFI1_IOCTL_GET_VERS:
370 uval = HFI1_USER_SWVERSION;
371 if (put_user(uval, (int __user *)arg))
372 return -EFAULT;
373 break;
374
375 default:
376 return -EINVAL;
377 }
378
379 return ret;
380}
381
178static ssize_t hfi1_file_write(struct file *fp, const char __user *data, 382static ssize_t hfi1_file_write(struct file *fp, const char __user *data,
179 size_t count, loff_t *offset) 383 size_t count, loff_t *offset)
180{ 384{
diff --git a/include/uapi/rdma/hfi/hfi1_user.h b/include/uapi/rdma/hfi/hfi1_user.h
index aa48fbe016af..9784159c9d52 100644
--- a/include/uapi/rdma/hfi/hfi1_user.h
+++ b/include/uapi/rdma/hfi/hfi1_user.h
@@ -78,6 +78,11 @@
78#define HFI1_USER_SWMINOR 1 78#define HFI1_USER_SWMINOR 1
79 79
80/* 80/*
81 * We will encode the major/minor inside a single 32bit version number.
82 */
83#define HFI1_SWMAJOR_SHIFT 16
84
85/*
81 * Set of HW and driver capability/feature bits. 86 * Set of HW and driver capability/feature bits.
82 * These bit values are used to configure enabled/disabled HW and 87 * These bit values are used to configure enabled/disabled HW and
83 * driver features. The same set of bits are communicated to user 88 * driver features. The same set of bits are communicated to user
@@ -121,6 +126,46 @@
121#define HFI1_CMD_SET_PKEY 11 /* set context's pkey */ 126#define HFI1_CMD_SET_PKEY 11 /* set context's pkey */
122#define HFI1_CMD_CTXT_RESET 12 /* reset context's HW send context */ 127#define HFI1_CMD_CTXT_RESET 12 /* reset context's HW send context */
123#define HFI1_CMD_TID_INVAL_READ 13 /* read TID cache invalidations */ 128#define HFI1_CMD_TID_INVAL_READ 13 /* read TID cache invalidations */
129#define HFI1_CMD_GET_VERS 14 /* get the version of the user cdev */
130
131/*
132 * User IOCTLs can not go above 128 if they do then see common.h and change the
133 * base for the snoop ioctl
134 */
135#define IB_IOCTL_MAGIC 0x1b /* See Documentation/ioctl/ioctl-number.txt */
136
137/*
138 * Make the ioctls occupy the last 0xf0-0xff portion of the IB range
139 */
140#define __NUM(cmd) (HFI1_CMD_##cmd + 0xe0)
141
142struct hfi1_cmd;
143#define HFI1_IOCTL_ASSIGN_CTXT \
144 _IOWR(IB_IOCTL_MAGIC, __NUM(ASSIGN_CTXT), struct hfi1_user_info)
145#define HFI1_IOCTL_CTXT_INFO \
146 _IOW(IB_IOCTL_MAGIC, __NUM(CTXT_INFO), struct hfi1_ctxt_info)
147#define HFI1_IOCTL_USER_INFO \
148 _IOW(IB_IOCTL_MAGIC, __NUM(USER_INFO), struct hfi1_base_info)
149#define HFI1_IOCTL_TID_UPDATE \
150 _IOWR(IB_IOCTL_MAGIC, __NUM(TID_UPDATE), struct hfi1_tid_info)
151#define HFI1_IOCTL_TID_FREE \
152 _IOWR(IB_IOCTL_MAGIC, __NUM(TID_FREE), struct hfi1_tid_info)
153#define HFI1_IOCTL_CREDIT_UPD \
154 _IO(IB_IOCTL_MAGIC, __NUM(CREDIT_UPD))
155#define HFI1_IOCTL_RECV_CTRL \
156 _IOW(IB_IOCTL_MAGIC, __NUM(RECV_CTRL), int)
157#define HFI1_IOCTL_POLL_TYPE \
158 _IOW(IB_IOCTL_MAGIC, __NUM(POLL_TYPE), int)
159#define HFI1_IOCTL_ACK_EVENT \
160 _IOW(IB_IOCTL_MAGIC, __NUM(ACK_EVENT), unsigned long)
161#define HFI1_IOCTL_SET_PKEY \
162 _IOW(IB_IOCTL_MAGIC, __NUM(SET_PKEY), __u16)
163#define HFI1_IOCTL_CTXT_RESET \
164 _IO(IB_IOCTL_MAGIC, __NUM(CTXT_RESET))
165#define HFI1_IOCTL_TID_INVAL_READ \
166 _IOWR(IB_IOCTL_MAGIC, __NUM(TID_INVAL_READ), struct hfi1_tid_info)
167#define HFI1_IOCTL_GET_VERS \
168 _IOR(IB_IOCTL_MAGIC, __NUM(GET_VERS), int)
124 169
125#define _HFI1_EVENT_FROZEN_BIT 0 170#define _HFI1_EVENT_FROZEN_BIT 0
126#define _HFI1_EVENT_LINKDOWN_BIT 1 171#define _HFI1_EVENT_LINKDOWN_BIT 1