bge_recv2.c revision 2675:54d99ec6d12d
1241823Smarcel/*
2241823Smarcel * CDDL HEADER START
3241823Smarcel *
4241823Smarcel * The contents of this file are subject to the terms of the
5241823Smarcel * Common Development and Distribution License (the "License").
6241823Smarcel * You may not use this file except in compliance with the License.
7241823Smarcel *
8241823Smarcel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9241823Smarcel * or http://www.opensolaris.org/os/licensing.
10241823Smarcel * See the License for the specific language governing permissions
11241823Smarcel * and limitations under the License.
12241823Smarcel *
13241823Smarcel * When distributing Covered Code, include this CDDL HEADER in each
14241823Smarcel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15241823Smarcel * If applicable, add the following below this CDDL HEADER, with the
16241823Smarcel * fields enclosed by brackets "[]" replaced with your own identifying
17241823Smarcel * information: Portions Copyright [yyyy] [name of copyright owner]
18241823Smarcel *
19241823Smarcel * CDDL HEADER END
20241823Smarcel */
21241823Smarcel
22241823Smarcel/*
23241823Smarcel * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24241823Smarcel * Use is subject to license terms.
25241823Smarcel */
26241823Smarcel
27241823Smarcel#pragma ident	"%Z%%M%	%I%	%E% SMI"
28265420Simp
29241823Smarcel#include "bge_impl.h"
30241823Smarcel
31307721Sngie#define	U32TOPTR(x)	((void *)(uintptr_t)(uint32_t)(x))
32241823Smarcel#define	PTRTOU32(x)	((uint32_t)(uintptr_t)(void *)(x))
33241823Smarcel
34241823Smarcel/*
35241823Smarcel * ========== RX side routines ==========
36273929Sjmmv */
37321142Sngie
38321142Sngie#define	BGE_DBG		BGE_DBG_RECV	/* debug flag for this code	*/
39241823Smarcel
40321142Sngiestatic void bge_refill(bge_t *bgep, buff_ring_t *brp, sw_rbd_t *srbdp);
41321142Sngie#pragma	inline(bge_refill)
42321142Sngie
43321142Sngie/*
44321142Sngie * Return the specified buffer (srbdp) to the ring it came from (brp).
45321142Sngie *
46321142Sngie * Note:
47321142Sngie *	If the driver is compiled with only one buffer ring *and* one
48321142Sngie *	return ring, then the buffers must be returned in sequence.
49321142Sngie *	In this case, we don't have to consider anything about the
50321142Sngie *	buffer at all; we can simply advance the cyclic counter.  And
51321142Sngie *	we don't even need the refill mutex <rf_lock>, as the caller
52321142Sngie *	will already be holding the (one-and-only) <rx_lock>.
53321142Sngie *
54321142Sngie *	If the driver supports multiple buffer rings, but only one
55321754Sngie *	return ring, the same still applies (to each buffer ring
56321142Sngie *	separately).
57321142Sngie */
58321142Sngiestatic void
59321142Sngiebge_refill(bge_t *bgep, buff_ring_t *brp, sw_rbd_t *srbdp)
60321142Sngie{
61321142Sngie	uint64_t slot;
62241823Smarcel
63273929Sjmmv	_NOTE(ARGUNUSED(srbdp))
64273929Sjmmv
65273929Sjmmv	slot = brp->rf_next;
66241823Smarcel	brp->rf_next = NEXT(slot, brp->desc.nslots);
67241823Smarcel	bge_mbx_put(bgep, brp->chip_mbx_reg, slot);
68360658Sdim}
69360658Sdim
70360658Sdimstatic mblk_t *bge_receive_packet(bge_t *bgep, bge_rbd_t *hw_rbd_p);
71275077Sbapt#pragma	inline(bge_receive_packet)
72241823Smarcel
73241823Smarcelstatic mblk_t *
74241823Smarcelbge_receive_packet(bge_t *bgep, bge_rbd_t *hw_rbd_p)
75241823Smarcel{
76241823Smarcel	bge_rbd_t hw_rbd;
77241823Smarcel	buff_ring_t *brp;
78257853Sjmmv	sw_rbd_t *srbdp;
79257853Sjmmv	uchar_t *dp;
80257853Sjmmv	mblk_t *mp;
81257853Sjmmv	uint_t len;
82260576Sjmmv	uint_t minsize;
83241823Smarcel	uint_t maxsize;
84	uint32_t pflags;
85
86	mp = NULL;
87	hw_rbd = *hw_rbd_p;
88
89	switch (hw_rbd.flags & (RBD_FLAG_MINI_RING|RBD_FLAG_JUMBO_RING)) {
90	case RBD_FLAG_MINI_RING|RBD_FLAG_JUMBO_RING:
91	default:
92		/* error, this shouldn't happen */
93		BGE_PKTDUMP((bgep, &hw_rbd, NULL, "bad ring flags!"));
94		goto error;
95
96	case RBD_FLAG_JUMBO_RING:
97		brp = &bgep->buff[BGE_JUMBO_BUFF_RING];
98		break;
99
100#if	(BGE_BUFF_RINGS_USED > 2)
101	case RBD_FLAG_MINI_RING:
102		brp = &bgep->buff[BGE_MINI_BUFF_RING];
103		break;
104#endif	/* BGE_BUFF_RINGS_USED > 2 */
105
106	case 0:
107		brp = &bgep->buff[BGE_STD_BUFF_RING];
108		break;
109	}
110
111	if (hw_rbd.index >= brp->desc.nslots) {
112		/* error, this shouldn't happen */
113		BGE_PKTDUMP((bgep, &hw_rbd, NULL, "bad ring index!"));
114		goto error;
115	}
116
117	srbdp = &brp->sw_rbds[hw_rbd.index];
118	if (hw_rbd.opaque != srbdp->pbuf.token) {
119		/* bogus, drop the packet */
120		BGE_PKTDUMP((bgep, &hw_rbd, srbdp, "bad ring token"));
121		goto refill;
122	}
123
124	if ((hw_rbd.flags & RBD_FLAG_PACKET_END) == 0) {
125		/* bogus, drop the packet */
126		BGE_PKTDUMP((bgep, &hw_rbd, srbdp, "unterminated packet"));
127		goto refill;
128	}
129
130	if (hw_rbd.flags & RBD_FLAG_FRAME_HAS_ERROR) {
131		/* bogus, drop the packet */
132		BGE_PKTDUMP((bgep, &hw_rbd, srbdp, "errored packet"));
133		goto refill;
134	}
135
136	len = hw_rbd.len;
137
138#ifdef BGE_IPMI_ASF
139	/*
140	 * When IPMI/ASF is enabled, VLAN tag must be stripped.
141	 */
142	if (bgep->asf_enabled && (hw_rbd.flags & RBD_FLAG_VLAN_TAG))
143		maxsize = bgep->chipid.ethmax_size + ETHERFCSL;
144	else
145#endif
146		/*
147		 * H/W will not strip the VLAN tag from incoming packet
148		 * now, as RECEIVE_MODE_KEEP_VLAN_TAG bit is set in
149		 * RECEIVE_MAC_MODE_REG register.
150		 */
151		maxsize = bgep->chipid.ethmax_size + VLAN_TAGSZ + ETHERFCSL;
152	if (len > maxsize) {
153		/* bogus, drop the packet */
154		BGE_PKTDUMP((bgep, &hw_rbd, srbdp, "oversize packet"));
155		goto refill;
156	}
157
158#ifdef BGE_IPMI_ASF
159	if (bgep->asf_enabled && (hw_rbd.flags & RBD_FLAG_VLAN_TAG))
160		minsize = ETHERMIN + ETHERFCSL - VLAN_TAGSZ;
161	else
162#endif
163		minsize = ETHERMIN + ETHERFCSL;
164	if (len < minsize) {
165		/* bogus, drop the packet */
166		BGE_PKTDUMP((bgep, &hw_rbd, srbdp, "undersize packet"));
167		goto refill;
168	}
169
170	/*
171	 * Packet looks good; get a buffer to copy it into.
172	 * We want to leave some space at the front of the allocated
173	 * buffer in case any upstream modules want to prepend some
174	 * sort of header.  This also has the side-effect of making
175	 * the packet *contents* 4-byte aligned, as required by NCA!
176	 */
177#ifdef BGE_IPMI_ASF
178	if (bgep->asf_enabled && (hw_rbd.flags & RBD_FLAG_VLAN_TAG)) {
179		mp = allocb(BGE_HEADROOM + len + VLAN_TAGSZ, 0);
180	} else {
181#endif
182
183		mp = allocb(BGE_HEADROOM + len, 0);
184#ifdef BGE_IPMI_ASF
185	}
186#endif
187	if (mp == NULL) {
188		/* Nothing to do but drop the packet */
189		goto refill;
190	}
191
192	/*
193	 * Sync the data and copy it to the STREAMS buffer.
194	 */
195	DMA_SYNC(srbdp->pbuf, DDI_DMA_SYNC_FORKERNEL);
196	if (bge_check_dma_handle(bgep, srbdp->pbuf.dma_hdl) != DDI_FM_OK) {
197		bgep->bge_dma_error = B_TRUE;
198		bgep->bge_chip_state = BGE_CHIP_ERROR;
199		return (NULL);
200	}
201#ifdef BGE_IPMI_ASF
202	if (bgep->asf_enabled && (hw_rbd.flags & RBD_FLAG_VLAN_TAG)) {
203		/*
204		 * As VLAN tag has been stripped from incoming packet in ASF
205		 * scenario, we insert it into this packet again.
206		 */
207		struct ether_vlan_header *ehp;
208		mp->b_rptr = dp = mp->b_rptr + BGE_HEADROOM - VLAN_TAGSZ;
209		bcopy(DMA_VPTR(srbdp->pbuf), dp, 2 * ETHERADDRL);
210		ehp = (struct ether_vlan_header *)dp;
211		ehp->ether_tpid = ntohs(VLAN_TPID);
212		ehp->ether_tci = ntohs(hw_rbd.vlan_tci);
213		bcopy(((uchar_t *)(DMA_VPTR(srbdp->pbuf))) + 2 * ETHERADDRL,
214			dp + 2 * ETHERADDRL + VLAN_TAGSZ,
215			len - 2 * ETHERADDRL);
216	} else {
217#endif
218		mp->b_rptr = dp = mp->b_rptr + BGE_HEADROOM;
219		bcopy(DMA_VPTR(srbdp->pbuf), dp, len);
220#ifdef BGE_IPMI_ASF
221	}
222
223	if (bgep->asf_enabled && (hw_rbd.flags & RBD_FLAG_VLAN_TAG)) {
224		mp->b_wptr = dp + len + VLAN_TAGSZ - ETHERFCSL;
225	} else
226#endif
227		mp->b_wptr = dp + len - ETHERFCSL;
228
229	/*
230	 * Special check for one specific type of data corruption;
231	 * in a good packet, the first 8 bytes are *very* unlikely
232	 * to be the same as the second 8 bytes ... but we let the
233	 * packet through just in case.
234	 */
235	if (bcmp(dp, dp+8, 8) == 0)
236		BGE_PKTDUMP((bgep, &hw_rbd, srbdp, "stuttered packet?"));
237
238	pflags = 0;
239	if (hw_rbd.flags & RBD_FLAG_TCP_UDP_CHECKSUM)
240		pflags |= HCK_FULLCKSUM;
241	if (hw_rbd.flags & RBD_FLAG_IP_CHECKSUM)
242		pflags |= HCK_IPV4_HDRCKSUM;
243	if (pflags != 0)
244		(void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0,
245		    hw_rbd.tcp_udp_cksum, pflags, 0);
246
247refill:
248	/*
249	 * Replace the buffer in the ring it came from ...
250	 */
251	bge_refill(bgep, brp, srbdp);
252	return (mp);
253
254error:
255	/*
256	 * We come here if the integrity of the ring descriptors
257	 * (rather than merely packet data) appears corrupted.
258	 * The factotum will attempt to reset-and-recover.
259	 */
260	bgep->bge_chip_state = BGE_CHIP_ERROR;
261	bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
262	return (NULL);
263}
264
265/*
266 * Accept the packets received in the specified ring up to
267 * (but not including) the producer index in the status block.
268 *
269 * Returns a chain of mblks containing the received data, to be
270 * passed up to gld_recv() (we can't call gld_recv() from here,
271 * 'cos we're holding the per-ring receive lock at this point).
272 *
273 * This function must advance (rrp->rx_next) and write it back to
274 * the chip to indicate the packets it has accepted from the ring.
275 */
276static mblk_t *bge_receive_ring(bge_t *bgep, recv_ring_t *rrp);
277#pragma	inline(bge_receive_ring)
278
279static mblk_t *
280bge_receive_ring(bge_t *bgep, recv_ring_t *rrp)
281{
282	bge_rbd_t *hw_rbd_p;
283	uint64_t slot;
284	mblk_t *head;
285	mblk_t **tail;
286	mblk_t *mp;
287
288	ASSERT(mutex_owned(rrp->rx_lock));
289
290	/*
291	 * Sync (all) the receive ring descriptors
292	 * before accepting the packets they describe
293	 */
294	DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORKERNEL);
295	if (*rrp->prod_index_p >= rrp->desc.nslots) {
296		bgep->bge_chip_state = BGE_CHIP_ERROR;
297		bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
298		return (NULL);
299	}
300	if (bge_check_dma_handle(bgep, rrp->desc.dma_hdl) != DDI_FM_OK) {
301		rrp->rx_next = *rrp->prod_index_p;
302		bge_mbx_put(bgep, rrp->chip_mbx_reg, rrp->rx_next);
303		bgep->bge_dma_error = B_TRUE;
304		bgep->bge_chip_state = BGE_CHIP_ERROR;
305		return (NULL);
306	}
307
308	hw_rbd_p = DMA_VPTR(rrp->desc);
309	head = NULL;
310	tail = &head;
311	slot = rrp->rx_next;
312
313	while (slot != *rrp->prod_index_p) {	/* Note: volatile	*/
314		if ((mp = bge_receive_packet(bgep, &hw_rbd_p[slot])) != NULL) {
315			*tail = mp;
316			tail = &mp->b_next;
317		}
318		rrp->rx_next = slot = NEXT(slot, rrp->desc.nslots);
319	}
320
321	bge_mbx_put(bgep, rrp->chip_mbx_reg, rrp->rx_next);
322	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
323		bgep->bge_chip_state = BGE_CHIP_ERROR;
324	return (head);
325}
326
327/*
328 * Receive all packets in all rings.
329 *
330 * To give priority to low-numbered rings, whenever we have received any
331 * packets in any ring except 0, we restart scanning again from ring 0.
332 * Thus, for example, if rings 0, 3, and 10 are carrying traffic, the
333 * pattern of receives might go 0, 3, 10, 3, 0, 10, 0:
334 *
335 *	0	found some - receive them
336 *	1..2					none found
337 *	3	found some - receive them	and restart scan
338 *	0..9					none found
339 *	10	found some - receive them	and restart scan
340 *	0..2					none found
341 *	3	found some more - receive them	and restart scan
342 *	0	found some more - receive them
343 *	1..9					none found
344 *	10	found some more - receive them	and restart scan
345 *	0	found some more - receive them
346 *	1..15					none found
347 *
348 * The routine returns only when a complete scan has been performed
349 * without finding any packets to receive.
350 *
351 * Note that driver-defined locks may *NOT* be held across calls
352 * to gld_recv().
353 *
354 * Note: the expression (BGE_RECV_RINGS_USED > 1), yields a compile-time
355 * constant and allows the compiler to optimise away the outer do-loop
356 * if only one receive ring is being used.
357 */
358void bge_receive(bge_t *bgep, bge_status_t *bsp);
359#pragma	no_inline(bge_receive)
360
361void
362bge_receive(bge_t *bgep, bge_status_t *bsp)
363{
364	recv_ring_t *rrp;
365	uint64_t ring;
366	uint64_t rx_rings = bgep->chipid.rx_rings;
367	mblk_t *mp;
368
369restart:
370	ring = 0;
371	rrp = &bgep->recv[ring];
372	do {
373		/*
374		 * For each ring, (rrp->prod_index_p) points to the
375		 * proper index within the status block (which has
376		 * already been sync'd by the caller)
377		 */
378		ASSERT(rrp->prod_index_p == RECV_INDEX_P(bsp, ring));
379
380		if (*rrp->prod_index_p == rrp->rx_next)
381			continue;		/* no packets		*/
382		if (mutex_tryenter(rrp->rx_lock) == 0)
383			continue;		/* already in process	*/
384		mp = bge_receive_ring(bgep, rrp);
385		mutex_exit(rrp->rx_lock);
386
387		if (mp != NULL) {
388			mac_rx(bgep->mh, rrp->handle, mp);
389
390			/*
391			 * Restart from ring 0, if the driver is compiled
392			 * with multiple rings and we're not on ring 0 now
393			 */
394			if (rx_rings > 1 && ring > 0)
395				goto restart;
396		}
397
398		/*
399		 * Loop over all rings (if there *are* multiple rings)
400		 */
401	} while (++rrp, ++ring < rx_rings);
402}
403