Commit 88a69b65 authored by Michael J. Ruhl's avatar Michael J. Ruhl Committed by Doug Ledford

IB/hfi1: Refactor get_user() IOCTLs

The IOCTL is a bit unwieldy.  Refactor to a common pattern.
Refactor _RECV_CTRL, _POLL_TYPE, _ACK_EVENT and _SET_PKEY
IOCTLs to a common pattern.
Reviewed-by: default avatarIra Weiny <ira.weiny@intel.com>
Signed-off-by: default avatarMichael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 8a41da09
...@@ -105,10 +105,10 @@ static void deallocate_ctxt(struct hfi1_ctxtdata *uctxt); ...@@ -105,10 +105,10 @@ static void deallocate_ctxt(struct hfi1_ctxtdata *uctxt);
static unsigned int poll_urgent(struct file *fp, struct poll_table_struct *pt); static unsigned int poll_urgent(struct file *fp, struct poll_table_struct *pt);
static unsigned int poll_next(struct file *fp, struct poll_table_struct *pt); static unsigned int poll_next(struct file *fp, struct poll_table_struct *pt);
static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt, static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt,
unsigned long events); unsigned long arg);
static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, u16 subctxt, u16 pkey); static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned long arg);
static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt, static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
int start_stop); unsigned long arg);
static int vma_fault(struct vm_fault *vmf); static int vma_fault(struct vm_fault *vmf);
static long hfi1_file_ioctl(struct file *fp, unsigned int cmd, static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
unsigned long arg); unsigned long arg);
...@@ -227,8 +227,6 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd, ...@@ -227,8 +227,6 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
struct hfi1_ctxtdata *uctxt = fd->uctxt; struct hfi1_ctxtdata *uctxt = fd->uctxt;
int ret = 0; int ret = 0;
int uval = 0; int uval = 0;
unsigned long ul_uval = 0;
u16 uval16 = 0;
hfi1_cdbg(IOCTL, "IOCTL recv: 0x%x", cmd); hfi1_cdbg(IOCTL, "IOCTL recv: 0x%x", cmd);
if (cmd != HFI1_IOCTL_ASSIGN_CTXT && if (cmd != HFI1_IOCTL_ASSIGN_CTXT &&
...@@ -267,34 +265,21 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd, ...@@ -267,34 +265,21 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
break; break;
case HFI1_IOCTL_RECV_CTRL: case HFI1_IOCTL_RECV_CTRL:
ret = get_user(uval, (int __user *)arg); ret = manage_rcvq(uctxt, fd->subctxt, arg);
if (ret != 0)
return -EFAULT;
ret = manage_rcvq(uctxt, fd->subctxt, uval);
break; break;
case HFI1_IOCTL_POLL_TYPE: case HFI1_IOCTL_POLL_TYPE:
ret = get_user(uval, (int __user *)arg); if (get_user(uval, (int __user *)arg))
if (ret != 0)
return -EFAULT; return -EFAULT;
uctxt->poll_type = (typeof(uctxt->poll_type))uval; uctxt->poll_type = (typeof(uctxt->poll_type))uval;
break; break;
case HFI1_IOCTL_ACK_EVENT: case HFI1_IOCTL_ACK_EVENT:
ret = get_user(ul_uval, (unsigned long __user *)arg); ret = user_event_ack(uctxt, fd->subctxt, arg);
if (ret != 0)
return -EFAULT;
ret = user_event_ack(uctxt, fd->subctxt, ul_uval);
break; break;
case HFI1_IOCTL_SET_PKEY: case HFI1_IOCTL_SET_PKEY:
ret = get_user(uval16, (u16 __user *)arg); ret = set_ctxt_pkey(uctxt, arg);
if (ret != 0)
return -EFAULT;
if (HFI1_CAP_IS_USET(PKEY_CHECK))
ret = set_ctxt_pkey(uctxt, fd->subctxt, uval16);
else
return -EPERM;
break; break;
case HFI1_IOCTL_CTXT_RESET: { case HFI1_IOCTL_CTXT_RESET: {
...@@ -1584,13 +1569,18 @@ int hfi1_set_uevent_bits(struct hfi1_pportdata *ppd, const int evtbit) ...@@ -1584,13 +1569,18 @@ int hfi1_set_uevent_bits(struct hfi1_pportdata *ppd, const int evtbit)
* re-init the software copy of the head register * re-init the software copy of the head register
*/ */
static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt, static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
int start_stop) unsigned long arg)
{ {
struct hfi1_devdata *dd = uctxt->dd; struct hfi1_devdata *dd = uctxt->dd;
unsigned int rcvctrl_op; unsigned int rcvctrl_op;
int start_stop;
if (subctxt) if (subctxt)
goto bail; return 0;
if (get_user(start_stop, (int __user *)arg))
return -EFAULT;
/* atomically clear receive enable ctxt. */ /* atomically clear receive enable ctxt. */
if (start_stop) { if (start_stop) {
/* /*
...@@ -1609,7 +1599,7 @@ static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt, ...@@ -1609,7 +1599,7 @@ static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
} }
hfi1_rcvctrl(dd, rcvctrl_op, uctxt); hfi1_rcvctrl(dd, rcvctrl_op, uctxt);
/* always; new head should be equal to new tail; see above */ /* always; new head should be equal to new tail; see above */
bail:
return 0; return 0;
} }
...@@ -1619,15 +1609,19 @@ static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt, ...@@ -1619,15 +1609,19 @@ static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
* set, if desired, and checks again in future. * set, if desired, and checks again in future.
*/ */
static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt, static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt,
unsigned long events) unsigned long arg)
{ {
int i; int i;
struct hfi1_devdata *dd = uctxt->dd; struct hfi1_devdata *dd = uctxt->dd;
unsigned long *evs; unsigned long *evs;
unsigned long events;
if (!dd->events) if (!dd->events)
return 0; return 0;
if (get_user(events, (unsigned long __user *)arg))
return -EFAULT;
evs = dd->events + uctxt_offset(uctxt) + subctxt; evs = dd->events + uctxt_offset(uctxt) + subctxt;
for (i = 0; i <= _HFI1_MAX_EVENT_BIT; i++) { for (i = 0; i <= _HFI1_MAX_EVENT_BIT; i++) {
...@@ -1638,27 +1632,27 @@ static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt, ...@@ -1638,27 +1632,27 @@ static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt,
return 0; return 0;
} }
static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, u16 subctxt, u16 pkey) static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned long arg)
{ {
int ret = -ENOENT, i, intable = 0; int i;
struct hfi1_pportdata *ppd = uctxt->ppd; struct hfi1_pportdata *ppd = uctxt->ppd;
struct hfi1_devdata *dd = uctxt->dd; struct hfi1_devdata *dd = uctxt->dd;
u16 pkey;
if (pkey == LIM_MGMT_P_KEY || pkey == FULL_MGMT_P_KEY) { if (!HFI1_CAP_IS_USET(PKEY_CHECK))
ret = -EINVAL; return -EPERM;
goto done;
} if (get_user(pkey, (u16 __user *)arg))
return -EFAULT;
if (pkey == LIM_MGMT_P_KEY || pkey == FULL_MGMT_P_KEY)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(ppd->pkeys); i++) for (i = 0; i < ARRAY_SIZE(ppd->pkeys); i++)
if (pkey == ppd->pkeys[i]) { if (pkey == ppd->pkeys[i])
intable = 1; return hfi1_set_ctxt_pkey(dd, uctxt, pkey);
break;
}
if (intable) return -ENOENT;
ret = hfi1_set_ctxt_pkey(dd, uctxt, pkey);
done:
return ret;
} }
static void user_remove(struct hfi1_devdata *dd) static void user_remove(struct hfi1_devdata *dd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment