forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/net/ncsi/ncsi-aen.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>
....@@ -50,13 +46,15 @@
5046 static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
5147 struct ncsi_aen_pkt_hdr *h)
5248 {
53
- struct ncsi_aen_lsc_pkt *lsc;
54
- struct ncsi_channel *nc;
49
+ struct ncsi_channel *nc, *tmp;
5550 struct ncsi_channel_mode *ncm;
51
+ unsigned long old_data, data;
52
+ struct ncsi_aen_lsc_pkt *lsc;
53
+ struct ncsi_package *np;
54
+ bool had_link, has_link;
55
+ unsigned long flags;
5656 bool chained;
5757 int state;
58
- unsigned long old_data, data;
59
- unsigned long flags;
6058
6159 /* Find the NCSI channel */
6260 ncsi_find_package_and_channel(ndp, h->common.channel, NULL, &nc);
....@@ -73,6 +71,9 @@
7371 ncm->data[2] = data;
7472 ncm->data[4] = ntohl(lsc->oem_status);
7573
74
+ had_link = !!(old_data & 0x1);
75
+ has_link = !!(data & 0x1);
76
+
7677 netdev_dbg(ndp->ndev.dev, "NCSI: LSC AEN - channel %u state %s\n",
7778 nc->id, data & 0x1 ? "up" : "down");
7879
....@@ -80,22 +81,65 @@
8081 state = nc->state;
8182 spin_unlock_irqrestore(&nc->lock, flags);
8283
83
- if (!((old_data ^ data) & 0x1) || chained)
84
- return 0;
85
- if (!(state == NCSI_CHANNEL_INACTIVE && (data & 0x1)) &&
86
- !(state == NCSI_CHANNEL_ACTIVE && !(data & 0x1)))
84
+ if (state == NCSI_CHANNEL_INACTIVE)
85
+ netdev_warn(ndp->ndev.dev,
86
+ "NCSI: Inactive channel %u received AEN!\n",
87
+ nc->id);
88
+
89
+ if ((had_link == has_link) || chained)
8790 return 0;
8891
89
- if (!(ndp->flags & NCSI_DEV_HWA) &&
90
- state == NCSI_CHANNEL_ACTIVE)
91
- ndp->flags |= NCSI_DEV_RESHUFFLE;
92
+ if (had_link)
93
+ netif_carrier_off(ndp->ndev.dev);
94
+ else
95
+ netif_carrier_on(ndp->ndev.dev);
9296
93
- ncsi_stop_channel_monitor(nc);
94
- spin_lock_irqsave(&ndp->lock, flags);
95
- list_add_tail_rcu(&nc->link, &ndp->channel_queue);
96
- spin_unlock_irqrestore(&ndp->lock, flags);
97
+ if (!ndp->multi_package && !nc->package->multi_channel) {
98
+ if (had_link) {
99
+ ndp->flags |= NCSI_DEV_RESHUFFLE;
100
+ ncsi_stop_channel_monitor(nc);
101
+ spin_lock_irqsave(&ndp->lock, flags);
102
+ list_add_tail_rcu(&nc->link, &ndp->channel_queue);
103
+ spin_unlock_irqrestore(&ndp->lock, flags);
104
+ return ncsi_process_next_channel(ndp);
105
+ }
106
+ /* Configured channel came up */
107
+ return 0;
108
+ }
97109
98
- return ncsi_process_next_channel(ndp);
110
+ if (had_link) {
111
+ ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
112
+ if (ncsi_channel_is_last(ndp, nc)) {
113
+ /* No channels left, reconfigure */
114
+ return ncsi_reset_dev(&ndp->ndev);
115
+ } else if (ncm->enable) {
116
+ /* Need to failover Tx channel */
117
+ ncsi_update_tx_channel(ndp, nc->package, nc, NULL);
118
+ }
119
+ } else if (has_link && nc->package->preferred_channel == nc) {
120
+ /* Return Tx to preferred channel */
121
+ ncsi_update_tx_channel(ndp, nc->package, NULL, nc);
122
+ } else if (has_link) {
123
+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
124
+ NCSI_FOR_EACH_CHANNEL(np, tmp) {
125
+ /* Enable Tx on this channel if the current Tx
126
+ * channel is down.
127
+ */
128
+ ncm = &tmp->modes[NCSI_MODE_TX_ENABLE];
129
+ if (ncm->enable &&
130
+ !ncsi_channel_has_link(tmp)) {
131
+ ncsi_update_tx_channel(ndp, nc->package,
132
+ tmp, nc);
133
+ break;
134
+ }
135
+ }
136
+ }
137
+ }
138
+
139
+ /* Leave configured channels active in a multi-channel scenario so
140
+ * AEN events are still received.
141
+ */
142
+ return 0;
99143 }
100144
101145 static int ncsi_aen_handler_cr(struct ncsi_dev_priv *ndp,
....@@ -126,6 +170,7 @@
126170 nc->state = NCSI_CHANNEL_INACTIVE;
127171 list_add_tail_rcu(&nc->link, &ndp->channel_queue);
128172 spin_unlock_irqrestore(&ndp->lock, flags);
173
+ nc->modes[NCSI_MODE_TX_ENABLE].enable = 0;
129174
130175 return ncsi_process_next_channel(ndp);
131176 }