14d0e5007SSukumar Swaminathan /*
24d0e5007SSukumar Swaminathan  * CDDL HEADER START
34d0e5007SSukumar Swaminathan  *
44d0e5007SSukumar Swaminathan  * The contents of this file are subject to the terms of the
54d0e5007SSukumar Swaminathan  * Common Development and Distribution License (the "License").
64d0e5007SSukumar Swaminathan  * You may not use this file except in compliance with the License.
74d0e5007SSukumar Swaminathan  *
84d0e5007SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94d0e5007SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
104d0e5007SSukumar Swaminathan  * See the License for the specific language governing permissions
114d0e5007SSukumar Swaminathan  * and limitations under the License.
124d0e5007SSukumar Swaminathan  *
134d0e5007SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
144d0e5007SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154d0e5007SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
164d0e5007SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
174d0e5007SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
184d0e5007SSukumar Swaminathan  *
194d0e5007SSukumar Swaminathan  * CDDL HEADER END
204d0e5007SSukumar Swaminathan  */
214d0e5007SSukumar Swaminathan 
22*3abb112fSGarrett D'Amore /* Copyright © 2003-2011 Emulex. All rights reserved.  */
234d0e5007SSukumar Swaminathan 
244d0e5007SSukumar Swaminathan /*
254d0e5007SSukumar Swaminathan  * Source file containing the implementation of the MailBox queue handling
264d0e5007SSukumar Swaminathan  * and related helper functions
274d0e5007SSukumar Swaminathan  */
284d0e5007SSukumar Swaminathan 
294d0e5007SSukumar Swaminathan #include <oce_impl.h>
304d0e5007SSukumar Swaminathan 
314d0e5007SSukumar Swaminathan /*
324d0e5007SSukumar Swaminathan  * function to drain a MCQ and process its CQEs
334d0e5007SSukumar Swaminathan  *
344d0e5007SSukumar Swaminathan  * dev - software handle to the device
354d0e5007SSukumar Swaminathan  * cq - pointer to the cq to drain
364d0e5007SSukumar Swaminathan  *
374d0e5007SSukumar Swaminathan  * return the number of CQEs processed
384d0e5007SSukumar Swaminathan  */
394d0e5007SSukumar Swaminathan uint16_t
oce_drain_mq_cq(void * arg)404d0e5007SSukumar Swaminathan oce_drain_mq_cq(void *arg)
414d0e5007SSukumar Swaminathan {
424d0e5007SSukumar Swaminathan 	struct oce_mq_cqe *cqe = NULL;
434d0e5007SSukumar Swaminathan 	uint16_t num_cqe = 0;
444d0e5007SSukumar Swaminathan 	link_state_t link_status;
454d0e5007SSukumar Swaminathan 	struct oce_async_cqe_link_state *acqe;
464d0e5007SSukumar Swaminathan 	struct oce_mq *mq;
474d0e5007SSukumar Swaminathan 	struct oce_cq  *cq;
484d0e5007SSukumar Swaminathan 	struct oce_dev *dev;
494d0e5007SSukumar Swaminathan 
504d0e5007SSukumar Swaminathan 	/* do while we do not reach a cqe that is not valid */
514d0e5007SSukumar Swaminathan 	mq = (struct oce_mq *)arg;
524d0e5007SSukumar Swaminathan 	cq = mq->cq;
534d0e5007SSukumar Swaminathan 	dev = mq->parent;
548d738d7dSSukumar Swaminathan 	mutex_enter(&mq->lock);
554d0e5007SSukumar Swaminathan 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
564d0e5007SSukumar Swaminathan 	while (cqe->u0.dw[3]) {
574d0e5007SSukumar Swaminathan 		DW_SWAP(u32ptr(cqe), sizeof (struct oce_mq_cqe));
584d0e5007SSukumar Swaminathan 		if (cqe->u0.s.async_event) {
594d0e5007SSukumar Swaminathan 			acqe = (struct oce_async_cqe_link_state *)cqe;
604d0e5007SSukumar Swaminathan 			if (acqe->u0.s.event_code ==
614d0e5007SSukumar Swaminathan 			    ASYNC_EVENT_CODE_LINK_STATE) {
625b9d3151SSukumar Swaminathan 				/*
635b9d3151SSukumar Swaminathan 				 * don't care logical or not,
645b9d3151SSukumar Swaminathan 				 * just check up down
655b9d3151SSukumar Swaminathan 				 */
665b9d3151SSukumar Swaminathan 
675b9d3151SSukumar Swaminathan 				link_status = ((acqe->u0.s.link_status &
685b9d3151SSukumar Swaminathan 				    ~ASYNC_EVENT_LOGICAL) ==
695b9d3151SSukumar Swaminathan 				    ASYNC_EVENT_LINK_UP) ?
705b9d3151SSukumar Swaminathan 				    LINK_STATE_UP: LINK_STATE_DOWN;
714d0e5007SSukumar Swaminathan 				mac_link_update(dev->mac_handle, link_status);
725b9d3151SSukumar Swaminathan 				dev->link_status = link_status;
735b9d3151SSukumar Swaminathan 				dev->link_speed = -1;
744d0e5007SSukumar Swaminathan 			}
754d0e5007SSukumar Swaminathan 		}
764d0e5007SSukumar Swaminathan 		cqe->u0.dw[3] = 0;
774d0e5007SSukumar Swaminathan 		RING_GET(cq->ring, 1);
784d0e5007SSukumar Swaminathan 		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
794d0e5007SSukumar Swaminathan 		num_cqe++;
804d0e5007SSukumar Swaminathan 	} /* for all valid CQE */
818d738d7dSSukumar Swaminathan 	mutex_exit(&mq->lock);
824d0e5007SSukumar Swaminathan 	oce_arm_cq(dev, cq->cq_id, num_cqe, B_TRUE);
834d0e5007SSukumar Swaminathan 	return (num_cqe);
844d0e5007SSukumar Swaminathan } /* oce_drain_mq_cq */
854d0e5007SSukumar Swaminathan 
868d738d7dSSukumar Swaminathan int
oce_start_mq(struct oce_mq * mq)878d738d7dSSukumar Swaminathan oce_start_mq(struct oce_mq *mq)
888d738d7dSSukumar Swaminathan {
898d738d7dSSukumar Swaminathan 	oce_arm_cq(mq->parent, mq->cq->cq_id, 0, B_TRUE);
908d738d7dSSukumar Swaminathan 	return (0);
918d738d7dSSukumar Swaminathan }
928d738d7dSSukumar Swaminathan 
938d738d7dSSukumar Swaminathan 
944d0e5007SSukumar Swaminathan void
oce_clean_mq(struct oce_mq * mq)958d738d7dSSukumar Swaminathan oce_clean_mq(struct oce_mq *mq)
964d0e5007SSukumar Swaminathan {
978d738d7dSSukumar Swaminathan 	struct oce_cq  *cq;
988d738d7dSSukumar Swaminathan 	struct oce_dev *dev;
998d738d7dSSukumar Swaminathan 	uint16_t num_cqe = 0;
1008d738d7dSSukumar Swaminathan 	struct oce_mq_cqe *cqe = NULL;
1014d0e5007SSukumar Swaminathan 
1028d738d7dSSukumar Swaminathan 	cq = mq->cq;
1038d738d7dSSukumar Swaminathan 	dev = mq->parent;
1048d738d7dSSukumar Swaminathan 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
1058d738d7dSSukumar Swaminathan 	while (cqe->u0.dw[3]) {
1068d738d7dSSukumar Swaminathan 		DW_SWAP(u32ptr(cqe), sizeof (struct oce_mq_cqe));
1078d738d7dSSukumar Swaminathan 		cqe->u0.dw[3] = 0;
1088d738d7dSSukumar Swaminathan 		RING_GET(cq->ring, 1);
1098d738d7dSSukumar Swaminathan 		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
1108d738d7dSSukumar Swaminathan 		num_cqe++;
1118d738d7dSSukumar Swaminathan 	} /* for all valid CQE */
1128d738d7dSSukumar Swaminathan 	if (num_cqe)
1138d738d7dSSukumar Swaminathan 		oce_arm_cq(dev, cq->cq_id, num_cqe, B_FALSE);
1144d0e5007SSukumar Swaminathan 	/* Drain the Event queue now */
1154d0e5007SSukumar Swaminathan 	oce_drain_eq(mq->cq->eq);
1164d0e5007SSukumar Swaminathan }
117