^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);