xref: /illumos-gate/usr/src/uts/common/io/qede/qede_gld.c (revision 589d6798)
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, v.1,  (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://opensource.org/licenses/CDDL-1.0.
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 2014-2017 Cavium, Inc.
24 * The contents of this file are subject to the terms of the Common Development
25 * and Distribution License, v.1,  (the "License").
26 
27 * You may not use this file except in compliance with the License.
28 
29 * You can obtain a copy of the License at available
30 * at http://opensource.org/licenses/CDDL-1.0
31 
32 * See the License for the specific language governing permissions and
33 * limitations under the License.
34 */
35 
36 /*
37  * Copyright 2018 Joyent, Inc.
38  */
39 
40 #include "qede.h"
41 
42 #define	FP_LOCK(ptr)	\
43 mutex_enter(&ptr->fp_lock);
44 #define	FP_UNLOCK(ptr)	\
45 mutex_exit(&ptr->fp_lock);
46 
47 int
qede_ucst_find(qede_t * qede,const uint8_t * mac_addr)48 qede_ucst_find(qede_t *qede, const uint8_t *mac_addr)
49 {
50 	int slot;
51 
52 	for(slot = 0; slot < qede->ucst_total; slot++) {
53 		if (bcmp(qede->ucst_mac[slot].mac_addr.ether_addr_octet,
54 		    mac_addr, ETHERADDRL) == 0) {
55 			return (slot);
56 		}
57 	}
58 	return (-1);
59 
60 }
61 
62 static int
qede_set_mac_addr(qede_t * qede,uint8_t * mac_addr,uint8_t fl)63 qede_set_mac_addr(qede_t *qede, uint8_t *mac_addr, uint8_t fl)
64 {
65 	struct ecore_filter_ucast params;
66 
67 	memset(&params, 0, sizeof (params));
68 
69 	params.opcode = fl;
70 	params.type = ECORE_FILTER_MAC;
71 	params.is_rx_filter = true;
72 	params.is_tx_filter = true;
73 	COPY_ETH_ADDRESS(mac_addr, params.mac);
74 
75 	return (ecore_filter_ucast_cmd(&qede->edev,
76 	    &params, ECORE_SPQ_MODE_EBLOCK, NULL));
77 
78 
79 }
80 static int
qede_add_macaddr(qede_t * qede,uint8_t * mac_addr)81 qede_add_macaddr(qede_t *qede, uint8_t *mac_addr)
82 {
83 	int i, ret = 0;
84 
85 	i = qede_ucst_find(qede, mac_addr);
86 	if (i != -1) {
87 		/* LINTED E_ARGUMENT_MISMATCH */
88 		qede_info(qede, "mac addr already added %d\n",
89 		    qede->ucst_avail);
90 		return (0);
91 	}
92 	if (qede->ucst_avail == 0) {
93 		qede_info(qede, "add macaddr ignored \n");
94 		return (ENOSPC);
95 	}
96 	for (i = 0; i < qede->ucst_total; i++) {
97 		if (qede->ucst_mac[i].set == 0) {
98 			break;
99 		}
100 	}
101 	if (i >= qede->ucst_total) {
102 		qede_info(qede, "add macaddr ignored no space");
103 		return (ENOSPC);
104 	}
105 	ret = qede_set_mac_addr(qede, (uint8_t *)mac_addr, ECORE_FILTER_ADD);
106 	if (ret == 0) {
107 		bcopy(mac_addr,
108 		    qede->ucst_mac[i].mac_addr.ether_addr_octet,
109 		    ETHERADDRL);
110 		qede->ucst_mac[i].set = 1;
111 		qede->ucst_avail--;
112 		/* LINTED E_ARGUMENT_MISMATCH */
113 		qede_info(qede,  " add macaddr passed for addr "
114 		    "%02x:%02x:%02x:%02x:%02x:%02x",
115 		    mac_addr[0], mac_addr[1],
116 		    mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
117 	} else {
118 		/* LINTED E_ARGUMENT_MISMATCH */
119 		qede_info(qede,  "add macaddr failed for addr "
120 		    "%02x:%02x:%02x:%02x:%02x:%02x",
121 		    mac_addr[0], mac_addr[1],
122 		    mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
123 
124 	}
125 	if (qede->ucst_avail == (qede->ucst_total -1)) {
126 			u8 bcast_addr[] =
127 			{
128 				0xff, 0xff, 0xff, 0xff, 0xff,
129 				0xff
130 			};
131 			for (i = 0; i < qede->ucst_total; i++) {
132 				if (qede->ucst_mac[i].set == 0)
133 					break;
134 			}
135 			ret = qede_set_mac_addr(qede,
136 			    (uint8_t *)bcast_addr, ECORE_FILTER_ADD);
137 			if (ret == 0) {
138 				bcopy(bcast_addr,
139 				    qede->ucst_mac[i].mac_addr.ether_addr_octet,
140 				    ETHERADDRL);
141 				qede->ucst_mac[i].set = 1;
142 				qede->ucst_avail--;
143 			} else {
144 
145 			/* LINTED E_ARGUMENT_MISMATCH */
146 			qede_info(qede,  "add macaddr failed for addr "
147 			    "%02x:%02x:%02x:%02x:%02x:%02x",
148 		            mac_addr[0], mac_addr[1],
149 		            mac_addr[2], mac_addr[3], mac_addr[4],
150 			    mac_addr[5]);
151 		       }
152 
153 		}
154 
155 	return (ret);
156 
157 }
158 
159 #ifndef ILLUMOS
160 static int
qede_add_mac_addr(void * arg,const uint8_t * mac_addr,const uint64_t flags)161 qede_add_mac_addr(void *arg, const uint8_t *mac_addr, const uint64_t flags)
162 #else
163 static int
164 qede_add_mac_addr(void *arg, const uint8_t *mac_addr)
165 #endif
166 {
167 	qede_mac_group_t *rx_group = (qede_mac_group_t *)arg;
168 	qede_t *qede = rx_group->qede;
169 	int ret = DDI_SUCCESS;
170 
171 	/* LINTED E_ARGUMENT_MISMATCH */
172 	qede_info(qede, " mac addr :" MAC_STRING,  MACTOSTR(mac_addr));
173 
174 	mutex_enter(&qede->gld_lock);
175 	if (qede->qede_state == QEDE_STATE_SUSPENDED) {
176 		mutex_exit(&qede->gld_lock);
177 		return (ECANCELED);
178 	}
179 	ret = qede_add_macaddr(qede, (uint8_t *)mac_addr);
180 
181 	mutex_exit(&qede->gld_lock);
182 
183 
184 	return (ret);
185 }
186 
187 static int
qede_rem_macaddr(qede_t * qede,uint8_t * mac_addr)188 qede_rem_macaddr(qede_t *qede, uint8_t *mac_addr)
189 {
190 	int ret = 0;
191 	int i;
192 
193 	i = qede_ucst_find(qede, mac_addr);
194 	if (i == -1) {
195 		/* LINTED E_ARGUMENT_MISMATCH */
196 		qede_info(qede,
197 		    "mac addr not there to remove",
198 		    MAC_STRING, MACTOSTR(mac_addr));
199 		return (0);
200 	}
201 	if (qede->ucst_mac[i].set == 0) {
202 	       	return (EINVAL);
203 	}
204 	ret = qede_set_mac_addr(qede, (uint8_t *)mac_addr, ECORE_FILTER_REMOVE);
205 	if (ret == 0) {
206 		bzero(qede->ucst_mac[i].mac_addr.ether_addr_octet,ETHERADDRL);
207 		qede->ucst_mac[i].set = 0;
208 		qede->ucst_avail++;
209 	} else {
210 		/* LINTED E_ARGUMENT_MISMATCH */
211 		qede_info(qede, "mac addr remove failed",
212 		    MAC_STRING, MACTOSTR(mac_addr));
213 	}
214 	return (ret);
215 
216 }
217 
218 
219 static int
qede_rem_mac_addr(void * arg,const uint8_t * mac_addr)220 qede_rem_mac_addr(void *arg, const uint8_t *mac_addr)
221 {
222 	qede_mac_group_t *rx_group = (qede_mac_group_t *)arg;
223 	qede_t *qede = rx_group->qede;
224 	int ret = DDI_SUCCESS;
225 
226 	/* LINTED E_ARGUMENT_MISMATCH */
227 	qede_info(qede, "mac addr remove:" MAC_STRING, MACTOSTR(mac_addr));
228 	mutex_enter(&qede->gld_lock);
229 	if (qede->qede_state == QEDE_STATE_SUSPENDED) {
230 		mutex_exit(&qede->gld_lock);
231 		return (ECANCELED);
232 	}
233 	ret = qede_rem_macaddr(qede, (uint8_t *)mac_addr);
234 	mutex_exit(&qede->gld_lock);
235 	return (ret);
236 }
237 
238 
239 static int
qede_tx_ring_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)240 qede_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
241 {
242 	int ret = 0;
243 
244 	qede_fastpath_t *fp = (qede_fastpath_t *)rh;
245 	qede_tx_ring_t *tx_ring = fp->tx_ring[0];
246 	qede_t *qede = fp->qede;
247 
248 
249 	if (qede->qede_state == QEDE_STATE_SUSPENDED)
250 		return (ECANCELED);
251 
252 	switch (stat) {
253 	case MAC_STAT_OBYTES:
254 		*val = tx_ring->tx_byte_count;
255 		break;
256 
257 	case MAC_STAT_OPACKETS:
258 		*val = tx_ring->tx_pkt_count;
259 		break;
260 
261 	default:
262 		*val = 0;
263 		ret = ENOTSUP;
264 	}
265 
266 	return (ret);
267 }
268 
269 #ifndef ILLUMOS
270 static mblk_t *
qede_rx_ring_poll(void * arg,int poll_bytes,int poll_pkts)271 qede_rx_ring_poll(void *arg, int poll_bytes, int poll_pkts)
272 {
273 #else
274 static mblk_t *
275 qede_rx_ring_poll(void *arg, int poll_bytes)
276 {
277 	/* XXX pick a value at the moment */
278 	int poll_pkts = 100;
279 #endif
280 	qede_fastpath_t *fp = (qede_fastpath_t *)arg;
281 	mblk_t *mp = NULL;
282 	int work_done = 0;
283 	qede_t *qede = fp->qede;
284 
285 	if (poll_bytes == 0) {
286 		return (NULL);
287 	}
288 
289 	mutex_enter(&fp->fp_lock);
290 	qede->intrSbPollCnt[fp->vect_info->vect_index]++;
291 
292 	mp = qede_process_fastpath(fp, poll_bytes, poll_pkts, &work_done);
293 	if (mp != NULL) {
294 		fp->rx_ring->rx_poll_cnt++;
295 	} else if ((mp == NULL) && (work_done == 0)) {
296 		qede->intrSbPollNoChangeCnt[fp->vect_info->vect_index]++;
297 	}
298 
299 	mutex_exit(&fp->fp_lock);
300 	return (mp);
301 }
302 
303 #ifndef ILLUMOS
304 static int
305 qede_rx_ring_intr_enable(mac_ring_driver_t rh)
306 #else
307 static int
308 qede_rx_ring_intr_enable(mac_intr_handle_t rh)
309 #endif
310 {
311 	qede_fastpath_t *fp = (qede_fastpath_t *)rh;
312 
313 	mutex_enter(&fp->qede->drv_lock);
314 	if (!fp->sb_phys && (fp->sb_dma_handle == NULL)) {
315 		mutex_exit(&fp->qede->drv_lock);
316 		return (DDI_FAILURE);
317 	}
318 
319 	fp->rx_ring->intrEnableCnt++;
320 	qede_enable_hw_intr(fp);
321 	fp->disabled_by_poll = 0;
322 	mutex_exit(&fp->qede->drv_lock);
323 
324 	return (DDI_SUCCESS);
325 }
326 
327 #ifndef	ILLUMOS
328 static int
329 qede_rx_ring_intr_disable(mac_ring_driver_t rh)
330 #else
331 static int
332 qede_rx_ring_intr_disable(mac_intr_handle_t rh)
333 #endif
334 {
335 	qede_fastpath_t *fp = (qede_fastpath_t *)rh;
336 
337 	mutex_enter(&fp->qede->drv_lock);
338 	if (!fp->sb_phys && (fp->sb_dma_handle == NULL)) {
339 		mutex_exit(&fp->qede->drv_lock);
340 		return (DDI_FAILURE);
341 	}
342 	fp->rx_ring->intrDisableCnt++;
343 	qede_disable_hw_intr(fp);
344 	fp->disabled_by_poll = 1;
345 	mutex_exit(&fp->qede->drv_lock);
346 	return (DDI_SUCCESS);
347 }
348 
349 static int
350 qede_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
351 {
352 
353 	int ret = 0;
354 
355 	qede_fastpath_t *fp = (qede_fastpath_t *)rh;
356 	qede_t *qede = fp->qede;
357 	qede_rx_ring_t *rx_ring = fp->rx_ring;
358 
359 	if (qede->qede_state == QEDE_STATE_SUSPENDED) {
360 		return (ECANCELED);
361 	}
362 
363 	switch (stat) {
364 	case MAC_STAT_RBYTES:
365 		*val = rx_ring->rx_byte_cnt;
366 		break;
367 	case MAC_STAT_IPACKETS:
368 		*val = rx_ring->rx_pkt_cnt;
369 		break;
370 	default:
371 		*val = 0;
372 		ret = ENOTSUP;
373 		break;
374 	}
375 
376 	return (ret);
377 }
378 
379 static int
380 qede_get_global_ring_index(qede_t *qede, int gindex, int rindex)
381 {
382 	qede_fastpath_t *fp;
383 	qede_rx_ring_t *rx_ring;
384 	int i = 0;
385 
386 	for (i = 0; i < qede->num_fp; i++) {
387 		fp = &qede->fp_array[i];
388 		rx_ring = fp->rx_ring;
389 
390 		if (rx_ring->group_index == gindex) {
391 			rindex--;
392 		}
393 		if (rindex < 0) {
394 			return (i);
395 		}
396 	}
397 
398 	return (-1);
399 }
400 
401 static void
402 qede_rx_ring_stop(mac_ring_driver_t rh)
403 {
404 	qede_fastpath_t *fp = (qede_fastpath_t *)rh;
405 	qede_rx_ring_t *rx_ring = fp->rx_ring;
406 
407 	qede_print("!%s(%d): called", __func__,fp->qede->instance);
408 	mutex_enter(&fp->fp_lock);
409 	rx_ring->mac_ring_started = B_FALSE;
410 	mutex_exit(&fp->fp_lock);
411 }
412 
413 static int
414 qede_rx_ring_start(mac_ring_driver_t rh, u64 mr_gen_num)
415 {
416 	qede_fastpath_t *fp = (qede_fastpath_t *)rh;
417 	qede_rx_ring_t *rx_ring = fp->rx_ring;
418 
419 	qede_print("!%s(%d): called", __func__,fp->qede->instance);
420 	mutex_enter(&fp->fp_lock);
421 	rx_ring->mr_gen_num = mr_gen_num;
422 	rx_ring->mac_ring_started = B_TRUE;
423         rx_ring->intrDisableCnt = 0;
424 	rx_ring->intrEnableCnt  = 0;
425 	fp->disabled_by_poll = 0;
426 
427 	mutex_exit(&fp->fp_lock);
428 
429 	return (DDI_SUCCESS);
430 }
431 
432 /* Callback function from mac layer to register rings */
433 void
434 qede_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
435     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
436 {
437 	qede_t *qede = (qede_t *)arg;
438 	mac_intr_t *mintr = &infop->mri_intr;
439 
440 	switch (rtype) {
441 	case MAC_RING_TYPE_RX: {
442 		/*
443 		 * Index passed as a param is the ring index within the
444 		 * given group index. If multiple groups are supported
445 		 * then need to search into all groups to find out the
446 		 * global ring index for the passed group relative
447 		 * ring index
448 		 */
449 		int global_ring_index = qede_get_global_ring_index(qede,
450 		    group_index, ring_index);
451 		qede_fastpath_t *fp;
452 		qede_rx_ring_t *rx_ring;
453 		int i;
454 
455 		/*
456 		 * global_ring_index < 0 means group index passed
457 		 * was registered by our driver
458 		 */
459 		ASSERT(global_ring_index >= 0);
460 
461 		if (rh == NULL) {
462 			cmn_err(CE_WARN, "!rx ring(%d) ring handle NULL",
463 			    global_ring_index);
464 		}
465 
466 		fp = &qede->fp_array[global_ring_index];
467 		rx_ring = fp->rx_ring;
468 		fp->qede = qede;
469 
470 		rx_ring->mac_ring_handle = rh;
471 
472 		qede_info(qede, "rx_ring %d mac_ring_handle %p",
473 		    rx_ring->rss_id, rh);
474 
475 		/* mri_driver passed as arg to mac_ring* callbacks */
476 		infop->mri_driver = (mac_ring_driver_t)fp;
477 		/*
478 		 * mri_start callback will supply a mac rings generation
479 		 * number which is needed while indicating packets
480 		 * upstream via mac_ring_rx() call
481 		 */
482 		infop->mri_start = qede_rx_ring_start;
483 		infop->mri_stop = qede_rx_ring_stop;
484 		infop->mri_poll = qede_rx_ring_poll;
485 		infop->mri_stat = qede_rx_ring_stat;
486 
487 		mintr->mi_handle = (mac_intr_handle_t)fp;
488 		mintr->mi_enable = qede_rx_ring_intr_enable;
489 		mintr->mi_disable = qede_rx_ring_intr_disable;
490 		if (qede->intr_ctx.intr_type_in_use &
491 		    (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
492 			mintr->mi_ddi_handle =
493 			    qede->intr_ctx.
494 			    intr_hdl_array[global_ring_index + qede->num_hwfns];
495 		}
496 		break;
497 	}
498 	case MAC_RING_TYPE_TX: {
499 		qede_fastpath_t *fp;
500 		qede_tx_ring_t *tx_ring;
501 		int i, tc;
502 
503 		ASSERT(ring_index < qede->num_fp);
504 
505 		fp = &qede->fp_array[ring_index];
506 		fp->qede = qede;
507 		tx_ring = fp->tx_ring[0];
508 		tx_ring->mac_ring_handle = rh;
509 		qede_info(qede, "tx_ring %d mac_ring_handle %p",
510 		    tx_ring->tx_queue_index, rh);
511 		infop->mri_driver = (mac_ring_driver_t)fp;
512 		infop->mri_start = NULL;
513 		infop->mri_stop = NULL;
514 		infop->mri_tx = qede_ring_tx;
515 		infop->mri_stat = qede_tx_ring_stat;
516 		if (qede->intr_ctx.intr_type_in_use &
517 		    (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
518 			mintr->mi_ddi_handle =
519 			    qede->intr_ctx.
520 			    intr_hdl_array[ring_index + qede->num_hwfns];
521 		}
522 		break;
523 	}
524 	default:
525 		break;
526 	}
527 }
528 
529 /*
530  * Callback function from mac layer to register group
531  */
532 void
533 qede_fill_group(void *arg, mac_ring_type_t rtype, const int index,
534     mac_group_info_t *infop, mac_group_handle_t gh)
535 {
536 	qede_t *qede = (qede_t *)arg;
537 
538 	switch (rtype) {
539 	case MAC_RING_TYPE_RX: {
540 		qede_mac_group_t *rx_group;
541 
542 		rx_group = &qede->rx_groups[index];
543 		rx_group->group_handle = gh;
544 		rx_group->group_index = index;
545 		rx_group->qede = qede;
546 		infop->mgi_driver = (mac_group_driver_t)rx_group;
547 		infop->mgi_start = NULL;
548 		infop->mgi_stop = NULL;
549 #ifndef ILLUMOS
550 		infop->mgi_addvlan = NULL;
551 		infop->mgi_remvlan = NULL;
552 		infop->mgi_getsriov_info = NULL;
553 		infop->mgi_setmtu = NULL;
554 #endif
555 		infop->mgi_addmac = qede_add_mac_addr;
556 		infop->mgi_remmac = qede_rem_mac_addr;
557 		infop->mgi_count =  qede->num_fp;
558 #ifndef ILLUMOS
559 		if (index == 0) {
560 			infop->mgi_flags = MAC_GROUP_DEFAULT;
561 		}
562 #endif
563 
564 		break;
565 	}
566 	case MAC_RING_TYPE_TX: {
567 		qede_mac_group_t *tx_group;
568 
569 		tx_group = &qede->tx_groups[index];
570 		tx_group->group_handle = gh;
571 		tx_group->group_index = index;
572 		tx_group->qede = qede;
573 
574 		infop->mgi_driver = (mac_group_driver_t)tx_group;
575 		infop->mgi_start = NULL;
576 		infop->mgi_stop = NULL;
577 		infop->mgi_addmac = NULL;
578 		infop->mgi_remmac = NULL;
579 #ifndef ILLUMOS
580 		infop->mgi_addvlan = NULL;
581 		infop->mgi_remvlan = NULL;
582 		infop->mgi_setmtu = NULL;
583 		infop->mgi_getsriov_info = NULL;
584 #endif
585 
586 		infop->mgi_count = qede->num_fp;
587 
588 #ifndef ILLUMOS
589 		if (index == 0) {
590 			infop->mgi_flags = MAC_GROUP_DEFAULT;
591 		}
592 #endif
593 		break;
594 	}
595 	default:
596 		break;
597 	}
598 }
599 
600 #ifdef ILLUMOS
601 static int
602 qede_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
603 {
604         qede_t *qede = arg;
605         struct ecore_dev *edev = &qede->edev;
606         struct ecore_hwfn *hwfn;
607         struct ecore_ptt *ptt;
608         uint32_t transceiver_state;
609 
610         if (id >= edev->num_hwfns || arg == NULL || infop == NULL)
611                 return (EINVAL);
612 
613         hwfn = &edev->hwfns[id];
614         ptt = ecore_ptt_acquire(hwfn);
615         if (ptt == NULL) {
616                 return (EIO);
617         }
618         /*
619          * Use the underlying raw API to get this information. While the
620          * ecore_phy routines have some ways of getting to this information, it
621          * ends up writing the raw data as ASCII characters which doesn't help
622          * us one bit.
623          */
624         transceiver_state = ecore_rd(hwfn, ptt, hwfn->mcp_info->port_addr +
625             offsetof(struct public_port, transceiver_data));
626         transceiver_state = GET_FIELD(transceiver_state, ETH_TRANSCEIVER_STATE);
627         ecore_ptt_release(hwfn, ptt);
628 
629         if ((transceiver_state & ETH_TRANSCEIVER_STATE_PRESENT) != 0) {
630                 mac_transceiver_info_set_present(infop, B_TRUE);
631                 /*
632                  * Based on our testing, the ETH_TRANSCEIVER_STATE_VALID flag is
633                  * not set, so we cannot rely on it. Instead, we have found that
634                  * the ETH_TRANSCEIVER_STATE_UPDATING will be set when we cannot
635                  * use the transceiver.
636                  */
637                 if ((transceiver_state & ETH_TRANSCEIVER_STATE_UPDATING) != 0) {
638                         mac_transceiver_info_set_usable(infop, B_FALSE);
639                 } else {
640                         mac_transceiver_info_set_usable(infop, B_TRUE);
641                 }
642         } else {
643                 mac_transceiver_info_set_present(infop, B_FALSE);
644                 mac_transceiver_info_set_usable(infop, B_FALSE);
645         }
646 
647         return (0);
648 }
649 
650 static int
651 qede_transceiver_read(void *arg, uint_t id, uint_t page, void *buf,
652     size_t nbytes, off_t offset, size_t *nread)
653 {
654         qede_t *qede = arg;
655         struct ecore_dev *edev = &qede->edev;
656         struct ecore_hwfn *hwfn;
657         uint32_t port, lane;
658         struct ecore_ptt *ptt;
659         enum _ecore_status_t ret;
660 
661         if (id >= edev->num_hwfns || buf == NULL || nbytes == 0 || nread == NULL ||
662             (page != 0xa0 && page != 0xa2) || offset < 0)
663                 return (EINVAL);
664 
665         /*
666          * Both supported pages have a length of 256 bytes, ensure nothing asks
667          * us to go beyond that.
668          */
669         if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
670                return (EINVAL);
671         }
672 
673         hwfn = &edev->hwfns[id];
674         ptt = ecore_ptt_acquire(hwfn);
675         if (ptt == NULL) {
676                 return (EIO);
677         }
678 
679         ret = ecore_mcp_phy_sfp_read(hwfn, ptt, hwfn->port_id, page, offset,
680             nbytes, buf);
681         ecore_ptt_release(hwfn, ptt);
682         if (ret != ECORE_SUCCESS) {
683                 return (EIO);
684         }
685         *nread = nbytes;
686         return (0);
687 }
688 #endif /* ILLUMOS */
689 
690 
691 static int
692 qede_mac_stats(void *     arg,
693                         uint_t     stat,
694                         uint64_t * value)
695 {
696 	qede_t * qede = (qede_t *)arg;
697 	struct ecore_eth_stats vstats;
698 	struct ecore_dev *edev = &qede->edev;
699 	struct qede_link_cfg lnkcfg;
700 	int rc = 0;
701 	qede_fastpath_t *fp = &qede->fp_array[0];
702 	qede_rx_ring_t *rx_ring;
703 	qede_tx_ring_t *tx_ring;
704 
705 	if ((qede == NULL) || (value == NULL)) {
706 		return EINVAL;
707 	}
708 
709 
710 	mutex_enter(&qede->gld_lock);
711 
712 	if(qede->qede_state != QEDE_STATE_STARTED) {
713 		mutex_exit(&qede->gld_lock);
714 		return EAGAIN;
715 	}
716 
717 	*value = 0;
718 
719 	memset(&vstats, 0, sizeof(struct ecore_eth_stats));
720 	ecore_get_vport_stats(edev, &vstats);
721 
722 
723         memset(&qede->curcfg, 0, sizeof(struct qede_link_cfg));
724         qede_get_link_info(&edev->hwfns[0], &qede->curcfg);
725 
726 
727 
728 	switch (stat)
729 	{
730 	case MAC_STAT_IFSPEED:
731 		*value = (qede->props.link_speed * 1000000ULL);
732 		break;
733 	case MAC_STAT_MULTIRCV:
734 		*value = vstats.common.rx_mcast_pkts;
735 		break;
736 	case MAC_STAT_BRDCSTRCV:
737 		*value = vstats.common.rx_bcast_pkts;
738 		break;
739 	case MAC_STAT_MULTIXMT:
740 		*value = vstats.common.tx_mcast_pkts;
741 		break;
742 	case MAC_STAT_BRDCSTXMT:
743 		*value = vstats.common.tx_bcast_pkts;
744 		break;
745 	case MAC_STAT_NORCVBUF:
746 		*value = vstats.common.no_buff_discards;
747 		break;
748 	case MAC_STAT_NOXMTBUF:
749 		*value = 0;
750 		break;
751 	case MAC_STAT_IERRORS:
752 	case ETHER_STAT_MACRCV_ERRORS:
753 		*value = vstats.common.mac_filter_discards +
754 		    vstats.common.packet_too_big_discard +
755 		    vstats.common.rx_crc_errors;
756 		break;
757 
758 	case MAC_STAT_OERRORS:
759 		break;
760 
761 	case MAC_STAT_COLLISIONS:
762 		*value = vstats.bb.tx_total_collisions;
763 		break;
764 
765 	case MAC_STAT_RBYTES:
766 		*value = vstats.common.rx_ucast_bytes +
767 		    vstats.common.rx_mcast_bytes +
768 		    vstats.common.rx_bcast_bytes;
769 		break;
770 
771 	case MAC_STAT_IPACKETS:
772 		*value = vstats.common.rx_ucast_pkts +
773 		    vstats.common.rx_mcast_pkts +
774 		    vstats.common.rx_bcast_pkts;
775 		break;
776 
777 	case MAC_STAT_OBYTES:
778 		*value = vstats.common.tx_ucast_bytes +
779 		    vstats.common.tx_mcast_bytes +
780 		    vstats.common.tx_bcast_bytes;
781 		break;
782 
783 	case MAC_STAT_OPACKETS:
784 		*value = vstats.common.tx_ucast_pkts +
785 		    vstats.common.tx_mcast_pkts +
786 		    vstats.common.tx_bcast_pkts;
787 		break;
788 
789 	case ETHER_STAT_ALIGN_ERRORS:
790 		*value = vstats.common.rx_align_errors;
791 		break;
792 
793 	case ETHER_STAT_FCS_ERRORS:
794 		*value = vstats.common.rx_crc_errors;
795 		break;
796 
797 	case ETHER_STAT_FIRST_COLLISIONS:
798 		break;
799 
800 	case ETHER_STAT_MULTI_COLLISIONS:
801 		break;
802 
803 	case ETHER_STAT_DEFER_XMTS:
804 		break;
805 
806 	case ETHER_STAT_TX_LATE_COLLISIONS:
807 		break;
808 
809 	case ETHER_STAT_EX_COLLISIONS:
810 		break;
811 
812 	case ETHER_STAT_MACXMT_ERRORS:
813 		*value = 0;
814 		break;
815 
816 	case ETHER_STAT_CARRIER_ERRORS:
817 		break;
818 
819 	case ETHER_STAT_TOOLONG_ERRORS:
820 		*value = vstats.common.rx_oversize_packets;
821 		break;
822 
823 #if (MAC_VERSION > 1)
824 	case ETHER_STAT_TOOSHORT_ERRORS:
825 		*value = vstats.common.rx_undersize_packets;
826 		break;
827 #endif
828 
829 	case ETHER_STAT_XCVR_ADDR:
830         	*value = 0;
831         	break;
832 
833 	case ETHER_STAT_XCVR_ID:
834         	*value = 0;
835         	break;
836 
837 	case ETHER_STAT_XCVR_INUSE:
838 		switch (qede->props.link_speed) {
839 		default:
840 			*value = XCVR_UNDEFINED;
841 		}
842 		break;
843 #if (MAC_VERSION > 1)
844 	case ETHER_STAT_CAP_10GFDX:
845 		*value = 0;
846 		break;
847 #endif
848 	case ETHER_STAT_CAP_100FDX:
849         	*value = 0;
850         	break;
851 	case ETHER_STAT_CAP_100HDX:
852         	*value = 0;
853         	break;
854 	case ETHER_STAT_CAP_ASMPAUSE:
855 		*value = 1;
856 		break;
857 	case ETHER_STAT_CAP_PAUSE:
858 		*value = 1;
859 		break;
860 	case ETHER_STAT_CAP_AUTONEG:
861 		*value = 1;
862 		break;
863 
864 #if (MAC_VERSION > 1)
865 	case ETHER_STAT_CAP_REMFAULT:
866 		*value = 0;
867 		break;
868 #endif
869 
870 #if (MAC_VERSION > 1)
871 	case ETHER_STAT_ADV_CAP_10GFDX:
872 		*value = 0;
873 		break;
874 #endif
875     case ETHER_STAT_ADV_CAP_ASMPAUSE:
876 		*value = 1;
877 		break;
878 
879 	case ETHER_STAT_ADV_CAP_PAUSE:
880 		*value = 1;
881 		break;
882 
883 	case ETHER_STAT_ADV_CAP_AUTONEG:
884 		*value = qede->curcfg.adv_capab.autoneg;
885 		break;
886 
887 #if (MAC_VERSION > 1)
888 	case ETHER_STAT_ADV_REMFAULT:
889 		*value = 0;
890 		break;
891 #endif
892 
893 	case ETHER_STAT_LINK_AUTONEG:
894 		*value	= qede->curcfg.autoneg;
895 		break;
896 
897 	case ETHER_STAT_LINK_DUPLEX:
898 		*value = (qede->props.link_duplex == DUPLEX_FULL) ?
899 				    LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
900 		break;
901         /*
902          * Supported speeds. These indicate what hardware is capable of.
903          */
904         case ETHER_STAT_CAP_1000HDX:
905                 *value = qede->curcfg.supp_capab.param_1000hdx;
906                 break;
907 
908         case ETHER_STAT_CAP_1000FDX:
909                 *value = qede->curcfg.supp_capab.param_1000fdx;
910                 break;
911 
912         case ETHER_STAT_CAP_10GFDX:
913                 *value = qede->curcfg.supp_capab.param_10000fdx;
914                 break;
915 
916         case ETHER_STAT_CAP_25GFDX:
917                 *value = qede->curcfg.supp_capab.param_25000fdx;
918                 break;
919 
920         case ETHER_STAT_CAP_40GFDX:
921                 *value = qede->curcfg.supp_capab.param_40000fdx;
922                 break;
923 
924         case ETHER_STAT_CAP_50GFDX:
925                 *value = qede->curcfg.supp_capab.param_50000fdx;
926                 break;
927 
928         case ETHER_STAT_CAP_100GFDX:
929                 *value = qede->curcfg.supp_capab.param_100000fdx;
930                 break;
931 
932         /*
933          * Advertised speeds. These indicate what hardware is currently sending.
934          */
935         case ETHER_STAT_ADV_CAP_1000HDX:
936                 *value = qede->curcfg.adv_capab.param_1000hdx;
937                 break;
938 
939         case ETHER_STAT_ADV_CAP_1000FDX:
940                 *value = qede->curcfg.adv_capab.param_1000fdx;
941                 break;
942 
943         case ETHER_STAT_ADV_CAP_10GFDX:
944                 *value = qede->curcfg.adv_capab.param_10000fdx;
945                 break;
946 
947         case ETHER_STAT_ADV_CAP_25GFDX:
948                 *value = qede->curcfg.adv_capab.param_25000fdx;
949                 break;
950 
951         case ETHER_STAT_ADV_CAP_40GFDX:
952                 *value = qede->curcfg.adv_capab.param_40000fdx;
953                 break;
954 
955         case ETHER_STAT_ADV_CAP_50GFDX:
956                 *value = qede->curcfg.adv_capab.param_50000fdx;
957                 break;
958 
959         case ETHER_STAT_ADV_CAP_100GFDX:
960                 *value = qede->curcfg.adv_capab.param_100000fdx;
961                 break;
962 
963 	default:
964 		rc = ENOTSUP;
965 	}
966 
967 	mutex_exit(&qede->gld_lock);
968 	return (rc);
969 }
970 
971 /* (flag) TRUE = on, FALSE = off */
972 static int
973 qede_mac_promiscuous(void *arg,
974     boolean_t on)
975 {
976     	qede_t *qede = (qede_t *)arg;
977 	qede_print("!%s(%d): called", __func__,qede->instance);
978 	int ret = DDI_SUCCESS;
979 	enum qede_filter_rx_mode_type mode;
980 
981 	mutex_enter(&qede->drv_lock);
982 
983 	if (qede->qede_state == QEDE_STATE_SUSPENDED) {
984 		ret = ECANCELED;
985 		goto exit;
986 	}
987 
988 	if (on) {
989 		qede_info(qede, "Entering promiscuous mode");
990 		mode = QEDE_FILTER_RX_MODE_PROMISC;
991 		qede->params.promisc_fl = B_TRUE;
992 	} else {
993 		qede_info(qede, "Leaving promiscuous mode");
994 		if(qede->params.multi_promisc_fl == B_TRUE) {
995 			mode = QEDE_FILTER_RX_MODE_MULTI_PROMISC;
996 		} else {
997 			 mode = QEDE_FILTER_RX_MODE_REGULAR;
998 		}
999 		qede->params.promisc_fl = B_FALSE;
1000 	}
1001 
1002 	ret = qede_set_filter_rx_mode(qede, mode);
1003 
1004 exit:
1005 	mutex_exit(&qede->drv_lock);
1006     	return (ret);
1007 }
1008 
1009 int qede_set_rx_mac_mcast(qede_t *qede, enum ecore_filter_opcode opcode,
1010 			  uint8_t *mac, int mc_cnt)
1011 {
1012 	struct ecore_filter_mcast cmd;
1013 	int i;
1014 	memset(&cmd, 0, sizeof(cmd));
1015 	cmd.opcode = opcode;
1016 	cmd.num_mc_addrs = mc_cnt;
1017 
1018         for (i = 0; i < mc_cnt; i++, mac += ETH_ALLEN) {
1019 		COPY_ETH_ADDRESS(mac, cmd.mac[i]);
1020         }
1021 
1022 
1023         return (ecore_filter_mcast_cmd(&qede->edev, &cmd,
1024 	    ECORE_SPQ_MODE_CB, NULL));
1025 
1026 }
1027 
1028 int
1029 qede_set_filter_rx_mode(qede_t * qede, enum qede_filter_rx_mode_type type)
1030 {
1031 	struct ecore_filter_accept_flags flg;
1032 
1033 	memset(&flg, 0, sizeof(flg));
1034 
1035 	flg.update_rx_mode_config      = 1;
1036 	flg.update_tx_mode_config      = 1;
1037 	flg.rx_accept_filter           = ECORE_ACCEPT_UCAST_MATCHED |
1038 	    ECORE_ACCEPT_MCAST_MATCHED | ECORE_ACCEPT_BCAST;
1039 	flg.tx_accept_filter = ECORE_ACCEPT_UCAST_MATCHED |
1040 	    ECORE_ACCEPT_MCAST_MATCHED | ECORE_ACCEPT_BCAST;
1041 
1042 	if (type == QEDE_FILTER_RX_MODE_PROMISC)
1043 		flg.rx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED |
1044 		    ECORE_ACCEPT_MCAST_UNMATCHED;
1045 	else if (type == QEDE_FILTER_RX_MODE_MULTI_PROMISC)
1046 		flg.rx_accept_filter |= ECORE_ACCEPT_MCAST_UNMATCHED;
1047 	qede_info(qede, "rx_mode rx_filter=0x%x tx_filter=0x%x type=0x%x\n",
1048 	    flg.rx_accept_filter, flg.tx_accept_filter, type);
1049 	return (ecore_filter_accept_cmd(&qede->edev, 0, flg,
1050 			0, /* update_accept_any_vlan */
1051 			0, /* accept_any_vlan */
1052 			ECORE_SPQ_MODE_CB, NULL));
1053 }
1054 
1055 int
1056 qede_multicast(qede_t *qede, boolean_t flag, const uint8_t *ptr_mcaddr)
1057 {
1058 	int i, ret = DDI_SUCCESS;
1059 	qede_mcast_list_entry_t *ptr_mlist;
1060 	qede_mcast_list_entry_t *ptr_entry;
1061 	int mc_cnt;
1062 	unsigned char *mc_macs, *tmpmc;
1063 	size_t size;
1064 	boolean_t mcmac_exists = B_FALSE;
1065 	enum qede_filter_rx_mode_type mode;
1066 
1067 	if (!ptr_mcaddr)  {
1068 		cmn_err(CE_NOTE, "Removing all multicast");
1069 	} else  {
1070 		cmn_err(CE_NOTE,
1071 		    "qede=%p %s multicast: %02x:%02x:%02x:%02x:%02x:%02x",
1072 		    qede, (flag) ? "Adding" : "Removing", ptr_mcaddr[0],
1073 		    ptr_mcaddr[1],ptr_mcaddr[2],ptr_mcaddr[3],ptr_mcaddr[4],
1074 		    ptr_mcaddr[5]);
1075 	}
1076 
1077 
1078 	if (flag && (ptr_mcaddr == NULL)) {
1079 		cmn_err(CE_WARN, "ERROR: Multicast address not specified");
1080 		return EINVAL;
1081 	}
1082 
1083 
1084 	/* exceeds addition of mcaddr above limit */
1085 	if (flag && (qede->mc_cnt >= MAX_MC_SOFT_LIMIT)) {
1086 		qede_info(qede, "Cannot add more than MAX_MC_SOFT_LIMIT");
1087 		return ENOENT;
1088 	}
1089 
1090 	size = MAX_MC_SOFT_LIMIT * ETH_ALLEN;
1091 
1092 	mc_macs = kmem_zalloc(size, KM_NOSLEEP);
1093 	if (!mc_macs) {
1094 		cmn_err(CE_WARN, "ERROR: Failed to allocate for mc_macs");
1095 		return EINVAL;
1096 	}
1097 
1098 	tmpmc = mc_macs;
1099 
1100         /* remove all multicast - as flag not set and mcaddr not specified*/
1101         if (!flag && (ptr_mcaddr == NULL)) {
1102                 QEDE_LIST_FOR_EACH_ENTRY(ptr_entry,
1103 		    &qede->mclist.head, qede_mcast_list_entry_t, mclist_entry)
1104                 {
1105                         if (ptr_entry != NULL) {
1106                         QEDE_LIST_REMOVE(&ptr_entry->mclist_entry,
1107 			    &qede->mclist.head);
1108                         kmem_free(ptr_entry,
1109 			    sizeof (qede_mcast_list_entry_t) + ETH_ALLEN);
1110                         }
1111                 }
1112 
1113                 ret = qede_set_rx_mac_mcast(qede,
1114 		    ECORE_FILTER_REMOVE, mc_macs, 1);
1115                 qede->mc_cnt = 0;
1116                 goto exit;
1117         }
1118 
1119         QEDE_LIST_FOR_EACH_ENTRY(ptr_entry,
1120 	    &qede->mclist.head, qede_mcast_list_entry_t, mclist_entry)
1121         {
1122                 if ((ptr_entry != NULL) &&
1123 		    IS_ETH_ADDRESS_EQUAL(ptr_mcaddr, ptr_entry->mac)) {
1124                         mcmac_exists = B_TRUE;
1125                         break;
1126                 }
1127         }
1128         if (flag && mcmac_exists) {
1129                 ret = DDI_SUCCESS;
1130                 goto exit;
1131         } else if (!flag && !mcmac_exists) {
1132                 ret = DDI_SUCCESS;
1133                 goto exit;
1134         }
1135 
1136        if (flag) {
1137                 ptr_entry = kmem_zalloc((sizeof (qede_mcast_list_entry_t) +
1138 		    ETH_ALLEN), KM_NOSLEEP);
1139                 ptr_entry->mac = (uint8_t *)ptr_entry +
1140 		    sizeof (qede_mcast_list_entry_t);
1141                 COPY_ETH_ADDRESS(ptr_mcaddr, ptr_entry->mac);
1142                 QEDE_LIST_ADD(&ptr_entry->mclist_entry, &qede->mclist.head);
1143         } else {
1144                 QEDE_LIST_REMOVE(&ptr_entry->mclist_entry, &qede->mclist.head);
1145                 kmem_free(ptr_entry, sizeof(qede_mcast_list_entry_t) +
1146 		    ETH_ALLEN);
1147         }
1148 
1149 	mc_cnt = 0;
1150         QEDE_LIST_FOR_EACH_ENTRY(ptr_entry, &qede->mclist.head,
1151 	    qede_mcast_list_entry_t, mclist_entry) {
1152                 COPY_ETH_ADDRESS(ptr_entry->mac, tmpmc);
1153                 tmpmc += ETH_ALLEN;
1154                 mc_cnt++;
1155         }
1156         qede->mc_cnt = mc_cnt;
1157         if (mc_cnt <=64) {
1158                 ret = qede_set_rx_mac_mcast(qede, ECORE_FILTER_ADD,
1159 		    (unsigned char *)mc_macs, mc_cnt);
1160                 if ((qede->params.multi_promisc_fl == B_TRUE) &&
1161 		    (qede->params.promisc_fl == B_FALSE)) {
1162                         mode = QEDE_FILTER_RX_MODE_REGULAR;
1163                         ret = qede_set_filter_rx_mode(qede, mode);
1164                 }
1165                 qede->params.multi_promisc_fl = B_FALSE;
1166         } else {
1167                 if ((qede->params.multi_promisc_fl == B_FALSE) &&
1168 		    (qede->params.promisc_fl == B_FALSE)) {
1169                         ret = qede_set_filter_rx_mode(qede,
1170 			    QEDE_FILTER_RX_MODE_MULTI_PROMISC);
1171                 }
1172                 qede->params.multi_promisc_fl = B_TRUE;
1173                 qede_info(qede, "mode is MULTI_PROMISC");
1174         }
1175 exit:
1176 kmem_free(mc_macs, size);
1177 qede_info(qede, "multicast ret %d mc_cnt %d\n", ret, qede->mc_cnt);
1178 return (ret);
1179 }
1180 
1181 /*
1182  * This function is used to enable or disable multicast packet reception for
1183  * particular multicast addresses.
1184  * (flag) TRUE = add, FALSE = remove
1185  */
1186 static int
1187 qede_mac_multicast(void *arg,
1188     boolean_t       flag,
1189     const uint8_t * mcast_addr)
1190 {
1191 	qede_t *qede = (qede_t *)arg;
1192 	int ret = DDI_SUCCESS;
1193 
1194 
1195 	mutex_enter(&qede->gld_lock);
1196 	if(qede->qede_state != QEDE_STATE_STARTED) {
1197 		mutex_exit(&qede->gld_lock);
1198 		return (EAGAIN);
1199 	}
1200 	ret = qede_multicast(qede, flag, mcast_addr);
1201 
1202 	mutex_exit(&qede->gld_lock);
1203 
1204     return (ret);
1205 }
1206 int
1207 qede_clear_filters(qede_t *qede)
1208 {
1209 	int ret = 0;
1210 	int i;
1211 	if ((qede->params.promisc_fl == B_TRUE) ||
1212 	    (qede->params.multi_promisc_fl == B_TRUE)) {
1213 		ret = qede_set_filter_rx_mode(qede,
1214 		    QEDE_FILTER_RX_MODE_REGULAR);
1215 		if (ret) {
1216 			qede_info(qede,
1217 			    "qede_clear_filters failed to set rx_mode");
1218 		}
1219 	}
1220 	for (i=0; i < qede->ucst_total; i++)
1221 	{
1222 		if (qede->ucst_mac[i].set) {
1223 			qede_rem_macaddr(qede,
1224 			    qede->ucst_mac[i].mac_addr.ether_addr_octet);
1225 		}
1226 	}
1227 	qede_multicast(qede, B_FALSE, NULL);
1228 	return (ret);
1229 }
1230 
1231 
1232 #ifdef  NO_CROSSBOW
1233 static int
1234 qede_mac_unicast(void *arg,
1235     const uint8_t * mac_addr)
1236 {
1237     qede_t *qede = (qede_t *)arg;
1238     return 0;
1239 }
1240 
1241 
1242 static mblk_t *
1243 qede_mac_tx(void *arg,
1244     mblk_t * mblk)
1245 {
1246     qede_t *qede = (qede_t *)arg;
1247     qede_fastpath_t *fp = &qede->fp_array[0];
1248 
1249     mblk = qede_ring_tx((void *)fp, mblk);
1250 
1251     return (mblk);
1252 }
1253 #endif  /* NO_CROSSBOW */
1254 
1255 
1256 static lb_property_t loopmodes[] = {
1257 	{ normal,       "normal",       QEDE_LOOP_NONE                },
1258 	{ internal,     "internal",     QEDE_LOOP_INTERNAL            },
1259 	{ external,     "external",     QEDE_LOOP_EXTERNAL            },
1260 };
1261 
1262 /*
1263  * Set Loopback mode
1264  */
1265 
1266 static enum ioc_reply
1267 qede_set_loopback_mode(qede_t *qede, uint32_t mode)
1268 {
1269 	int i = 0;
1270 	struct ecore_dev *edev = &qede->edev;
1271 	struct ecore_hwfn *hwfn;
1272 	struct ecore_ptt *ptt = NULL;
1273 	struct ecore_mcp_link_params *link_params;
1274 
1275 	hwfn = &edev->hwfns[0];
1276 	link_params = ecore_mcp_get_link_params(hwfn);
1277 	ptt = ecore_ptt_acquire(hwfn);
1278 
1279 	switch(mode) {
1280 	default:
1281 		qede_info(qede, "unknown loopback mode !!");
1282 		ecore_ptt_release(hwfn, ptt);
1283 		return IOC_INVAL;
1284 
1285 	case QEDE_LOOP_NONE:
1286 		ecore_mcp_set_link(hwfn, ptt, 0);
1287 
1288 		while (qede->params.link_state && i < 5000) {
1289 			OSAL_MSLEEP(1);
1290 			i++;
1291 		}
1292 		i = 0;
1293 
1294 		link_params->loopback_mode = ETH_LOOPBACK_NONE;
1295 		qede->loop_back_mode = QEDE_LOOP_NONE;
1296 		(void) ecore_mcp_set_link(hwfn, ptt, 1);
1297 		ecore_ptt_release(hwfn, ptt);
1298 
1299 		while (!qede->params.link_state && i < 5000) {
1300 			OSAL_MSLEEP(1);
1301 			i++;
1302 		}
1303 		return IOC_REPLY;
1304 
1305 	case QEDE_LOOP_INTERNAL:
1306 		qede_print("!%s(%d) : loopback mode (INTERNAL) is set!",
1307 		    __func__, qede->instance);
1308 		    ecore_mcp_set_link(hwfn, ptt, 0);
1309 
1310 		while(qede->params.link_state && i < 5000) {
1311 			OSAL_MSLEEP(1);
1312 			i++;
1313 		}
1314 		i = 0;
1315 		link_params->loopback_mode = ETH_LOOPBACK_INT_PHY;
1316 		qede->loop_back_mode = QEDE_LOOP_INTERNAL;
1317 		(void) ecore_mcp_set_link(hwfn, ptt, 1);
1318 		ecore_ptt_release(hwfn, ptt);
1319 
1320 		while(!qede->params.link_state && i < 5000) {
1321 			OSAL_MSLEEP(1);
1322 			i++;
1323 		}
1324 		return IOC_REPLY;
1325 
1326 	case QEDE_LOOP_EXTERNAL:
1327 		qede_print("!%s(%d) : External loopback mode is not supported",
1328 		    __func__, qede->instance);
1329 		ecore_ptt_release(hwfn, ptt);
1330 		return IOC_INVAL;
1331 	}
1332 }
1333 
1334 static int
1335 qede_ioctl_pcicfg_rd(qede_t *qede, u32 addr, void *data,
1336     int len)
1337 {
1338 	u32 crb, actual_crb;
1339 	uint32_t ret = 0;
1340 	int cap_offset = 0, cap_id = 0, next_cap = 0;
1341 	ddi_acc_handle_t pci_cfg_handle  = qede->pci_cfg_handle;
1342 	qede_ioctl_data_t * data1 = (qede_ioctl_data_t *) data;
1343 
1344 	cap_offset = pci_config_get8(pci_cfg_handle, PCI_CONF_CAP_PTR);
1345 	while (cap_offset != 0) {
1346                 /* Check for an invalid PCI read. */
1347                 if (cap_offset == PCI_EINVAL8) {
1348                         return DDI_FAILURE;
1349                 }
1350 		cap_id = pci_config_get8(pci_cfg_handle, cap_offset);
1351 		if (cap_id == PCI_CAP_ID_PCI_E) {
1352 			/* PCIe expr capab struct found */
1353 			break;
1354 		} else {
1355 			next_cap = pci_config_get8(pci_cfg_handle,
1356 			    cap_offset + 1);
1357 			cap_offset = next_cap;
1358 		}
1359 	}
1360 
1361 	switch (len) {
1362 	case 1:
1363 		ret = pci_config_get8(qede->pci_cfg_handle, addr);
1364 		(void) memcpy(data, &ret, sizeof(uint8_t));
1365 		break;
1366 	case 2:
1367 		ret = pci_config_get16(qede->pci_cfg_handle, addr);
1368 		(void) memcpy(data, &ret, sizeof(uint16_t));
1369 		break;
1370 	case 4:
1371 		ret = pci_config_get32(qede->pci_cfg_handle, addr);
1372 		(void) memcpy(data, &ret, sizeof(uint32_t));
1373 		break;
1374 	default:
1375 		cmn_err(CE_WARN, "bad length for pci config read\n");
1376 		return (1);
1377 	}
1378 	return (0);
1379 }
1380 
1381 static int
1382 qede_ioctl_pcicfg_wr(qede_t *qede, u32 addr, void *data,
1383     int len)
1384 {
1385 	uint16_t ret = 0;
1386 	int cap_offset = 0, cap_id = 0, next_cap = 0;
1387 	qede_ioctl_data_t * data1 = (qede_ioctl_data_t *) data;
1388 	ddi_acc_handle_t pci_cfg_handle  = qede->pci_cfg_handle;
1389 #if 1
1390 	cap_offset = pci_config_get8(pci_cfg_handle, PCI_CONF_CAP_PTR);
1391 	while (cap_offset != 0) {
1392 		cap_id = pci_config_get8(pci_cfg_handle, cap_offset);
1393 		if (cap_id == PCI_CAP_ID_PCI_E) {
1394 			/* PCIe expr capab struct found */
1395 			break;
1396 		} else {
1397 			next_cap = pci_config_get8(pci_cfg_handle,
1398 			    cap_offset + 1);
1399 			cap_offset = next_cap;
1400 		}
1401 	}
1402 #endif
1403 
1404 	switch(len) {
1405 	case 1:
1406 		pci_config_put8(qede->pci_cfg_handle, addr,
1407 		    *(char *)&(data));
1408 		break;
1409 	case 2:
1410 		ret = pci_config_get16(qede->pci_cfg_handle, addr);
1411 		ret = ret | *(uint16_t *)data1->uabc;
1412 
1413 		pci_config_put16(qede->pci_cfg_handle, addr,
1414 		    ret);
1415 		break;
1416 	case 4:
1417 		pci_config_put32(qede->pci_cfg_handle, addr, *(uint32_t *)data1->uabc);
1418 		break;
1419 
1420 	default:
1421 		return (1);
1422 	}
1423 	return (0);
1424 }
1425 
1426 static int
1427 qede_ioctl_rd_wr_reg(qede_t *qede, void *data)
1428 {
1429 	struct ecore_hwfn *p_hwfn;
1430 	struct ecore_dev *edev = &qede->edev;
1431 	struct ecore_ptt *ptt;
1432 	qede_ioctl_data_t *data1 = (qede_ioctl_data_t *)data;
1433 	uint32_t ret = 0;
1434 	uint8_t cmd = (uint8_t) data1->unused1;
1435 	uint32_t addr = data1->off;
1436 	uint32_t val = *(uint32_t *)&data1->uabc[1];
1437 	uint32_t hwfn_index = *(uint32_t *)&data1->uabc[5];
1438 	uint32_t *reg_addr;
1439 
1440 	if (hwfn_index > qede->num_hwfns) {
1441 		cmn_err(CE_WARN, "invalid hwfn index from application\n");
1442 		return (EINVAL);
1443 	}
1444 	p_hwfn = &edev->hwfns[hwfn_index];
1445 
1446 	switch(cmd) {
1447 	case QEDE_REG_READ:
1448 		ret = ecore_rd(p_hwfn, p_hwfn->p_main_ptt, addr);
1449 		(void) memcpy(data1->uabc, &ret, sizeof(uint32_t));
1450 		break;
1451 
1452 	case QEDE_REG_WRITE:
1453 		ecore_wr(p_hwfn, p_hwfn->p_main_ptt, addr, val);
1454 		break;
1455 
1456 	default:
1457 		cmn_err(CE_WARN,
1458 		    "wrong command in register read/write from application\n");
1459 		break;
1460 	}
1461 	return (ret);
1462 }
1463 
1464 static int
1465 qede_ioctl_rd_wr_nvram(qede_t *qede, mblk_t *mp)
1466 {
1467 	qede_nvram_data_t *data1 = (qede_nvram_data_t *)(mp->b_cont->b_rptr);
1468 	qede_nvram_data_t *data2, *next_data;
1469 	struct ecore_dev *edev = &qede->edev;
1470 	uint32_t hdr_size = 24, bytes_to_copy, copy_len = 0;
1471 	uint32_t copy_len1 = 0;
1472 	uint32_t addr = data1->off;
1473 	uint32_t size = data1->size, i, buf_size;
1474 	uint8_t cmd, cmd2;
1475 	uint8_t *buf, *tmp_buf;
1476 	mblk_t *mp1;
1477 
1478 	cmd = (uint8_t)data1->unused1;
1479 
1480 	switch(cmd) {
1481 	case QEDE_NVRAM_CMD_READ:
1482 		buf = kmem_zalloc(size, GFP_KERNEL);
1483 		if(buf == NULL) {
1484 			cmn_err(CE_WARN, "memory allocation failed"
1485 			" in nvram read ioctl\n");
1486 			return (DDI_FAILURE);
1487 		}
1488 		(void) ecore_mcp_nvm_read(edev, addr, buf, data1->size);
1489 
1490 		copy_len = (MBLKL(mp->b_cont)) - hdr_size;
1491 		if(copy_len > size) {
1492 			(void) memcpy(data1->uabc, buf, size);
1493 			kmem_free(buf, size);
1494 			//OSAL_FREE(edev, buf);
1495 			break;
1496 		}
1497 		(void) memcpy(data1->uabc, buf, copy_len);
1498 		bytes_to_copy = size - copy_len;
1499 		tmp_buf = ((uint8_t *)buf) + copy_len;
1500 		copy_len1 = copy_len;
1501 		mp1 = mp->b_cont;
1502 		mp1 = mp1->b_cont;
1503 
1504 		while (mp1) {
1505 			copy_len = MBLKL(mp1);
1506 			if(mp1->b_cont == NULL) {
1507 				copy_len = MBLKL(mp1) - 4;
1508 			}
1509 			data2 = (qede_nvram_data_t *)mp1->b_rptr;
1510 			if (copy_len > bytes_to_copy) {
1511 				(void) memcpy(data2->uabc, tmp_buf,
1512 				    bytes_to_copy);
1513 				kmem_free(buf, size);
1514 				//OSAL_FREE(edev, buf);
1515 				break;
1516 			}
1517 			(void) memcpy(data2->uabc, tmp_buf, copy_len);
1518 			tmp_buf = tmp_buf + copy_len;
1519 			copy_len += copy_len;
1520 			mp1 = mp1->b_cont;
1521 			bytes_to_copy = bytes_to_copy - copy_len;
1522 		}
1523 
1524 		kmem_free(buf, size);
1525 		//OSAL_FREE(edev, buf);
1526 		break;
1527 
1528 	case QEDE_NVRAM_CMD_WRITE:
1529 		cmd2 = (uint8_t )data1->cmd2;
1530 		size = data1->size;
1531 		addr = data1->off;
1532 		buf_size =  size; //data1->buf_size;
1533 		//buf_size =  data1->buf_size;
1534 
1535 		switch(cmd2){
1536 		case START_NVM_WRITE:
1537 			buf = kmem_zalloc(size, GFP_KERNEL);
1538 			//buf = qede->reserved_buf;
1539 			qede->nvm_buf_size = data1->size;
1540 			if(buf == NULL) {
1541 				cmn_err(CE_WARN,
1542 				"memory allocation failed in START_NVM_WRITE\n");
1543 				return DDI_FAILURE;
1544 			}
1545 			qede->nvm_buf_start = buf;
1546 			cmn_err(CE_NOTE,
1547 			    "buf = %p, size = %x\n", qede->nvm_buf_start, size);
1548 			qede->nvm_buf = buf;
1549 			qede->copy_len = 0;
1550 			//tmp_buf = buf + addr;
1551 			break;
1552 
1553 		case ACCUMULATE_NVM_BUF:
1554 			tmp_buf = qede->nvm_buf;
1555 			copy_len = MBLKL(mp->b_cont) - hdr_size;
1556 			if(copy_len > buf_size) {
1557 			 	if (buf_size < qede->nvm_buf_size) {
1558 				(void) memcpy(tmp_buf, data1->uabc, buf_size);
1559 					qede->copy_len = qede->copy_len +
1560 					    buf_size;
1561 				} else {
1562 					(void) memcpy(tmp_buf,
1563 					    data1->uabc, qede->nvm_buf_size);
1564 					qede->copy_len =
1565 					    qede->copy_len + qede->nvm_buf_size;
1566 				}
1567 				tmp_buf = tmp_buf + buf_size;
1568 				qede->nvm_buf = tmp_buf;
1569 				//qede->copy_len = qede->copy_len + buf_size;
1570 				cmn_err(CE_NOTE,
1571 				    "buf_size from app = %x\n", copy_len);
1572 				break;
1573 			}
1574 			(void) memcpy(tmp_buf, data1->uabc, copy_len);
1575 			tmp_buf = tmp_buf + copy_len;
1576 			bytes_to_copy = buf_size - copy_len;
1577 			mp1 = mp->b_cont;
1578 			mp1 = mp1->b_cont;
1579 			copy_len1 = copy_len;
1580 
1581 			while (mp1) {
1582 				copy_len = MBLKL(mp1);
1583 				if (mp1->b_cont == NULL) {
1584 					copy_len = MBLKL(mp1) - 4;
1585 				}
1586 				next_data = (qede_nvram_data_t *) mp1->b_rptr;
1587 				if (copy_len > bytes_to_copy){
1588 					(void) memcpy(tmp_buf, next_data->uabc,
1589 					    bytes_to_copy);
1590 					qede->copy_len = qede->copy_len +
1591 					    bytes_to_copy;
1592 					break;
1593 				}
1594 				(void) memcpy(tmp_buf, next_data->uabc,
1595 				    copy_len);
1596 				qede->copy_len = qede->copy_len + copy_len;
1597 				tmp_buf = tmp_buf + copy_len;
1598 				copy_len = copy_len1 + copy_len;
1599 				bytes_to_copy = bytes_to_copy - copy_len;
1600 				mp1 = mp1->b_cont;
1601 			}
1602 			qede->nvm_buf = tmp_buf;
1603 			break;
1604 
1605 		case STOP_NVM_WRITE:
1606 			//qede->nvm_buf = tmp_buf;
1607 			break;
1608 		case READ_BUF:
1609 			tmp_buf = (uint8_t *)qede->nvm_buf_start;
1610 			for(i = 0; i < size ; i++){
1611 				cmn_err(CE_NOTE,
1612 				    "buff (%d) : %d\n", i, *tmp_buf);
1613 				tmp_buf ++;
1614 			}
1615 			break;
1616 		}
1617 		break;
1618 	case QEDE_NVRAM_CMD_PUT_FILE_DATA:
1619 		tmp_buf = qede->nvm_buf_start;
1620 		(void) ecore_mcp_nvm_write(edev, ECORE_PUT_FILE_DATA,
1621 			  addr, tmp_buf, size);
1622 		kmem_free(qede->nvm_buf_start, size);
1623 		//OSAL_FREE(edev, tmp_buf);
1624 		cmn_err(CE_NOTE, "total size = %x, copied size = %x\n",
1625 		    qede->nvm_buf_size, qede->copy_len);
1626 		tmp_buf = NULL;
1627 		qede->nvm_buf = NULL;
1628 		qede->nvm_buf_start = NULL;
1629 		break;
1630 
1631 	case QEDE_NVRAM_CMD_SET_SECURE_MODE:
1632 		(void) ecore_mcp_nvm_set_secure_mode(edev, addr);
1633 		break;
1634 
1635 	case QEDE_NVRAM_CMD_DEL_FILE:
1636 		(void) ecore_mcp_nvm_del_file(edev, addr);
1637 		break;
1638 
1639 	case QEDE_NVRAM_CMD_PUT_FILE_BEGIN:
1640 		(void) ecore_mcp_nvm_put_file_begin(edev, addr);
1641 		break;
1642 
1643 	case QEDE_NVRAM_CMD_GET_NVRAM_RESP:
1644 		buf = kmem_zalloc(size, KM_SLEEP);
1645 		(void) ecore_mcp_nvm_resp(edev, buf);
1646 		(void)memcpy(data1->uabc, buf, size);
1647 		kmem_free(buf, size);
1648 		break;
1649 
1650 	default:
1651 		cmn_err(CE_WARN,
1652 		    "wrong command in NVRAM read/write from application\n");
1653 		break;
1654 	}
1655 	return (DDI_SUCCESS);
1656 }
1657 
1658 static int
1659 qede_get_func_info(qede_t *qede, void *data)
1660 {
1661 	qede_link_output_t link_op;
1662 	qede_func_info_t func_info;
1663 	qede_ioctl_data_t *data1 = (qede_ioctl_data_t *)data;
1664 	struct ecore_dev *edev = &qede->edev;
1665 	struct ecore_hwfn *hwfn;
1666 	struct ecore_mcp_link_params params;
1667 	struct ecore_mcp_link_state link;
1668 
1669 	hwfn = &edev->hwfns[0];
1670 
1671 	if(hwfn == NULL){
1672 		cmn_err(CE_WARN, "(%s) : cannot acquire hwfn\n",
1673 		    __func__);
1674 		return (DDI_FAILURE);
1675 	}
1676 	memcpy(&params, &hwfn->mcp_info->link_input, sizeof(params));
1677 	memcpy(&link, &hwfn->mcp_info->link_output, sizeof(link));
1678 
1679 	if(link.link_up) {
1680 		link_op.link_up = true;
1681 	}
1682 
1683 	link_op.supported_caps = SUPPORTED_FIBRE;
1684 	if(params.speed.autoneg) {
1685 		link_op.supported_caps |= SUPPORTED_Autoneg;
1686 	}
1687 
1688 	if(params.pause.autoneg ||
1689 	    (params.pause.forced_rx && params.pause.forced_tx)) {
1690 		link_op.supported_caps |= SUPPORTED_Asym_Pause;
1691 	}
1692 
1693 	if (params.pause.autoneg || params.pause.forced_rx ||
1694 	     params.pause.forced_tx) {
1695 		link_op.supported_caps |= SUPPORTED_Pause;
1696 	}
1697 
1698 	if (params.speed.advertised_speeds &
1699 	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
1700 		link_op.supported_caps |= SUPPORTED_1000baseT_Half |
1701 	    	    SUPPORTED_1000baseT_Full;
1702 	}
1703 
1704 	if (params.speed.advertised_speeds &
1705 	    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
1706 		link_op.supported_caps |= SUPPORTED_10000baseKR_Full;
1707 	}
1708 
1709 	if (params.speed.advertised_speeds &
1710 	    NVM_CFG1_PORT_DRV_LINK_SPEED_40G) {
1711 		link_op.supported_caps |= SUPPORTED_40000baseLR4_Full;
1712 	}
1713 
1714 	link_op.advertised_caps = link_op.supported_caps;
1715 
1716 	if(link.link_up) {
1717 		link_op.speed = link.speed;
1718 	} else {
1719 		link_op.speed = 0;
1720 	}
1721 
1722 	link_op.duplex = DUPLEX_FULL;
1723 	link_op.port = PORT_FIBRE;
1724 
1725 	link_op.autoneg = params.speed.autoneg;
1726 
1727 	/* Link partner capabilities */
1728 	if (link.partner_adv_speed &
1729 	    ECORE_LINK_PARTNER_SPEED_1G_HD) {
1730 		link_op.lp_caps |= SUPPORTED_1000baseT_Half;
1731 	}
1732 
1733 	if (link.partner_adv_speed &
1734 	    ECORE_LINK_PARTNER_SPEED_1G_FD) {
1735 		link_op.lp_caps |= SUPPORTED_1000baseT_Full;
1736 	}
1737 
1738 	if (link.partner_adv_speed &
1739 	    ECORE_LINK_PARTNER_SPEED_10G) {
1740 		link_op.lp_caps |= SUPPORTED_10000baseKR_Full;
1741 	}
1742 
1743 	if (link.partner_adv_speed &
1744 	    ECORE_LINK_PARTNER_SPEED_20G) {
1745 		link_op.lp_caps |= SUPPORTED_20000baseKR2_Full;
1746 	}
1747 
1748 	if (link.partner_adv_speed &
1749 	    ECORE_LINK_PARTNER_SPEED_40G) {
1750 		link_op.lp_caps |= SUPPORTED_40000baseLR4_Full;
1751 	}
1752 
1753 	if (link.an_complete) {
1754 		link_op.lp_caps |= SUPPORTED_Autoneg;
1755 	}
1756 
1757 	if (link.partner_adv_pause) {
1758 		link_op.lp_caps |= SUPPORTED_Pause;
1759 	}
1760 
1761 	if (link.partner_adv_pause == ECORE_LINK_PARTNER_ASYMMETRIC_PAUSE ||
1762 	    link.partner_adv_pause == ECORE_LINK_PARTNER_BOTH_PAUSE) {
1763 		link_op.lp_caps |= SUPPORTED_Asym_Pause;
1764 	}
1765 
1766 	func_info.supported = link_op.supported_caps;
1767 	func_info.advertising = link_op.advertised_caps;
1768 	func_info.speed = link_op.speed;
1769 	func_info.duplex = link_op.duplex;
1770 	func_info.port = qede->pci_func & 0x1;
1771 	func_info.autoneg = link_op.autoneg;
1772 
1773 	(void) memcpy(data1->uabc, &func_info, sizeof(qede_func_info_t));
1774 
1775 	return (0);
1776 }
1777 
1778 static int
1779 qede_do_ioctl(qede_t *qede, queue_t *q, mblk_t *mp)
1780 {
1781 	qede_ioctl_data_t *up_data;
1782 	qede_driver_info_t driver_info;
1783 	struct ecore_dev *edev = &qede->edev;
1784 	struct ecore_hwfn *hwfn;
1785 	struct ecore_ptt *ptt = NULL;
1786 	struct mcp_file_att attrib;
1787 	uint32_t flash_size;
1788 	uint32_t mcp_resp, mcp_param, txn_size;
1789 	uint32_t cmd, size, ret = 0;
1790 	uint64_t off;
1791 	int * up_data1;
1792 	void * ptr;
1793 	mblk_t *mp1 = mp;
1794 	char mac_addr[32];
1795 
1796 	up_data = (qede_ioctl_data_t *)(mp->b_cont->b_rptr);
1797 
1798 	cmd = up_data->cmd;
1799 	off = up_data->off;
1800 	size = up_data->size;
1801 
1802 	switch (cmd) {
1803 	case QEDE_DRV_INFO:
1804 		hwfn = &edev->hwfns[0];
1805 		ptt = ecore_ptt_acquire(hwfn);
1806 
1807 		snprintf(driver_info.drv_name, MAX_QEDE_NAME_LEN, "%s", "qede");
1808 		snprintf(driver_info.drv_version, QEDE_STR_SIZE,
1809 		    "v:%s", qede->version);
1810 		snprintf(driver_info.mfw_version, QEDE_STR_SIZE,
1811 		    "%s", qede->versionMFW);
1812 		snprintf(driver_info.stormfw_version, QEDE_STR_SIZE,
1813 		    "%s", qede->versionFW);
1814 		snprintf(driver_info.bus_info, QEDE_STR_SIZE,
1815 		    "%s", qede->bus_dev_func);
1816 
1817 
1818 		/*
1819 		 * calling ecore_mcp_nvm_rd_cmd to find the flash length, i
1820 		 * 0x08 is equivalent of NVM_TYPE_MFW_TRACE1
1821 		 */
1822 		ecore_mcp_get_flash_size(hwfn, ptt, &flash_size);
1823 		driver_info.eeprom_dump_len = flash_size;
1824 		(void) memcpy(up_data->uabc, &driver_info,
1825 		    sizeof (qede_driver_info_t));
1826 		up_data->size = sizeof (qede_driver_info_t);
1827 
1828 		ecore_ptt_release(hwfn, ptt);
1829 		break;
1830 
1831 	case QEDE_RD_PCICFG:
1832 		ret = qede_ioctl_pcicfg_rd(qede, off, up_data->uabc, size);
1833 		break;
1834 
1835 	case QEDE_WR_PCICFG:
1836 		ret = qede_ioctl_pcicfg_wr(qede, off, up_data, size);
1837 		break;
1838 
1839 	case QEDE_RW_REG:
1840 		ret = qede_ioctl_rd_wr_reg(qede, (void *)up_data);
1841 	       	break;
1842 
1843 	case QEDE_RW_NVRAM:
1844 		ret = qede_ioctl_rd_wr_nvram(qede, mp1);
1845 		break;
1846 
1847 	case QEDE_FUNC_INFO:
1848 		ret = qede_get_func_info(qede, (void *)up_data);
1849 		break;
1850 
1851 	case QEDE_MAC_ADDR:
1852 		snprintf(mac_addr, sizeof(mac_addr),
1853 			"%02x:%02x:%02x:%02x:%02x:%02x",
1854 			qede->ether_addr[0], qede->ether_addr[1],
1855 			qede->ether_addr[2], qede->ether_addr[3],
1856 			qede->ether_addr[4], qede->ether_addr[5]);
1857 		(void) memcpy(up_data->uabc, &mac_addr, sizeof(mac_addr));
1858 		break;
1859 
1860 	}
1861 	//if (cmd == QEDE_RW_NVRAM) {
1862 	//	miocack (q, mp, (sizeof(qede_ioctl_data_t)), 0);
1863 	//	return IOC_REPLY;
1864 	//}
1865 	miocack (q, mp, (sizeof(qede_ioctl_data_t)), ret);
1866 	//miocack (q, mp, 0, ret);
1867 	return (IOC_REPLY);
1868 }
1869 
1870 static void
1871 qede_ioctl(qede_t *qede, int cmd, queue_t *q, mblk_t *mp)
1872 {
1873 	void *ptr;
1874 
1875 	switch(cmd) {
1876 	case QEDE_CMD:
1877 		(void) qede_do_ioctl(qede, q, mp);
1878 		break;
1879 	default :
1880 		cmn_err(CE_WARN, "qede ioctl command %x not supported\n", cmd);
1881 		break;
1882 	}
1883 	return;
1884 }
1885 enum ioc_reply
1886 qede_loopback_ioctl(qede_t *qede, queue_t *wq, mblk_t *mp,
1887     struct iocblk *iocp)
1888 {
1889 	lb_info_sz_t *lb_info_size;
1890 	lb_property_t *lb_prop;
1891 	uint32_t *lb_mode;
1892 	int cmd;
1893 
1894 	/*
1895 	 * Validate format of ioctl
1896 	 */
1897 	if(mp->b_cont == NULL) {
1898 		return IOC_INVAL;
1899 	}
1900 
1901 	cmd = iocp->ioc_cmd;
1902 
1903 	switch(cmd) {
1904 	default:
1905 		qede_print("!%s(%d): unknown ioctl command %x\n",
1906 		    __func__, qede->instance, cmd);
1907 		return IOC_INVAL;
1908 	case LB_GET_INFO_SIZE:
1909 		if (iocp->ioc_count != sizeof(lb_info_sz_t)) {
1910 			qede_info(qede, "error: ioc_count %d, sizeof %d",
1911 			    iocp->ioc_count,  sizeof(lb_info_sz_t));
1912 			return IOC_INVAL;
1913 		}
1914 		lb_info_size = (void *)mp->b_cont->b_rptr;
1915 		*lb_info_size = sizeof(loopmodes);
1916 		return IOC_REPLY;
1917 	case LB_GET_INFO:
1918 		if (iocp->ioc_count != sizeof (loopmodes)) {
1919 			qede_info(qede, "error: iocp->ioc_count %d, sizepof %d",
1920 			    iocp->ioc_count,  sizeof (loopmodes));
1921 			return (IOC_INVAL);
1922 		}
1923 		lb_prop = (void *)mp->b_cont->b_rptr;
1924 		bcopy(loopmodes, lb_prop, sizeof (loopmodes));
1925 		return IOC_REPLY;
1926 	case LB_GET_MODE:
1927 		if (iocp->ioc_count != sizeof (uint32_t)) {
1928 			qede_info(qede, "iocp->ioc_count %d, sizeof : %d\n",
1929 			    iocp->ioc_count, sizeof (uint32_t));
1930 			return (IOC_INVAL);
1931 		}
1932 		lb_mode = (void *)mp->b_cont->b_rptr;
1933 		*lb_mode = qede->loop_back_mode;
1934 		return IOC_REPLY;
1935 	case LB_SET_MODE:
1936 		if (iocp->ioc_count != sizeof (uint32_t)) {
1937 			qede_info(qede, "iocp->ioc_count %d, sizeof : %d\n",
1938 			    iocp->ioc_count, sizeof (uint32_t));
1939 			return (IOC_INVAL);
1940 		}
1941 		lb_mode = (void *)mp->b_cont->b_rptr;
1942 		return (qede_set_loopback_mode(qede,*lb_mode));
1943 	}
1944 }
1945 
1946 static void
1947 qede_mac_ioctl(void *    arg,
1948                queue_t * wq,
1949                mblk_t *  mp)
1950 {
1951 	int err, cmd;
1952     	qede_t * qede = (qede_t *)arg;
1953     	struct iocblk *iocp = (struct iocblk *) (uintptr_t)mp->b_rptr;
1954     	enum ioc_reply status = IOC_DONE;
1955     	boolean_t need_privilege = B_TRUE;
1956 
1957 	iocp->ioc_error = 0;
1958 	cmd = iocp->ioc_cmd;
1959 
1960 	mutex_enter(&qede->drv_lock);
1961 	if ((qede->qede_state == QEDE_STATE_SUSPENDING) ||
1962 	   (qede->qede_state == QEDE_STATE_SUSPENDED)) {
1963 		mutex_exit(&qede->drv_lock);
1964 		miocnak(wq, mp, 0, EINVAL);
1965 		return;
1966 	}
1967 
1968 	switch(cmd) {
1969 		case QEDE_CMD:
1970 			break;
1971 		case LB_GET_INFO_SIZE:
1972 		case LB_GET_INFO:
1973 		case LB_GET_MODE:
1974 			need_privilege = B_FALSE;
1975 		case LB_SET_MODE:
1976 			break;
1977 		default:
1978 			qede_print("!%s(%d) unknown ioctl command %x\n",
1979 			    __func__, qede->instance, cmd);
1980 			miocnak(wq, mp, 0, EINVAL);
1981 			mutex_exit(&qede->drv_lock);
1982 			return;
1983 	}
1984 
1985 	if(need_privilege) {
1986 		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
1987 		if(err){
1988 			qede_info(qede, "secpolicy() failed");
1989 			miocnak(wq, mp, 0, err);
1990 		       	mutex_exit(&qede->drv_lock);
1991 			return;
1992 		}
1993 	}
1994 
1995 	switch (cmd) {
1996 		default:
1997 			qede_print("!%s(%d) : unknown ioctl command %x\n",
1998 			    __func__, qede->instance, cmd);
1999 			status = IOC_INVAL;
2000 			mutex_exit(&qede->drv_lock);
2001 			return;
2002 		case LB_GET_INFO_SIZE:
2003 		case LB_GET_INFO:
2004 		case LB_GET_MODE:
2005 		case LB_SET_MODE:
2006 			status = qede_loopback_ioctl(qede, wq, mp, iocp);
2007 			break;
2008 		case QEDE_CMD:
2009 			qede_ioctl(qede, cmd, wq, mp);
2010 			status = IOC_DONE;
2011 			break;
2012 	}
2013 
2014 	switch(status){
2015 		default:
2016 			qede_print("!%s(%d) : invalid status from ioctl",
2017 			    __func__,qede->instance);
2018 			break;
2019 		case IOC_DONE:
2020 			/*
2021 			 * OK, Reply already sent
2022 			 */
2023 
2024 			break;
2025 		case IOC_REPLY:
2026 			mp->b_datap->db_type = iocp->ioc_error == 0 ?
2027 				M_IOCACK : M_IOCNAK;
2028 			qreply(wq, mp);
2029 			break;
2030 		case IOC_INVAL:
2031 			mutex_exit(&qede->drv_lock);
2032 			//miocack(wq, mp, 0, 0);
2033 			miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
2034 			    EINVAL : iocp->ioc_error);
2035 			return;
2036 	}
2037 	mutex_exit(&qede->drv_lock);
2038 }
2039 
2040 extern ddi_dma_attr_t qede_buf2k_dma_attr_txbuf;
2041 extern ddi_dma_attr_t qede_dma_attr_rxbuf;
2042 extern ddi_dma_attr_t qede_dma_attr_desc;
2043 
2044 static boolean_t
2045 qede_mac_get_capability(void *arg,
2046 	mac_capab_t capability,
2047 	void *      cap_data)
2048 {
2049  	qede_t * qede = (qede_t *)arg;
2050 	uint32_t *txflags = cap_data;
2051 	boolean_t ret = B_FALSE;
2052 
2053 	switch (capability) {
2054 	case MAC_CAPAB_HCKSUM: {
2055 		u32 *tx_flags = cap_data;
2056 		/*
2057 		 * Check if checksum is enabled on
2058 		 * tx and advertise the cksum capab
2059 		 * to mac layer accordingly. On Rx
2060 		 * side checksummed packets are
2061 		 * reveiced anyway
2062 		 */
2063 		qede_info(qede, "%s tx checksum offload",
2064 		    (qede->checksum == DEFAULT_CKSUM_OFFLOAD) ?
2065 		    "Enabling":
2066 		    "Disabling");
2067 
2068 		if (qede->checksum != DEFAULT_CKSUM_OFFLOAD) {
2069 			ret = B_FALSE;
2070 			break;
2071 		}
2072                 /*
2073                  * Hardware does not support ICMPv6 checksumming. Right now the
2074                  * GLDv3 doesn't provide us a way to specify that we don't
2075                  * support that. As such, we cannot indicate
2076                  * HCKSUM_INET_FULL_V6.
2077                  */
2078 
2079 		*tx_flags = HCKSUM_INET_FULL_V4 |
2080 		    HCKSUM_IPHDRCKSUM;
2081 		ret = B_TRUE;
2082 		break;
2083 	}
2084 	case MAC_CAPAB_LSO: {
2085 		mac_capab_lso_t *cap_lso = (mac_capab_lso_t *)cap_data;
2086 
2087 		qede_info(qede, "%s large segmentation offload",
2088 		    qede->lso_enable ? "Enabling": "Disabling");
2089 		if (qede->lso_enable) {
2090 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
2091 			cap_lso->lso_basic_tcp_ipv4.lso_max = QEDE_LSO_MAXLEN;
2092 			ret = B_TRUE;
2093 		}
2094 		break;
2095 	}
2096 	case MAC_CAPAB_RINGS: {
2097 #ifndef NO_CROSSBOW
2098 		mac_capab_rings_t *cap_rings = cap_data;
2099 #ifndef ILLUMOS
2100 		cap_rings->mr_version = MAC_RINGS_VERSION_1;
2101 #endif
2102 
2103 		switch (cap_rings->mr_type) {
2104 		case MAC_RING_TYPE_RX:
2105 #ifndef ILLUMOS
2106 			cap_rings->mr_flags = MAC_RINGS_VLAN_TRANSPARENT;
2107 #endif
2108 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
2109 			//cap_rings->mr_rnum = 1; /* qede variable */
2110 			cap_rings->mr_rnum = qede->num_fp; /* qede variable */
2111 			cap_rings->mr_gnum = 1;
2112 			cap_rings->mr_rget = qede_fill_ring;
2113 			cap_rings->mr_gget = qede_fill_group;
2114 			cap_rings->mr_gaddring = NULL;
2115 			cap_rings->mr_gremring = NULL;
2116 #ifndef	ILLUMOS
2117 			cap_rings->mr_ggetringtc = NULL;
2118 #endif
2119 			ret = B_TRUE;
2120 			break;
2121 		case MAC_RING_TYPE_TX:
2122 #ifndef ILLUMOS
2123 			cap_rings->mr_flags = MAC_RINGS_VLAN_TRANSPARENT;
2124 #endif
2125 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
2126 			//cap_rings->mr_rnum = 1;
2127 			cap_rings->mr_rnum = qede->num_fp;
2128 			cap_rings->mr_gnum = 0;
2129 			cap_rings->mr_rget = qede_fill_ring;
2130 			cap_rings->mr_gget = qede_fill_group;
2131 			cap_rings->mr_gaddring = NULL;
2132 			cap_rings->mr_gremring = NULL;
2133 #ifndef	ILLUMOS
2134 			cap_rings->mr_ggetringtc = NULL;
2135 #endif
2136 			ret = B_TRUE;
2137 			break;
2138 		default:
2139 			ret = B_FALSE;
2140 			break;
2141 		}
2142 #endif
2143 		break; /* CASE MAC_CAPAB_RINGS */
2144 	}
2145 #ifdef ILLUMOS
2146         case MAC_CAPAB_TRANSCEIVER: {
2147                 mac_capab_transceiver_t *mct = cap_data;
2148 
2149                 mct->mct_flags = 0;
2150                 mct->mct_ntransceivers = qede->edev.num_hwfns;
2151                 mct->mct_info = qede_transceiver_info;
2152                 mct->mct_read = qede_transceiver_read;
2153 
2154                 ret = B_TRUE;
2155                 break;
2156         }
2157 #endif
2158 	default:
2159 		break;
2160 	}
2161 
2162     return (ret);
2163 }
2164 
2165 int
2166 qede_configure_link(qede_t *qede, bool op);
2167 
2168 static int
2169 qede_mac_set_property(void *        arg,
2170                               const char *  pr_name,
2171                               mac_prop_id_t pr_num,
2172                               uint_t        pr_valsize,
2173                               const void *  pr_val)
2174 {
2175 	qede_t * qede = (qede_t *)arg;
2176 	struct ecore_mcp_link_params *link_params;
2177 	struct ecore_dev *edev = &qede->edev;
2178 	struct ecore_hwfn *hwfn;
2179 	int ret_val = 0, i;
2180 	uint32_t option;
2181 
2182 	mutex_enter(&qede->gld_lock);
2183 	switch (pr_num)
2184 	{
2185         case MAC_PROP_MTU:
2186                 bcopy(pr_val, &option, sizeof (option));
2187 
2188                 if(option == qede->mtu) {
2189                         ret_val = 0;
2190                         break;
2191                 }
2192                 if ((option != DEFAULT_JUMBO_MTU) &&
2193                    (option != DEFAULT_MTU)) {
2194                         ret_val = EINVAL;
2195                         break;
2196                 }
2197                 if(qede->qede_state == QEDE_STATE_STARTED) {
2198                         ret_val = EBUSY;
2199                         break;
2200                 }
2201 
2202                 ret_val = mac_maxsdu_update(qede->mac_handle, qede->mtu);
2203                 if (ret_val == 0) {
2204 
2205                         qede->mtu = option;
2206                         if (option == DEFAULT_JUMBO_MTU) {
2207                                 qede->jumbo_enable = B_TRUE;
2208 			} else {
2209 				qede->jumbo_enable = B_FALSE;
2210 			}
2211 
2212                         hwfn = ECORE_LEADING_HWFN(edev);
2213                         hwfn->hw_info.mtu = qede->mtu;
2214                         ret_val = ecore_mcp_ov_update_mtu(hwfn,
2215 			    hwfn->p_main_ptt,
2216 			    hwfn->hw_info.mtu);
2217                         if (ret_val != ECORE_SUCCESS) {
2218                                 qede_print("!%s(%d): MTU change %d option %d"
2219 				    "FAILED",
2220 				    __func__,qede->instance, qede->mtu, option);
2221 				break;
2222 			}
2223                         qede_print("!%s(%d): MTU changed  %d MTU option"
2224 			    " %d hwfn %d",
2225 			    __func__,qede->instance, qede->mtu,
2226 			    option, hwfn->hw_info.mtu);
2227                 }
2228                 break;
2229 
2230 	case MAC_PROP_EN_10GFDX_CAP:
2231 		hwfn = &edev->hwfns[0];
2232 		link_params = ecore_mcp_get_link_params(hwfn);
2233 		if (*(uint8_t *) pr_val) {
2234 			link_params->speed.autoneg = 0;
2235 			link_params->speed.forced_speed = 10000;
2236 			link_params->speed.advertised_speeds =
2237 			    NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
2238 			qede->forced_speed_10G = *(uint8_t *)pr_val;
2239 		}
2240 		else {
2241 			memcpy(link_params,
2242 			    &qede->link_input_params.default_link_params,
2243 			    sizeof (struct ecore_mcp_link_params));
2244 			qede->forced_speed_10G = *(uint8_t *)pr_val;
2245 		}
2246 		if (qede->qede_state == QEDE_STATE_STARTED) {
2247 			qede_configure_link(qede,1);
2248 		} else {
2249 			mutex_exit(&qede->gld_lock);
2250 			return (0);
2251 		}
2252 		break;
2253 	default:
2254 		ret_val = ENOTSUP;
2255 		break;
2256 	}
2257 	mutex_exit(&qede->gld_lock);
2258 	return (ret_val);
2259 }
2260 
2261 static void
2262 qede_mac_stop(void *arg)
2263 {
2264     qede_t *qede = (qede_t *)arg;
2265 	int status;
2266 
2267 	qede_print("!%s(%d): called",
2268 	    __func__,qede->instance);
2269 	mutex_enter(&qede->drv_lock);
2270 	status = qede_stop(qede);
2271 	if (status != DDI_SUCCESS) {
2272 		qede_print("!%s(%d): qede_stop "
2273 		    "FAILED",
2274 	        __func__,qede->instance);
2275 	}
2276 
2277 	mac_link_update(qede->mac_handle, LINK_STATE_UNKNOWN);
2278 	mutex_exit(&qede->drv_lock);
2279 }
2280 
2281 static int
2282 qede_mac_start(void *arg)
2283 {
2284     	qede_t *qede = (qede_t *)arg;
2285 	int status;
2286 
2287 	qede_print("!%s(%d): called", __func__,qede->instance);
2288 	if (!mutex_tryenter(&qede->drv_lock)) {
2289 		return (EAGAIN);
2290 	}
2291 
2292 	if (qede->qede_state == QEDE_STATE_SUSPENDED) {
2293 		mutex_exit(&qede->drv_lock);
2294 		return (ECANCELED);
2295 	}
2296 
2297 	status = qede_start(qede);
2298 	if (status != DDI_SUCCESS) {
2299 		mutex_exit(&qede->drv_lock);
2300 		return (EIO);
2301 	}
2302 
2303 	mutex_exit(&qede->drv_lock);
2304 
2305 #ifdef	DBLK_DMA_PREMAP
2306 	qede->pm_handle = mac_pmh_tx_get(qede->mac_handle);
2307 #endif
2308 	return (0);
2309 }
2310 
2311 static int
2312 qede_mac_get_property(void *arg,
2313     const char *pr_name,
2314     mac_prop_id_t pr_num,
2315     uint_t        pr_valsize,
2316     void *pr_val)
2317 {
2318 	qede_t *qede = (qede_t *)arg;
2319 	struct ecore_dev *edev = &qede->edev;
2320 	link_state_t    link_state;
2321 	link_duplex_t   link_duplex;
2322 	uint64_t        link_speed;
2323 	link_flowctrl_t link_flowctrl;
2324 	struct qede_link_cfg link_cfg;
2325 	qede_link_cfg_t  *hw_cfg  = &qede->hwinit;
2326 	int ret_val = 0;
2327 
2328 	memset(&link_cfg, 0, sizeof (struct qede_link_cfg));
2329 	qede_get_link_info(&edev->hwfns[0], &link_cfg);
2330 
2331 
2332 
2333 	switch (pr_num)
2334 	{
2335 	case MAC_PROP_MTU:
2336 
2337 		ASSERT(pr_valsize >= sizeof(uint32_t));
2338 		bcopy(&qede->mtu, pr_val, sizeof(uint32_t));
2339 		break;
2340 
2341 	case MAC_PROP_DUPLEX:
2342 
2343 		ASSERT(pr_valsize >= sizeof(link_duplex_t));
2344 		link_duplex = (qede->props.link_duplex) ?
2345 					  LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
2346 		bcopy(&link_duplex, pr_val, sizeof(link_duplex_t));
2347 		break;
2348 
2349 	case MAC_PROP_SPEED:
2350 
2351 		ASSERT(pr_valsize >= sizeof(link_speed));
2352 
2353 		link_speed = (qede->props.link_speed * 1000000ULL);
2354 		bcopy(&link_speed, pr_val, sizeof(link_speed));
2355 	    	break;
2356 
2357 	case MAC_PROP_STATUS:
2358 
2359 		ASSERT(pr_valsize >= sizeof(link_state_t));
2360 
2361 		link_state = (qede->params.link_state) ?
2362 		                        LINK_STATE_UP : LINK_STATE_DOWN;
2363 		bcopy(&link_state, pr_val, sizeof(link_state_t));
2364 		qede_info(qede, "mac_prop_status %d\n", link_state);
2365 		break;
2366 
2367 	case MAC_PROP_AUTONEG:
2368 
2369 		*(uint8_t *)pr_val = link_cfg.autoneg;
2370 		break;
2371 
2372 	case MAC_PROP_FLOWCTRL:
2373 
2374 		ASSERT(pr_valsize >= sizeof(link_flowctrl_t));
2375 
2376 /*
2377  * illumos does not have the notion of LINK_FLOWCTRL_AUTO at this time.
2378  */
2379 #ifndef	ILLUMOS
2380 		if (link_cfg.pause_cfg & QEDE_LINK_PAUSE_AUTONEG_ENABLE)  {
2381 	            link_flowctrl = LINK_FLOWCTRL_AUTO;
2382 		}
2383 #endif
2384 
2385 		if (!(link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) &&
2386 		    !(link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2387 	            link_flowctrl = LINK_FLOWCTRL_NONE;
2388 		}
2389 		if ((link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) &&
2390 		    !(link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2391 	            link_flowctrl = LINK_FLOWCTRL_RX;
2392 	    	}
2393         	if (!(link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) &&
2394 		    (link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2395 	            link_flowctrl = LINK_FLOWCTRL_TX;
2396 		}
2397 		if ((link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) &&
2398 		    (link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2399 	            link_flowctrl = LINK_FLOWCTRL_BI;
2400 		}
2401 
2402         	bcopy(&link_flowctrl, pr_val, sizeof (link_flowctrl_t));
2403         	break;
2404 
2405 	case MAC_PROP_ADV_10GFDX_CAP:
2406 		*(uint8_t *)pr_val = link_cfg.adv_capab.param_10000fdx;
2407 		break;
2408 
2409 	case MAC_PROP_EN_10GFDX_CAP:
2410 		*(uint8_t *)pr_val = qede->forced_speed_10G;
2411 		break;
2412 
2413 	case MAC_PROP_PRIVATE:
2414 	default:
2415 		return (ENOTSUP);
2416 
2417 	}
2418 
2419 	return (0);
2420 }
2421 
2422 static void
2423 qede_mac_property_info(void *arg,
2424     const char *pr_name,
2425     mac_prop_id_t  pr_num,
2426     mac_prop_info_handle_t prh)
2427 {
2428 	qede_t *qede = (qede_t *)arg;
2429 	qede_link_props_t *def_cfg = &qede_def_link_props;
2430 	link_flowctrl_t link_flowctrl;
2431 
2432 
2433 	switch (pr_num)
2434 	{
2435 
2436 	case MAC_PROP_STATUS:
2437 	case MAC_PROP_SPEED:
2438 	case MAC_PROP_DUPLEX:
2439 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2440 		break;
2441 
2442 	case MAC_PROP_MTU:
2443 
2444 		mac_prop_info_set_range_uint32(prh,
2445 		    MIN_MTU,
2446 		    MAX_MTU);
2447 		break;
2448 
2449 	case MAC_PROP_AUTONEG:
2450 
2451 		mac_prop_info_set_default_uint8(prh, def_cfg->autoneg);
2452 		break;
2453 
2454 	case MAC_PROP_FLOWCTRL:
2455 
2456 		if (!def_cfg->pause) {
2457 			link_flowctrl = LINK_FLOWCTRL_NONE;
2458 		} else {
2459 			link_flowctrl = LINK_FLOWCTRL_BI;
2460 		}
2461 
2462 		mac_prop_info_set_default_link_flowctrl(prh, link_flowctrl);
2463 		break;
2464 
2465 	case MAC_PROP_EN_10GFDX_CAP:
2466 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
2467 		break;
2468 
2469 	case MAC_PROP_ADV_10GFDX_CAP:
2470 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2471 		break;
2472 
2473 	default:
2474 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2475 		break;
2476 
2477     }
2478 }
2479 
2480 static mac_callbacks_t qede_callbacks =
2481 {
2482     (
2483       MC_IOCTL
2484 /*    | MC_RESOURCES */
2485     | MC_SETPROP
2486     | MC_GETPROP
2487     | MC_PROPINFO
2488     | MC_GETCAPAB
2489     ),
2490     qede_mac_stats,
2491     qede_mac_start,
2492     qede_mac_stop,
2493     qede_mac_promiscuous,
2494     qede_mac_multicast,
2495     NULL,
2496 #ifndef NO_CROSSBOW
2497     NULL,
2498 #else
2499     qede_mac_tx,
2500 #endif
2501     NULL,	/* qede_mac_resources, */
2502     qede_mac_ioctl,
2503     qede_mac_get_capability,
2504     NULL,
2505     NULL,
2506     qede_mac_set_property,
2507     qede_mac_get_property,
2508 #ifdef MC_PROPINFO
2509     qede_mac_property_info
2510 #endif
2511 };
2512 
2513 boolean_t
2514 qede_gld_init(qede_t *qede)
2515 {
2516 	int status, ret;
2517 	mac_register_t *macp;
2518 
2519 	macp = mac_alloc(MAC_VERSION);
2520 	if (macp == NULL) {
2521 		cmn_err(CE_NOTE, "%s: mac_alloc() failed\n", __func__);
2522 		return (B_FALSE);
2523 	}
2524 
2525  	macp->m_driver = qede;
2526 	macp->m_dip = qede->dip;
2527 	macp->m_instance = qede->instance;
2528 	macp->m_priv_props = NULL;
2529 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
2530  	macp->m_src_addr = qede->ether_addr;
2531 	macp->m_callbacks = &qede_callbacks;
2532 	macp->m_min_sdu = 0;
2533 	macp->m_max_sdu = qede->mtu;
2534 	macp->m_margin = VLAN_TAGSZ;
2535 #ifdef	ILLUMOS
2536 	macp->m_v12n = MAC_VIRT_LEVEL1;
2537 #endif
2538 
2539 	status = mac_register(macp, &qede->mac_handle);
2540 	if (status != 0) {
2541 		cmn_err(CE_NOTE, "%s: mac_register() failed\n", __func__);
2542 	}
2543 
2544 	mac_free(macp);
2545 	if (status == 0) {
2546 		return (B_TRUE);
2547 	}
2548 	return (B_FALSE);
2549 }
2550 
2551 boolean_t qede_gld_fini(qede_t * qede)
2552 {
2553     return (B_TRUE);
2554 }
2555 
2556 
2557 void qede_link_update(qede_t * qede,
2558                  link_state_t  state)
2559 {
2560     mac_link_update(qede->mac_handle, state);
2561 }
2562 
2563