diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 15:56:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 15:56:07 -0400 |
commit | 5c402355adf8f920531f02099f4ec0d2bccd4c64 (patch) | |
tree | eba326f8df01efc0d384874839384040401f5b45 /drivers/infiniband/core | |
parent | ecc8b655b38a880b578146895e0e1e2d477ca2c0 (diff) | |
parent | 2cc177364e4746becdf421f926fb967c047ccc32 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
MAINTAINERS: Remove Glenn Streiff from NetEffect entry
mlx4_core: Improve error message when not enough UAR pages are available
IB/mlx4: Add support for memory management extensions and local DMA L_Key
IB/mthca: Keep free count for MTT buddy allocator
mlx4_core: Keep free count for MTT buddy allocator
mlx4_code: Add missing FW status return code
IB/mlx4: Rename struct mlx4_lso_seg to mlx4_wqe_lso_seg
mlx4_core: Add module parameter to enable QoS support
RDMA/iwcm: Remove IB_ACCESS_LOCAL_WRITE from remote QP attributes
IPoIB: Include err code in trace message for ib_sa_path_rec_get() failures
IB/sa_query: Check if sm_ah is NULL in ib_sa_remove_one()
IB/ehca: Release mutex in error path of alloc_small_queue_page()
IB/ehca: Use default value for Local CA ACK Delay if FW returns 0
IB/ehca: Filter PATH_MIG events if QP was never armed
IB/iser: Add support for RDMA_CM_EVENT_ADDR_CHANGE event
RDMA/cma: Add RDMA_CM_EVENT_TIMEWAIT_EXIT event
RDMA/cma: Add RDMA_CM_EVENT_ADDR_CHANGE event
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r-- | drivers/infiniband/core/cma.c | 99 | ||||
-rw-r--r-- | drivers/infiniband/core/iwcm.c | 3 | ||||
-rw-r--r-- | drivers/infiniband/core/sa_query.c | 3 |
3 files changed, 101 insertions, 4 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index ae11d5cc74d0..e980ff3335db 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -168,6 +168,12 @@ struct cma_work { | |||
168 | struct rdma_cm_event event; | 168 | struct rdma_cm_event event; |
169 | }; | 169 | }; |
170 | 170 | ||
171 | struct cma_ndev_work { | ||
172 | struct work_struct work; | ||
173 | struct rdma_id_private *id; | ||
174 | struct rdma_cm_event event; | ||
175 | }; | ||
176 | |||
171 | union cma_ip_addr { | 177 | union cma_ip_addr { |
172 | struct in6_addr ip6; | 178 | struct in6_addr ip6; |
173 | struct { | 179 | struct { |
@@ -914,7 +920,10 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
914 | struct rdma_cm_event event; | 920 | struct rdma_cm_event event; |
915 | int ret = 0; | 921 | int ret = 0; |
916 | 922 | ||
917 | if (cma_disable_callback(id_priv, CMA_CONNECT)) | 923 | if ((ib_event->event != IB_CM_TIMEWAIT_EXIT && |
924 | cma_disable_callback(id_priv, CMA_CONNECT)) || | ||
925 | (ib_event->event == IB_CM_TIMEWAIT_EXIT && | ||
926 | cma_disable_callback(id_priv, CMA_DISCONNECT))) | ||
918 | return 0; | 927 | return 0; |
919 | 928 | ||
920 | memset(&event, 0, sizeof event); | 929 | memset(&event, 0, sizeof event); |
@@ -950,6 +959,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) | |||
950 | event.event = RDMA_CM_EVENT_DISCONNECTED; | 959 | event.event = RDMA_CM_EVENT_DISCONNECTED; |
951 | break; | 960 | break; |
952 | case IB_CM_TIMEWAIT_EXIT: | 961 | case IB_CM_TIMEWAIT_EXIT: |
962 | event.event = RDMA_CM_EVENT_TIMEWAIT_EXIT; | ||
963 | break; | ||
953 | case IB_CM_MRA_RECEIVED: | 964 | case IB_CM_MRA_RECEIVED: |
954 | /* ignore event */ | 965 | /* ignore event */ |
955 | goto out; | 966 | goto out; |
@@ -1598,6 +1609,30 @@ out: | |||
1598 | kfree(work); | 1609 | kfree(work); |
1599 | } | 1610 | } |
1600 | 1611 | ||
1612 | static void cma_ndev_work_handler(struct work_struct *_work) | ||
1613 | { | ||
1614 | struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work); | ||
1615 | struct rdma_id_private *id_priv = work->id; | ||
1616 | int destroy = 0; | ||
1617 | |||
1618 | mutex_lock(&id_priv->handler_mutex); | ||
1619 | if (id_priv->state == CMA_DESTROYING || | ||
1620 | id_priv->state == CMA_DEVICE_REMOVAL) | ||
1621 | goto out; | ||
1622 | |||
1623 | if (id_priv->id.event_handler(&id_priv->id, &work->event)) { | ||
1624 | cma_exch(id_priv, CMA_DESTROYING); | ||
1625 | destroy = 1; | ||
1626 | } | ||
1627 | |||
1628 | out: | ||
1629 | mutex_unlock(&id_priv->handler_mutex); | ||
1630 | cma_deref_id(id_priv); | ||
1631 | if (destroy) | ||
1632 | rdma_destroy_id(&id_priv->id); | ||
1633 | kfree(work); | ||
1634 | } | ||
1635 | |||
1601 | static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) | 1636 | static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) |
1602 | { | 1637 | { |
1603 | struct rdma_route *route = &id_priv->id.route; | 1638 | struct rdma_route *route = &id_priv->id.route; |
@@ -2723,6 +2758,65 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr) | |||
2723 | } | 2758 | } |
2724 | EXPORT_SYMBOL(rdma_leave_multicast); | 2759 | EXPORT_SYMBOL(rdma_leave_multicast); |
2725 | 2760 | ||
2761 | static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id_priv) | ||
2762 | { | ||
2763 | struct rdma_dev_addr *dev_addr; | ||
2764 | struct cma_ndev_work *work; | ||
2765 | |||
2766 | dev_addr = &id_priv->id.route.addr.dev_addr; | ||
2767 | |||
2768 | if ((dev_addr->src_dev == ndev) && | ||
2769 | memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) { | ||
2770 | printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n", | ||
2771 | ndev->name, &id_priv->id); | ||
2772 | work = kzalloc(sizeof *work, GFP_KERNEL); | ||
2773 | if (!work) | ||
2774 | return -ENOMEM; | ||
2775 | |||
2776 | INIT_WORK(&work->work, cma_ndev_work_handler); | ||
2777 | work->id = id_priv; | ||
2778 | work->event.event = RDMA_CM_EVENT_ADDR_CHANGE; | ||
2779 | atomic_inc(&id_priv->refcount); | ||
2780 | queue_work(cma_wq, &work->work); | ||
2781 | } | ||
2782 | |||
2783 | return 0; | ||
2784 | } | ||
2785 | |||
2786 | static int cma_netdev_callback(struct notifier_block *self, unsigned long event, | ||
2787 | void *ctx) | ||
2788 | { | ||
2789 | struct net_device *ndev = (struct net_device *)ctx; | ||
2790 | struct cma_device *cma_dev; | ||
2791 | struct rdma_id_private *id_priv; | ||
2792 | int ret = NOTIFY_DONE; | ||
2793 | |||
2794 | if (dev_net(ndev) != &init_net) | ||
2795 | return NOTIFY_DONE; | ||
2796 | |||
2797 | if (event != NETDEV_BONDING_FAILOVER) | ||
2798 | return NOTIFY_DONE; | ||
2799 | |||
2800 | if (!(ndev->flags & IFF_MASTER) || !(ndev->priv_flags & IFF_BONDING)) | ||
2801 | return NOTIFY_DONE; | ||
2802 | |||
2803 | mutex_lock(&lock); | ||
2804 | list_for_each_entry(cma_dev, &dev_list, list) | ||
2805 | list_for_each_entry(id_priv, &cma_dev->id_list, list) { | ||
2806 | ret = cma_netdev_change(ndev, id_priv); | ||
2807 | if (ret) | ||
2808 | goto out; | ||
2809 | } | ||
2810 | |||
2811 | out: | ||
2812 | mutex_unlock(&lock); | ||
2813 | return ret; | ||
2814 | } | ||
2815 | |||
2816 | static struct notifier_block cma_nb = { | ||
2817 | .notifier_call = cma_netdev_callback | ||
2818 | }; | ||
2819 | |||
2726 | static void cma_add_one(struct ib_device *device) | 2820 | static void cma_add_one(struct ib_device *device) |
2727 | { | 2821 | { |
2728 | struct cma_device *cma_dev; | 2822 | struct cma_device *cma_dev; |
@@ -2831,6 +2925,7 @@ static int cma_init(void) | |||
2831 | 2925 | ||
2832 | ib_sa_register_client(&sa_client); | 2926 | ib_sa_register_client(&sa_client); |
2833 | rdma_addr_register_client(&addr_client); | 2927 | rdma_addr_register_client(&addr_client); |
2928 | register_netdevice_notifier(&cma_nb); | ||
2834 | 2929 | ||
2835 | ret = ib_register_client(&cma_client); | 2930 | ret = ib_register_client(&cma_client); |
2836 | if (ret) | 2931 | if (ret) |
@@ -2838,6 +2933,7 @@ static int cma_init(void) | |||
2838 | return 0; | 2933 | return 0; |
2839 | 2934 | ||
2840 | err: | 2935 | err: |
2936 | unregister_netdevice_notifier(&cma_nb); | ||
2841 | rdma_addr_unregister_client(&addr_client); | 2937 | rdma_addr_unregister_client(&addr_client); |
2842 | ib_sa_unregister_client(&sa_client); | 2938 | ib_sa_unregister_client(&sa_client); |
2843 | destroy_workqueue(cma_wq); | 2939 | destroy_workqueue(cma_wq); |
@@ -2847,6 +2943,7 @@ err: | |||
2847 | static void cma_cleanup(void) | 2943 | static void cma_cleanup(void) |
2848 | { | 2944 | { |
2849 | ib_unregister_client(&cma_client); | 2945 | ib_unregister_client(&cma_client); |
2946 | unregister_netdevice_notifier(&cma_nb); | ||
2850 | rdma_addr_unregister_client(&addr_client); | 2947 | rdma_addr_unregister_client(&addr_client); |
2851 | ib_sa_unregister_client(&sa_client); | 2948 | ib_sa_unregister_client(&sa_client); |
2852 | destroy_workqueue(cma_wq); | 2949 | destroy_workqueue(cma_wq); |
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 81c9195b512a..8f9509e1ebf7 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c | |||
@@ -942,8 +942,7 @@ static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv, | |||
942 | case IW_CM_STATE_CONN_RECV: | 942 | case IW_CM_STATE_CONN_RECV: |
943 | case IW_CM_STATE_ESTABLISHED: | 943 | case IW_CM_STATE_ESTABLISHED: |
944 | *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS; | 944 | *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS; |
945 | qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | | 945 | qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE| |
946 | IB_ACCESS_REMOTE_WRITE| | ||
947 | IB_ACCESS_REMOTE_READ; | 946 | IB_ACCESS_REMOTE_READ; |
948 | ret = 0; | 947 | ret = 0; |
949 | break; | 948 | break; |
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 1341de793e51..7863a50d56f2 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -1064,7 +1064,8 @@ static void ib_sa_remove_one(struct ib_device *device) | |||
1064 | 1064 | ||
1065 | for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) { | 1065 | for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) { |
1066 | ib_unregister_mad_agent(sa_dev->port[i].agent); | 1066 | ib_unregister_mad_agent(sa_dev->port[i].agent); |
1067 | kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah); | 1067 | if (sa_dev->port[i].sm_ah) |
1068 | kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah); | ||
1068 | } | 1069 | } |
1069 | 1070 | ||
1070 | kfree(sa_dev); | 1071 | kfree(sa_dev); |