hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/net/ncsi/ncsi-manage.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright Gavin Shan, IBM Corporation 2016.
3
- *
4
- * This program is free software; you can redistribute it and/or modify
5
- * it under the terms of the GNU General Public License as published by
6
- * the Free Software Foundation; either version 2 of the License, or
7
- * (at your option) any later version.
84 */
95
106 #include <linux/module.h>
....@@ -12,13 +8,15 @@
128 #include <linux/init.h>
139 #include <linux/netdevice.h>
1410 #include <linux/skbuff.h>
11
+#include <linux/of.h>
12
+#include <linux/platform_device.h>
1513
1614 #include <net/ncsi.h>
1715 #include <net/net_namespace.h>
1816 #include <net/sock.h>
1917 #include <net/addrconf.h>
2018 #include <net/ipv6.h>
21
-#include <net/if_inet6.h>
19
+#include <net/genetlink.h>
2220
2321 #include "internal.h"
2422 #include "ncsi-pkt.h"
....@@ -26,6 +24,29 @@
2624
2725 LIST_HEAD(ncsi_dev_list);
2826 DEFINE_SPINLOCK(ncsi_dev_lock);
27
+
28
+bool ncsi_channel_has_link(struct ncsi_channel *channel)
29
+{
30
+ return !!(channel->modes[NCSI_MODE_LINK].data[2] & 0x1);
31
+}
32
+
33
+bool ncsi_channel_is_last(struct ncsi_dev_priv *ndp,
34
+ struct ncsi_channel *channel)
35
+{
36
+ struct ncsi_package *np;
37
+ struct ncsi_channel *nc;
38
+
39
+ NCSI_FOR_EACH_PACKAGE(ndp, np)
40
+ NCSI_FOR_EACH_CHANNEL(np, nc) {
41
+ if (nc == channel)
42
+ continue;
43
+ if (nc->state == NCSI_CHANNEL_ACTIVE &&
44
+ ncsi_channel_has_link(nc))
45
+ return false;
46
+ }
47
+
48
+ return true;
49
+}
2950
3051 static void ncsi_report_link(struct ncsi_dev_priv *ndp, bool force_down)
3152 {
....@@ -51,7 +72,7 @@
5172 continue;
5273 }
5374
54
- if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
75
+ if (ncsi_channel_has_link(nc)) {
5576 spin_unlock_irqrestore(&nc->lock, flags);
5677 nd->link_up = 1;
5778 goto report;
....@@ -119,10 +140,8 @@
119140 default:
120141 netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n",
121142 nc->id);
122
- if (!(ndp->flags & NCSI_DEV_HWA)) {
123
- ncsi_report_link(ndp, true);
124
- ndp->flags |= NCSI_DEV_RESHUFFLE;
125
- }
143
+ ncsi_report_link(ndp, true);
144
+ ndp->flags |= NCSI_DEV_RESHUFFLE;
126145
127146 ncm = &nc->modes[NCSI_MODE_LINK];
128147 spin_lock_irqsave(&nc->lock, flags);
....@@ -274,6 +293,7 @@
274293 np->ndp = ndp;
275294 spin_lock_init(&np->lock);
276295 INIT_LIST_HEAD(&np->channels);
296
+ np->channel_whitelist = UINT_MAX;
277297
278298 spin_lock_irqsave(&ndp->lock, flags);
279299 tmp = ncsi_find_package(ndp, id);
....@@ -412,6 +432,9 @@
412432 {
413433 struct ncsi_request *nr = from_timer(nr, t, timer);
414434 struct ncsi_dev_priv *ndp = nr->ndp;
435
+ struct ncsi_cmd_pkt *cmd;
436
+ struct ncsi_package *np;
437
+ struct ncsi_channel *nc;
415438 unsigned long flags;
416439
417440 /* If the request already had associated response,
....@@ -425,6 +448,18 @@
425448 }
426449 spin_unlock_irqrestore(&ndp->lock, flags);
427450
451
+ if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
452
+ if (nr->cmd) {
453
+ /* Find the package */
454
+ cmd = (struct ncsi_cmd_pkt *)
455
+ skb_network_header(nr->cmd);
456
+ ncsi_find_package_and_channel(ndp,
457
+ cmd->cmd.common.channel,
458
+ &np, &nc);
459
+ ncsi_send_netlink_timeout(nr, np, nc);
460
+ }
461
+ }
462
+
428463 /* Release the request */
429464 ncsi_free_request(nr);
430465 }
....@@ -432,18 +467,20 @@
432467 static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
433468 {
434469 struct ncsi_dev *nd = &ndp->ndev;
435
- struct ncsi_package *np = ndp->active_package;
436
- struct ncsi_channel *nc = ndp->active_channel;
470
+ struct ncsi_package *np;
471
+ struct ncsi_channel *nc, *tmp;
437472 struct ncsi_cmd_arg nca;
438473 unsigned long flags;
439474 int ret;
440475
476
+ np = ndp->active_package;
477
+ nc = ndp->active_channel;
441478 nca.ndp = ndp;
442479 nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN;
443480 switch (nd->state) {
444481 case ncsi_dev_state_suspend:
445482 nd->state = ncsi_dev_state_suspend_select;
446
- /* Fall through */
483
+ fallthrough;
447484 case ncsi_dev_state_suspend_select:
448485 ndp->pending_req_num = 1;
449486
....@@ -513,6 +550,15 @@
513550 if (ret)
514551 goto error;
515552
553
+ NCSI_FOR_EACH_CHANNEL(np, tmp) {
554
+ /* If there is another channel active on this package
555
+ * do not deselect the package.
556
+ */
557
+ if (tmp != nc && tmp->state == NCSI_CHANNEL_ACTIVE) {
558
+ nd->state = ncsi_dev_state_suspend_done;
559
+ break;
560
+ }
561
+ }
516562 break;
517563 case ncsi_dev_state_suspend_deselect:
518564 ndp->pending_req_num = 1;
....@@ -531,8 +577,10 @@
531577 spin_lock_irqsave(&nc->lock, flags);
532578 nc->state = NCSI_CHANNEL_INACTIVE;
533579 spin_unlock_irqrestore(&nc->lock, flags);
534
- ncsi_process_next_channel(ndp);
535
-
580
+ if (ndp->flags & NCSI_DEV_RESET)
581
+ ncsi_reset_dev(nd);
582
+ else
583
+ ncsi_process_next_channel(ndp);
536584 break;
537585 default:
538586 netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n",
....@@ -641,13 +689,261 @@
641689 return 0;
642690 }
643691
692
+#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
693
+
694
+/* NCSI OEM Command APIs */
695
+static int ncsi_oem_gma_handler_bcm(struct ncsi_cmd_arg *nca)
696
+{
697
+ unsigned char data[NCSI_OEM_BCM_CMD_GMA_LEN];
698
+ int ret = 0;
699
+
700
+ nca->payload = NCSI_OEM_BCM_CMD_GMA_LEN;
701
+
702
+ memset(data, 0, NCSI_OEM_BCM_CMD_GMA_LEN);
703
+ *(unsigned int *)data = ntohl(NCSI_OEM_MFR_BCM_ID);
704
+ data[5] = NCSI_OEM_BCM_CMD_GMA;
705
+
706
+ nca->data = data;
707
+
708
+ ret = ncsi_xmit_cmd(nca);
709
+ if (ret)
710
+ netdev_err(nca->ndp->ndev.dev,
711
+ "NCSI: Failed to transmit cmd 0x%x during configure\n",
712
+ nca->type);
713
+ return ret;
714
+}
715
+
716
+static int ncsi_oem_gma_handler_mlx(struct ncsi_cmd_arg *nca)
717
+{
718
+ union {
719
+ u8 data_u8[NCSI_OEM_MLX_CMD_GMA_LEN];
720
+ u32 data_u32[NCSI_OEM_MLX_CMD_GMA_LEN / sizeof(u32)];
721
+ } u;
722
+ int ret = 0;
723
+
724
+ nca->payload = NCSI_OEM_MLX_CMD_GMA_LEN;
725
+
726
+ memset(&u, 0, sizeof(u));
727
+ u.data_u32[0] = ntohl(NCSI_OEM_MFR_MLX_ID);
728
+ u.data_u8[5] = NCSI_OEM_MLX_CMD_GMA;
729
+ u.data_u8[6] = NCSI_OEM_MLX_CMD_GMA_PARAM;
730
+
731
+ nca->data = u.data_u8;
732
+
733
+ ret = ncsi_xmit_cmd(nca);
734
+ if (ret)
735
+ netdev_err(nca->ndp->ndev.dev,
736
+ "NCSI: Failed to transmit cmd 0x%x during configure\n",
737
+ nca->type);
738
+ return ret;
739
+}
740
+
741
+static int ncsi_oem_smaf_mlx(struct ncsi_cmd_arg *nca)
742
+{
743
+ union {
744
+ u8 data_u8[NCSI_OEM_MLX_CMD_SMAF_LEN];
745
+ u32 data_u32[NCSI_OEM_MLX_CMD_SMAF_LEN / sizeof(u32)];
746
+ } u;
747
+ int ret = 0;
748
+
749
+ memset(&u, 0, sizeof(u));
750
+ u.data_u32[0] = ntohl(NCSI_OEM_MFR_MLX_ID);
751
+ u.data_u8[5] = NCSI_OEM_MLX_CMD_SMAF;
752
+ u.data_u8[6] = NCSI_OEM_MLX_CMD_SMAF_PARAM;
753
+ memcpy(&u.data_u8[MLX_SMAF_MAC_ADDR_OFFSET],
754
+ nca->ndp->ndev.dev->dev_addr, ETH_ALEN);
755
+ u.data_u8[MLX_SMAF_MED_SUPPORT_OFFSET] =
756
+ (MLX_MC_RBT_AVL | MLX_MC_RBT_SUPPORT);
757
+
758
+ nca->payload = NCSI_OEM_MLX_CMD_SMAF_LEN;
759
+ nca->data = u.data_u8;
760
+
761
+ ret = ncsi_xmit_cmd(nca);
762
+ if (ret)
763
+ netdev_err(nca->ndp->ndev.dev,
764
+ "NCSI: Failed to transmit cmd 0x%x during probe\n",
765
+ nca->type);
766
+ return ret;
767
+}
768
+
769
+/* OEM Command handlers initialization */
770
+static struct ncsi_oem_gma_handler {
771
+ unsigned int mfr_id;
772
+ int (*handler)(struct ncsi_cmd_arg *nca);
773
+} ncsi_oem_gma_handlers[] = {
774
+ { NCSI_OEM_MFR_BCM_ID, ncsi_oem_gma_handler_bcm },
775
+ { NCSI_OEM_MFR_MLX_ID, ncsi_oem_gma_handler_mlx }
776
+};
777
+
778
+static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)
779
+{
780
+ struct ncsi_oem_gma_handler *nch = NULL;
781
+ int i;
782
+
783
+ /* This function should only be called once, return if flag set */
784
+ if (nca->ndp->gma_flag == 1)
785
+ return -1;
786
+
787
+ /* Find gma handler for given manufacturer id */
788
+ for (i = 0; i < ARRAY_SIZE(ncsi_oem_gma_handlers); i++) {
789
+ if (ncsi_oem_gma_handlers[i].mfr_id == mf_id) {
790
+ if (ncsi_oem_gma_handlers[i].handler)
791
+ nch = &ncsi_oem_gma_handlers[i];
792
+ break;
793
+ }
794
+ }
795
+
796
+ if (!nch) {
797
+ netdev_err(nca->ndp->ndev.dev,
798
+ "NCSI: No GMA handler available for MFR-ID (0x%x)\n",
799
+ mf_id);
800
+ return -1;
801
+ }
802
+
803
+ /* Get Mac address from NCSI device */
804
+ return nch->handler(nca);
805
+}
806
+
807
+#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
808
+
809
+/* Determine if a given channel from the channel_queue should be used for Tx */
810
+static bool ncsi_channel_is_tx(struct ncsi_dev_priv *ndp,
811
+ struct ncsi_channel *nc)
812
+{
813
+ struct ncsi_channel_mode *ncm;
814
+ struct ncsi_channel *channel;
815
+ struct ncsi_package *np;
816
+
817
+ /* Check if any other channel has Tx enabled; a channel may have already
818
+ * been configured and removed from the channel queue.
819
+ */
820
+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
821
+ if (!ndp->multi_package && np != nc->package)
822
+ continue;
823
+ NCSI_FOR_EACH_CHANNEL(np, channel) {
824
+ ncm = &channel->modes[NCSI_MODE_TX_ENABLE];
825
+ if (ncm->enable)
826
+ return false;
827
+ }
828
+ }
829
+
830
+ /* This channel is the preferred channel and has link */
831
+ list_for_each_entry_rcu(channel, &ndp->channel_queue, link) {
832
+ np = channel->package;
833
+ if (np->preferred_channel &&
834
+ ncsi_channel_has_link(np->preferred_channel)) {
835
+ return np->preferred_channel == nc;
836
+ }
837
+ }
838
+
839
+ /* This channel has link */
840
+ if (ncsi_channel_has_link(nc))
841
+ return true;
842
+
843
+ list_for_each_entry_rcu(channel, &ndp->channel_queue, link)
844
+ if (ncsi_channel_has_link(channel))
845
+ return false;
846
+
847
+ /* No other channel has link; default to this one */
848
+ return true;
849
+}
850
+
851
+/* Change the active Tx channel in a multi-channel setup */
852
+int ncsi_update_tx_channel(struct ncsi_dev_priv *ndp,
853
+ struct ncsi_package *package,
854
+ struct ncsi_channel *disable,
855
+ struct ncsi_channel *enable)
856
+{
857
+ struct ncsi_cmd_arg nca;
858
+ struct ncsi_channel *nc;
859
+ struct ncsi_package *np;
860
+ int ret = 0;
861
+
862
+ if (!package->multi_channel && !ndp->multi_package)
863
+ netdev_warn(ndp->ndev.dev,
864
+ "NCSI: Trying to update Tx channel in single-channel mode\n");
865
+ nca.ndp = ndp;
866
+ nca.req_flags = 0;
867
+
868
+ /* Find current channel with Tx enabled */
869
+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
870
+ if (disable)
871
+ break;
872
+ if (!ndp->multi_package && np != package)
873
+ continue;
874
+
875
+ NCSI_FOR_EACH_CHANNEL(np, nc)
876
+ if (nc->modes[NCSI_MODE_TX_ENABLE].enable) {
877
+ disable = nc;
878
+ break;
879
+ }
880
+ }
881
+
882
+ /* Find a suitable channel for Tx */
883
+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
884
+ if (enable)
885
+ break;
886
+ if (!ndp->multi_package && np != package)
887
+ continue;
888
+ if (!(ndp->package_whitelist & (0x1 << np->id)))
889
+ continue;
890
+
891
+ if (np->preferred_channel &&
892
+ ncsi_channel_has_link(np->preferred_channel)) {
893
+ enable = np->preferred_channel;
894
+ break;
895
+ }
896
+
897
+ NCSI_FOR_EACH_CHANNEL(np, nc) {
898
+ if (!(np->channel_whitelist & 0x1 << nc->id))
899
+ continue;
900
+ if (nc->state != NCSI_CHANNEL_ACTIVE)
901
+ continue;
902
+ if (ncsi_channel_has_link(nc)) {
903
+ enable = nc;
904
+ break;
905
+ }
906
+ }
907
+ }
908
+
909
+ if (disable == enable)
910
+ return -1;
911
+
912
+ if (!enable)
913
+ return -1;
914
+
915
+ if (disable) {
916
+ nca.channel = disable->id;
917
+ nca.package = disable->package->id;
918
+ nca.type = NCSI_PKT_CMD_DCNT;
919
+ ret = ncsi_xmit_cmd(&nca);
920
+ if (ret)
921
+ netdev_err(ndp->ndev.dev,
922
+ "Error %d sending DCNT\n",
923
+ ret);
924
+ }
925
+
926
+ netdev_info(ndp->ndev.dev, "NCSI: channel %u enables Tx\n", enable->id);
927
+
928
+ nca.channel = enable->id;
929
+ nca.package = enable->package->id;
930
+ nca.type = NCSI_PKT_CMD_ECNT;
931
+ ret = ncsi_xmit_cmd(&nca);
932
+ if (ret)
933
+ netdev_err(ndp->ndev.dev,
934
+ "Error %d sending ECNT\n",
935
+ ret);
936
+
937
+ return ret;
938
+}
939
+
644940 static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
645941 {
646
- struct ncsi_dev *nd = &ndp->ndev;
647
- struct net_device *dev = nd->dev;
648942 struct ncsi_package *np = ndp->active_package;
649943 struct ncsi_channel *nc = ndp->active_channel;
650944 struct ncsi_channel *hot_nc = NULL;
945
+ struct ncsi_dev *nd = &ndp->ndev;
946
+ struct net_device *dev = nd->dev;
651947 struct ncsi_cmd_arg nca;
652948 unsigned char index;
653949 unsigned long flags;
....@@ -691,16 +987,30 @@
691987 goto error;
692988 }
693989
990
+ nd->state = ncsi_dev_state_config_oem_gma;
991
+ break;
992
+ case ncsi_dev_state_config_oem_gma:
694993 nd->state = ncsi_dev_state_config_clear_vids;
994
+ ret = -1;
995
+
996
+#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
997
+ nca.type = NCSI_PKT_CMD_OEM;
998
+ nca.package = np->id;
999
+ nca.channel = nc->id;
1000
+ ndp->pending_req_num = 1;
1001
+ ret = ncsi_gma_handler(&nca, nc->version.mf_id);
1002
+#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
1003
+
1004
+ if (ret < 0)
1005
+ schedule_work(&ndp->work);
1006
+
6951007 break;
6961008 case ncsi_dev_state_config_clear_vids:
6971009 case ncsi_dev_state_config_svf:
6981010 case ncsi_dev_state_config_ev:
6991011 case ncsi_dev_state_config_sma:
7001012 case ncsi_dev_state_config_ebf:
701
-#if IS_ENABLED(CONFIG_IPV6)
702
- case ncsi_dev_state_config_egmf:
703
-#endif
1013
+ case ncsi_dev_state_config_dgmf:
7041014 case ncsi_dev_state_config_ecnt:
7051015 case ncsi_dev_state_config_ec:
7061016 case ncsi_dev_state_config_ae:
....@@ -753,20 +1063,29 @@
7531063 } else if (nd->state == ncsi_dev_state_config_ebf) {
7541064 nca.type = NCSI_PKT_CMD_EBF;
7551065 nca.dwords[0] = nc->caps[NCSI_CAP_BC].cap;
756
- nd->state = ncsi_dev_state_config_ecnt;
757
-#if IS_ENABLED(CONFIG_IPV6)
758
- if (ndp->inet6_addr_num > 0 &&
759
- (nc->caps[NCSI_CAP_GENERIC].cap &
760
- NCSI_CAP_GENERIC_MC))
761
- nd->state = ncsi_dev_state_config_egmf;
762
- else
1066
+ /* if multicast global filtering is supported then
1067
+ * disable it so that all multicast packet will be
1068
+ * forwarded to management controller
1069
+ */
1070
+ if (nc->caps[NCSI_CAP_GENERIC].cap &
1071
+ NCSI_CAP_GENERIC_MC)
1072
+ nd->state = ncsi_dev_state_config_dgmf;
1073
+ else if (ncsi_channel_is_tx(ndp, nc))
7631074 nd->state = ncsi_dev_state_config_ecnt;
764
- } else if (nd->state == ncsi_dev_state_config_egmf) {
765
- nca.type = NCSI_PKT_CMD_EGMF;
766
- nca.dwords[0] = nc->caps[NCSI_CAP_MC].cap;
767
- nd->state = ncsi_dev_state_config_ecnt;
768
-#endif /* CONFIG_IPV6 */
1075
+ else
1076
+ nd->state = ncsi_dev_state_config_ec;
1077
+ } else if (nd->state == ncsi_dev_state_config_dgmf) {
1078
+ nca.type = NCSI_PKT_CMD_DGMF;
1079
+ if (ncsi_channel_is_tx(ndp, nc))
1080
+ nd->state = ncsi_dev_state_config_ecnt;
1081
+ else
1082
+ nd->state = ncsi_dev_state_config_ec;
7691083 } else if (nd->state == ncsi_dev_state_config_ecnt) {
1084
+ if (np->preferred_channel &&
1085
+ nc != np->preferred_channel)
1086
+ netdev_info(ndp->ndev.dev,
1087
+ "NCSI: Tx failed over to channel %u\n",
1088
+ nc->id);
7701089 nca.type = NCSI_PKT_CMD_ECNT;
7711090 nd->state = ncsi_dev_state_config_ec;
7721091 } else if (nd->state == ncsi_dev_state_config_ec) {
....@@ -797,6 +1116,16 @@
7971116 netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n",
7981117 nc->id);
7991118 spin_lock_irqsave(&nc->lock, flags);
1119
+ nc->state = NCSI_CHANNEL_ACTIVE;
1120
+
1121
+ if (ndp->flags & NCSI_DEV_RESET) {
1122
+ /* A reset event happened during config, start it now */
1123
+ nc->reconfigure_needed = false;
1124
+ spin_unlock_irqrestore(&nc->lock, flags);
1125
+ ncsi_reset_dev(nd);
1126
+ break;
1127
+ }
1128
+
8001129 if (nc->reconfigure_needed) {
8011130 /* This channel's configuration has been updated
8021131 * part-way during the config state - start the
....@@ -817,10 +1146,8 @@
8171146
8181147 if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
8191148 hot_nc = nc;
820
- nc->state = NCSI_CHANNEL_ACTIVE;
8211149 } else {
8221150 hot_nc = NULL;
823
- nc->state = NCSI_CHANNEL_INACTIVE;
8241151 netdev_dbg(ndp->ndev.dev,
8251152 "NCSI: channel %u link down after config\n",
8261153 nc->id);
....@@ -848,43 +1175,35 @@
8481175
8491176 static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
8501177 {
851
- struct ncsi_package *np, *force_package;
852
- struct ncsi_channel *nc, *found, *hot_nc, *force_channel;
1178
+ struct ncsi_channel *nc, *found, *hot_nc;
8531179 struct ncsi_channel_mode *ncm;
854
- unsigned long flags;
1180
+ unsigned long flags, cflags;
1181
+ struct ncsi_package *np;
1182
+ bool with_link;
8551183
8561184 spin_lock_irqsave(&ndp->lock, flags);
8571185 hot_nc = ndp->hot_channel;
858
- force_channel = ndp->force_channel;
859
- force_package = ndp->force_package;
8601186 spin_unlock_irqrestore(&ndp->lock, flags);
8611187
862
- /* Force a specific channel whether or not it has link if we have been
863
- * configured to do so
864
- */
865
- if (force_package && force_channel) {
866
- found = force_channel;
867
- ncm = &found->modes[NCSI_MODE_LINK];
868
- if (!(ncm->data[2] & 0x1))
869
- netdev_info(ndp->ndev.dev,
870
- "NCSI: Channel %u forced, but it is link down\n",
871
- found->id);
872
- goto out;
873
- }
874
-
875
- /* The search is done once an inactive channel with up
876
- * link is found.
1188
+ /* By default the search is done once an inactive channel with up
1189
+ * link is found, unless a preferred channel is set.
1190
+ * If multi_package or multi_channel are configured all channels in the
1191
+ * whitelist are added to the channel queue.
8771192 */
8781193 found = NULL;
1194
+ with_link = false;
8791195 NCSI_FOR_EACH_PACKAGE(ndp, np) {
880
- if (ndp->force_package && np != ndp->force_package)
1196
+ if (!(ndp->package_whitelist & (0x1 << np->id)))
8811197 continue;
8821198 NCSI_FOR_EACH_CHANNEL(np, nc) {
883
- spin_lock_irqsave(&nc->lock, flags);
1199
+ if (!(np->channel_whitelist & (0x1 << nc->id)))
1200
+ continue;
1201
+
1202
+ spin_lock_irqsave(&nc->lock, cflags);
8841203
8851204 if (!list_empty(&nc->link) ||
8861205 nc->state != NCSI_CHANNEL_INACTIVE) {
887
- spin_unlock_irqrestore(&nc->lock, flags);
1206
+ spin_unlock_irqrestore(&nc->lock, cflags);
8881207 continue;
8891208 }
8901209
....@@ -896,31 +1215,48 @@
8961215
8971216 ncm = &nc->modes[NCSI_MODE_LINK];
8981217 if (ncm->data[2] & 0x1) {
899
- spin_unlock_irqrestore(&nc->lock, flags);
9001218 found = nc;
901
- goto out;
1219
+ with_link = true;
9021220 }
9031221
904
- spin_unlock_irqrestore(&nc->lock, flags);
1222
+ /* If multi_channel is enabled configure all valid
1223
+ * channels whether or not they currently have link
1224
+ * so they will have AENs enabled.
1225
+ */
1226
+ if (with_link || np->multi_channel) {
1227
+ spin_lock_irqsave(&ndp->lock, flags);
1228
+ list_add_tail_rcu(&nc->link,
1229
+ &ndp->channel_queue);
1230
+ spin_unlock_irqrestore(&ndp->lock, flags);
1231
+
1232
+ netdev_dbg(ndp->ndev.dev,
1233
+ "NCSI: Channel %u added to queue (link %s)\n",
1234
+ nc->id,
1235
+ ncm->data[2] & 0x1 ? "up" : "down");
1236
+ }
1237
+
1238
+ spin_unlock_irqrestore(&nc->lock, cflags);
1239
+
1240
+ if (with_link && !np->multi_channel)
1241
+ break;
9051242 }
1243
+ if (with_link && !ndp->multi_package)
1244
+ break;
9061245 }
9071246
908
- if (!found) {
1247
+ if (list_empty(&ndp->channel_queue) && found) {
1248
+ netdev_info(ndp->ndev.dev,
1249
+ "NCSI: No channel with link found, configuring channel %u\n",
1250
+ found->id);
1251
+ spin_lock_irqsave(&ndp->lock, flags);
1252
+ list_add_tail_rcu(&found->link, &ndp->channel_queue);
1253
+ spin_unlock_irqrestore(&ndp->lock, flags);
1254
+ } else if (!found) {
9091255 netdev_warn(ndp->ndev.dev,
910
- "NCSI: No channel found with link\n");
1256
+ "NCSI: No channel found to configure!\n");
9111257 ncsi_report_link(ndp, true);
9121258 return -ENODEV;
9131259 }
914
-
915
- ncm = &found->modes[NCSI_MODE_LINK];
916
- netdev_dbg(ndp->ndev.dev,
917
- "NCSI: Channel %u added to queue (link %s)\n",
918
- found->id, ncm->data[2] & 0x1 ? "up" : "down");
919
-
920
-out:
921
- spin_lock_irqsave(&ndp->lock, flags);
922
- list_add_tail_rcu(&found->link, &ndp->channel_queue);
923
- spin_unlock_irqrestore(&ndp->lock, flags);
9241260
9251261 return ncsi_process_next_channel(ndp);
9261262 }
....@@ -958,35 +1294,6 @@
9581294 return false;
9591295 }
9601296
961
-static int ncsi_enable_hwa(struct ncsi_dev_priv *ndp)
962
-{
963
- struct ncsi_package *np;
964
- struct ncsi_channel *nc;
965
- unsigned long flags;
966
-
967
- /* Move all available channels to processing queue */
968
- spin_lock_irqsave(&ndp->lock, flags);
969
- NCSI_FOR_EACH_PACKAGE(ndp, np) {
970
- NCSI_FOR_EACH_CHANNEL(np, nc) {
971
- WARN_ON_ONCE(nc->state != NCSI_CHANNEL_INACTIVE ||
972
- !list_empty(&nc->link));
973
- ncsi_stop_channel_monitor(nc);
974
- list_add_tail_rcu(&nc->link, &ndp->channel_queue);
975
- }
976
- }
977
- spin_unlock_irqrestore(&ndp->lock, flags);
978
-
979
- /* We can have no channels in extremely case */
980
- if (list_empty(&ndp->channel_queue)) {
981
- netdev_err(ndp->ndev.dev,
982
- "NCSI: No available channels for HWA\n");
983
- ncsi_report_link(ndp, false);
984
- return -ENOENT;
985
- }
986
-
987
- return ncsi_process_next_channel(ndp);
988
-}
989
-
9901297 static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
9911298 {
9921299 struct ncsi_dev *nd = &ndp->ndev;
....@@ -1001,7 +1308,7 @@
10011308 switch (nd->state) {
10021309 case ncsi_dev_state_probe:
10031310 nd->state = ncsi_dev_state_probe_deselect;
1004
- /* Fall through */
1311
+ fallthrough;
10051312 case ncsi_dev_state_probe_deselect:
10061313 ndp->pending_req_num = 8;
10071314
....@@ -1018,71 +1325,59 @@
10181325 nd->state = ncsi_dev_state_probe_package;
10191326 break;
10201327 case ncsi_dev_state_probe_package:
1021
- ndp->pending_req_num = 16;
1328
+ ndp->pending_req_num = 1;
10221329
1023
- /* Select all possible packages */
10241330 nca.type = NCSI_PKT_CMD_SP;
10251331 nca.bytes[0] = 1;
1332
+ nca.package = ndp->package_probe_id;
10261333 nca.channel = NCSI_RESERVED_CHANNEL;
1027
- for (index = 0; index < 8; index++) {
1028
- nca.package = index;
1029
- ret = ncsi_xmit_cmd(&nca);
1030
- if (ret)
1031
- goto error;
1032
- }
1033
-
1034
- /* Disable all possible packages */
1035
- nca.type = NCSI_PKT_CMD_DP;
1036
- for (index = 0; index < 8; index++) {
1037
- nca.package = index;
1038
- ret = ncsi_xmit_cmd(&nca);
1039
- if (ret)
1040
- goto error;
1041
- }
1042
-
1334
+ ret = ncsi_xmit_cmd(&nca);
1335
+ if (ret)
1336
+ goto error;
10431337 nd->state = ncsi_dev_state_probe_channel;
10441338 break;
10451339 case ncsi_dev_state_probe_channel:
1046
- if (!ndp->active_package)
1047
- ndp->active_package = list_first_or_null_rcu(
1048
- &ndp->packages, struct ncsi_package, node);
1049
- else if (list_is_last(&ndp->active_package->node,
1050
- &ndp->packages))
1051
- ndp->active_package = NULL;
1052
- else
1053
- ndp->active_package = list_next_entry(
1054
- ndp->active_package, node);
1055
-
1056
- /* All available packages and channels are enumerated. The
1057
- * enumeration happens for once when the NCSI interface is
1058
- * started. So we need continue to start the interface after
1059
- * the enumeration.
1060
- *
1061
- * We have to choose an active channel before configuring it.
1062
- * Note that we possibly don't have active channel in extreme
1063
- * situation.
1064
- */
1340
+ ndp->active_package = ncsi_find_package(ndp,
1341
+ ndp->package_probe_id);
10651342 if (!ndp->active_package) {
1066
- ndp->flags |= NCSI_DEV_PROBED;
1067
- if (ncsi_check_hwa(ndp))
1068
- ncsi_enable_hwa(ndp);
1069
- else
1070
- ncsi_choose_active_channel(ndp);
1071
- return;
1343
+ /* No response */
1344
+ nd->state = ncsi_dev_state_probe_dp;
1345
+ schedule_work(&ndp->work);
1346
+ break;
10721347 }
1348
+ nd->state = ncsi_dev_state_probe_cis;
1349
+ if (IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC) &&
1350
+ ndp->mlx_multi_host)
1351
+ nd->state = ncsi_dev_state_probe_mlx_gma;
10731352
1074
- /* Select the active package */
1353
+ schedule_work(&ndp->work);
1354
+ break;
1355
+#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
1356
+ case ncsi_dev_state_probe_mlx_gma:
10751357 ndp->pending_req_num = 1;
1076
- nca.type = NCSI_PKT_CMD_SP;
1077
- nca.bytes[0] = 1;
1358
+
1359
+ nca.type = NCSI_PKT_CMD_OEM;
10781360 nca.package = ndp->active_package->id;
1079
- nca.channel = NCSI_RESERVED_CHANNEL;
1080
- ret = ncsi_xmit_cmd(&nca);
1361
+ nca.channel = 0;
1362
+ ret = ncsi_oem_gma_handler_mlx(&nca);
1363
+ if (ret)
1364
+ goto error;
1365
+
1366
+ nd->state = ncsi_dev_state_probe_mlx_smaf;
1367
+ break;
1368
+ case ncsi_dev_state_probe_mlx_smaf:
1369
+ ndp->pending_req_num = 1;
1370
+
1371
+ nca.type = NCSI_PKT_CMD_OEM;
1372
+ nca.package = ndp->active_package->id;
1373
+ nca.channel = 0;
1374
+ ret = ncsi_oem_smaf_mlx(&nca);
10811375 if (ret)
10821376 goto error;
10831377
10841378 nd->state = ncsi_dev_state_probe_cis;
10851379 break;
1380
+#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
10861381 case ncsi_dev_state_probe_cis:
10871382 ndp->pending_req_num = NCSI_RESERVED_CHANNEL;
10881383
....@@ -1130,20 +1425,33 @@
11301425 case ncsi_dev_state_probe_dp:
11311426 ndp->pending_req_num = 1;
11321427
1133
- /* Deselect the active package */
1428
+ /* Deselect the current package */
11341429 nca.type = NCSI_PKT_CMD_DP;
1135
- nca.package = ndp->active_package->id;
1430
+ nca.package = ndp->package_probe_id;
11361431 nca.channel = NCSI_RESERVED_CHANNEL;
11371432 ret = ncsi_xmit_cmd(&nca);
11381433 if (ret)
11391434 goto error;
11401435
1141
- /* Scan channels in next package */
1142
- nd->state = ncsi_dev_state_probe_channel;
1436
+ /* Probe next package */
1437
+ ndp->package_probe_id++;
1438
+ if (ndp->package_probe_id >= 8) {
1439
+ /* Probe finished */
1440
+ ndp->flags |= NCSI_DEV_PROBED;
1441
+ break;
1442
+ }
1443
+ nd->state = ncsi_dev_state_probe_package;
1444
+ ndp->active_package = NULL;
11431445 break;
11441446 default:
11451447 netdev_warn(nd->dev, "Wrong NCSI state 0x%0x in enumeration\n",
11461448 nd->state);
1449
+ }
1450
+
1451
+ if (ndp->flags & NCSI_DEV_PROBED) {
1452
+ /* Check if all packages have HWA support */
1453
+ ncsi_check_hwa(ndp);
1454
+ ncsi_choose_active_channel(ndp);
11471455 }
11481456
11491457 return;
....@@ -1234,70 +1542,6 @@
12341542 ncsi_report_link(ndp, false);
12351543 return -ENODEV;
12361544 }
1237
-
1238
-#if IS_ENABLED(CONFIG_IPV6)
1239
-static int ncsi_inet6addr_event(struct notifier_block *this,
1240
- unsigned long event, void *data)
1241
-{
1242
- struct inet6_ifaddr *ifa = data;
1243
- struct net_device *dev = ifa->idev->dev;
1244
- struct ncsi_dev *nd = ncsi_find_dev(dev);
1245
- struct ncsi_dev_priv *ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
1246
- struct ncsi_package *np;
1247
- struct ncsi_channel *nc;
1248
- struct ncsi_cmd_arg nca;
1249
- bool action;
1250
- int ret;
1251
-
1252
- if (!ndp || (ipv6_addr_type(&ifa->addr) &
1253
- (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK)))
1254
- return NOTIFY_OK;
1255
-
1256
- switch (event) {
1257
- case NETDEV_UP:
1258
- action = (++ndp->inet6_addr_num) == 1;
1259
- nca.type = NCSI_PKT_CMD_EGMF;
1260
- break;
1261
- case NETDEV_DOWN:
1262
- action = (--ndp->inet6_addr_num == 0);
1263
- nca.type = NCSI_PKT_CMD_DGMF;
1264
- break;
1265
- default:
1266
- return NOTIFY_OK;
1267
- }
1268
-
1269
- /* We might not have active channel or packages. The IPv6
1270
- * required multicast will be enabled when active channel
1271
- * or packages are chosen.
1272
- */
1273
- np = ndp->active_package;
1274
- nc = ndp->active_channel;
1275
- if (!action || !np || !nc)
1276
- return NOTIFY_OK;
1277
-
1278
- /* We needn't enable or disable it if the function isn't supported */
1279
- if (!(nc->caps[NCSI_CAP_GENERIC].cap & NCSI_CAP_GENERIC_MC))
1280
- return NOTIFY_OK;
1281
-
1282
- nca.ndp = ndp;
1283
- nca.req_flags = 0;
1284
- nca.package = np->id;
1285
- nca.channel = nc->id;
1286
- nca.dwords[0] = nc->caps[NCSI_CAP_MC].cap;
1287
- ret = ncsi_xmit_cmd(&nca);
1288
- if (ret) {
1289
- netdev_warn(dev, "Fail to %s global multicast filter (%d)\n",
1290
- (event == NETDEV_UP) ? "enable" : "disable", ret);
1291
- return NOTIFY_DONE;
1292
- }
1293
-
1294
- return NOTIFY_OK;
1295
-}
1296
-
1297
-static struct notifier_block ncsi_inet6addr_notifier = {
1298
- .notifier_call = ncsi_inet6addr_event,
1299
-};
1300
-#endif /* CONFIG_IPV6 */
13011545
13021546 static int ncsi_kick_channels(struct ncsi_dev_priv *ndp)
13031547 {
....@@ -1443,6 +1687,8 @@
14431687 {
14441688 struct ncsi_dev_priv *ndp;
14451689 struct ncsi_dev *nd;
1690
+ struct platform_device *pdev;
1691
+ struct device_node *np;
14461692 unsigned long flags;
14471693 int i;
14481694
....@@ -1464,6 +1710,7 @@
14641710 INIT_LIST_HEAD(&ndp->channel_queue);
14651711 INIT_LIST_HEAD(&ndp->vlan_vids);
14661712 INIT_WORK(&ndp->work, ncsi_dev_work);
1713
+ ndp->package_whitelist = UINT_MAX;
14671714
14681715 /* Initialize private NCSI device */
14691716 spin_lock_init(&ndp->lock);
....@@ -1476,11 +1723,6 @@
14761723 }
14771724
14781725 spin_lock_irqsave(&ncsi_dev_lock, flags);
1479
-#if IS_ENABLED(CONFIG_IPV6)
1480
- ndp->inet6_addr_num = 0;
1481
- if (list_empty(&ncsi_dev_list))
1482
- register_inet6addr_notifier(&ncsi_inet6addr_notifier);
1483
-#endif
14841726 list_add_tail_rcu(&ndp->node, &ncsi_dev_list);
14851727 spin_unlock_irqrestore(&ncsi_dev_lock, flags);
14861728
....@@ -1490,6 +1732,13 @@
14901732 ndp->ptype.dev = dev;
14911733 dev_add_pack(&ndp->ptype);
14921734
1735
+ pdev = to_platform_device(dev->dev.parent);
1736
+ if (pdev) {
1737
+ np = pdev->dev.of_node;
1738
+ if (np && of_get_property(np, "mlx,multi-host", NULL))
1739
+ ndp->mlx_multi_host = true;
1740
+ }
1741
+
14931742 return nd;
14941743 }
14951744 EXPORT_SYMBOL_GPL(ncsi_register_dev);
....@@ -1497,26 +1746,19 @@
14971746 int ncsi_start_dev(struct ncsi_dev *nd)
14981747 {
14991748 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
1500
- int ret;
15011749
15021750 if (nd->state != ncsi_dev_state_registered &&
15031751 nd->state != ncsi_dev_state_functional)
15041752 return -ENOTTY;
15051753
15061754 if (!(ndp->flags & NCSI_DEV_PROBED)) {
1755
+ ndp->package_probe_id = 0;
15071756 nd->state = ncsi_dev_state_probe;
15081757 schedule_work(&ndp->work);
15091758 return 0;
15101759 }
15111760
1512
- if (ndp->flags & NCSI_DEV_HWA) {
1513
- netdev_info(ndp->ndev.dev, "NCSI: Enabling HWA mode\n");
1514
- ret = ncsi_enable_hwa(ndp);
1515
- } else {
1516
- ret = ncsi_choose_active_channel(ndp);
1517
- }
1518
-
1519
- return ret;
1761
+ return ncsi_reset_dev(nd);
15201762 }
15211763 EXPORT_SYMBOL_GPL(ncsi_start_dev);
15221764
....@@ -1529,7 +1771,10 @@
15291771 int old_state;
15301772 unsigned long flags;
15311773
1532
- /* Stop the channel monitor and reset channel's state */
1774
+ /* Stop the channel monitor on any active channels. Don't reset the
1775
+ * channel state so we know which were active when ncsi_start_dev()
1776
+ * is next called.
1777
+ */
15331778 NCSI_FOR_EACH_PACKAGE(ndp, np) {
15341779 NCSI_FOR_EACH_CHANNEL(np, nc) {
15351780 ncsi_stop_channel_monitor(nc);
....@@ -1537,7 +1782,6 @@
15371782 spin_lock_irqsave(&nc->lock, flags);
15381783 chained = !list_empty(&nc->link);
15391784 old_state = nc->state;
1540
- nc->state = NCSI_CHANNEL_INACTIVE;
15411785 spin_unlock_irqrestore(&nc->lock, flags);
15421786
15431787 WARN_ON_ONCE(chained ||
....@@ -1549,6 +1793,92 @@
15491793 ncsi_report_link(ndp, true);
15501794 }
15511795 EXPORT_SYMBOL_GPL(ncsi_stop_dev);
1796
+
1797
+int ncsi_reset_dev(struct ncsi_dev *nd)
1798
+{
1799
+ struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
1800
+ struct ncsi_channel *nc, *active, *tmp;
1801
+ struct ncsi_package *np;
1802
+ unsigned long flags;
1803
+
1804
+ spin_lock_irqsave(&ndp->lock, flags);
1805
+
1806
+ if (!(ndp->flags & NCSI_DEV_RESET)) {
1807
+ /* Haven't been called yet, check states */
1808
+ switch (nd->state & ncsi_dev_state_major) {
1809
+ case ncsi_dev_state_registered:
1810
+ case ncsi_dev_state_probe:
1811
+ /* Not even probed yet - do nothing */
1812
+ spin_unlock_irqrestore(&ndp->lock, flags);
1813
+ return 0;
1814
+ case ncsi_dev_state_suspend:
1815
+ case ncsi_dev_state_config:
1816
+ /* Wait for the channel to finish its suspend/config
1817
+ * operation; once it finishes it will check for
1818
+ * NCSI_DEV_RESET and reset the state.
1819
+ */
1820
+ ndp->flags |= NCSI_DEV_RESET;
1821
+ spin_unlock_irqrestore(&ndp->lock, flags);
1822
+ return 0;
1823
+ }
1824
+ } else {
1825
+ switch (nd->state) {
1826
+ case ncsi_dev_state_suspend_done:
1827
+ case ncsi_dev_state_config_done:
1828
+ case ncsi_dev_state_functional:
1829
+ /* Ok */
1830
+ break;
1831
+ default:
1832
+ /* Current reset operation happening */
1833
+ spin_unlock_irqrestore(&ndp->lock, flags);
1834
+ return 0;
1835
+ }
1836
+ }
1837
+
1838
+ if (!list_empty(&ndp->channel_queue)) {
1839
+ /* Clear any channel queue we may have interrupted */
1840
+ list_for_each_entry_safe(nc, tmp, &ndp->channel_queue, link)
1841
+ list_del_init(&nc->link);
1842
+ }
1843
+ spin_unlock_irqrestore(&ndp->lock, flags);
1844
+
1845
+ active = NULL;
1846
+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
1847
+ NCSI_FOR_EACH_CHANNEL(np, nc) {
1848
+ spin_lock_irqsave(&nc->lock, flags);
1849
+
1850
+ if (nc->state == NCSI_CHANNEL_ACTIVE) {
1851
+ active = nc;
1852
+ nc->state = NCSI_CHANNEL_INVISIBLE;
1853
+ spin_unlock_irqrestore(&nc->lock, flags);
1854
+ ncsi_stop_channel_monitor(nc);
1855
+ break;
1856
+ }
1857
+
1858
+ spin_unlock_irqrestore(&nc->lock, flags);
1859
+ }
1860
+ if (active)
1861
+ break;
1862
+ }
1863
+
1864
+ if (!active) {
1865
+ /* Done */
1866
+ spin_lock_irqsave(&ndp->lock, flags);
1867
+ ndp->flags &= ~NCSI_DEV_RESET;
1868
+ spin_unlock_irqrestore(&ndp->lock, flags);
1869
+ return ncsi_choose_active_channel(ndp);
1870
+ }
1871
+
1872
+ spin_lock_irqsave(&ndp->lock, flags);
1873
+ ndp->flags |= NCSI_DEV_RESET;
1874
+ ndp->active_channel = active;
1875
+ ndp->active_package = active->package;
1876
+ spin_unlock_irqrestore(&ndp->lock, flags);
1877
+
1878
+ nd->state = ncsi_dev_state_suspend;
1879
+ schedule_work(&ndp->work);
1880
+ return 0;
1881
+}
15521882
15531883 void ncsi_unregister_dev(struct ncsi_dev *nd)
15541884 {
....@@ -1563,10 +1893,6 @@
15631893
15641894 spin_lock_irqsave(&ncsi_dev_lock, flags);
15651895 list_del_rcu(&ndp->node);
1566
-#if IS_ENABLED(CONFIG_IPV6)
1567
- if (list_empty(&ncsi_dev_list))
1568
- unregister_inet6addr_notifier(&ncsi_inet6addr_notifier);
1569
-#endif
15701896 spin_unlock_irqrestore(&ncsi_dev_lock, flags);
15711897
15721898 kfree(ndp);