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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * nxge_hio_guest.c
29 *
30 * This file manages the virtualization resources for a guest domain.
31 *
32 */
33
34 #include <sys/nxge/nxge_impl.h>
35 #include <sys/nxge/nxge_fzc.h>
36 #include <sys/nxge/nxge_rxdma.h>
37 #include <sys/nxge/nxge_txdma.h>
38 #include <sys/nxge/nxge_hio.h>
39
40 /*
41 * nxge_guest_regs_map
42 *
43 * Map in a guest domain's register set(s).
44 *
45 * Arguments:
46 * nxge
47 *
48 * Notes:
49 * Note that we set <is_vraddr> to TRUE.
50 *
51 * Context:
52 * Guest domain
53 */
54 static ddi_device_acc_attr_t nxge_guest_register_access_attributes = {
55 DDI_DEVICE_ATTR_V0,
56 DDI_STRUCTURE_LE_ACC,
57 DDI_STRICTORDER_ACC,
58 };
59
60 int
nxge_guest_regs_map(nxge_t * nxge)61 nxge_guest_regs_map(nxge_t *nxge)
62 {
63 dev_regs_t *regs;
64 off_t regsize;
65 int rv;
66
67 NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_guest_regs_map"));
68
69 /* So we can allocate properly-aligned memory. */
70 nxge->niu_type = N2_NIU; /* Version 1.0 only */
71 nxge->function_num = nxge->instance; /* HIOXXX Looking for ideas. */
72
73 nxge->dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP);
74 regs = nxge->dev_regs;
75
76 if ((rv = ddi_dev_regsize(nxge->dip, 0, ®size)) != DDI_SUCCESS) {
77 NXGE_ERROR_MSG((nxge, HIO_CTL, "ddi_dev_regsize() failed"));
78 return (NXGE_ERROR);
79 }
80
81 rv = ddi_regs_map_setup(nxge->dip, 0, (caddr_t *)®s->nxge_regp, 0, 0,
82 &nxge_guest_register_access_attributes, ®s->nxge_regh);
83
84 if (rv != DDI_SUCCESS) {
85 NXGE_ERROR_MSG((nxge, HIO_CTL, "ddi_regs_map_setup() failed"));
86 return (NXGE_ERROR);
87 }
88
89 nxge->npi_handle.regh = regs->nxge_regh;
90 nxge->npi_handle.regp = (npi_reg_ptr_t)regs->nxge_regp;
91 nxge->npi_handle.is_vraddr = B_TRUE;
92 nxge->npi_handle.function.instance = nxge->instance;
93 nxge->npi_handle.function.function = nxge->function_num;
94 nxge->npi_handle.nxgep = (void *)nxge;
95
96 /* NPI_REG_ADD_HANDLE_SET() */
97 nxge->npi_reg_handle.regh = regs->nxge_regh;
98 nxge->npi_reg_handle.regp = (npi_reg_ptr_t)regs->nxge_regp;
99 nxge->npi_reg_handle.is_vraddr = B_TRUE;
100 nxge->npi_reg_handle.function.instance = nxge->instance;
101 nxge->npi_reg_handle.function.function = nxge->function_num;
102 nxge->npi_reg_handle.nxgep = (void *)nxge;
103
104 /* NPI_VREG_ADD_HANDLE_SET() */
105 nxge->npi_vreg_handle.regh = regs->nxge_regh;
106 nxge->npi_vreg_handle.regp = (npi_reg_ptr_t)regs->nxge_regp;
107 nxge->npi_vreg_handle.is_vraddr = B_TRUE;
108 nxge->npi_vreg_handle.function.instance = nxge->instance;
109 nxge->npi_vreg_handle.function.function = nxge->function_num;
110 nxge->npi_vreg_handle.nxgep = (void *)nxge;
111
112 regs->nxge_vir_regp = regs->nxge_regp;
113 regs->nxge_vir_regh = regs->nxge_regh;
114
115 /*
116 * We do NOT set the PCI, MSI-X, 2nd Virtualization,
117 * or FCODE reg variables.
118 */
119
120 NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_guest_regs_map"));
121
122 return (NXGE_OK);
123 }
124
125 void
nxge_guest_regs_map_free(nxge_t * nxge)126 nxge_guest_regs_map_free(
127 nxge_t *nxge)
128 {
129 NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_guest_regs_map_free"));
130
131 if (nxge->dev_regs) {
132 if (nxge->dev_regs->nxge_regh) {
133 NXGE_DEBUG_MSG((nxge, DDI_CTL,
134 "==> nxge_unmap_regs: device registers"));
135 ddi_regs_map_free(&nxge->dev_regs->nxge_regh);
136 nxge->dev_regs->nxge_regh = NULL;
137 }
138 kmem_free(nxge->dev_regs, sizeof (dev_regs_t));
139 nxge->dev_regs = 0;
140 }
141
142 NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_guest_regs_map_free"));
143 }
144
145 #if defined(sun4v)
146
147 /*
148 * -------------------------------------------------------------
149 * Local prototypes
150 * -------------------------------------------------------------
151 */
152 static nxge_hio_dc_t *nxge_guest_dc_alloc(
153 nxge_t *, nxge_hio_vr_t *, nxge_grp_type_t);
154
155 static void res_map_parse(nxge_t *, nxge_grp_type_t, uint64_t);
156 static void nxge_check_guest_state(nxge_hio_vr_t *);
157
158 /*
159 * nxge_hio_vr_add
160 *
161 * If we have been given a virtualization region (VR),
162 * then initialize it.
163 *
164 * Arguments:
165 * nxge
166 *
167 * Notes:
168 *
169 * Context:
170 * Guest domain
171 */
172 int
nxge_hio_vr_add(nxge_t * nxge)173 nxge_hio_vr_add(nxge_t *nxge)
174 {
175 extern nxge_status_t nxge_mac_register(p_nxge_t);
176
177 nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
178 nxge_hio_vr_t *vr;
179 nxge_hio_dc_t *dc;
180 int *reg_val;
181 uint_t reg_len;
182 uint8_t vr_index;
183 nxhv_vr_fp_t *fp;
184 uint64_t vr_address, vr_size;
185 uint32_t cookie;
186 nxhv_dc_fp_t *tx, *rx;
187 uint64_t tx_map, rx_map;
188 uint64_t hv_rv;
189 int i;
190 nxge_status_t status;
191
192 NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_vr_add"));
193
194 if (nhd->type == NXGE_HIO_TYPE_SERVICE) {
195 /*
196 * Can't add VR to the service domain from which we came.
197 */
198 ASSERT(nhd->type == NXGE_HIO_TYPE_GUEST);
199 return (DDI_FAILURE);
200 }
201
202 /*
203 * Get our HV cookie.
204 */
205 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxge->dip,
206 0, "reg", ®_val, ®_len) != DDI_PROP_SUCCESS) {
207 NXGE_DEBUG_MSG((nxge, VPD_CTL, "`reg' property not found"));
208 return (DDI_FAILURE);
209 }
210
211 cookie = (uint32_t)(reg_val[0]);
212 ddi_prop_free(reg_val);
213
214 fp = &nhd->hio.vr;
215 hv_rv = (*fp->getinfo)(cookie, &vr_address, &vr_size);
216 if (hv_rv != 0) {
217 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
218 "vr->getinfo() failed"));
219 return (DDI_FAILURE);
220 }
221
222 /*
223 * In the guest domain, we can use any VR data structure
224 * we want, because we're not supposed to know which VR
225 * the service domain has allocated to us.
226 *
227 * In the current version, the least significant nybble of
228 * the cookie is the VR region, but that could change
229 * very easily.
230 *
231 * In the future, a guest may have more than one VR allocated
232 * to it, which is why we go through this exercise.
233 */
234 MUTEX_ENTER(&nhd->lock);
235 for (vr_index = 0; vr_index < FUNC_VIR_MAX; vr_index++) {
236 if (nhd->vr[vr_index].nxge == 0) {
237 nhd->vr[vr_index].nxge = (uintptr_t)nxge;
238 break;
239 }
240 }
241 MUTEX_EXIT(&nhd->lock);
242
243 if (vr_index == FUNC_VIR_MAX) {
244 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_hio_vr_add "
245 "no VRs available"));
246 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
247 "nxge_hio_vr_add(%d): cookie(0x%x)\n",
248 nxge->instance, cookie));
249 return (DDI_FAILURE);
250 }
251
252 vr = &nhd->vr[vr_index];
253
254 vr->nxge = (uintptr_t)nxge;
255 vr->cookie = (uint32_t)cookie;
256 vr->address = vr_address;
257 vr->size = vr_size;
258 vr->region = vr_index;
259
260 /*
261 * This is redundant data, but useful nonetheless. It helps
262 * us to keep track of which RDCs & TDCs belong to us.
263 */
264 if (nxge->tx_set.lg.count == 0)
265 (void) nxge_grp_add(nxge, NXGE_TRANSMIT_GROUP);
266 if (nxge->rx_set.lg.count == 0)
267 (void) nxge_grp_add(nxge, NXGE_RECEIVE_GROUP);
268
269 /*
270 * See nxge_intr.c.
271 */
272 if (nxge_hio_intr_init(nxge) != NXGE_OK) {
273 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
274 "nxge_hio_intr_init() failed"));
275 return (DDI_FAILURE);
276 }
277
278 /*
279 * Now we find out which RDCs & TDCs have been allocated to us.
280 */
281 tx = &nhd->hio.tx;
282 if (tx->get_map) {
283 /*
284 * The map we get back is a bitmap of the
285 * virtual Tx DMA channels we own -
286 * they are NOT real channel numbers.
287 */
288 hv_rv = (*tx->get_map)(vr->cookie, &tx_map);
289 if (hv_rv != 0) {
290 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
291 "tx->get_map() failed"));
292 return (DDI_FAILURE);
293 }
294 res_map_parse(nxge, NXGE_TRANSMIT_GROUP, tx_map);
295
296 /*
297 * For each channel, mark these two fields
298 * while we have the VR data structure.
299 */
300 for (i = 0; i < VP_CHANNEL_MAX; i++) {
301 if ((1 << i) & tx_map) {
302 dc = nxge_guest_dc_alloc(nxge, vr,
303 NXGE_TRANSMIT_GROUP);
304 if (dc == 0) {
305 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
306 "DC add failed"));
307 return (DDI_FAILURE);
308 }
309 dc->channel = (nxge_channel_t)i;
310 }
311 }
312 }
313
314 rx = &nhd->hio.rx;
315 if (rx->get_map) {
316 /*
317 * I repeat, the map we get back is a bitmap of
318 * the virtual Rx DMA channels we own -
319 * they are NOT real channel numbers.
320 */
321 hv_rv = (*rx->get_map)(vr->cookie, &rx_map);
322 if (hv_rv != 0) {
323 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
324 "rx->get_map() failed"));
325 return (DDI_FAILURE);
326 }
327 res_map_parse(nxge, NXGE_RECEIVE_GROUP, rx_map);
328
329 /*
330 * For each channel, mark these two fields
331 * while we have the VR data structure.
332 */
333 for (i = 0; i < VP_CHANNEL_MAX; i++) {
334 if ((1 << i) & rx_map) {
335 dc = nxge_guest_dc_alloc(nxge, vr,
336 NXGE_RECEIVE_GROUP);
337 if (dc == 0) {
338 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
339 "DC add failed"));
340 return (DDI_FAILURE);
341 }
342 dc->channel = (nxge_channel_t)i;
343 }
344 }
345 }
346
347 status = nxge_mac_register(nxge);
348 if (status != NXGE_OK) {
349 cmn_err(CE_WARN, "nxge(%d): nxge_mac_register failed\n",
350 nxge->instance);
351 return (DDI_FAILURE);
352 }
353
354 nxge->hio_vr = vr; /* For faster lookups. */
355
356 NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_vr_add"));
357
358 return (DDI_SUCCESS);
359 }
360
361 /*
362 * nxge_guest_dc_alloc
363 *
364 * Find a free nxge_hio_dc_t data structure.
365 *
366 * Arguments:
367 * nxge
368 * type TRANSMIT or RECEIVE.
369 *
370 * Notes:
371 *
372 * Context:
373 * Guest domain
374 */
375 nxge_hio_dc_t *
nxge_guest_dc_alloc(nxge_t * nxge,nxge_hio_vr_t * vr,nxge_grp_type_t type)376 nxge_guest_dc_alloc(
377 nxge_t *nxge,
378 nxge_hio_vr_t *vr,
379 nxge_grp_type_t type)
380 {
381 nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
382 nxge_hio_dc_t *dc;
383 int limit, i;
384
385 /*
386 * In the guest domain, there may be more than one VR.
387 * each one of which will be using the same slots, or
388 * virtual channel numbers. So the <nhd>'s rdc & tdc
389 * tables must be shared.
390 */
391 if (type == NXGE_TRANSMIT_GROUP) {
392 dc = &nhd->tdc[0];
393 limit = NXGE_MAX_TDCS;
394 } else {
395 dc = &nhd->rdc[0];
396 limit = NXGE_MAX_RDCS;
397 }
398
399 MUTEX_ENTER(&nhd->lock);
400 for (i = 0; i < limit; i++, dc++) {
401 if (dc->vr == 0) {
402 dc->vr = vr;
403 dc->cookie = vr->cookie;
404 MUTEX_EXIT(&nhd->lock);
405 return (dc);
406 }
407 }
408 MUTEX_EXIT(&nhd->lock);
409
410 return (0);
411 }
412
413 int
nxge_hio_get_dc_htable_idx(nxge_t * nxge,vpc_type_t type,uint32_t channel)414 nxge_hio_get_dc_htable_idx(nxge_t *nxge, vpc_type_t type, uint32_t channel)
415 {
416 nxge_hio_dc_t *dc;
417
418 ASSERT(isLDOMguest(nxge));
419
420 dc = nxge_grp_dc_find(nxge, type, channel);
421 if (dc == NULL)
422 return (-1);
423
424 return (dc->ldg.vector);
425 }
426
427 /*
428 * res_map_parse
429 *
430 * Parse a resource map. The resources are DMA channels, receive
431 * or transmit, depending on <type>.
432 *
433 * Arguments:
434 * nxge
435 * type Transmit or receive.
436 * res_map The resource map to parse.
437 *
438 * Notes:
439 *
440 * Context:
441 * Guest domain
442 */
443 void
res_map_parse(nxge_t * nxge,nxge_grp_type_t type,uint64_t res_map)444 res_map_parse(
445 nxge_t *nxge,
446 nxge_grp_type_t type,
447 uint64_t res_map)
448 {
449 uint8_t slots, mask, slot;
450 int first, count;
451
452 nxge_hw_pt_cfg_t *hardware;
453 nxge_grp_t *group;
454
455 /* Slots are numbered 0 - 7. */
456 slots = (uint8_t)(res_map & 0xff);
457
458 /* Count the number of bits in the bitmap. */
459 for (slot = 0, count = 0, mask = 1; slot < 8; slot++) {
460 if (slots & mask)
461 count++;
462 if (count == 1)
463 first = slot;
464 mask <<= 1;
465 }
466
467 hardware = &nxge->pt_config.hw_config;
468 group = (type == NXGE_TRANSMIT_GROUP) ?
469 nxge->tx_set.group[0] : nxge->rx_set.group[0];
470
471 /*
472 * A guest domain has one Tx & one Rx group, so far.
473 * In the future, there may be more than one.
474 */
475 if (type == NXGE_TRANSMIT_GROUP) {
476 nxge_dma_pt_cfg_t *port = &nxge->pt_config;
477 nxge_tdc_grp_t *tdc_grp = &nxge->pt_config.tdc_grps[0];
478
479 hardware->tdc.start = first;
480 hardware->tdc.count = count;
481 hardware->tdc.owned = count;
482
483 tdc_grp->start_tdc = first;
484 tdc_grp->max_tdcs = (uint8_t)count;
485 tdc_grp->grp_index = group->index;
486 tdc_grp->map = slots;
487
488 group->map = slots;
489
490 /*
491 * Pointless in a guest domain. This bitmap is used
492 * in only one place: nxge_txc_init(),
493 * a service-domain-only function.
494 */
495 port->tx_dma_map = slots;
496
497 nxge->tx_set.owned.map |= slots;
498 } else {
499 nxge_rdc_grp_t *rdc_grp = &nxge->pt_config.rdc_grps[0];
500
501 hardware->start_rdc = first;
502 hardware->max_rdcs = count;
503
504 rdc_grp->start_rdc = (uint8_t)first;
505 rdc_grp->max_rdcs = (uint8_t)count;
506 rdc_grp->def_rdc = (uint8_t)first;
507
508 rdc_grp->map = slots;
509 group->map = slots;
510
511 nxge->rx_set.owned.map |= slots;
512 }
513 }
514
515 /*
516 * nxge_hio_vr_release
517 *
518 * Release a virtualization region (VR).
519 *
520 * Arguments:
521 * nxge
522 *
523 * Notes:
524 * We must uninitialize all DMA channels associated with the VR, too.
525 *
526 * The service domain will re-initialize these DMA channels later.
527 * See nxge_hio.c:nxge_hio_share_free() for details.
528 *
529 * Context:
530 * Guest domain
531 */
532 int
nxge_hio_vr_release(nxge_t * nxge)533 nxge_hio_vr_release(nxge_t *nxge)
534 {
535 nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
536 int vr_index;
537
538 NXGE_DEBUG_MSG((nxge, MEM2_CTL, "==> nxge_hio_vr_release"));
539
540 if (nxge->hio_vr == NULL) {
541 return (NXGE_OK);
542 }
543
544 /*
545 * Uninitialize interrupts.
546 */
547 nxge_hio_intr_uninit(nxge);
548
549 /*
550 * Uninitialize the receive DMA channels.
551 */
552 nxge_uninit_rxdma_channels(nxge);
553
554 /*
555 * Uninitialize the transmit DMA channels.
556 */
557 nxge_uninit_txdma_channels(nxge);
558
559 /*
560 * Remove both groups. Assumption: only two groups!
561 */
562 if (nxge->rx_set.group[0] != NULL)
563 nxge_grp_remove(nxge, nxge->rx_set.group[0]);
564 if (nxge->tx_set.group[0] != NULL)
565 nxge_grp_remove(nxge, nxge->tx_set.group[0]);
566
567 NXGE_DEBUG_MSG((nxge, MEM2_CTL, "<== nxge_hio_vr_release"));
568
569 /*
570 * Clean up.
571 */
572 MUTEX_ENTER(&nhd->lock);
573 for (vr_index = 0; vr_index < FUNC_VIR_MAX; vr_index++) {
574 if (nhd->vr[vr_index].nxge == (uintptr_t)nxge) {
575 nhd->vr[vr_index].nxge = NULL;
576 break;
577 }
578 }
579 MUTEX_EXIT(&nhd->lock);
580
581 return (NXGE_OK);
582 }
583
584 #if defined(NIU_LP_WORKAROUND)
585 /*
586 * nxge_tdc_lp_conf
587 *
588 * Configure the logical pages for a TDC.
589 *
590 * Arguments:
591 * nxge
592 * channel The TDC to configure.
593 *
594 * Notes:
595 *
596 * Context:
597 * Guest domain
598 */
599 nxge_status_t
nxge_tdc_lp_conf(p_nxge_t nxge,int channel)600 nxge_tdc_lp_conf(
601 p_nxge_t nxge,
602 int channel)
603 {
604 nxge_hio_dc_t *dc;
605 nxge_dma_common_t *data;
606 nxge_dma_common_t *control;
607 tx_ring_t *ring;
608
609 uint64_t hv_rv;
610 uint64_t ra, size;
611
612 NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_tdc_lp_conf"));
613
614 ring = nxge->tx_rings->rings[channel];
615
616 if (ring->hv_set) {
617 /* This shouldn't happen. */
618 return (NXGE_OK);
619 }
620
621 if (!(dc = nxge_grp_dc_find(nxge, VP_BOUND_TX, channel)))
622 return (NXGE_ERROR);
623
624 /*
625 * Initialize logical page 0 for data buffers.
626 *
627 * <orig_ioaddr_pp> & <orig_alength> are initialized in
628 * nxge_main.c:nxge_dma_mem_alloc().
629 */
630 data = nxge->tx_buf_pool_p->dma_buf_pool_p[channel];
631 ring->hv_tx_buf_base_ioaddr_pp = (uint64_t)data->orig_ioaddr_pp;
632 ring->hv_tx_buf_ioaddr_size = (uint64_t)data->orig_alength;
633
634 hv_rv = hv_niu_vrtx_logical_page_conf(dc->cookie,
635 (uint64_t)channel, 0,
636 ring->hv_tx_buf_base_ioaddr_pp,
637 ring->hv_tx_buf_ioaddr_size);
638
639 if (hv_rv != 0) {
640 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
641 "<== nxge_tdc_lp_conf: channel %d "
642 "(page 0 data buf) hv: %d "
643 "ioaddr_pp $%p size 0x%llx ",
644 channel, hv_rv,
645 ring->hv_tx_buf_base_ioaddr_pp,
646 ring->hv_tx_buf_ioaddr_size));
647 return (NXGE_ERROR | hv_rv);
648 }
649
650 ra = size = 0;
651 hv_rv = hv_niu_vrtx_logical_page_info(dc->cookie,
652 (uint64_t)channel, 0, &ra, &size);
653
654 NXGE_DEBUG_MSG((nxge, HIO_CTL,
655 "==> nxge_tdc_lp_conf: channel %d "
656 "(page 0 data buf) hv_rv 0x%llx "
657 "set ioaddr_pp $%p set size 0x%llx "
658 "get ra ioaddr_pp $%p get size 0x%llx ",
659 channel, hv_rv, ring->hv_tx_buf_base_ioaddr_pp,
660 ring->hv_tx_buf_ioaddr_size, ra, size));
661
662 /*
663 * Initialize logical page 1 for control buffers.
664 */
665 control = nxge->tx_cntl_pool_p->dma_buf_pool_p[channel];
666 ring->hv_tx_cntl_base_ioaddr_pp = (uint64_t)control->orig_ioaddr_pp;
667 ring->hv_tx_cntl_ioaddr_size = (uint64_t)control->orig_alength;
668
669 hv_rv = hv_niu_vrtx_logical_page_conf(dc->cookie,
670 (uint64_t)channel, (uint64_t)1,
671 ring->hv_tx_cntl_base_ioaddr_pp,
672 ring->hv_tx_cntl_ioaddr_size);
673
674 if (hv_rv != 0) {
675 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
676 "<== nxge_tdc_lp_conf: channel %d "
677 "(page 1 cntl buf) hv_rv 0x%llx "
678 "ioaddr_pp $%p size 0x%llx ",
679 channel, hv_rv,
680 ring->hv_tx_cntl_base_ioaddr_pp,
681 ring->hv_tx_cntl_ioaddr_size));
682 return (NXGE_ERROR | hv_rv);
683 }
684
685 ra = size = 0;
686 hv_rv = hv_niu_vrtx_logical_page_info(dc->cookie,
687 (uint64_t)channel, (uint64_t)1, &ra, &size);
688
689 NXGE_DEBUG_MSG((nxge, HIO_CTL,
690 "==> nxge_tdc_lp_conf: channel %d "
691 "(page 1 cntl buf) hv_rv 0x%llx "
692 "set ioaddr_pp $%p set size 0x%llx "
693 "get ra ioaddr_pp $%p get size 0x%llx ",
694 channel, hv_rv, ring->hv_tx_cntl_base_ioaddr_pp,
695 ring->hv_tx_cntl_ioaddr_size, ra, size));
696
697 ring->hv_set = B_TRUE;
698
699 NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_tdc_lp_conf"));
700
701 return (NXGE_OK);
702 }
703
704 /*
705 * nxge_rdc_lp_conf
706 *
707 * Configure an RDC's logical pages.
708 *
709 * Arguments:
710 * nxge
711 * channel The RDC to configure.
712 *
713 * Notes:
714 *
715 * Context:
716 * Guest domain
717 */
718 nxge_status_t
nxge_rdc_lp_conf(p_nxge_t nxge,int channel)719 nxge_rdc_lp_conf(
720 p_nxge_t nxge,
721 int channel)
722 {
723 nxge_hio_dc_t *dc;
724 nxge_dma_common_t *data;
725 nxge_dma_common_t *control;
726 rx_rbr_ring_t *ring;
727
728 uint64_t hv_rv;
729 uint64_t ra, size;
730
731 NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_rdc_lp_conf"));
732
733 ring = nxge->rx_rbr_rings->rbr_rings[channel];
734
735 if (ring->hv_set) {
736 return (NXGE_OK);
737 }
738
739 if (!(dc = nxge_grp_dc_find(nxge, VP_BOUND_RX, channel)))
740 return (NXGE_ERROR);
741
742 /*
743 * Initialize logical page 0 for data buffers.
744 *
745 * <orig_ioaddr_pp> & <orig_alength> are initialized in
746 * nxge_main.c:nxge_dma_mem_alloc().
747 */
748 data = nxge->rx_buf_pool_p->dma_buf_pool_p[channel];
749 ring->hv_rx_buf_base_ioaddr_pp = (uint64_t)data->orig_ioaddr_pp;
750 ring->hv_rx_buf_ioaddr_size = (uint64_t)data->orig_alength;
751
752 hv_rv = hv_niu_vrrx_logical_page_conf(dc->cookie,
753 (uint64_t)channel, 0,
754 ring->hv_rx_buf_base_ioaddr_pp,
755 ring->hv_rx_buf_ioaddr_size);
756
757 if (hv_rv != 0) {
758 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
759 "<== nxge_rdc_lp_conf: channel %d "
760 "(page 0 data buf) hv_rv 0x%llx "
761 "ioaddr_pp $%p size 0x%llx ",
762 channel, hv_rv,
763 ring->hv_rx_buf_base_ioaddr_pp,
764 ring->hv_rx_buf_ioaddr_size));
765 return (NXGE_ERROR | hv_rv);
766 }
767
768 ra = size = 0;
769 hv_rv = hv_niu_vrrx_logical_page_info(dc->cookie,
770 (uint64_t)channel, 0, &ra, &size);
771
772 NXGE_DEBUG_MSG((nxge, HIO_CTL,
773 "==> nxge_rdc_lp_conf: channel %d "
774 "(page 0 data buf) hv_rv 0x%llx "
775 "set ioaddr_pp $%p set size 0x%llx "
776 "get ra ioaddr_pp $%p get size 0x%llx ",
777 channel, hv_rv, ring->hv_rx_buf_base_ioaddr_pp,
778 ring->hv_rx_buf_ioaddr_size, ra, size));
779
780 /*
781 * Initialize logical page 1 for control buffers.
782 */
783 control = nxge->rx_cntl_pool_p->dma_buf_pool_p[channel];
784 ring->hv_rx_cntl_base_ioaddr_pp = (uint64_t)control->orig_ioaddr_pp;
785 ring->hv_rx_cntl_ioaddr_size = (uint64_t)control->orig_alength;
786
787 hv_rv = hv_niu_vrrx_logical_page_conf(dc->cookie,
788 (uint64_t)channel, (uint64_t)1,
789 ring->hv_rx_cntl_base_ioaddr_pp,
790 ring->hv_rx_cntl_ioaddr_size);
791
792 if (hv_rv != 0) {
793 NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
794 "<== nxge_rdc_lp_conf: channel %d "
795 "(page 1 cntl buf) hv_rv 0x%llx "
796 "ioaddr_pp $%p size 0x%llx ",
797 channel, hv_rv,
798 ring->hv_rx_cntl_base_ioaddr_pp,
799 ring->hv_rx_cntl_ioaddr_size));
800 return (NXGE_ERROR | hv_rv);
801 }
802
803 ra = size = 0;
804 hv_rv = hv_niu_vrrx_logical_page_info(dc->cookie,
805 (uint64_t)channel, (uint64_t)1, &ra, &size);
806
807 NXGE_DEBUG_MSG((nxge, HIO_CTL,
808 "==> nxge_rdc_lp_conf: channel %d "
809 "(page 1 cntl buf) hv_rv 0x%llx "
810 "set ioaddr_pp $%p set size 0x%llx "
811 "get ra ioaddr_pp $%p get size 0x%llx ",
812 channel, hv_rv, ring->hv_rx_cntl_base_ioaddr_pp,
813 ring->hv_rx_cntl_ioaddr_size, ra, size));
814
815 ring->hv_set = B_TRUE;
816
817 NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_rdc_lp_conf"));
818
819 return (NXGE_OK);
820 }
821 #endif /* defined(NIU_LP_WORKAROUND) */
822
823 /*
824 * This value is in milliseconds.
825 */
826 #define NXGE_GUEST_TIMER 500 /* 1/2 second, for now */
827
828 /*
829 * nxge_hio_start_timer
830 *
831 * Start the timer which checks for Tx hangs.
832 *
833 * Arguments:
834 * nxge
835 *
836 * Notes:
837 * This function is called from nxge_attach().
838 *
839 * This function kicks off the guest domain equivalent of
840 * nxge_check_hw_state(). It is called only once, from attach.
841 *
842 * Context:
843 * Guest domain
844 */
845 void
nxge_hio_start_timer(nxge_t * nxge)846 nxge_hio_start_timer(
847 nxge_t *nxge)
848 {
849 nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
850 nxge_hio_vr_t *vr;
851 int region;
852
853 NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_timer_start"));
854
855 MUTEX_ENTER(&nhd->lock);
856
857 /*
858 * Find our VR data structure. (We are currently assuming
859 * one VR per guest domain. That may change in the future.)
860 */
861 for (region = FUNC0_VIR0; region < NXGE_VR_SR_MAX; region++) {
862 if (nhd->vr[region].nxge == (uintptr_t)nxge)
863 break;
864 }
865
866 MUTEX_EXIT(&nhd->lock);
867
868 if (region == NXGE_VR_SR_MAX) {
869 return;
870 }
871
872 vr = (nxge_hio_vr_t *)&nhd->vr[region];
873
874 nxge->nxge_timerid = timeout((void(*)(void *))nxge_check_guest_state,
875 (void *)vr, drv_usectohz(1000 * NXGE_GUEST_TIMER));
876
877 NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_timer_start"));
878 }
879
880 /*
881 * nxge_check_guest_state
882 *
883 * Essentially, check for Tx hangs. In the future, if we are
884 * polling the hardware, we may do so here.
885 *
886 * Arguments:
887 * vr The virtualization region (VR) data structure.
888 *
889 * Notes:
890 * This function is the guest domain equivalent of
891 * nxge_check_hw_state(). Since we have no hardware to
892 * check, we simply call nxge_check_tx_hang().
893 *
894 * Context:
895 * Guest domain
896 */
897 void
nxge_check_guest_state(nxge_hio_vr_t * vr)898 nxge_check_guest_state(
899 nxge_hio_vr_t *vr)
900 {
901 nxge_t *nxge = (nxge_t *)vr->nxge;
902
903 NXGE_DEBUG_MSG((nxge, SYSERR_CTL, "==> nxge_check_guest_state"));
904
905 MUTEX_ENTER(nxge->genlock);
906 nxge->nxge_timerid = 0;
907
908 if (nxge->nxge_mac_state == NXGE_MAC_STARTED) {
909 nxge_check_tx_hang(nxge);
910
911 nxge->nxge_timerid = timeout((void(*)(void *))
912 nxge_check_guest_state, (caddr_t)vr,
913 drv_usectohz(1000 * NXGE_GUEST_TIMER));
914 }
915
916 nxge_check_guest_state_exit:
917 MUTEX_EXIT(nxge->genlock);
918 NXGE_DEBUG_MSG((nxge, SYSERR_CTL, "<== nxge_check_guest_state"));
919 }
920
921 nxge_status_t
nxge_hio_rdc_intr_arm(p_nxge_t nxge,boolean_t arm)922 nxge_hio_rdc_intr_arm(p_nxge_t nxge, boolean_t arm)
923 {
924 nxge_grp_t *group;
925 uint32_t channel;
926 nxge_hio_dc_t *dc;
927 nxge_ldg_t *ldgp;
928
929 /*
930 * Validate state of guest interface before
931 * proceeeding.
932 */
933 if (!isLDOMguest(nxge))
934 return (NXGE_ERROR);
935 if (nxge->nxge_mac_state != NXGE_MAC_STARTED)
936 return (NXGE_ERROR);
937
938 /*
939 * In guest domain, always and only dealing with
940 * group 0 for an instance of nxge.
941 */
942 group = nxge->rx_set.group[0];
943
944 /*
945 * Look to arm the the RDCs for the group.
946 */
947 for (channel = 0; channel < NXGE_MAX_RDCS; channel++) {
948 if ((1 << channel) & group->map) {
949 /*
950 * Get the RDC.
951 */
952 dc = nxge_grp_dc_find(nxge, VP_BOUND_RX, channel);
953 if (dc == NULL)
954 return (NXGE_ERROR);
955
956 /*
957 * Get the RDC's ldg group.
958 */
959 ldgp = &nxge->ldgvp->ldgp[dc->ldg.vector];
960 if (ldgp == NULL)
961 return (NXGE_ERROR);
962
963 /*
964 * Set the state of the group.
965 */
966 ldgp->arm = arm;
967
968 nxge_hio_ldgimgn(nxge, ldgp);
969 }
970 }
971
972 return (NXGE_OK);
973 }
974
975 nxge_status_t
nxge_hio_rdc_enable(p_nxge_t nxge)976 nxge_hio_rdc_enable(p_nxge_t nxge)
977 {
978 nxge_grp_t *group;
979 npi_handle_t handle;
980 uint32_t channel;
981 npi_status_t rval;
982
983 /*
984 * Validate state of guest interface before
985 * proceeeding.
986 */
987 if (!isLDOMguest(nxge))
988 return (NXGE_ERROR);
989 if (nxge->nxge_mac_state != NXGE_MAC_STARTED)
990 return (NXGE_ERROR);
991
992 /*
993 * In guest domain, always and only dealing with
994 * group 0 for an instance of nxge.
995 */
996 group = nxge->rx_set.group[0];
997
998 /*
999 * Get the PIO handle.
1000 */
1001 handle = NXGE_DEV_NPI_HANDLE(nxge);
1002
1003 for (channel = 0; channel < NXGE_MAX_RDCS; channel++) {
1004 /*
1005 * If this channel is in the map, then enable
1006 * it.
1007 */
1008 if ((1 << channel) & group->map) {
1009 /*
1010 * Enable the RDC and clear the empty bit.
1011 */
1012 rval = npi_rxdma_cfg_rdc_enable(handle, channel);
1013 if (rval != NPI_SUCCESS)
1014 return (NXGE_ERROR);
1015
1016 (void) npi_rxdma_channel_rbr_empty_clear(handle,
1017 channel);
1018 }
1019 }
1020
1021 return (NXGE_OK);
1022 }
1023 #endif /* defined(sun4v) */
1024