1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * Nexus driver for AoE initiator and COMSTAR target
18 *
19 * Common AoE interface interacts with MAC, managing AoE ports,
20 * doing MAC address discovery/managment, and AoE frame
21 * encapsulation/decapsulation
22 */
23
24 #include <sys/aoe.h>
25 #include <sys/bootconf.h>
26 #include <sys/conf.h>
27 #include <sys/ddi.h>
28 #include <sys/debug.h>
29 #include <sys/devops.h>
30 #include <sys/dls.h>
31 #include <sys/dls_mgmt.h>
32 #include <sys/errno.h>
33 #include <sys/file.h>
34 #include <sys/kmem.h>
35 #include <sys/kmem.h>
36 #include <sys/ksynch.h>
37 #include <sys/log.h>
38 #include <sys/mac_client.h>
39 #include <sys/modctl.h>
40 #include <sys/modctl.h>
41 #include <sys/param.h>
42 #include <sys/pci.h>
43 #include <sys/stat.h>
44 #include <sys/stream.h>
45 #include <sys/stropts.h>
46 #include <sys/strsubr.h>
47 #include <sys/strsun.h>
48 #include <sys/sunndi.h>
49 #include <sys/sysmacros.h>
50 #include <sys/types.h>
51 #include <sys/ethernet.h>
52
53 /*
54 * There will be only one aoe instance
55 */
56 typedef struct aoe_soft_state {
57 dev_info_t *ss_dip;
58 uint32_t ss_flags;
59 list_t ss_mac_list;
60 list_t ss_port_list;
61 uint32_t ss_ioctl_flags;
62 kmutex_t ss_ioctl_mutex;
63 } aoe_soft_state_t;
64
65 /*
66 * One for each ethernet interface
67 */
68 struct aoe_port;
69 typedef struct aoe_mac
70 {
71 list_node_t am_ss_node;
72 datalink_id_t am_linkid;
73 char am_ifname[MAXNAMELEN];
74
75 struct aoe_port *am_port;
76 aoe_soft_state_t *am_ss;
77
78 mac_handle_t am_handle;
79 mac_client_handle_t am_cli_handle;
80 mac_promisc_handle_t am_promisc_handle;
81 mac_notify_handle_t am_notify_handle;
82 mac_unicast_handle_t am_unicst_handle;
83 ether_addr_t am_primary_addr;
84 ether_addr_t am_current_addr;
85 uint32_t am_running:1,
86 am_force_promisc:1,
87 am_rsvd:22,
88 am_link_state:8;
89 uint32_t am_use_cnt;
90 uint32_t am_frm_cnt;
91 uint32_t am_link_speed;
92 uint32_t am_mtu;
93 uint64_t am_rtt_cnt;
94 uint64_t am_rx_frames;
95 uint64_t am_tx_frames;
96 kcondvar_t am_tx_cv;
97 kmutex_t am_mutex;
98 } aoe_mac_t;
99
100 typedef struct aoe_path
101 {
102 aoe_mac_t *ap_mac;
103 ether_addr_t ap_addr;
104 uint16_t ap_state;
105 uint32_t ap_link_speed; /* in Mbps */
106 uint32_t ap_weight;
107 uint32_t ap_wait_cnt;
108 } aoe_path_t;
109
110 #define WLB_MAX_RETRY_COUNT 100
111 #define WLB_RTT_WEIGHT(x) (x << 1)
112
113 typedef struct aoe_unit
114 {
115 unsigned long au_unit;
116 aoe_path_t au_path[AOE_MAX_MACOBJ];
117 uint32_t au_path_cnt;
118 uint32_t au_rrp_next;
119 } aoe_unit_t;
120
121 typedef struct aoe_port
122 {
123 list_node_t p_ss_node;
124 aoe_eport_t p_eport;
125 aoe_soft_state_t *p_ss;
126 dev_info_t *p_client_dev;
127 aoe_client_t p_client;
128 kmem_cache_t *p_frame_cache;
129 aoe_cli_policy_t p_policy;
130 aoe_cli_type_t p_type;
131 uint32_t p_portid;
132 uint32_t p_rsvd:28,
133 p_state:4;
134 uint32_t p_flags;
135 uint32_t p_mac_cnt;
136 uint32_t p_unit_cnt;
137 aoe_unit_t p_unit[AOE_MAX_UNIT];
138 aoe_mac_t *p_mac[AOE_MAX_MACOBJ];
139 } aoe_port_t;
140
141 #define EPORT2PORT(x_eport) ((aoe_port_t *)(x_eport)->eport_aoe_private)
142 #define FRM2MAC(x_frm) ((aoe_mac_t *)(x_frm)->af_mac)
143
144 #define AOE_PORT_FLAG_BOUND 0x01
145 #define AOE_PORT_FLAG_BUSY 0x02
146
147 #define AOE_STR_LEN 32
148 #define MAX_RESERVE_SIZE (AOE_MAX_MACOBJ * ETHERADDRL)
149
150 /*
151 * Ethernet functions
152 */
153 static int aoe_open_mac(aoe_mac_t *, int);
154 static int aoe_close_mac(aoe_mac_t *);
155 static void aoe_destroy_mac(aoe_mac_t *);
156 static void aoe_destroy_port(aoe_port_t *port);
157 static aoe_mac_t *aoe_lookup_mac_by_id(datalink_id_t);
158 static aoe_port_t *aoe_lookup_port_by_id(uint32_t);
159 static aoe_mac_t *aoe_create_mac_by_id(uint32_t, datalink_id_t, int *);
160 static int aoe_mac_set_address(aoe_mac_t *, uint8_t *, boolean_t);
161 static void aoe_port_notify_link_up(void *);
162 static void aoe_port_notify_link_down(void *);
163 static void aoe_mac_notify(void *, mac_notify_type_t);
164 static mblk_t *aoe_get_mblk(aoe_mac_t *, uint32_t);
165
166 /*
167 * Driver's global variables
168 */
169 static char aoe_ident[] = "Common AOE library and nexus driver";
170 static void *aoe_state = NULL;
171 aoe_soft_state_t *aoe_global_ss = NULL;
172
173 /*
174 * Nexus driver functions
175 */
176 static int aoe_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
177 void *, void *result);
178 static int aoe_initchild(dev_info_t *, dev_info_t *);
179 static int aoe_uninitchild(dev_info_t *, dev_info_t *);
180 static int aoe_attach(dev_info_t *, ddi_attach_cmd_t);
181 static int aoe_detach(dev_info_t *, ddi_detach_cmd_t);
182 static int aoe_open(dev_t *, int, int, cred_t *);
183 static int aoe_close(dev_t, int, int, cred_t *);
184 static int aoe_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
185 static int aoe_copyin_iocdata(intptr_t, int, aoeio_t **, void **, void **,
186 void **);
187 static int aoe_copyout_iocdata(intptr_t, int, aoeio_t *, void *);
188 static int aoe_iocmd(aoe_soft_state_t *, intptr_t, int);
189 static int aoe_create_port(dev_info_t *, aoe_port_t *, aoe_cli_type_t,
190 aoe_cli_policy_t, char *);
191 static int aoe_delete_port(dev_info_t *, aoeio_t *, uint32_t);
192 static int aoe_get_port_list(aoe_port_instance_t *, int);
193 static int aoe_i_port_autoconf(uint32_t);
194 static void aoe_unit_update(aoe_port_t *, aoe_mac_t *, int, int);
195
196 /*
197 * Client functions
198 */
199 static void aoe_deregister_client(aoe_eport_t *);
200 static void aoe_rx(void *, mac_resource_handle_t, mblk_t *, boolean_t);
201 static int aoe_enable_callback(aoe_mac_t *);
202 static int aoe_disable_callback(aoe_mac_t *);
203 static int aoe_ctl(aoe_eport_t *, void *, int, void *);
204 static int aoe_report_unit(aoe_eport_t *, void *, unsigned long, char *);
205 static void aoe_tx_frame(aoe_frame_t *);
206 static void aoe_release_frame(aoe_frame_t *);
207 static void *aoe_alloc_netb(aoe_frame_t *, uint32_t, caddr_t, int);
208 static void aoe_free_netb(void *);
209 static aoe_frame_t *aoe_allocate_frame(aoe_eport_t *, int, void *, int);
210 static uint8_t *aoe_get_mac_addr(void *);
211 static int aoe_get_mac_link_state(void *);
212 static uint32_t aoe_allow_port_detach(aoe_eport_t *);
213
214 /*
215 * Driver identificaton stuff
216 */
217 static struct cb_ops aoe_cb_ops = {
218 aoe_open,
219 aoe_close,
220 nodev,
221 nodev,
222 nodev,
223 nodev,
224 nodev,
225 aoe_ioctl,
226 nodev,
227 nodev,
228 nodev,
229 nochpoll,
230 ddi_prop_op,
231 0,
232 D_MP | D_NEW | D_HOTPLUG,
233 CB_REV,
234 nodev,
235 nodev
236 };
237
238 static struct bus_ops aoe_busops = {
239 BUSO_REV,
240 nullbusmap, /* bus_map */
241 NULL, /* bus_get_intrspec */
242 NULL, /* bus_add_intrspec */
243 NULL, /* bus_remove_intrspec */
244 i_ddi_map_fault, /* bus_map_fault */
245 NULL, /* bus_dma_map (OBSOLETE) */
246 ddi_dma_allochdl, /* bus_dma_allochdl */
247 ddi_dma_freehdl, /* bus_dma_freehdl */
248 ddi_dma_bindhdl, /* bus_dma_bindhdl */
249 ddi_dma_unbindhdl, /* bus_unbindhdl */
250 ddi_dma_flush, /* bus_dma_flush */
251 ddi_dma_win, /* bus_dma_win */
252 ddi_dma_mctl, /* bus_dma_ctl */
253 aoe_bus_ctl, /* bus_ctl */
254 ddi_bus_prop_op, /* bus_prop_op */
255 NULL, /* bus_get_eventcookie */
256 NULL, /* bus_add_eventcall */
257 NULL, /* bus_remove_event */
258 NULL, /* bus_post_event */
259 NULL, /* bus_intr_ctl */
260 NULL, /* bus_config */
261 NULL, /* bus_unconfig */
262 NULL, /* bus_fm_init */
263 NULL, /* bus_fm_fini */
264 NULL, /* bus_fm_access_enter */
265 NULL, /* bus_fm_access_exit */
266 NULL, /* bus_power */
267 NULL
268 };
269
270 static struct dev_ops aoe_dev_ops = {
271 DEVO_REV,
272 0,
273 ddi_no_info,
274 nulldev, /* identify */
275 nulldev, /* probe */
276 aoe_attach, /* attach */
277 aoe_detach, /* detach */
278 nodev, /* reset */
279 &aoe_cb_ops, /* cb_ops */
280 &aoe_busops, /* bus_ops */
281 NULL, /* power */
282 ddi_quiesce_not_supported /* quiesce */
283 };
284
285 extern char *aoepath_prop;
286
287 /* Standard Module linkage initialization for a Streams driver */
288 extern struct mod_ops mod_driverops;
289
290 static struct modldrv modldrv = {
291 &mod_driverops, /* Type of module. This one is a driver */
292 aoe_ident, /* short description */
293 &aoe_dev_ops /* driver specific ops */
294 };
295
296 static struct modlinkage modlinkage = {
297 MODREV_1,
298 {
299 (void *)&modldrv,
300 NULL,
301 },
302 };
303
304 /*
305 * Bus control operations for nexus drivers.
306 */
307 static int
308 aoe_bus_ctl(dev_info_t *aoe_dip, dev_info_t *rip,
309 ddi_ctl_enum_t op, void *clientarg, void *result)
310 {
311 int ret;
312 switch (op) {
313 case DDI_CTLOPS_REPORTDEV:
314 case DDI_CTLOPS_IOMIN:
315 ret = DDI_SUCCESS;
316 break;
317
318 case DDI_CTLOPS_INITCHILD:
319 ret = aoe_initchild(aoe_dip, (dev_info_t *)clientarg);
320 break;
321
322 case DDI_CTLOPS_UNINITCHILD:
323 ret = aoe_uninitchild(aoe_dip, (dev_info_t *)clientarg);
324 break;
325
326 default:
327 ret = ddi_ctlops(aoe_dip, rip, op, clientarg, result);
328 break;
329 }
330
331 return (ret);
332 }
333
334 /*
335 * We need specify the dev address for client driver's instance, or we
336 * can't online client driver's instance.
337 */
338 /* ARGSUSED */
339 static int
340 aoe_initchild(dev_info_t *aoe_dip, dev_info_t *client_dip)
341 {
342 char client_addr[AOE_STR_LEN];
343 int rval;
344
345 rval = ddi_prop_get_int(DDI_DEV_T_ANY, client_dip,
346 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "port_id", -1);
347 if (rval == -1) {
348 dev_err(aoe_dip, CE_WARN, "no port_id property: %p",
349 (void *)client_dip);
350 return (DDI_FAILURE);
351 }
352
353 bzero(client_addr, AOE_STR_LEN);
354 (void) sprintf((char *)client_addr, "%x,0", rval);
355 ddi_set_name_addr(client_dip, client_addr);
356 return (DDI_SUCCESS);
357 }
358
359 /* ARGSUSED */
360 static int
361 aoe_uninitchild(dev_info_t *aoe_dip, dev_info_t *client_dip)
362 {
363 ddi_set_name_addr(client_dip, NULL);
364 return (DDI_SUCCESS);
365 }
366
367 static int
368 aoe_open_mac(aoe_mac_t *mac, int force_promisc)
369 {
370 int ret;
371 char cli_name[MAXNAMELEN];
372 mac_diag_t diag;
373 uint16_t am_open_flag = 0;
374
375 /*
376 * Open MAC interface
377 */
378 ret = mac_open_by_linkid(mac->am_linkid, &mac->am_handle);
379 if (ret != 0) {
380 if (mac->am_ifname)
381 ret = mac_open(mac->am_ifname, &mac->am_handle);
382 if (ret != 0) {
383 cmn_err(CE_WARN, "mac_open %d failed %x",
384 mac->am_linkid, ret);
385 return (DDI_FAILURE);
386 }
387 }
388
389 (void) sprintf(cli_name, "%s-%d", "aoe", mac->am_linkid);
390
391 ret = mac_client_open(mac->am_handle,
392 &mac->am_cli_handle, cli_name, am_open_flag);
393 if (ret != 0) {
394 (void) aoe_close_mac(mac);
395 return (DDI_FAILURE);
396 }
397
398 /*
399 * Cache the pointer of the immutable MAC inforamtion and
400 * the current and primary MAC address
401 */
402 mac_unicast_primary_get(mac->am_handle, mac->am_primary_addr);
403 ether_copy((void *)mac->am_primary_addr, (void *)mac->am_current_addr);
404
405 ret = mac_unicast_add(mac->am_cli_handle, NULL, MAC_UNICAST_PRIMARY,
406 &mac->am_unicst_handle, 0, &diag);
407 if (ret != 0) {
408 cmn_err(CE_WARN, "mac_unicast_add failed. ret=%d", ret);
409 (void) aoe_close_mac(mac);
410 return (DDI_FAILURE);
411 }
412
413 if (force_promisc) {
414 mac->am_force_promisc = B_TRUE;
415 }
416
417 /* Get mtu */
418 mac_sdu_get(mac->am_handle, NULL, &mac->am_mtu);
419
420 /* Get link speed */
421 mac->am_link_speed =
422 mac_client_stat_get(mac->am_cli_handle, MAC_STAT_IFSPEED);
423
424 cv_init(&mac->am_tx_cv, NULL, CV_DRIVER, NULL);
425 mutex_init(&mac->am_mutex, NULL, MUTEX_DRIVER, NULL);
426 mac->am_running = B_TRUE;
427
428 return (DDI_SUCCESS);
429 }
430
431 static int
432 aoe_close_mac(aoe_mac_t *mac)
433 {
434 int ret;
435
436 if (mac->am_handle == NULL) {
437 return (DDI_SUCCESS);
438 }
439
440 if (mac->am_running) {
441 cv_destroy(&mac->am_tx_cv);
442 mutex_destroy(&mac->am_mutex);
443 mac->am_running = B_FALSE;
444 }
445
446 if (mac->am_promisc_handle != NULL) {
447 mac_promisc_remove(mac->am_promisc_handle);
448 mac->am_promisc_handle = NULL;
449 } else {
450 mac_rx_clear(mac->am_cli_handle);
451 }
452
453 if (mac->am_notify_handle != NULL) {
454 ret = mac_notify_remove(mac->am_notify_handle, B_TRUE);
455 ASSERT(ret == 0);
456 mac->am_notify_handle = NULL;
457 }
458
459 if (mac->am_unicst_handle != NULL) {
460 (void) mac_unicast_remove(mac->am_cli_handle,
461 mac->am_unicst_handle);
462 mac->am_unicst_handle = NULL;
463 }
464
465 mac_client_close(mac->am_cli_handle, 0);
466 mac->am_cli_handle = NULL;
467
468 (void) mac_close(mac->am_handle);
469 mac->am_handle = NULL;
470 return (DDI_SUCCESS);
471 }
472
473 /*
474 * Return mac instance if it exist, or else return NULL.
475 */
476 static aoe_mac_t *
477 aoe_lookup_mac_by_id(datalink_id_t linkid)
478 {
479 aoe_mac_t *mac = NULL;
480
481 ASSERT(MUTEX_HELD(&aoe_global_ss->ss_ioctl_mutex));
482 for (mac = list_head(&aoe_global_ss->ss_mac_list); mac;
483 mac = list_next(&aoe_global_ss->ss_mac_list, mac)) {
484 if (linkid == mac->am_linkid)
485 return (mac);
486 }
487 return (NULL);
488 }
489
490 /*
491 * Return port instance if it exist, or else return NULL.
492 */
493 static aoe_port_t *
494 aoe_lookup_port_by_id(uint32_t portid)
495 {
496 aoe_port_t *port = NULL;
497
498 ASSERT(MUTEX_HELD(&aoe_global_ss->ss_ioctl_mutex));
499 for (port = list_head(&aoe_global_ss->ss_port_list); port;
500 port = list_next(&aoe_global_ss->ss_port_list, port)) {
501 if (portid == port->p_portid)
502 return (port);
503 }
504 return (NULL);
505 }
506
507 /*
508 * Return aoe_mac if it exists, otherwise create a new one
509 */
510 static aoe_mac_t *
511 aoe_create_mac_by_id(uint32_t portid, datalink_id_t linkid,
512 int *is_port_created)
513 {
514 aoe_port_t *port;
515 aoe_mac_t *mac;
516 int port_created = 0;
517 ASSERT(MUTEX_HELD(&aoe_global_ss->ss_ioctl_mutex));
518
519 *is_port_created = 0;
520 port = aoe_lookup_port_by_id(portid);
521 if (port == NULL) {
522 port = kmem_zalloc(sizeof (aoe_port_t), KM_SLEEP);
523 if (!port)
524 return (NULL);
525 port->p_portid = portid;
526 port->p_ss = aoe_global_ss;
527 port->p_mac_cnt = 0;
528
529 list_insert_tail(&port->p_ss->ss_port_list, port);
530 port_created = 1;
531 }
532
533 mac = aoe_lookup_mac_by_id(linkid);
534 if (mac != NULL) {
535 if (port_created)
536 aoe_destroy_port(port);
537 return (NULL);
538 }
539
540 mac = kmem_zalloc(sizeof (aoe_mac_t), KM_SLEEP);
541 if (!mac) {
542 if (port_created)
543 aoe_destroy_port(port);
544 return (NULL);
545 }
546 mac->am_linkid = linkid;
547 mac->am_ss = aoe_global_ss;
548 mac->am_port = port;
549 port->p_mac[port->p_mac_cnt++] = mac;
550
551 list_insert_tail(&mac->am_ss->ss_mac_list, mac);
552 *is_port_created = port_created;
553 return (mac);
554 }
555
556 static void
557 aoe_destroy_port(aoe_port_t *port)
558 {
559 ASSERT(port != NULL);
560 ASSERT(port->p_mac_cnt == 0);
561 list_remove(&port->p_ss->ss_port_list, port);
562 kmem_free(port, sizeof (aoe_port_t));
563 }
564
565 static void
566 aoe_destroy_mac(aoe_mac_t *mac)
567 {
568 aoe_port_t *port;
569 ASSERT(mac != NULL);
570
571 port = mac->am_port;
572 list_remove(&mac->am_ss->ss_mac_list, mac);
573 kmem_free(mac, sizeof (aoe_mac_t));
574
575 port->p_mac_cnt--;
576 }
577
578
579 /*
580 * The following routines will be called through vectors in aoe_eport_t
581 */
582
583 /*
584 * Deregister aoet/aoei modules, client should make sure the port is in
585 * offline status already
586 */
587 static void
588 aoe_deregister_client(aoe_eport_t *eport)
589 {
590 aoe_port_t *port = EPORT2PORT(eport);
591 int i, found = 0;
592
593 /*
594 * Wait for all the related frame to be freed, this should be fast
595 * because before deregister aoei/aoet will make sure its port
596 * is already in offline status so no frame will be received or sent
597 * any more
598 */
599 for (i = 0; i < port->p_mac_cnt; i++) {
600 if (port->p_mac[i]->am_frm_cnt > 0) {
601 found = 1;
602 break;
603 }
604 }
605 if (found)
606 delay(100);
607
608 kmem_cache_destroy(port->p_frame_cache);
609
610 atomic_and_32(&port->p_flags, ~AOE_PORT_FLAG_BOUND);
611 }
612
613 /* ARGSUSED */
614 static void
615 aoe_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp, boolean_t loopback)
616 {
617 aoe_mac_t *mac = (aoe_mac_t *)arg;
618 mblk_t *next;
619 aoe_frame_t *frm;
620 uint16_t frm_type;
621 aoe_port_t *port;
622
623 port = mac->am_port;
624
625 while (mp != NULL) {
626 next = mp->b_next;
627 mp->b_next = NULL;
628 frm_type = ntohs(*(uint16_t *)((uintptr_t)mp->b_rptr + 12));
629
630 if (frm_type != ETHERTYPE_AOE ||
631 !(port->p_flags & AOE_PORT_FLAG_BOUND)) {
632 /*
633 * This mp is not allocated in AoE, we must free it...
634 *
635 * We are using freemsg because we haven't done the
636 * b_cont check yet. Most of the time it WILL be a
637 * single mblk, but freemsg is more conservative here.
638 */
639 freemsg(mp);
640 mp = next;
641 continue;
642 }
643
644 if (mp->b_cont != NULL) {
645 mblk_t *nmp = msgpullup(mp, -1);
646 if (nmp == NULL) {
647 freemsg(mp);
648 mp = next;
649 continue;
650 }
651 /* Reset it to new collapsed mp */
652 freemsg(mp);
653 mp = nmp;
654 }
655
656 frm = aoe_allocate_frame(&port->p_eport, -1, mac, KM_NOSLEEP);
657 if (frm != NULL) {
658 aoe_hdr_t *h = (aoe_hdr_t *)mp->b_rptr;
659
660 ether_copy((void *)h->aoeh_src, (void *)frm->af_addr);
661 frm->af_netb = mp;
662 frm->af_data = (uint8_t *)mp->b_rptr;
663 port->p_client.ect_rx_frame(frm);
664 mac->am_rx_frames++;
665 } else
666 /* Using freeb because we know it is a single mblk */
667 freeb(mp);
668
669 mp = next;
670 }
671 }
672
673 static int
674 aoe_enable_callback(aoe_mac_t *mac)
675 {
676 int ret;
677
678 /*
679 * Set message callback
680 */
681 if (mac->am_force_promisc) {
682 ret = mac_promisc_add(mac->am_cli_handle,
683 MAC_CLIENT_PROMISC_FILTERED, aoe_rx, mac,
684 &mac->am_promisc_handle,
685 MAC_PROMISC_FLAGS_NO_TX_LOOP);
686 if (ret != 0) {
687 dev_err(mac->am_port->p_client_dev, CE_WARN,
688 "mac_promisc_add on %d failed (%x)",
689 mac->am_linkid, ret);
690 return (DDI_FAILURE);
691 }
692 } else {
693 mac_rx_set(mac->am_cli_handle, aoe_rx, mac);
694 }
695
696 /* Get the link state, if it's up, we will need to notify client */
697 mac->am_link_state =
698 mac_stat_get(mac->am_handle, MAC_STAT_LINK_UP)?
699 AOE_MAC_LINK_STATE_UP:AOE_MAC_LINK_STATE_DOWN;
700
701 /*
702 * Add a notify function so that we get updates from MAC
703 */
704 mac->am_notify_handle = mac_notify_add(mac->am_handle,
705 aoe_mac_notify, (void *)mac);
706 return (DDI_SUCCESS);
707 }
708
709 static int
710 aoe_disable_callback(aoe_mac_t *mac)
711 {
712 int ret;
713
714 if (mac->am_promisc_handle) {
715 mac_promisc_remove(mac->am_promisc_handle);
716 mac->am_promisc_handle = NULL;
717 } else {
718 mac_rx_clear(mac->am_cli_handle);
719 }
720
721 if (mac->am_notify_handle) {
722 ret = mac_notify_remove(mac->am_notify_handle, B_TRUE);
723 ASSERT(ret == 0);
724 mac->am_notify_handle = NULL;
725 }
726
727 ret = aoe_mac_set_address(mac, mac->am_primary_addr, B_FALSE);
728
729 return (ret);
730 }
731
732 static void
733 aoe_update_path_info(aoe_unit_t *u, aoe_path_t *p)
734 {
735 aoe_path_t *xp;
736 unsigned int i;
737 uint32_t max_speed;
738
739 p->ap_link_speed = p->ap_mac->am_link_speed / 1000000;
740
741 /* find the maximum speed */
742 max_speed = 0;
743 for (i = 0; i < u->au_path_cnt; i++) {
744 xp = &u->au_path[i];
745 if (xp->ap_link_speed > max_speed)
746 max_speed = xp->ap_link_speed;
747 }
748
749 /* update per-path weight */
750 for (i = 0; i < u->au_path_cnt; i++) {
751 xp = &u->au_path[i];
752 if (xp->ap_link_speed)
753 xp->ap_weight = max_speed / xp->ap_link_speed;
754 else
755 xp->ap_weight = 100; /* an arbitrary number */
756 }
757
758 /* update per-path wait count */
759 for (i = 0; i < u->au_path_cnt; i++) {
760 xp = &u->au_path[i];
761 xp->ap_wait_cnt = xp->ap_weight;
762 }
763 }
764
765 static int
766 aoe_report_unit(aoe_eport_t *eport, void *mac, unsigned long unit,
767 char *dst_addr)
768 {
769 int i, j;
770 aoe_unit_t *u = NULL;
771 aoe_path_t *p = NULL;
772 aoe_port_t *port = EPORT2PORT(eport);
773
774 for (i = 0; i < port->p_unit_cnt; i++) {
775 if (port->p_unit[i].au_unit == unit) {
776 u = &port->p_unit[i];
777 break;
778 }
779 }
780
781 if (u == NULL) {
782 /*
783 * Record new unit
784 */
785 u = &port->p_unit[i];
786 u->au_unit = unit;
787 p = &u->au_path[u->au_path_cnt++];
788 p->ap_mac = mac;
789 p->ap_state = AOE_CMD_PORT_UNIT_ONLINE;
790 if (port->p_policy == AOE_POLICY_LOADBALANCE)
791 aoe_update_path_info(u, p);
792 ether_copy((void *)dst_addr, (void *)p->ap_addr);
793 port->p_unit_cnt++;
794 return (i);
795 }
796
797 /*
798 * See if it is a new path... and log new path if so
799 */
800 for (j = 0; j < u->au_path_cnt; j++) {
801 if (u->au_path[j].ap_mac == mac) {
802 p = &u->au_path[j];
803 break;
804 }
805 }
806
807 if (p == NULL) {
808 p = &u->au_path[u->au_path_cnt++];
809 p->ap_mac = mac;
810 p->ap_state = AOE_CMD_PORT_UNIT_ONLINE;
811 if (port->p_policy == AOE_POLICY_LOADBALANCE)
812 aoe_update_path_info(u, p);
813 }
814 ether_copy((void *)dst_addr, (void *)p->ap_addr);
815
816 return (i);
817 }
818
819 static void
820 aoe_unit_update(aoe_port_t *port, aoe_mac_t *mac, int cmd, int unit_id)
821 {
822 aoe_unit_t *u;
823 aoe_path_t *p = NULL;
824 int j;
825
826 /*
827 * Must report unit first
828 */
829 ASSERT(unit_id <= port->p_unit_cnt);
830
831 u = &port->p_unit[unit_id];
832
833 /*
834 * Log state to the matching path
835 */
836 for (j = 0; j < u->au_path_cnt; j++) {
837 if (u->au_path[j].ap_mac == mac) {
838 p = &u->au_path[j];
839 break;
840 }
841 }
842
843 if (p) {
844 if (cmd == AOE_CMD_PORT_UNIT_RETRANSMIT)
845 p->ap_mac->am_rtt_cnt++;
846 else
847 p->ap_state = (uint16_t)cmd;
848 }
849 }
850
851 /* ARGSUSED */
852 static int
853 aoe_ctl(aoe_eport_t *eport, void *mac, int cmd, void *arg)
854 {
855 aoe_port_t *port = EPORT2PORT(eport);
856 int i;
857
858 switch (cmd) {
859 case AOE_CMD_PORT_ONLINE:
860 for (i = 0; i < port->p_mac_cnt; i++) {
861 if (aoe_enable_callback(port->p_mac[i])
862 == DDI_FAILURE) {
863 int j;
864 for (j = i - 1; j >= 0; j--)
865 (void) aoe_disable_callback(
866 port->p_mac[j]);
867 return (DDI_FAILURE);
868 }
869 }
870 port->p_state = AOE_PORT_STATE_ONLINE;
871 break;
872 case AOE_CMD_PORT_OFFLINE:
873 for (i = 0; i < port->p_mac_cnt; i++) {
874 if (aoe_disable_callback(port->p_mac[i])
875 == DDI_FAILURE) {
876 int j;
877 for (j = i - 1; j >= 0; j--)
878 (void) aoe_enable_callback(
879 port->p_mac[j]);
880 return (DDI_FAILURE);
881 }
882 }
883 port->p_state = AOE_PORT_STATE_OFFLINE;
884
885 /*
886 * in case there are threads waiting
887 */
888 for (i = 0; i < port->p_mac_cnt; i++) {
889 mutex_enter(&port->p_mac[i]->am_mutex);
890 cv_broadcast(&port->p_mac[i]->am_tx_cv);
891 mutex_exit(&port->p_mac[i]->am_mutex);
892 }
893 break;
894 case AOE_CMD_PORT_UNIT_ONLINE:
895 aoe_unit_update(port, mac, cmd, (unsigned long)arg);
896 break;
897 case AOE_CMD_PORT_UNIT_OFFLINE:
898 aoe_unit_update(port, mac, cmd, (unsigned long)arg);
899 break;
900 case AOE_CMD_PORT_UNIT_RETRANSMIT:
901 aoe_unit_update(port, mac, cmd, (unsigned long)arg);
902 break;
903 default:
904 dev_err(port->p_client_dev, CE_WARN,
905 "aoe_ctl, unsupported cmd %x", cmd);
906 break;
907 }
908
909 return (DDI_SUCCESS);
910 }
911
912 /*
913 * Transmit the specified frame to the link
914 */
915 static void
916 aoe_tx_frame(aoe_frame_t *af)
917 {
918 mblk_t *ret_mblk = NULL;
919 aoe_mac_t *mac = FRM2MAC(af);
920 mac_tx_cookie_t ret_cookie;
921
922 tx_frame:
923 ret_cookie = mac_tx(mac->am_cli_handle, af->af_netb, 0,
924 MAC_TX_NO_ENQUEUE, &ret_mblk);
925 if (ret_cookie != NULL) {
926 mutex_enter(&mac->am_mutex);
927 (void) cv_reltimedwait(&mac->am_tx_cv, &mac->am_mutex,
928 drv_usectohz(100000), TR_CLOCK_TICK);
929 mutex_exit(&mac->am_mutex);
930
931 if (mac->am_port->p_state == AOE_PORT_STATE_OFFLINE) {
932 /*
933 * we are doing offline, so just tell the upper that
934 * this is finished, the cmd will be aborted soon.
935 */
936 aoe_free_netb(ret_mblk);
937 } else {
938 goto tx_frame;
939 }
940 }
941
942 /*
943 * MAC driver will release the mblk of the frame
944 */
945
946 mac->am_tx_frames++;
947 }
948
949 /*
950 * raw frame layout:
951 * AoE header + AoE command + AoE payload
952 */
953 /* ARGSUSED */
954 static mblk_t *
955 aoe_get_mblk(aoe_mac_t *mac, uint32_t raw_frame_size)
956 {
957 mblk_t *mp;
958 int err;
959
960 while ((mp = allocb((size_t)raw_frame_size, 0)) == NULL) {
961 if ((err = strwaitbuf((size_t)raw_frame_size, BPRI_LO)) != 0) {
962 dev_err(mac->am_port->p_client_dev, CE_WARN,
963 "strwaitbuf return %d", err);
964 return (NULL);
965 }
966 }
967 mp->b_wptr = mp->b_rptr + raw_frame_size;
968
969 return (mp);
970 }
971
972 static void *
973 aoe_alloc_netb(aoe_frame_t *af, uint32_t buf_size, caddr_t buf, int kmflag)
974 {
975 mblk_t *mp;
976 aoe_mac_t *mac = FRM2MAC(af);
977
978 if (buf)
979 mp = kmflag == KM_NOSLEEP ?
980 esballoc((unsigned char *)buf, buf_size, 0, &frnop) :
981 esballoc_wait((unsigned char *)buf, buf_size, 0, &frnop);
982 else
983 mp = aoe_get_mblk(mac, buf_size);
984
985 if (mp) {
986 if (af->af_netb == NULL) {
987 aoe_hdr_t *h = (aoe_hdr_t *)mp->b_rptr;
988
989 af->af_netb = mp;
990 af->af_data = (uint8_t *)mp->b_rptr;
991 ether_copy((void *)mac->am_current_addr,
992 (void *)h->aoeh_src);
993 ether_copy((void *)af->af_addr,
994 (void *)h->aoeh_dst);
995 } else
996 ((mblk_t *)af->af_netb)->b_cont = mp;
997 mp->b_wptr = mp->b_rptr + buf_size;
998 }
999
1000 return (mp);
1001 }
1002
1003 static void
1004 aoe_free_netb(void *netb)
1005 {
1006 freeb((mblk_t *)netb);
1007 }
1008
1009 static void
1010 aoe_release_frame(aoe_frame_t *af)
1011 {
1012 aoe_port_t *port = EPORT2PORT(af->af_eport);
1013 aoe_mac_t *mac = FRM2MAC(af);
1014 aoe_hdr_t *h = (aoe_hdr_t *)af->af_data;
1015
1016 if (h->aoeh_cmd == AOECMD_ATA && mac->am_rtt_cnt)
1017 mac->am_rtt_cnt--;
1018 kmem_cache_free(port->p_frame_cache, af);
1019 mac->am_frm_cnt--;
1020 }
1021
1022 static aoe_path_t *
1023 load_balancing(aoe_unit_t *u)
1024 {
1025 aoe_mac_t *mac;
1026 aoe_path_t *p = NULL;
1027 aoe_path_t *xp = NULL;
1028 int i;
1029 int j = 0;
1030 int mst;
1031 int pst;
1032 int retry = 0;
1033
1034 for (;;) {
1035 if (u->au_rrp_next >= u->au_path_cnt)
1036 i = u->au_rrp_next = 0;
1037 else
1038 i = u->au_rrp_next++;
1039 if (j > u->au_path_cnt) {
1040 /*
1041 * We have already scanned all the paths,
1042 * if there is one online, use it!
1043 */
1044 if (xp) {
1045 p = xp;
1046 break;
1047 } else {
1048 retry++;
1049 if (retry > WLB_MAX_RETRY_COUNT) {
1050 p = NULL;
1051 break;
1052 }
1053 j = 0;
1054 delay(30);
1055 continue;
1056 }
1057 }
1058 j++; /* number of paths scanned so far */
1059 p = &u->au_path[i];
1060 mac = p->ap_mac;
1061 if (mac == NULL)
1062 continue;
1063 mst = mac->am_link_state;
1064 pst = p->ap_state;
1065 if (mst == AOE_MAC_LINK_STATE_UP &&
1066 pst == AOE_CMD_PORT_UNIT_ONLINE) {
1067 /* found an online path */
1068 if (--p->ap_wait_cnt) {
1069 /* weight has not fully dropped yet */
1070 xp = p;
1071 continue;
1072 } else {
1073 /* reset weight & return the path */
1074 p->ap_wait_cnt = p->ap_weight +
1075 WLB_RTT_WEIGHT(mac->am_rtt_cnt);
1076 break;
1077 }
1078 }
1079 }
1080 return (p);
1081 }
1082
1083 static aoe_frame_t *
1084 aoe_allocate_frame(aoe_eport_t *eport, int unit_id, void *xmac, int kmflag)
1085 {
1086 aoe_port_t *port = EPORT2PORT(eport);
1087 aoe_frame_t *af;
1088 aoe_mac_t *mac = xmac;
1089 int i;
1090
1091 /*
1092 * aoe_frame_t initialization
1093 */
1094 af = (aoe_frame_t *)kmem_cache_alloc(port->p_frame_cache, kmflag);
1095 if (af == NULL)
1096 return (NULL);
1097 bzero(af, sizeof (*af) + port->p_client.ect_private_frame_struct_size);
1098
1099 if (mac == NULL) {
1100 aoe_path_t *p = NULL;
1101
1102 ASSERT(unit_id <= port->p_unit_cnt);
1103 ASSERT(port->p_unit_cnt);
1104
1105 /*
1106 * Apply selected port policy
1107 */
1108 if (port->p_policy == AOE_POLICY_NONE) {
1109 p = &port->p_unit[unit_id].au_path[0];
1110 } else if (port->p_policy == AOE_POLICY_FAILOVER) {
1111 aoe_unit_t *u = &port->p_unit[unit_id];
1112
1113 /*
1114 * Select first ONLINE path
1115 */
1116 for (i = 0; i < u->au_path_cnt; i++) {
1117 int mst = u->au_path[i].ap_mac->am_link_state;
1118 int pst = u->au_path[i].ap_state;
1119
1120 if (mst == AOE_MAC_LINK_STATE_UP &&
1121 pst == AOE_CMD_PORT_UNIT_ONLINE) {
1122 p = &u->au_path[i];
1123 break;
1124 }
1125 }
1126 } else if (port->p_policy == AOE_POLICY_ROUNDROBIN) {
1127 aoe_unit_t *u = &port->p_unit[unit_id];
1128 int j = 0;
1129
1130 /*
1131 * Just round-robin through ONLINE paths
1132 */
1133 round2:
1134 for (i = u->au_rrp_next++; i < u->au_path_cnt; i++) {
1135 int mst = u->au_path[i].ap_mac->am_link_state;
1136 int pst = u->au_path[i].ap_state;
1137
1138 if (mst == AOE_MAC_LINK_STATE_UP &&
1139 pst == AOE_CMD_PORT_UNIT_ONLINE) {
1140 p = &u->au_path[i];
1141 break;
1142 }
1143 j++;
1144 }
1145 if (p == NULL && j < u->au_path_cnt) {
1146 u->au_rrp_next = 0;
1147 goto round2;
1148 }
1149 if (p == NULL || u->au_rrp_next == u->au_path_cnt)
1150 u->au_rrp_next = 0;
1151 } else if (port->p_policy == AOE_POLICY_LOADBALANCE) {
1152 /*
1153 * Weighted balancing
1154 */
1155 p = load_balancing(&port->p_unit[unit_id]);
1156 } else {
1157 ASSERT(0);
1158 }
1159
1160 if (p == NULL) {
1161 kmem_cache_free(port->p_frame_cache, af);
1162 return (NULL);
1163 }
1164
1165 mac = p->ap_mac;
1166 ether_copy((void *)p->ap_addr, (void *)af->af_addr);
1167 } else if (unit_id >= 0) {
1168 aoe_unit_t *u = &port->p_unit[unit_id];
1169
1170 /*
1171 * If unit_id and xmac specified, we should select the right
1172 * target address
1173 */
1174 for (i = 0; i < u->au_path_cnt; i++) {
1175 if (u->au_path[i].ap_mac == mac) {
1176 aoe_path_t *p = &u->au_path[i];
1177 ether_copy((void *)p->ap_addr,
1178 (void *)af->af_addr);
1179 break;
1180 }
1181 }
1182 }
1183
1184 af->af_eport = eport;
1185 af->af_mac = mac;
1186
1187 mac->am_frm_cnt++;
1188
1189 return (af);
1190 }
1191
1192 static int
1193 aoe_get_mac_link_state(void *xmac)
1194 {
1195 aoe_mac_t *mac = xmac;
1196
1197 return (mac->am_link_state);
1198 }
1199
1200 static uint8_t *
1201 aoe_get_mac_addr(void *xmac)
1202 {
1203 aoe_mac_t *mac = xmac;
1204
1205 return (mac->am_current_addr);
1206 }
1207
1208 /*
1209 * Only this function will be called explicitly by clients
1210 * Register the specified client port (initiator/target)
1211 */
1212 aoe_eport_t *
1213 aoe_register_client(aoe_client_t *client)
1214 {
1215 aoe_eport_t *eport;
1216 char cache_string[32];
1217 aoe_port_t *port;
1218 uint32_t alloc_size;
1219 uint32_t i;
1220 uint32_t min_mtu = 0;
1221
1222 /*
1223 * We will not come here, when someone is changing ss_port_list,
1224 * so it's safe to go through ss_port_list.
1225 */
1226 for (port = list_head(&aoe_global_ss->ss_port_list); port;
1227 port = list_next(&aoe_global_ss->ss_port_list, port)) {
1228 if (client->ect_channelid == port->p_portid)
1229 break;
1230 }
1231
1232 if (port == NULL) {
1233 cmn_err(CE_WARN, "can't find the port to bind");
1234 return (NULL);
1235 }
1236
1237 if (port->p_flags & AOE_PORT_FLAG_BOUND) {
1238 dev_err(port->p_client_dev, CE_WARN,
1239 "the port you want to bind is bound already");
1240 return (NULL);
1241 }
1242
1243 atomic_or_32(&port->p_flags, AOE_PORT_FLAG_BOUND);
1244 bcopy(client, &port->p_client, sizeof (aoe_client_t));
1245
1246 alloc_size = sizeof (aoe_frame_t) +
1247 port->p_client.ect_private_frame_struct_size + MAX_RESERVE_SIZE;
1248
1249 (void) sprintf(cache_string, "port_frame_cache_%d", port->p_portid);
1250 port->p_frame_cache = kmem_cache_create(cache_string,
1251 alloc_size, 0, NULL, NULL, NULL, port, NULL, KM_SLEEP);
1252 if (!port->p_frame_cache) {
1253 return (NULL);
1254 }
1255 atomic_or_32(&port->p_flags, AOE_PORT_FLAG_BUSY);
1256
1257 /*
1258 * aoe_eport_t initialization
1259 */
1260 eport = &port->p_eport;
1261 eport->eport_aoe_private = port;
1262 eport->eport_client_private = client->ect_client_port_struct;
1263 eport->eport_mac = (void **)port->p_mac;
1264 eport->eport_mac_cnt = port->p_mac_cnt;
1265
1266 for (i = 0; i < port->p_mac_cnt; i++) {
1267 aoe_mac_t *mac = port->p_mac[i];
1268
1269 if (min_mtu == 0 || mac->am_mtu < min_mtu)
1270 min_mtu = mac->am_mtu;
1271 }
1272
1273 eport->cache_unit_size = alloc_size;
1274 eport->eport_maxxfer = (min_mtu - AOEHDRSZ) & ~(DEV_BSIZE - 1);
1275 eport->eport_tx_frame = aoe_tx_frame;
1276 eport->eport_alloc_frame = aoe_allocate_frame;
1277 eport->eport_release_frame = aoe_release_frame;
1278 eport->eport_alloc_netb = aoe_alloc_netb;
1279 eport->eport_free_netb = aoe_free_netb;
1280 eport->eport_deregister_client = aoe_deregister_client;
1281 eport->eport_get_mac_addr = aoe_get_mac_addr;
1282 eport->eport_get_mac_link_state = aoe_get_mac_link_state;
1283 eport->eport_ctl = aoe_ctl;
1284 eport->eport_report_unit = aoe_report_unit;
1285 eport->eport_allow_port_detach = aoe_allow_port_detach;
1286
1287 return (eport);
1288 }
1289
1290 static int
1291 aoe_mac_set_address(aoe_mac_t *mac, uint8_t *addr, boolean_t assigned)
1292 {
1293 int ret;
1294
1295 if (ether_cmp((void *)addr, (void *)mac->am_current_addr) == 0) {
1296 return (DDI_SUCCESS);
1297 }
1298
1299 mutex_enter(&mac->am_mutex);
1300 if (mac->am_promisc_handle == NULL) {
1301 ret = mac_unicast_primary_set(mac->am_handle, addr);
1302 if (ret != 0) {
1303 mutex_exit(&mac->am_mutex);
1304 dev_err(mac->am_port->p_client_dev, CE_WARN,
1305 "mac_unicast_primary_set on %d "
1306 "failed %x", mac->am_linkid, ret);
1307 return (DDI_FAILURE);
1308 }
1309 }
1310 if (assigned) {
1311 ether_copy((void *)addr,
1312 (void *)mac->am_current_addr);
1313 } else {
1314 ether_copy((void *)mac->am_primary_addr,
1315 (void *)mac->am_current_addr);
1316 }
1317 mutex_exit(&mac->am_mutex);
1318 return (DDI_SUCCESS);
1319 }
1320
1321 static void
1322 aoe_port_notify_link_up(void *arg)
1323 {
1324 aoe_port_t *port = (aoe_port_t *)arg;
1325
1326 ASSERT(port->p_flags & AOE_PORT_FLAG_BOUND);
1327
1328 port->p_client.ect_port_event(&port->p_eport,
1329 AOE_NOTIFY_EPORT_LINK_UP);
1330 }
1331
1332 static void
1333 aoe_port_notify_link_down(void *arg)
1334 {
1335 aoe_port_t *port = (aoe_port_t *)arg;
1336
1337 if (port->p_flags & AOE_PORT_FLAG_BOUND) {
1338 port->p_client.ect_port_event(&port->p_eport,
1339 AOE_NOTIFY_EPORT_LINK_DOWN);
1340 }
1341 }
1342
1343 static void
1344 aoe_mac_notify(void *arg, mac_notify_type_t type)
1345 {
1346 aoe_mac_t *mac = (aoe_mac_t *)arg;
1347 int link_cnt = 0, i;
1348 aoe_port_t *port;
1349
1350 port = mac->am_port;
1351
1352 /*
1353 * We assume that the calls to this notification callback are serialized
1354 * by MAC layer.
1355 *
1356 * Notes for GLDv3: There is one notification thread per mac_handle_t
1357 * (mac_impl_t), so if a given callback was only added once on a single
1358 * mac_handle_t, then it will not be called concurrently.
1359 *
1360 * This is based on the current implementation of mac_handle_t. If that
1361 * implementation changes, so should we.
1362 */
1363
1364 switch (type) {
1365 case MAC_NOTE_LINK:
1366 /*
1367 * This notification is sent every time the MAC driver
1368 * updates the link state.
1369 */
1370 if (mac_stat_get(mac->am_handle, MAC_STAT_LINK_UP) != 0) {
1371 if (mac->am_link_state == AOE_MAC_LINK_STATE_UP) {
1372 break;
1373 }
1374
1375 (void) aoe_mac_set_address(mac,
1376 mac->am_primary_addr, B_FALSE);
1377
1378 mac->am_link_state = AOE_MAC_LINK_STATE_UP;
1379
1380 for (i = 0; i < port->p_mac_cnt; i++) {
1381 if (port->p_mac[i]->am_link_state ==
1382 AOE_MAC_LINK_STATE_UP)
1383 link_cnt++;
1384 }
1385
1386 /*
1387 * Signal only once... we can have 2+ MACs with
1388 * different states, but if at least one is green
1389 * we are in "good" shape
1390 */
1391 if (link_cnt == 1) {
1392 dev_err(port->p_client_dev, CE_WARN,
1393 "aoe_mac_notify: link/%d arg/%p LINK up",
1394 mac->am_linkid, arg);
1395 aoe_port_notify_link_up(port);
1396 }
1397 } else {
1398 if (mac->am_link_state == AOE_MAC_LINK_STATE_DOWN) {
1399 break;
1400 }
1401
1402 mac->am_link_state = AOE_MAC_LINK_STATE_DOWN;
1403
1404 for (i = 0; i < port->p_mac_cnt; i++) {
1405 if (port->p_mac[i]->am_link_state ==
1406 AOE_MAC_LINK_STATE_UP)
1407 link_cnt++;
1408 }
1409
1410 /*
1411 * Signal only once
1412 */
1413 if (link_cnt == 0) {
1414 dev_err(port->p_client_dev, CE_WARN,
1415 "aoe_mac_notify: link/%d arg/%p LINK down",
1416 mac->am_linkid, arg);
1417 aoe_port_notify_link_down(port);
1418 }
1419 }
1420 break;
1421
1422 case MAC_NOTE_TX:
1423 /*
1424 * MAC is not so busy now, then wake up aoe_tx_frame to try
1425 */
1426 mutex_enter(&mac->am_mutex);
1427 cv_broadcast(&mac->am_tx_cv);
1428 mutex_exit(&mac->am_mutex);
1429 break;
1430
1431 case MAC_NOTE_CAPAB_CHG:
1432 /*
1433 * This notification is sent whenever the MAC resources
1434 * change or capabilities change. We need to renegotiate
1435 * the capabilities. This driver does not support this feature.
1436 */
1437 break;
1438
1439 case MAC_NOTE_LOWLINK:
1440 /*
1441 * LOWLINK refers to the actual link status. For links that
1442 * are not part of a bridge instance LOWLINK and LINK state
1443 * are the same (this is handled above). This driver only
1444 * support this case.
1445 */
1446 break;
1447
1448 default:
1449 dev_err(port->p_client_dev, CE_WARN,
1450 "aoe_mac_notify: not supported arg/%p, type/%d",
1451 arg, type);
1452 break;
1453 }
1454 }
1455
1456 /*
1457 * Device access entry points
1458 */
1459 static int
1460 aoe_open(dev_t *devp, int flag, int otype, cred_t *credp)
1461 {
1462 int instance;
1463 aoe_soft_state_t *ss;
1464
1465 if (otype != OTYP_CHR) {
1466 return (EINVAL);
1467 }
1468
1469 /*
1470 * Only allow root to issue ioctl
1471 */
1472 if (drv_priv(credp) != 0) {
1473 return (EPERM);
1474 }
1475
1476 instance = (int)getminor(*devp);
1477 ss = ddi_get_soft_state(aoe_state, instance);
1478 if (ss == NULL) {
1479 return (ENXIO);
1480 }
1481
1482 mutex_enter(&ss->ss_ioctl_mutex);
1483 if (ss->ss_ioctl_flags & AOE_IOCTL_FLAG_EXCL) {
1484 /*
1485 * It is already open for exclusive access.
1486 * So shut the door on this caller.
1487 */
1488 mutex_exit(&ss->ss_ioctl_mutex);
1489 return (EBUSY);
1490 }
1491
1492 if (flag & FEXCL) {
1493 if (ss->ss_ioctl_flags & AOE_IOCTL_FLAG_OPEN) {
1494 /*
1495 * Exclusive operation not possible
1496 * as it is already opened
1497 */
1498 mutex_exit(&ss->ss_ioctl_mutex);
1499 return (EBUSY);
1500 }
1501 ss->ss_ioctl_flags |= AOE_IOCTL_FLAG_EXCL;
1502 }
1503
1504 ss->ss_ioctl_flags |= AOE_IOCTL_FLAG_OPEN;
1505 mutex_exit(&ss->ss_ioctl_mutex);
1506
1507 return (0);
1508 }
1509
1510 /* ARGSUSED */
1511 static int
1512 aoe_close(dev_t dev, int flag, int otype, cred_t *credp)
1513 {
1514 int instance;
1515 aoe_soft_state_t *ss;
1516
1517 if (otype != OTYP_CHR) {
1518 return (EINVAL);
1519 }
1520
1521 instance = (int)getminor(dev);
1522 ss = ddi_get_soft_state(aoe_state, instance);
1523 if (ss == NULL) {
1524 return (ENXIO);
1525 }
1526
1527 mutex_enter(&ss->ss_ioctl_mutex);
1528 if ((ss->ss_ioctl_flags & AOE_IOCTL_FLAG_OPEN) == 0) {
1529 mutex_exit(&ss->ss_ioctl_mutex);
1530 return (ENODEV);
1531 }
1532
1533 ss->ss_ioctl_flags &= ~AOE_IOCTL_FLAG_MASK;
1534 mutex_exit(&ss->ss_ioctl_mutex);
1535
1536 return (0);
1537 }
1538
1539 static int
1540 aoe_create_port(dev_info_t *parent, aoe_port_t *port,
1541 aoe_cli_type_t type, aoe_cli_policy_t policy, char *module)
1542 {
1543 int rval = 0, i;
1544 dev_info_t *child = NULL;
1545 char *devname;
1546
1547 if (module != NULL)
1548 devname = module;
1549 else
1550 devname = type ? AOET_DRIVER_NAME : AOEI_DRIVER_NAME;
1551
1552 ndi_devi_alloc_sleep(parent, devname, DEVI_PSEUDO_NODEID, &child);
1553 if (child == NULL) {
1554 dev_err(parent, CE_WARN, "fail to create new devinfo '%s'",
1555 devname);
1556 return (NDI_FAILURE);
1557 }
1558
1559 if (ddi_prop_update_int(DDI_DEV_T_NONE, child,
1560 "port_id", port->p_portid) != DDI_PROP_SUCCESS) {
1561 dev_err(parent, CE_WARN,
1562 "prop_update port_id failed for port %d", port->p_portid);
1563 (void) ndi_devi_free(child);
1564 return (NDI_FAILURE);
1565 }
1566
1567 rval = ndi_devi_online(child, NDI_ONLINE_ATTACH);
1568 if (rval != NDI_SUCCESS) {
1569 dev_err(parent, CE_WARN,
1570 "online_driver failed for port %d (%s)", port->p_portid,
1571 devname);
1572 return (NDI_FAILURE);
1573 }
1574
1575 port->p_client_dev = child;
1576 port->p_policy = policy;
1577 port->p_type = type;
1578
1579 for (i = 0; i < port->p_mac_cnt; i++)
1580 port->p_mac[i]->am_use_cnt++;
1581
1582 return (DDI_SUCCESS);
1583 }
1584
1585 static int
1586 aoe_delete_port(dev_info_t *parent, aoeio_t *aoeio, uint32_t portid)
1587 {
1588 int rval, i, mac_cnt;
1589 aoe_port_t *port;
1590 int mac_in_use = 0;
1591
1592 port = aoe_lookup_port_by_id(portid);
1593 if (port == NULL) {
1594 aoeio->aoeio_status = AOEIOE_INVAL_ARG;
1595 return (EINVAL);
1596 }
1597
1598 for (i = 0; i < port->p_mac_cnt; i++) {
1599 aoe_mac_t *mac = port->p_mac[i];
1600
1601 mac = aoe_lookup_mac_by_id(mac->am_linkid);
1602 if (mac == NULL) {
1603 aoeio->aoeio_status = AOEIOE_MAC_NOT_FOUND;
1604 return (EINVAL);
1605 }
1606 }
1607
1608 if (port->p_flags & AOE_PORT_FLAG_BOUND) {
1609 /*
1610 * Offline it first
1611 */
1612 atomic_and_32(&port->p_flags, ~AOE_PORT_FLAG_BUSY);
1613 rval = ndi_devi_offline(port->p_client_dev, NDI_DEVI_REMOVE);
1614 if (rval != NDI_SUCCESS) {
1615 atomic_or_32(&port->p_flags, AOE_PORT_FLAG_BUSY);
1616 aoeio->aoeio_status = AOEIOE_OFFLINE_FAILURE;
1617 dev_err(parent, CE_WARN, "offline_driver %s failed",
1618 ddi_get_name(port->p_client_dev));
1619 return (EBUSY);
1620 }
1621 atomic_and_32(&port->p_flags, ~AOE_PORT_FLAG_BOUND);
1622 }
1623
1624 /*
1625 * If AOE_PORT_FLAG_BOUND flag is clear, it means that deferred
1626 * detach has finished of last delete operation
1627 */
1628
1629 /*
1630 * aoe_destroy_mac() will decrement it.. so we need to
1631 * loop using stack variable...
1632 */
1633 mac_cnt = port->p_mac_cnt;
1634 for (i = mac_cnt - 1; i >= 0; i--) {
1635 aoe_mac_t *mac = port->p_mac[i];
1636 if (mac->am_use_cnt <= 1) {
1637 (void) aoe_close_mac(mac);
1638 aoe_destroy_mac(mac);
1639 } else {
1640 mac_in_use = 1;
1641 break;
1642 }
1643 }
1644 if (!port->p_mac_cnt && !mac_in_use)
1645 aoe_destroy_port(port);
1646 else {
1647 cmn_err(CE_WARN, "Can't delete port due to mac in use\n");
1648 return (EINVAL);
1649 }
1650
1651 return (0);
1652 }
1653
1654 static int
1655 aoe_get_port_list(aoe_port_instance_t *ports, int count)
1656 {
1657 int i = 0;
1658 int j;
1659 aoe_port_t *port;
1660
1661 ASSERT(ports != NULL);
1662 ASSERT(MUTEX_HELD(&aoe_global_ss->ss_ioctl_mutex));
1663
1664 for (port = list_head(&aoe_global_ss->ss_port_list); port;
1665 port = list_next(&aoe_global_ss->ss_port_list, port)) {
1666 if (i >= count)
1667 break;
1668 ports[i].api_mac_cnt = port->p_mac_cnt;
1669 ports[i].api_maxxfer = port->p_eport.eport_maxxfer;
1670 ports[i].api_port_id = port->p_portid;
1671 ports[i].api_port_policy = port->p_policy;
1672 ports[i].api_port_state = port->p_state;
1673 ports[i].api_port_type = port->p_type;
1674 for (j = 0; j < port->p_mac_cnt; j++) {
1675 aoe_mac_t *mac = port->p_mac[j];
1676
1677 ports[i].api_mac[j].ami_mac_rx_frames =
1678 mac->am_rx_frames;
1679
1680 ports[i].api_mac[j].ami_mac_tx_frames =
1681 mac->am_tx_frames;
1682
1683 ports[i].api_mac[j].ami_mac_link_state =
1684 mac->am_link_state;
1685
1686 ports[i].api_mac[j].ami_mac_linkid = mac->am_linkid;
1687
1688 ether_copy((void *)mac->am_current_addr,
1689 (void *)ports[i].api_mac[j].ami_mac_current_addr);
1690
1691 ether_copy((void *)mac->am_primary_addr,
1692 (void *)ports[i].api_mac[j].ami_mac_factory_addr);
1693
1694 ports[i].api_mac[j].ami_mtu_size = mac->am_mtu;
1695
1696 ports[i].api_mac[j].ami_mac_promisc =
1697 mac->am_promisc_handle != NULL ? 1 : 0;
1698 }
1699 i++;
1700 }
1701 return (i);
1702 }
1703
1704 /* ARGSUSED */
1705 static int
1706 aoe_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
1707 cred_t *credp, int *rval)
1708 {
1709 aoe_soft_state_t *ss;
1710 int ret = 0;
1711
1712 if (drv_priv(credp) != 0) {
1713 return (EPERM);
1714 }
1715
1716 ss = ddi_get_soft_state(aoe_state, (int32_t)getminor(dev));
1717 if (ss == NULL) {
1718 return (ENXIO);
1719 }
1720
1721 mutex_enter(&ss->ss_ioctl_mutex);
1722 if ((ss->ss_ioctl_flags & AOE_IOCTL_FLAG_OPEN) == 0) {
1723 mutex_exit(&ss->ss_ioctl_mutex);
1724 return (ENXIO);
1725 }
1726 mutex_exit(&ss->ss_ioctl_mutex);
1727
1728 switch (cmd) {
1729 case AOEIO_CMD:
1730 ret = aoe_iocmd(ss, data, mode);
1731 break;
1732 default:
1733 ret = ENOTTY;
1734 break;
1735 }
1736
1737 return (ret);
1738 }
1739
1740 static int
1741 aoe_copyin_iocdata(intptr_t data, int mode, aoeio_t **aoeio,
1742 void **ibuf, void **abuf, void **obuf)
1743 {
1744 int ret = 0;
1745
1746 *ibuf = NULL;
1747 *abuf = NULL;
1748 *obuf = NULL;
1749 *aoeio = kmem_zalloc(sizeof (aoeio_t), KM_SLEEP);
1750 if (ddi_copyin((void *)data, *aoeio, sizeof (aoeio_t), mode) != 0) {
1751 ret = EFAULT;
1752 goto copyin_iocdata_fail;
1753 }
1754
1755 if ((*aoeio)->aoeio_ilen > AOEIO_MAX_BUF_LEN ||
1756 (*aoeio)->aoeio_alen > AOEIO_MAX_BUF_LEN ||
1757 (*aoeio)->aoeio_olen > AOEIO_MAX_BUF_LEN) {
1758 ret = EFAULT;
1759 goto copyin_iocdata_fail;
1760 }
1761
1762 if ((*aoeio)->aoeio_ilen) {
1763 *ibuf = kmem_zalloc((*aoeio)->aoeio_ilen, KM_SLEEP);
1764 if (ddi_copyin((void *)(unsigned long)(*aoeio)->aoeio_ibuf,
1765 *ibuf, (*aoeio)->aoeio_ilen, mode) != 0) {
1766 ret = EFAULT;
1767 goto copyin_iocdata_fail;
1768 }
1769 }
1770
1771 if ((*aoeio)->aoeio_alen) {
1772 *abuf = kmem_zalloc((*aoeio)->aoeio_alen, KM_SLEEP);
1773 if (ddi_copyin((void *)(unsigned long)(*aoeio)->aoeio_abuf,
1774 *abuf, (*aoeio)->aoeio_alen, mode) != 0) {
1775 ret = EFAULT;
1776 goto copyin_iocdata_fail;
1777 }
1778 }
1779
1780 if ((*aoeio)->aoeio_olen) {
1781 *obuf = kmem_zalloc((*aoeio)->aoeio_olen, KM_SLEEP);
1782 }
1783 return (ret);
1784
1785 copyin_iocdata_fail:
1786 if (*abuf) {
1787 kmem_free(*abuf, (*aoeio)->aoeio_alen);
1788 *abuf = NULL;
1789 }
1790
1791 if (*ibuf) {
1792 kmem_free(*ibuf, (*aoeio)->aoeio_ilen);
1793 *ibuf = NULL;
1794 }
1795
1796 kmem_free(*aoeio, sizeof (aoeio_t));
1797 return (ret);
1798 }
1799
1800 static int
1801 aoe_copyout_iocdata(intptr_t data, int mode, aoeio_t *aoeio, void *obuf)
1802 {
1803
1804 if (aoeio->aoeio_olen) {
1805 if (ddi_copyout(obuf,
1806 (void *)(unsigned long)aoeio->aoeio_obuf,
1807 aoeio->aoeio_olen, mode) != 0) {
1808 return (EFAULT);
1809 }
1810 }
1811
1812 if (ddi_copyout(aoeio, (void *)data, sizeof (aoeio_t), mode) != 0) {
1813 return (EFAULT);
1814 }
1815 return (0);
1816 }
1817
1818 static int
1819 aoe_iocmd(aoe_soft_state_t *ss, intptr_t data, int mode)
1820 {
1821 aoe_mac_t *aoe_mac[AOE_MAX_MACOBJ];
1822 aoeio_t *aoeio;
1823 int i;
1824 int j;
1825 int ret = 0;
1826 void *abuf = NULL;
1827 void *ibuf = NULL;
1828 void *obuf = NULL;
1829
1830 ret = aoe_copyin_iocdata(data, mode, &aoeio, &ibuf, &abuf, &obuf);
1831 if (ret != 0)
1832 goto aoeiocmd_release_buf;
1833
1834 /*
1835 * If an exclusive open was demanded during open, ensure that
1836 * only one thread can execute an ioctl at a time
1837 */
1838 mutex_enter(&ss->ss_ioctl_mutex);
1839 if (ss->ss_ioctl_flags & AOE_IOCTL_FLAG_EXCL) {
1840 if (ss->ss_ioctl_flags & AOE_IOCTL_FLAG_EXCL_BUSY) {
1841 mutex_exit(&ss->ss_ioctl_mutex);
1842 aoeio->aoeio_status = AOEIOE_BUSY;
1843 ret = EBUSY;
1844 goto aoeiocmd_release_buf;
1845 }
1846 ss->ss_ioctl_flags |= AOE_IOCTL_FLAG_EXCL_BUSY;
1847 }
1848 mutex_exit(&ss->ss_ioctl_mutex);
1849
1850 aoeio->aoeio_status = 0;
1851
1852 switch (aoeio->aoeio_cmd) {
1853 case AOEIO_CREATE_PORT: {
1854 aoe_port_t *created_port = NULL;
1855 aoe_mac_t *created_mac[AOE_MAX_MACOBJ];
1856 aoe_mac_t *opened_mac[AOE_MAX_MACOBJ];
1857 int mac_used = 0, m = 0, n = 0;
1858 int is_port_created = 0;
1859 aoeio_create_port_param_t *param =
1860 (aoeio_create_port_param_t *)ibuf;
1861 int portid = param->acp_port_id;
1862
1863 if (aoeio->aoeio_ilen != sizeof (aoeio_create_port_param_t) ||
1864 aoeio->aoeio_xfer != AOEIO_XFER_WRITE) {
1865 aoeio->aoeio_status = AOEIOE_INVAL_ARG;
1866 ret = EINVAL;
1867 break;
1868 }
1869
1870 mutex_enter(&ss->ss_ioctl_mutex);
1871
1872 if (aoe_lookup_port_by_id(portid) != NULL) {
1873 aoeio->aoeio_status = AOEIOE_ALREADY;
1874 ret = EINVAL;
1875 mutex_exit(&ss->ss_ioctl_mutex);
1876 break;
1877 }
1878
1879 /*
1880 * In case of error, we should destroy all the
1881 * created macs and the created port.
1882 */
1883 for (i = 0; i < AOE_MAX_MACOBJ; i++) {
1884 int linkid = param->acp_mac_linkid[i];
1885 aoe_mac_t *mac;
1886
1887 /* last one */
1888 if (linkid == 0)
1889 break;
1890
1891 aoe_mac[i] = NULL;
1892 mac = aoe_create_mac_by_id(portid, linkid,
1893 &is_port_created);
1894 if (mac == NULL) {
1895 aoeio->aoeio_status = AOEIOE_CREATE_MAC;
1896 ret = EIO;
1897 goto error_1;
1898 }
1899 if (mac->am_port->p_mac_cnt == 1)
1900 created_port = mac->am_port;
1901 created_mac[m++] = mac;
1902 if (mac->am_use_cnt) {
1903 aoe_mac[i] = mac;
1904 continue;
1905 }
1906 for (j = i - 1; j >= 0; j--) {
1907 if (aoe_mac[j] == mac) {
1908 aoeio->aoeio_status = AOEIOE_ALREADY;
1909 ret = EINVAL;
1910 goto error_1;
1911 }
1912 }
1913 ret = aoe_open_mac(mac, param->acp_force_promisc);
1914 if (ret != 0) {
1915 ret = EIO;
1916 if (aoeio->aoeio_status == 0)
1917 aoeio->aoeio_status = AOEIOE_OPEN_MAC;
1918 goto error_1;
1919 }
1920 opened_mac[n++] = mac;
1921 aoe_mac[i] = mac;
1922 }
1923
1924 ret = aoe_create_port(ss->ss_dip, aoe_mac[0]->am_port,
1925 param->acp_port_type, param->acp_port_policy,
1926 (*param->acp_module) ? param->acp_module : NULL);
1927 if (!ret)
1928 goto exit_1;
1929 aoeio->aoeio_status = AOEIOE_CREATE_PORT;
1930 ret = EIO;
1931
1932 error_1:
1933 for (i = 0; i < n; i++) {
1934 if (!opened_mac[i]->am_use_cnt)
1935 (void) aoe_close_mac(opened_mac[i]);
1936 else
1937 mac_used = 1;
1938 }
1939 for (i = 0; i < m; i++) {
1940 if (!created_mac[i]->am_use_cnt)
1941 aoe_destroy_mac(created_mac[i]);
1942 else
1943 mac_used = 1;
1944 }
1945 if (is_port_created) {
1946 if (!mac_used) {
1947 created_port = aoe_lookup_port_by_id(portid);
1948 aoe_destroy_port(created_port);
1949 } else {
1950 cmn_err(CE_WARN, "Cannot delete port after "
1951 "failed port creation due to "
1952 "a mac is in use!\n");
1953 }
1954 }
1955 exit_1:
1956 mutex_exit(&ss->ss_ioctl_mutex);
1957 break;
1958 }
1959
1960 case AOEIO_DELETE_PORT: {
1961 aoeio_delete_port_param_t *del_port_param =
1962 (aoeio_delete_port_param_t *)ibuf;
1963
1964 if (aoeio->aoeio_ilen < sizeof (aoeio_delete_port_param_t) ||
1965 aoeio->aoeio_xfer != AOEIO_XFER_READ) {
1966 aoeio->aoeio_status = AOEIOE_INVAL_ARG;
1967 ret = EINVAL;
1968 break;
1969 }
1970
1971 mutex_enter(&ss->ss_ioctl_mutex);
1972 ret = aoe_delete_port(ss->ss_dip, aoeio,
1973 del_port_param->adp_port_id);
1974 mutex_exit(&ss->ss_ioctl_mutex);
1975 break;
1976 }
1977
1978 case AOEIO_GET_PORT_LIST: {
1979 aoe_port_list_t *list = (aoe_port_list_t *)obuf;
1980 int count;
1981
1982 if (aoeio->aoeio_xfer != AOEIO_XFER_READ ||
1983 aoeio->aoeio_olen < sizeof (aoe_port_list_t)) {
1984 aoeio->aoeio_status = AOEIOE_INVAL_ARG;
1985 ret = EINVAL;
1986 break;
1987 }
1988 mutex_enter(&ss->ss_ioctl_mutex);
1989
1990 list->num_ports = 1 + (aoeio->aoeio_olen -
1991 sizeof (aoe_port_list_t))/sizeof (aoe_port_instance_t);
1992
1993 count = aoe_get_port_list(list->ports, list->num_ports);
1994
1995 if (count > list->num_ports) {
1996 aoeio->aoeio_status = AOEIOE_MORE_DATA;
1997 ret = ENOSPC;
1998 }
1999 list->num_ports = count;
2000 mutex_exit(&ss->ss_ioctl_mutex);
2001
2002 break;
2003
2004 }
2005
2006 default:
2007 return (ENOTTY);
2008 }
2009
2010 aoeiocmd_release_buf:
2011 if (ret == 0) {
2012 ret = aoe_copyout_iocdata(data, mode, aoeio, obuf);
2013 } else if (aoeio->aoeio_status) {
2014 (void) aoe_copyout_iocdata(data, mode, aoeio, obuf);
2015 }
2016
2017 if (obuf != NULL) {
2018 kmem_free(obuf, aoeio->aoeio_olen);
2019 obuf = NULL;
2020 }
2021 if (abuf != NULL) {
2022 kmem_free(abuf, aoeio->aoeio_alen);
2023 abuf = NULL;
2024 }
2025
2026 if (ibuf != NULL) {
2027 kmem_free(ibuf, aoeio->aoeio_ilen);
2028 ibuf = NULL;
2029 }
2030 kmem_free(aoeio, sizeof (aoeio_t));
2031
2032 return (ret);
2033 }
2034
2035 static int
2036 aoe_i_port_autoconf(uint32_t portid)
2037 {
2038 aoeio_t iost;
2039 int ret, i;
2040 aoe_soft_state_t *ss = aoe_global_ss;
2041 aoe_mac_t *mac;
2042 uint32_t linkid = rootfs.bo_ppa;
2043 aoe_port_t *created_port = NULL;
2044 int is_port_created = 0;
2045
2046 /*
2047 * Automatically discover MAC interfaces with AoE targets on it
2048 * One MAC per port will be created. Means that if you have
2049 * multi-pathed AoE target setup, system will see two disks
2050 */
2051 mutex_enter(&ss->ss_ioctl_mutex);
2052 mac = aoe_create_mac_by_id(portid, linkid, &is_port_created);
2053 if (mac == NULL) {
2054 cmn_err(CE_WARN, "Error while creating mac linkid=%d", linkid);
2055 if (is_port_created) {
2056 created_port = aoe_lookup_port_by_id(portid);
2057 aoe_destroy_port(created_port);
2058 }
2059 mutex_exit(&ss->ss_ioctl_mutex);
2060 return (0);
2061 }
2062
2063 (void) strlcpy(mac->am_ifname, rootfs.bo_ifname,
2064 sizeof (mac->am_ifname));
2065
2066 ret = aoe_open_mac(mac, B_FALSE);
2067 if (ret != 0) {
2068 cmn_err(CE_WARN, "Error while opening mac linkid=%d", linkid);
2069 aoe_destroy_mac(mac);
2070 if (is_port_created) {
2071 created_port = aoe_lookup_port_by_id(portid);
2072 aoe_destroy_port(created_port);
2073 }
2074 mutex_exit(&ss->ss_ioctl_mutex);
2075 return (0);
2076 }
2077
2078 ret = aoe_create_port(ss->ss_dip, mac->am_port,
2079 AOE_CLIENT_INITIATOR, AOE_POLICY_FAILOVER, NULL);
2080 if (ret != 0) {
2081 cmn_err(CE_WARN, "Error while creating port linkid=%d", linkid);
2082 (void) aoe_close_mac(mac);
2083 aoe_destroy_mac(mac);
2084 if (is_port_created) {
2085 created_port = aoe_lookup_port_by_id(portid);
2086 aoe_destroy_port(created_port);
2087 }
2088 mutex_exit(&ss->ss_ioctl_mutex);
2089 return (0);
2090 }
2091 mutex_exit(&ss->ss_ioctl_mutex);
2092
2093 /*
2094 * We got that far means port in a good shape,
2095 * lets poll for state change...
2096 *
2097 * Timeout is 30 seconds so that at least two attempts of periodic
2098 * disk discovery would fit while brining up boot device...
2099 */
2100 for (i = 0; i < 30; i++) {
2101 delay(100);
2102 if (mac->am_port->p_unit_cnt > 0) {
2103 cmn_err(CE_NOTE, "AoE autoconf: %d disks detected",
2104 mac->am_port->p_unit_cnt);
2105 /*
2106 * TODO: If boot-aoepath is set to "auto",
2107 * configure first found AoE device. This is
2108 * to be done in the future.
2109 */
2110 if (aoepath_prop != NULL &&
2111 strcmp(aoepath_prop, "auto") == 0)
2112 cmn_err(CE_PANIC, "FIXME autoconf bootpath");
2113
2114 /* keep port open */
2115 return (1);
2116 }
2117 }
2118
2119 mutex_enter(&ss->ss_ioctl_mutex);
2120 ret = aoe_delete_port(ss->ss_dip, &iost, portid);
2121 mutex_exit(&ss->ss_ioctl_mutex);
2122
2123 return (0);
2124 }
2125
2126 static int
2127 aoe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2128 {
2129 int ret;
2130 int instance;
2131 aoe_soft_state_t *ss;
2132
2133 instance = ddi_get_instance(dip);
2134 switch (cmd) {
2135 case DDI_ATTACH:
2136 break;
2137
2138 case DDI_RESUME:
2139 case DDI_PM_RESUME:
2140 dev_err(dip, CE_WARN, "resume not supported yet");
2141 ret = DDI_FAILURE;
2142 goto exit;
2143
2144 default:
2145 dev_err(dip, CE_WARN, "cmd 0x%x not recognized", cmd);
2146 ret = DDI_FAILURE;
2147 goto exit;
2148 }
2149
2150 ret = ddi_soft_state_zalloc(aoe_state, instance);
2151 if (ret != DDI_SUCCESS) {
2152 dev_err(dip, CE_WARN, "soft_state_zalloc-%x/%x", ret,
2153 instance);
2154 goto exit;
2155 }
2156
2157 ss = ddi_get_soft_state(aoe_state, instance);
2158 ss->ss_dip = dip;
2159 ss->ss_ioctl_flags = 0;
2160 mutex_init(&ss->ss_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
2161 list_create(&ss->ss_mac_list, sizeof (aoe_mac_t),
2162 offsetof(aoe_mac_t, am_ss_node));
2163 list_create(&ss->ss_port_list, sizeof (aoe_port_t),
2164 offsetof(aoe_port_t, p_ss_node));
2165
2166 ret = ddi_create_minor_node(dip, "admin", S_IFCHR,
2167 ddi_get_instance(dip), DDI_PSEUDO, 0);
2168 if (ret != DDI_SUCCESS) {
2169 dev_err(dip, CE_WARN, "ddi_create_minor_node failed");
2170 goto exit;
2171 }
2172
2173 ASSERT(aoe_global_ss == NULL);
2174 aoe_global_ss = ss;
2175
2176 if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_root_node(),
2177 DDI_PROP_DONTPASS, "boot-mac"))
2178 (void) aoe_i_port_autoconf(0);
2179
2180 ddi_report_dev(dip);
2181 return (DDI_SUCCESS);
2182
2183 exit:
2184 return (ret);
2185 }
2186
2187 static int
2188 aoe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2189 {
2190 aoe_soft_state_t *ss;
2191 int instance;
2192
2193 instance = ddi_get_instance(dip);
2194 ss = ddi_get_soft_state(aoe_state, instance);
2195 if (ss == NULL)
2196 return (DDI_FAILURE);
2197
2198 ASSERT(aoe_global_ss != NULL);
2199 ASSERT(dip == aoe_global_ss->ss_dip);
2200
2201 switch (cmd) {
2202 case DDI_DETACH:
2203 break;
2204 case DDI_PM_SUSPEND:
2205 dev_err(dip, CE_WARN, "suspend not supported yet");
2206 return (DDI_FAILURE);
2207 default:
2208 dev_err(dip, CE_WARN, "cmd 0x%x unrecognized", cmd);
2209 return (DDI_FAILURE);
2210 }
2211
2212 if (!list_is_empty(&ss->ss_mac_list)) {
2213 dev_err(dip, CE_WARN, "ss_mac_list is not empty when detach");
2214 return (DDI_FAILURE);
2215 }
2216
2217 ddi_remove_minor_node(ss->ss_dip, NULL);
2218 mutex_destroy(&ss->ss_ioctl_mutex);
2219 list_destroy(&ss->ss_mac_list);
2220 list_destroy(&ss->ss_port_list);
2221
2222 return (DDI_SUCCESS);
2223 }
2224
2225 /*
2226 * Check if AoE port can be detached
2227 */
2228 static uint32_t
2229 aoe_allow_port_detach(aoe_eport_t *eport)
2230 {
2231 aoe_port_t *port = EPORT2PORT(eport);
2232
2233 return (port->p_flags & AOE_PORT_FLAG_BUSY);
2234 }
2235
2236 int
2237 _init(void)
2238 {
2239 int rv;
2240
2241 rv = ddi_soft_state_init(&aoe_state, sizeof (aoe_soft_state_t), 0);
2242 if (rv != 0)
2243 return (rv);
2244
2245 if ((rv = mod_install(&modlinkage)) != 0)
2246 ddi_soft_state_fini(&aoe_state);
2247
2248 return (rv);
2249 }
2250
2251 int
2252 _fini(void)
2253 {
2254 int rv;
2255
2256 if ((rv = mod_remove(&modlinkage)) == 0)
2257 ddi_soft_state_fini(&aoe_state);
2258
2259 return (rv);
2260 }
2261
2262 int
2263 _info(struct modinfo *modinfop)
2264 {
2265
2266 return (mod_info(&modlinkage, modinfop));
2267 }