From 03dd4cb26d967f9588437b0fc9cc0e8353322bb7 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Fri, 25 Mar 2016 03:53:42 -0300 Subject: Linux-libre 4.5-gnu --- drivers/staging/rdma/hfi1/diag.c | 499 +++++++++++++++++++-------------------- 1 file changed, 242 insertions(+), 257 deletions(-) (limited to 'drivers/staging/rdma/hfi1/diag.c') diff --git a/drivers/staging/rdma/hfi1/diag.c b/drivers/staging/rdma/hfi1/diag.c index 88414d720..0c8831705 100644 --- a/drivers/staging/rdma/hfi1/diag.c +++ b/drivers/staging/rdma/hfi1/diag.c @@ -78,8 +78,8 @@ hfi1_cdbg(SNOOP, fmt, ##__VA_ARGS__) /* Snoop option mask */ -#define SNOOP_DROP_SEND (1 << 0) -#define SNOOP_USE_METADATA (1 << 1) +#define SNOOP_DROP_SEND BIT(0) +#define SNOOP_USE_METADATA BIT(1) static u8 snoop_flags; @@ -135,7 +135,7 @@ static struct cdev diagpkt_cdev; static struct device *diagpkt_device; static ssize_t diagpkt_write(struct file *fp, const char __user *data, - size_t count, loff_t *off); + size_t count, loff_t *off); static const struct file_operations diagpkt_file_ops = { .owner = THIS_MODULE, @@ -177,37 +177,37 @@ struct hfi1_link_info { #define HFI1_SNOOP_IOCGETLINKSTATE \ _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ) #define HFI1_SNOOP_IOCSETLINKSTATE \ - _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+1) + _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 1) #define HFI1_SNOOP_IOCCLEARQUEUE \ - _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+2) + _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 2) #define HFI1_SNOOP_IOCCLEARFILTER \ - _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+3) + _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 3) #define HFI1_SNOOP_IOCSETFILTER \ - _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+4) + _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 4) #define HFI1_SNOOP_IOCGETVERSION \ - _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+5) + _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 5) #define HFI1_SNOOP_IOCSET_OPTS \ - _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+6) + _IO(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 6) /* * These offsets +6/+7 could change, but these are already known and used * IOCTL numbers so don't change them without a good reason. */ #define HFI1_SNOOP_IOCGETLINKSTATE_EXTRA \ - _IOWR(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+6, \ + _IOWR(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 6, \ struct hfi1_link_info) #define HFI1_SNOOP_IOCSETLINKSTATE_EXTRA \ - _IOWR(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ+7, \ + _IOWR(HFI1_SNOOP_IOC_MAGIC, HFI1_SNOOP_IOC_BASE_SEQ + 7, \ struct hfi1_link_info) static int hfi1_snoop_open(struct inode *in, struct file *fp); static ssize_t hfi1_snoop_read(struct file *fp, char __user *data, - size_t pkt_len, loff_t *off); + size_t pkt_len, loff_t *off); static ssize_t hfi1_snoop_write(struct file *fp, const char __user *data, - size_t count, loff_t *off); + size_t count, loff_t *off); static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); static unsigned int hfi1_snoop_poll(struct file *fp, - struct poll_table_struct *wait); + struct poll_table_struct *wait); static int hfi1_snoop_release(struct inode *in, struct file *fp); struct hfi1_packet_filter_command { @@ -323,14 +323,12 @@ static void hfi1_snoop_remove(struct hfi1_devdata *dd) void hfi1_diag_remove(struct hfi1_devdata *dd) { - hfi1_snoop_remove(dd); if (atomic_dec_and_test(&diagpkt_count)) hfi1_cdev_cleanup(&diagpkt_cdev, &diagpkt_device); hfi1_cdev_cleanup(&dd->diag_cdev, &dd->diag_device); } - /* * Allocated structure shared between the credit return mechanism and * diagpkt_send(). @@ -379,6 +377,7 @@ static ssize_t diagpkt_send(struct diag_pkt *dp) pio_release_cb credit_cb = NULL; void *credit_arg = NULL; struct diagpkt_wait *wait = NULL; + int trycount = 0; dd = hfi1_lookup(dp->unit); if (!dd || !(dd->flags & HFI1_PRESENT) || !dd->kregbase) { @@ -393,7 +392,7 @@ static ssize_t diagpkt_send(struct diag_pkt *dp) if (dp->version != _DIAG_PKT_VERS) { dd_dev_err(dd, "Invalid version %u for diagpkt_write\n", - dp->version); + dp->version); ret = -EINVAL; goto bail; } @@ -440,7 +439,7 @@ static ssize_t diagpkt_send(struct diag_pkt *dp) } if (copy_from_user(tmpbuf, - (const void __user *) (unsigned long) dp->data, + (const void __user *)(unsigned long)dp->data, dp->len)) { ret = -EFAULT; goto bail; @@ -493,8 +492,15 @@ static ssize_t diagpkt_send(struct diag_pkt *dp) credit_arg = wait; } +retry: pbuf = sc_buffer_alloc(sc, total_len, credit_cb, credit_arg); if (!pbuf) { + if (trycount == 0) { + /* force a credit return and try again */ + sc_return_credits(sc); + trycount = 1; + goto retry; + } /* * No send buffer means no credit callback. Undo * the wait set-up that was done above. We free wait @@ -530,9 +536,9 @@ static ssize_t diagpkt_send(struct diag_pkt *dp) * NOTE: PRC_FILL_ERR is at best informational and cannot * be depended on. */ - if (!ret && (((wait->code & PRC_STATUS_ERR) - || (wait->code & PRC_FILL_ERR) - || (wait->code & PRC_SC_DISABLE)))) + if (!ret && (((wait->code & PRC_STATUS_ERR) || + (wait->code & PRC_FILL_ERR) || + (wait->code & PRC_SC_DISABLE)))) ret = -EIO; put_diagpkt_wait(wait); /* finished with the structure */ @@ -545,7 +551,7 @@ bail: } static ssize_t diagpkt_write(struct file *fp, const char __user *data, - size_t count, loff_t *off) + size_t count, loff_t *off) { struct hfi1_devdata *dd; struct send_context *sc; @@ -565,7 +571,7 @@ static ssize_t diagpkt_write(struct file *fp, const char __user *data, */ if (dp.pbc) { dd = hfi1_lookup(dp.unit); - if (dd == NULL) + if (!dd) return -ENODEV; vl = (dp.pbc >> PBC_VL_SHIFT) & PBC_VL_MASK; sc = dd->vld[vl].sc; @@ -598,7 +604,7 @@ static int hfi1_snoop_add(struct hfi1_devdata *dd, const char *name) if (ret) { dd_dev_err(dd, "Couldn't create %s device: %d", name, ret); hfi1_cdev_cleanup(&dd->hfi1_snoop.cdev, - &dd->hfi1_snoop.class_dev); + &dd->hfi1_snoop.class_dev); } return ret; @@ -611,7 +617,6 @@ static struct hfi1_devdata *hfi1_dd_from_sc_inode(struct inode *in) dd = hfi1_lookup(unit); return dd; - } /* clear or restore send context integrity checks */ @@ -652,7 +657,7 @@ static int hfi1_snoop_open(struct inode *in, struct file *fp) mutex_lock(&hfi1_mutex); dd = hfi1_dd_from_sc_inode(in); - if (dd == NULL) { + if (!dd) { ret = -ENODEV; goto bail; } @@ -739,7 +744,7 @@ static int hfi1_snoop_release(struct inode *in, struct file *fp) int mode_flag; dd = hfi1_dd_from_sc_inode(in); - if (dd == NULL) + if (!dd) return -ENODEV; spin_lock_irqsave(&dd->hfi1_snoop.snoop_lock, flags); @@ -794,7 +799,7 @@ static unsigned int hfi1_snoop_poll(struct file *fp, struct hfi1_devdata *dd; dd = hfi1_dd_from_sc_inode(fp->f_inode); - if (dd == NULL) + if (!dd) return -ENODEV; spin_lock_irqsave(&dd->hfi1_snoop.snoop_lock, flags); @@ -805,7 +810,6 @@ static unsigned int hfi1_snoop_poll(struct file *fp, spin_unlock_irqrestore(&dd->hfi1_snoop.snoop_lock, flags); return ret; - } static ssize_t hfi1_snoop_write(struct file *fp, const char __user *data, @@ -822,7 +826,7 @@ static ssize_t hfi1_snoop_write(struct file *fp, const char __user *data, struct hfi1_pportdata *ppd; dd = hfi1_dd_from_sc_inode(fp->f_inode); - if (dd == NULL) + if (!dd) return -ENODEV; ppd = dd->pport; @@ -847,7 +851,7 @@ static ssize_t hfi1_snoop_write(struct file *fp, const char __user *data, if (copy_from_user(&byte_one, data, 1)) return -EINVAL; - if (copy_from_user(&byte_two, data+1, 1)) + if (copy_from_user(&byte_two, data + 1, 1)) return -EINVAL; sc4 = (byte_one >> 4) & 0xf; @@ -920,7 +924,7 @@ static ssize_t hfi1_snoop_read(struct file *fp, char __user *data, struct hfi1_devdata *dd; dd = hfi1_dd_from_sc_inode(fp->f_inode); - if (dd == NULL) + if (!dd) return -ENODEV; spin_lock_irqsave(&dd->hfi1_snoop.snoop_lock, flags); @@ -946,16 +950,18 @@ static ssize_t hfi1_snoop_read(struct file *fp, char __user *data, spin_unlock_irqrestore(&dd->hfi1_snoop.snoop_lock, flags); if (pkt_len >= packet->total_len) { if (copy_to_user(data, packet->data, - packet->total_len)) + packet->total_len)) ret = -EFAULT; else ret = packet->total_len; - } else + } else { ret = -EINVAL; + } kfree(packet); - } else + } else { spin_unlock_irqrestore(&dd->hfi1_snoop.snoop_lock, flags); + } return ret; } @@ -966,9 +972,9 @@ static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) void *filter_value = NULL; long ret = 0; int value = 0; - u8 physState = 0; - u8 linkState = 0; - u16 devState = 0; + u8 phys_state = 0; + u8 link_state = 0; + u16 dev_state = 0; unsigned long flags = 0; unsigned long *argp = NULL; struct hfi1_packet_filter_command filter_cmd = {0}; @@ -976,237 +982,221 @@ static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) struct hfi1_pportdata *ppd = NULL; unsigned int index; struct hfi1_link_info link_info; + int read_cmd, write_cmd, read_ok, write_ok; dd = hfi1_dd_from_sc_inode(fp->f_inode); - if (dd == NULL) + if (!dd) return -ENODEV; - spin_lock_irqsave(&dd->hfi1_snoop.snoop_lock, flags); - mode_flag = dd->hfi1_snoop.mode_flag; + read_cmd = _IOC_DIR(cmd) & _IOC_READ; + write_cmd = _IOC_DIR(cmd) & _IOC_WRITE; + write_ok = access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + read_ok = access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); - if (((_IOC_DIR(cmd) & _IOC_READ) - && !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd))) - || ((_IOC_DIR(cmd) & _IOC_WRITE) - && !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)))) { - ret = -EFAULT; - } else if (!capable(CAP_SYS_ADMIN)) { - ret = -EPERM; - } else if ((mode_flag & HFI1_PORT_CAPTURE_MODE) && - (cmd != HFI1_SNOOP_IOCCLEARQUEUE) && - (cmd != HFI1_SNOOP_IOCCLEARFILTER) && - (cmd != HFI1_SNOOP_IOCSETFILTER)) { + if ((read_cmd && !write_ok) || (write_cmd && !read_ok)) + return -EFAULT; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if ((mode_flag & HFI1_PORT_CAPTURE_MODE) && + (cmd != HFI1_SNOOP_IOCCLEARQUEUE) && + (cmd != HFI1_SNOOP_IOCCLEARFILTER) && + (cmd != HFI1_SNOOP_IOCSETFILTER)) /* Capture devices are allowed only 3 operations * 1.Clear capture queue * 2.Clear capture filter * 3.Set capture filter * Other are invalid. */ - ret = -EINVAL; - } else { - switch (cmd) { - case HFI1_SNOOP_IOCSETLINKSTATE: - snoop_dbg("HFI1_SNOOP_IOCSETLINKSTATE is not valid"); - ret = -EINVAL; - break; + return -EINVAL; - case HFI1_SNOOP_IOCSETLINKSTATE_EXTRA: - memset(&link_info, 0, sizeof(link_info)); + switch (cmd) { + case HFI1_SNOOP_IOCSETLINKSTATE_EXTRA: + memset(&link_info, 0, sizeof(link_info)); - if (copy_from_user(&link_info, - (struct hfi1_link_info __user *)arg, - sizeof(link_info))) - ret = -EFAULT; + if (copy_from_user(&link_info, + (struct hfi1_link_info __user *)arg, + sizeof(link_info))) + return -EFAULT; - value = link_info.port_state; - index = link_info.port_number; - if (index > dd->num_pports - 1) { - ret = -EINVAL; - break; - } + value = link_info.port_state; + index = link_info.port_number; + if (index > dd->num_pports - 1) + return -EINVAL; - ppd = &dd->pport[index]; - if (!ppd) { - ret = -EINVAL; - break; - } + ppd = &dd->pport[index]; + if (!ppd) + return -EINVAL; - /* What we want to transition to */ - physState = (value >> 4) & 0xF; - linkState = value & 0xF; - snoop_dbg("Setting link state 0x%x", value); - - switch (linkState) { - case IB_PORT_NOP: - if (physState == 0) - break; - /* fall through */ - case IB_PORT_DOWN: - switch (physState) { - case 0: - devState = HLS_DN_DOWNDEF; - break; - case 2: - devState = HLS_DN_POLL; - break; - case 3: - devState = HLS_DN_DISABLE; - break; - default: - ret = -EINVAL; - goto done; - } - ret = set_link_state(ppd, devState); - break; - case IB_PORT_ARMED: - ret = set_link_state(ppd, HLS_UP_ARMED); - if (!ret) - send_idle_sma(dd, SMA_IDLE_ARM); - break; - case IB_PORT_ACTIVE: - ret = set_link_state(ppd, HLS_UP_ACTIVE); - if (!ret) - send_idle_sma(dd, SMA_IDLE_ACTIVE); - break; - default: - ret = -EINVAL; - break; - } + /* What we want to transition to */ + phys_state = (value >> 4) & 0xF; + link_state = value & 0xF; + snoop_dbg("Setting link state 0x%x", value); - if (ret) + switch (link_state) { + case IB_PORT_NOP: + if (phys_state == 0) break; - /* fall through */ - case HFI1_SNOOP_IOCGETLINKSTATE: - case HFI1_SNOOP_IOCGETLINKSTATE_EXTRA: - if (cmd == HFI1_SNOOP_IOCGETLINKSTATE_EXTRA) { - memset(&link_info, 0, sizeof(link_info)); - if (copy_from_user(&link_info, - (struct hfi1_link_info __user *)arg, - sizeof(link_info))) - ret = -EFAULT; - index = link_info.port_number; - } else { - ret = __get_user(index, (int __user *) arg); - if (ret != 0) - break; - } - - if (index > dd->num_pports - 1) { - ret = -EINVAL; + /* fall through */ + case IB_PORT_DOWN: + switch (phys_state) { + case 0: + dev_state = HLS_DN_DOWNDEF; break; - } - - ppd = &dd->pport[index]; - if (!ppd) { - ret = -EINVAL; + case 2: + dev_state = HLS_DN_POLL; break; + case 3: + dev_state = HLS_DN_DISABLE; + break; + default: + return -EINVAL; } - value = hfi1_ibphys_portstate(ppd); - value <<= 4; - value |= driver_lstate(ppd); - - snoop_dbg("Link port | Link State: %d", value); - - if ((cmd == HFI1_SNOOP_IOCGETLINKSTATE_EXTRA) || - (cmd == HFI1_SNOOP_IOCSETLINKSTATE_EXTRA)) { - link_info.port_state = value; - link_info.node_guid = cpu_to_be64(ppd->guid); - link_info.link_speed_active = - ppd->link_speed_active; - link_info.link_width_active = - ppd->link_width_active; - if (copy_to_user( - (struct hfi1_link_info __user *)arg, - &link_info, sizeof(link_info))) - ret = -EFAULT; - } else { - ret = __put_user(value, (int __user *)arg); - } + ret = set_link_state(ppd, dev_state); break; - - case HFI1_SNOOP_IOCCLEARQUEUE: - snoop_dbg("Clearing snoop queue"); - drain_snoop_list(&dd->hfi1_snoop.queue); + case IB_PORT_ARMED: + ret = set_link_state(ppd, HLS_UP_ARMED); + if (!ret) + send_idle_sma(dd, SMA_IDLE_ARM); break; - - case HFI1_SNOOP_IOCCLEARFILTER: - snoop_dbg("Clearing filter"); - if (dd->hfi1_snoop.filter_callback) { - /* Drain packets first */ - drain_snoop_list(&dd->hfi1_snoop.queue); - dd->hfi1_snoop.filter_callback = NULL; - } - kfree(dd->hfi1_snoop.filter_value); - dd->hfi1_snoop.filter_value = NULL; + case IB_PORT_ACTIVE: + ret = set_link_state(ppd, HLS_UP_ACTIVE); + if (!ret) + send_idle_sma(dd, SMA_IDLE_ACTIVE); break; + default: + return -EINVAL; + } - case HFI1_SNOOP_IOCSETFILTER: - snoop_dbg("Setting filter"); - /* just copy command structure */ - argp = (unsigned long *)arg; - if (copy_from_user(&filter_cmd, (void __user *)argp, - sizeof(filter_cmd))) { - ret = -EFAULT; - break; - } - if (filter_cmd.opcode >= HFI1_MAX_FILTERS) { - pr_alert("Invalid opcode in request\n"); - ret = -EINVAL; + if (ret) + break; + /* fall through */ + case HFI1_SNOOP_IOCGETLINKSTATE: + case HFI1_SNOOP_IOCGETLINKSTATE_EXTRA: + if (cmd == HFI1_SNOOP_IOCGETLINKSTATE_EXTRA) { + memset(&link_info, 0, sizeof(link_info)); + if (copy_from_user(&link_info, + (struct hfi1_link_info __user *)arg, + sizeof(link_info))) + return -EFAULT; + index = link_info.port_number; + } else { + ret = __get_user(index, (int __user *)arg); + if (ret != 0) break; - } + } - snoop_dbg("Opcode %d Len %d Ptr %p", - filter_cmd.opcode, filter_cmd.length, - filter_cmd.value_ptr); + if (index > dd->num_pports - 1) + return -EINVAL; - filter_value = kcalloc(filter_cmd.length, sizeof(u8), - GFP_KERNEL); - if (!filter_value) { - pr_alert("Not enough memory\n"); - ret = -ENOMEM; - break; - } - /* copy remaining data from userspace */ - if (copy_from_user((u8 *)filter_value, - (void __user *)filter_cmd.value_ptr, - filter_cmd.length)) { - kfree(filter_value); - ret = -EFAULT; - break; - } + ppd = &dd->pport[index]; + if (!ppd) + return -EINVAL; + + value = hfi1_ibphys_portstate(ppd); + value <<= 4; + value |= driver_lstate(ppd); + + snoop_dbg("Link port | Link State: %d", value); + + if ((cmd == HFI1_SNOOP_IOCGETLINKSTATE_EXTRA) || + (cmd == HFI1_SNOOP_IOCSETLINKSTATE_EXTRA)) { + link_info.port_state = value; + link_info.node_guid = cpu_to_be64(ppd->guid); + link_info.link_speed_active = + ppd->link_speed_active; + link_info.link_width_active = + ppd->link_width_active; + if (copy_to_user((struct hfi1_link_info __user *)arg, + &link_info, sizeof(link_info))) + return -EFAULT; + } else { + ret = __put_user(value, (int __user *)arg); + } + break; + + case HFI1_SNOOP_IOCCLEARQUEUE: + snoop_dbg("Clearing snoop queue"); + spin_lock_irqsave(&dd->hfi1_snoop.snoop_lock, flags); + drain_snoop_list(&dd->hfi1_snoop.queue); + spin_unlock_irqrestore(&dd->hfi1_snoop.snoop_lock, flags); + break; + + case HFI1_SNOOP_IOCCLEARFILTER: + snoop_dbg("Clearing filter"); + spin_lock_irqsave(&dd->hfi1_snoop.snoop_lock, flags); + if (dd->hfi1_snoop.filter_callback) { /* Drain packets first */ drain_snoop_list(&dd->hfi1_snoop.queue); - dd->hfi1_snoop.filter_callback = - hfi1_filters[filter_cmd.opcode].filter; - /* just in case we see back to back sets */ - kfree(dd->hfi1_snoop.filter_value); - dd->hfi1_snoop.filter_value = filter_value; + dd->hfi1_snoop.filter_callback = NULL; + } + kfree(dd->hfi1_snoop.filter_value); + dd->hfi1_snoop.filter_value = NULL; + spin_unlock_irqrestore(&dd->hfi1_snoop.snoop_lock, flags); + break; - break; - case HFI1_SNOOP_IOCGETVERSION: - value = SNOOP_CAPTURE_VERSION; - snoop_dbg("Getting version: %d", value); - ret = __put_user(value, (int __user *)arg); - break; - case HFI1_SNOOP_IOCSET_OPTS: - snoop_flags = 0; - ret = __get_user(value, (int __user *) arg); - if (ret != 0) - break; + case HFI1_SNOOP_IOCSETFILTER: + snoop_dbg("Setting filter"); + /* just copy command structure */ + argp = (unsigned long *)arg; + if (copy_from_user(&filter_cmd, (void __user *)argp, + sizeof(filter_cmd))) + return -EFAULT; - snoop_dbg("Setting snoop option %d", value); - if (value & SNOOP_DROP_SEND) - snoop_flags |= SNOOP_DROP_SEND; - if (value & SNOOP_USE_METADATA) - snoop_flags |= SNOOP_USE_METADATA; - break; - default: - ret = -ENOTTY; - break; + if (filter_cmd.opcode >= HFI1_MAX_FILTERS) { + pr_alert("Invalid opcode in request\n"); + return -EINVAL; + } + + snoop_dbg("Opcode %d Len %d Ptr %p", + filter_cmd.opcode, filter_cmd.length, + filter_cmd.value_ptr); + + filter_value = kcalloc(filter_cmd.length, sizeof(u8), + GFP_KERNEL); + if (!filter_value) + return -ENOMEM; + + /* copy remaining data from userspace */ + if (copy_from_user((u8 *)filter_value, + (void __user *)filter_cmd.value_ptr, + filter_cmd.length)) { + kfree(filter_value); + return -EFAULT; } + /* Drain packets first */ + spin_lock_irqsave(&dd->hfi1_snoop.snoop_lock, flags); + drain_snoop_list(&dd->hfi1_snoop.queue); + dd->hfi1_snoop.filter_callback = + hfi1_filters[filter_cmd.opcode].filter; + /* just in case we see back to back sets */ + kfree(dd->hfi1_snoop.filter_value); + dd->hfi1_snoop.filter_value = filter_value; + spin_unlock_irqrestore(&dd->hfi1_snoop.snoop_lock, flags); + break; + case HFI1_SNOOP_IOCGETVERSION: + value = SNOOP_CAPTURE_VERSION; + snoop_dbg("Getting version: %d", value); + ret = __put_user(value, (int __user *)arg); + break; + case HFI1_SNOOP_IOCSET_OPTS: + snoop_flags = 0; + ret = __get_user(value, (int __user *)arg); + if (ret != 0) + break; + + snoop_dbg("Setting snoop option %d", value); + if (value & SNOOP_DROP_SEND) + snoop_flags |= SNOOP_DROP_SEND; + if (value & SNOOP_USE_METADATA) + snoop_flags |= SNOOP_USE_METADATA; + break; + default: + return -ENOTTY; } -done: - spin_unlock_irqrestore(&dd->hfi1_snoop.snoop_lock, flags); + return ret; } @@ -1321,7 +1311,6 @@ static int hfi1_filter_mad_mgmt_class(void *ibhdr, void *packet_data, static int hfi1_filter_qp_number(void *ibhdr, void *packet_data, void *value) { - struct hfi1_ib_header *hdr; struct hfi1_other_headers *ohdr = NULL; int ret; @@ -1404,7 +1393,6 @@ static int hfi1_filter_ib_service_level(void *ibhdr, void *packet_data, static int hfi1_filter_ib_pkey(void *ibhdr, void *packet_data, void *value) { - u32 lnh = 0; struct hfi1_ib_header *hdr; struct hfi1_other_headers *ohdr = NULL; @@ -1476,16 +1464,14 @@ static struct snoop_packet *allocate_snoop_packet(u32 hdr_len, u32 data_len, u32 md_len) { - struct snoop_packet *packet; - packet = kzalloc(sizeof(struct snoop_packet) + hdr_len + data_len + packet = kzalloc(sizeof(*packet) + hdr_len + data_len + md_len, GFP_ATOMIC | __GFP_NOWARN); if (likely(packet)) INIT_LIST_HEAD(&packet->list); - return packet; } @@ -1542,12 +1528,11 @@ int snoop_recv_handler(struct hfi1_packet *packet) unlikely(snoop_flags & SNOOP_USE_METADATA)) md_len = sizeof(struct capture_md); - s_packet = allocate_snoop_packet(header_size, tlen - header_size, md_len); - if (unlikely(s_packet == NULL)) { + if (unlikely(!s_packet)) { dd_dev_warn_ratelimited(ppd->dd, "Unable to allocate snoop/capture packet\n"); break; } @@ -1618,14 +1603,12 @@ int snoop_recv_handler(struct hfi1_packet *packet) /* * Handle snooping and capturing packets when sdma is being used. */ -int snoop_send_dma_handler(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr, - u32 hdrwords, struct hfi1_sge_state *ss, u32 len, - u32 plen, u32 dwords, u64 pbc) +int snoop_send_dma_handler(struct hfi1_qp *qp, struct hfi1_pkt_state *ps, + u64 pbc) { - pr_alert("Snooping/Capture of Send DMA Packets Is Not Supported!\n"); + pr_alert("Snooping/Capture of Send DMA Packets Is Not Supported!\n"); snoop_dbg("Unsupported Operation"); - return hfi1_verbs_send_dma(qp, ibhdr, hdrwords, ss, len, plen, dwords, - 0); + return hfi1_verbs_send_dma(qp, ps, 0); } /* @@ -1633,12 +1616,16 @@ int snoop_send_dma_handler(struct hfi1_qp *qp, struct ahg_ib_header *ibhdr, * bypass packets. The only way to send a bypass packet currently is to use the * diagpkt interface. When that interface is enable snoop/capture is not. */ -int snoop_send_pio_handler(struct hfi1_qp *qp, struct ahg_ib_header *ahdr, - u32 hdrwords, struct hfi1_sge_state *ss, u32 len, - u32 plen, u32 dwords, u64 pbc) +int snoop_send_pio_handler(struct hfi1_qp *qp, struct hfi1_pkt_state *ps, + u64 pbc) { - struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); - struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); + struct ahg_ib_header *ahdr = qp->s_hdr; + u32 hdrwords = qp->s_hdrwords; + struct hfi1_sge_state *ss = qp->s_cur_sge; + u32 len = qp->s_cur_size; + u32 dwords = (len + 3) >> 2; + u32 plen = hdrwords + dwords + 2; /* includes pbc */ + struct hfi1_pportdata *ppd = ps->ppd; struct snoop_packet *s_packet = NULL; u32 *hdr = (u32 *)&ahdr->ibh; u32 length = 0; @@ -1666,7 +1653,7 @@ int snoop_send_pio_handler(struct hfi1_qp *qp, struct ahg_ib_header *ahdr, /* not using ss->total_len as arg 2 b/c that does not count CRC */ s_packet = allocate_snoop_packet(hdr_len, tlen - hdr_len, md_len); - if (unlikely(s_packet == NULL)) { + if (unlikely(!s_packet)) { dd_dev_warn_ratelimited(ppd->dd, "Unable to allocate snoop/capture packet\n"); goto out; } @@ -1783,8 +1770,7 @@ int snoop_send_pio_handler(struct hfi1_qp *qp, struct ahg_ib_header *ahdr, break; } out: - return hfi1_verbs_send_pio(qp, ahdr, hdrwords, ss, len, plen, dwords, - md.u.pbc); + return hfi1_verbs_send_pio(qp, ps, md.u.pbc); } /* @@ -1836,7 +1822,7 @@ void snoop_inline_pio_send(struct hfi1_devdata *dd, struct pio_buf *pbuf, s_packet = allocate_snoop_packet(packet_len, 0, md_len); - if (unlikely(s_packet == NULL)) { + if (unlikely(!s_packet)) { dd_dev_warn_ratelimited(dd, "Unable to allocate snoop/capture packet\n"); goto inline_pio_out; } @@ -1868,5 +1854,4 @@ void snoop_inline_pio_send(struct hfi1_devdata *dd, struct pio_buf *pbuf, inline_pio_out: pio_copy(dd, pbuf, pbc, from, count); - } -- cgit v1.2.3-54-g00ecf