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 driver entry points
29  * and related helper functions
30  */
31 
32 #include <oce_impl.h>
33 #include <oce_ioctl.h>
34 
35 /* array of properties supported by this driver */
36 mac_priv_prop_t oce_priv_props[] = {
37 	{"_tx_ring_size", MAC_PROP_PERM_READ},
38 	{"_tx_bcopy_limit", MAC_PROP_PERM_RW},
39 	{"_rx_ring_size", MAC_PROP_PERM_READ},
40 };
41 uint32_t oce_num_props = sizeof (oce_priv_props) / sizeof (mac_priv_prop_t);
42 
43 
44 /* ---[ static function declarations ]----------------------------------- */
45 static int oce_power10(int power);
46 static int oce_set_priv_prop(struct oce_dev *dev, const char *name,
47     uint_t size, const void *val);
48 
49 static int oce_get_priv_prop(struct oce_dev *dev, const char *name,
50     uint_t flags, uint_t size, void *val);
51 
52 /* ---[ GLD entry points ]----------------------------------------------- */
53 int
54 oce_m_start(void *arg)
55 {
56 	struct oce_dev *dev = arg;
57 	int ret;
58 
59 	mutex_enter(&dev->dev_lock);
60 
61 	if (dev->state & STATE_MAC_STARTED) {
62 		mutex_exit(&dev->dev_lock);
63 		return (0);
64 	}
65 
66 	if (dev->suspended) {
67 		mutex_exit(&dev->dev_lock);
68 		return (EIO);
69 	}
70 
71 	if (oce_fm_check_acc_handle(dev, dev->db_handle)) {
72 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
73 		mutex_exit(&dev->dev_lock);
74 		return (EIO);
75 	}
76 
77 	if (oce_fm_check_acc_handle(dev, dev->csr_handle)) {
78 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
79 		mutex_exit(&dev->dev_lock);
80 		return (EIO);
81 	}
82 
83 	if (oce_fm_check_acc_handle(dev, dev->cfg_handle)) {
84 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
85 		mutex_exit(&dev->dev_lock);
86 		return (EIO);
87 	}
88 
89 	ret = oce_start(dev);
90 	if (ret != DDI_SUCCESS) {
91 		mutex_exit(&dev->dev_lock);
92 		return (EIO);
93 	}
94 
95 	dev->state |= STATE_MAC_STARTED;
96 	mutex_exit(&dev->dev_lock);
97 
98 	/* enable interrupts */
99 	oce_ei(dev);
100 
101 	return (DDI_SUCCESS);
102 }
103 
104 int
105 oce_start(struct oce_dev *dev)
106 {
107 	int qidx = 0;
108 	int ret;
109 
110 	ret = oce_hw_init(dev);
111 	if (ret != DDI_SUCCESS) {
112 		oce_log(dev, CE_WARN, MOD_CONFIG,
113 		    "Hardware initialization failed with %d", ret);
114 		return (ret);
115 	}
116 
117 	ret = oce_chip_hw_init(dev);
118 	if (ret != DDI_SUCCESS) {
119 		oce_log(dev, CE_WARN, MOD_CONFIG,
120 		    "Chip initialization failed: %d", ret);
121 		oce_hw_fini(dev);
122 		return (ret);
123 	}
124 	ret = oce_setup_handlers(dev);
125 	if (ret != DDI_SUCCESS) {
126 		oce_log(dev, CE_WARN, MOD_CONFIG,
127 		    "Interrupt handler setup failed with %d", ret);
128 		oce_chip_hw_fini(dev);
129 		oce_hw_fini(dev);
130 		return (ret);
131 	}
132 
133 	(void) oce_start_wq(dev->wq[0]);
134 	(void) oce_start_rq(dev->rq[0]);
135 
136 	/* get link status */
137 	(void) oce_get_link_status(dev, &dev->link);
138 
139 	if (dev->link.mac_speed == PHY_LINK_SPEED_ZERO) {
140 		oce_log(dev, CE_NOTE, MOD_CONFIG,
141 		    "LINK_DOWN: 0x%x", dev->link.mac_speed);
142 		mac_link_update(dev->mac_handle, LINK_STATE_DOWN);
143 	} else {
144 		oce_log(dev, CE_NOTE, MOD_CONFIG,
145 		    "(f,s,d,pp)=(0x%x, 0x%x, 0x%x, 0x%x)",
146 		    dev->link.mac_fault, dev->link.mac_speed,
147 		    dev->link.mac_duplex, dev->link.physical_port);
148 		mac_link_update(dev->mac_handle, LINK_STATE_UP);
149 	}
150 	/* arm the eqs */
151 	for (qidx = 0; qidx < dev->neqs; qidx++) {
152 		oce_arm_eq(dev, dev->eq[qidx]->eq_id, 0, B_TRUE, B_FALSE);
153 	}
154 
155 	/* update state */
156 	return (DDI_SUCCESS);
157 } /* oce_start */
158 
159 
160 void
161 oce_m_stop(void *arg)
162 {
163 	struct oce_dev *dev = arg;
164 
165 	/* disable interrupts */
166 	oce_di(dev);
167 
168 	mutex_enter(&dev->dev_lock);
169 
170 	dev->state |= STATE_MAC_STOPPING;
171 
172 	if (dev->suspended) {
173 		mutex_exit(&dev->dev_lock);
174 		return;
175 	}
176 
177 	oce_stop(dev);
178 
179 	dev->state &= ~(STATE_MAC_STOPPING | STATE_MAC_STARTED);
180 
181 	mutex_exit(&dev->dev_lock);
182 }
183 
184 void
185 oce_stop(struct oce_dev *dev)
186 {
187 	/* complete the pending Tx */
188 	oce_stop_wq(dev->wq[0]);
189 
190 	oce_chip_hw_fini(dev);
191 
192 	OCE_MSDELAY(200);
193 	oce_stop_mq(dev->mq);
194 	oce_stop_rq(dev->rq[0]);
195 
196 	/* remove interrupt handlers */
197 	oce_remove_handler(dev);
198 	/* release hw resources */
199 	oce_hw_fini(dev);
200 
201 } /* oce_stop */
202 
203 int
204 oce_m_multicast(void *arg, boolean_t add, const uint8_t *mca)
205 {
206 
207 	struct oce_dev *dev = (struct oce_dev *)arg;
208 	struct ether_addr  *mca_drv_list;
209 	struct ether_addr  *mca_hw_list;
210 	int new_mcnt = 0;
211 	int ret;
212 	int i;
213 
214 	/* check the address */
215 	if ((mca[0] & 0x1) == 0) {
216 		return (EINVAL);
217 	}
218 
219 	/* Allocate the local array for holding the addresses temporarily */
220 	mca_hw_list = kmem_zalloc(OCE_MAX_MCA * sizeof (struct ether_addr),
221 	    KM_NOSLEEP);
222 
223 	if (mca_hw_list == NULL)
224 		return (ENOMEM);
225 
226 	mca_drv_list = &dev->multi_cast[0];
227 	if (add) {
228 		/* check if we exceeded hw max  supported */
229 		if (dev->num_mca >= OCE_MAX_MCA) {
230 			return (ENOENT);
231 		}
232 		/* copy entire dev mca to the mbx */
233 		bcopy((void*)mca_drv_list,
234 		    (void *)mca_hw_list,
235 		    (dev->num_mca * sizeof (struct ether_addr)));
236 		/* Append the new one to local list */
237 		bcopy(mca, &mca_hw_list[dev->num_mca],
238 		    sizeof (struct ether_addr));
239 		new_mcnt = dev->num_mca + 1;
240 
241 	} else {
242 		struct ether_addr *hwlistp = mca_hw_list;
243 		for (i = 0; i < dev->num_mca; i++) {
244 			/* copy only if it does not match */
245 			if (bcmp((mca_drv_list + i), mca, ETHERADDRL)) {
246 				bcopy(mca_drv_list + i, hwlistp,
247 				    ETHERADDRL);
248 				hwlistp++;
249 			}
250 		}
251 		new_mcnt = dev->num_mca - 1;
252 	}
253 
254 	mutex_enter(&dev->dev_lock);
255 	if (dev->suspended) {
256 		mutex_exit(&dev->dev_lock);
257 		goto finish;
258 	}
259 	mutex_exit(&dev->dev_lock);
260 
261 	ret = oce_set_multicast_table(dev, mca_hw_list, new_mcnt, B_FALSE);
262 	if (ret != 0) {
263 		kmem_free(mca_hw_list,
264 		    OCE_MAX_MCA * sizeof (struct ether_addr));
265 		return (EIO);
266 	}
267 	/*
268 	 *  Copy the local structure to dev structure
269 	 */
270 finish:
271 	bcopy(mca_hw_list, mca_drv_list,
272 	    new_mcnt * sizeof (struct ether_addr));
273 	dev->num_mca = (uint16_t)new_mcnt;
274 	kmem_free(mca_hw_list, OCE_MAX_MCA * sizeof (struct ether_addr));
275 	return (0);
276 } /* oce_m_multicast */
277 
278 int
279 oce_m_unicast(void *arg, const uint8_t *uca)
280 {
281 	struct oce_dev *dev = arg;
282 	int ret;
283 
284 	DEV_LOCK(dev);
285 	if (dev->suspended) {
286 		bcopy(uca, dev->unicast_addr, ETHERADDRL);
287 		DEV_UNLOCK(dev);
288 		return (DDI_SUCCESS);
289 	}
290 	DEV_UNLOCK(dev);
291 
292 	/* Delete previous one and add new one */
293 	ret = oce_del_mac(dev, &dev->pmac_id);
294 	if (ret != DDI_SUCCESS) {
295 		return (EIO);
296 	}
297 
298 	/* Set the New MAC addr earlier is no longer valid */
299 	ret = oce_add_mac(dev, uca, &dev->pmac_id);
300 	if (ret != DDI_SUCCESS) {
301 		return (EIO);
302 	}
303 	return (ret);
304 } /* oce_m_unicast */
305 
306 mblk_t *
307 oce_m_send(void *arg, mblk_t *mp)
308 {
309 	struct oce_dev *dev = arg;
310 	mblk_t *nxt_pkt;
311 	mblk_t *rmp = NULL;
312 
313 	DEV_LOCK(dev);
314 	if (dev->suspended) {
315 		DEV_UNLOCK(dev);
316 		freemsg(mp);
317 		return (NULL);
318 	}
319 	DEV_UNLOCK(dev);
320 
321 	while (mp != NULL) {
322 		/* Save the Pointer since mp will be freed in case of copy */
323 		nxt_pkt = mp->b_next;
324 		mp->b_next = NULL;
325 		/* Hardcode wq since we have only one */
326 		rmp = oce_send_packet(dev->wq[0], mp);
327 		if (rmp != NULL) {
328 			/* restore the chain */
329 			rmp->b_next = nxt_pkt;
330 			break;
331 		}
332 		mp  = nxt_pkt;
333 	}
334 	return (rmp);
335 } /* oce_send */
336 
337 boolean_t
338 oce_m_getcap(void *arg, mac_capab_t cap, void *data)
339 {
340 	struct oce_dev *dev = arg;
341 	boolean_t ret = B_TRUE;
342 	switch (cap) {
343 
344 	case MAC_CAPAB_HCKSUM: {
345 		uint32_t *csum_flags = u32ptr(data);
346 		*csum_flags = HCKSUM_ENABLE |
347 		    HCKSUM_INET_FULL_V4 |
348 		    HCKSUM_IPHDRCKSUM;
349 		break;
350 	}
351 	case MAC_CAPAB_LSO: {
352 		mac_capab_lso_t *mcap_lso = (mac_capab_lso_t *)data;
353 		if (dev->lso_capable) {
354 			mcap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
355 			mcap_lso->lso_basic_tcp_ipv4.lso_max = OCE_LSO_MAX_SIZE;
356 		} else {
357 			ret = B_FALSE;
358 		}
359 		break;
360 	}
361 	default:
362 		ret = B_FALSE;
363 		break;
364 	}
365 	return (ret);
366 } /* oce_m_getcap */
367 
368 int
369 oce_m_setprop(void *arg, const char *name, mac_prop_id_t id,
370     uint_t size, const void *val)
371 {
372 	struct oce_dev *dev = arg;
373 	int ret = 0;
374 
375 	switch (id) {
376 	case MAC_PROP_MTU: {
377 		uint32_t mtu;
378 
379 		bcopy(val, &mtu, sizeof (uint32_t));
380 
381 		if (dev->mtu == mtu) {
382 			ret = 0;
383 			break;
384 		}
385 
386 		if (mtu != OCE_MIN_MTU && mtu != OCE_MAX_MTU) {
387 			ret = EINVAL;
388 			break;
389 		}
390 
391 		ret = mac_maxsdu_update(dev->mac_handle, mtu);
392 		if (0 == ret) {
393 			dev->mtu = mtu;
394 			break;
395 		}
396 		break;
397 	}
398 
399 	case MAC_PROP_FLOWCTRL: {
400 		link_flowctrl_t flowctrl;
401 		uint32_t fc = 0;
402 
403 		bcopy(val, &flowctrl, sizeof (link_flowctrl_t));
404 
405 		switch (flowctrl) {
406 		case LINK_FLOWCTRL_NONE:
407 			fc = 0;
408 			break;
409 
410 		case LINK_FLOWCTRL_RX:
411 			fc = OCE_FC_RX;
412 			break;
413 
414 		case LINK_FLOWCTRL_TX:
415 			fc = OCE_FC_TX;
416 			break;
417 
418 		case LINK_FLOWCTRL_BI:
419 			fc = OCE_FC_RX | OCE_FC_TX;
420 			break;
421 		default:
422 			ret = EINVAL;
423 			break;
424 		} /* switch flowctrl */
425 
426 		if (ret)
427 			break;
428 
429 		if (fc == dev->flow_control)
430 			break;
431 
432 		if (dev->suspended) {
433 			dev->flow_control = fc;
434 			break;
435 		}
436 		/* call to set flow control */
437 		ret = oce_set_flow_control(dev, fc);
438 		/* store the new fc setting on success */
439 		if (ret == 0) {
440 		dev->flow_control = fc;
441 		}
442 		break;
443 	}
444 
445 	case MAC_PROP_PRIVATE:
446 		ret = oce_set_priv_prop(dev, name, size, val);
447 		break;
448 
449 	default:
450 		ret = ENOTSUP;
451 		break;
452 	} /* switch id */
453 
454 	return (ret);
455 } /* oce_m_setprop */
456 
457 int
458 oce_m_getprop(void *arg, const char *name, mac_prop_id_t id,
459     uint_t flags, uint_t size, void *val, uint_t *perm)
460 {
461 	struct oce_dev *dev = arg;
462 	uint32_t ret = 0;
463 
464 	switch (id) {
465 	case MAC_PROP_AUTONEG:
466 	case MAC_PROP_EN_AUTONEG:
467 	case MAC_PROP_ADV_1000FDX_CAP:
468 	case MAC_PROP_EN_1000FDX_CAP:
469 	case MAC_PROP_ADV_1000HDX_CAP:
470 	case MAC_PROP_EN_1000HDX_CAP:
471 	case MAC_PROP_ADV_100FDX_CAP:
472 	case MAC_PROP_EN_100FDX_CAP:
473 	case MAC_PROP_ADV_100HDX_CAP:
474 	case MAC_PROP_EN_100HDX_CAP:
475 	case MAC_PROP_ADV_10FDX_CAP:
476 	case MAC_PROP_EN_10FDX_CAP:
477 	case MAC_PROP_ADV_10HDX_CAP:
478 	case MAC_PROP_EN_10HDX_CAP:
479 	case MAC_PROP_ADV_100T4_CAP:
480 	case MAC_PROP_EN_100T4_CAP: {
481 		*perm = MAC_PROP_PERM_READ;
482 		*(uint8_t *)val = 0x0;
483 		break;
484 	}
485 
486 	case MAC_PROP_ADV_10GFDX_CAP:
487 	case MAC_PROP_EN_10GFDX_CAP: {
488 		*perm = MAC_PROP_PERM_READ;
489 		*(uint8_t *)val = 0x01;
490 		break;
491 	}
492 
493 	case MAC_PROP_DUPLEX: {
494 		if (size >= sizeof (link_duplex_t)) {
495 			uint32_t *mode = (uint32_t *)val;
496 
497 			*perm = MAC_PROP_PERM_READ;
498 			if (dev->state & STATE_MAC_STARTED)
499 				*mode = LINK_DUPLEX_FULL;
500 			else
501 				*mode = LINK_DUPLEX_UNKNOWN;
502 
503 		} else
504 			ret = EINVAL;
505 		break;
506 	}
507 
508 	case MAC_PROP_SPEED: {
509 		if (size >= sizeof (uint64_t)) {
510 			uint64_t *speed = (uint64_t *)val;
511 
512 			*perm = MAC_PROP_PERM_READ;
513 			*speed = 0;
514 			if ((dev->state & STATE_MAC_STARTED) &&
515 			    (dev->link.mac_speed != 0)) {
516 				*speed = 1000000ull *
517 				    oce_power10(dev->link.mac_speed);
518 			}
519 		} else
520 			ret = EINVAL;
521 		break;
522 	}
523 
524 	case MAC_PROP_MTU: {
525 		mac_propval_range_t range;
526 
527 		*perm = MAC_PROP_PERM_RW;
528 		if (!(flags & MAC_PROP_POSSIBLE)) {
529 			ret = ENOTSUP;
530 			break;
531 		}
532 		range.mpr_count = 1;
533 		range.mpr_type = MAC_PROPVAL_UINT32;
534 		range.range_uint32[0].mpur_min = OCE_MIN_MTU;
535 		range.range_uint32[0].mpur_max = OCE_MAX_MTU;
536 		bcopy(&range, val, sizeof (mac_propval_range_t));
537 		break;
538 	}
539 
540 	case MAC_PROP_FLOWCTRL: {
541 		link_flowctrl_t *fc = (link_flowctrl_t *)val;
542 
543 		if (size < sizeof (link_flowctrl_t)) {
544 			ret = EINVAL;
545 			break;
546 		}
547 
548 		if (size >= sizeof (link_flowctrl_t)) {
549 			if (dev->flow_control & OCE_FC_TX &&
550 			    dev->flow_control & OCE_FC_RX)
551 				*fc = LINK_FLOWCTRL_BI;
552 			else if (dev->flow_control == OCE_FC_TX)
553 				*fc = LINK_FLOWCTRL_TX;
554 			else if (dev->flow_control == OCE_FC_RX)
555 				*fc = LINK_FLOWCTRL_RX;
556 			else if (dev->flow_control == 0)
557 				*fc = LINK_FLOWCTRL_NONE;
558 			else
559 				ret = EINVAL;
560 		}
561 		break;
562 	}
563 
564 	case MAC_PROP_PRIVATE: {
565 		ret = oce_get_priv_prop(dev, name, flags, size, val);
566 		break;
567 	}
568 	default:
569 		break;
570 	} /* switch id */
571 	return (ret);
572 } /* oce_m_getprop */
573 
574 /*
575  * function to handle dlpi streams message from GLDv3 mac layer
576  */
577 void
578 oce_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
579 {
580 	struct oce_dev *dev = arg;
581 	struct  iocblk *iocp;
582 	int cmd;
583 	uint32_t payload_length;
584 	int ret;
585 
586 	iocp = (struct iocblk *)voidptr(mp->b_rptr);
587 	iocp->ioc_error = 0;
588 	cmd = iocp->ioc_cmd;
589 
590 	DEV_LOCK(dev);
591 	if (dev->suspended) {
592 		miocnak(wq, mp, 0, EINVAL);
593 		DEV_UNLOCK(dev);
594 		return;
595 	}
596 	DEV_UNLOCK(dev);
597 
598 	switch (cmd) {
599 
600 	case OCE_ISSUE_MBOX: {
601 		ret = oce_issue_mbox(dev, wq, mp, &payload_length);
602 		if (ret != 0) {
603 			miocnak(wq, mp, payload_length, ret);
604 		} else {
605 			miocack(wq, mp, payload_length, 0);
606 		}
607 		break;
608 	}
609 
610 	default:
611 		miocnak(wq, mp, 0, ENOTSUP);
612 		break;
613 	}
614 } /* oce_m_ioctl */
615 
616 int
617 oce_m_promiscuous(void *arg, boolean_t enable)
618 {
619 	struct oce_dev *dev = arg;
620 	int ret = 0;
621 
622 	DEV_LOCK(dev);
623 
624 	if (dev->promisc == enable) {
625 		DEV_UNLOCK(dev);
626 		return (ret);
627 	}
628 	dev->promisc = enable;
629 
630 	if (dev->suspended) {
631 		DEV_UNLOCK(dev);
632 		return (ret);
633 	}
634 
635 	DEV_UNLOCK(dev);
636 
637 	ret = oce_set_promiscuous(dev, enable);
638 
639 	return (ret);
640 } /* oce_m_promiscuous */
641 
642 static int
643 oce_power10(int power)
644 {
645 	int ret = 1;
646 
647 	while (power) {
648 		ret *= 10;
649 		power--;
650 	}
651 	return (ret);
652 }
653 
654 /*
655  * function to set a private property.
656  * Called from the set_prop GLD entry point
657  *
658  * dev - sofware handle to the device
659  * name - string containing the property name
660  * size - length of the string in name
661  * val - pointer to a location where the value to set is stored
662  *
663  * return EINVAL => invalid value in val 0 => success
664  */
665 static int
666 oce_set_priv_prop(struct oce_dev *dev, const char *name,
667     uint_t size, const void *val)
668 {
669 	int ret = ENOTSUP;
670 	long result;
671 
672 	_NOTE(ARGUNUSED(size));
673 
674 	if (NULL == val) {
675 		ret = EINVAL;
676 		return (ret);
677 	}
678 
679 	if (strcmp(name, "_tx_bcopy_limit") == 0) {
680 		(void) ddi_strtol(val, (char **)NULL, 0, &result);
681 		if (result <= OCE_WQ_BUF_SIZE) {
682 			if (result != dev->bcopy_limit)
683 				dev->bcopy_limit = (uint32_t)result;
684 			ret = 0;
685 		} else {
686 			ret = EINVAL;
687 		}
688 	}
689 
690 	return (ret);
691 } /* oce_set_priv_prop */
692 
693 /*
694  * function to get the value of a private property. Called from get_prop
695  *
696  * dev - software handle to the device
697  * name - string containing the property name
698  * flags - flags sent by the OS to get_prop
699  * size - length of the string contained name
700  * val - [OUT] pointer to the location where the result is returned
701  *
702  * return EINVAL => invalid request 0 => success
703  */
704 static int
705 oce_get_priv_prop(struct oce_dev *dev, const char *name,
706     uint_t flags, uint_t size, void *val)
707 {
708 	int ret = ENOTSUP;
709 	int value;
710 	boolean_t is_default = (flags & MAC_PROP_DEFAULT);
711 
712 	if (NULL == val) {
713 		ret = EINVAL;
714 		return (ret);
715 	}
716 
717 	if (strcmp(name, "_tx_ring_size") == 0) {
718 		value = is_default ? OCE_DEFAULT_TX_RING_SIZE :
719 		    dev->tx_ring_size;
720 		ret = 0;
721 		goto done;
722 	}
723 
724 	if (strcmp(name, "_tx_bcopy_limit") == 0) {
725 		value = dev->bcopy_limit;
726 		ret = 0;
727 		goto done;
728 	}
729 
730 	if (strcmp(name, "_rx_ring_size") == 0) {
731 		value = is_default ? OCE_DEFAULT_RX_RING_SIZE :
732 		    dev->rx_ring_size;
733 		ret = 0;
734 		goto done;
735 	}
736 
737 done:
738 	if (ret != 0) {
739 		(void) snprintf(val, size, "%d", value);
740 	}
741 	return (ret);
742 } /* oce_get_priv_prop */
743