diff options
Diffstat (limited to 'drivers/infiniband/hw')
29 files changed, 504 insertions, 302 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 7fc35cf0cddf..c825142a2fb7 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -175,6 +175,13 @@ struct ehca_queue_map { | |||
175 | unsigned int next_wqe_idx; /* Idx to first wqe to be flushed */ | 175 | unsigned int next_wqe_idx; /* Idx to first wqe to be flushed */ |
176 | }; | 176 | }; |
177 | 177 | ||
178 | /* function to calculate the next index for the qmap */ | ||
179 | static inline unsigned int next_index(unsigned int cur_index, unsigned int limit) | ||
180 | { | ||
181 | unsigned int temp = cur_index + 1; | ||
182 | return (temp == limit) ? 0 : temp; | ||
183 | } | ||
184 | |||
178 | struct ehca_qp { | 185 | struct ehca_qp { |
179 | union { | 186 | union { |
180 | struct ib_qp ib_qp; | 187 | struct ib_qp ib_qp; |
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c index 49660dfa1867..523e733c630e 100644 --- a/drivers/infiniband/hw/ehca/ehca_eq.c +++ b/drivers/infiniband/hw/ehca/ehca_eq.c | |||
@@ -113,7 +113,7 @@ int ehca_create_eq(struct ehca_shca *shca, | |||
113 | if (h_ret != H_SUCCESS || vpage) | 113 | if (h_ret != H_SUCCESS || vpage) |
114 | goto create_eq_exit2; | 114 | goto create_eq_exit2; |
115 | } else { | 115 | } else { |
116 | if (h_ret != H_PAGE_REGISTERED || !vpage) | 116 | if (h_ret != H_PAGE_REGISTERED) |
117 | goto create_eq_exit2; | 117 | goto create_eq_exit2; |
118 | } | 118 | } |
119 | } | 119 | } |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index bec7e0249358..3b77b674cbf6 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -717,6 +717,7 @@ static int __devinit ehca_probe(struct of_device *dev, | |||
717 | const u64 *handle; | 717 | const u64 *handle; |
718 | struct ib_pd *ibpd; | 718 | struct ib_pd *ibpd; |
719 | int ret, i, eq_size; | 719 | int ret, i, eq_size; |
720 | unsigned long flags; | ||
720 | 721 | ||
721 | handle = of_get_property(dev->node, "ibm,hca-handle", NULL); | 722 | handle = of_get_property(dev->node, "ibm,hca-handle", NULL); |
722 | if (!handle) { | 723 | if (!handle) { |
@@ -830,9 +831,9 @@ static int __devinit ehca_probe(struct of_device *dev, | |||
830 | ehca_err(&shca->ib_device, | 831 | ehca_err(&shca->ib_device, |
831 | "Cannot create device attributes ret=%d", ret); | 832 | "Cannot create device attributes ret=%d", ret); |
832 | 833 | ||
833 | spin_lock(&shca_list_lock); | 834 | spin_lock_irqsave(&shca_list_lock, flags); |
834 | list_add(&shca->shca_list, &shca_list); | 835 | list_add(&shca->shca_list, &shca_list); |
835 | spin_unlock(&shca_list_lock); | 836 | spin_unlock_irqrestore(&shca_list_lock, flags); |
836 | 837 | ||
837 | return 0; | 838 | return 0; |
838 | 839 | ||
@@ -878,6 +879,7 @@ probe1: | |||
878 | static int __devexit ehca_remove(struct of_device *dev) | 879 | static int __devexit ehca_remove(struct of_device *dev) |
879 | { | 880 | { |
880 | struct ehca_shca *shca = dev->dev.driver_data; | 881 | struct ehca_shca *shca = dev->dev.driver_data; |
882 | unsigned long flags; | ||
881 | int ret; | 883 | int ret; |
882 | 884 | ||
883 | sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp); | 885 | sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp); |
@@ -915,9 +917,9 @@ static int __devexit ehca_remove(struct of_device *dev) | |||
915 | 917 | ||
916 | ib_dealloc_device(&shca->ib_device); | 918 | ib_dealloc_device(&shca->ib_device); |
917 | 919 | ||
918 | spin_lock(&shca_list_lock); | 920 | spin_lock_irqsave(&shca_list_lock, flags); |
919 | list_del(&shca->shca_list); | 921 | list_del(&shca->shca_list); |
920 | spin_unlock(&shca_list_lock); | 922 | spin_unlock_irqrestore(&shca_list_lock, flags); |
921 | 923 | ||
922 | return ret; | 924 | return ret; |
923 | } | 925 | } |
@@ -975,6 +977,7 @@ static int ehca_mem_notifier(struct notifier_block *nb, | |||
975 | unsigned long action, void *data) | 977 | unsigned long action, void *data) |
976 | { | 978 | { |
977 | static unsigned long ehca_dmem_warn_time; | 979 | static unsigned long ehca_dmem_warn_time; |
980 | unsigned long flags; | ||
978 | 981 | ||
979 | switch (action) { | 982 | switch (action) { |
980 | case MEM_CANCEL_OFFLINE: | 983 | case MEM_CANCEL_OFFLINE: |
@@ -985,12 +988,12 @@ static int ehca_mem_notifier(struct notifier_block *nb, | |||
985 | case MEM_GOING_ONLINE: | 988 | case MEM_GOING_ONLINE: |
986 | case MEM_GOING_OFFLINE: | 989 | case MEM_GOING_OFFLINE: |
987 | /* only ok if no hca is attached to the lpar */ | 990 | /* only ok if no hca is attached to the lpar */ |
988 | spin_lock(&shca_list_lock); | 991 | spin_lock_irqsave(&shca_list_lock, flags); |
989 | if (list_empty(&shca_list)) { | 992 | if (list_empty(&shca_list)) { |
990 | spin_unlock(&shca_list_lock); | 993 | spin_unlock_irqrestore(&shca_list_lock, flags); |
991 | return NOTIFY_OK; | 994 | return NOTIFY_OK; |
992 | } else { | 995 | } else { |
993 | spin_unlock(&shca_list_lock); | 996 | spin_unlock_irqrestore(&shca_list_lock, flags); |
994 | if (printk_timed_ratelimit(&ehca_dmem_warn_time, | 997 | if (printk_timed_ratelimit(&ehca_dmem_warn_time, |
995 | 30 * 1000)) | 998 | 30 * 1000)) |
996 | ehca_gen_err("DMEM operations are not allowed" | 999 | ehca_gen_err("DMEM operations are not allowed" |
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index cadbf0cdd910..f161cf173dbe 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
@@ -1138,14 +1138,14 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, | |||
1138 | return -EFAULT; | 1138 | return -EFAULT; |
1139 | } | 1139 | } |
1140 | 1140 | ||
1141 | tail_idx = (qmap->tail + 1) % qmap->entries; | 1141 | tail_idx = next_index(qmap->tail, qmap->entries); |
1142 | wqe_idx = q_ofs / ipz_queue->qe_size; | 1142 | wqe_idx = q_ofs / ipz_queue->qe_size; |
1143 | 1143 | ||
1144 | /* check all processed wqes, whether a cqe is requested or not */ | 1144 | /* check all processed wqes, whether a cqe is requested or not */ |
1145 | while (tail_idx != wqe_idx) { | 1145 | while (tail_idx != wqe_idx) { |
1146 | if (qmap->map[tail_idx].cqe_req) | 1146 | if (qmap->map[tail_idx].cqe_req) |
1147 | qmap->left_to_poll++; | 1147 | qmap->left_to_poll++; |
1148 | tail_idx = (tail_idx + 1) % qmap->entries; | 1148 | tail_idx = next_index(tail_idx, qmap->entries); |
1149 | } | 1149 | } |
1150 | /* save index in queue, where we have to start flushing */ | 1150 | /* save index in queue, where we have to start flushing */ |
1151 | qmap->next_wqe_idx = wqe_idx; | 1151 | qmap->next_wqe_idx = wqe_idx; |
@@ -1195,14 +1195,14 @@ static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca) | |||
1195 | } else { | 1195 | } else { |
1196 | spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); | 1196 | spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); |
1197 | my_qp->sq_map.left_to_poll = 0; | 1197 | my_qp->sq_map.left_to_poll = 0; |
1198 | my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) % | 1198 | my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail, |
1199 | my_qp->sq_map.entries; | 1199 | my_qp->sq_map.entries); |
1200 | spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); | 1200 | spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); |
1201 | 1201 | ||
1202 | spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); | 1202 | spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); |
1203 | my_qp->rq_map.left_to_poll = 0; | 1203 | my_qp->rq_map.left_to_poll = 0; |
1204 | my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) % | 1204 | my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail, |
1205 | my_qp->rq_map.entries; | 1205 | my_qp->rq_map.entries); |
1206 | spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); | 1206 | spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); |
1207 | } | 1207 | } |
1208 | 1208 | ||
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index 00a648f4316c..c7112686782f 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c | |||
@@ -726,13 +726,13 @@ repoll: | |||
726 | * set left_to_poll to 0 because in error state, we will not | 726 | * set left_to_poll to 0 because in error state, we will not |
727 | * get any additional CQEs | 727 | * get any additional CQEs |
728 | */ | 728 | */ |
729 | my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) % | 729 | my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail, |
730 | my_qp->sq_map.entries; | 730 | my_qp->sq_map.entries); |
731 | my_qp->sq_map.left_to_poll = 0; | 731 | my_qp->sq_map.left_to_poll = 0; |
732 | ehca_add_to_err_list(my_qp, 1); | 732 | ehca_add_to_err_list(my_qp, 1); |
733 | 733 | ||
734 | my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) % | 734 | my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail, |
735 | my_qp->rq_map.entries; | 735 | my_qp->rq_map.entries); |
736 | my_qp->rq_map.left_to_poll = 0; | 736 | my_qp->rq_map.left_to_poll = 0; |
737 | if (HAS_RQ(my_qp)) | 737 | if (HAS_RQ(my_qp)) |
738 | ehca_add_to_err_list(my_qp, 0); | 738 | ehca_add_to_err_list(my_qp, 0); |
@@ -860,9 +860,8 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, | |||
860 | 860 | ||
861 | /* mark as reported and advance next_wqe pointer */ | 861 | /* mark as reported and advance next_wqe pointer */ |
862 | qmap_entry->reported = 1; | 862 | qmap_entry->reported = 1; |
863 | qmap->next_wqe_idx++; | 863 | qmap->next_wqe_idx = next_index(qmap->next_wqe_idx, |
864 | if (qmap->next_wqe_idx == qmap->entries) | 864 | qmap->entries); |
865 | qmap->next_wqe_idx = 0; | ||
866 | qmap_entry = &qmap->map[qmap->next_wqe_idx]; | 865 | qmap_entry = &qmap->map[qmap->next_wqe_idx]; |
867 | 866 | ||
868 | wc++; nr++; | 867 | wc++; nr++; |
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index ad0aab60b051..69c0ce321b4e 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -661,6 +661,8 @@ bail: | |||
661 | static void __devexit cleanup_device(struct ipath_devdata *dd) | 661 | static void __devexit cleanup_device(struct ipath_devdata *dd) |
662 | { | 662 | { |
663 | int port; | 663 | int port; |
664 | struct ipath_portdata **tmp; | ||
665 | unsigned long flags; | ||
664 | 666 | ||
665 | if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) { | 667 | if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) { |
666 | /* can't do anything more with chip; needs re-init */ | 668 | /* can't do anything more with chip; needs re-init */ |
@@ -742,20 +744,21 @@ static void __devexit cleanup_device(struct ipath_devdata *dd) | |||
742 | 744 | ||
743 | /* | 745 | /* |
744 | * free any resources still in use (usually just kernel ports) | 746 | * free any resources still in use (usually just kernel ports) |
745 | * at unload; we do for portcnt, not cfgports, because cfgports | 747 | * at unload; we do for portcnt, because that's what we allocate. |
746 | * could have changed while we were loaded. | 748 | * We acquire lock to be really paranoid that ipath_pd isn't being |
749 | * accessed from some interrupt-related code (that should not happen, | ||
750 | * but best to be sure). | ||
747 | */ | 751 | */ |
752 | spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); | ||
753 | tmp = dd->ipath_pd; | ||
754 | dd->ipath_pd = NULL; | ||
755 | spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); | ||
748 | for (port = 0; port < dd->ipath_portcnt; port++) { | 756 | for (port = 0; port < dd->ipath_portcnt; port++) { |
749 | struct ipath_portdata *pd = dd->ipath_pd[port]; | 757 | struct ipath_portdata *pd = tmp[port]; |
750 | dd->ipath_pd[port] = NULL; | 758 | tmp[port] = NULL; /* debugging paranoia */ |
751 | ipath_free_pddata(dd, pd); | 759 | ipath_free_pddata(dd, pd); |
752 | } | 760 | } |
753 | kfree(dd->ipath_pd); | 761 | kfree(tmp); |
754 | /* | ||
755 | * debuggability, in case some cleanup path tries to use it | ||
756 | * after this | ||
757 | */ | ||
758 | dd->ipath_pd = NULL; | ||
759 | } | 762 | } |
760 | 763 | ||
761 | static void __devexit ipath_remove_one(struct pci_dev *pdev) | 764 | static void __devexit ipath_remove_one(struct pci_dev *pdev) |
@@ -2586,6 +2589,7 @@ int ipath_reset_device(int unit) | |||
2586 | { | 2589 | { |
2587 | int ret, i; | 2590 | int ret, i; |
2588 | struct ipath_devdata *dd = ipath_lookup(unit); | 2591 | struct ipath_devdata *dd = ipath_lookup(unit); |
2592 | unsigned long flags; | ||
2589 | 2593 | ||
2590 | if (!dd) { | 2594 | if (!dd) { |
2591 | ret = -ENODEV; | 2595 | ret = -ENODEV; |
@@ -2611,18 +2615,21 @@ int ipath_reset_device(int unit) | |||
2611 | goto bail; | 2615 | goto bail; |
2612 | } | 2616 | } |
2613 | 2617 | ||
2618 | spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); | ||
2614 | if (dd->ipath_pd) | 2619 | if (dd->ipath_pd) |
2615 | for (i = 1; i < dd->ipath_cfgports; i++) { | 2620 | for (i = 1; i < dd->ipath_cfgports; i++) { |
2616 | if (dd->ipath_pd[i] && dd->ipath_pd[i]->port_cnt) { | 2621 | if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt) |
2617 | ipath_dbg("unit %u port %d is in use " | 2622 | continue; |
2618 | "(PID %u cmd %s), can't reset\n", | 2623 | spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); |
2619 | unit, i, | 2624 | ipath_dbg("unit %u port %d is in use " |
2620 | pid_nr(dd->ipath_pd[i]->port_pid), | 2625 | "(PID %u cmd %s), can't reset\n", |
2621 | dd->ipath_pd[i]->port_comm); | 2626 | unit, i, |
2622 | ret = -EBUSY; | 2627 | pid_nr(dd->ipath_pd[i]->port_pid), |
2623 | goto bail; | 2628 | dd->ipath_pd[i]->port_comm); |
2624 | } | 2629 | ret = -EBUSY; |
2630 | goto bail; | ||
2625 | } | 2631 | } |
2632 | spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); | ||
2626 | 2633 | ||
2627 | if (dd->ipath_flags & IPATH_HAS_SEND_DMA) | 2634 | if (dd->ipath_flags & IPATH_HAS_SEND_DMA) |
2628 | teardown_sdma(dd); | 2635 | teardown_sdma(dd); |
@@ -2656,9 +2663,12 @@ static int ipath_signal_procs(struct ipath_devdata *dd, int sig) | |||
2656 | { | 2663 | { |
2657 | int i, sub, any = 0; | 2664 | int i, sub, any = 0; |
2658 | struct pid *pid; | 2665 | struct pid *pid; |
2666 | unsigned long flags; | ||
2659 | 2667 | ||
2660 | if (!dd->ipath_pd) | 2668 | if (!dd->ipath_pd) |
2661 | return 0; | 2669 | return 0; |
2670 | |||
2671 | spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); | ||
2662 | for (i = 1; i < dd->ipath_cfgports; i++) { | 2672 | for (i = 1; i < dd->ipath_cfgports; i++) { |
2663 | if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt) | 2673 | if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt) |
2664 | continue; | 2674 | continue; |
@@ -2682,6 +2692,7 @@ static int ipath_signal_procs(struct ipath_devdata *dd, int sig) | |||
2682 | any++; | 2692 | any++; |
2683 | } | 2693 | } |
2684 | } | 2694 | } |
2695 | spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); | ||
2685 | return any; | 2696 | return any; |
2686 | } | 2697 | } |
2687 | 2698 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 1af1f3a907c6..239d4e8068ac 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
@@ -223,8 +223,13 @@ static int ipath_get_base_info(struct file *fp, | |||
223 | (unsigned long long) kinfo->spi_subport_rcvhdr_base); | 223 | (unsigned long long) kinfo->spi_subport_rcvhdr_base); |
224 | } | 224 | } |
225 | 225 | ||
226 | kinfo->spi_pioindex = (kinfo->spi_piobufbase - dd->ipath_piobufbase) / | 226 | /* |
227 | dd->ipath_palign; | 227 | * All user buffers are 2KB buffers. If we ever support |
228 | * giving 4KB buffers to user processes, this will need some | ||
229 | * work. | ||
230 | */ | ||
231 | kinfo->spi_pioindex = (kinfo->spi_piobufbase - | ||
232 | (dd->ipath_piobufbase & 0xffffffff)) / dd->ipath_palign; | ||
228 | kinfo->spi_pioalign = dd->ipath_palign; | 233 | kinfo->spi_pioalign = dd->ipath_palign; |
229 | 234 | ||
230 | kinfo->spi_qpair = IPATH_KD_QP; | 235 | kinfo->spi_qpair = IPATH_KD_QP; |
@@ -2041,7 +2046,9 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
2041 | struct ipath_filedata *fd; | 2046 | struct ipath_filedata *fd; |
2042 | struct ipath_portdata *pd; | 2047 | struct ipath_portdata *pd; |
2043 | struct ipath_devdata *dd; | 2048 | struct ipath_devdata *dd; |
2049 | unsigned long flags; | ||
2044 | unsigned port; | 2050 | unsigned port; |
2051 | struct pid *pid; | ||
2045 | 2052 | ||
2046 | ipath_cdbg(VERBOSE, "close on dev %lx, private data %p\n", | 2053 | ipath_cdbg(VERBOSE, "close on dev %lx, private data %p\n", |
2047 | (long)in->i_rdev, fp->private_data); | 2054 | (long)in->i_rdev, fp->private_data); |
@@ -2074,14 +2081,13 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
2074 | mutex_unlock(&ipath_mutex); | 2081 | mutex_unlock(&ipath_mutex); |
2075 | goto bail; | 2082 | goto bail; |
2076 | } | 2083 | } |
2084 | /* early; no interrupt users after this */ | ||
2085 | spin_lock_irqsave(&dd->ipath_uctxt_lock, flags); | ||
2077 | port = pd->port_port; | 2086 | port = pd->port_port; |
2078 | 2087 | dd->ipath_pd[port] = NULL; | |
2079 | if (pd->port_hdrqfull) { | 2088 | pid = pd->port_pid; |
2080 | ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors " | 2089 | pd->port_pid = NULL; |
2081 | "during run\n", pd->port_comm, pid_nr(pd->port_pid), | 2090 | spin_unlock_irqrestore(&dd->ipath_uctxt_lock, flags); |
2082 | pd->port_hdrqfull); | ||
2083 | pd->port_hdrqfull = 0; | ||
2084 | } | ||
2085 | 2091 | ||
2086 | if (pd->port_rcvwait_to || pd->port_piowait_to | 2092 | if (pd->port_rcvwait_to || pd->port_piowait_to |
2087 | || pd->port_rcvnowait || pd->port_pionowait) { | 2093 | || pd->port_rcvnowait || pd->port_pionowait) { |
@@ -2138,13 +2144,11 @@ static int ipath_close(struct inode *in, struct file *fp) | |||
2138 | unlock_expected_tids(pd); | 2144 | unlock_expected_tids(pd); |
2139 | ipath_stats.sps_ports--; | 2145 | ipath_stats.sps_ports--; |
2140 | ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", | 2146 | ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", |
2141 | pd->port_comm, pid_nr(pd->port_pid), | 2147 | pd->port_comm, pid_nr(pid), |
2142 | dd->ipath_unit, port); | 2148 | dd->ipath_unit, port); |
2143 | } | 2149 | } |
2144 | 2150 | ||
2145 | put_pid(pd->port_pid); | 2151 | put_pid(pid); |
2146 | pd->port_pid = NULL; | ||
2147 | dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */ | ||
2148 | mutex_unlock(&ipath_mutex); | 2152 | mutex_unlock(&ipath_mutex); |
2149 | ipath_free_pddata(dd, pd); /* after releasing the mutex */ | 2153 | ipath_free_pddata(dd, pd); /* after releasing the mutex */ |
2150 | 2154 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 8bb5170b4e41..53912c327bfe 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c | |||
@@ -86,7 +86,7 @@ static int create_file(const char *name, mode_t mode, | |||
86 | *dentry = NULL; | 86 | *dentry = NULL; |
87 | mutex_lock(&parent->d_inode->i_mutex); | 87 | mutex_lock(&parent->d_inode->i_mutex); |
88 | *dentry = lookup_one_len(name, parent, strlen(name)); | 88 | *dentry = lookup_one_len(name, parent, strlen(name)); |
89 | if (!IS_ERR(dentry)) | 89 | if (!IS_ERR(*dentry)) |
90 | error = ipathfs_mknod(parent->d_inode, *dentry, | 90 | error = ipathfs_mknod(parent->d_inode, *dentry, |
91 | mode, fops, data); | 91 | mode, fops, data); |
92 | else | 92 | else |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index 421cc2af891f..fbf8c5379ea8 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c | |||
@@ -721,6 +721,12 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd) | |||
721 | INFINIPATH_HWE_SERDESPLLFAILED); | 721 | INFINIPATH_HWE_SERDESPLLFAILED); |
722 | } | 722 | } |
723 | 723 | ||
724 | dd->ibdeltainprog = 1; | ||
725 | dd->ibsymsnap = | ||
726 | ipath_read_creg32(dd, dd->ipath_cregs->cr_ibsymbolerrcnt); | ||
727 | dd->iblnkerrsnap = | ||
728 | ipath_read_creg32(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
729 | |||
724 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); | 730 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); |
725 | config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1); | 731 | config1 = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig1); |
726 | 732 | ||
@@ -810,6 +816,36 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd) | |||
810 | { | 816 | { |
811 | u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); | 817 | u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0); |
812 | 818 | ||
819 | if (dd->ibsymdelta || dd->iblnkerrdelta || | ||
820 | dd->ibdeltainprog) { | ||
821 | u64 diagc; | ||
822 | /* enable counter writes */ | ||
823 | diagc = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwdiagctrl); | ||
824 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, | ||
825 | diagc | INFINIPATH_DC_COUNTERWREN); | ||
826 | |||
827 | if (dd->ibsymdelta || dd->ibdeltainprog) { | ||
828 | val = ipath_read_creg32(dd, | ||
829 | dd->ipath_cregs->cr_ibsymbolerrcnt); | ||
830 | if (dd->ibdeltainprog) | ||
831 | val -= val - dd->ibsymsnap; | ||
832 | val -= dd->ibsymdelta; | ||
833 | ipath_write_creg(dd, | ||
834 | dd->ipath_cregs->cr_ibsymbolerrcnt, val); | ||
835 | } | ||
836 | if (dd->iblnkerrdelta || dd->ibdeltainprog) { | ||
837 | val = ipath_read_creg32(dd, | ||
838 | dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
839 | if (dd->ibdeltainprog) | ||
840 | val -= val - dd->iblnkerrsnap; | ||
841 | val -= dd->iblnkerrdelta; | ||
842 | ipath_write_creg(dd, | ||
843 | dd->ipath_cregs->cr_iblinkerrrecovcnt, val); | ||
844 | } | ||
845 | |||
846 | /* and disable counter writes */ | ||
847 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, diagc); | ||
848 | } | ||
813 | val |= INFINIPATH_SERDC0_TXIDLE; | 849 | val |= INFINIPATH_SERDC0_TXIDLE; |
814 | ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n", | 850 | ipath_dbg("Setting TxIdleEn on serdes (config0 = %llx)\n", |
815 | (unsigned long long) val); | 851 | (unsigned long long) val); |
@@ -1749,6 +1785,31 @@ static void ipath_pe_config_jint(struct ipath_devdata *dd, u16 a, u16 b) | |||
1749 | 1785 | ||
1750 | static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) | 1786 | static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) |
1751 | { | 1787 | { |
1788 | if (ibup) { | ||
1789 | if (dd->ibdeltainprog) { | ||
1790 | dd->ibdeltainprog = 0; | ||
1791 | dd->ibsymdelta += | ||
1792 | ipath_read_creg32(dd, | ||
1793 | dd->ipath_cregs->cr_ibsymbolerrcnt) - | ||
1794 | dd->ibsymsnap; | ||
1795 | dd->iblnkerrdelta += | ||
1796 | ipath_read_creg32(dd, | ||
1797 | dd->ipath_cregs->cr_iblinkerrrecovcnt) - | ||
1798 | dd->iblnkerrsnap; | ||
1799 | } | ||
1800 | } else { | ||
1801 | dd->ipath_lli_counter = 0; | ||
1802 | if (!dd->ibdeltainprog) { | ||
1803 | dd->ibdeltainprog = 1; | ||
1804 | dd->ibsymsnap = | ||
1805 | ipath_read_creg32(dd, | ||
1806 | dd->ipath_cregs->cr_ibsymbolerrcnt); | ||
1807 | dd->iblnkerrsnap = | ||
1808 | ipath_read_creg32(dd, | ||
1809 | dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
1810 | } | ||
1811 | } | ||
1812 | |||
1752 | ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs), | 1813 | ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs), |
1753 | ipath_ib_linktrstate(dd, ibcs)); | 1814 | ipath_ib_linktrstate(dd, ibcs)); |
1754 | return 0; | 1815 | return 0; |
diff --git a/drivers/infiniband/hw/ipath/ipath_iba7220.c b/drivers/infiniband/hw/ipath/ipath_iba7220.c index 9839e20119bc..b2a9d4c155d1 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba7220.c +++ b/drivers/infiniband/hw/ipath/ipath_iba7220.c | |||
@@ -951,6 +951,12 @@ static int ipath_7220_bringup_serdes(struct ipath_devdata *dd) | |||
951 | INFINIPATH_HWE_SERDESPLLFAILED); | 951 | INFINIPATH_HWE_SERDESPLLFAILED); |
952 | } | 952 | } |
953 | 953 | ||
954 | dd->ibdeltainprog = 1; | ||
955 | dd->ibsymsnap = | ||
956 | ipath_read_creg32(dd, dd->ipath_cregs->cr_ibsymbolerrcnt); | ||
957 | dd->iblnkerrsnap = | ||
958 | ipath_read_creg32(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
959 | |||
954 | if (!dd->ipath_ibcddrctrl) { | 960 | if (!dd->ipath_ibcddrctrl) { |
955 | /* not on re-init after reset */ | 961 | /* not on re-init after reset */ |
956 | dd->ipath_ibcddrctrl = | 962 | dd->ipath_ibcddrctrl = |
@@ -1084,6 +1090,37 @@ static void ipath_7220_config_jint(struct ipath_devdata *dd, | |||
1084 | static void ipath_7220_quiet_serdes(struct ipath_devdata *dd) | 1090 | static void ipath_7220_quiet_serdes(struct ipath_devdata *dd) |
1085 | { | 1091 | { |
1086 | u64 val; | 1092 | u64 val; |
1093 | if (dd->ibsymdelta || dd->iblnkerrdelta || | ||
1094 | dd->ibdeltainprog) { | ||
1095 | u64 diagc; | ||
1096 | /* enable counter writes */ | ||
1097 | diagc = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwdiagctrl); | ||
1098 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, | ||
1099 | diagc | INFINIPATH_DC_COUNTERWREN); | ||
1100 | |||
1101 | if (dd->ibsymdelta || dd->ibdeltainprog) { | ||
1102 | val = ipath_read_creg32(dd, | ||
1103 | dd->ipath_cregs->cr_ibsymbolerrcnt); | ||
1104 | if (dd->ibdeltainprog) | ||
1105 | val -= val - dd->ibsymsnap; | ||
1106 | val -= dd->ibsymdelta; | ||
1107 | ipath_write_creg(dd, | ||
1108 | dd->ipath_cregs->cr_ibsymbolerrcnt, val); | ||
1109 | } | ||
1110 | if (dd->iblnkerrdelta || dd->ibdeltainprog) { | ||
1111 | val = ipath_read_creg32(dd, | ||
1112 | dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
1113 | if (dd->ibdeltainprog) | ||
1114 | val -= val - dd->iblnkerrsnap; | ||
1115 | val -= dd->iblnkerrdelta; | ||
1116 | ipath_write_creg(dd, | ||
1117 | dd->ipath_cregs->cr_iblinkerrrecovcnt, val); | ||
1118 | } | ||
1119 | |||
1120 | /* and disable counter writes */ | ||
1121 | ipath_write_kreg(dd, dd->ipath_kregs->kr_hwdiagctrl, diagc); | ||
1122 | } | ||
1123 | |||
1087 | dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG; | 1124 | dd->ipath_flags &= ~IPATH_IB_AUTONEG_INPROG; |
1088 | wake_up(&dd->ipath_autoneg_wait); | 1125 | wake_up(&dd->ipath_autoneg_wait); |
1089 | cancel_delayed_work(&dd->ipath_autoneg_work); | 1126 | cancel_delayed_work(&dd->ipath_autoneg_work); |
@@ -2325,7 +2362,7 @@ static void try_auto_neg(struct ipath_devdata *dd) | |||
2325 | 2362 | ||
2326 | static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) | 2363 | static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) |
2327 | { | 2364 | { |
2328 | int ret = 0; | 2365 | int ret = 0, symadj = 0; |
2329 | u32 ltstate = ipath_ib_linkstate(dd, ibcs); | 2366 | u32 ltstate = ipath_ib_linkstate(dd, ibcs); |
2330 | 2367 | ||
2331 | dd->ipath_link_width_active = | 2368 | dd->ipath_link_width_active = |
@@ -2368,6 +2405,13 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) | |||
2368 | ipath_dbg("DDR negotiation try, %u/%u\n", | 2405 | ipath_dbg("DDR negotiation try, %u/%u\n", |
2369 | dd->ipath_autoneg_tries, | 2406 | dd->ipath_autoneg_tries, |
2370 | IPATH_AUTONEG_TRIES); | 2407 | IPATH_AUTONEG_TRIES); |
2408 | if (!dd->ibdeltainprog) { | ||
2409 | dd->ibdeltainprog = 1; | ||
2410 | dd->ibsymsnap = ipath_read_creg32(dd, | ||
2411 | dd->ipath_cregs->cr_ibsymbolerrcnt); | ||
2412 | dd->iblnkerrsnap = ipath_read_creg32(dd, | ||
2413 | dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
2414 | } | ||
2371 | try_auto_neg(dd); | 2415 | try_auto_neg(dd); |
2372 | ret = 1; /* no other IB status change processing */ | 2416 | ret = 1; /* no other IB status change processing */ |
2373 | } else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) | 2417 | } else if ((dd->ipath_flags & IPATH_IB_AUTONEG_INPROG) |
@@ -2388,6 +2432,7 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) | |||
2388 | set_speed_fast(dd, | 2432 | set_speed_fast(dd, |
2389 | dd->ipath_link_speed_enabled); | 2433 | dd->ipath_link_speed_enabled); |
2390 | wake_up(&dd->ipath_autoneg_wait); | 2434 | wake_up(&dd->ipath_autoneg_wait); |
2435 | symadj = 1; | ||
2391 | } else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) { | 2436 | } else if (dd->ipath_flags & IPATH_IB_AUTONEG_FAILED) { |
2392 | /* | 2437 | /* |
2393 | * clear autoneg failure flag, and do setup | 2438 | * clear autoneg failure flag, and do setup |
@@ -2403,22 +2448,28 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) | |||
2403 | IBA7220_IBC_IBTA_1_2_MASK; | 2448 | IBA7220_IBC_IBTA_1_2_MASK; |
2404 | ipath_write_kreg(dd, | 2449 | ipath_write_kreg(dd, |
2405 | IPATH_KREG_OFFSET(IBNCModeCtrl), 0); | 2450 | IPATH_KREG_OFFSET(IBNCModeCtrl), 0); |
2451 | symadj = 1; | ||
2406 | } | 2452 | } |
2407 | } | 2453 | } |
2408 | /* | 2454 | /* |
2409 | * if we are in 1X, and are in autoneg width, it | 2455 | * if we are in 1X on rev1 only, and are in autoneg width, |
2410 | * could be due to an xgxs problem, so if we haven't | 2456 | * it could be due to an xgxs problem, so if we haven't |
2411 | * already tried, try twice to get to 4X; if we | 2457 | * already tried, try twice to get to 4X; if we |
2412 | * tried, and couldn't, report it, since it will | 2458 | * tried, and couldn't, report it, since it will |
2413 | * probably not be what is desired. | 2459 | * probably not be what is desired. |
2414 | */ | 2460 | */ |
2415 | if ((dd->ipath_link_width_enabled & (IB_WIDTH_1X | | 2461 | if (dd->ipath_minrev == 1 && |
2462 | (dd->ipath_link_width_enabled & (IB_WIDTH_1X | | ||
2416 | IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X) | 2463 | IB_WIDTH_4X)) == (IB_WIDTH_1X | IB_WIDTH_4X) |
2417 | && dd->ipath_link_width_active == IB_WIDTH_1X | 2464 | && dd->ipath_link_width_active == IB_WIDTH_1X |
2418 | && dd->ipath_x1_fix_tries < 3) { | 2465 | && dd->ipath_x1_fix_tries < 3) { |
2419 | if (++dd->ipath_x1_fix_tries == 3) | 2466 | if (++dd->ipath_x1_fix_tries == 3) { |
2420 | dev_info(&dd->pcidev->dev, | 2467 | dev_info(&dd->pcidev->dev, |
2421 | "IB link is in 1X mode\n"); | 2468 | "IB link is in 1X mode\n"); |
2469 | if (!(dd->ipath_flags & | ||
2470 | IPATH_IB_AUTONEG_INPROG)) | ||
2471 | symadj = 1; | ||
2472 | } | ||
2422 | else { | 2473 | else { |
2423 | ipath_cdbg(VERBOSE, "IB 1X in " | 2474 | ipath_cdbg(VERBOSE, "IB 1X in " |
2424 | "auto-width, try %u to be " | 2475 | "auto-width, try %u to be " |
@@ -2429,7 +2480,8 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) | |||
2429 | dd->ipath_f_xgxs_reset(dd); | 2480 | dd->ipath_f_xgxs_reset(dd); |
2430 | ret = 1; /* skip other processing */ | 2481 | ret = 1; /* skip other processing */ |
2431 | } | 2482 | } |
2432 | } | 2483 | } else if (!(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)) |
2484 | symadj = 1; | ||
2433 | 2485 | ||
2434 | if (!ret) { | 2486 | if (!ret) { |
2435 | dd->delay_mult = rate_to_delay | 2487 | dd->delay_mult = rate_to_delay |
@@ -2440,6 +2492,25 @@ static int ipath_7220_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs) | |||
2440 | } | 2492 | } |
2441 | } | 2493 | } |
2442 | 2494 | ||
2495 | if (symadj) { | ||
2496 | if (dd->ibdeltainprog) { | ||
2497 | dd->ibdeltainprog = 0; | ||
2498 | dd->ibsymdelta += ipath_read_creg32(dd, | ||
2499 | dd->ipath_cregs->cr_ibsymbolerrcnt) - | ||
2500 | dd->ibsymsnap; | ||
2501 | dd->iblnkerrdelta += ipath_read_creg32(dd, | ||
2502 | dd->ipath_cregs->cr_iblinkerrrecovcnt) - | ||
2503 | dd->iblnkerrsnap; | ||
2504 | } | ||
2505 | } else if (!ibup && !dd->ibdeltainprog | ||
2506 | && !(dd->ipath_flags & IPATH_IB_AUTONEG_INPROG)) { | ||
2507 | dd->ibdeltainprog = 1; | ||
2508 | dd->ibsymsnap = ipath_read_creg32(dd, | ||
2509 | dd->ipath_cregs->cr_ibsymbolerrcnt); | ||
2510 | dd->iblnkerrsnap = ipath_read_creg32(dd, | ||
2511 | dd->ipath_cregs->cr_iblinkerrrecovcnt); | ||
2512 | } | ||
2513 | |||
2443 | if (!ret) | 2514 | if (!ret) |
2444 | ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs), | 2515 | ipath_setup_7220_setextled(dd, ipath_ib_linkstate(dd, ibcs), |
2445 | ltstate); | 2516 | ltstate); |
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 3e5baa43fc82..64aeefbd2a5d 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
@@ -229,6 +229,7 @@ static int init_chip_first(struct ipath_devdata *dd) | |||
229 | spin_lock_init(&dd->ipath_kernel_tid_lock); | 229 | spin_lock_init(&dd->ipath_kernel_tid_lock); |
230 | spin_lock_init(&dd->ipath_user_tid_lock); | 230 | spin_lock_init(&dd->ipath_user_tid_lock); |
231 | spin_lock_init(&dd->ipath_sendctrl_lock); | 231 | spin_lock_init(&dd->ipath_sendctrl_lock); |
232 | spin_lock_init(&dd->ipath_uctxt_lock); | ||
232 | spin_lock_init(&dd->ipath_sdma_lock); | 233 | spin_lock_init(&dd->ipath_sdma_lock); |
233 | spin_lock_init(&dd->ipath_gpio_lock); | 234 | spin_lock_init(&dd->ipath_gpio_lock); |
234 | spin_lock_init(&dd->ipath_eep_st_lock); | 235 | spin_lock_init(&dd->ipath_eep_st_lock); |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 0bd8bcb184a1..6ba4861dd6ac 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -355,6 +355,19 @@ struct ipath_devdata { | |||
355 | /* errors masked because they occur too fast */ | 355 | /* errors masked because they occur too fast */ |
356 | ipath_err_t ipath_maskederrs; | 356 | ipath_err_t ipath_maskederrs; |
357 | u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */ | 357 | u64 ipath_lastlinkrecov; /* link recoveries at last ACTIVE */ |
358 | /* these 5 fields are used to establish deltas for IB Symbol | ||
359 | * errors and linkrecovery errors. They can be reported on | ||
360 | * some chips during link negotiation prior to INIT, and with | ||
361 | * DDR when faking DDR negotiations with non-IBTA switches. | ||
362 | * The chip counters are adjusted at driver unload if there is | ||
363 | * a non-zero delta. | ||
364 | */ | ||
365 | u64 ibdeltainprog; | ||
366 | u64 ibsymdelta; | ||
367 | u64 ibsymsnap; | ||
368 | u64 iblnkerrdelta; | ||
369 | u64 iblnkerrsnap; | ||
370 | |||
358 | /* time in jiffies at which to re-enable maskederrs */ | 371 | /* time in jiffies at which to re-enable maskederrs */ |
359 | unsigned long ipath_unmasktime; | 372 | unsigned long ipath_unmasktime; |
360 | /* count of egrfull errors, combined for all ports */ | 373 | /* count of egrfull errors, combined for all ports */ |
@@ -464,6 +477,8 @@ struct ipath_devdata { | |||
464 | spinlock_t ipath_kernel_tid_lock; | 477 | spinlock_t ipath_kernel_tid_lock; |
465 | spinlock_t ipath_user_tid_lock; | 478 | spinlock_t ipath_user_tid_lock; |
466 | spinlock_t ipath_sendctrl_lock; | 479 | spinlock_t ipath_sendctrl_lock; |
480 | /* around ipath_pd and (user ports) port_cnt use (intr vs free) */ | ||
481 | spinlock_t ipath_uctxt_lock; | ||
467 | 482 | ||
468 | /* | 483 | /* |
469 | * IPATH_STATUS_*, | 484 | * IPATH_STATUS_*, |
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c index 8f32b17a5eed..c0e933fec218 100644 --- a/drivers/infiniband/hw/ipath/ipath_keys.c +++ b/drivers/infiniband/hw/ipath/ipath_keys.c | |||
@@ -132,6 +132,7 @@ int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge, | |||
132 | * (see ipath_get_dma_mr and ipath_dma.c). | 132 | * (see ipath_get_dma_mr and ipath_dma.c). |
133 | */ | 133 | */ |
134 | if (sge->lkey == 0) { | 134 | if (sge->lkey == 0) { |
135 | /* always a kernel port, no locking needed */ | ||
135 | struct ipath_pd *pd = to_ipd(qp->ibqp.pd); | 136 | struct ipath_pd *pd = to_ipd(qp->ibqp.pd); |
136 | 137 | ||
137 | if (pd->user) { | 138 | if (pd->user) { |
@@ -211,6 +212,7 @@ int ipath_rkey_ok(struct ipath_qp *qp, struct ipath_sge_state *ss, | |||
211 | * (see ipath_get_dma_mr and ipath_dma.c). | 212 | * (see ipath_get_dma_mr and ipath_dma.c). |
212 | */ | 213 | */ |
213 | if (rkey == 0) { | 214 | if (rkey == 0) { |
215 | /* always a kernel port, no locking needed */ | ||
214 | struct ipath_pd *pd = to_ipd(qp->ibqp.pd); | 216 | struct ipath_pd *pd = to_ipd(qp->ibqp.pd); |
215 | 217 | ||
216 | if (pd->user) { | 218 | if (pd->user) { |
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c index be4fc9ada8e7..17a123197477 100644 --- a/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/drivers/infiniband/hw/ipath/ipath_mad.c | |||
@@ -348,6 +348,7 @@ bail: | |||
348 | */ | 348 | */ |
349 | static int get_pkeys(struct ipath_devdata *dd, u16 * pkeys) | 349 | static int get_pkeys(struct ipath_devdata *dd, u16 * pkeys) |
350 | { | 350 | { |
351 | /* always a kernel port, no locking needed */ | ||
351 | struct ipath_portdata *pd = dd->ipath_pd[0]; | 352 | struct ipath_portdata *pd = dd->ipath_pd[0]; |
352 | 353 | ||
353 | memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys)); | 354 | memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys)); |
@@ -730,6 +731,7 @@ static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys) | |||
730 | int i; | 731 | int i; |
731 | int changed = 0; | 732 | int changed = 0; |
732 | 733 | ||
734 | /* always a kernel port, no locking needed */ | ||
733 | pd = dd->ipath_pd[0]; | 735 | pd = dd->ipath_pd[0]; |
734 | 736 | ||
735 | for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) { | 737 | for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) { |
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 4715911101e4..3a5a89b609c4 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c | |||
@@ -745,6 +745,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
745 | struct ipath_swqe *swq = NULL; | 745 | struct ipath_swqe *swq = NULL; |
746 | struct ipath_ibdev *dev; | 746 | struct ipath_ibdev *dev; |
747 | size_t sz; | 747 | size_t sz; |
748 | size_t sg_list_sz; | ||
748 | struct ib_qp *ret; | 749 | struct ib_qp *ret; |
749 | 750 | ||
750 | if (init_attr->create_flags) { | 751 | if (init_attr->create_flags) { |
@@ -789,19 +790,31 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
789 | goto bail; | 790 | goto bail; |
790 | } | 791 | } |
791 | sz = sizeof(*qp); | 792 | sz = sizeof(*qp); |
793 | sg_list_sz = 0; | ||
792 | if (init_attr->srq) { | 794 | if (init_attr->srq) { |
793 | struct ipath_srq *srq = to_isrq(init_attr->srq); | 795 | struct ipath_srq *srq = to_isrq(init_attr->srq); |
794 | 796 | ||
795 | sz += sizeof(*qp->r_sg_list) * | 797 | if (srq->rq.max_sge > 1) |
796 | srq->rq.max_sge; | 798 | sg_list_sz = sizeof(*qp->r_sg_list) * |
797 | } else | 799 | (srq->rq.max_sge - 1); |
798 | sz += sizeof(*qp->r_sg_list) * | 800 | } else if (init_attr->cap.max_recv_sge > 1) |
799 | init_attr->cap.max_recv_sge; | 801 | sg_list_sz = sizeof(*qp->r_sg_list) * |
800 | qp = kmalloc(sz, GFP_KERNEL); | 802 | (init_attr->cap.max_recv_sge - 1); |
803 | qp = kmalloc(sz + sg_list_sz, GFP_KERNEL); | ||
801 | if (!qp) { | 804 | if (!qp) { |
802 | ret = ERR_PTR(-ENOMEM); | 805 | ret = ERR_PTR(-ENOMEM); |
803 | goto bail_swq; | 806 | goto bail_swq; |
804 | } | 807 | } |
808 | if (sg_list_sz && (init_attr->qp_type == IB_QPT_UD || | ||
809 | init_attr->qp_type == IB_QPT_SMI || | ||
810 | init_attr->qp_type == IB_QPT_GSI)) { | ||
811 | qp->r_ud_sg_list = kmalloc(sg_list_sz, GFP_KERNEL); | ||
812 | if (!qp->r_ud_sg_list) { | ||
813 | ret = ERR_PTR(-ENOMEM); | ||
814 | goto bail_qp; | ||
815 | } | ||
816 | } else | ||
817 | qp->r_ud_sg_list = NULL; | ||
805 | if (init_attr->srq) { | 818 | if (init_attr->srq) { |
806 | sz = 0; | 819 | sz = 0; |
807 | qp->r_rq.size = 0; | 820 | qp->r_rq.size = 0; |
@@ -818,7 +831,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
818 | qp->r_rq.size * sz); | 831 | qp->r_rq.size * sz); |
819 | if (!qp->r_rq.wq) { | 832 | if (!qp->r_rq.wq) { |
820 | ret = ERR_PTR(-ENOMEM); | 833 | ret = ERR_PTR(-ENOMEM); |
821 | goto bail_qp; | 834 | goto bail_sg_list; |
822 | } | 835 | } |
823 | } | 836 | } |
824 | 837 | ||
@@ -848,7 +861,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, | |||
848 | if (err) { | 861 | if (err) { |
849 | ret = ERR_PTR(err); | 862 | ret = ERR_PTR(err); |
850 | vfree(qp->r_rq.wq); | 863 | vfree(qp->r_rq.wq); |
851 | goto bail_qp; | 864 | goto bail_sg_list; |
852 | } | 865 | } |
853 | qp->ip = NULL; | 866 | qp->ip = NULL; |
854 | qp->s_tx = NULL; | 867 | qp->s_tx = NULL; |
@@ -925,6 +938,8 @@ bail_ip: | |||
925 | vfree(qp->r_rq.wq); | 938 | vfree(qp->r_rq.wq); |
926 | ipath_free_qp(&dev->qp_table, qp); | 939 | ipath_free_qp(&dev->qp_table, qp); |
927 | free_qpn(&dev->qp_table, qp->ibqp.qp_num); | 940 | free_qpn(&dev->qp_table, qp->ibqp.qp_num); |
941 | bail_sg_list: | ||
942 | kfree(qp->r_ud_sg_list); | ||
928 | bail_qp: | 943 | bail_qp: |
929 | kfree(qp); | 944 | kfree(qp); |
930 | bail_swq: | 945 | bail_swq: |
@@ -989,6 +1004,7 @@ int ipath_destroy_qp(struct ib_qp *ibqp) | |||
989 | kref_put(&qp->ip->ref, ipath_release_mmap_info); | 1004 | kref_put(&qp->ip->ref, ipath_release_mmap_info); |
990 | else | 1005 | else |
991 | vfree(qp->r_rq.wq); | 1006 | vfree(qp->r_rq.wq); |
1007 | kfree(qp->r_ud_sg_list); | ||
992 | vfree(qp->s_wq); | 1008 | vfree(qp->s_wq); |
993 | kfree(qp); | 1009 | kfree(qp); |
994 | return 0; | 1010 | return 0; |
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 7b93cda1a4bd..9170710b950d 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c | |||
@@ -573,9 +573,8 @@ int ipath_make_rc_req(struct ipath_qp *qp) | |||
573 | ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len); | 573 | ohdr->u.rc.reth.length = cpu_to_be32(qp->s_len); |
574 | qp->s_state = OP(RDMA_READ_REQUEST); | 574 | qp->s_state = OP(RDMA_READ_REQUEST); |
575 | hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); | 575 | hwords += sizeof(ohdr->u.rc.reth) / sizeof(u32); |
576 | bth2 = qp->s_psn++ & IPATH_PSN_MASK; | 576 | bth2 = qp->s_psn & IPATH_PSN_MASK; |
577 | if (ipath_cmp24(qp->s_psn, qp->s_next_psn) > 0) | 577 | qp->s_psn = wqe->lpsn + 1; |
578 | qp->s_next_psn = qp->s_psn; | ||
579 | ss = NULL; | 578 | ss = NULL; |
580 | len = 0; | 579 | len = 0; |
581 | qp->s_cur++; | 580 | qp->s_cur++; |
diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c index 284c9bca517e..8e255adf5d9b 100644 --- a/drivers/infiniband/hw/ipath/ipath_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_sdma.c | |||
@@ -698,10 +698,8 @@ retry: | |||
698 | 698 | ||
699 | addr = dma_map_single(&dd->pcidev->dev, tx->txreq.map_addr, | 699 | addr = dma_map_single(&dd->pcidev->dev, tx->txreq.map_addr, |
700 | tx->map_len, DMA_TO_DEVICE); | 700 | tx->map_len, DMA_TO_DEVICE); |
701 | if (dma_mapping_error(&dd->pcidev->dev, addr)) { | 701 | if (dma_mapping_error(&dd->pcidev->dev, addr)) |
702 | ret = -EIO; | 702 | goto ioerr; |
703 | goto unlock; | ||
704 | } | ||
705 | 703 | ||
706 | dwoffset = tx->map_len >> 2; | 704 | dwoffset = tx->map_len >> 2; |
707 | make_sdma_desc(dd, sdmadesc, (u64) addr, dwoffset, 0); | 705 | make_sdma_desc(dd, sdmadesc, (u64) addr, dwoffset, 0); |
@@ -741,6 +739,8 @@ retry: | |||
741 | dw = (len + 3) >> 2; | 739 | dw = (len + 3) >> 2; |
742 | addr = dma_map_single(&dd->pcidev->dev, sge->vaddr, dw << 2, | 740 | addr = dma_map_single(&dd->pcidev->dev, sge->vaddr, dw << 2, |
743 | DMA_TO_DEVICE); | 741 | DMA_TO_DEVICE); |
742 | if (dma_mapping_error(&dd->pcidev->dev, addr)) | ||
743 | goto unmap; | ||
744 | make_sdma_desc(dd, sdmadesc, (u64) addr, dw, dwoffset); | 744 | make_sdma_desc(dd, sdmadesc, (u64) addr, dw, dwoffset); |
745 | /* SDmaUseLargeBuf has to be set in every descriptor */ | 745 | /* SDmaUseLargeBuf has to be set in every descriptor */ |
746 | if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF) | 746 | if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_USELARGEBUF) |
@@ -798,7 +798,18 @@ retry: | |||
798 | list_add_tail(&tx->txreq.list, &dd->ipath_sdma_activelist); | 798 | list_add_tail(&tx->txreq.list, &dd->ipath_sdma_activelist); |
799 | if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_VL15) | 799 | if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_VL15) |
800 | vl15_watchdog_enq(dd); | 800 | vl15_watchdog_enq(dd); |
801 | 801 | goto unlock; | |
802 | |||
803 | unmap: | ||
804 | while (tail != dd->ipath_sdma_descq_tail) { | ||
805 | if (!tail) | ||
806 | tail = dd->ipath_sdma_descq_cnt - 1; | ||
807 | else | ||
808 | tail--; | ||
809 | unmap_desc(dd, tail); | ||
810 | } | ||
811 | ioerr: | ||
812 | ret = -EIO; | ||
802 | unlock: | 813 | unlock: |
803 | spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); | 814 | spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); |
804 | fail: | 815 | fail: |
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c index c8e3d65f0de8..f63e143e3292 100644 --- a/drivers/infiniband/hw/ipath/ipath_stats.c +++ b/drivers/infiniband/hw/ipath/ipath_stats.c | |||
@@ -112,6 +112,14 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg) | |||
112 | dd->ipath_lastrpkts = val; | 112 | dd->ipath_lastrpkts = val; |
113 | } | 113 | } |
114 | val64 = dd->ipath_rpkts; | 114 | val64 = dd->ipath_rpkts; |
115 | } else if (creg == dd->ipath_cregs->cr_ibsymbolerrcnt) { | ||
116 | if (dd->ibdeltainprog) | ||
117 | val64 -= val64 - dd->ibsymsnap; | ||
118 | val64 -= dd->ibsymdelta; | ||
119 | } else if (creg == dd->ipath_cregs->cr_iblinkerrrecovcnt) { | ||
120 | if (dd->ibdeltainprog) | ||
121 | val64 -= val64 - dd->iblnkerrsnap; | ||
122 | val64 -= dd->iblnkerrdelta; | ||
115 | } else | 123 | } else |
116 | val64 = (u64) val; | 124 | val64 = (u64) val; |
117 | 125 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 729446f56aab..91c74cc797ae 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c | |||
@@ -70,8 +70,6 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) | |||
70 | goto done; | 70 | goto done; |
71 | } | 71 | } |
72 | 72 | ||
73 | rsge.sg_list = NULL; | ||
74 | |||
75 | /* | 73 | /* |
76 | * Check that the qkey matches (except for QP0, see 9.6.1.4.1). | 74 | * Check that the qkey matches (except for QP0, see 9.6.1.4.1). |
77 | * Qkeys with the high order bit set mean use the | 75 | * Qkeys with the high order bit set mean use the |
@@ -115,21 +113,6 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) | |||
115 | rq = &qp->r_rq; | 113 | rq = &qp->r_rq; |
116 | } | 114 | } |
117 | 115 | ||
118 | if (rq->max_sge > 1) { | ||
119 | /* | ||
120 | * XXX We could use GFP_KERNEL if ipath_do_send() | ||
121 | * was always called from the tasklet instead of | ||
122 | * from ipath_post_send(). | ||
123 | */ | ||
124 | rsge.sg_list = kmalloc((rq->max_sge - 1) * | ||
125 | sizeof(struct ipath_sge), | ||
126 | GFP_ATOMIC); | ||
127 | if (!rsge.sg_list) { | ||
128 | dev->n_pkt_drops++; | ||
129 | goto drop; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | /* | 116 | /* |
134 | * Get the next work request entry to find where to put the data. | 117 | * Get the next work request entry to find where to put the data. |
135 | * Note that it is safe to drop the lock after changing rq->tail | 118 | * Note that it is safe to drop the lock after changing rq->tail |
@@ -147,6 +130,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) | |||
147 | goto drop; | 130 | goto drop; |
148 | } | 131 | } |
149 | wqe = get_rwqe_ptr(rq, tail); | 132 | wqe = get_rwqe_ptr(rq, tail); |
133 | rsge.sg_list = qp->r_ud_sg_list; | ||
150 | if (!ipath_init_sge(qp, wqe, &rlen, &rsge)) { | 134 | if (!ipath_init_sge(qp, wqe, &rlen, &rsge)) { |
151 | spin_unlock_irqrestore(&rq->lock, flags); | 135 | spin_unlock_irqrestore(&rq->lock, flags); |
152 | dev->n_pkt_drops++; | 136 | dev->n_pkt_drops++; |
@@ -242,7 +226,6 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) | |||
242 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, | 226 | ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, |
243 | swqe->wr.send_flags & IB_SEND_SOLICITED); | 227 | swqe->wr.send_flags & IB_SEND_SOLICITED); |
244 | drop: | 228 | drop: |
245 | kfree(rsge.sg_list); | ||
246 | if (atomic_dec_and_test(&qp->refcount)) | 229 | if (atomic_dec_and_test(&qp->refcount)) |
247 | wake_up(&qp->wait); | 230 | wake_up(&qp->wait); |
248 | done:; | 231 | done:; |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index eabc4247860b..cdf0e6abd34d 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
@@ -1852,7 +1852,7 @@ unsigned ipath_get_npkeys(struct ipath_devdata *dd) | |||
1852 | } | 1852 | } |
1853 | 1853 | ||
1854 | /** | 1854 | /** |
1855 | * ipath_get_pkey - return the indexed PKEY from the port 0 PKEY table | 1855 | * ipath_get_pkey - return the indexed PKEY from the port PKEY table |
1856 | * @dd: the infinipath device | 1856 | * @dd: the infinipath device |
1857 | * @index: the PKEY index | 1857 | * @index: the PKEY index |
1858 | */ | 1858 | */ |
@@ -1860,6 +1860,7 @@ unsigned ipath_get_pkey(struct ipath_devdata *dd, unsigned index) | |||
1860 | { | 1860 | { |
1861 | unsigned ret; | 1861 | unsigned ret; |
1862 | 1862 | ||
1863 | /* always a kernel port, no locking needed */ | ||
1863 | if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys)) | 1864 | if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys)) |
1864 | ret = 0; | 1865 | ret = 0; |
1865 | else | 1866 | else |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index 9d12ae8a778e..11e3f613df93 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h | |||
@@ -431,6 +431,7 @@ struct ipath_qp { | |||
431 | u32 s_lsn; /* limit sequence number (credit) */ | 431 | u32 s_lsn; /* limit sequence number (credit) */ |
432 | struct ipath_swqe *s_wq; /* send work queue */ | 432 | struct ipath_swqe *s_wq; /* send work queue */ |
433 | struct ipath_swqe *s_wqe; | 433 | struct ipath_swqe *s_wqe; |
434 | struct ipath_sge *r_ud_sg_list; | ||
434 | struct ipath_rq r_rq; /* receive work queue */ | 435 | struct ipath_rq r_rq; /* receive work queue */ |
435 | struct ipath_sge r_sg_list[0]; /* verified SGEs */ | 436 | struct ipath_sge r_sg_list[0]; /* verified SGEs */ |
436 | }; | 437 | }; |
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index 18308494a195..8415ecce5c4c 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c | |||
@@ -222,7 +222,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector | |||
222 | } | 222 | } |
223 | 223 | ||
224 | err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, | 224 | err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, |
225 | cq->db.dma, &cq->mcq, 0); | 225 | cq->db.dma, &cq->mcq, vector, 0); |
226 | if (err) | 226 | if (err) |
227 | goto err_dbmap; | 227 | goto err_dbmap; |
228 | 228 | ||
@@ -325,15 +325,17 @@ static int mlx4_ib_get_outstanding_cqes(struct mlx4_ib_cq *cq) | |||
325 | 325 | ||
326 | static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq) | 326 | static void mlx4_ib_cq_resize_copy_cqes(struct mlx4_ib_cq *cq) |
327 | { | 327 | { |
328 | struct mlx4_cqe *cqe; | 328 | struct mlx4_cqe *cqe, *new_cqe; |
329 | int i; | 329 | int i; |
330 | 330 | ||
331 | i = cq->mcq.cons_index; | 331 | i = cq->mcq.cons_index; |
332 | cqe = get_cqe(cq, i & cq->ibcq.cqe); | 332 | cqe = get_cqe(cq, i & cq->ibcq.cqe); |
333 | while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) { | 333 | while ((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) != MLX4_CQE_OPCODE_RESIZE) { |
334 | memcpy(get_cqe_from_buf(&cq->resize_buf->buf, | 334 | new_cqe = get_cqe_from_buf(&cq->resize_buf->buf, |
335 | (i + 1) & cq->resize_buf->cqe), | 335 | (i + 1) & cq->resize_buf->cqe); |
336 | get_cqe(cq, i & cq->ibcq.cqe), sizeof(struct mlx4_cqe)); | 336 | memcpy(new_cqe, get_cqe(cq, i & cq->ibcq.cqe), sizeof(struct mlx4_cqe)); |
337 | new_cqe->owner_sr_opcode = (cqe->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK) | | ||
338 | (((i + 1) & (cq->resize_buf->cqe + 1)) ? MLX4_CQE_OWNER_MASK : 0); | ||
337 | cqe = get_cqe(cq, ++i & cq->ibcq.cqe); | 339 | cqe = get_cqe(cq, ++i & cq->ibcq.cqe); |
338 | } | 340 | } |
339 | ++cq->mcq.cons_index; | 341 | ++cq->mcq.cons_index; |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 2e80f8f47b02..dcefe1fceb5c 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -578,7 +578,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
578 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) | 578 | mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) |
579 | ibdev->num_ports++; | 579 | ibdev->num_ports++; |
580 | ibdev->ib_dev.phys_port_cnt = ibdev->num_ports; | 580 | ibdev->ib_dev.phys_port_cnt = ibdev->num_ports; |
581 | ibdev->ib_dev.num_comp_vectors = 1; | 581 | ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors; |
582 | ibdev->ib_dev.dma_device = &dev->pdev->dev; | 582 | ibdev->ib_dev.dma_device = &dev->pdev->dev; |
583 | 583 | ||
584 | ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_ABI_VERSION; | 584 | ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_ABI_VERSION; |
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 1595dc7bba9d..13a5bb1a7bcf 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h | |||
@@ -137,14 +137,18 @@ | |||
137 | 137 | ||
138 | #ifdef CONFIG_INFINIBAND_NES_DEBUG | 138 | #ifdef CONFIG_INFINIBAND_NES_DEBUG |
139 | #define nes_debug(level, fmt, args...) \ | 139 | #define nes_debug(level, fmt, args...) \ |
140 | do { \ | ||
140 | if (level & nes_debug_level) \ | 141 | if (level & nes_debug_level) \ |
141 | printk(KERN_ERR PFX "%s[%u]: " fmt, __func__, __LINE__, ##args) | 142 | printk(KERN_ERR PFX "%s[%u]: " fmt, __func__, __LINE__, ##args); \ |
142 | 143 | } while (0) | |
143 | #define assert(expr) \ | 144 | |
144 | if (!(expr)) { \ | 145 | #define assert(expr) \ |
145 | printk(KERN_ERR PFX "Assertion failed! %s, %s, %s, line %d\n", \ | 146 | do { \ |
146 | #expr, __FILE__, __func__, __LINE__); \ | 147 | if (!(expr)) { \ |
147 | } | 148 | printk(KERN_ERR PFX "Assertion failed! %s, %s, %s, line %d\n", \ |
149 | #expr, __FILE__, __func__, __LINE__); \ | ||
150 | } \ | ||
151 | } while (0) | ||
148 | 152 | ||
149 | #define NES_EVENT_TIMEOUT 1200000 | 153 | #define NES_EVENT_TIMEOUT 1200000 |
150 | #else | 154 | #else |
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 2854a6f7fdfe..a812db243477 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -86,15 +86,14 @@ static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, | |||
86 | struct nes_cm_node *); | 86 | struct nes_cm_node *); |
87 | static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, | 87 | static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, |
88 | struct nes_cm_node *); | 88 | struct nes_cm_node *); |
89 | static void mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, | 89 | static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, |
90 | struct sk_buff *); | 90 | struct sk_buff *); |
91 | static int mini_cm_dealloc_core(struct nes_cm_core *); | 91 | static int mini_cm_dealloc_core(struct nes_cm_core *); |
92 | static int mini_cm_get(struct nes_cm_core *); | 92 | static int mini_cm_get(struct nes_cm_core *); |
93 | static int mini_cm_set(struct nes_cm_core *, u32, u32); | 93 | static int mini_cm_set(struct nes_cm_core *, u32, u32); |
94 | 94 | ||
95 | static struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *, | 95 | static void form_cm_frame(struct sk_buff *, struct nes_cm_node *, |
96 | void *, u32, void *, u32, u8); | 96 | void *, u32, void *, u32, u8); |
97 | static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node); | ||
98 | static int add_ref_cm_node(struct nes_cm_node *); | 97 | static int add_ref_cm_node(struct nes_cm_node *); |
99 | static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *); | 98 | static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *); |
100 | 99 | ||
@@ -251,7 +250,7 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len) | |||
251 | * form_cm_frame - get a free packet and build empty frame Use | 250 | * form_cm_frame - get a free packet and build empty frame Use |
252 | * node info to build. | 251 | * node info to build. |
253 | */ | 252 | */ |
254 | static struct sk_buff *form_cm_frame(struct sk_buff *skb, | 253 | static void form_cm_frame(struct sk_buff *skb, |
255 | struct nes_cm_node *cm_node, void *options, u32 optionsize, | 254 | struct nes_cm_node *cm_node, void *options, u32 optionsize, |
256 | void *data, u32 datasize, u8 flags) | 255 | void *data, u32 datasize, u8 flags) |
257 | { | 256 | { |
@@ -339,7 +338,6 @@ static struct sk_buff *form_cm_frame(struct sk_buff *skb, | |||
339 | skb_shinfo(skb)->nr_frags = 0; | 338 | skb_shinfo(skb)->nr_frags = 0; |
340 | cm_packets_created++; | 339 | cm_packets_created++; |
341 | 340 | ||
342 | return skb; | ||
343 | } | 341 | } |
344 | 342 | ||
345 | 343 | ||
@@ -356,7 +354,6 @@ static void print_core(struct nes_cm_core *core) | |||
356 | 354 | ||
357 | nes_debug(NES_DBG_CM, "State : %u \n", core->state); | 355 | nes_debug(NES_DBG_CM, "State : %u \n", core->state); |
358 | 356 | ||
359 | nes_debug(NES_DBG_CM, "Tx Free cnt : %u \n", skb_queue_len(&core->tx_free_list)); | ||
360 | nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt)); | 357 | nes_debug(NES_DBG_CM, "Listen Nodes : %u \n", atomic_read(&core->listen_node_cnt)); |
361 | nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt)); | 358 | nes_debug(NES_DBG_CM, "Active Nodes : %u \n", atomic_read(&core->node_cnt)); |
362 | 359 | ||
@@ -381,8 +378,6 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
381 | int ret = 0; | 378 | int ret = 0; |
382 | u32 was_timer_set; | 379 | u32 was_timer_set; |
383 | 380 | ||
384 | if (!cm_node) | ||
385 | return -EINVAL; | ||
386 | new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC); | 381 | new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC); |
387 | if (!new_send) | 382 | if (!new_send) |
388 | return -1; | 383 | return -1; |
@@ -459,13 +454,23 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
459 | int ret = NETDEV_TX_OK; | 454 | int ret = NETDEV_TX_OK; |
460 | enum nes_cm_node_state last_state; | 455 | enum nes_cm_node_state last_state; |
461 | 456 | ||
457 | struct list_head timer_list; | ||
458 | INIT_LIST_HEAD(&timer_list); | ||
462 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 459 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
463 | 460 | ||
464 | list_for_each_safe(list_node, list_core_temp, | 461 | list_for_each_safe(list_node, list_core_temp, |
465 | &cm_core->connected_nodes) { | 462 | &cm_core->connected_nodes) { |
466 | cm_node = container_of(list_node, struct nes_cm_node, list); | 463 | cm_node = container_of(list_node, struct nes_cm_node, list); |
467 | add_ref_cm_node(cm_node); | 464 | if (!list_empty(&cm_node->recv_list) || (cm_node->send_entry)) { |
468 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | 465 | add_ref_cm_node(cm_node); |
466 | list_add(&cm_node->timer_entry, &timer_list); | ||
467 | } | ||
468 | } | ||
469 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | ||
470 | |||
471 | list_for_each_safe(list_node, list_core_temp, &timer_list) { | ||
472 | cm_node = container_of(list_node, struct nes_cm_node, | ||
473 | timer_entry); | ||
469 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); | 474 | spin_lock_irqsave(&cm_node->recv_list_lock, flags); |
470 | list_for_each_safe(list_core, list_node_temp, | 475 | list_for_each_safe(list_core, list_node_temp, |
471 | &cm_node->recv_list) { | 476 | &cm_node->recv_list) { |
@@ -519,7 +524,7 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
519 | do { | 524 | do { |
520 | send_entry = cm_node->send_entry; | 525 | send_entry = cm_node->send_entry; |
521 | if (!send_entry) | 526 | if (!send_entry) |
522 | continue; | 527 | break; |
523 | if (time_after(send_entry->timetosend, jiffies)) { | 528 | if (time_after(send_entry->timetosend, jiffies)) { |
524 | if (cm_node->state != NES_CM_STATE_TSA) { | 529 | if (cm_node->state != NES_CM_STATE_TSA) { |
525 | if ((nexttimeout > | 530 | if ((nexttimeout > |
@@ -528,18 +533,18 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
528 | nexttimeout = | 533 | nexttimeout = |
529 | send_entry->timetosend; | 534 | send_entry->timetosend; |
530 | settimer = 1; | 535 | settimer = 1; |
531 | continue; | 536 | break; |
532 | } | 537 | } |
533 | } else { | 538 | } else { |
534 | free_retrans_entry(cm_node); | 539 | free_retrans_entry(cm_node); |
535 | continue; | 540 | break; |
536 | } | 541 | } |
537 | } | 542 | } |
538 | 543 | ||
539 | if ((cm_node->state == NES_CM_STATE_TSA) || | 544 | if ((cm_node->state == NES_CM_STATE_TSA) || |
540 | (cm_node->state == NES_CM_STATE_CLOSED)) { | 545 | (cm_node->state == NES_CM_STATE_CLOSED)) { |
541 | free_retrans_entry(cm_node); | 546 | free_retrans_entry(cm_node); |
542 | continue; | 547 | break; |
543 | } | 548 | } |
544 | 549 | ||
545 | if (!send_entry->retranscount || | 550 | if (!send_entry->retranscount || |
@@ -557,7 +562,7 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
557 | NES_CM_EVENT_ABORTED); | 562 | NES_CM_EVENT_ABORTED); |
558 | spin_lock_irqsave(&cm_node->retrans_list_lock, | 563 | spin_lock_irqsave(&cm_node->retrans_list_lock, |
559 | flags); | 564 | flags); |
560 | continue; | 565 | break; |
561 | } | 566 | } |
562 | atomic_inc(&send_entry->skb->users); | 567 | atomic_inc(&send_entry->skb->users); |
563 | cm_packets_retrans++; | 568 | cm_packets_retrans++; |
@@ -583,7 +588,7 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
583 | send_entry->retrycount--; | 588 | send_entry->retrycount--; |
584 | nexttimeout = jiffies + NES_SHORT_TIME; | 589 | nexttimeout = jiffies + NES_SHORT_TIME; |
585 | settimer = 1; | 590 | settimer = 1; |
586 | continue; | 591 | break; |
587 | } else { | 592 | } else { |
588 | cm_packets_sent++; | 593 | cm_packets_sent++; |
589 | } | 594 | } |
@@ -615,14 +620,12 @@ static void nes_cm_timer_tick(unsigned long pass) | |||
615 | 620 | ||
616 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); | 621 | spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); |
617 | rem_ref_cm_node(cm_node->cm_core, cm_node); | 622 | rem_ref_cm_node(cm_node->cm_core, cm_node); |
618 | spin_lock_irqsave(&cm_core->ht_lock, flags); | ||
619 | if (ret != NETDEV_TX_OK) { | 623 | if (ret != NETDEV_TX_OK) { |
620 | nes_debug(NES_DBG_CM, "rexmit failed for cm_node=%p\n", | 624 | nes_debug(NES_DBG_CM, "rexmit failed for cm_node=%p\n", |
621 | cm_node); | 625 | cm_node); |
622 | break; | 626 | break; |
623 | } | 627 | } |
624 | } | 628 | } |
625 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | ||
626 | 629 | ||
627 | if (settimer) { | 630 | if (settimer) { |
628 | if (!timer_pending(&cm_core->tcp_timer)) { | 631 | if (!timer_pending(&cm_core->tcp_timer)) { |
@@ -683,7 +686,7 @@ static int send_syn(struct nes_cm_node *cm_node, u32 sendack, | |||
683 | optionssize += 1; | 686 | optionssize += 1; |
684 | 687 | ||
685 | if (!skb) | 688 | if (!skb) |
686 | skb = get_free_pkt(cm_node); | 689 | skb = dev_alloc_skb(MAX_CM_BUFFER); |
687 | if (!skb) { | 690 | if (!skb) { |
688 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 691 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
689 | return -1; | 692 | return -1; |
@@ -708,7 +711,7 @@ static int send_reset(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
708 | int flags = SET_RST | SET_ACK; | 711 | int flags = SET_RST | SET_ACK; |
709 | 712 | ||
710 | if (!skb) | 713 | if (!skb) |
711 | skb = get_free_pkt(cm_node); | 714 | skb = dev_alloc_skb(MAX_CM_BUFFER); |
712 | if (!skb) { | 715 | if (!skb) { |
713 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 716 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
714 | return -1; | 717 | return -1; |
@@ -729,7 +732,7 @@ static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
729 | int ret; | 732 | int ret; |
730 | 733 | ||
731 | if (!skb) | 734 | if (!skb) |
732 | skb = get_free_pkt(cm_node); | 735 | skb = dev_alloc_skb(MAX_CM_BUFFER); |
733 | 736 | ||
734 | if (!skb) { | 737 | if (!skb) { |
735 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 738 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
@@ -752,7 +755,7 @@ static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
752 | 755 | ||
753 | /* if we didn't get a frame get one */ | 756 | /* if we didn't get a frame get one */ |
754 | if (!skb) | 757 | if (!skb) |
755 | skb = get_free_pkt(cm_node); | 758 | skb = dev_alloc_skb(MAX_CM_BUFFER); |
756 | 759 | ||
757 | if (!skb) { | 760 | if (!skb) { |
758 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); | 761 | nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n"); |
@@ -767,59 +770,15 @@ static int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb) | |||
767 | 770 | ||
768 | 771 | ||
769 | /** | 772 | /** |
770 | * get_free_pkt | ||
771 | */ | ||
772 | static struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node) | ||
773 | { | ||
774 | struct sk_buff *skb, *new_skb; | ||
775 | |||
776 | /* check to see if we need to repopulate the free tx pkt queue */ | ||
777 | if (skb_queue_len(&cm_node->cm_core->tx_free_list) < NES_CM_FREE_PKT_LO_WATERMARK) { | ||
778 | while (skb_queue_len(&cm_node->cm_core->tx_free_list) < | ||
779 | cm_node->cm_core->free_tx_pkt_max) { | ||
780 | /* replace the frame we took, we won't get it back */ | ||
781 | new_skb = dev_alloc_skb(cm_node->cm_core->mtu); | ||
782 | BUG_ON(!new_skb); | ||
783 | /* add a replacement frame to the free tx list head */ | ||
784 | skb_queue_head(&cm_node->cm_core->tx_free_list, new_skb); | ||
785 | } | ||
786 | } | ||
787 | |||
788 | skb = skb_dequeue(&cm_node->cm_core->tx_free_list); | ||
789 | |||
790 | return skb; | ||
791 | } | ||
792 | |||
793 | |||
794 | /** | ||
795 | * make_hashkey - generate hash key from node tuple | ||
796 | */ | ||
797 | static inline int make_hashkey(u16 loc_port, nes_addr_t loc_addr, u16 rem_port, | ||
798 | nes_addr_t rem_addr) | ||
799 | { | ||
800 | u32 hashkey = 0; | ||
801 | |||
802 | hashkey = loc_addr + rem_addr + loc_port + rem_port; | ||
803 | hashkey = (hashkey % NES_CM_HASHTABLE_SIZE); | ||
804 | |||
805 | return hashkey; | ||
806 | } | ||
807 | |||
808 | |||
809 | /** | ||
810 | * find_node - find a cm node that matches the reference cm node | 773 | * find_node - find a cm node that matches the reference cm node |
811 | */ | 774 | */ |
812 | static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, | 775 | static struct nes_cm_node *find_node(struct nes_cm_core *cm_core, |
813 | u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr) | 776 | u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr) |
814 | { | 777 | { |
815 | unsigned long flags; | 778 | unsigned long flags; |
816 | u32 hashkey; | ||
817 | struct list_head *hte; | 779 | struct list_head *hte; |
818 | struct nes_cm_node *cm_node; | 780 | struct nes_cm_node *cm_node; |
819 | 781 | ||
820 | /* make a hash index key for this packet */ | ||
821 | hashkey = make_hashkey(loc_port, loc_addr, rem_port, rem_addr); | ||
822 | |||
823 | /* get a handle on the hte */ | 782 | /* get a handle on the hte */ |
824 | hte = &cm_core->connected_nodes; | 783 | hte = &cm_core->connected_nodes; |
825 | 784 | ||
@@ -887,7 +846,6 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core, | |||
887 | static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node) | 846 | static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node) |
888 | { | 847 | { |
889 | unsigned long flags; | 848 | unsigned long flags; |
890 | u32 hashkey; | ||
891 | struct list_head *hte; | 849 | struct list_head *hte; |
892 | 850 | ||
893 | if (!cm_node || !cm_core) | 851 | if (!cm_node || !cm_core) |
@@ -896,11 +854,6 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node | |||
896 | nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n", | 854 | nes_debug(NES_DBG_CM, "Adding Node %p to Active Connection HT\n", |
897 | cm_node); | 855 | cm_node); |
898 | 856 | ||
899 | /* first, make an index into our hash table */ | ||
900 | hashkey = make_hashkey(cm_node->loc_port, cm_node->loc_addr, | ||
901 | cm_node->rem_port, cm_node->rem_addr); | ||
902 | cm_node->hashkey = hashkey; | ||
903 | |||
904 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 857 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
905 | 858 | ||
906 | /* get a handle on the hash table element (list head for this slot) */ | 859 | /* get a handle on the hash table element (list head for this slot) */ |
@@ -925,28 +878,36 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core, | |||
925 | struct list_head *list_pos = NULL; | 878 | struct list_head *list_pos = NULL; |
926 | struct list_head *list_temp = NULL; | 879 | struct list_head *list_temp = NULL; |
927 | struct nes_cm_node *cm_node = NULL; | 880 | struct nes_cm_node *cm_node = NULL; |
881 | struct list_head reset_list; | ||
928 | 882 | ||
929 | nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, " | 883 | nes_debug(NES_DBG_CM, "attempting listener= %p free_nodes= %d, " |
930 | "refcnt=%d\n", listener, free_hanging_nodes, | 884 | "refcnt=%d\n", listener, free_hanging_nodes, |
931 | atomic_read(&listener->ref_count)); | 885 | atomic_read(&listener->ref_count)); |
932 | /* free non-accelerated child nodes for this listener */ | 886 | /* free non-accelerated child nodes for this listener */ |
887 | INIT_LIST_HEAD(&reset_list); | ||
933 | if (free_hanging_nodes) { | 888 | if (free_hanging_nodes) { |
934 | spin_lock_irqsave(&cm_core->ht_lock, flags); | 889 | spin_lock_irqsave(&cm_core->ht_lock, flags); |
935 | list_for_each_safe(list_pos, list_temp, | 890 | list_for_each_safe(list_pos, list_temp, |
936 | &g_cm_core->connected_nodes) { | 891 | &g_cm_core->connected_nodes) { |
937 | cm_node = container_of(list_pos, struct nes_cm_node, | 892 | cm_node = container_of(list_pos, struct nes_cm_node, |
938 | list); | 893 | list); |
939 | if ((cm_node->listener == listener) && | 894 | if ((cm_node->listener == listener) && |
940 | (!cm_node->accelerated)) { | 895 | (!cm_node->accelerated)) { |
941 | cleanup_retrans_entry(cm_node); | 896 | add_ref_cm_node(cm_node); |
942 | spin_unlock_irqrestore(&cm_core->ht_lock, | 897 | list_add(&cm_node->reset_entry, &reset_list); |
943 | flags); | ||
944 | send_reset(cm_node, NULL); | ||
945 | spin_lock_irqsave(&cm_core->ht_lock, flags); | ||
946 | } | 898 | } |
947 | } | 899 | } |
948 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); | 900 | spin_unlock_irqrestore(&cm_core->ht_lock, flags); |
949 | } | 901 | } |
902 | |||
903 | list_for_each_safe(list_pos, list_temp, &reset_list) { | ||
904 | cm_node = container_of(list_pos, struct nes_cm_node, | ||
905 | reset_entry); | ||
906 | cleanup_retrans_entry(cm_node); | ||
907 | send_reset(cm_node, NULL); | ||
908 | rem_ref_cm_node(cm_node->cm_core, cm_node); | ||
909 | } | ||
910 | |||
950 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); | 911 | spin_lock_irqsave(&cm_core->listen_list_lock, flags); |
951 | if (!atomic_dec_return(&listener->ref_count)) { | 912 | if (!atomic_dec_return(&listener->ref_count)) { |
952 | list_del(&listener->list); | 913 | list_del(&listener->list); |
@@ -1123,7 +1084,10 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core, | |||
1123 | 1084 | ||
1124 | cm_node->loopbackpartner = NULL; | 1085 | cm_node->loopbackpartner = NULL; |
1125 | /* get the mac addr for the remote node */ | 1086 | /* get the mac addr for the remote node */ |
1126 | arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE); | 1087 | if (ipv4_is_loopback(htonl(cm_node->rem_addr))) |
1088 | arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE); | ||
1089 | else | ||
1090 | arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE); | ||
1127 | if (arpindex < 0) { | 1091 | if (arpindex < 0) { |
1128 | arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr); | 1092 | arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr); |
1129 | if (arpindex < 0) { | 1093 | if (arpindex < 0) { |
@@ -1303,7 +1267,6 @@ static void drop_packet(struct sk_buff *skb) | |||
1303 | static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | 1267 | static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, |
1304 | struct tcphdr *tcph) | 1268 | struct tcphdr *tcph) |
1305 | { | 1269 | { |
1306 | atomic_inc(&cm_resets_recvd); | ||
1307 | nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " | 1270 | nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " |
1308 | "refcnt=%d\n", cm_node, cm_node->state, | 1271 | "refcnt=%d\n", cm_node, cm_node->state, |
1309 | atomic_read(&cm_node->ref_count)); | 1272 | atomic_read(&cm_node->ref_count)); |
@@ -1341,6 +1304,7 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1341 | { | 1304 | { |
1342 | 1305 | ||
1343 | int reset = 0; /* whether to send reset in case of err.. */ | 1306 | int reset = 0; /* whether to send reset in case of err.. */ |
1307 | int passive_state; | ||
1344 | atomic_inc(&cm_resets_recvd); | 1308 | atomic_inc(&cm_resets_recvd); |
1345 | nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u." | 1309 | nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u." |
1346 | " refcnt=%d\n", cm_node, cm_node->state, | 1310 | " refcnt=%d\n", cm_node, cm_node->state, |
@@ -1354,7 +1318,14 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1354 | cm_node->listener, cm_node->state); | 1318 | cm_node->listener, cm_node->state); |
1355 | active_open_err(cm_node, skb, reset); | 1319 | active_open_err(cm_node, skb, reset); |
1356 | break; | 1320 | break; |
1357 | /* For PASSIVE open states, remove the cm_node event */ | 1321 | case NES_CM_STATE_MPAREQ_RCVD: |
1322 | passive_state = atomic_add_return(1, &cm_node->passive_state); | ||
1323 | if (passive_state == NES_SEND_RESET_EVENT) | ||
1324 | create_event(cm_node, NES_CM_EVENT_RESET); | ||
1325 | cleanup_retrans_entry(cm_node); | ||
1326 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1327 | dev_kfree_skb_any(skb); | ||
1328 | break; | ||
1358 | case NES_CM_STATE_ESTABLISHED: | 1329 | case NES_CM_STATE_ESTABLISHED: |
1359 | case NES_CM_STATE_SYN_RCVD: | 1330 | case NES_CM_STATE_SYN_RCVD: |
1360 | case NES_CM_STATE_LISTENING: | 1331 | case NES_CM_STATE_LISTENING: |
@@ -1362,7 +1333,14 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1362 | passive_open_err(cm_node, skb, reset); | 1333 | passive_open_err(cm_node, skb, reset); |
1363 | break; | 1334 | break; |
1364 | case NES_CM_STATE_TSA: | 1335 | case NES_CM_STATE_TSA: |
1336 | active_open_err(cm_node, skb, reset); | ||
1337 | break; | ||
1338 | case NES_CM_STATE_CLOSED: | ||
1339 | cleanup_retrans_entry(cm_node); | ||
1340 | drop_packet(skb); | ||
1341 | break; | ||
1365 | default: | 1342 | default: |
1343 | drop_packet(skb); | ||
1366 | break; | 1344 | break; |
1367 | } | 1345 | } |
1368 | } | 1346 | } |
@@ -1391,6 +1369,9 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1391 | dev_kfree_skb_any(skb); | 1369 | dev_kfree_skb_any(skb); |
1392 | if (type == NES_CM_EVENT_CONNECTED) | 1370 | if (type == NES_CM_EVENT_CONNECTED) |
1393 | cm_node->state = NES_CM_STATE_TSA; | 1371 | cm_node->state = NES_CM_STATE_TSA; |
1372 | else | ||
1373 | atomic_set(&cm_node->passive_state, | ||
1374 | NES_PASSIVE_STATE_INDICATED); | ||
1394 | create_event(cm_node, type); | 1375 | create_event(cm_node, type); |
1395 | 1376 | ||
1396 | } | 1377 | } |
@@ -1471,7 +1452,7 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1471 | int optionsize; | 1452 | int optionsize; |
1472 | 1453 | ||
1473 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1454 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1474 | skb_pull(skb, tcph->doff << 2); | 1455 | skb_trim(skb, 0); |
1475 | inc_sequence = ntohl(tcph->seq); | 1456 | inc_sequence = ntohl(tcph->seq); |
1476 | 1457 | ||
1477 | switch (cm_node->state) { | 1458 | switch (cm_node->state) { |
@@ -1504,6 +1485,10 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1504 | cm_node->state = NES_CM_STATE_SYN_RCVD; | 1485 | cm_node->state = NES_CM_STATE_SYN_RCVD; |
1505 | send_syn(cm_node, 1, skb); | 1486 | send_syn(cm_node, 1, skb); |
1506 | break; | 1487 | break; |
1488 | case NES_CM_STATE_CLOSED: | ||
1489 | cleanup_retrans_entry(cm_node); | ||
1490 | send_reset(cm_node, skb); | ||
1491 | break; | ||
1507 | case NES_CM_STATE_TSA: | 1492 | case NES_CM_STATE_TSA: |
1508 | case NES_CM_STATE_ESTABLISHED: | 1493 | case NES_CM_STATE_ESTABLISHED: |
1509 | case NES_CM_STATE_FIN_WAIT1: | 1494 | case NES_CM_STATE_FIN_WAIT1: |
@@ -1512,7 +1497,6 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1512 | case NES_CM_STATE_LAST_ACK: | 1497 | case NES_CM_STATE_LAST_ACK: |
1513 | case NES_CM_STATE_CLOSING: | 1498 | case NES_CM_STATE_CLOSING: |
1514 | case NES_CM_STATE_UNKNOWN: | 1499 | case NES_CM_STATE_UNKNOWN: |
1515 | case NES_CM_STATE_CLOSED: | ||
1516 | default: | 1500 | default: |
1517 | drop_packet(skb); | 1501 | drop_packet(skb); |
1518 | break; | 1502 | break; |
@@ -1528,7 +1512,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1528 | int optionsize; | 1512 | int optionsize; |
1529 | 1513 | ||
1530 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1514 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1531 | skb_pull(skb, tcph->doff << 2); | 1515 | skb_trim(skb, 0); |
1532 | inc_sequence = ntohl(tcph->seq); | 1516 | inc_sequence = ntohl(tcph->seq); |
1533 | switch (cm_node->state) { | 1517 | switch (cm_node->state) { |
1534 | case NES_CM_STATE_SYN_SENT: | 1518 | case NES_CM_STATE_SYN_SENT: |
@@ -1552,6 +1536,12 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1552 | /* passive open, so should not be here */ | 1536 | /* passive open, so should not be here */ |
1553 | passive_open_err(cm_node, skb, 1); | 1537 | passive_open_err(cm_node, skb, 1); |
1554 | break; | 1538 | break; |
1539 | case NES_CM_STATE_LISTENING: | ||
1540 | case NES_CM_STATE_CLOSED: | ||
1541 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1542 | cleanup_retrans_entry(cm_node); | ||
1543 | send_reset(cm_node, skb); | ||
1544 | break; | ||
1555 | case NES_CM_STATE_ESTABLISHED: | 1545 | case NES_CM_STATE_ESTABLISHED: |
1556 | case NES_CM_STATE_FIN_WAIT1: | 1546 | case NES_CM_STATE_FIN_WAIT1: |
1557 | case NES_CM_STATE_FIN_WAIT2: | 1547 | case NES_CM_STATE_FIN_WAIT2: |
@@ -1559,7 +1549,6 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1559 | case NES_CM_STATE_TSA: | 1549 | case NES_CM_STATE_TSA: |
1560 | case NES_CM_STATE_CLOSING: | 1550 | case NES_CM_STATE_CLOSING: |
1561 | case NES_CM_STATE_UNKNOWN: | 1551 | case NES_CM_STATE_UNKNOWN: |
1562 | case NES_CM_STATE_CLOSED: | ||
1563 | case NES_CM_STATE_MPAREQ_SENT: | 1552 | case NES_CM_STATE_MPAREQ_SENT: |
1564 | default: | 1553 | default: |
1565 | drop_packet(skb); | 1554 | drop_packet(skb); |
@@ -1574,6 +1563,13 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1574 | u32 inc_sequence; | 1563 | u32 inc_sequence; |
1575 | u32 rem_seq_ack; | 1564 | u32 rem_seq_ack; |
1576 | u32 rem_seq; | 1565 | u32 rem_seq; |
1566 | int ret; | ||
1567 | int optionsize; | ||
1568 | u32 temp_seq = cm_node->tcp_cntxt.loc_seq_num; | ||
1569 | |||
1570 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | ||
1571 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1572 | |||
1577 | if (check_seq(cm_node, tcph, skb)) | 1573 | if (check_seq(cm_node, tcph, skb)) |
1578 | return; | 1574 | return; |
1579 | 1575 | ||
@@ -1586,7 +1582,18 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1586 | switch (cm_node->state) { | 1582 | switch (cm_node->state) { |
1587 | case NES_CM_STATE_SYN_RCVD: | 1583 | case NES_CM_STATE_SYN_RCVD: |
1588 | /* Passive OPEN */ | 1584 | /* Passive OPEN */ |
1585 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 1); | ||
1586 | if (ret) | ||
1587 | break; | ||
1589 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1588 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1589 | cm_node->tcp_cntxt.loc_seq_num = temp_seq; | ||
1590 | if (cm_node->tcp_cntxt.rem_ack_num != | ||
1591 | cm_node->tcp_cntxt.loc_seq_num) { | ||
1592 | nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n"); | ||
1593 | cleanup_retrans_entry(cm_node); | ||
1594 | send_reset(cm_node, skb); | ||
1595 | return; | ||
1596 | } | ||
1590 | cm_node->state = NES_CM_STATE_ESTABLISHED; | 1597 | cm_node->state = NES_CM_STATE_ESTABLISHED; |
1591 | if (datasize) { | 1598 | if (datasize) { |
1592 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1599 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
@@ -1618,11 +1625,15 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1618 | dev_kfree_skb_any(skb); | 1625 | dev_kfree_skb_any(skb); |
1619 | } | 1626 | } |
1620 | break; | 1627 | break; |
1628 | case NES_CM_STATE_LISTENING: | ||
1629 | case NES_CM_STATE_CLOSED: | ||
1630 | cleanup_retrans_entry(cm_node); | ||
1631 | send_reset(cm_node, skb); | ||
1632 | break; | ||
1621 | case NES_CM_STATE_FIN_WAIT1: | 1633 | case NES_CM_STATE_FIN_WAIT1: |
1622 | case NES_CM_STATE_SYN_SENT: | 1634 | case NES_CM_STATE_SYN_SENT: |
1623 | case NES_CM_STATE_FIN_WAIT2: | 1635 | case NES_CM_STATE_FIN_WAIT2: |
1624 | case NES_CM_STATE_TSA: | 1636 | case NES_CM_STATE_TSA: |
1625 | case NES_CM_STATE_CLOSED: | ||
1626 | case NES_CM_STATE_MPAREQ_RCVD: | 1637 | case NES_CM_STATE_MPAREQ_RCVD: |
1627 | case NES_CM_STATE_LAST_ACK: | 1638 | case NES_CM_STATE_LAST_ACK: |
1628 | case NES_CM_STATE_CLOSING: | 1639 | case NES_CM_STATE_CLOSING: |
@@ -1645,9 +1656,9 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | |||
1645 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", | 1656 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", |
1646 | __func__, cm_node); | 1657 | __func__, cm_node); |
1647 | if (passive) | 1658 | if (passive) |
1648 | passive_open_err(cm_node, skb, 0); | 1659 | passive_open_err(cm_node, skb, 1); |
1649 | else | 1660 | else |
1650 | active_open_err(cm_node, skb, 0); | 1661 | active_open_err(cm_node, skb, 1); |
1651 | return 1; | 1662 | return 1; |
1652 | } | 1663 | } |
1653 | } | 1664 | } |
@@ -1967,6 +1978,7 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
1967 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) | 1978 | struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node) |
1968 | { | 1979 | { |
1969 | int ret = 0; | 1980 | int ret = 0; |
1981 | int passive_state; | ||
1970 | 1982 | ||
1971 | nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", | 1983 | nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n", |
1972 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); | 1984 | __func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state); |
@@ -1974,9 +1986,13 @@ static int mini_cm_reject(struct nes_cm_core *cm_core, | |||
1974 | if (cm_node->tcp_cntxt.client) | 1986 | if (cm_node->tcp_cntxt.client) |
1975 | return ret; | 1987 | return ret; |
1976 | cleanup_retrans_entry(cm_node); | 1988 | cleanup_retrans_entry(cm_node); |
1977 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1978 | 1989 | ||
1979 | ret = send_reset(cm_node, NULL); | 1990 | passive_state = atomic_add_return(1, &cm_node->passive_state); |
1991 | cm_node->state = NES_CM_STATE_CLOSED; | ||
1992 | if (passive_state == NES_SEND_RESET_EVENT) | ||
1993 | rem_ref_cm_node(cm_core, cm_node); | ||
1994 | else | ||
1995 | ret = send_reset(cm_node, NULL); | ||
1980 | return ret; | 1996 | return ret; |
1981 | } | 1997 | } |
1982 | 1998 | ||
@@ -2034,7 +2050,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
2034 | * recv_pkt - recv an ETHERNET packet, and process it through CM | 2050 | * recv_pkt - recv an ETHERNET packet, and process it through CM |
2035 | * node state machine | 2051 | * node state machine |
2036 | */ | 2052 | */ |
2037 | static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | 2053 | static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, |
2038 | struct nes_vnic *nesvnic, struct sk_buff *skb) | 2054 | struct nes_vnic *nesvnic, struct sk_buff *skb) |
2039 | { | 2055 | { |
2040 | struct nes_cm_node *cm_node = NULL; | 2056 | struct nes_cm_node *cm_node = NULL; |
@@ -2042,23 +2058,16 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2042 | struct iphdr *iph; | 2058 | struct iphdr *iph; |
2043 | struct tcphdr *tcph; | 2059 | struct tcphdr *tcph; |
2044 | struct nes_cm_info nfo; | 2060 | struct nes_cm_info nfo; |
2061 | int skb_handled = 1; | ||
2045 | 2062 | ||
2046 | if (!skb) | 2063 | if (!skb) |
2047 | return; | 2064 | return 0; |
2048 | if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { | 2065 | if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { |
2049 | dev_kfree_skb_any(skb); | 2066 | return 0; |
2050 | return; | ||
2051 | } | 2067 | } |
2052 | 2068 | ||
2053 | iph = (struct iphdr *)skb->data; | 2069 | iph = (struct iphdr *)skb->data; |
2054 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); | 2070 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); |
2055 | skb_reset_network_header(skb); | ||
2056 | skb_set_transport_header(skb, sizeof(*tcph)); | ||
2057 | if (!tcph) { | ||
2058 | dev_kfree_skb_any(skb); | ||
2059 | return; | ||
2060 | } | ||
2061 | skb->len = ntohs(iph->tot_len); | ||
2062 | 2071 | ||
2063 | nfo.loc_addr = ntohl(iph->daddr); | 2072 | nfo.loc_addr = ntohl(iph->daddr); |
2064 | nfo.loc_port = ntohs(tcph->dest); | 2073 | nfo.loc_port = ntohs(tcph->dest); |
@@ -2077,23 +2086,21 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2077 | /* Only type of packet accepted are for */ | 2086 | /* Only type of packet accepted are for */ |
2078 | /* the PASSIVE open (syn only) */ | 2087 | /* the PASSIVE open (syn only) */ |
2079 | if ((!tcph->syn) || (tcph->ack)) { | 2088 | if ((!tcph->syn) || (tcph->ack)) { |
2080 | cm_packets_dropped++; | 2089 | skb_handled = 0; |
2081 | break; | 2090 | break; |
2082 | } | 2091 | } |
2083 | listener = find_listener(cm_core, nfo.loc_addr, | 2092 | listener = find_listener(cm_core, nfo.loc_addr, |
2084 | nfo.loc_port, | 2093 | nfo.loc_port, |
2085 | NES_CM_LISTENER_ACTIVE_STATE); | 2094 | NES_CM_LISTENER_ACTIVE_STATE); |
2086 | if (listener) { | 2095 | if (!listener) { |
2087 | nfo.cm_id = listener->cm_id; | 2096 | nfo.cm_id = NULL; |
2088 | nfo.conn_type = listener->conn_type; | 2097 | nfo.conn_type = 0; |
2089 | } else { | 2098 | nes_debug(NES_DBG_CM, "Unable to find listener for the pkt\n"); |
2090 | nes_debug(NES_DBG_CM, "Unable to find listener " | 2099 | skb_handled = 0; |
2091 | "for the pkt\n"); | ||
2092 | cm_packets_dropped++; | ||
2093 | dev_kfree_skb_any(skb); | ||
2094 | break; | 2100 | break; |
2095 | } | 2101 | } |
2096 | 2102 | nfo.cm_id = listener->cm_id; | |
2103 | nfo.conn_type = listener->conn_type; | ||
2097 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, | 2104 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, |
2098 | listener); | 2105 | listener); |
2099 | if (!cm_node) { | 2106 | if (!cm_node) { |
@@ -2119,9 +2126,13 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2119 | dev_kfree_skb_any(skb); | 2126 | dev_kfree_skb_any(skb); |
2120 | break; | 2127 | break; |
2121 | } | 2128 | } |
2129 | skb_reset_network_header(skb); | ||
2130 | skb_set_transport_header(skb, sizeof(*tcph)); | ||
2131 | skb->len = ntohs(iph->tot_len); | ||
2122 | process_packet(cm_node, skb, cm_core); | 2132 | process_packet(cm_node, skb, cm_core); |
2123 | rem_ref_cm_node(cm_core, cm_node); | 2133 | rem_ref_cm_node(cm_core, cm_node); |
2124 | } while (0); | 2134 | } while (0); |
2135 | return skb_handled; | ||
2125 | } | 2136 | } |
2126 | 2137 | ||
2127 | 2138 | ||
@@ -2130,10 +2141,7 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2130 | */ | 2141 | */ |
2131 | static struct nes_cm_core *nes_cm_alloc_core(void) | 2142 | static struct nes_cm_core *nes_cm_alloc_core(void) |
2132 | { | 2143 | { |
2133 | int i; | ||
2134 | |||
2135 | struct nes_cm_core *cm_core; | 2144 | struct nes_cm_core *cm_core; |
2136 | struct sk_buff *skb = NULL; | ||
2137 | 2145 | ||
2138 | /* setup the CM core */ | 2146 | /* setup the CM core */ |
2139 | /* alloc top level core control structure */ | 2147 | /* alloc top level core control structure */ |
@@ -2151,19 +2159,6 @@ static struct nes_cm_core *nes_cm_alloc_core(void) | |||
2151 | 2159 | ||
2152 | atomic_set(&cm_core->events_posted, 0); | 2160 | atomic_set(&cm_core->events_posted, 0); |
2153 | 2161 | ||
2154 | /* init the packet lists */ | ||
2155 | skb_queue_head_init(&cm_core->tx_free_list); | ||
2156 | |||
2157 | for (i = 0; i < NES_CM_DEFAULT_FRAME_CNT; i++) { | ||
2158 | skb = dev_alloc_skb(cm_core->mtu); | ||
2159 | if (!skb) { | ||
2160 | kfree(cm_core); | ||
2161 | return NULL; | ||
2162 | } | ||
2163 | /* add 'raw' skb to free frame list */ | ||
2164 | skb_queue_head(&cm_core->tx_free_list, skb); | ||
2165 | } | ||
2166 | |||
2167 | cm_core->api = &nes_cm_api; | 2162 | cm_core->api = &nes_cm_api; |
2168 | 2163 | ||
2169 | spin_lock_init(&cm_core->ht_lock); | 2164 | spin_lock_init(&cm_core->ht_lock); |
@@ -2392,7 +2387,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) | |||
2392 | atomic_inc(&cm_disconnects); | 2387 | atomic_inc(&cm_disconnects); |
2393 | cm_event.event = IW_CM_EVENT_DISCONNECT; | 2388 | cm_event.event = IW_CM_EVENT_DISCONNECT; |
2394 | if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { | 2389 | if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) { |
2395 | issued_disconnect_reset = 1; | ||
2396 | cm_event.status = IW_CM_EVENT_STATUS_RESET; | 2390 | cm_event.status = IW_CM_EVENT_STATUS_RESET; |
2397 | nes_debug(NES_DBG_CM, "Generating a CM " | 2391 | nes_debug(NES_DBG_CM, "Generating a CM " |
2398 | "Disconnect Event (status reset) for " | 2392 | "Disconnect Event (status reset) for " |
@@ -2542,6 +2536,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2542 | struct nes_v4_quad nes_quad; | 2536 | struct nes_v4_quad nes_quad; |
2543 | u32 crc_value; | 2537 | u32 crc_value; |
2544 | int ret; | 2538 | int ret; |
2539 | int passive_state; | ||
2545 | 2540 | ||
2546 | ibqp = nes_get_qp(cm_id->device, conn_param->qpn); | 2541 | ibqp = nes_get_qp(cm_id->device, conn_param->qpn); |
2547 | if (!ibqp) | 2542 | if (!ibqp) |
@@ -2709,8 +2704,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2709 | conn_param->private_data_len + | 2704 | conn_param->private_data_len + |
2710 | sizeof(struct ietf_mpa_frame)); | 2705 | sizeof(struct ietf_mpa_frame)); |
2711 | 2706 | ||
2712 | attr.qp_state = IB_QPS_RTS; | ||
2713 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); | ||
2714 | 2707 | ||
2715 | /* notify OF layer that accept event was successfull */ | 2708 | /* notify OF layer that accept event was successfull */ |
2716 | cm_id->add_ref(cm_id); | 2709 | cm_id->add_ref(cm_id); |
@@ -2723,6 +2716,8 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2723 | cm_event.private_data = NULL; | 2716 | cm_event.private_data = NULL; |
2724 | cm_event.private_data_len = 0; | 2717 | cm_event.private_data_len = 0; |
2725 | ret = cm_id->event_handler(cm_id, &cm_event); | 2718 | ret = cm_id->event_handler(cm_id, &cm_event); |
2719 | attr.qp_state = IB_QPS_RTS; | ||
2720 | nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL); | ||
2726 | if (cm_node->loopbackpartner) { | 2721 | if (cm_node->loopbackpartner) { |
2727 | cm_node->loopbackpartner->mpa_frame_size = | 2722 | cm_node->loopbackpartner->mpa_frame_size = |
2728 | nesqp->private_data_len; | 2723 | nesqp->private_data_len; |
@@ -2735,6 +2730,9 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
2735 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " | 2730 | printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " |
2736 | "ret=%d\n", __func__, __LINE__, ret); | 2731 | "ret=%d\n", __func__, __LINE__, ret); |
2737 | 2732 | ||
2733 | passive_state = atomic_add_return(1, &cm_node->passive_state); | ||
2734 | if (passive_state == NES_SEND_RESET_EVENT) | ||
2735 | create_event(cm_node, NES_CM_EVENT_RESET); | ||
2738 | return 0; | 2736 | return 0; |
2739 | } | 2737 | } |
2740 | 2738 | ||
@@ -2938,15 +2936,16 @@ int nes_destroy_listen(struct iw_cm_id *cm_id) | |||
2938 | */ | 2936 | */ |
2939 | int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice) | 2937 | int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice) |
2940 | { | 2938 | { |
2939 | int rc = 0; | ||
2941 | cm_packets_received++; | 2940 | cm_packets_received++; |
2942 | if ((g_cm_core) && (g_cm_core->api)) { | 2941 | if ((g_cm_core) && (g_cm_core->api)) { |
2943 | g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); | 2942 | rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); |
2944 | } else { | 2943 | } else { |
2945 | nes_debug(NES_DBG_CM, "Unable to process packet for CM," | 2944 | nes_debug(NES_DBG_CM, "Unable to process packet for CM," |
2946 | " cm is not setup properly.\n"); | 2945 | " cm is not setup properly.\n"); |
2947 | } | 2946 | } |
2948 | 2947 | ||
2949 | return 0; | 2948 | return rc; |
2950 | } | 2949 | } |
2951 | 2950 | ||
2952 | 2951 | ||
@@ -3217,6 +3216,18 @@ static void cm_event_reset(struct nes_cm_event *event) | |||
3217 | cm_event.private_data_len = 0; | 3216 | cm_event.private_data_len = 0; |
3218 | 3217 | ||
3219 | ret = cm_id->event_handler(cm_id, &cm_event); | 3218 | ret = cm_id->event_handler(cm_id, &cm_event); |
3219 | cm_id->add_ref(cm_id); | ||
3220 | atomic_inc(&cm_closes); | ||
3221 | cm_event.event = IW_CM_EVENT_CLOSE; | ||
3222 | cm_event.status = IW_CM_EVENT_STATUS_OK; | ||
3223 | cm_event.provider_data = cm_id->provider_data; | ||
3224 | cm_event.local_addr = cm_id->local_addr; | ||
3225 | cm_event.remote_addr = cm_id->remote_addr; | ||
3226 | cm_event.private_data = NULL; | ||
3227 | cm_event.private_data_len = 0; | ||
3228 | nes_debug(NES_DBG_CM, "NODE %p Generating CLOSE\n", event->cm_node); | ||
3229 | ret = cm_id->event_handler(cm_id, &cm_event); | ||
3230 | |||
3220 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); | 3231 | nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret); |
3221 | 3232 | ||
3222 | 3233 | ||
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 367b3d290140..fafa35042ebd 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
@@ -76,6 +76,10 @@ enum nes_timer_type { | |||
76 | NES_TIMER_TYPE_CLOSE, | 76 | NES_TIMER_TYPE_CLOSE, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | #define NES_PASSIVE_STATE_INDICATED 0 | ||
80 | #define NES_DO_NOT_SEND_RESET_EVENT 1 | ||
81 | #define NES_SEND_RESET_EVENT 2 | ||
82 | |||
79 | #define MAX_NES_IFS 4 | 83 | #define MAX_NES_IFS 4 |
80 | 84 | ||
81 | #define SET_ACK 1 | 85 | #define SET_ACK 1 |
@@ -161,6 +165,8 @@ struct nes_timer_entry { | |||
161 | 165 | ||
162 | #define NES_CM_DEF_SEQ2 0x18ed5740 | 166 | #define NES_CM_DEF_SEQ2 0x18ed5740 |
163 | #define NES_CM_DEF_LOCAL_ID2 0xb807 | 167 | #define NES_CM_DEF_LOCAL_ID2 0xb807 |
168 | #define MAX_CM_BUFFER 512 | ||
169 | |||
164 | 170 | ||
165 | typedef u32 nes_addr_t; | 171 | typedef u32 nes_addr_t; |
166 | 172 | ||
@@ -254,8 +260,6 @@ struct nes_cm_listener { | |||
254 | 260 | ||
255 | /* per connection node and node state information */ | 261 | /* per connection node and node state information */ |
256 | struct nes_cm_node { | 262 | struct nes_cm_node { |
257 | u32 hashkey; | ||
258 | |||
259 | nes_addr_t loc_addr, rem_addr; | 263 | nes_addr_t loc_addr, rem_addr; |
260 | u16 loc_port, rem_port; | 264 | u16 loc_port, rem_port; |
261 | 265 | ||
@@ -292,7 +296,10 @@ struct nes_cm_node { | |||
292 | int apbvt_set; | 296 | int apbvt_set; |
293 | int accept_pend; | 297 | int accept_pend; |
294 | int freed; | 298 | int freed; |
299 | struct list_head timer_entry; | ||
300 | struct list_head reset_entry; | ||
295 | struct nes_qp *nesqp; | 301 | struct nes_qp *nesqp; |
302 | atomic_t passive_state; | ||
296 | }; | 303 | }; |
297 | 304 | ||
298 | /* structure for client or CM to fill when making CM api calls. */ | 305 | /* structure for client or CM to fill when making CM api calls. */ |
@@ -350,7 +357,6 @@ struct nes_cm_core { | |||
350 | u32 mtu; | 357 | u32 mtu; |
351 | u32 free_tx_pkt_max; | 358 | u32 free_tx_pkt_max; |
352 | u32 rx_pkt_posted; | 359 | u32 rx_pkt_posted; |
353 | struct sk_buff_head tx_free_list; | ||
354 | atomic_t ht_node_cnt; | 360 | atomic_t ht_node_cnt; |
355 | struct list_head connected_nodes; | 361 | struct list_head connected_nodes; |
356 | /* struct list_head hashtable[NES_CM_HASHTABLE_SIZE]; */ | 362 | /* struct list_head hashtable[NES_CM_HASHTABLE_SIZE]; */ |
@@ -390,7 +396,7 @@ struct nes_cm_ops { | |||
390 | struct nes_cm_node *); | 396 | struct nes_cm_node *); |
391 | int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, | 397 | int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, |
392 | struct nes_cm_node *); | 398 | struct nes_cm_node *); |
393 | void (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, | 399 | int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, |
394 | struct sk_buff *); | 400 | struct sk_buff *); |
395 | int (*destroy_cm_core)(struct nes_cm_core *); | 401 | int (*destroy_cm_core)(struct nes_cm_core *); |
396 | int (*get)(struct nes_cm_core *); | 402 | int (*get)(struct nes_cm_core *); |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 735c125b48af..5d139db1b771 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -2700,27 +2700,33 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) | |||
2700 | pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */ | 2700 | pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */ |
2701 | 2701 | ||
2702 | if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) { | 2702 | if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) { |
2703 | nes_cm_recv(rx_skb, nesvnic->netdev); | 2703 | if (nes_cm_recv(rx_skb, nesvnic->netdev)) |
2704 | rx_skb = NULL; | ||
2705 | } | ||
2706 | if (rx_skb == NULL) | ||
2707 | goto skip_rx_indicate0; | ||
2708 | |||
2709 | |||
2710 | if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && | ||
2711 | (nesvnic->vlan_grp != NULL)) { | ||
2712 | vlan_tag = (u16)(le32_to_cpu( | ||
2713 | cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]) | ||
2714 | >> 16); | ||
2715 | nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", | ||
2716 | nesvnic->netdev->name, vlan_tag); | ||
2717 | if (nes_use_lro) | ||
2718 | lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb, | ||
2719 | nesvnic->vlan_grp, vlan_tag, NULL); | ||
2720 | else | ||
2721 | nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); | ||
2704 | } else { | 2722 | } else { |
2705 | if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && (nesvnic->vlan_grp != NULL)) { | 2723 | if (nes_use_lro) |
2706 | vlan_tag = (u16)(le32_to_cpu( | 2724 | lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL); |
2707 | cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]) | 2725 | else |
2708 | >> 16); | 2726 | nes_netif_rx(rx_skb); |
2709 | nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", | ||
2710 | nesvnic->netdev->name, vlan_tag); | ||
2711 | if (nes_use_lro) | ||
2712 | lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb, | ||
2713 | nesvnic->vlan_grp, vlan_tag, NULL); | ||
2714 | else | ||
2715 | nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); | ||
2716 | } else { | ||
2717 | if (nes_use_lro) | ||
2718 | lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL); | ||
2719 | else | ||
2720 | nes_netif_rx(rx_skb); | ||
2721 | } | ||
2722 | } | 2727 | } |
2723 | 2728 | ||
2729 | skip_rx_indicate0: | ||
2724 | nesvnic->netdev->last_rx = jiffies; | 2730 | nesvnic->netdev->last_rx = jiffies; |
2725 | /* nesvnic->netstats.rx_packets++; */ | 2731 | /* nesvnic->netstats.rx_packets++; */ |
2726 | /* nesvnic->netstats.rx_bytes += rx_pkt_size; */ | 2732 | /* nesvnic->netstats.rx_bytes += rx_pkt_size; */ |
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c index 9f16f7a89efc..aa9b7348c728 100644 --- a/drivers/infiniband/hw/nes/nes_utils.c +++ b/drivers/infiniband/hw/nes/nes_utils.c | |||
@@ -540,11 +540,14 @@ struct nes_cqp_request *nes_get_cqp_request(struct nes_device *nesdev) | |||
540 | 540 | ||
541 | if (!list_empty(&nesdev->cqp_avail_reqs)) { | 541 | if (!list_empty(&nesdev->cqp_avail_reqs)) { |
542 | spin_lock_irqsave(&nesdev->cqp.lock, flags); | 542 | spin_lock_irqsave(&nesdev->cqp.lock, flags); |
543 | cqp_request = list_entry(nesdev->cqp_avail_reqs.next, | 543 | if (!list_empty(&nesdev->cqp_avail_reqs)) { |
544 | cqp_request = list_entry(nesdev->cqp_avail_reqs.next, | ||
544 | struct nes_cqp_request, list); | 545 | struct nes_cqp_request, list); |
545 | list_del_init(&cqp_request->list); | 546 | list_del_init(&cqp_request->list); |
547 | } | ||
546 | spin_unlock_irqrestore(&nesdev->cqp.lock, flags); | 548 | spin_unlock_irqrestore(&nesdev->cqp.lock, flags); |
547 | } else { | 549 | } |
550 | if (cqp_request == NULL) { | ||
548 | cqp_request = kzalloc(sizeof(struct nes_cqp_request), GFP_KERNEL); | 551 | cqp_request = kzalloc(sizeof(struct nes_cqp_request), GFP_KERNEL); |
549 | if (cqp_request) { | 552 | if (cqp_request) { |
550 | cqp_request->dynamic = 1; | 553 | cqp_request->dynamic = 1; |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index d36c9a0bf1bb..4fdb72454f94 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
@@ -1695,13 +1695,8 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | |||
1695 | /* use 4k pbl */ | 1695 | /* use 4k pbl */ |
1696 | nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 4k PBL\n", pbl_entries); | 1696 | nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 4k PBL\n", pbl_entries); |
1697 | if (nesadapter->free_4kpbl == 0) { | 1697 | if (nesadapter->free_4kpbl == 0) { |
1698 | if (cqp_request->dynamic) { | 1698 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
1699 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 1699 | nes_free_cqp_request(nesdev, cqp_request); |
1700 | kfree(cqp_request); | ||
1701 | } else { | ||
1702 | list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); | ||
1703 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
1704 | } | ||
1705 | if (!context) | 1700 | if (!context) |
1706 | pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, | 1701 | pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, |
1707 | nescq->hw_cq.cq_pbase); | 1702 | nescq->hw_cq.cq_pbase); |
@@ -1717,13 +1712,8 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, | |||
1717 | /* use 256 byte pbl */ | 1712 | /* use 256 byte pbl */ |
1718 | nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 256 byte PBL\n", pbl_entries); | 1713 | nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 256 byte PBL\n", pbl_entries); |
1719 | if (nesadapter->free_256pbl == 0) { | 1714 | if (nesadapter->free_256pbl == 0) { |
1720 | if (cqp_request->dynamic) { | 1715 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
1721 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 1716 | nes_free_cqp_request(nesdev, cqp_request); |
1722 | kfree(cqp_request); | ||
1723 | } else { | ||
1724 | list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); | ||
1725 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
1726 | } | ||
1727 | if (!context) | 1717 | if (!context) |
1728 | pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, | 1718 | pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem, |
1729 | nescq->hw_cq.cq_pbase); | 1719 | nescq->hw_cq.cq_pbase); |
@@ -1928,13 +1918,8 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd, | |||
1928 | /* Two level PBL */ | 1918 | /* Two level PBL */ |
1929 | if ((pbl_count+1) > nesadapter->free_4kpbl) { | 1919 | if ((pbl_count+1) > nesadapter->free_4kpbl) { |
1930 | nes_debug(NES_DBG_MR, "Out of 4KB Pbls for two level request.\n"); | 1920 | nes_debug(NES_DBG_MR, "Out of 4KB Pbls for two level request.\n"); |
1931 | if (cqp_request->dynamic) { | 1921 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
1932 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 1922 | nes_free_cqp_request(nesdev, cqp_request); |
1933 | kfree(cqp_request); | ||
1934 | } else { | ||
1935 | list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); | ||
1936 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
1937 | } | ||
1938 | return -ENOMEM; | 1923 | return -ENOMEM; |
1939 | } else { | 1924 | } else { |
1940 | nesadapter->free_4kpbl -= pbl_count+1; | 1925 | nesadapter->free_4kpbl -= pbl_count+1; |
@@ -1942,13 +1927,8 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd, | |||
1942 | } else if (residual_page_count > 32) { | 1927 | } else if (residual_page_count > 32) { |
1943 | if (pbl_count > nesadapter->free_4kpbl) { | 1928 | if (pbl_count > nesadapter->free_4kpbl) { |
1944 | nes_debug(NES_DBG_MR, "Out of 4KB Pbls.\n"); | 1929 | nes_debug(NES_DBG_MR, "Out of 4KB Pbls.\n"); |
1945 | if (cqp_request->dynamic) { | 1930 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
1946 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 1931 | nes_free_cqp_request(nesdev, cqp_request); |
1947 | kfree(cqp_request); | ||
1948 | } else { | ||
1949 | list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); | ||
1950 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
1951 | } | ||
1952 | return -ENOMEM; | 1932 | return -ENOMEM; |
1953 | } else { | 1933 | } else { |
1954 | nesadapter->free_4kpbl -= pbl_count; | 1934 | nesadapter->free_4kpbl -= pbl_count; |
@@ -1956,13 +1936,8 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd, | |||
1956 | } else { | 1936 | } else { |
1957 | if (pbl_count > nesadapter->free_256pbl) { | 1937 | if (pbl_count > nesadapter->free_256pbl) { |
1958 | nes_debug(NES_DBG_MR, "Out of 256B Pbls.\n"); | 1938 | nes_debug(NES_DBG_MR, "Out of 256B Pbls.\n"); |
1959 | if (cqp_request->dynamic) { | 1939 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); |
1960 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | 1940 | nes_free_cqp_request(nesdev, cqp_request); |
1961 | kfree(cqp_request); | ||
1962 | } else { | ||
1963 | list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs); | ||
1964 | spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); | ||
1965 | } | ||
1966 | return -ENOMEM; | 1941 | return -ENOMEM; |
1967 | } else { | 1942 | } else { |
1968 | nesadapter->free_256pbl -= pbl_count; | 1943 | nesadapter->free_256pbl -= pbl_count; |