| .. | .. |
|---|
| 51 | 51 | */ |
|---|
| 52 | 52 | |
|---|
| 53 | 53 | #include <linux/module.h> |
|---|
| 54 | +#include <linux/xarray.h> |
|---|
| 54 | 55 | #include <rdma/ib_addr.h> |
|---|
| 55 | 56 | #include <rdma/ib_verbs.h> |
|---|
| 56 | 57 | #include <rdma/opa_smi.h> |
|---|
| .. | .. |
|---|
| 58 | 59 | |
|---|
| 59 | 60 | #include "opa_vnic_internal.h" |
|---|
| 60 | 61 | |
|---|
| 61 | | -#define DRV_VERSION "1.0" |
|---|
| 62 | 62 | char opa_vnic_driver_name[] = "opa_vnic"; |
|---|
| 63 | | -const char opa_vnic_driver_version[] = DRV_VERSION; |
|---|
| 64 | 63 | |
|---|
| 65 | 64 | /* |
|---|
| 66 | 65 | * The trap service level is kept in bits 3 to 7 in the trap_sl_rsvd |
|---|
| .. | .. |
|---|
| 97 | 96 | * @class_port_info: Class port info information. |
|---|
| 98 | 97 | * @tid: Transaction id |
|---|
| 99 | 98 | * @port_num: OPA port number |
|---|
| 100 | | - * @vport_idr: vnic ports idr |
|---|
| 99 | + * @vports: vnic ports |
|---|
| 101 | 100 | * @event_handler: ib event handler |
|---|
| 102 | 101 | * @lock: adapter interface lock |
|---|
| 103 | 102 | */ |
|---|
| .. | .. |
|---|
| 107 | 106 | struct opa_class_port_info class_port_info; |
|---|
| 108 | 107 | u64 tid; |
|---|
| 109 | 108 | u8 port_num; |
|---|
| 110 | | - struct idr vport_idr; |
|---|
| 109 | + struct xarray vports; |
|---|
| 111 | 110 | struct ib_event_handler event_handler; |
|---|
| 112 | 111 | |
|---|
| 113 | 112 | /* Lock to query/update network adapter */ |
|---|
| 114 | 113 | struct mutex lock; |
|---|
| 115 | 114 | }; |
|---|
| 116 | 115 | |
|---|
| 117 | | -static void opa_vnic_vema_add_one(struct ib_device *device); |
|---|
| 116 | +static int opa_vnic_vema_add_one(struct ib_device *device); |
|---|
| 118 | 117 | static void opa_vnic_vema_rem_one(struct ib_device *device, |
|---|
| 119 | 118 | void *client_data); |
|---|
| 120 | 119 | |
|---|
| .. | .. |
|---|
| 148 | 147 | { |
|---|
| 149 | 148 | u8 vport_num = vema_get_vport_num(recvd_mad); |
|---|
| 150 | 149 | |
|---|
| 151 | | - return idr_find(&port->vport_idr, vport_num); |
|---|
| 150 | + return xa_load(&port->vports, vport_num); |
|---|
| 152 | 151 | } |
|---|
| 153 | 152 | |
|---|
| 154 | 153 | /** |
|---|
| .. | .. |
|---|
| 207 | 206 | int rc; |
|---|
| 208 | 207 | |
|---|
| 209 | 208 | adapter->cport = cport; |
|---|
| 210 | | - rc = idr_alloc(&port->vport_idr, adapter, vport_num, |
|---|
| 211 | | - vport_num + 1, GFP_NOWAIT); |
|---|
| 209 | + rc = xa_insert(&port->vports, vport_num, adapter, GFP_KERNEL); |
|---|
| 212 | 210 | if (rc < 0) { |
|---|
| 213 | 211 | opa_vnic_rem_netdev(adapter); |
|---|
| 214 | 212 | adapter = ERR_PTR(rc); |
|---|
| .. | .. |
|---|
| 549 | 547 | vema_get_mac_entries(port, recvd_mad, rsp_mad); |
|---|
| 550 | 548 | break; |
|---|
| 551 | 549 | case OPA_EM_ATTR_IFACE_UCAST_MACS: |
|---|
| 552 | | - /* fall through */ |
|---|
| 553 | 550 | case OPA_EM_ATTR_IFACE_MCAST_MACS: |
|---|
| 554 | 551 | vema_get_mac_list(port, recvd_mad, rsp_mad, attr_id); |
|---|
| 555 | 552 | break; |
|---|
| .. | .. |
|---|
| 606 | 603 | static void vema_send(struct ib_mad_agent *mad_agent, |
|---|
| 607 | 604 | struct ib_mad_send_wc *mad_wc) |
|---|
| 608 | 605 | { |
|---|
| 609 | | - rdma_destroy_ah(mad_wc->send_buf->ah); |
|---|
| 606 | + rdma_destroy_ah(mad_wc->send_buf->ah, RDMA_DESTROY_AH_SLEEPABLE); |
|---|
| 610 | 607 | ib_free_send_mad(mad_wc->send_buf); |
|---|
| 611 | 608 | } |
|---|
| 612 | 609 | |
|---|
| .. | .. |
|---|
| 680 | 677 | ib_free_send_mad(rsp); |
|---|
| 681 | 678 | |
|---|
| 682 | 679 | err_rsp: |
|---|
| 683 | | - rdma_destroy_ah(ah); |
|---|
| 680 | + rdma_destroy_ah(ah, RDMA_DESTROY_AH_SLEEPABLE); |
|---|
| 684 | 681 | free_recv_mad: |
|---|
| 685 | 682 | ib_free_recv_mad(mad_wc); |
|---|
| 686 | 683 | } |
|---|
| .. | .. |
|---|
| 777 | 774 | } |
|---|
| 778 | 775 | |
|---|
| 779 | 776 | rdma_ah_set_dlid(&ah_attr, trap_lid); |
|---|
| 780 | | - ah = rdma_create_ah(port->mad_agent->qp->pd, &ah_attr); |
|---|
| 777 | + ah = rdma_create_ah(port->mad_agent->qp->pd, &ah_attr, 0); |
|---|
| 781 | 778 | if (IS_ERR(ah)) { |
|---|
| 782 | 779 | c_err("%s:Couldn't create new AH = %p\n", __func__, ah); |
|---|
| 783 | 780 | c_err("%s:dlid = %d, sl = %d, port = %d\n", __func__, |
|---|
| .. | .. |
|---|
| 848 | 845 | } |
|---|
| 849 | 846 | |
|---|
| 850 | 847 | err_sndbuf: |
|---|
| 851 | | - rdma_destroy_ah(ah); |
|---|
| 848 | + rdma_destroy_ah(ah, 0); |
|---|
| 852 | 849 | err_exit: |
|---|
| 853 | 850 | v_err("Aborting trap\n"); |
|---|
| 854 | | -} |
|---|
| 855 | | - |
|---|
| 856 | | -static int vema_rem_vport(int id, void *p, void *data) |
|---|
| 857 | | -{ |
|---|
| 858 | | - struct opa_vnic_adapter *adapter = p; |
|---|
| 859 | | - |
|---|
| 860 | | - opa_vnic_rem_netdev(adapter); |
|---|
| 861 | | - return 0; |
|---|
| 862 | | -} |
|---|
| 863 | | - |
|---|
| 864 | | -static int vema_enable_vport(int id, void *p, void *data) |
|---|
| 865 | | -{ |
|---|
| 866 | | - struct opa_vnic_adapter *adapter = p; |
|---|
| 867 | | - |
|---|
| 868 | | - netif_carrier_on(adapter->netdev); |
|---|
| 869 | | - return 0; |
|---|
| 870 | | -} |
|---|
| 871 | | - |
|---|
| 872 | | -static int vema_disable_vport(int id, void *p, void *data) |
|---|
| 873 | | -{ |
|---|
| 874 | | - struct opa_vnic_adapter *adapter = p; |
|---|
| 875 | | - |
|---|
| 876 | | - netif_carrier_off(adapter->netdev); |
|---|
| 877 | | - return 0; |
|---|
| 878 | 851 | } |
|---|
| 879 | 852 | |
|---|
| 880 | 853 | static void opa_vnic_event(struct ib_event_handler *handler, |
|---|
| .. | .. |
|---|
| 883 | 856 | struct opa_vnic_vema_port *port = |
|---|
| 884 | 857 | container_of(handler, struct opa_vnic_vema_port, event_handler); |
|---|
| 885 | 858 | struct opa_vnic_ctrl_port *cport = port->cport; |
|---|
| 859 | + struct opa_vnic_adapter *adapter; |
|---|
| 860 | + unsigned long index; |
|---|
| 886 | 861 | |
|---|
| 887 | 862 | if (record->element.port_num != port->port_num) |
|---|
| 888 | 863 | return; |
|---|
| 889 | 864 | |
|---|
| 890 | 865 | c_dbg("OPA_VNIC received event %d on device %s port %d\n", |
|---|
| 891 | | - record->event, record->device->name, record->element.port_num); |
|---|
| 866 | + record->event, dev_name(&record->device->dev), |
|---|
| 867 | + record->element.port_num); |
|---|
| 892 | 868 | |
|---|
| 893 | | - if (record->event == IB_EVENT_PORT_ERR) |
|---|
| 894 | | - idr_for_each(&port->vport_idr, vema_disable_vport, NULL); |
|---|
| 895 | | - if (record->event == IB_EVENT_PORT_ACTIVE) |
|---|
| 896 | | - idr_for_each(&port->vport_idr, vema_enable_vport, NULL); |
|---|
| 869 | + if (record->event != IB_EVENT_PORT_ERR && |
|---|
| 870 | + record->event != IB_EVENT_PORT_ACTIVE) |
|---|
| 871 | + return; |
|---|
| 872 | + |
|---|
| 873 | + xa_for_each(&port->vports, index, adapter) { |
|---|
| 874 | + if (record->event == IB_EVENT_PORT_ACTIVE) |
|---|
| 875 | + netif_carrier_on(adapter->netdev); |
|---|
| 876 | + else |
|---|
| 877 | + netif_carrier_off(adapter->netdev); |
|---|
| 878 | + } |
|---|
| 897 | 879 | } |
|---|
| 898 | 880 | |
|---|
| 899 | 881 | /** |
|---|
| .. | .. |
|---|
| 904 | 886 | */ |
|---|
| 905 | 887 | static void vema_unregister(struct opa_vnic_ctrl_port *cport) |
|---|
| 906 | 888 | { |
|---|
| 889 | + struct opa_vnic_adapter *adapter; |
|---|
| 890 | + unsigned long index; |
|---|
| 907 | 891 | int i; |
|---|
| 908 | 892 | |
|---|
| 909 | 893 | for (i = 1; i <= cport->num_ports; i++) { |
|---|
| .. | .. |
|---|
| 914 | 898 | |
|---|
| 915 | 899 | /* Lock ensures no MAD is being processed */ |
|---|
| 916 | 900 | mutex_lock(&port->lock); |
|---|
| 917 | | - idr_for_each(&port->vport_idr, vema_rem_vport, NULL); |
|---|
| 901 | + xa_for_each(&port->vports, index, adapter) |
|---|
| 902 | + opa_vnic_rem_netdev(adapter); |
|---|
| 918 | 903 | mutex_unlock(&port->lock); |
|---|
| 919 | 904 | |
|---|
| 920 | 905 | ib_unregister_mad_agent(port->mad_agent); |
|---|
| 921 | 906 | port->mad_agent = NULL; |
|---|
| 922 | 907 | mutex_destroy(&port->lock); |
|---|
| 923 | | - idr_destroy(&port->vport_idr); |
|---|
| 908 | + xa_destroy(&port->vports); |
|---|
| 924 | 909 | ib_unregister_event_handler(&port->event_handler); |
|---|
| 925 | 910 | } |
|---|
| 926 | 911 | } |
|---|
| .. | .. |
|---|
| 957 | 942 | cport->ibdev, opa_vnic_event); |
|---|
| 958 | 943 | ib_register_event_handler(&port->event_handler); |
|---|
| 959 | 944 | |
|---|
| 960 | | - idr_init(&port->vport_idr); |
|---|
| 945 | + xa_init(&port->vports); |
|---|
| 961 | 946 | mutex_init(&port->lock); |
|---|
| 962 | 947 | port->mad_agent = ib_register_mad_agent(cport->ibdev, i, |
|---|
| 963 | 948 | IB_QPT_GSI, ®_req, |
|---|
| .. | .. |
|---|
| 968 | 953 | ret = PTR_ERR(port->mad_agent); |
|---|
| 969 | 954 | port->mad_agent = NULL; |
|---|
| 970 | 955 | mutex_destroy(&port->lock); |
|---|
| 971 | | - idr_destroy(&port->vport_idr); |
|---|
| 972 | 956 | vema_unregister(cport); |
|---|
| 973 | 957 | return ret; |
|---|
| 974 | 958 | } |
|---|
| .. | .. |
|---|
| 1004 | 988 | * |
|---|
| 1005 | 989 | * Allocate the vnic control port and initialize it. |
|---|
| 1006 | 990 | */ |
|---|
| 1007 | | -static void opa_vnic_vema_add_one(struct ib_device *device) |
|---|
| 991 | +static int opa_vnic_vema_add_one(struct ib_device *device) |
|---|
| 1008 | 992 | { |
|---|
| 1009 | 993 | struct opa_vnic_ctrl_port *cport; |
|---|
| 1010 | 994 | int rc, size = sizeof(*cport); |
|---|
| 1011 | 995 | |
|---|
| 1012 | 996 | if (!rdma_cap_opa_vnic(device)) |
|---|
| 1013 | | - return; |
|---|
| 997 | + return -EOPNOTSUPP; |
|---|
| 1014 | 998 | |
|---|
| 1015 | 999 | size += device->phys_port_cnt * sizeof(struct opa_vnic_vema_port); |
|---|
| 1016 | 1000 | cport = kzalloc(size, GFP_KERNEL); |
|---|
| 1017 | 1001 | if (!cport) |
|---|
| 1018 | | - return; |
|---|
| 1002 | + return -ENOMEM; |
|---|
| 1019 | 1003 | |
|---|
| 1020 | 1004 | cport->num_ports = device->phys_port_cnt; |
|---|
| 1021 | 1005 | cport->ibdev = device; |
|---|
| .. | .. |
|---|
| 1027 | 1011 | |
|---|
| 1028 | 1012 | ib_set_client_data(device, &opa_vnic_client, cport); |
|---|
| 1029 | 1013 | opa_vnic_ctrl_config_dev(cport, true); |
|---|
| 1014 | + return 0; |
|---|
| 1030 | 1015 | } |
|---|
| 1031 | 1016 | |
|---|
| 1032 | 1017 | /** |
|---|
| .. | .. |
|---|
| 1041 | 1026 | { |
|---|
| 1042 | 1027 | struct opa_vnic_ctrl_port *cport = client_data; |
|---|
| 1043 | 1028 | |
|---|
| 1044 | | - if (!cport) |
|---|
| 1045 | | - return; |
|---|
| 1046 | | - |
|---|
| 1047 | 1029 | c_info("removing VNIC client\n"); |
|---|
| 1048 | 1030 | opa_vnic_ctrl_config_dev(cport, false); |
|---|
| 1049 | 1031 | vema_unregister(cport); |
|---|
| .. | .. |
|---|
| 1053 | 1035 | static int __init opa_vnic_init(void) |
|---|
| 1054 | 1036 | { |
|---|
| 1055 | 1037 | int rc; |
|---|
| 1056 | | - |
|---|
| 1057 | | - pr_info("OPA Virtual Network Driver - v%s\n", |
|---|
| 1058 | | - opa_vnic_driver_version); |
|---|
| 1059 | 1038 | |
|---|
| 1060 | 1039 | rc = ib_register_client(&opa_vnic_client); |
|---|
| 1061 | 1040 | if (rc) |
|---|