Lines Matching +full:lock +full:- +full:state

1 // SPDX-License-Identifier: GPL-2.0-or-later
22 #include "ncsi-pkt.h"
23 #include "ncsi-netlink.h"
30 return !!(channel->modes[NCSI_MODE_LINK].data[2] & 0x1); in ncsi_channel_has_link()
43 if (nc->state == NCSI_CHANNEL_ACTIVE && in ncsi_channel_is_last()
53 struct ncsi_dev *nd = &ndp->ndev; in ncsi_report_link()
58 nd->state = ncsi_dev_state_functional; in ncsi_report_link()
60 nd->link_up = 0; in ncsi_report_link()
64 nd->link_up = 0; in ncsi_report_link()
67 spin_lock_irqsave(&nc->lock, flags); in ncsi_report_link()
69 if (!list_empty(&nc->link) || in ncsi_report_link()
70 nc->state != NCSI_CHANNEL_ACTIVE) { in ncsi_report_link()
71 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_report_link()
76 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_report_link()
77 nd->link_up = 1; in ncsi_report_link()
81 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_report_link()
86 nd->handler(nd); in ncsi_report_link()
92 struct ncsi_package *np = nc->package; in ncsi_channel_monitor()
93 struct ncsi_dev_priv *ndp = np->ndp; in ncsi_channel_monitor()
99 int state, ret; in ncsi_channel_monitor() local
101 spin_lock_irqsave(&nc->lock, flags); in ncsi_channel_monitor()
102 state = nc->state; in ncsi_channel_monitor()
103 chained = !list_empty(&nc->link); in ncsi_channel_monitor()
104 enabled = nc->monitor.enabled; in ncsi_channel_monitor()
105 monitor_state = nc->monitor.state; in ncsi_channel_monitor()
106 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_channel_monitor()
113 if (state != NCSI_CHANNEL_INACTIVE && in ncsi_channel_monitor()
114 state != NCSI_CHANNEL_ACTIVE) { in ncsi_channel_monitor()
116 netdev_warn(ndp->ndev.dev, in ncsi_channel_monitor()
117 "Bad NCSI monitor state channel %d 0x%x %s queue\n", in ncsi_channel_monitor()
118 nc->id, state, chained ? "on" : "off"); in ncsi_channel_monitor()
119 spin_lock_irqsave(&nc->lock, flags); in ncsi_channel_monitor()
120 nc->monitor.enabled = false; in ncsi_channel_monitor()
121 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_channel_monitor()
129 nca.package = np->id; in ncsi_channel_monitor()
130 nca.channel = nc->id; in ncsi_channel_monitor()
135 netdev_err(ndp->ndev.dev, "Error %d sending GLS\n", in ncsi_channel_monitor()
141 netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n", in ncsi_channel_monitor()
142 nc->id); in ncsi_channel_monitor()
144 ndp->flags |= NCSI_DEV_RESHUFFLE; in ncsi_channel_monitor()
146 ncm = &nc->modes[NCSI_MODE_LINK]; in ncsi_channel_monitor()
147 spin_lock_irqsave(&nc->lock, flags); in ncsi_channel_monitor()
148 nc->monitor.enabled = false; in ncsi_channel_monitor()
149 nc->state = NCSI_CHANNEL_INVISIBLE; in ncsi_channel_monitor()
150 ncm->data[2] &= ~0x1; in ncsi_channel_monitor()
151 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_channel_monitor()
153 spin_lock_irqsave(&ndp->lock, flags); in ncsi_channel_monitor()
154 nc->state = NCSI_CHANNEL_ACTIVE; in ncsi_channel_monitor()
155 list_add_tail_rcu(&nc->link, &ndp->channel_queue); in ncsi_channel_monitor()
156 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_channel_monitor()
161 spin_lock_irqsave(&nc->lock, flags); in ncsi_channel_monitor()
162 nc->monitor.state++; in ncsi_channel_monitor()
163 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_channel_monitor()
164 mod_timer(&nc->monitor.timer, jiffies + HZ); in ncsi_channel_monitor()
171 spin_lock_irqsave(&nc->lock, flags); in ncsi_start_channel_monitor()
172 WARN_ON_ONCE(nc->monitor.enabled); in ncsi_start_channel_monitor()
173 nc->monitor.enabled = true; in ncsi_start_channel_monitor()
174 nc->monitor.state = NCSI_CHANNEL_MONITOR_START; in ncsi_start_channel_monitor()
175 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_start_channel_monitor()
177 mod_timer(&nc->monitor.timer, jiffies + HZ); in ncsi_start_channel_monitor()
184 spin_lock_irqsave(&nc->lock, flags); in ncsi_stop_channel_monitor()
185 if (!nc->monitor.enabled) { in ncsi_stop_channel_monitor()
186 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_stop_channel_monitor()
189 nc->monitor.enabled = false; in ncsi_stop_channel_monitor()
190 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_stop_channel_monitor()
192 del_timer_sync(&nc->monitor.timer); in ncsi_stop_channel_monitor()
201 if (nc->id == id) in ncsi_find_channel()
218 nc->id = id; in ncsi_add_channel()
219 nc->package = np; in ncsi_add_channel()
220 nc->state = NCSI_CHANNEL_INACTIVE; in ncsi_add_channel()
221 nc->monitor.enabled = false; in ncsi_add_channel()
222 timer_setup(&nc->monitor.timer, ncsi_channel_monitor, 0); in ncsi_add_channel()
223 spin_lock_init(&nc->lock); in ncsi_add_channel()
224 INIT_LIST_HEAD(&nc->link); in ncsi_add_channel()
226 nc->caps[index].index = index; in ncsi_add_channel()
228 nc->modes[index].index = index; in ncsi_add_channel()
230 spin_lock_irqsave(&np->lock, flags); in ncsi_add_channel()
233 spin_unlock_irqrestore(&np->lock, flags); in ncsi_add_channel()
238 list_add_tail_rcu(&nc->node, &np->channels); in ncsi_add_channel()
239 np->channel_num++; in ncsi_add_channel()
240 spin_unlock_irqrestore(&np->lock, flags); in ncsi_add_channel()
247 struct ncsi_package *np = nc->package; in ncsi_remove_channel()
250 spin_lock_irqsave(&nc->lock, flags); in ncsi_remove_channel()
253 kfree(nc->mac_filter.addrs); in ncsi_remove_channel()
254 kfree(nc->vlan_filter.vids); in ncsi_remove_channel()
256 nc->state = NCSI_CHANNEL_INACTIVE; in ncsi_remove_channel()
257 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_remove_channel()
261 spin_lock_irqsave(&np->lock, flags); in ncsi_remove_channel()
262 list_del_rcu(&nc->node); in ncsi_remove_channel()
263 np->channel_num--; in ncsi_remove_channel()
264 spin_unlock_irqrestore(&np->lock, flags); in ncsi_remove_channel()
275 if (np->id == id) in ncsi_find_package()
292 np->id = id; in ncsi_add_package()
293 np->ndp = ndp; in ncsi_add_package()
294 spin_lock_init(&np->lock); in ncsi_add_package()
295 INIT_LIST_HEAD(&np->channels); in ncsi_add_package()
296 np->channel_whitelist = UINT_MAX; in ncsi_add_package()
298 spin_lock_irqsave(&ndp->lock, flags); in ncsi_add_package()
301 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_add_package()
306 list_add_tail_rcu(&np->node, &ndp->packages); in ncsi_add_package()
307 ndp->package_num++; in ncsi_add_package()
308 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_add_package()
315 struct ncsi_dev_priv *ndp = np->ndp; in ncsi_remove_package()
320 list_for_each_entry_safe(nc, tmp, &np->channels, node) in ncsi_remove_package()
324 spin_lock_irqsave(&ndp->lock, flags); in ncsi_remove_package()
325 list_del_rcu(&np->node); in ncsi_remove_package()
326 ndp->package_num--; in ncsi_remove_package()
327 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_remove_package()
351 * the available IDs are allocated in round-robin fashion.
357 int i, limit = ARRAY_SIZE(ndp->requests); in ncsi_alloc_request()
361 spin_lock_irqsave(&ndp->lock, flags); in ncsi_alloc_request()
362 for (i = ndp->request_id; i < limit; i++) { in ncsi_alloc_request()
363 if (ndp->requests[i].used) in ncsi_alloc_request()
366 nr = &ndp->requests[i]; in ncsi_alloc_request()
367 nr->used = true; in ncsi_alloc_request()
368 nr->flags = req_flags; in ncsi_alloc_request()
369 ndp->request_id = i + 1; in ncsi_alloc_request()
374 for (i = NCSI_REQ_START_IDX; i < ndp->request_id; i++) { in ncsi_alloc_request()
375 if (ndp->requests[i].used) in ncsi_alloc_request()
378 nr = &ndp->requests[i]; in ncsi_alloc_request()
379 nr->used = true; in ncsi_alloc_request()
380 nr->flags = req_flags; in ncsi_alloc_request()
381 ndp->request_id = i + 1; in ncsi_alloc_request()
386 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_alloc_request()
392 struct ncsi_dev_priv *ndp = nr->ndp; in ncsi_free_request()
397 if (nr->enabled) { in ncsi_free_request()
398 nr->enabled = false; in ncsi_free_request()
399 del_timer_sync(&nr->timer); in ncsi_free_request()
402 spin_lock_irqsave(&ndp->lock, flags); in ncsi_free_request()
403 cmd = nr->cmd; in ncsi_free_request()
404 rsp = nr->rsp; in ncsi_free_request()
405 nr->cmd = NULL; in ncsi_free_request()
406 nr->rsp = NULL; in ncsi_free_request()
407 nr->used = false; in ncsi_free_request()
408 driven = !!(nr->flags & NCSI_REQ_FLAG_EVENT_DRIVEN); in ncsi_free_request()
409 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_free_request()
411 if (driven && cmd && --ndp->pending_req_num == 0) in ncsi_free_request()
412 schedule_work(&ndp->work); in ncsi_free_request()
424 if (ndp->ndev.dev == dev) in ncsi_find_dev()
425 return &ndp->ndev; in ncsi_find_dev()
434 struct ncsi_dev_priv *ndp = nr->ndp; in ncsi_request_timeout()
443 spin_lock_irqsave(&ndp->lock, flags); in ncsi_request_timeout()
444 nr->enabled = false; in ncsi_request_timeout()
445 if (nr->rsp || !nr->cmd) { in ncsi_request_timeout()
446 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_request_timeout()
449 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_request_timeout()
451 if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) { in ncsi_request_timeout()
452 if (nr->cmd) { in ncsi_request_timeout()
455 skb_network_header(nr->cmd); in ncsi_request_timeout()
457 cmd->cmd.common.channel, in ncsi_request_timeout()
469 struct ncsi_dev *nd = &ndp->ndev; in ncsi_suspend_channel()
476 np = ndp->active_package; in ncsi_suspend_channel()
477 nc = ndp->active_channel; in ncsi_suspend_channel()
480 switch (nd->state) { in ncsi_suspend_channel()
482 nd->state = ncsi_dev_state_suspend_select; in ncsi_suspend_channel()
485 ndp->pending_req_num = 1; in ncsi_suspend_channel()
488 nca.package = np->id; in ncsi_suspend_channel()
490 if (ndp->flags & NCSI_DEV_HWA) in ncsi_suspend_channel()
503 if (ndp->flags & NCSI_DEV_RESHUFFLE) in ncsi_suspend_channel()
504 nd->state = ncsi_dev_state_suspend_gls; in ncsi_suspend_channel()
506 nd->state = ncsi_dev_state_suspend_dcnt; in ncsi_suspend_channel()
513 ndp->pending_req_num = np->channel_num; in ncsi_suspend_channel()
516 nca.package = np->id; in ncsi_suspend_channel()
518 nd->state = ncsi_dev_state_suspend_dcnt; in ncsi_suspend_channel()
520 nca.channel = nc->id; in ncsi_suspend_channel()
528 ndp->pending_req_num = 1; in ncsi_suspend_channel()
531 nca.package = np->id; in ncsi_suspend_channel()
532 nca.channel = nc->id; in ncsi_suspend_channel()
534 nd->state = ncsi_dev_state_suspend_dc; in ncsi_suspend_channel()
541 ndp->pending_req_num = 1; in ncsi_suspend_channel()
544 nca.package = np->id; in ncsi_suspend_channel()
545 nca.channel = nc->id; in ncsi_suspend_channel()
548 nd->state = ncsi_dev_state_suspend_deselect; in ncsi_suspend_channel()
557 if (tmp != nc && tmp->state == NCSI_CHANNEL_ACTIVE) { in ncsi_suspend_channel()
558 nd->state = ncsi_dev_state_suspend_done; in ncsi_suspend_channel()
564 ndp->pending_req_num = 1; in ncsi_suspend_channel()
567 nca.package = np->id; in ncsi_suspend_channel()
570 nd->state = ncsi_dev_state_suspend_done; in ncsi_suspend_channel()
577 spin_lock_irqsave(&nc->lock, flags); in ncsi_suspend_channel()
578 nc->state = NCSI_CHANNEL_INACTIVE; in ncsi_suspend_channel()
579 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_suspend_channel()
580 if (ndp->flags & NCSI_DEV_RESET) in ncsi_suspend_channel()
586 netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n", in ncsi_suspend_channel()
587 nd->state); in ncsi_suspend_channel()
592 nd->state = ncsi_dev_state_functional; in ncsi_suspend_channel()
596 * "Set VLAN Filter - Disable" packet if found.
607 ncf = &nc->vlan_filter; in clear_one_vid()
608 bitmap = &ncf->bitmap; in clear_one_vid()
610 spin_lock_irqsave(&nc->lock, flags); in clear_one_vid()
611 index = find_first_bit(bitmap, ncf->n_vids); in clear_one_vid()
612 if (index >= ncf->n_vids) { in clear_one_vid()
613 spin_unlock_irqrestore(&nc->lock, flags); in clear_one_vid()
614 return -1; in clear_one_vid()
616 vid = ncf->vids[index]; in clear_one_vid()
619 ncf->vids[index] = 0; in clear_one_vid()
620 spin_unlock_irqrestore(&nc->lock, flags); in clear_one_vid()
622 nca->type = NCSI_PKT_CMD_SVF; in clear_one_vid()
623 nca->words[1] = vid; in clear_one_vid()
625 nca->bytes[6] = index + 1; in clear_one_vid()
626 nca->bytes[7] = 0x00; in clear_one_vid()
630 /* Find an outstanding VLAN tag and construct a "Set VLAN Filter - Enable"
643 if (list_empty(&ndp->vlan_vids)) in set_one_vid()
644 return -1; in set_one_vid()
646 ncf = &nc->vlan_filter; in set_one_vid()
647 bitmap = &ncf->bitmap; in set_one_vid()
649 spin_lock_irqsave(&nc->lock, flags); in set_one_vid()
652 list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) { in set_one_vid()
653 vid = vlan->vid; in set_one_vid()
654 for (i = 0; i < ncf->n_vids; i++) in set_one_vid()
655 if (ncf->vids[i] == vid) { in set_one_vid()
666 spin_unlock_irqrestore(&nc->lock, flags); in set_one_vid()
667 return -1; in set_one_vid()
670 index = find_first_zero_bit(bitmap, ncf->n_vids); in set_one_vid()
671 if (index < 0 || index >= ncf->n_vids) { in set_one_vid()
672 netdev_err(ndp->ndev.dev, in set_one_vid()
674 nc->id); in set_one_vid()
675 spin_unlock_irqrestore(&nc->lock, flags); in set_one_vid()
676 return -1; in set_one_vid()
679 ncf->vids[index] = vid; in set_one_vid()
681 spin_unlock_irqrestore(&nc->lock, flags); in set_one_vid()
683 nca->type = NCSI_PKT_CMD_SVF; in set_one_vid()
684 nca->words[1] = vid; in set_one_vid()
686 nca->bytes[6] = index + 1; in set_one_vid()
687 nca->bytes[7] = 0x01; in set_one_vid()
697 nca->payload = NCSI_OEM_INTEL_CMD_KEEP_PHY_LEN; in ncsi_oem_keep_phy_intel()
707 nca->data = data; in ncsi_oem_keep_phy_intel()
711 netdev_err(nca->ndp->ndev.dev, in ncsi_oem_keep_phy_intel()
713 nca->type); in ncsi_oem_keep_phy_intel()
723 nca->payload = NCSI_OEM_BCM_CMD_GMA_LEN; in ncsi_oem_gma_handler_bcm()
729 nca->data = data; in ncsi_oem_gma_handler_bcm()
733 netdev_err(nca->ndp->ndev.dev, in ncsi_oem_gma_handler_bcm()
735 nca->type); in ncsi_oem_gma_handler_bcm()
747 nca->payload = NCSI_OEM_MLX_CMD_GMA_LEN; in ncsi_oem_gma_handler_mlx()
754 nca->data = u.data_u8; in ncsi_oem_gma_handler_mlx()
758 netdev_err(nca->ndp->ndev.dev, in ncsi_oem_gma_handler_mlx()
760 nca->type); in ncsi_oem_gma_handler_mlx()
777 nca->ndp->ndev.dev->dev_addr, ETH_ALEN); in ncsi_oem_smaf_mlx()
781 nca->payload = NCSI_OEM_MLX_CMD_SMAF_LEN; in ncsi_oem_smaf_mlx()
782 nca->data = u.data_u8; in ncsi_oem_smaf_mlx()
786 netdev_err(nca->ndp->ndev.dev, in ncsi_oem_smaf_mlx()
788 nca->type); in ncsi_oem_smaf_mlx()
797 nca->payload = NCSI_OEM_INTEL_CMD_GMA_LEN; in ncsi_oem_gma_handler_intel()
803 nca->data = data; in ncsi_oem_gma_handler_intel()
807 netdev_err(nca->ndp->ndev.dev, in ncsi_oem_gma_handler_intel()
809 nca->type); in ncsi_oem_gma_handler_intel()
830 if (nca->ndp->gma_flag == 1) in ncsi_gma_handler()
831 return -1; in ncsi_gma_handler()
843 netdev_err(nca->ndp->ndev.dev, in ncsi_gma_handler()
844 "NCSI: No GMA handler available for MFR-ID (0x%x)\n", in ncsi_gma_handler()
846 return -1; in ncsi_gma_handler()
850 return nch->handler(nca); in ncsi_gma_handler()
865 if (!ndp->multi_package && np != nc->package) in ncsi_channel_is_tx()
868 ncm = &channel->modes[NCSI_MODE_TX_ENABLE]; in ncsi_channel_is_tx()
869 if (ncm->enable) in ncsi_channel_is_tx()
875 list_for_each_entry_rcu(channel, &ndp->channel_queue, link) { in ncsi_channel_is_tx()
876 np = channel->package; in ncsi_channel_is_tx()
877 if (np->preferred_channel && in ncsi_channel_is_tx()
878 ncsi_channel_has_link(np->preferred_channel)) { in ncsi_channel_is_tx()
879 return np->preferred_channel == nc; in ncsi_channel_is_tx()
887 list_for_each_entry_rcu(channel, &ndp->channel_queue, link) in ncsi_channel_is_tx()
895 /* Change the active Tx channel in a multi-channel setup */
906 if (!package->multi_channel && !ndp->multi_package) in ncsi_update_tx_channel()
907 netdev_warn(ndp->ndev.dev, in ncsi_update_tx_channel()
908 "NCSI: Trying to update Tx channel in single-channel mode\n"); in ncsi_update_tx_channel()
916 if (!ndp->multi_package && np != package) in ncsi_update_tx_channel()
920 if (nc->modes[NCSI_MODE_TX_ENABLE].enable) { in ncsi_update_tx_channel()
930 if (!ndp->multi_package && np != package) in ncsi_update_tx_channel()
932 if (!(ndp->package_whitelist & (0x1 << np->id))) in ncsi_update_tx_channel()
935 if (np->preferred_channel && in ncsi_update_tx_channel()
936 ncsi_channel_has_link(np->preferred_channel)) { in ncsi_update_tx_channel()
937 enable = np->preferred_channel; in ncsi_update_tx_channel()
942 if (!(np->channel_whitelist & 0x1 << nc->id)) in ncsi_update_tx_channel()
944 if (nc->state != NCSI_CHANNEL_ACTIVE) in ncsi_update_tx_channel()
954 return -1; in ncsi_update_tx_channel()
957 return -1; in ncsi_update_tx_channel()
960 nca.channel = disable->id; in ncsi_update_tx_channel()
961 nca.package = disable->package->id; in ncsi_update_tx_channel()
965 netdev_err(ndp->ndev.dev, in ncsi_update_tx_channel()
970 netdev_info(ndp->ndev.dev, "NCSI: channel %u enables Tx\n", enable->id); in ncsi_update_tx_channel()
972 nca.channel = enable->id; in ncsi_update_tx_channel()
973 nca.package = enable->package->id; in ncsi_update_tx_channel()
977 netdev_err(ndp->ndev.dev, in ncsi_update_tx_channel()
986 struct ncsi_package *np = ndp->active_package; in ncsi_configure_channel()
987 struct ncsi_channel *nc = ndp->active_channel; in ncsi_configure_channel()
989 struct ncsi_dev *nd = &ndp->ndev; in ncsi_configure_channel()
990 struct net_device *dev = nd->dev; in ncsi_configure_channel()
998 switch (nd->state) { in ncsi_configure_channel()
1001 ndp->pending_req_num = 1; in ncsi_configure_channel()
1005 if (ndp->flags & NCSI_DEV_HWA) in ncsi_configure_channel()
1009 nca.package = np->id; in ncsi_configure_channel()
1013 netdev_err(ndp->ndev.dev, in ncsi_configure_channel()
1018 nd->state = ncsi_dev_state_config_cis; in ncsi_configure_channel()
1021 ndp->pending_req_num = 1; in ncsi_configure_channel()
1023 /* Clear initial state */ in ncsi_configure_channel()
1025 nca.package = np->id; in ncsi_configure_channel()
1026 nca.channel = nc->id; in ncsi_configure_channel()
1029 netdev_err(ndp->ndev.dev, in ncsi_configure_channel()
1034 nd->state = IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC) in ncsi_configure_channel()
1039 nd->state = ncsi_dev_state_config_clear_vids; in ncsi_configure_channel()
1041 nca.package = np->id; in ncsi_configure_channel()
1042 nca.channel = nc->id; in ncsi_configure_channel()
1043 ndp->pending_req_num = 1; in ncsi_configure_channel()
1044 if (nc->version.major >= 1 && nc->version.minor >= 2) { in ncsi_configure_channel()
1049 ret = ncsi_gma_handler(&nca, nc->version.mf_id); in ncsi_configure_channel()
1052 schedule_work(&ndp->work); in ncsi_configure_channel()
1065 ndp->pending_req_num = 1; in ncsi_configure_channel()
1067 nca.package = np->id; in ncsi_configure_channel()
1068 nca.channel = nc->id; in ncsi_configure_channel()
1071 if (nd->state == ncsi_dev_state_config_clear_vids) { in ncsi_configure_channel()
1074 nd->state = ncsi_dev_state_config_svf; in ncsi_configure_channel()
1075 schedule_work(&ndp->work); in ncsi_configure_channel()
1079 nd->state = ncsi_dev_state_config_clear_vids; in ncsi_configure_channel()
1081 } else if (nd->state == ncsi_dev_state_config_svf) { in ncsi_configure_channel()
1084 nd->state = ncsi_dev_state_config_ev; in ncsi_configure_channel()
1085 schedule_work(&ndp->work); in ncsi_configure_channel()
1089 nd->state = ncsi_dev_state_config_svf; in ncsi_configure_channel()
1091 } else if (nd->state == ncsi_dev_state_config_ev) { in ncsi_configure_channel()
1092 if (list_empty(&ndp->vlan_vids)) { in ncsi_configure_channel()
1098 nd->state = ncsi_dev_state_config_sma; in ncsi_configure_channel()
1099 } else if (nd->state == ncsi_dev_state_config_sma) { in ncsi_configure_channel()
1106 nca.bytes[index] = dev->dev_addr[index]; in ncsi_configure_channel()
1109 nd->state = ncsi_dev_state_config_ebf; in ncsi_configure_channel()
1110 } else if (nd->state == ncsi_dev_state_config_ebf) { in ncsi_configure_channel()
1112 nca.dwords[0] = nc->caps[NCSI_CAP_BC].cap; in ncsi_configure_channel()
1117 if (nc->caps[NCSI_CAP_GENERIC].cap & in ncsi_configure_channel()
1119 nd->state = ncsi_dev_state_config_dgmf; in ncsi_configure_channel()
1121 nd->state = ncsi_dev_state_config_ecnt; in ncsi_configure_channel()
1123 nd->state = ncsi_dev_state_config_ec; in ncsi_configure_channel()
1124 } else if (nd->state == ncsi_dev_state_config_dgmf) { in ncsi_configure_channel()
1127 nd->state = ncsi_dev_state_config_ecnt; in ncsi_configure_channel()
1129 nd->state = ncsi_dev_state_config_ec; in ncsi_configure_channel()
1130 } else if (nd->state == ncsi_dev_state_config_ecnt) { in ncsi_configure_channel()
1131 if (np->preferred_channel && in ncsi_configure_channel()
1132 nc != np->preferred_channel) in ncsi_configure_channel()
1133 netdev_info(ndp->ndev.dev, in ncsi_configure_channel()
1135 nc->id); in ncsi_configure_channel()
1137 nd->state = ncsi_dev_state_config_ec; in ncsi_configure_channel()
1138 } else if (nd->state == ncsi_dev_state_config_ec) { in ncsi_configure_channel()
1141 nd->state = ncsi_dev_state_config_ae; in ncsi_configure_channel()
1142 if (!(nc->caps[NCSI_CAP_AEN].cap & NCSI_CAP_AEN_MASK)) in ncsi_configure_channel()
1143 nd->state = ncsi_dev_state_config_gls; in ncsi_configure_channel()
1144 } else if (nd->state == ncsi_dev_state_config_ae) { in ncsi_configure_channel()
1147 nca.dwords[1] = nc->caps[NCSI_CAP_AEN].cap; in ncsi_configure_channel()
1148 nd->state = ncsi_dev_state_config_gls; in ncsi_configure_channel()
1149 } else if (nd->state == ncsi_dev_state_config_gls) { in ncsi_configure_channel()
1151 nd->state = ncsi_dev_state_config_done; in ncsi_configure_channel()
1156 netdev_err(ndp->ndev.dev, in ncsi_configure_channel()
1163 netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n", in ncsi_configure_channel()
1164 nc->id); in ncsi_configure_channel()
1165 spin_lock_irqsave(&nc->lock, flags); in ncsi_configure_channel()
1166 nc->state = NCSI_CHANNEL_ACTIVE; in ncsi_configure_channel()
1168 if (ndp->flags & NCSI_DEV_RESET) { in ncsi_configure_channel()
1170 nc->reconfigure_needed = false; in ncsi_configure_channel()
1171 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_configure_channel()
1176 if (nc->reconfigure_needed) { in ncsi_configure_channel()
1178 * part-way during the config state - start the in ncsi_configure_channel()
1181 nc->reconfigure_needed = false; in ncsi_configure_channel()
1182 nc->state = NCSI_CHANNEL_INACTIVE; in ncsi_configure_channel()
1183 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_configure_channel()
1185 spin_lock_irqsave(&ndp->lock, flags); in ncsi_configure_channel()
1186 list_add_tail_rcu(&nc->link, &ndp->channel_queue); in ncsi_configure_channel()
1187 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_configure_channel()
1189 netdev_dbg(dev, "Dirty NCSI channel state reset\n"); in ncsi_configure_channel()
1194 if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) { in ncsi_configure_channel()
1198 netdev_dbg(ndp->ndev.dev, in ncsi_configure_channel()
1200 nc->id); in ncsi_configure_channel()
1202 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_configure_channel()
1205 spin_lock_irqsave(&ndp->lock, flags); in ncsi_configure_channel()
1206 ndp->hot_channel = hot_nc; in ncsi_configure_channel()
1207 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_configure_channel()
1213 netdev_alert(dev, "Wrong NCSI state 0x%x in config\n", in ncsi_configure_channel()
1214 nd->state); in ncsi_configure_channel()
1231 spin_lock_irqsave(&ndp->lock, flags); in ncsi_choose_active_channel()
1232 hot_nc = ndp->hot_channel; in ncsi_choose_active_channel()
1233 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_choose_active_channel()
1243 if (!(ndp->package_whitelist & (0x1 << np->id))) in ncsi_choose_active_channel()
1246 if (!(np->channel_whitelist & (0x1 << nc->id))) in ncsi_choose_active_channel()
1249 spin_lock_irqsave(&nc->lock, cflags); in ncsi_choose_active_channel()
1251 if (!list_empty(&nc->link) || in ncsi_choose_active_channel()
1252 nc->state != NCSI_CHANNEL_INACTIVE) { in ncsi_choose_active_channel()
1253 spin_unlock_irqrestore(&nc->lock, cflags); in ncsi_choose_active_channel()
1263 ncm = &nc->modes[NCSI_MODE_LINK]; in ncsi_choose_active_channel()
1264 if (ncm->data[2] & 0x1) { in ncsi_choose_active_channel()
1273 if (with_link || np->multi_channel) { in ncsi_choose_active_channel()
1274 spin_lock_irqsave(&ndp->lock, flags); in ncsi_choose_active_channel()
1275 list_add_tail_rcu(&nc->link, in ncsi_choose_active_channel()
1276 &ndp->channel_queue); in ncsi_choose_active_channel()
1277 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_choose_active_channel()
1279 netdev_dbg(ndp->ndev.dev, in ncsi_choose_active_channel()
1281 nc->id, in ncsi_choose_active_channel()
1282 ncm->data[2] & 0x1 ? "up" : "down"); in ncsi_choose_active_channel()
1285 spin_unlock_irqrestore(&nc->lock, cflags); in ncsi_choose_active_channel()
1287 if (with_link && !np->multi_channel) in ncsi_choose_active_channel()
1290 if (with_link && !ndp->multi_package) in ncsi_choose_active_channel()
1294 if (list_empty(&ndp->channel_queue) && found) { in ncsi_choose_active_channel()
1295 netdev_info(ndp->ndev.dev, in ncsi_choose_active_channel()
1297 found->id); in ncsi_choose_active_channel()
1298 spin_lock_irqsave(&ndp->lock, flags); in ncsi_choose_active_channel()
1299 list_add_tail_rcu(&found->link, &ndp->channel_queue); in ncsi_choose_active_channel()
1300 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_choose_active_channel()
1302 netdev_warn(ndp->ndev.dev, in ncsi_choose_active_channel()
1305 return -ENODEV; in ncsi_choose_active_channel()
1325 cap = nc->caps[NCSI_CAP_GENERIC].cap; in ncsi_check_hwa()
1329 ndp->flags &= ~NCSI_DEV_HWA; in ncsi_check_hwa()
1336 ndp->flags |= NCSI_DEV_HWA; in ncsi_check_hwa()
1340 ndp->flags &= ~NCSI_DEV_HWA; in ncsi_check_hwa()
1346 struct ncsi_dev *nd = &ndp->ndev; in ncsi_probe_channel()
1355 switch (nd->state) { in ncsi_probe_channel()
1357 nd->state = ncsi_dev_state_probe_deselect; in ncsi_probe_channel()
1360 ndp->pending_req_num = 8; in ncsi_probe_channel()
1372 nd->state = ncsi_dev_state_probe_package; in ncsi_probe_channel()
1375 ndp->pending_req_num = 1; in ncsi_probe_channel()
1379 nca.package = ndp->package_probe_id; in ncsi_probe_channel()
1384 nd->state = ncsi_dev_state_probe_channel; in ncsi_probe_channel()
1387 ndp->active_package = ncsi_find_package(ndp, in ncsi_probe_channel()
1388 ndp->package_probe_id); in ncsi_probe_channel()
1389 if (!ndp->active_package) { in ncsi_probe_channel()
1391 nd->state = ncsi_dev_state_probe_dp; in ncsi_probe_channel()
1392 schedule_work(&ndp->work); in ncsi_probe_channel()
1395 nd->state = ncsi_dev_state_probe_cis; in ncsi_probe_channel()
1397 ndp->mlx_multi_host) in ncsi_probe_channel()
1398 nd->state = ncsi_dev_state_probe_mlx_gma; in ncsi_probe_channel()
1400 schedule_work(&ndp->work); in ncsi_probe_channel()
1403 ndp->pending_req_num = 1; in ncsi_probe_channel()
1406 nca.package = ndp->active_package->id; in ncsi_probe_channel()
1412 nd->state = ncsi_dev_state_probe_mlx_smaf; in ncsi_probe_channel()
1415 ndp->pending_req_num = 1; in ncsi_probe_channel()
1418 nca.package = ndp->active_package->id; in ncsi_probe_channel()
1424 nd->state = ncsi_dev_state_probe_cis; in ncsi_probe_channel()
1427 ndp->pending_req_num = NCSI_RESERVED_CHANNEL; in ncsi_probe_channel()
1429 /* Clear initial state */ in ncsi_probe_channel()
1431 nca.package = ndp->active_package->id; in ncsi_probe_channel()
1439 nd->state = ncsi_dev_state_probe_gvi; in ncsi_probe_channel()
1441 nd->state = ncsi_dev_state_probe_keep_phy; in ncsi_probe_channel()
1444 ndp->pending_req_num = 1; in ncsi_probe_channel()
1447 nca.package = ndp->active_package->id; in ncsi_probe_channel()
1453 nd->state = ncsi_dev_state_probe_gvi; in ncsi_probe_channel()
1458 np = ndp->active_package; in ncsi_probe_channel()
1459 ndp->pending_req_num = np->channel_num; in ncsi_probe_channel()
1462 if (nd->state == ncsi_dev_state_probe_gvi) in ncsi_probe_channel()
1464 else if (nd->state == ncsi_dev_state_probe_gc) in ncsi_probe_channel()
1469 nca.package = np->id; in ncsi_probe_channel()
1471 nca.channel = nc->id; in ncsi_probe_channel()
1477 if (nd->state == ncsi_dev_state_probe_gvi) in ncsi_probe_channel()
1478 nd->state = ncsi_dev_state_probe_gc; in ncsi_probe_channel()
1479 else if (nd->state == ncsi_dev_state_probe_gc) in ncsi_probe_channel()
1480 nd->state = ncsi_dev_state_probe_gls; in ncsi_probe_channel()
1482 nd->state = ncsi_dev_state_probe_dp; in ncsi_probe_channel()
1485 ndp->pending_req_num = 1; in ncsi_probe_channel()
1489 nca.package = ndp->package_probe_id; in ncsi_probe_channel()
1496 ndp->package_probe_id++; in ncsi_probe_channel()
1497 if (ndp->package_probe_id >= 8) { in ncsi_probe_channel()
1499 ndp->flags |= NCSI_DEV_PROBED; in ncsi_probe_channel()
1502 nd->state = ncsi_dev_state_probe_package; in ncsi_probe_channel()
1503 ndp->active_package = NULL; in ncsi_probe_channel()
1506 netdev_warn(nd->dev, "Wrong NCSI state 0x%0x in enumeration\n", in ncsi_probe_channel()
1507 nd->state); in ncsi_probe_channel()
1510 if (ndp->flags & NCSI_DEV_PROBED) { in ncsi_probe_channel()
1518 netdev_err(ndp->ndev.dev, in ncsi_probe_channel()
1528 struct ncsi_dev *nd = &ndp->ndev; in ncsi_dev_work()
1530 switch (nd->state & ncsi_dev_state_major) { in ncsi_dev_work()
1541 netdev_warn(nd->dev, "Wrong NCSI state 0x%x in workqueue\n", in ncsi_dev_work()
1542 nd->state); in ncsi_dev_work()
1552 spin_lock_irqsave(&ndp->lock, flags); in ncsi_process_next_channel()
1553 nc = list_first_or_null_rcu(&ndp->channel_queue, in ncsi_process_next_channel()
1556 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_process_next_channel()
1560 list_del_init(&nc->link); in ncsi_process_next_channel()
1561 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_process_next_channel()
1563 spin_lock_irqsave(&nc->lock, flags); in ncsi_process_next_channel()
1564 old_state = nc->state; in ncsi_process_next_channel()
1565 nc->state = NCSI_CHANNEL_INVISIBLE; in ncsi_process_next_channel()
1566 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_process_next_channel()
1568 ndp->active_channel = nc; in ncsi_process_next_channel()
1569 ndp->active_package = nc->package; in ncsi_process_next_channel()
1573 ndp->ndev.state = ncsi_dev_state_config; in ncsi_process_next_channel()
1574 netdev_dbg(ndp->ndev.dev, "NCSI: configuring channel %u\n", in ncsi_process_next_channel()
1575 nc->id); in ncsi_process_next_channel()
1579 ndp->ndev.state = ncsi_dev_state_suspend; in ncsi_process_next_channel()
1580 netdev_dbg(ndp->ndev.dev, "NCSI: suspending channel %u\n", in ncsi_process_next_channel()
1581 nc->id); in ncsi_process_next_channel()
1585 netdev_err(ndp->ndev.dev, "Invalid state 0x%x on %d:%d\n", in ncsi_process_next_channel()
1586 old_state, nc->package->id, nc->id); in ncsi_process_next_channel()
1588 return -EINVAL; in ncsi_process_next_channel()
1594 ndp->active_channel = NULL; in ncsi_process_next_channel()
1595 ndp->active_package = NULL; in ncsi_process_next_channel()
1596 if (ndp->flags & NCSI_DEV_RESHUFFLE) { in ncsi_process_next_channel()
1597 ndp->flags &= ~NCSI_DEV_RESHUFFLE; in ncsi_process_next_channel()
1602 return -ENODEV; in ncsi_process_next_channel()
1607 struct ncsi_dev *nd = &ndp->ndev; in ncsi_kick_channels()
1615 spin_lock_irqsave(&nc->lock, flags); in ncsi_kick_channels()
1621 * c) it's ndev is in the config state in ncsi_kick_channels()
1623 if (nc->state != NCSI_CHANNEL_ACTIVE) { in ncsi_kick_channels()
1624 if ((ndp->ndev.state & 0xff00) == in ncsi_kick_channels()
1626 !list_empty(&nc->link)) { in ncsi_kick_channels()
1627 netdev_dbg(nd->dev, in ncsi_kick_channels()
1630 nc->reconfigure_needed = true; in ncsi_kick_channels()
1632 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_kick_channels()
1636 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_kick_channels()
1639 spin_lock_irqsave(&nc->lock, flags); in ncsi_kick_channels()
1640 nc->state = NCSI_CHANNEL_INACTIVE; in ncsi_kick_channels()
1641 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_kick_channels()
1643 spin_lock_irqsave(&ndp->lock, flags); in ncsi_kick_channels()
1644 list_add_tail_rcu(&nc->link, &ndp->channel_queue); in ncsi_kick_channels()
1645 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_kick_channels()
1647 netdev_dbg(nd->dev, "NCSI: kicked channel %p\n", nc); in ncsi_kick_channels()
1675 list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) { in ncsi_vlan_rx_add_vid()
1677 if (vlan->vid == vid) { in ncsi_vlan_rx_add_vid()
1687 return -ENOSPC; in ncsi_vlan_rx_add_vid()
1692 return -ENOMEM; in ncsi_vlan_rx_add_vid()
1694 vlan->proto = proto; in ncsi_vlan_rx_add_vid()
1695 vlan->vid = vid; in ncsi_vlan_rx_add_vid()
1696 list_add_rcu(&vlan->list, &ndp->vlan_vids); in ncsi_vlan_rx_add_vid()
1725 list_for_each_entry_safe(vlan, tmp, &ndp->vlan_vids, list) in ncsi_vlan_rx_kill_vid()
1726 if (vlan->vid == vid) { in ncsi_vlan_rx_kill_vid()
1728 list_del_rcu(&vlan->list); in ncsi_vlan_rx_kill_vid()
1735 return -EINVAL; in ncsi_vlan_rx_kill_vid()
1764 nd = &ndp->ndev; in ncsi_register_dev()
1765 nd->state = ncsi_dev_state_registered; in ncsi_register_dev()
1766 nd->dev = dev; in ncsi_register_dev()
1767 nd->handler = handler; in ncsi_register_dev()
1768 ndp->pending_req_num = 0; in ncsi_register_dev()
1769 INIT_LIST_HEAD(&ndp->channel_queue); in ncsi_register_dev()
1770 INIT_LIST_HEAD(&ndp->vlan_vids); in ncsi_register_dev()
1771 INIT_WORK(&ndp->work, ncsi_dev_work); in ncsi_register_dev()
1772 ndp->package_whitelist = UINT_MAX; in ncsi_register_dev()
1775 spin_lock_init(&ndp->lock); in ncsi_register_dev()
1776 INIT_LIST_HEAD(&ndp->packages); in ncsi_register_dev()
1777 ndp->request_id = NCSI_REQ_START_IDX; in ncsi_register_dev()
1778 for (i = 0; i < ARRAY_SIZE(ndp->requests); i++) { in ncsi_register_dev()
1779 ndp->requests[i].id = i; in ncsi_register_dev()
1780 ndp->requests[i].ndp = ndp; in ncsi_register_dev()
1781 timer_setup(&ndp->requests[i].timer, ncsi_request_timeout, 0); in ncsi_register_dev()
1785 list_add_tail_rcu(&ndp->node, &ncsi_dev_list); in ncsi_register_dev()
1789 ndp->ptype.type = cpu_to_be16(ETH_P_NCSI); in ncsi_register_dev()
1790 ndp->ptype.func = ncsi_rcv_rsp; in ncsi_register_dev()
1791 ndp->ptype.dev = dev; in ncsi_register_dev()
1792 dev_add_pack(&ndp->ptype); in ncsi_register_dev()
1794 pdev = to_platform_device(dev->dev.parent); in ncsi_register_dev()
1796 np = pdev->dev.of_node; in ncsi_register_dev()
1797 if (np && (of_property_read_bool(np, "mellanox,multi-host") || in ncsi_register_dev()
1798 of_property_read_bool(np, "mlx,multi-host"))) in ncsi_register_dev()
1799 ndp->mlx_multi_host = true; in ncsi_register_dev()
1810 if (nd->state != ncsi_dev_state_registered && in ncsi_start_dev()
1811 nd->state != ncsi_dev_state_functional) in ncsi_start_dev()
1812 return -ENOTTY; in ncsi_start_dev()
1814 if (!(ndp->flags & NCSI_DEV_PROBED)) { in ncsi_start_dev()
1815 ndp->package_probe_id = 0; in ncsi_start_dev()
1816 nd->state = ncsi_dev_state_probe; in ncsi_start_dev()
1817 schedule_work(&ndp->work); in ncsi_start_dev()
1835 * channel state so we know which were active when ncsi_start_dev() in ncsi_stop_dev()
1842 spin_lock_irqsave(&nc->lock, flags); in ncsi_stop_dev()
1843 chained = !list_empty(&nc->link); in ncsi_stop_dev()
1844 old_state = nc->state; in ncsi_stop_dev()
1845 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_stop_dev()
1852 netdev_dbg(ndp->ndev.dev, "NCSI: Stopping device\n"); in ncsi_stop_dev()
1864 spin_lock_irqsave(&ndp->lock, flags); in ncsi_reset_dev()
1866 if (!(ndp->flags & NCSI_DEV_RESET)) { in ncsi_reset_dev()
1868 switch (nd->state & ncsi_dev_state_major) { in ncsi_reset_dev()
1871 /* Not even probed yet - do nothing */ in ncsi_reset_dev()
1872 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_reset_dev()
1878 * NCSI_DEV_RESET and reset the state. in ncsi_reset_dev()
1880 ndp->flags |= NCSI_DEV_RESET; in ncsi_reset_dev()
1881 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_reset_dev()
1885 switch (nd->state) { in ncsi_reset_dev()
1893 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_reset_dev()
1898 if (!list_empty(&ndp->channel_queue)) { in ncsi_reset_dev()
1900 list_for_each_entry_safe(nc, tmp, &ndp->channel_queue, link) in ncsi_reset_dev()
1901 list_del_init(&nc->link); in ncsi_reset_dev()
1903 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_reset_dev()
1908 spin_lock_irqsave(&nc->lock, flags); in ncsi_reset_dev()
1910 if (nc->state == NCSI_CHANNEL_ACTIVE) { in ncsi_reset_dev()
1912 nc->state = NCSI_CHANNEL_INVISIBLE; in ncsi_reset_dev()
1913 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_reset_dev()
1918 spin_unlock_irqrestore(&nc->lock, flags); in ncsi_reset_dev()
1926 spin_lock_irqsave(&ndp->lock, flags); in ncsi_reset_dev()
1927 ndp->flags &= ~NCSI_DEV_RESET; in ncsi_reset_dev()
1928 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_reset_dev()
1932 spin_lock_irqsave(&ndp->lock, flags); in ncsi_reset_dev()
1933 ndp->flags |= NCSI_DEV_RESET; in ncsi_reset_dev()
1934 ndp->active_channel = active; in ncsi_reset_dev()
1935 ndp->active_package = active->package; in ncsi_reset_dev()
1936 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_reset_dev()
1938 nd->state = ncsi_dev_state_suspend; in ncsi_reset_dev()
1939 schedule_work(&ndp->work); in ncsi_reset_dev()
1949 dev_remove_pack(&ndp->ptype); in ncsi_unregister_dev()
1951 list_for_each_entry_safe(np, tmp, &ndp->packages, node) in ncsi_unregister_dev()
1955 list_del_rcu(&ndp->node); in ncsi_unregister_dev()