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