blob: b58451fd51083ab05e010182741a2388ae3ae8e2 [file] [log] [blame]
Tushar Mathur66506542014-04-03 22:01:40 +05301/*
2 **************************************************************************
Stephen Wang3e2dbd12018-03-14 17:28:17 -07003 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
Tushar Mathur66506542014-04-03 22:01:40 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
17/*
18 * nss_tx_rx_lag.c
19 * NSS LAG Tx APIs
20 */
21
22#include <linux/if_bonding.h>
23
24#include "nss_tx_rx_common.h"
Sachin Shashidhar384d2aa2018-08-06 19:27:55 -070025#include "nss_lag_log.h"
Tushar Mathur66506542014-04-03 22:01:40 +053026
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +053027#define NSS_LAG_RESP_TIMEOUT 60000 /* 60 Sec */
28
29/*
30 * Private data structure of dynamic interface
31 */
32struct nss_lag_pvt {
33 struct completion complete; /* completion structure */
34 enum nss_cmn_response response; /* Message response */
35};
36
37/*
38 * nss_lag_state_callback()
39 * Call back function for nss LAG State
40 */
41void nss_lag_state_callback(void *arg, struct nss_lag_msg *nm)
42{
43 struct nss_lag_pvt *lag_msg_state = arg;
44
45 /*
46 * Unblock the sleeping function.
47 */
48 lag_msg_state->response = nm->cm.response;
49 complete(&lag_msg_state->complete);
50}
51
52/*
53 * nss_lag_verify_ifnum()
54 *
55 */
56static void nss_lag_verify_ifnum(uint32_t if_num)
57{
58 nss_assert((if_num == NSS_LAG0_INTERFACE_NUM) ||
59 (if_num == NSS_LAG1_INTERFACE_NUM) ||
60 (if_num == NSS_LAG2_INTERFACE_NUM) ||
61 (if_num == NSS_LAG3_INTERFACE_NUM));
62}
63
64/*
65 * nss_lag_get_context()
66 */
67static struct nss_ctx_instance *nss_lag_get_context(void)
68{
69 uint8_t ipv4_handler_id = nss_top_main.ipv4_handler_id;
70
71 return (struct nss_ctx_instance *)&nss_top_main.nss[ipv4_handler_id];
72}
73
Tushar Mathur66506542014-04-03 22:01:40 +053074/*
75 * nss_lag_tx()
Sol Kavycd1bd5c2014-04-04 11:09:44 -070076 * Transmit a LAG msg to the firmware.
Tushar Mathur66506542014-04-03 22:01:40 +053077 */
78nss_tx_status_t nss_lag_tx(struct nss_ctx_instance *nss_ctx, struct nss_lag_msg *msg)
79{
Stephen Wang3e2dbd12018-03-14 17:28:17 -070080 struct nss_cmn_msg *ncm = &msg->cm;
Tushar Mathur66506542014-04-03 22:01:40 +053081
Stephen Wang3e2dbd12018-03-14 17:28:17 -070082 /*
Sachin Shashidhar384d2aa2018-08-06 19:27:55 -070083 * Trace Messages
84 */
85 nss_lag_log_tx_msg(msg);
86
87 /*
Stephen Wang3e2dbd12018-03-14 17:28:17 -070088 * Sanity check the message
89 */
90 nss_lag_verify_ifnum(ncm->interface);
Tushar Mathur66506542014-04-03 22:01:40 +053091
Stephen Wang3e2dbd12018-03-14 17:28:17 -070092 if (ncm->type > NSS_TX_METADATA_LAG_MAX) {
93 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
Tushar Mathur66506542014-04-03 22:01:40 +053094 return NSS_TX_FAILURE;
95 }
96
Stephen Wang3e2dbd12018-03-14 17:28:17 -070097 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
Tushar Mathur66506542014-04-03 22:01:40 +053098}
99EXPORT_SYMBOL(nss_lag_tx);
Tushar Mathura3e03052014-04-07 20:17:28 +0530100
101/**
102 * nss_register_lag_if()
103 */
Gareth Williamsb52af512014-04-25 19:31:15 +0100104void *nss_register_lag_if(uint32_t if_num,
Tushar Mathura3e03052014-04-07 20:17:28 +0530105 nss_lag_callback_t lag_cb,
106 nss_lag_event_callback_t lag_ev_cb,
107 struct net_device *netdev)
108{
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +0530109 struct nss_ctx_instance *nss_ctx = nss_lag_get_context();
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800110 uint32_t features = 0;
111
Stephen Wang84e0e992016-09-07 12:31:40 -0700112 nss_assert(nss_ctx);
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +0530113 nss_lag_verify_ifnum(if_num);
Tushar Mathura3e03052014-04-07 20:17:28 +0530114
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700115 nss_core_register_subsys_dp(nss_ctx, if_num, lag_cb, NULL, NULL, netdev, features);
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800116
Tushar Mathura3e03052014-04-07 20:17:28 +0530117 nss_top_main.lag_event_callback = lag_ev_cb;
Gareth Williamsb52af512014-04-25 19:31:15 +0100118
119 /*
120 * Return the NSS driver context for LAG (same as for ipv4 functions)
121 */
Stephen Wang84e0e992016-09-07 12:31:40 -0700122 return (void *)nss_ctx;
Tushar Mathura3e03052014-04-07 20:17:28 +0530123}
124EXPORT_SYMBOL(nss_register_lag_if);
125
126
127/**
128 * nss_unregister_lag_if()
129 */
130void nss_unregister_lag_if(uint32_t if_num)
131{
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +0530132 struct nss_ctx_instance *nss_ctx = nss_lag_get_context();
Stephen Wang84e0e992016-09-07 12:31:40 -0700133
134 nss_assert(nss_ctx);
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +0530135 nss_lag_verify_ifnum(if_num);
Tushar Mathura3e03052014-04-07 20:17:28 +0530136
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700137 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800138
Tushar Mathura3e03052014-04-07 20:17:28 +0530139 nss_top_main.lag_event_callback = NULL;
140}
141EXPORT_SYMBOL(nss_unregister_lag_if);
142
143
144/**
145 * nss_lag_handler()
146 */
147void nss_lag_handler(struct nss_ctx_instance *nss_ctx,
148 struct nss_cmn_msg *ncm,
149 void *app_data)
150{
151 struct nss_lag_msg *lm = (struct nss_lag_msg *)ncm;
152 void *ctx = NULL;
153 nss_lag_event_callback_t cb;
154
155 BUG_ON(ncm->interface != NSS_LAG0_INTERFACE_NUM
Suman Ghoshcf8ed1c2015-09-07 18:57:04 +0530156 && ncm->interface != NSS_LAG1_INTERFACE_NUM
157 && ncm->interface != NSS_LAG2_INTERFACE_NUM
158 && ncm->interface != NSS_LAG3_INTERFACE_NUM);
Tushar Mathura3e03052014-04-07 20:17:28 +0530159
Sachin Shashidhar384d2aa2018-08-06 19:27:55 -0700160 /*
161 * Trace Messages
162 */
163 nss_lag_log_rx_msg(lm);
164
Tushar Mathura3e03052014-04-07 20:17:28 +0530165 if (ncm->type >= NSS_TX_METADATA_LAG_MAX) {
166 nss_warning("%p: received invalid message %d for LAG interface", nss_ctx, ncm->type);
167 return;
168 }
169
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800170 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_lag_msg)) {
171 nss_warning("%p: invalid length for LAG message: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Tushar Mathura3e03052014-04-07 20:17:28 +0530172 return;
173 }
174
175 /**
176 * Update the callback and app_data for NOTIFY messages.
177 * LAG sends all notify messages to the same callback.
178 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530179 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Stephen Wangaed46332016-12-12 17:29:03 -0800180 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->lag_event_callback;
Tushar Mathura3e03052014-04-07 20:17:28 +0530181 }
182
183 /**
184 * Log failures
185 */
186 nss_core_log_msg_failures(nss_ctx, ncm);
187
188 /**
189 * Do we have a call back
190 */
191 if (!ncm->cb) {
192 return;
193 }
194
195 /**
196 * callback
197 */
198 cb = (nss_lag_event_callback_t)ncm->cb;
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +0530199 ctx = (void *)ncm->app_data;
Tushar Mathura3e03052014-04-07 20:17:28 +0530200
201 cb(ctx, lm);
202}
203
204
205/**
206 * nss_lag_register_handler()
207 */
208void nss_lag_register_handler(void)
209{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700210 struct nss_ctx_instance *nss_ctx = nss_lag_get_context();
211
212 nss_core_register_handler(nss_ctx, NSS_LAG0_INTERFACE_NUM, nss_lag_handler, NULL);
213 nss_core_register_handler(nss_ctx, NSS_LAG1_INTERFACE_NUM, nss_lag_handler, NULL);
214 nss_core_register_handler(nss_ctx, NSS_LAG2_INTERFACE_NUM, nss_lag_handler, NULL);
215 nss_core_register_handler(nss_ctx, NSS_LAG3_INTERFACE_NUM, nss_lag_handler, NULL);
Tushar Mathura3e03052014-04-07 20:17:28 +0530216}
217
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700218/**
219 * nss_lag_msg_init()
220 * Initialize lag message
221 */
222void nss_lag_msg_init(struct nss_lag_msg *nlm, uint16_t lag_num, uint32_t type, uint32_t len,
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +0530223 nss_lag_msg_callback_t cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700224{
225 nss_cmn_msg_init(&nlm->cm, lag_num, type, len, (void *)cb, app_data);
226}
227EXPORT_SYMBOL(nss_lag_msg_init);
Bhaskar Valaboju76988ef2017-02-20 19:51:49 +0530228
229/**
230 * nss_lag_tx_slave_state()
231 */
232nss_tx_status_t nss_lag_tx_slave_state(uint16_t lagid, int32_t slave_ifnum,
233 enum nss_lag_state_change_ev slave_state)
234{
235 struct nss_lag_msg nm;
236 struct nss_lag_state_change *nlsc = NULL;
237 nss_tx_status_t status;
238 int ret;
239 struct nss_ctx_instance *nss_ctx = nss_lag_get_context();
240 struct nss_lag_pvt lag_msg_state;
241
242 init_completion(&lag_msg_state.complete);
243 lag_msg_state.response = false;
244
245 /*
246 * Construct a message to the NSS to update it
247 */
248 nss_lag_msg_init(&nm, lagid,
249 NSS_TX_METADATA_LAG_STATE_CHANGE,
250 sizeof(struct nss_lag_state_change),
251 nss_lag_state_callback, &lag_msg_state);
252
253 nlsc = &nm.msg.state;
254 nlsc->event = slave_state;
255 nlsc->interface = slave_ifnum;
256
257 status = nss_lag_tx(nss_ctx, &nm);
258 if (status != NSS_TX_SUCCESS) {
259 nss_warning("%p: Send LAG update failed, status: %d\n", nss_ctx,
260 status);
261 return NSS_TX_FAILURE;
262 }
263
264 /*
265 * Blocking call, wait till we get ACK for this msg.
266 */
267 ret = wait_for_completion_timeout(&lag_msg_state.complete,
268 msecs_to_jiffies(NSS_LAG_RESP_TIMEOUT));
269 if (!ret) {
270 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
271 return NSS_TX_FAILURE;
272 }
273
274 return lag_msg_state.response;
275}
276EXPORT_SYMBOL(nss_lag_tx_slave_state);