Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Copyright Gavin Shan, IBM Corporation 2016.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <net/ncsi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include "ncsi-pkt.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include "ncsi-netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) LIST_HEAD(ncsi_dev_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) DEFINE_SPINLOCK(ncsi_dev_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) bool ncsi_channel_has_link(struct ncsi_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 	return !!(channel->modes[NCSI_MODE_LINK].data[2] & 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) bool ncsi_channel_is_last(struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) 			  struct ncsi_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 	NCSI_FOR_EACH_PACKAGE(ndp, np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 			if (nc == channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 			if (nc->state == NCSI_CHANNEL_ACTIVE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 			    ncsi_channel_has_link(nc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) static void ncsi_report_link(struct ncsi_dev_priv *ndp, bool force_down)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	struct ncsi_dev *nd = &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 	nd->state = ncsi_dev_state_functional;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	if (force_down) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 		nd->link_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 		goto report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	nd->link_up = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 			spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 			if (!list_empty(&nc->link) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 			    nc->state != NCSI_CHANNEL_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 				spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 			if (ncsi_channel_has_link(nc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 				spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 				nd->link_up = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 				goto report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 			spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) report:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 	nd->handler(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) static void ncsi_channel_monitor(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	struct ncsi_channel *nc = from_timer(nc, t, monitor.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	struct ncsi_package *np = nc->package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	struct ncsi_dev_priv *ndp = np->ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	struct ncsi_channel_mode *ncm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	struct ncsi_cmd_arg nca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	bool enabled, chained;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	unsigned int monitor_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	int state, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	state = nc->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	chained = !list_empty(&nc->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	enabled = nc->monitor.enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	monitor_state = nc->monitor.state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	if (!enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 		return;		/* expected race disabling timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	if (WARN_ON_ONCE(chained))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 		goto bad_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	if (state != NCSI_CHANNEL_INACTIVE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	    state != NCSI_CHANNEL_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) bad_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 		netdev_warn(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 			    "Bad NCSI monitor state channel %d 0x%x %s queue\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 			    nc->id, state, chained ? "on" : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 		spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 		nc->monitor.enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	switch (monitor_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	case NCSI_CHANNEL_MONITOR_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	case NCSI_CHANNEL_MONITOR_RETRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 		nca.ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 		nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 		nca.type = NCSI_PKT_CMD_GLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		nca.req_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 			netdev_err(ndp->ndev.dev, "Error %d sending GLS\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 				   ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	case NCSI_CHANNEL_MONITOR_WAIT ... NCSI_CHANNEL_MONITOR_WAIT_MAX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 		netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 			   nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 		ncsi_report_link(ndp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 		ndp->flags |= NCSI_DEV_RESHUFFLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 		ncm = &nc->modes[NCSI_MODE_LINK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		nc->monitor.enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 		nc->state = NCSI_CHANNEL_INVISIBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 		ncm->data[2] &= ~0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 		nc->state = NCSI_CHANNEL_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		list_add_tail_rcu(&nc->link, &ndp->channel_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 		spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 		ncsi_process_next_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	nc->monitor.state++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	mod_timer(&nc->monitor.timer, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) void ncsi_start_channel_monitor(struct ncsi_channel *nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	WARN_ON_ONCE(nc->monitor.enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	nc->monitor.enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	nc->monitor.state = NCSI_CHANNEL_MONITOR_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	mod_timer(&nc->monitor.timer, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) void ncsi_stop_channel_monitor(struct ncsi_channel *nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	if (!nc->monitor.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	nc->monitor.enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	del_timer_sync(&nc->monitor.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) struct ncsi_channel *ncsi_find_channel(struct ncsi_package *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 				       unsigned char id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 		if (nc->id == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 			return nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) struct ncsi_channel *ncsi_add_channel(struct ncsi_package *np, unsigned char id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	struct ncsi_channel *nc, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	nc = kzalloc(sizeof(*nc), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	if (!nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	nc->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	nc->package = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	nc->state = NCSI_CHANNEL_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	nc->monitor.enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	timer_setup(&nc->monitor.timer, ncsi_channel_monitor, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	spin_lock_init(&nc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	INIT_LIST_HEAD(&nc->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	for (index = 0; index < NCSI_CAP_MAX; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 		nc->caps[index].index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	for (index = 0; index < NCSI_MODE_MAX; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		nc->modes[index].index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	spin_lock_irqsave(&np->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	tmp = ncsi_find_channel(np, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 		spin_unlock_irqrestore(&np->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		kfree(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	list_add_tail_rcu(&nc->node, &np->channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	np->channel_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	spin_unlock_irqrestore(&np->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	return nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) static void ncsi_remove_channel(struct ncsi_channel *nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	struct ncsi_package *np = nc->package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	/* Release filters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	kfree(nc->mac_filter.addrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	kfree(nc->vlan_filter.vids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	nc->state = NCSI_CHANNEL_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	ncsi_stop_channel_monitor(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	/* Remove and free channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	spin_lock_irqsave(&np->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	list_del_rcu(&nc->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	np->channel_num--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	spin_unlock_irqrestore(&np->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	kfree(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) struct ncsi_package *ncsi_find_package(struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 				       unsigned char id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 		if (np->id == id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 			return np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) struct ncsi_package *ncsi_add_package(struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 				      unsigned char id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	struct ncsi_package *np, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	np = kzalloc(sizeof(*np), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	np->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	np->ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	spin_lock_init(&np->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	INIT_LIST_HEAD(&np->channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	np->channel_whitelist = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	tmp = ncsi_find_package(ndp, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 		spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 		kfree(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 		return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	list_add_tail_rcu(&np->node, &ndp->packages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	ndp->package_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	return np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) void ncsi_remove_package(struct ncsi_package *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	struct ncsi_dev_priv *ndp = np->ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	struct ncsi_channel *nc, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	/* Release all child channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	list_for_each_entry_safe(nc, tmp, &np->channels, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 		ncsi_remove_channel(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	/* Remove and free package */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	list_del_rcu(&np->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	ndp->package_num--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	kfree(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) void ncsi_find_package_and_channel(struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 				   unsigned char id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 				   struct ncsi_package **np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 				   struct ncsi_channel **nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	struct ncsi_package *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	struct ncsi_channel *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	p = ncsi_find_package(ndp, NCSI_PACKAGE_INDEX(id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	c = p ? ncsi_find_channel(p, NCSI_CHANNEL_INDEX(id)) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	if (np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 		*np = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	if (nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		*nc = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) /* For two consecutive NCSI commands, the packet IDs shouldn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350)  * be same. Otherwise, the bogus response might be replied. So
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351)  * the available IDs are allocated in round-robin fashion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) struct ncsi_request *ncsi_alloc_request(struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 					unsigned int req_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	struct ncsi_request *nr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	int i, limit = ARRAY_SIZE(ndp->requests);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 	/* Check if there is one available request until the ceiling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	for (i = ndp->request_id; i < limit; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 		if (ndp->requests[i].used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		nr = &ndp->requests[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		nr->used = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 		nr->flags = req_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 		ndp->request_id = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 		goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	/* Fail back to check from the starting cursor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	for (i = NCSI_REQ_START_IDX; i < ndp->request_id; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		if (ndp->requests[i].used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		nr = &ndp->requests[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		nr->used = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		nr->flags = req_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		ndp->request_id = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	return nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) void ncsi_free_request(struct ncsi_request *nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	struct ncsi_dev_priv *ndp = nr->ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	struct sk_buff *cmd, *rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	bool driven;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	if (nr->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		nr->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 		del_timer_sync(&nr->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	cmd = nr->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	rsp = nr->rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	nr->cmd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	nr->rsp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	nr->used = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	driven = !!(nr->flags & NCSI_REQ_FLAG_EVENT_DRIVEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	if (driven && cmd && --ndp->pending_req_num == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 		schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	/* Release command and response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	consume_skb(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	consume_skb(rsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) struct ncsi_dev *ncsi_find_dev(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	NCSI_FOR_EACH_DEV(ndp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		if (ndp->ndev.dev == dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 			return &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) static void ncsi_request_timeout(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	struct ncsi_request *nr = from_timer(nr, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	struct ncsi_dev_priv *ndp = nr->ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	struct ncsi_cmd_pkt *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	/* If the request already had associated response,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	 * let the response handler to release it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	nr->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	if (nr->rsp || !nr->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	if (nr->flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		if (nr->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 			/* Find the package */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 			cmd = (struct ncsi_cmd_pkt *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 			      skb_network_header(nr->cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 			ncsi_find_package_and_channel(ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 						      cmd->cmd.common.channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 						      &np, &nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 			ncsi_send_netlink_timeout(nr, np, nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	/* Release the request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	ncsi_free_request(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	struct ncsi_dev *nd = &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	struct ncsi_channel *nc, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	struct ncsi_cmd_arg nca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	np = ndp->active_package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	nc = ndp->active_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	nca.ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	switch (nd->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	case ncsi_dev_state_suspend:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		nd->state = ncsi_dev_state_suspend_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	case ncsi_dev_state_suspend_select:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		nca.type = NCSI_PKT_CMD_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 		nca.channel = NCSI_RESERVED_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 		if (ndp->flags & NCSI_DEV_HWA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 			nca.bytes[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 			nca.bytes[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 		/* To retrieve the last link states of channels in current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		 * package when current active channel needs fail over to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 		 * another one. It means we will possibly select another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		 * channel as next active one. The link states of channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		 * are most important factor of the selection. So we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		 * accurate link states. Unfortunately, the link states on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		 * inactive channels can't be updated with LSC AEN in time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 		if (ndp->flags & NCSI_DEV_RESHUFFLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 			nd->state = ncsi_dev_state_suspend_gls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 			nd->state = ncsi_dev_state_suspend_dcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	case ncsi_dev_state_suspend_gls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		ndp->pending_req_num = np->channel_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 		nca.type = NCSI_PKT_CMD_GLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		nd->state = ncsi_dev_state_suspend_dcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 			nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 			ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 				goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	case ncsi_dev_state_suspend_dcnt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		nca.type = NCSI_PKT_CMD_DCNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 		nd->state = ncsi_dev_state_suspend_dc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	case ncsi_dev_state_suspend_dc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		nca.type = NCSI_PKT_CMD_DC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		nca.bytes[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		nd->state = ncsi_dev_state_suspend_deselect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 		NCSI_FOR_EACH_CHANNEL(np, tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 			/* If there is another channel active on this package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 			 * do not deselect the package.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 			if (tmp != nc && tmp->state == NCSI_CHANNEL_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 				nd->state = ncsi_dev_state_suspend_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	case ncsi_dev_state_suspend_deselect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		nca.type = NCSI_PKT_CMD_DP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		nca.channel = NCSI_RESERVED_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		nd->state = ncsi_dev_state_suspend_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	case ncsi_dev_state_suspend_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		nc->state = NCSI_CHANNEL_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		if (ndp->flags & NCSI_DEV_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			ncsi_reset_dev(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 			ncsi_process_next_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			    nd->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	nd->state = ncsi_dev_state_functional;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) /* Check the VLAN filter bitmap for a set filter, and construct a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596)  * "Set VLAN Filter - Disable" packet if found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) static int clear_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 			 struct ncsi_cmd_arg *nca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	struct ncsi_channel_vlan_filter *ncf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	void *bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	u16 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	ncf = &nc->vlan_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	bitmap = &ncf->bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	index = find_next_bit(bitmap, ncf->n_vids, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	if (index >= ncf->n_vids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	vid = ncf->vids[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	clear_bit(index, bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	ncf->vids[index] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	nca->type = NCSI_PKT_CMD_SVF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	nca->words[1] = vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	/* HW filter index starts at 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	nca->bytes[6] = index + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	nca->bytes[7] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) /* Find an outstanding VLAN tag and constuct a "Set VLAN Filter - Enable"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631)  * packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 		       struct ncsi_cmd_arg *nca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	struct ncsi_channel_vlan_filter *ncf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	struct vlan_vid *vlan = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	int i, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	void *bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	u16 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	if (list_empty(&ndp->vlan_vids))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	ncf = &nc->vlan_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	bitmap = &ncf->bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		vid = vlan->vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		for (i = 0; i < ncf->n_vids; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 			if (ncf->vids[i] == vid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 				vid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		if (vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	if (!vid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		/* No VLAN ID is not set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	index = find_next_zero_bit(bitmap, ncf->n_vids, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	if (index < 0 || index >= ncf->n_vids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 			   "Channel %u already has all VLAN filters set\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 			   nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	ncf->vids[index] = vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	set_bit(index, bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	nca->type = NCSI_PKT_CMD_SVF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	nca->words[1] = vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	/* HW filter index starts at 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	nca->bytes[6] = index + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	nca->bytes[7] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) #if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) /* NCSI OEM Command APIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) static int ncsi_oem_gma_handler_bcm(struct ncsi_cmd_arg *nca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	unsigned char data[NCSI_OEM_BCM_CMD_GMA_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	nca->payload = NCSI_OEM_BCM_CMD_GMA_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	memset(data, 0, NCSI_OEM_BCM_CMD_GMA_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	*(unsigned int *)data = ntohl(NCSI_OEM_MFR_BCM_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	data[5] = NCSI_OEM_BCM_CMD_GMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	nca->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	ret = ncsi_xmit_cmd(nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		netdev_err(nca->ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 			   "NCSI: Failed to transmit cmd 0x%x during configure\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 			   nca->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) static int ncsi_oem_gma_handler_mlx(struct ncsi_cmd_arg *nca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		u8 data_u8[NCSI_OEM_MLX_CMD_GMA_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		u32 data_u32[NCSI_OEM_MLX_CMD_GMA_LEN / sizeof(u32)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	} u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	nca->payload = NCSI_OEM_MLX_CMD_GMA_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	memset(&u, 0, sizeof(u));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	u.data_u32[0] = ntohl(NCSI_OEM_MFR_MLX_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	u.data_u8[5] = NCSI_OEM_MLX_CMD_GMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	u.data_u8[6] = NCSI_OEM_MLX_CMD_GMA_PARAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	nca->data = u.data_u8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	ret = ncsi_xmit_cmd(nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 		netdev_err(nca->ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 			   "NCSI: Failed to transmit cmd 0x%x during configure\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 			   nca->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) static int ncsi_oem_smaf_mlx(struct ncsi_cmd_arg *nca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 		u8 data_u8[NCSI_OEM_MLX_CMD_SMAF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 		u32 data_u32[NCSI_OEM_MLX_CMD_SMAF_LEN / sizeof(u32)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	} u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	memset(&u, 0, sizeof(u));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	u.data_u32[0] = ntohl(NCSI_OEM_MFR_MLX_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	u.data_u8[5] = NCSI_OEM_MLX_CMD_SMAF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	u.data_u8[6] = NCSI_OEM_MLX_CMD_SMAF_PARAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	memcpy(&u.data_u8[MLX_SMAF_MAC_ADDR_OFFSET],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	       nca->ndp->ndev.dev->dev_addr,	ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	u.data_u8[MLX_SMAF_MED_SUPPORT_OFFSET] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		(MLX_MC_RBT_AVL | MLX_MC_RBT_SUPPORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	nca->payload = NCSI_OEM_MLX_CMD_SMAF_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	nca->data = u.data_u8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	ret = ncsi_xmit_cmd(nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 		netdev_err(nca->ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 			   "NCSI: Failed to transmit cmd 0x%x during probe\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 			   nca->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) /* OEM Command handlers initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) static struct ncsi_oem_gma_handler {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	unsigned int	mfr_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	int		(*handler)(struct ncsi_cmd_arg *nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) } ncsi_oem_gma_handlers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	{ NCSI_OEM_MFR_BCM_ID, ncsi_oem_gma_handler_bcm },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	{ NCSI_OEM_MFR_MLX_ID, ncsi_oem_gma_handler_mlx }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	struct ncsi_oem_gma_handler *nch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	/* This function should only be called once, return if flag set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	if (nca->ndp->gma_flag == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	/* Find gma handler for given manufacturer id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	for (i = 0; i < ARRAY_SIZE(ncsi_oem_gma_handlers); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 		if (ncsi_oem_gma_handlers[i].mfr_id == mf_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 			if (ncsi_oem_gma_handlers[i].handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 				nch = &ncsi_oem_gma_handlers[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	if (!nch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		netdev_err(nca->ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 			   "NCSI: No GMA handler available for MFR-ID (0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 			   mf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	/* Get Mac address from NCSI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	return nch->handler(nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) #endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) /* Determine if a given channel from the channel_queue should be used for Tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) static bool ncsi_channel_is_tx(struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 			       struct ncsi_channel *nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	struct ncsi_channel_mode *ncm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	struct ncsi_channel *channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	/* Check if any other channel has Tx enabled; a channel may have already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	 * been configured and removed from the channel queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		if (!ndp->multi_package && np != nc->package)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 		NCSI_FOR_EACH_CHANNEL(np, channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 			ncm = &channel->modes[NCSI_MODE_TX_ENABLE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 			if (ncm->enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	/* This channel is the preferred channel and has link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	list_for_each_entry_rcu(channel, &ndp->channel_queue, link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 		np = channel->package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		if (np->preferred_channel &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 		    ncsi_channel_has_link(np->preferred_channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 			return np->preferred_channel == nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	/* This channel has link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	if (ncsi_channel_has_link(nc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	list_for_each_entry_rcu(channel, &ndp->channel_queue, link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		if (ncsi_channel_has_link(channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	/* No other channel has link; default to this one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) /* Change the active Tx channel in a multi-channel setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) int ncsi_update_tx_channel(struct ncsi_dev_priv *ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 			   struct ncsi_package *package,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 			   struct ncsi_channel *disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 			   struct ncsi_channel *enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	struct ncsi_cmd_arg nca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	if (!package->multi_channel && !ndp->multi_package)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 		netdev_warn(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 			    "NCSI: Trying to update Tx channel in single-channel mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	nca.ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	nca.req_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	/* Find current channel with Tx enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 		if (disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		if (!ndp->multi_package && np != package)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 		NCSI_FOR_EACH_CHANNEL(np, nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 			if (nc->modes[NCSI_MODE_TX_ENABLE].enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 				disable = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	/* Find a suitable channel for Tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 		if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		if (!ndp->multi_package && np != package)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		if (!(ndp->package_whitelist & (0x1 << np->id)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 		if (np->preferred_channel &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		    ncsi_channel_has_link(np->preferred_channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 			enable = np->preferred_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 			if (!(np->channel_whitelist & 0x1 << nc->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			if (nc->state != NCSI_CHANNEL_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 			if (ncsi_channel_has_link(nc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 				enable = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	if (disable == enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	if (disable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		nca.channel = disable->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		nca.package = disable->package->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		nca.type = NCSI_PKT_CMD_DCNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 			netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 				   "Error %d sending DCNT\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 				   ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	netdev_info(ndp->ndev.dev, "NCSI: channel %u enables Tx\n", enable->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	nca.channel = enable->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	nca.package = enable->package->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	nca.type = NCSI_PKT_CMD_ECNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 			   "Error %d sending ECNT\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 			   ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	struct ncsi_package *np = ndp->active_package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	struct ncsi_channel *nc = ndp->active_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	struct ncsi_channel *hot_nc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	struct ncsi_dev *nd = &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	struct net_device *dev = nd->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	struct ncsi_cmd_arg nca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	unsigned char index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	nca.ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	switch (nd->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	case ncsi_dev_state_config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	case ncsi_dev_state_config_sp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		/* Select the specific package */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		nca.type = NCSI_PKT_CMD_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		if (ndp->flags & NCSI_DEV_HWA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 			nca.bytes[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 			nca.bytes[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		nca.channel = NCSI_RESERVED_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 			netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 				   "NCSI: Failed to transmit CMD_SP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		nd->state = ncsi_dev_state_config_cis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	case ncsi_dev_state_config_cis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 		/* Clear initial state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		nca.type = NCSI_PKT_CMD_CIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 		nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 			netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 				   "NCSI: Failed to transmit CMD_CIS\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		nd->state = ncsi_dev_state_config_oem_gma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	case ncsi_dev_state_config_oem_gma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		nd->state = ncsi_dev_state_config_clear_vids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) #if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		nca.type = NCSI_PKT_CMD_OEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 		ret = ncsi_gma_handler(&nca, nc->version.mf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) #endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 			schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	case ncsi_dev_state_config_clear_vids:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	case ncsi_dev_state_config_svf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	case ncsi_dev_state_config_ev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	case ncsi_dev_state_config_sma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	case ncsi_dev_state_config_ebf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	case ncsi_dev_state_config_dgmf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	case ncsi_dev_state_config_ecnt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	case ncsi_dev_state_config_ec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	case ncsi_dev_state_config_ae:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	case ncsi_dev_state_config_gls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		/* Clear any active filters on the channel before setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 		if (nd->state == ncsi_dev_state_config_clear_vids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 			ret = clear_one_vid(ndp, nc, &nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 			if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 				nd->state = ncsi_dev_state_config_svf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 				schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 			/* Repeat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 			nd->state = ncsi_dev_state_config_clear_vids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		/* Add known VLAN tags to the filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 		} else if (nd->state == ncsi_dev_state_config_svf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 			ret = set_one_vid(ndp, nc, &nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 			if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 				nd->state = ncsi_dev_state_config_ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 				schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 			/* Repeat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 			nd->state = ncsi_dev_state_config_svf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 		/* Enable/Disable the VLAN filter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		} else if (nd->state == ncsi_dev_state_config_ev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 			if (list_empty(&ndp->vlan_vids)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 				nca.type = NCSI_PKT_CMD_DV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 				nca.type = NCSI_PKT_CMD_EV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 				nca.bytes[3] = NCSI_CAP_VLAN_NO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 			nd->state = ncsi_dev_state_config_sma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 		} else if (nd->state == ncsi_dev_state_config_sma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		/* Use first entry in unicast filter table. Note that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		 * the MAC filter table starts from entry 1 instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 		 * 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 			nca.type = NCSI_PKT_CMD_SMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 			for (index = 0; index < 6; index++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 				nca.bytes[index] = dev->dev_addr[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 			nca.bytes[6] = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 			nca.bytes[7] = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 			nd->state = ncsi_dev_state_config_ebf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 		} else if (nd->state == ncsi_dev_state_config_ebf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 			nca.type = NCSI_PKT_CMD_EBF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 			nca.dwords[0] = nc->caps[NCSI_CAP_BC].cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 			/* if multicast global filtering is supported then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 			 * disable it so that all multicast packet will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			 * forwarded to management controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 			if (nc->caps[NCSI_CAP_GENERIC].cap &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 			    NCSI_CAP_GENERIC_MC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 				nd->state = ncsi_dev_state_config_dgmf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 			else if (ncsi_channel_is_tx(ndp, nc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 				nd->state = ncsi_dev_state_config_ecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 				nd->state = ncsi_dev_state_config_ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		} else if (nd->state == ncsi_dev_state_config_dgmf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 			nca.type = NCSI_PKT_CMD_DGMF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 			if (ncsi_channel_is_tx(ndp, nc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 				nd->state = ncsi_dev_state_config_ecnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 				nd->state = ncsi_dev_state_config_ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		} else if (nd->state == ncsi_dev_state_config_ecnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 			if (np->preferred_channel &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 			    nc != np->preferred_channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 				netdev_info(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 					    "NCSI: Tx failed over to channel %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 					    nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 			nca.type = NCSI_PKT_CMD_ECNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			nd->state = ncsi_dev_state_config_ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		} else if (nd->state == ncsi_dev_state_config_ec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 			/* Enable AEN if it's supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 			nca.type = NCSI_PKT_CMD_EC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			nd->state = ncsi_dev_state_config_ae;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 			if (!(nc->caps[NCSI_CAP_AEN].cap & NCSI_CAP_AEN_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 				nd->state = ncsi_dev_state_config_gls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 		} else if (nd->state == ncsi_dev_state_config_ae) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 			nca.type = NCSI_PKT_CMD_AE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 			nca.bytes[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 			nca.dwords[1] = nc->caps[NCSI_CAP_AEN].cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 			nd->state = ncsi_dev_state_config_gls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		} else if (nd->state == ncsi_dev_state_config_gls) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 			nca.type = NCSI_PKT_CMD_GLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 			nd->state = ncsi_dev_state_config_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 			netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 				   "NCSI: Failed to transmit CMD %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 				   nca.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	case ncsi_dev_state_config_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 		netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 			   nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 		spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 		nc->state = NCSI_CHANNEL_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		if (ndp->flags & NCSI_DEV_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 			/* A reset event happened during config, start it now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 			nc->reconfigure_needed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 			spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 			ncsi_reset_dev(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 		if (nc->reconfigure_needed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 			/* This channel's configuration has been updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 			 * part-way during the config state - start the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 			 * channel configuration over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 			nc->reconfigure_needed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 			nc->state = NCSI_CHANNEL_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 			spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 			spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 			list_add_tail_rcu(&nc->link, &ndp->channel_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 			spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 			netdev_dbg(dev, "Dirty NCSI channel state reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 			ncsi_process_next_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 			hot_nc = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 			hot_nc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 			netdev_dbg(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 				   "NCSI: channel %u link down after config\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 				   nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 		spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		/* Update the hot channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 		spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 		ndp->hot_channel = hot_nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 		ncsi_start_channel_monitor(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 		ncsi_process_next_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 		netdev_alert(dev, "Wrong NCSI state 0x%x in config\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 			     nd->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	ncsi_report_link(ndp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	struct ncsi_channel *nc, *found, *hot_nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	struct ncsi_channel_mode *ncm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	unsigned long flags, cflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	bool with_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	hot_nc = ndp->hot_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	/* By default the search is done once an inactive channel with up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	 * link is found, unless a preferred channel is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	 * If multi_package or multi_channel are configured all channels in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	 * whitelist are added to the channel queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	found = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	with_link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		if (!(ndp->package_whitelist & (0x1 << np->id)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 			if (!(np->channel_whitelist & (0x1 << nc->id)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 			spin_lock_irqsave(&nc->lock, cflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 			if (!list_empty(&nc->link) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 			    nc->state != NCSI_CHANNEL_INACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 				spin_unlock_irqrestore(&nc->lock, cflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 			if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 				found = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 			if (nc == hot_nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 				found = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 			ncm = &nc->modes[NCSI_MODE_LINK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 			if (ncm->data[2] & 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 				found = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 				with_link = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 			/* If multi_channel is enabled configure all valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 			 * channels whether or not they currently have link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 			 * so they will have AENs enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 			if (with_link || np->multi_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 				spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 				list_add_tail_rcu(&nc->link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 						  &ndp->channel_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 				spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 				netdev_dbg(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 					   "NCSI: Channel %u added to queue (link %s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 					   nc->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 					   ncm->data[2] & 0x1 ? "up" : "down");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 			spin_unlock_irqrestore(&nc->lock, cflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 			if (with_link && !np->multi_channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 		if (with_link && !ndp->multi_package)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	if (list_empty(&ndp->channel_queue) && found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 		netdev_info(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 			    "NCSI: No channel with link found, configuring channel %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 			    found->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		list_add_tail_rcu(&found->link, &ndp->channel_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 		spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	} else if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		netdev_warn(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 			    "NCSI: No channel found to configure!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 		ncsi_report_link(ndp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 	return ncsi_process_next_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) static bool ncsi_check_hwa(struct ncsi_dev_priv *ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	unsigned int cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 	bool has_channel = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 	/* The hardware arbitration is disabled if any one channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	 * doesn't support explicitly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 			has_channel = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 			cap = nc->caps[NCSI_CAP_GENERIC].cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 			if (!(cap & NCSI_CAP_GENERIC_HWA) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 			    (cap & NCSI_CAP_GENERIC_HWA_MASK) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 			    NCSI_CAP_GENERIC_HWA_SUPPORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 				ndp->flags &= ~NCSI_DEV_HWA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 				return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	if (has_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 		ndp->flags |= NCSI_DEV_HWA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	ndp->flags &= ~NCSI_DEV_HWA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 	struct ncsi_dev *nd = &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	struct ncsi_cmd_arg nca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	unsigned char index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	nca.ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	switch (nd->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	case ncsi_dev_state_probe:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 		nd->state = ncsi_dev_state_probe_deselect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	case ncsi_dev_state_probe_deselect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 		ndp->pending_req_num = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 		/* Deselect all possible packages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 		nca.type = NCSI_PKT_CMD_DP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		nca.channel = NCSI_RESERVED_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		for (index = 0; index < 8; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 			nca.package = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 			ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 				goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 		nd->state = ncsi_dev_state_probe_package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	case ncsi_dev_state_probe_package:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 		nca.type = NCSI_PKT_CMD_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 		nca.bytes[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		nca.package = ndp->package_probe_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 		nca.channel = NCSI_RESERVED_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 		nd->state = ncsi_dev_state_probe_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 	case ncsi_dev_state_probe_channel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 		ndp->active_package = ncsi_find_package(ndp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 							ndp->package_probe_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		if (!ndp->active_package) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 			/* No response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 			nd->state = ncsi_dev_state_probe_dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 			schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 		nd->state = ncsi_dev_state_probe_cis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 		if (IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 		    ndp->mlx_multi_host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 			nd->state = ncsi_dev_state_probe_mlx_gma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 		schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) #if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 	case ncsi_dev_state_probe_mlx_gma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 		nca.type = NCSI_PKT_CMD_OEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 		nca.package = ndp->active_package->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		nca.channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 		ret = ncsi_oem_gma_handler_mlx(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 		nd->state = ncsi_dev_state_probe_mlx_smaf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 	case ncsi_dev_state_probe_mlx_smaf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 		nca.type = NCSI_PKT_CMD_OEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 		nca.package = ndp->active_package->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 		nca.channel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 		ret = ncsi_oem_smaf_mlx(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 		nd->state = ncsi_dev_state_probe_cis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) #endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 	case ncsi_dev_state_probe_cis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		ndp->pending_req_num = NCSI_RESERVED_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 		/* Clear initial state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 		nca.type = NCSI_PKT_CMD_CIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 		nca.package = ndp->active_package->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 		for (index = 0; index < NCSI_RESERVED_CHANNEL; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 			nca.channel = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 			ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 				goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 		nd->state = ncsi_dev_state_probe_gvi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 	case ncsi_dev_state_probe_gvi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 	case ncsi_dev_state_probe_gc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	case ncsi_dev_state_probe_gls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 		np = ndp->active_package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		ndp->pending_req_num = np->channel_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		/* Retrieve version, capability or link status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 		if (nd->state == ncsi_dev_state_probe_gvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 			nca.type = NCSI_PKT_CMD_GVI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 		else if (nd->state == ncsi_dev_state_probe_gc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 			nca.type = NCSI_PKT_CMD_GC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 			nca.type = NCSI_PKT_CMD_GLS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 		nca.package = np->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 			nca.channel = nc->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 			ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 				goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 		if (nd->state == ncsi_dev_state_probe_gvi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 			nd->state = ncsi_dev_state_probe_gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 		else if (nd->state == ncsi_dev_state_probe_gc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 			nd->state = ncsi_dev_state_probe_gls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 			nd->state = ncsi_dev_state_probe_dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 	case ncsi_dev_state_probe_dp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 		ndp->pending_req_num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		/* Deselect the current package */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 		nca.type = NCSI_PKT_CMD_DP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 		nca.package = ndp->package_probe_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 		nca.channel = NCSI_RESERVED_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 		ret = ncsi_xmit_cmd(&nca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 		/* Probe next package */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 		ndp->package_probe_id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		if (ndp->package_probe_id >= 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 			/* Probe finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 			ndp->flags |= NCSI_DEV_PROBED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		nd->state = ncsi_dev_state_probe_package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 		ndp->active_package = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 		netdev_warn(nd->dev, "Wrong NCSI state 0x%0x in enumeration\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 			    nd->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 	if (ndp->flags & NCSI_DEV_PROBED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		/* Check if all packages have HWA support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 		ncsi_check_hwa(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		ncsi_choose_active_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 	netdev_err(ndp->ndev.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 		   "NCSI: Failed to transmit cmd 0x%x during probe\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 		   nca.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	ncsi_report_link(ndp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) static void ncsi_dev_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 	struct ncsi_dev_priv *ndp = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 			struct ncsi_dev_priv, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 	struct ncsi_dev *nd = &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 	switch (nd->state & ncsi_dev_state_major) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 	case ncsi_dev_state_probe:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 		ncsi_probe_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 	case ncsi_dev_state_suspend:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 		ncsi_suspend_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 	case ncsi_dev_state_config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 		ncsi_configure_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 		netdev_warn(nd->dev, "Wrong NCSI state 0x%x in workqueue\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 			    nd->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) int ncsi_process_next_channel(struct ncsi_dev_priv *ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 	int old_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	nc = list_first_or_null_rcu(&ndp->channel_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 				    struct ncsi_channel, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 	if (!nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 		spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	list_del_init(&nc->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	old_state = nc->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	nc->state = NCSI_CHANNEL_INVISIBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	ndp->active_channel = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	ndp->active_package = nc->package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 	switch (old_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 	case NCSI_CHANNEL_INACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 		ndp->ndev.state = ncsi_dev_state_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 		netdev_dbg(ndp->ndev.dev, "NCSI: configuring channel %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 	                   nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 		ncsi_configure_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	case NCSI_CHANNEL_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 		ndp->ndev.state = ncsi_dev_state_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 		netdev_dbg(ndp->ndev.dev, "NCSI: suspending channel %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 			   nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 		ncsi_suspend_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 		netdev_err(ndp->ndev.dev, "Invalid state 0x%x on %d:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 			   old_state, nc->package->id, nc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 		ncsi_report_link(ndp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	ndp->active_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 	ndp->active_package = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 	if (ndp->flags & NCSI_DEV_RESHUFFLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 		ndp->flags &= ~NCSI_DEV_RESHUFFLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 		return ncsi_choose_active_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 	ncsi_report_link(ndp, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) static int ncsi_kick_channels(struct ncsi_dev_priv *ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 	struct ncsi_dev *nd = &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 	unsigned int n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 			spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 			/* Channels may be busy, mark dirty instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 			 * kicking if;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 			 * a) not ACTIVE (configured)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 			 * b) in the channel_queue (to be configured)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 			 * c) it's ndev is in the config state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 			if (nc->state != NCSI_CHANNEL_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 				if ((ndp->ndev.state & 0xff00) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 						ncsi_dev_state_config ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 						!list_empty(&nc->link)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 					netdev_dbg(nd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 						   "NCSI: channel %p marked dirty\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 						   nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 					nc->reconfigure_needed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 				spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 			spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 			ncsi_stop_channel_monitor(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 			spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 			nc->state = NCSI_CHANNEL_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 			spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 			spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 			list_add_tail_rcu(&nc->link, &ndp->channel_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 			spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 			netdev_dbg(nd->dev, "NCSI: kicked channel %p\n", nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 			n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 	return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	unsigned int n_vids = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 	struct vlan_vid *vlan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	struct ncsi_dev *nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 	bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 	if (vid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 	nd = ncsi_find_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	if (!nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 		netdev_warn(dev, "NCSI: No net_device?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 	ndp = TO_NCSI_DEV_PRIV(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 	/* Add the VLAN id to our internal list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 	list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 		n_vids++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 		if (vlan->vid == vid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 			netdev_dbg(dev, "NCSI: vid %u already registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 				   vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 	if (n_vids >= NCSI_MAX_VLAN_VIDS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) 		netdev_warn(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) 			    "tried to add vlan id %u but NCSI max already registered (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 			    vid, NCSI_MAX_VLAN_VIDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 		return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 	vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 	if (!vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 	vlan->proto = proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 	vlan->vid = vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	list_add_rcu(&vlan->list, &ndp->vlan_vids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 	netdev_dbg(dev, "NCSI: Added new vid %u\n", vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	found = ncsi_kick_channels(ndp) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 	return found ? ncsi_process_next_channel(ndp) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) EXPORT_SYMBOL_GPL(ncsi_vlan_rx_add_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) int ncsi_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 	struct vlan_vid *vlan, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 	struct ncsi_dev *nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 	bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 	if (vid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 	nd = ncsi_find_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 	if (!nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 		netdev_warn(dev, "NCSI: no net_device?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 	ndp = TO_NCSI_DEV_PRIV(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 	/* Remove the VLAN id from our internal list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 	list_for_each_entry_safe(vlan, tmp, &ndp->vlan_vids, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 		if (vlan->vid == vid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 			netdev_dbg(dev, "NCSI: vid %u found, removing\n", vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 			list_del_rcu(&vlan->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 			found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 			kfree(vlan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 		netdev_err(dev, "NCSI: vid %u wasn't registered!\n", vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 	found = ncsi_kick_channels(ndp) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 	return found ? ncsi_process_next_channel(ndp) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) EXPORT_SYMBOL_GPL(ncsi_vlan_rx_kill_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 				   void (*handler)(struct ncsi_dev *ndev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 	struct ncsi_dev_priv *ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 	struct ncsi_dev *nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 	struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 	struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 	/* Check if the device has been registered or not */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 	nd = ncsi_find_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 	if (nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 		return nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	/* Create NCSI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 	ndp = kzalloc(sizeof(*ndp), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 	if (!ndp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 	nd = &ndp->ndev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 	nd->state = ncsi_dev_state_registered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 	nd->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 	nd->handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 	ndp->pending_req_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 	INIT_LIST_HEAD(&ndp->channel_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 	INIT_LIST_HEAD(&ndp->vlan_vids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 	INIT_WORK(&ndp->work, ncsi_dev_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	ndp->package_whitelist = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 	/* Initialize private NCSI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 	spin_lock_init(&ndp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 	INIT_LIST_HEAD(&ndp->packages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 	ndp->request_id = NCSI_REQ_START_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 	for (i = 0; i < ARRAY_SIZE(ndp->requests); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 		ndp->requests[i].id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 		ndp->requests[i].ndp = ndp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 		timer_setup(&ndp->requests[i].timer, ncsi_request_timeout, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 	spin_lock_irqsave(&ncsi_dev_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 	list_add_tail_rcu(&ndp->node, &ncsi_dev_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 	spin_unlock_irqrestore(&ncsi_dev_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 	/* Register NCSI packet Rx handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 	ndp->ptype.type = cpu_to_be16(ETH_P_NCSI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 	ndp->ptype.func = ncsi_rcv_rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 	ndp->ptype.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 	dev_add_pack(&ndp->ptype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 	pdev = to_platform_device(dev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 	if (pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 		np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 		if (np && of_get_property(np, "mlx,multi-host", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 			ndp->mlx_multi_host = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 	return nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) EXPORT_SYMBOL_GPL(ncsi_register_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) int ncsi_start_dev(struct ncsi_dev *nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 	struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 	if (nd->state != ncsi_dev_state_registered &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 	    nd->state != ncsi_dev_state_functional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 		return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 	if (!(ndp->flags & NCSI_DEV_PROBED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 		ndp->package_probe_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 		nd->state = ncsi_dev_state_probe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 		schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 	return ncsi_reset_dev(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) EXPORT_SYMBOL_GPL(ncsi_start_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) void ncsi_stop_dev(struct ncsi_dev *nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 	struct ncsi_channel *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 	bool chained;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 	int old_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 	/* Stop the channel monitor on any active channels. Don't reset the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 	 * channel state so we know which were active when ncsi_start_dev()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 	 * is next called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 			ncsi_stop_channel_monitor(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 			spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 			chained = !list_empty(&nc->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 			old_state = nc->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 			spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 			WARN_ON_ONCE(chained ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 				     old_state == NCSI_CHANNEL_INVISIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 	netdev_dbg(ndp->ndev.dev, "NCSI: Stopping device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 	ncsi_report_link(ndp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) EXPORT_SYMBOL_GPL(ncsi_stop_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) int ncsi_reset_dev(struct ncsi_dev *nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 	struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 	struct ncsi_channel *nc, *active, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	struct ncsi_package *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 	if (!(ndp->flags & NCSI_DEV_RESET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 		/* Haven't been called yet, check states */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 		switch (nd->state & ncsi_dev_state_major) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 		case ncsi_dev_state_registered:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 		case ncsi_dev_state_probe:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 			/* Not even probed yet - do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 			spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 		case ncsi_dev_state_suspend:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 		case ncsi_dev_state_config:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 			/* Wait for the channel to finish its suspend/config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 			 * operation; once it finishes it will check for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 			 * NCSI_DEV_RESET and reset the state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 			ndp->flags |= NCSI_DEV_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 			spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 		switch (nd->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 		case ncsi_dev_state_suspend_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 		case ncsi_dev_state_config_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 		case ncsi_dev_state_functional:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 			/* Ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 			/* Current reset operation happening */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 			spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 	if (!list_empty(&ndp->channel_queue)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 		/* Clear any channel queue we may have interrupted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 		list_for_each_entry_safe(nc, tmp, &ndp->channel_queue, link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 			list_del_init(&nc->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 	active = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 	NCSI_FOR_EACH_PACKAGE(ndp, np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 		NCSI_FOR_EACH_CHANNEL(np, nc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 			spin_lock_irqsave(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) 			if (nc->state == NCSI_CHANNEL_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 				active = nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 				nc->state = NCSI_CHANNEL_INVISIBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 				spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 				ncsi_stop_channel_monitor(nc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 			spin_unlock_irqrestore(&nc->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 		if (active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 	if (!active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 		/* Done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 		spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 		ndp->flags &= ~NCSI_DEV_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 		spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 		return ncsi_choose_active_channel(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 	spin_lock_irqsave(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) 	ndp->flags |= NCSI_DEV_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 	ndp->active_channel = active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 	ndp->active_package = active->package;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 	spin_unlock_irqrestore(&ndp->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 	nd->state = ncsi_dev_state_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 	schedule_work(&ndp->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) void ncsi_unregister_dev(struct ncsi_dev *nd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 	struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 	struct ncsi_package *np, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 	dev_remove_pack(&ndp->ptype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) 	list_for_each_entry_safe(np, tmp, &ndp->packages, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) 		ncsi_remove_package(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) 	spin_lock_irqsave(&ncsi_dev_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) 	list_del_rcu(&ndp->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) 	spin_unlock_irqrestore(&ncsi_dev_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) 	kfree(ndp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) EXPORT_SYMBOL_GPL(ncsi_unregister_dev);