1/*
2 * Copyright (c) 2006 QLogic, Inc. All rights reserved.
3 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses.  You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
10 *
11 *     Redistribution and use in source and binary forms, with or
12 *     without modification, are permitted provided that the following
13 *     conditions are met:
14 *
15 *      - Redistributions of source code must retain the above
16 *        copyright notice, this list of conditions and the following
17 *        disclaimer.
18 *
19 *      - Redistributions in binary form must reproduce the above
20 *        copyright notice, this list of conditions and the following
21 *        disclaimer in the documentation and/or other materials
22 *        provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34/*
35 * These are the routines used by layered drivers, currently just the
36 * layered ethernet driver and verbs layer.
37 */
38
39#include <linux/io.h>
40#include <asm/byteorder.h>
41
42#include "ipath_kernel.h"
43#include "ipath_layer.h"
44#include "ipath_verbs.h"
45#include "ipath_common.h"
46
47/* Acquire before ipath_devs_lock. */
48static DEFINE_MUTEX(ipath_layer_mutex);
49
50u16 ipath_layer_rcv_opcode;
51
52static int (*layer_intr)(void *, u32);
53static int (*layer_rcv)(void *, void *, struct sk_buff *);
54static int (*layer_rcv_lid)(void *, void *);
55
56static void *(*layer_add_one)(int, struct ipath_devdata *);
57static void (*layer_remove_one)(void *);
58
59int __ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
60{
61	int ret = -ENODEV;
62
63	if (dd->ipath_layer.l_arg && layer_intr)
64		ret = layer_intr(dd->ipath_layer.l_arg, arg);
65
66	return ret;
67}
68
69int ipath_layer_intr(struct ipath_devdata *dd, u32 arg)
70{
71	int ret;
72
73	mutex_lock(&ipath_layer_mutex);
74
75	ret = __ipath_layer_intr(dd, arg);
76
77	mutex_unlock(&ipath_layer_mutex);
78
79	return ret;
80}
81
82int __ipath_layer_rcv(struct ipath_devdata *dd, void *hdr,
83		      struct sk_buff *skb)
84{
85	int ret = -ENODEV;
86
87	if (dd->ipath_layer.l_arg && layer_rcv)
88		ret = layer_rcv(dd->ipath_layer.l_arg, hdr, skb);
89
90	return ret;
91}
92
93int __ipath_layer_rcv_lid(struct ipath_devdata *dd, void *hdr)
94{
95	int ret = -ENODEV;
96
97	if (dd->ipath_layer.l_arg && layer_rcv_lid)
98		ret = layer_rcv_lid(dd->ipath_layer.l_arg, hdr);
99
100	return ret;
101}
102
103void ipath_layer_lid_changed(struct ipath_devdata *dd)
104{
105	mutex_lock(&ipath_layer_mutex);
106
107	if (dd->ipath_layer.l_arg && layer_intr)
108		layer_intr(dd->ipath_layer.l_arg, IPATH_LAYER_INT_LID);
109
110	mutex_unlock(&ipath_layer_mutex);
111}
112
113void ipath_layer_add(struct ipath_devdata *dd)
114{
115	mutex_lock(&ipath_layer_mutex);
116
117	if (layer_add_one)
118		dd->ipath_layer.l_arg =
119			layer_add_one(dd->ipath_unit, dd);
120
121	mutex_unlock(&ipath_layer_mutex);
122}
123
124void ipath_layer_remove(struct ipath_devdata *dd)
125{
126	mutex_lock(&ipath_layer_mutex);
127
128	if (dd->ipath_layer.l_arg && layer_remove_one) {
129		layer_remove_one(dd->ipath_layer.l_arg);
130		dd->ipath_layer.l_arg = NULL;
131	}
132
133	mutex_unlock(&ipath_layer_mutex);
134}
135
136int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *),
137			 void (*l_remove)(void *),
138			 int (*l_intr)(void *, u32),
139			 int (*l_rcv)(void *, void *, struct sk_buff *),
140			 u16 l_rcv_opcode,
141			 int (*l_rcv_lid)(void *, void *))
142{
143	struct ipath_devdata *dd, *tmp;
144	unsigned long flags;
145
146	mutex_lock(&ipath_layer_mutex);
147
148	layer_add_one = l_add;
149	layer_remove_one = l_remove;
150	layer_intr = l_intr;
151	layer_rcv = l_rcv;
152	layer_rcv_lid = l_rcv_lid;
153	ipath_layer_rcv_opcode = l_rcv_opcode;
154
155	spin_lock_irqsave(&ipath_devs_lock, flags);
156
157	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
158		if (!(dd->ipath_flags & IPATH_INITTED))
159			continue;
160
161		if (dd->ipath_layer.l_arg)
162			continue;
163
164		spin_unlock_irqrestore(&ipath_devs_lock, flags);
165		dd->ipath_layer.l_arg = l_add(dd->ipath_unit, dd);
166		spin_lock_irqsave(&ipath_devs_lock, flags);
167	}
168
169	spin_unlock_irqrestore(&ipath_devs_lock, flags);
170	mutex_unlock(&ipath_layer_mutex);
171
172	return 0;
173}
174
175EXPORT_SYMBOL_GPL(ipath_layer_register);
176
177void ipath_layer_unregister(void)
178{
179	struct ipath_devdata *dd, *tmp;
180	unsigned long flags;
181
182	mutex_lock(&ipath_layer_mutex);
183	spin_lock_irqsave(&ipath_devs_lock, flags);
184
185	list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
186		if (dd->ipath_layer.l_arg && layer_remove_one) {
187			spin_unlock_irqrestore(&ipath_devs_lock, flags);
188			layer_remove_one(dd->ipath_layer.l_arg);
189			spin_lock_irqsave(&ipath_devs_lock, flags);
190			dd->ipath_layer.l_arg = NULL;
191		}
192	}
193
194	spin_unlock_irqrestore(&ipath_devs_lock, flags);
195
196	layer_add_one = NULL;
197	layer_remove_one = NULL;
198	layer_intr = NULL;
199	layer_rcv = NULL;
200	layer_rcv_lid = NULL;
201
202	mutex_unlock(&ipath_layer_mutex);
203}
204
205EXPORT_SYMBOL_GPL(ipath_layer_unregister);
206
207int ipath_layer_open(struct ipath_devdata *dd, u32 * pktmax)
208{
209	int ret;
210	u32 intval = 0;
211
212	mutex_lock(&ipath_layer_mutex);
213
214	if (!dd->ipath_layer.l_arg) {
215		ret = -EINVAL;
216		goto bail;
217	}
218
219	ret = ipath_setrcvhdrsize(dd, IPATH_HEADER_QUEUE_WORDS);
220
221	if (ret < 0)
222		goto bail;
223
224	*pktmax = dd->ipath_ibmaxlen;
225
226	if (*dd->ipath_statusp & IPATH_STATUS_IB_READY)
227		intval |= IPATH_LAYER_INT_IF_UP;
228	if (dd->ipath_lid)
229		intval |= IPATH_LAYER_INT_LID;
230	if (dd->ipath_mlid)
231		intval |= IPATH_LAYER_INT_BCAST;
232	/*
233	 * do this on open, in case low level is already up and
234	 * just layered driver was reloaded, etc.
235	 */
236	if (intval)
237		layer_intr(dd->ipath_layer.l_arg, intval);
238
239	ret = 0;
240bail:
241	mutex_unlock(&ipath_layer_mutex);
242
243	return ret;
244}
245
246EXPORT_SYMBOL_GPL(ipath_layer_open);
247
248u16 ipath_layer_get_lid(struct ipath_devdata *dd)
249{
250	return dd->ipath_lid;
251}
252
253EXPORT_SYMBOL_GPL(ipath_layer_get_lid);
254
255/**
256 * ipath_layer_get_mac - get the MAC address
257 * @dd: the infinipath device
258 * @mac: the MAC is put here
259 *
260 * This is the EUID-64 OUI octets (top 3), then
261 * skip the next 2 (which should both be zero or 0xff).
262 * The returned MAC is in network order
263 * mac points to at least 6 bytes of buffer
264 * We assume that by the time the LID is set, that the GUID is as valid
265 * as it's ever going to be, rather than adding yet another status bit.
266 */
267
268int ipath_layer_get_mac(struct ipath_devdata *dd, u8 * mac)
269{
270	u8 *guid;
271
272	guid = (u8 *) &dd->ipath_guid;
273
274	mac[0] = guid[0];
275	mac[1] = guid[1];
276	mac[2] = guid[2];
277	mac[3] = guid[5];
278	mac[4] = guid[6];
279	mac[5] = guid[7];
280	if ((guid[3] || guid[4]) && !(guid[3] == 0xff && guid[4] == 0xff))
281		ipath_dbg("Warning, guid bytes 3 and 4 not 0 or 0xffff: "
282			  "%x %x\n", guid[3], guid[4]);
283	return 0;
284}
285
286EXPORT_SYMBOL_GPL(ipath_layer_get_mac);
287
288u16 ipath_layer_get_bcast(struct ipath_devdata *dd)
289{
290	return dd->ipath_mlid;
291}
292
293EXPORT_SYMBOL_GPL(ipath_layer_get_bcast);
294
295int ipath_layer_send_hdr(struct ipath_devdata *dd, struct ether_header *hdr)
296{
297	int ret = 0;
298	u32 __iomem *piobuf;
299	u32 plen, *uhdr;
300	size_t count;
301	__be16 vlsllnh;
302
303	if (!(dd->ipath_flags & IPATH_RCVHDRSZ_SET)) {
304		ipath_dbg("send while not open\n");
305		ret = -EINVAL;
306	} else
307		if ((dd->ipath_flags & (IPATH_LINKUNK | IPATH_LINKDOWN)) ||
308		    dd->ipath_lid == 0) {
309			/*
310			 * lid check is for when sma hasn't yet configured
311			 */
312			ret = -ENETDOWN;
313			ipath_cdbg(VERBOSE, "send while not ready, "
314				   "mylid=%u, flags=0x%x\n",
315				   dd->ipath_lid, dd->ipath_flags);
316		}
317
318	vlsllnh = *((__be16 *) hdr);
319	if (vlsllnh != htons(IPATH_LRH_BTH)) {
320		ipath_dbg("Warning: lrh[0] wrong (%x, not %x); "
321			  "not sending\n", be16_to_cpu(vlsllnh),
322			  IPATH_LRH_BTH);
323		ret = -EINVAL;
324	}
325	if (ret)
326		goto done;
327
328	/* Get a PIO buffer to use. */
329	piobuf = ipath_getpiobuf(dd, NULL);
330	if (piobuf == NULL) {
331		ret = -EBUSY;
332		goto done;
333	}
334
335	plen = (sizeof(*hdr) >> 2); /* actual length */
336	ipath_cdbg(EPKT, "0x%x+1w pio %p\n", plen, piobuf);
337
338	writeq(plen+1, piobuf); /* len (+1 for pad) to pbc, no flags */
339	ipath_flush_wc();
340	piobuf += 2;
341	uhdr = (u32 *)hdr;
342	count = plen-1; /* amount we can copy before trigger word */
343	__iowrite32_copy(piobuf, uhdr, count);
344	ipath_flush_wc();
345	__raw_writel(uhdr[count], piobuf + count);
346	ipath_flush_wc(); /* ensure it's sent, now */
347
348	ipath_stats.sps_ether_spkts++;	/* ether packet sent */
349
350done:
351	return ret;
352}
353
354EXPORT_SYMBOL_GPL(ipath_layer_send_hdr);
355
356int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd)
357{
358	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
359
360	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
361			 dd->ipath_sendctrl);
362	return 0;
363}
364
365EXPORT_SYMBOL_GPL(ipath_layer_set_piointbufavail_int);
366