1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 QLogic Corporation. All rights reserved.
24 */
25
26 #include <sys/note.h>
27 #include <qlge.h>
28 #include <sys/strsubr.h>
29 #include <netinet/in.h>
30 #include <netinet/ip.h>
31 #include <netinet/ip6.h>
32 #include <inet/ip.h>
33
34 /*
35 * GLDv3 functions prototypes
36 */
37 static int ql_m_getstat(void *, uint_t, uint64_t *);
38 static int ql_m_start(void *);
39 static void ql_m_stop(void *);
40 static int ql_m_setpromiscuous(void *, boolean_t);
41 static int ql_m_multicst(void *, boolean_t, const uint8_t *);
42 static int ql_m_unicst(void *, const uint8_t *);
43 static mblk_t *ql_m_tx(void *, mblk_t *);
44 static void ql_m_ioctl(void *, queue_t *, mblk_t *);
45 static boolean_t ql_m_getcapab(void *, mac_capab_t, void *);
46
47 static int ql_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
48 const void *);
49 static int ql_m_getprop(void *, const char *, mac_prop_id_t, uint_t, void *);
50 static void ql_m_propinfo(void *, const char *, mac_prop_id_t,
51 mac_prop_info_handle_t);
52
53 #define QL_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | \
54 MC_GETPROP | MC_PROPINFO)
55 static mac_callbacks_t ql_m_callbacks = {
56 QL_M_CALLBACK_FLAGS,
57 ql_m_getstat,
58 ql_m_start,
59 ql_m_stop,
60 ql_m_setpromiscuous,
61 ql_m_multicst,
62 NULL,
63 NULL,
64 NULL,
65 ql_m_ioctl,
66 ql_m_getcapab,
67 NULL,
68 NULL,
69 ql_m_setprop,
70 ql_m_getprop,
71 ql_m_propinfo
72 };
73
74 char *qlge_priv_prop[] = {
75 "_adv_pause_mode",
76 "_fm_enable",
77 NULL
78 };
79
80 /*
81 * This function starts the driver
82 */
83 static int
ql_m_start(void * arg)84 ql_m_start(void *arg)
85 {
86 qlge_t *qlge = (qlge_t *)arg;
87
88 /*
89 * reset chip, re-initialize everything but do not
90 * re-allocate memory
91 */
92 mutex_enter(&qlge->gen_mutex);
93 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
94 mutex_exit(&qlge->gen_mutex);
95 return (ECANCELED);
96 }
97 mutex_enter(&qlge->hw_mutex);
98 qlge->mac_flags = QL_MAC_INIT;
99 /*
100 * Write default ethernet address to chip register Mac
101 * Address slot 0 and Enable Primary Mac Function.
102 */
103 (void) ql_unicst_set(qlge,
104 (uint8_t *)qlge->unicst_addr[0].addr.ether_addr_octet, 0);
105 qlge->stats.rpackets = 0;
106 qlge->stats.rbytes = 0;
107 qlge->stats.opackets = 0;
108 qlge->stats.obytes = 0;
109 mutex_exit(&qlge->hw_mutex);
110
111 (void) ql_do_start(qlge);
112 mutex_exit(&qlge->gen_mutex);
113
114 mutex_enter(&qlge->mbx_mutex);
115 (void) ql_get_firmware_version(qlge, NULL);
116 mutex_exit(&qlge->mbx_mutex);
117
118 return (0);
119 }
120
121 /*
122 * This function stops the driver
123 */
124 static void
ql_m_stop(void * arg)125 ql_m_stop(void *arg)
126 {
127 qlge_t *qlge = (qlge_t *)arg;
128
129 mutex_enter(&qlge->gen_mutex);
130 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
131 mutex_exit(&qlge->gen_mutex);
132 return;
133 }
134 (void) ql_do_stop(qlge);
135 mutex_exit(&qlge->gen_mutex);
136 qlge->mac_flags = QL_MAC_STOPPED;
137 }
138
139 /*
140 * Add or remove a multicast address
141 */
142 static int
ql_m_multicst(void * arg,boolean_t add,const uint8_t * ep)143 ql_m_multicst(void *arg, boolean_t add, const uint8_t *ep)
144 {
145 qlge_t *qlge = (qlge_t *)arg;
146 int ret = DDI_SUCCESS;
147
148 mutex_enter(&qlge->gen_mutex);
149 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
150 mutex_exit(&qlge->gen_mutex);
151 return (ECANCELED);
152 }
153
154 if (qlge->mac_flags == QL_MAC_DETACH) {
155 mutex_exit(&qlge->gen_mutex);
156 return (ECANCELED);
157 }
158 if (add) {
159 QL_DUMP(DBG_GLD, "add to multicast list:\n",
160 (uint8_t *)ep, 8, ETHERADDRL);
161 ret = ql_add_to_multicast_list(qlge, (uint8_t *)ep);
162 } else {
163 QL_DUMP(DBG_GLD, "remove from multicast list:\n",
164 (uint8_t *)ep, 8, ETHERADDRL);
165 ret = ql_remove_from_multicast_list(qlge, (uint8_t *)ep);
166 }
167 mutex_exit(&qlge->gen_mutex);
168
169 if (ret != DDI_SUCCESS) {
170 ret = EIO;
171 if (qlge->fm_enable) {
172 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
173 }
174 } else {
175 ret = 0;
176 }
177 return (ret);
178 }
179
180 /*
181 * Enable or disable promiscuous mode
182 */
183 static int
ql_m_setpromiscuous(void * arg,boolean_t on)184 ql_m_setpromiscuous(void* arg, boolean_t on)
185 {
186 qlge_t *qlge = (qlge_t *)arg;
187 int mode;
188
189 mutex_enter(&qlge->gen_mutex);
190 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
191 mutex_exit(&qlge->gen_mutex);
192 return (ECANCELED);
193 }
194
195 /* enable reception of all packets on the medium, */
196 if (on) {
197 mode = 1;
198 QL_PRINT(DBG_GLD, ("%s(%d) enable promiscuous mode\n",
199 __func__, qlge->instance));
200 } else {
201 mode = 0;
202 QL_PRINT(DBG_GLD, ("%s(%d) disable promiscuous mode\n",
203 __func__, qlge->instance));
204 }
205
206 mutex_enter(&qlge->hw_mutex);
207 ql_set_promiscuous(qlge, mode);
208 mutex_exit(&qlge->hw_mutex);
209 mutex_exit(&qlge->gen_mutex);
210 return (DDI_SUCCESS);
211 }
212
213
214 static int
ql_m_getstat(void * arg,uint_t stat,uint64_t * valp)215 ql_m_getstat(void *arg, uint_t stat, uint64_t *valp)
216 {
217 qlge_t *qlge = (qlge_t *)arg;
218 struct ql_stats *cur_stats;
219 uint64_t val = 0;
220 int i;
221 uint32_t val32;
222 struct rx_ring *rx_ring;
223 struct tx_ring *tx_ring;
224
225 ASSERT(qlge != NULL);
226 mutex_enter(&qlge->gen_mutex);
227 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
228 mutex_exit(&qlge->gen_mutex);
229 return (ECANCELED);
230 }
231
232 cur_stats = &qlge->stats;
233 /* these stats are maintained in software */
234 switch (stat) {
235
236 case MAC_STAT_IFSPEED /* 1000 */ :
237 if (CFG_IST(qlge, CFG_CHIP_8100) != 0) {
238 qlge->speed = SPEED_10G;
239 }
240 val = qlge->speed * 1000000ull;
241 break;
242
243 case MAC_STAT_MULTIRCV:
244 val = cur_stats->multircv;
245 break;
246
247 case MAC_STAT_BRDCSTRCV:
248 val = cur_stats->brdcstrcv;
249 break;
250
251 case MAC_STAT_MULTIXMT:
252 cur_stats->multixmt = 0;
253 for (i = 0; i < qlge->tx_ring_count; i++) {
254 tx_ring = &qlge->tx_ring[i];
255 cur_stats->multixmt += tx_ring->multixmt;
256 }
257 val = cur_stats->multixmt;
258 break;
259
260 case MAC_STAT_BRDCSTXMT:
261 cur_stats->brdcstxmt = 0;
262 for (i = 0; i < qlge->tx_ring_count; i++) {
263 tx_ring = &qlge->tx_ring[i];
264 cur_stats->brdcstxmt += tx_ring->brdcstxmt;
265 }
266 val = cur_stats->brdcstxmt;
267 break;
268
269 case MAC_STAT_NORCVBUF:
270 val = cur_stats->norcvbuf;
271 break;
272
273 case MAC_STAT_IERRORS:
274 val = cur_stats->errrcv;
275 break;
276
277 case MAC_STAT_OBYTES:
278 cur_stats->obytes = 0;
279 for (i = 0; i < qlge->tx_ring_count; i++) {
280 tx_ring = &qlge->tx_ring[i];
281 cur_stats->obytes += tx_ring->obytes;
282 }
283 val = cur_stats->obytes;
284 break;
285
286 case MAC_STAT_OPACKETS:
287 cur_stats->opackets = 0;
288 for (i = 0; i < qlge->tx_ring_count; i++) {
289 tx_ring = &qlge->tx_ring[i];
290 cur_stats->opackets += tx_ring->opackets;
291 }
292 val = cur_stats->opackets;
293 break;
294
295 case ETHER_STAT_DEFER_XMTS:
296 cur_stats->defer = 0;
297 for (i = 0; i < qlge->tx_ring_count; i++) {
298 tx_ring = &qlge->tx_ring[i];
299 cur_stats->defer += (tx_ring->defer);
300 }
301 val = cur_stats->defer;
302 break;
303
304 case MAC_STAT_OERRORS:
305 cur_stats->errxmt = 0;
306 for (i = 0; i < qlge->tx_ring_count; i++) {
307 tx_ring = &qlge->tx_ring[i];
308 cur_stats->errxmt += tx_ring->errxmt;
309 }
310 val = cur_stats->errxmt;
311 break;
312
313 case MAC_STAT_RBYTES:
314 cur_stats->rbytes = 0;
315 for (i = 0; i < qlge->rx_ring_count; i++) {
316 rx_ring = &qlge->rx_ring[i];
317 cur_stats->rbytes += rx_ring->rx_bytes;
318 }
319 val = cur_stats->rbytes;
320 break;
321
322 case MAC_STAT_IPACKETS:
323 cur_stats->rpackets = 0;
324 for (i = 0; i < qlge->rx_ring_count; i++) {
325 rx_ring = &qlge->rx_ring[i];
326 cur_stats->rpackets += rx_ring->rx_packets;
327 }
328 val = cur_stats->rpackets;
329 break;
330
331 case ETHER_STAT_FCS_ERRORS:
332 cur_stats->crc = 0;
333 for (i = 0; i < qlge->rx_ring_count; i++) {
334 rx_ring = &qlge->rx_ring[i];
335 cur_stats->crc += rx_ring->fcs_err;
336 }
337 val = cur_stats->crc;
338 break;
339
340 case ETHER_STAT_TOOLONG_ERRORS:
341 cur_stats->frame_too_long = 0;
342 for (i = 0; i < qlge->rx_ring_count; i++) {
343 rx_ring = &qlge->rx_ring[i];
344 cur_stats->frame_too_long +=
345 rx_ring->frame_too_long;
346 }
347 val = cur_stats->frame_too_long;
348 break;
349
350 case ETHER_STAT_XCVR_INUSE:
351 val = XCVR_1000X;
352 break;
353 case ETHER_STAT_JABBER_ERRORS:
354 if (ql_sem_spinlock(qlge, qlge->xgmac_sem_mask) !=
355 DDI_SUCCESS) {
356 break;
357 }
358 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_JABBER_PKTS,
359 &val32);
360 val = val32;
361 ql_sem_unlock(qlge, qlge->xgmac_sem_mask);
362 QL_PRINT(DBG_STATS, ("%s(%d) MAC_STAT_JABBER_ERRORS "
363 "status %d\n", __func__, qlge->instance, val));
364 break;
365 case ETHER_STAT_LINK_DUPLEX:
366 if (qlge->duplex == 1)
367 val = LINK_DUPLEX_FULL;
368 else
369 val = LINK_DUPLEX_HALF;
370 break;
371
372 /* statics saved in hw */
373 case ETHER_STAT_MACRCV_ERRORS:
374 val = 0;
375 if (ql_sem_spinlock(qlge, qlge->xgmac_sem_mask) !=
376 DDI_SUCCESS) {
377 break;
378 }
379 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_ALIGN_ERR,
380 &val32);
381 val += val32;
382 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_FCS_ERR, &val32);
383 val += val32;
384 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_JABBER_PKTS,
385 &val32);
386 val += val32;
387 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_SYM_ERR,
388 &val32);
389 val += val32;
390 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_INT_ERR,
391 &val32);
392 val += val32;
393 ql_sem_unlock(qlge, qlge->xgmac_sem_mask);
394 break;
395
396 default:
397 mutex_exit(&qlge->gen_mutex);
398 return (ENOTSUP);
399 }
400 *valp = val;
401 mutex_exit(&qlge->gen_mutex);
402
403 return (0);
404
405 }
406
407 /*
408 * Set the physical network address
409 */
410 int
ql_unicst_set(qlge_t * qlge,const uint8_t * macaddr,int slot)411 ql_unicst_set(qlge_t *qlge, const uint8_t *macaddr, int slot)
412 {
413 int ret;
414
415 ret = ql_sem_spinlock(qlge, SEM_MAC_ADDR_MASK);
416 if (ret != DDI_SUCCESS)
417 goto exit;
418 ret = ql_set_mac_addr_reg(qlge, (uint8_t *)macaddr,
419 MAC_ADDR_TYPE_CAM_MAC,
420 (uint16_t)(qlge->func_number * MAX_CQ + slot));
421 ql_sem_unlock(qlge, SEM_MAC_ADDR_MASK);
422
423 exit:
424 if (ret != DDI_SUCCESS) {
425 ret = EIO;
426 if (qlge->fm_enable) {
427 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
428 }
429 } else {
430 ret = 0;
431 }
432 return (ret);
433 }
434
435 /*
436 * Set default MAC address
437 * Each function has a total of 128 mac address, function0: 0~127,
438 * function1 128~254 etc or func_number *128 + n (0~127), but
439 * we only support one MAC address, so its address is
440 * func_number*128+0
441 */
442 static int
ql_m_unicst(void * arg,const uint8_t * mac)443 ql_m_unicst(void *arg, const uint8_t *mac)
444 {
445 qlge_t *qlge = (qlge_t *)arg;
446 int status;
447
448 ASSERT(qlge->mac_flags != QL_MAC_DETACH);
449 mutex_enter(&qlge->gen_mutex);
450 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
451 mutex_exit(&qlge->gen_mutex);
452 return (ECANCELED);
453 }
454
455 mutex_enter(&qlge->hw_mutex);
456 bcopy(mac, qlge->unicst_addr[0].addr.ether_addr_octet, ETHERADDRL);
457 /* Set Mac Address to slot 0 and Enable Primary Mac Function */
458 status = ql_unicst_set(qlge, mac, 0);
459 mutex_exit(&qlge->hw_mutex);
460 mutex_exit(&qlge->gen_mutex);
461
462 return (status);
463 }
464
465 /*
466 * ql_m_tx is used only for sending data packets into ethernet wire.
467 */
468 static mblk_t *
ql_m_tx(void * arg,mblk_t * mp)469 ql_m_tx(void *arg, mblk_t *mp)
470 {
471 qlge_t *qlge = (qlge_t *)arg;
472 struct tx_ring *tx_ring;
473 mblk_t *next;
474 int rval;
475 uint32_t tx_count = 0;
476 caddr_t bp;
477 uint8_t selected_ring = 0;
478
479 if ((qlge->port_link_state == LS_DOWN) ||
480 (qlge->mac_flags != QL_MAC_STARTED)) {
481
482 cmn_err(CE_WARN, "!%s(%d): exit due to link down",
483 __func__, qlge->instance);
484 freemsgchain(mp);
485 mp = NULL;
486 goto tx_exit;
487 }
488
489 /*
490 * Calculate which tx ring to send this packet
491 */
492 bp = (caddr_t)mp->b_rptr;
493 selected_ring = ql_tx_hashing(qlge, bp);
494 tx_ring = &qlge->tx_ring[selected_ring];
495 mutex_enter(&tx_ring->tx_lock);
496 if (tx_ring->mac_flags != QL_MAC_STARTED) {
497 mutex_exit(&tx_ring->tx_lock);
498 goto tx_exit;
499 }
500
501 /* we must try to send all */
502 while (mp != NULL) {
503 /*
504 * if number of available slots is less than a threshold,
505 * then quit
506 */
507 if (tx_ring->tx_free_count <= TX_STOP_THRESHOLD) {
508 tx_ring->queue_stopped = 1;
509 rval = DDI_FAILURE;
510 /*
511 * If we return the buffer back we are expected to
512 * call mac_tx_ring_update() when
513 * resources are available
514 */
515 tx_ring->defer++;
516 break;
517 }
518 next = mp->b_next;
519 mp->b_next = NULL;
520
521 rval = ql_send_common(tx_ring, mp);
522
523 if (rval != DDI_SUCCESS) {
524 mp->b_next = next;
525 break;
526 }
527 tx_count++;
528 mp = next;
529 }
530 /*
531 * After all msg blocks are mapped or copied to tx buffer,
532 * trigger the hardware to send the msg!
533 */
534 if (tx_count > 0) {
535 ql_write_doorbell_reg(tx_ring->qlge, tx_ring->prod_idx_db_reg,
536 tx_ring->prod_idx);
537 }
538 mutex_exit(&tx_ring->tx_lock);
539 tx_exit:
540 return (mp);
541 }
542
543 static void
ql_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)544 ql_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
545 {
546 qlge_t *qlge = (qlge_t *)arg;
547 struct iocblk *iocp;
548 boolean_t need_privilege = B_TRUE;
549 int err, cmd;
550 enum ioc_reply status;
551
552 /*
553 * Validate the command before bothering with the mutex...
554 */
555 iocp = (struct iocblk *)(void *)mp->b_rptr;
556 iocp->ioc_error = 0;
557 cmd = iocp->ioc_cmd;
558
559 mutex_enter(&qlge->gen_mutex);
560 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
561 mutex_exit(&qlge->gen_mutex);
562 miocnak(wq, mp, 0, EINVAL);
563 return;
564 }
565 switch (cmd) {
566 default:
567 QL_PRINT(DBG_GLD, ("unknown ioctl cmd \n"));
568 miocnak(wq, mp, 0, EINVAL);
569 mutex_exit(&qlge->gen_mutex);
570 return;
571 case QLA_PCI_STATUS:
572 case QLA_WRITE_REG:
573 case QLA_READ_PCI_REG:
574 case QLA_WRITE_PCI_REG:
575 case QLA_GET_DBGLEAVEL:
576 case QLA_SET_DBGLEAVEL:
577 case QLA_READ_CONTRL_REGISTERS:
578 case QLA_MANUAL_READ_FLASH:
579 case QLA_MANUAL_WRITE_FLASH:
580 case QLA_GET_BINARY_CORE_DUMP:
581 case QLA_SUPPORTED_DUMP_TYPES:
582 case QLA_TRIGGER_SYS_ERROR_EVENT:
583 case QLA_READ_FLASH:
584 case QLA_WRITE_FLASH:
585 case QLA_READ_VPD:
586 case QLA_GET_PROP:
587 case QLA_SHOW_REGION:
588 case QLA_LIST_ADAPTER_INFO:
589 case QLA_READ_FW_IMAGE:
590 case QLA_WRITE_FW_IMAGE_HEADERS:
591 case QLA_CONTINUE_COPY_IN:
592 case QLA_CONTINUE_COPY_OUT:
593 case QLA_SOFT_RESET:
594 break;
595 case LB_GET_INFO_SIZE:
596 case LB_GET_INFO:
597 case LB_GET_MODE:
598 need_privilege = B_FALSE;
599 /* FALLTHRU */
600 case LB_SET_MODE:
601 break;
602 }
603
604 if (need_privilege) {
605 /*
606 * Check for specific net_config privilege
607 */
608 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
609 if (err != 0) {
610 miocnak(wq, mp, 0, err);
611 mutex_exit(&qlge->gen_mutex);
612 return;
613 }
614 }
615 /*
616 * Implement ioctl
617 */
618 switch (cmd) {
619 case QLA_PCI_STATUS:
620 case QLA_WRITE_REG:
621 case QLA_READ_PCI_REG:
622 case QLA_WRITE_PCI_REG:
623 case QLA_GET_DBGLEAVEL:
624 case QLA_SET_DBGLEAVEL:
625 case QLA_READ_CONTRL_REGISTERS:
626 case QLA_MANUAL_READ_FLASH:
627 case QLA_MANUAL_WRITE_FLASH:
628 case QLA_GET_BINARY_CORE_DUMP:
629 case QLA_SUPPORTED_DUMP_TYPES:
630 case QLA_TRIGGER_SYS_ERROR_EVENT:
631 case QLA_READ_FLASH:
632 case QLA_WRITE_FLASH:
633 case QLA_READ_VPD:
634 case QLA_GET_PROP:
635 case QLA_SHOW_REGION:
636 case QLA_LIST_ADAPTER_INFO:
637 case QLA_READ_FW_IMAGE:
638 case QLA_WRITE_FW_IMAGE_HEADERS:
639 case QLA_CONTINUE_COPY_IN:
640 case QLA_CONTINUE_COPY_OUT:
641 case QLA_SOFT_RESET:
642 status = ql_chip_ioctl(qlge, wq, mp);
643 break;
644 case LB_GET_INFO_SIZE:
645 case LB_GET_INFO:
646 case LB_GET_MODE:
647 case LB_SET_MODE:
648 status = ql_loop_ioctl(qlge, wq, mp, iocp);
649 break;
650 default:
651 status = IOC_INVAL;
652 break;
653 }
654
655 /*
656 * Decide how to reply
657 */
658 switch (status) {
659 default:
660 case IOC_INVAL:
661 /*
662 * Error, reply with a NAK and EINVAL or the specified error
663 */
664 miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
665 EINVAL : iocp->ioc_error);
666 break;
667
668 case IOC_DONE:
669 /*
670 * OK, reply already sent
671 */
672 break;
673
674 case IOC_ACK:
675 /*
676 * OK, reply with an ACK
677 */
678 miocack(wq, mp, 0, 0);
679 break;
680
681 case IOC_REPLY:
682 /*
683 * OK, send prepared reply as ACK or NAK
684 */
685 mp->b_datap->db_type = (uint8_t)(iocp->ioc_error == 0 ?
686 M_IOCACK : M_IOCNAK);
687 qreply(wq, mp);
688 break;
689 }
690 mutex_exit(&qlge->gen_mutex);
691 }
692 /* ARGSUSED */
693 static int
qlge_set_priv_prop(qlge_t * qlge,const char * pr_name,uint_t pr_valsize,const void * pr_val)694 qlge_set_priv_prop(qlge_t *qlge, const char *pr_name, uint_t pr_valsize,
695 const void *pr_val)
696 {
697 int err = 0;
698 long result;
699
700 if (strcmp(pr_name, "_adv_pause_mode") == 0) {
701 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
702 if (result > PAUSE_MODE_PER_PRIORITY ||
703 result < PAUSE_MODE_DISABLED) {
704 err = EINVAL;
705 } else if (qlge->pause != (uint32_t)result) {
706 qlge->pause = (uint32_t)result;
707 if (qlge->flags & INTERRUPTS_ENABLED) {
708 mutex_enter(&qlge->mbx_mutex);
709 if (ql_set_pause_mode(qlge) == DDI_FAILURE)
710 err = EINVAL;
711 mutex_exit(&qlge->mbx_mutex);
712 }
713 }
714 return (err);
715 } else if (strcmp(pr_name, "_fm_enable") == 0) {
716 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
717 if ((result != 0) && (result != 1)) {
718 err = EINVAL;
719 } else if (qlge->fm_enable != (boolean_t)result) {
720 qlge->fm_enable = (boolean_t)result;
721 }
722 return (err);
723 }
724 return (ENOTSUP);
725 }
726
727 /*
728 * callback functions for set/get of properties
729 */
730 /* ARGSUSED */
731 static int
ql_m_setprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)732 ql_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
733 uint_t pr_valsize, const void *pr_val)
734 {
735 qlge_t *qlge = barg;
736 int err = 0;
737 uint32_t cur_mtu, new_mtu;
738
739 mutex_enter(&qlge->gen_mutex);
740 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
741 mutex_exit(&qlge->gen_mutex);
742 return (ECANCELED);
743 }
744
745 switch (pr_num) {
746 case MAC_PROP_MTU:
747 cur_mtu = qlge->mtu;
748 bcopy(pr_val, &new_mtu, sizeof (new_mtu));
749
750 QL_PRINT(DBG_GLD, ("%s(%d) new mtu %d \n",
751 __func__, qlge->instance, new_mtu));
752 if (new_mtu == cur_mtu) {
753 err = 0;
754 break;
755 }
756 if ((new_mtu != ETHERMTU) && (new_mtu != JUMBO_MTU)) {
757 err = EINVAL;
758 break;
759 }
760 /*
761 * do not change on the fly, allow only before
762 * driver is started or stopped
763 */
764 if ((qlge->mac_flags == QL_MAC_STARTED) ||
765 (qlge->mac_flags == QL_MAC_DETACH)) {
766 err = EBUSY;
767 cmn_err(CE_WARN, "%s(%d) new mtu %d ignored, "
768 "driver busy, mac_flags %d", __func__,
769 qlge->instance, new_mtu, qlge->mac_flags);
770 break;
771 }
772 qlge->mtu = new_mtu;
773 err = mac_maxsdu_update(qlge->mh, qlge->mtu);
774 if (err == 0) {
775 /* EMPTY */
776 QL_PRINT(DBG_GLD, ("%s(%d) new mtu %d set success\n",
777 __func__, qlge->instance,
778 new_mtu));
779 }
780 break;
781 case MAC_PROP_PRIVATE:
782 mutex_exit(&qlge->gen_mutex);
783 err = qlge_set_priv_prop(qlge, pr_name, pr_valsize,
784 pr_val);
785 mutex_enter(&qlge->gen_mutex);
786 break;
787 default:
788 err = ENOTSUP;
789 break;
790 }
791 mutex_exit(&qlge->gen_mutex);
792 return (err);
793 }
794
795 static int
qlge_get_priv_prop(qlge_t * qlge,const char * pr_name,uint_t pr_valsize,void * pr_val)796 qlge_get_priv_prop(qlge_t *qlge, const char *pr_name, uint_t pr_valsize,
797 void *pr_val)
798 {
799 int err = ENOTSUP;
800 uint32_t value;
801
802 if (strcmp(pr_name, "_adv_pause_mode") == 0) {
803 value = qlge->pause;
804 err = 0;
805 } else if (strcmp(pr_name, "_fm_enable") == 0) {
806 value = qlge->fm_enable;
807 err = 0;
808 }
809
810 if (err == 0) {
811 (void) snprintf(pr_val, pr_valsize, "%d", value);
812 }
813 return (err);
814 }
815
816 /* ARGSUSED */
817 static int
ql_m_getprop(void * barg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)818 ql_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
819 uint_t pr_valsize, void *pr_val)
820 {
821 qlge_t *qlge = barg;
822 uint64_t speed;
823 link_state_t link_state;
824 link_duplex_t link_duplex;
825 int err = 0;
826
827 mutex_enter(&qlge->gen_mutex);
828 if (qlge->mac_flags == QL_MAC_SUSPENDED) {
829 err = ECANCELED;
830 goto out;
831 }
832
833 switch (pr_num) {
834 case MAC_PROP_DUPLEX:
835 ASSERT(pr_valsize >= sizeof (link_duplex_t));
836 if (qlge->duplex)
837 link_duplex = LINK_DUPLEX_FULL;
838 else
839 link_duplex = LINK_DUPLEX_HALF;
840
841 bcopy(&link_duplex, pr_val,
842 sizeof (link_duplex_t));
843 break;
844 case MAC_PROP_SPEED:
845 ASSERT(pr_valsize >= sizeof (speed));
846 speed = qlge->speed * 1000000ull;
847 bcopy(&speed, pr_val, sizeof (speed));
848 break;
849 case MAC_PROP_STATUS:
850 ASSERT(pr_valsize >= sizeof (link_state_t));
851 if (qlge->port_link_state == LS_DOWN)
852 link_state = LINK_STATE_DOWN;
853 else
854 link_state = LINK_STATE_UP;
855 bcopy(&link_state, pr_val,
856 sizeof (link_state_t));
857 break;
858
859 case MAC_PROP_PRIVATE:
860 err = qlge_get_priv_prop(qlge, pr_name, pr_valsize, pr_val);
861 break;
862
863 default:
864 err = ENOTSUP;
865 }
866 out:
867 mutex_exit(&qlge->gen_mutex);
868 return (err);
869 }
870
871 /* ARGSUSED */
872 static void
ql_m_propinfo(void * barg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)873 ql_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num,
874 mac_prop_info_handle_t prh)
875 {
876 _NOTE(ARGUNUSED(barg));
877
878 switch (pr_num) {
879 case MAC_PROP_DUPLEX:
880 case MAC_PROP_SPEED:
881 case MAC_PROP_STATUS:
882 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
883 break;
884
885 case MAC_PROP_PRIVATE: {
886 char val_str[64];
887 int default_val;
888
889 if (strcmp(pr_name, "_adv_pause_mode") == 0)
890 default_val = 2;
891 else if (strcmp(pr_name, "_fm_enable") == 0)
892 default_val = 1;
893 else
894 return;
895
896 (void) snprintf(val_str, sizeof (val_str), "%d", default_val);
897 mac_prop_info_set_default_str(prh, val_str);
898 break;
899 }
900 }
901 }
902
903 /* ARGSUSED */
904 static boolean_t
ql_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)905 ql_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
906 {
907 int ret = B_FALSE;
908 uint32_t cksum = 0;
909 qlge_t *qlge = (qlge_t *)arg;
910
911 switch (cap) {
912 case MAC_CAPAB_HCKSUM:
913 if ((qlge->cfg_flags & CFG_CKSUM_FULL_IPv4) != 0) {
914 cksum |= HCKSUM_INET_FULL_V4;
915 }
916 if ((qlge->cfg_flags & CFG_CKSUM_FULL_IPv6) != 0) {
917 cksum |= HCKSUM_INET_FULL_V6;
918 }
919 if ((qlge->cfg_flags & CFG_CKSUM_HEADER_IPv4) != 0) {
920 cksum |= HCKSUM_IPHDRCKSUM;
921 }
922 if ((qlge->cfg_flags & CFG_CKSUM_PARTIAL) != 0) {
923 cksum |= HCKSUM_INET_PARTIAL;
924 }
925 qlge->chksum_cap = cksum;
926 *(uint32_t *)cap_data = cksum;
927 ret = B_TRUE;
928 break;
929
930 case MAC_CAPAB_LSO: {
931 mac_capab_lso_t *cap_lso = (mac_capab_lso_t *)cap_data;
932 uint32_t page_size;
933 uint32_t lso_max;
934
935 if ((qlge->cfg_flags & CFG_LSO)&&
936 (qlge->cfg_flags & CFG_SUPPORT_SCATTER_GATHER)) {
937 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
938 page_size = ddi_ptob(qlge->dip, (ulong_t)1);
939 lso_max = page_size * (QL_MAX_TX_DMA_HANDLES-1);
940 cap_lso->lso_basic_tcp_ipv4.lso_max =
941 min(lso_max, QL_LSO_MAX);
942 ret = B_TRUE;
943 }
944 break;
945 }
946
947 default:
948 return (B_FALSE);
949 }
950 return (ret);
951 }
952
953 void
ql_gld3_init(qlge_t * qlge,mac_register_t * macp)954 ql_gld3_init(qlge_t *qlge, mac_register_t *macp)
955 {
956 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
957 macp->m_driver = qlge;
958 macp->m_dip = qlge->dip;
959 /* This is the mac address from flash to be used by the port */
960 macp->m_src_addr = qlge->dev_addr.ether_addr_octet;
961 macp->m_min_sdu = 0;
962 macp->m_max_sdu = qlge->mtu;
963 macp->m_margin = VLAN_TAGSZ;
964 macp->m_priv_props = qlge_priv_prop;
965 macp->m_v12n = 0;
966 ql_m_callbacks.mc_unicst = ql_m_unicst;
967 ql_m_callbacks.mc_tx = ql_m_tx;
968 macp->m_callbacks = &ql_m_callbacks;
969 }
970