1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Source file containing the implementation of the MailBox queue handling
29  * and related helper functions
30  */
31 
32 #include <oce_impl.h>
33 
34 /*
35  * function to drain a MCQ and process its CQEs
36  *
37  * dev - software handle to the device
38  * cq - pointer to the cq to drain
39  *
40  * return the number of CQEs processed
41  */
42 uint16_t
43 oce_drain_mq_cq(void *arg)
44 {
45 	struct oce_mq_cqe *cqe = NULL;
46 	uint16_t num_cqe = 0;
47 	link_state_t link_status;
48 	struct oce_async_cqe_link_state *acqe;
49 	struct oce_mq *mq;
50 	struct oce_cq  *cq;
51 	struct oce_dev *dev;
52 
53 	/* do while we do not reach a cqe that is not valid */
54 	mq = (struct oce_mq *)arg;
55 	cq = mq->cq;
56 	dev = mq->parent;
57 	mutex_enter(&cq->lock);
58 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
59 	while (cqe->u0.dw[3]) {
60 		DW_SWAP(u32ptr(cqe), sizeof (struct oce_mq_cqe));
61 		if (cqe->u0.s.async_event) {
62 			acqe = (struct oce_async_cqe_link_state *)cqe;
63 			if (acqe->u0.s.event_code ==
64 			    ASYNC_EVENT_CODE_LINK_STATE) {
65 				link_status = (acqe->u0.s.link_status)?
66 				    LINK_STATE_UP : LINK_STATE_DOWN;
67 				mac_link_update(dev->mac_handle, link_status);
68 			}
69 		}
70 		cqe->u0.dw[3] = 0;
71 		RING_GET(cq->ring, 1);
72 		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
73 		num_cqe++;
74 	} /* for all valid CQE */
75 	mutex_exit(&cq->lock);
76 	oce_arm_cq(dev, cq->cq_id, num_cqe, B_TRUE);
77 	return (num_cqe);
78 } /* oce_drain_mq_cq */
79 
80 void
81 oce_stop_mq(struct oce_mq *mq)
82 {
83 	while (oce_drain_mq_cq(mq) != 0) {
84 	}
85 
86 	/* Drain the Event queue now */
87 	oce_drain_eq(mq->cq->eq);
88 }
89