Merge branches 'clk-range', 'clk-uniphier', 'clk-apple' and 'clk-qcom' into clk-next
[linux-2.6-microblaze.git] / drivers / infiniband / hw / hfi1 / ipoib_main.c
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /*
3  * Copyright(c) 2020 Intel Corporation.
4  *
5  */
6
7 /*
8  * This file contains HFI1 support for ipoib functionality
9  */
10
11 #include "ipoib.h"
12 #include "hfi.h"
13
14 static u32 qpn_from_mac(const u8 *mac_arr)
15 {
16         return (u32)mac_arr[1] << 16 | mac_arr[2] << 8 | mac_arr[3];
17 }
18
19 static int hfi1_ipoib_dev_init(struct net_device *dev)
20 {
21         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
22         int ret;
23
24         dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
25         if (!dev->tstats)
26                 return -ENOMEM;
27
28         ret = priv->netdev_ops->ndo_init(dev);
29         if (ret)
30                 goto out_ret;
31
32         ret = hfi1_netdev_add_data(priv->dd,
33                                    qpn_from_mac(priv->netdev->dev_addr),
34                                    dev);
35         if (ret < 0) {
36                 priv->netdev_ops->ndo_uninit(dev);
37                 goto out_ret;
38         }
39
40         return 0;
41 out_ret:
42         free_percpu(dev->tstats);
43         dev->tstats = NULL;
44         return ret;
45 }
46
47 static void hfi1_ipoib_dev_uninit(struct net_device *dev)
48 {
49         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
50
51         free_percpu(dev->tstats);
52         dev->tstats = NULL;
53
54         hfi1_netdev_remove_data(priv->dd, qpn_from_mac(priv->netdev->dev_addr));
55
56         priv->netdev_ops->ndo_uninit(dev);
57 }
58
59 static int hfi1_ipoib_dev_open(struct net_device *dev)
60 {
61         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
62         int ret;
63
64         ret = priv->netdev_ops->ndo_open(dev);
65         if (!ret) {
66                 struct hfi1_ibport *ibp = to_iport(priv->device,
67                                                    priv->port_num);
68                 struct rvt_qp *qp;
69                 u32 qpn = qpn_from_mac(priv->netdev->dev_addr);
70
71                 rcu_read_lock();
72                 qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
73                 if (!qp) {
74                         rcu_read_unlock();
75                         priv->netdev_ops->ndo_stop(dev);
76                         return -EINVAL;
77                 }
78                 rvt_get_qp(qp);
79                 priv->qp = qp;
80                 rcu_read_unlock();
81
82                 hfi1_netdev_enable_queues(priv->dd);
83                 hfi1_ipoib_napi_tx_enable(dev);
84         }
85
86         return ret;
87 }
88
89 static int hfi1_ipoib_dev_stop(struct net_device *dev)
90 {
91         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
92
93         if (!priv->qp)
94                 return 0;
95
96         hfi1_ipoib_napi_tx_disable(dev);
97         hfi1_netdev_disable_queues(priv->dd);
98
99         rvt_put_qp(priv->qp);
100         priv->qp = NULL;
101
102         return priv->netdev_ops->ndo_stop(dev);
103 }
104
105 static const struct net_device_ops hfi1_ipoib_netdev_ops = {
106         .ndo_init         = hfi1_ipoib_dev_init,
107         .ndo_uninit       = hfi1_ipoib_dev_uninit,
108         .ndo_open         = hfi1_ipoib_dev_open,
109         .ndo_stop         = hfi1_ipoib_dev_stop,
110         .ndo_get_stats64  = dev_get_tstats64,
111 };
112
113 static int hfi1_ipoib_mcast_attach(struct net_device *dev,
114                                    struct ib_device *device,
115                                    union ib_gid *mgid,
116                                    u16 mlid,
117                                    int set_qkey,
118                                    u32 qkey)
119 {
120         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
121         u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
122         struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
123         struct rvt_qp *qp;
124         int ret = -EINVAL;
125
126         rcu_read_lock();
127
128         qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
129         if (qp) {
130                 rvt_get_qp(qp);
131                 rcu_read_unlock();
132                 if (set_qkey)
133                         priv->qkey = qkey;
134
135                 /* attach QP to multicast group */
136                 ret = ib_attach_mcast(&qp->ibqp, mgid, mlid);
137                 rvt_put_qp(qp);
138         } else {
139                 rcu_read_unlock();
140         }
141
142         return ret;
143 }
144
145 static int hfi1_ipoib_mcast_detach(struct net_device *dev,
146                                    struct ib_device *device,
147                                    union ib_gid *mgid,
148                                    u16 mlid)
149 {
150         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
151         u32 qpn = (u32)qpn_from_mac(priv->netdev->dev_addr);
152         struct hfi1_ibport *ibp = to_iport(priv->device, priv->port_num);
153         struct rvt_qp *qp;
154         int ret = -EINVAL;
155
156         rcu_read_lock();
157
158         qp = rvt_lookup_qpn(ib_to_rvt(priv->device), &ibp->rvp, qpn);
159         if (qp) {
160                 rvt_get_qp(qp);
161                 rcu_read_unlock();
162                 ret = ib_detach_mcast(&qp->ibqp, mgid, mlid);
163                 rvt_put_qp(qp);
164         } else {
165                 rcu_read_unlock();
166         }
167         return ret;
168 }
169
170 static void hfi1_ipoib_netdev_dtor(struct net_device *dev)
171 {
172         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
173
174         hfi1_ipoib_txreq_deinit(priv);
175         hfi1_ipoib_rxq_deinit(priv->netdev);
176
177         free_percpu(dev->tstats);
178         dev->tstats = NULL;
179 }
180
181 static void hfi1_ipoib_set_id(struct net_device *dev, int id)
182 {
183         struct hfi1_ipoib_dev_priv *priv = hfi1_ipoib_priv(dev);
184
185         priv->pkey_index = (u16)id;
186         ib_query_pkey(priv->device,
187                       priv->port_num,
188                       priv->pkey_index,
189                       &priv->pkey);
190 }
191
192 static int hfi1_ipoib_setup_rn(struct ib_device *device,
193                                u32 port_num,
194                                struct net_device *netdev,
195                                void *param)
196 {
197         struct hfi1_devdata *dd = dd_from_ibdev(device);
198         struct rdma_netdev *rn = netdev_priv(netdev);
199         struct hfi1_ipoib_dev_priv *priv;
200         int rc;
201
202         rn->send = hfi1_ipoib_send;
203         rn->tx_timeout = hfi1_ipoib_tx_timeout;
204         rn->attach_mcast = hfi1_ipoib_mcast_attach;
205         rn->detach_mcast = hfi1_ipoib_mcast_detach;
206         rn->set_id = hfi1_ipoib_set_id;
207         rn->hca = device;
208         rn->port_num = port_num;
209         rn->mtu = netdev->mtu;
210
211         priv = hfi1_ipoib_priv(netdev);
212         priv->dd = dd;
213         priv->netdev = netdev;
214         priv->device = device;
215         priv->port_num = port_num;
216         priv->netdev_ops = netdev->netdev_ops;
217
218         ib_query_pkey(device, port_num, priv->pkey_index, &priv->pkey);
219
220         rc = hfi1_ipoib_txreq_init(priv);
221         if (rc) {
222                 dd_dev_err(dd, "IPoIB netdev TX init - failed(%d)\n", rc);
223                 return rc;
224         }
225
226         rc = hfi1_ipoib_rxq_init(netdev);
227         if (rc) {
228                 dd_dev_err(dd, "IPoIB netdev RX init - failed(%d)\n", rc);
229                 hfi1_ipoib_txreq_deinit(priv);
230                 return rc;
231         }
232
233         netdev->netdev_ops = &hfi1_ipoib_netdev_ops;
234
235         netdev->priv_destructor = hfi1_ipoib_netdev_dtor;
236         netdev->needs_free_netdev = true;
237
238         return 0;
239 }
240
241 int hfi1_ipoib_rn_get_params(struct ib_device *device,
242                              u32 port_num,
243                              enum rdma_netdev_t type,
244                              struct rdma_netdev_alloc_params *params)
245 {
246         struct hfi1_devdata *dd = dd_from_ibdev(device);
247
248         if (type != RDMA_NETDEV_IPOIB)
249                 return -EOPNOTSUPP;
250
251         if (!HFI1_CAP_IS_KSET(AIP) || !dd->num_netdev_contexts)
252                 return -EOPNOTSUPP;
253
254         if (!port_num || port_num > dd->num_pports)
255                 return -EINVAL;
256
257         params->sizeof_priv = sizeof(struct hfi1_ipoib_rdma_netdev);
258         params->txqs = dd->num_sdma;
259         params->rxqs = dd->num_netdev_contexts;
260         params->param = NULL;
261         params->initialize_rdma_netdev = hfi1_ipoib_setup_rn;
262
263         return 0;
264 }