Print this page
NEX-1890 update oce from source provided by Emulex
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/fibre-channel/fca/oce/oce_mq.c
+++ new/usr/src/uts/common/io/fibre-channel/fca/oce/oce_mq.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 -/* Copyright © 2003-2011 Emulex. All rights reserved. */
22 +/*
23 + * Copyright (c) 2009-2012 Emulex. All rights reserved.
24 + * Use is subject to license terms.
25 + */
23 26
27 +
28 +
24 29 /*
25 30 * Source file containing the implementation of the MailBox queue handling
26 31 * and related helper functions
27 32 */
28 33
29 34 #include <oce_impl.h>
30 35
36 +int pow10[5] = {
37 + 0,
38 + 10,
39 + 100,
40 + 1000,
41 + 10000
42 +};
43 +
44 +static void oce_process_link_event(struct oce_dev *dev,
45 + struct oce_async_cqe_link_state *acqe);
46 +static void oce_async_grp5_qos_speed_process(struct oce_dev *dev,
47 + struct oce_async_event_grp5_qos_link_speed *acqe);
48 +static void oce_async_grp5_pvid_state(struct oce_dev *dev,
49 + struct oce_async_event_grp5_pvid_state *acqe);
50 +static void oce_async_grp5_cos_priority(struct oce_dev *dev,
51 + struct oce_async_event_grp5_cos_priority *acqe);
52 +void oce_process_grp5_event(struct oce_dev *dev,
53 + struct oce_mq_cqe *cqe, uint8_t event_type);
54 +static void oce_process_mq_compl(struct oce_dev *dev,
55 + struct oce_mq_cqe *cqe);
56 +static void oce_process_async_events(struct oce_dev *dev,
57 + struct oce_mq_cqe *cqe);
58 +
59 +
60 +static void
61 +oce_process_debug_event(struct oce_dev *dev,
62 + struct async_event_qnq *acqe, uint8_t event_type)
63 +{
64 + oce_log(dev, CE_NOTE, MOD_CONFIG,
65 + "Debug Event: type = %d, enabled = %d, tag = 0x%x",
66 + acqe->trailer.u0.bits.event_type, acqe->enabled, acqe->vlan_tag);
67 +
68 + if (event_type == ASYNC_DEBUG_EVENT_TYPE_QNQ) {
69 + dev->QnQ_queried = 1;
70 + dev->QnQ_valid = acqe->enabled;
71 + dev->QnQ_tag = LE_16(acqe->vlan_tag);
72 +
73 + if (!dev->QnQ_valid) {
74 + dev->QnQ_tag = 0;
75 + }
76 + }
77 +}
78 +
79 +static void
80 +oce_process_link_event(struct oce_dev *dev,
81 + struct oce_async_cqe_link_state *acqe)
82 +{
83 + link_state_t link_status;
84 +
85 + link_status = ((acqe->link_status & ~ASYNC_EVENT_LOGICAL) ==
86 + ASYNC_EVENT_LINK_UP) ? LINK_STATE_UP: LINK_STATE_DOWN;
87 +
88 + /* store the link status */
89 + dev->link_status = link_status;
90 +
91 + dev->link_speed = (acqe->qos_link_speed > 0) ?
92 + LE_16(acqe->qos_link_speed) * 10 : pow10[acqe->speed];
93 + dev->link_duplex = acqe->duplex;
94 +
95 + mac_link_update(dev->mac_handle, link_status);
96 + oce_log(dev, CE_NOTE, MOD_CONFIG, " Link Event"
97 + "Link Status %d Link Speed %d Link Duplex %d\n",
98 + dev->link_status, dev->link_speed, dev->link_duplex);
99 +}
100 +
101 +static void
102 +oce_async_grp5_qos_speed_process(struct oce_dev *dev,
103 + struct oce_async_event_grp5_qos_link_speed *acqe)
104 +{
105 +
106 + if (acqe->physical_port == dev->port_id) {
107 + dev->link_speed = LE_16(acqe->qos_link_speed) * 10;
108 + }
109 + oce_log(dev, CE_NOTE, MOD_CONFIG, "GRP5 QOS_SPEED EVENT"
110 + "Physical Port : %d QOS_SPEED %d\n", acqe->physical_port,
111 + acqe->qos_link_speed);
112 +}
113 +
114 +static void
115 +oce_async_grp5_pvid_state(struct oce_dev *dev,
116 + struct oce_async_event_grp5_pvid_state *acqe)
117 +{
118 +
119 + if (acqe->enabled) {
120 + dev->pvid = BE_16(acqe->tag);
121 + } else {
122 + dev->pvid = 0;
123 + }
124 + oce_log(dev, CE_NOTE, MOD_CONFIG, "GRP5 PVID EVENT"
125 + "PVID Configured : 0x%x\n", dev->pvid);
126 +}
127 +
128 +static void
129 +oce_async_grp5_cos_priority(struct oce_dev *dev,
130 + struct oce_async_event_grp5_cos_priority *acqe)
131 +{
132 + if (acqe->valid) {
133 + dev->vlan_prio_bmap = acqe->available_priority_bmap;
134 + dev->reco_priority &= acqe->reco_default_priority;
135 + }
136 +
137 +}
138 +
139 +void
140 +oce_process_grp5_event(struct oce_dev *dev,
141 + struct oce_mq_cqe *cqe, uint8_t event_type)
142 +{
143 + switch (event_type) {
144 + case ASYNC_EVENT_QOS_SPEED:
145 + oce_async_grp5_qos_speed_process(dev,
146 + (struct oce_async_event_grp5_qos_link_speed *)cqe);
147 + break;
148 + case ASYNC_EVENT_COS_PRIORITY:
149 + oce_async_grp5_cos_priority(dev,
150 + (struct oce_async_event_grp5_cos_priority *)cqe);
151 + break;
152 + case ASYNC_EVENT_PVID_STATE:
153 + oce_async_grp5_pvid_state(dev,
154 + (struct oce_async_event_grp5_pvid_state *)cqe);
155 + break;
156 + default:
157 + break;
158 + }
159 +
160 +}
31 161 /*
32 162 * function to drain a MCQ and process its CQEs
33 163 *
34 164 * dev - software handle to the device
35 165 * cq - pointer to the cq to drain
36 166 *
37 167 * return the number of CQEs processed
38 168 */
39 -uint16_t
40 -oce_drain_mq_cq(void *arg)
169 +void *
170 +oce_drain_mq_cq(void *arg, int arg2, int arg3)
41 171 {
42 172 struct oce_mq_cqe *cqe = NULL;
43 173 uint16_t num_cqe = 0;
44 - link_state_t link_status;
45 - struct oce_async_cqe_link_state *acqe;
46 174 struct oce_mq *mq;
47 175 struct oce_cq *cq;
48 176 struct oce_dev *dev;
177 + uint32_t flags = 0;
49 178
179 + _NOTE(ARGUNUSED(arg2));
180 + _NOTE(ARGUNUSED(arg3));
181 +
50 182 /* do while we do not reach a cqe that is not valid */
51 183 mq = (struct oce_mq *)arg;
52 184 cq = mq->cq;
53 185 dev = mq->parent;
54 - mutex_enter(&mq->lock);
186 +
187 + DBUF_SYNC(cq->ring->dbuf, 0, 0, DDI_DMA_SYNC_FORKERNEL);
55 188 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
56 - while (cqe->u0.dw[3]) {
57 - DW_SWAP(u32ptr(cqe), sizeof (struct oce_mq_cqe));
58 - if (cqe->u0.s.async_event) {
59 - acqe = (struct oce_async_cqe_link_state *)cqe;
60 - if (acqe->u0.s.event_code ==
61 - ASYNC_EVENT_CODE_LINK_STATE) {
62 - /*
63 - * don't care logical or not,
64 - * just check up down
65 - */
66 189
67 - link_status = ((acqe->u0.s.link_status &
68 - ~ASYNC_EVENT_LOGICAL) ==
69 - ASYNC_EVENT_LINK_UP) ?
70 - LINK_STATE_UP: LINK_STATE_DOWN;
71 - mac_link_update(dev->mac_handle, link_status);
72 - dev->link_status = link_status;
73 - dev->link_speed = -1;
74 - }
190 + while (MQ_CQE_VALID(cqe)) {
191 + flags = LE_32(cqe->u0.dw[3]);
192 +
193 + if (flags & MQ_CQE_ASYNC_MASK) {
194 + oce_process_async_events(dev, cqe);
195 + } else if (flags & MQ_CQE_COMPLETED_MASK) {
196 + oce_process_mq_compl(dev, cqe);
197 + atomic_add_32(&mq->mq_free, 1);
75 198 }
76 - cqe->u0.dw[3] = 0;
199 + MQ_CQE_INVALIDATE(cqe);
77 200 RING_GET(cq->ring, 1);
78 201 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
79 202 num_cqe++;
80 203 } /* for all valid CQE */
81 - mutex_exit(&mq->lock);
204 + DBUF_SYNC(cq->ring->dbuf, 0, 0, DDI_DMA_SYNC_FORDEV);
82 205 oce_arm_cq(dev, cq->cq_id, num_cqe, B_TRUE);
83 - return (num_cqe);
206 + return (NULL);
84 207 } /* oce_drain_mq_cq */
85 208
86 209 int
87 210 oce_start_mq(struct oce_mq *mq)
88 211 {
89 212 oce_arm_cq(mq->parent, mq->cq->cq_id, 0, B_TRUE);
90 213 return (0);
91 214 }
92 215
93 216
94 217 void
95 218 oce_clean_mq(struct oce_mq *mq)
96 219 {
97 - struct oce_cq *cq;
98 - struct oce_dev *dev;
99 - uint16_t num_cqe = 0;
100 - struct oce_mq_cqe *cqe = NULL;
101 -
102 - cq = mq->cq;
103 - dev = mq->parent;
104 - cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
105 - while (cqe->u0.dw[3]) {
106 - DW_SWAP(u32ptr(cqe), sizeof (struct oce_mq_cqe));
107 - cqe->u0.dw[3] = 0;
108 - RING_GET(cq->ring, 1);
109 - cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
110 - num_cqe++;
111 - } /* for all valid CQE */
112 - if (num_cqe)
113 - oce_arm_cq(dev, cq->cq_id, num_cqe, B_FALSE);
220 + while (mq->mq_free != mq->cfg.q_len) {
221 + (void) oce_drain_mq_cq(mq, 0, 0);
222 + }
114 223 /* Drain the Event queue now */
115 224 oce_drain_eq(mq->cq->eq);
225 +}
226 +
227 +/* function to issue mbox on mq */
228 +int
229 +oce_issue_mq_mbox(struct oce_dev *dev, struct oce_mbx *mbx)
230 +{
231 + struct oce_mq *mq;
232 + struct oce_mbx *mqe;
233 + struct oce_mbx_ctx *mbctx;
234 + uint32_t mqdb = 0;
235 +
236 + mq = dev->mq;
237 + mbctx = (struct oce_mbx_ctx *)
238 + (uintptr_t)ADDR_64(mbx->tag[1], mbx->tag[0]);
239 +
240 + mutex_enter(&mq->lock);
241 +
242 + if (oce_atomic_reserve(&mq->mq_free, 1) < 0) {
243 + mutex_exit(&mq->lock);
244 + oce_log(dev, CE_NOTE, MOD_CONFIG,
245 + "MQ Entries Free(%d) Retry the command Later",
246 + mq->mq_free);
247 + return (MBX_QUEUE_FULL);
248 + }
249 +
250 + mqe = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
251 + /* save the mqe pointer in ctx required to copy resp back */
252 + mbctx->mqe = mqe;
253 + /* enqueue the command */
254 + bcopy(mbx, mqe, sizeof (struct oce_mbx));
255 + RING_PUT(mq->ring, 1);
256 + /* ring mq doorbell num posted is 1 */
257 + mqdb = (1 << 16) | mq->mq_id;
258 + OCE_DB_WRITE32(dev, PD_MQ_DB, mqdb);
259 + mutex_exit(&mq->lock);
260 + return (MBX_SUCCESS);
261 +}
262 +
263 +void
264 +oce_process_mq_compl(struct oce_dev *dev, struct oce_mq_cqe *cqe)
265 +{
266 + struct oce_mbx_ctx *mbctx;
267 + struct oce_mbx *mbx;
268 +
269 + _NOTE(ARGUNUSED(dev));
270 +
271 + /* retrieve the context pointer */
272 + mbctx = (struct oce_mbx_ctx *)(uintptr_t)ADDR_64(cqe->u0.s.mq_tag[1],
273 + cqe->u0.s.mq_tag[0]);
274 +
275 + if (mbctx == NULL) {
276 + return;
277 + }
278 + mbx = mbctx->mbx;
279 +
280 + mbctx->compl_status = LE_32(cqe->u0.dw[0]);
281 + if (mbctx->compl_status == 0) {
282 + bcopy(mbctx->mqe, mbx, sizeof (struct oce_mbx));
283 + }
284 + mutex_enter(&mbctx->cv_lock);
285 + mbctx->mbx_status = MBX_COMPLETED;
286 + cv_signal(&mbctx->cond_var);
287 + mutex_exit(&mbctx->cv_lock);
288 +
289 +}
290 +
291 +static void
292 +oce_process_async_events(struct oce_dev *dev, struct oce_mq_cqe *cqe)
293 +{
294 + struct oce_async_event_trailer trailer;
295 +
296 + trailer.u0.code = LE_32(cqe->u0.dw[3]);
297 +
298 + switch (trailer.u0.bits.event_code) {
299 + case ASYNC_EVENT_CODE_DEBUG:
300 + oce_process_debug_event(dev, (struct async_event_qnq *)cqe,
301 + trailer.u0.bits.event_type);
302 + break;
303 + case ASYNC_EVENT_CODE_LINK_STATE:
304 + oce_process_link_event(dev,
305 + (struct oce_async_cqe_link_state *)cqe);
306 + break;
307 + case ASYNC_EVENT_CODE_GRP_5:
308 + oce_process_grp5_event(dev, cqe, trailer.u0.bits.event_type);
309 + break;
310 +
311 + default:
312 + break;
313 + }
116 314 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX