1From b19111bb23044c9312d13e64dd1df2a9565f6b38 Mon Sep 17 00:00:00 2001
2From: Artem Senichev <a.senichev@yadro.com>
3Date: Wed, 12 Feb 2020 14:05:15 +0300
4Subject: [PATCH] Add NCSI channel selector
5
6NCSI channel number is selected depending on GPIO state of a pin
7described in the device tree (gpio/nsci_cfg node).
8Currently, this pin is controlled via MCU, and its state represents
9Nicole's physical position inside a fabric.
10
11Channel selector scheme:
12* GPIO pin value is 0: channel 0;
13* GPIO pin value is 1: channel 1;
14* invalid configuration or error: channel 0.
15
16After changing pin's state it is necessary to reboot the BMC to apply
17new channel number.
18
19Signed-off-by: Artem Senichev <a.senichev@yadro.com>
20---
21 net/ncsi/ncsi-rsp.c | 80 ++++++++++++++++++++++++++++++++++++++++++++-
22 1 file changed, 79 insertions(+), 1 deletion(-)
23
24diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
25index d876bd55f356..d211a7e64b14 100644
26--- a/net/ncsi/ncsi-rsp.c
27+++ b/net/ncsi/ncsi-rsp.c
28@@ -9,6 +9,9 @@
29 #include <linux/netdevice.h>
30 #include <linux/etherdevice.h>
31 #include <linux/skbuff.h>
32+#include <linux/of.h>
33+#include <linux/gpio.h>
34+#include <linux/gpio/consumer.h>
35
36 #include <net/ncsi.h>
37 #include <net/net_namespace.h>
38@@ -19,6 +22,81 @@
39 #include "ncsi-pkt.h"
40 #include "ncsi-netlink.h"
41
42+/* NSCI channel number, used as default in case of errors. */
43+#define NCSI_DEFAULT_CHANNEL 0
44+
45+/* Predicate for gpiochip_find() call. */
46+static int device_match(struct gpio_chip* chip, void* data)
47+{
48+	const struct device_node *node = data;
49+	return chip->of_node == node;
50+}
51+
52+/**
53+ * ncsi_select_channel() - Get channel number for NCSI.
54+ * @dev: Network device.
55+ *
56+ * NCSI channel number is selected depending on GPIO state of a pin
57+ * described in the device tree (gpio/nsci_cfg node).
58+ *
59+ * Return: channel number.
60+ */
61+static int ncsi_select_channel(const struct net_device* dev)
62+{
63+	static int channel_id = -1;
64+	struct device_node* node = NULL;
65+
66+	while (channel_id < 0) {
67+		struct gpio_chip* chip;
68+		const struct gpio_desc* desc;
69+		u32 pin;
70+		int rc;
71+
72+		/* Read NCSI configuration node from device tree */
73+		node = of_find_node_by_name(NULL, "ncsi_cfg");
74+		if (!node) {
75+			netdev_err(dev, "NCSI: Configuration node not found\n");
76+			break;
77+		}
78+
79+		/* Read GPIO pin configuration */
80+		rc = of_property_read_u32_index(node, "gpios", 0, &pin);
81+		if (rc) {
82+			netdev_err(dev, "NCSI: GPIO configuration not found\n");
83+			break;
84+		}
85+
86+		/* Find GPIO chip */
87+		chip = gpiochip_find(node->parent, device_match);
88+		if (!chip) {
89+			netdev_err(dev, "NCSI: GPIO chip not found\n");
90+			break;
91+		}
92+
93+		/* Read GPIO state */
94+		desc = gpio_to_desc(chip->base + pin);
95+		if (!desc) {
96+			netdev_err(dev, "NCSI: Cannot get GPIO descriptor\n");
97+			break;
98+		}
99+		channel_id = gpiod_get_value(desc);
100+		if (channel_id < 0) {
101+			netdev_err(dev, "NCSI: GPIO read error %d\n", channel_id);
102+		}
103+		break;
104+	}
105+
106+	if (node) {
107+		of_node_put(node);
108+	}
109+	if (channel_id < 0) {
110+		channel_id = NCSI_DEFAULT_CHANNEL;
111+	}
112+	netdev_info(dev, "NCSI: Set channel %d\n", channel_id);
113+
114+	return channel_id;
115+}
116+
117 static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
118 				 unsigned short payload)
119 {
120@@ -87,7 +165,7 @@ static int ncsi_rsp_handler_cis(struct ncsi_request *nr)
121 		if (ndp->flags & NCSI_DEV_PROBED)
122 			return -ENXIO;
123
124-		id = NCSI_CHANNEL_INDEX(rsp->rsp.common.channel);
125+		id = ncsi_select_channel(ndp->ndev.dev);
126 		nc = ncsi_add_channel(np, id);
127 	}
128
129--
1302.25.0
131
132