blob: c00c9baf72da897c2a5ca6c736d743ab677a1bd4 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:proprietary:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7This program is the proprietary software of Broadcom Corporation and/or its
8licensors, and may only be used, duplicated, modified or distributed pursuant
9to the terms and conditions of a separate, written license agreement executed
10between you and Broadcom (an "Authorized License"). Except as set forth in
11an Authorized License, Broadcom grants no license (express or implied), right
12to use, or waiver of any kind with respect to the Software, and Broadcom
13expressly reserves all rights in and to the Software and all intellectual
14property rights therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE
15NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY
16BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
17
18Except as expressly set forth in the Authorized License,
19
201. This program, including its structure, sequence and organization,
21 constitutes the valuable trade secrets of Broadcom, and you shall use
22 all reasonable efforts to protect the confidentiality thereof, and to
23 use this information only in connection with your use of Broadcom
24 integrated circuit products.
25
262. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
27 AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
28 WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
29 RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND
30 ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT,
31 FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
32 COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE
33 TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF USE OR
34 PERFORMANCE OF THE SOFTWARE.
35
363. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR
37 ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL,
38 INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY
39 WAY RELATING TO YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN
40 IF BROADCOM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES;
41 OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE
42 SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE LIMITATIONS
43 SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY
44 LIMITED REMEDY.
45:>
46*/
47/*
48 * bcmtr_plugin_direct.c
49 *
50 * This plugin
51 * - TX: forwards messages to trmux
52 * - RX: waits on rx task's message queue
53 */
54
55#include <bcmos_system.h>
56
57#include <bcmtr_plugin.h>
58#include <bcm_config.h>
59#include <bcmolt_tr_mux.h>
60
61/* Receive OS message pool and queue */
62static bcmos_msg_pool bcmtr_rx_msg_pool[BCMTR_MAX_OLTS];
63static bcmos_msg_queue bcmtr_rxq[BCMTR_MAX_OLTS];
64
65/* Flags indicating init progress */
66static bcmos_bool rx_pool_created[BCMTR_MAX_OLTS];
67static bcmos_bool rxq_created[BCMTR_MAX_OLTS];
68static void _bcmtr_direct_rx_from_trmux(bcmolt_devid device, bcmos_buf *buf, bcmtrmux_channel channel, void *data);
69
70/* To resolve symbols in user_appl in band not applicable for VXWorks*/
71void using_inband_set(bcmos_bool using_inband){}
72bcmos_bool using_inband_get(void)
73{
74 return BCMOS_FALSE;
75}
76
77
78/* Transport IPC message data */
79typedef struct bcmtr_ipc_data
80{
81 bcmolt_buf buf; /* Rx buffer */
82 bcmolt_subchannel subch; /* rx channel */
83} bcmtr_ipc_data;
84
85
86/* System --> OLT buffer translation.
87 * system buffer is released in case of success
88 */
89static bcmos_errno bcmtr_sysbuf_to_oltbuf(bcmos_buf *sysb, bcmolt_buf *oltb)
90{
91 bcmos_errno err;
92
93 err = bcmolt_buf_alloc(oltb, bcmos_buf_length(sysb), BCMTR_BUF_ENDIAN);
94 if (err)
95 return err;
96 bcmolt_buf_write(oltb, bcmos_buf_data(sysb), bcmos_buf_length(sysb));
97 bcmos_buf_free(sysb);
98 oltb->curr = oltb->start;
99 return BCM_ERR_OK;
100}
101
102/* OLT buffer --> system buffer translation.
103 * OLT buffer must have headroom for bcmos_buf header
104 */
105static bcmos_buf *bcmtr_oltbuf_to_sysbuf(bcmolt_buf *oltb)
106{
107 bcmos_buf *sysb;
108 uint32_t len = bcmolt_buf_get_used(oltb);
109
110 sysb = bcmos_buf_alloc(len);
111 if (sysb == NULL)
112 return NULL;
113 memcpy(bcmos_buf_data(sysb), oltb->start, len);
114 bcmos_buf_length_set(sysb, len);
115 /* We don't release the original oltb because it is needed for retransmission.
116 * It will be released by the transport layer
117 */
118 return sysb;
119}
120
121/* Release message data */
122static void bcmtr_msg_data_release(bcmos_msg *msg)
123{
124 bcmtr_ipc_data *data = msg->data;
125 bcmolt_buf_free(&data->buf);
126}
127
128/** Close communication channel */
129static bcmos_errno bcmtr_direct_close(bcmtr_plugin_channel ch)
130{
131 bcmolt_devid device = (bcmolt_devid)(ch >> 8);
132 bcmtrmux_channel muxch = (bcmtrmux_channel)(ch & 0xff);
133
134 /* Unregister from TRMUX */
135 bcmtrmux_channel_unregister(device, muxch);
136
137 /* Destroy rx message pool */
138 if (rx_pool_created[device])
139 {
140 bcmos_msg_pool_destroy(&bcmtr_rx_msg_pool[device]);
141 rx_pool_created[device] = BCMOS_FALSE;
142 }
143
144 /* Destroy RX message queue */
145 if (rxq_created[device])
146 {
147 bcmos_msg_queue_destroy(&bcmtr_rxq[device]);
148 rxq_created[device] = BCMOS_FALSE;
149 }
150
151 return BCM_ERR_OK;
152}
153
154/** Open communication channel */
155static bcmos_errno bcmtr_direct_open(int device, bcmtr_plugin_cfg *cfg, bcmtr_plugin_channel *ch)
156{
157 /* The following variables are declared static in order to protect name string */
158 static bcmos_msg_queue_parm msgq_parm = { .name = "tr_rxq"};
159 bcmos_msg_pool_parm msg_pool_parm = {};
160 bcmtrmux_channel mux_channel = BCMTRMUX_CHANNEL_AUTO_ASSIGN;
161 bcmos_errno err;
162
163 /* Direct plugin supports only 1 application instance */
164 if (device >= BCMTR_MAX_OLTS)
165 BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Device %u is out of range\n", device);
166 if (rx_pool_created[device])
167 BCMOS_TRACE_RETURN(BCM_ERR_ALREADY, "Transport is already initialized for device %u\n", device);
168
169 /* Create RX msg pool */
170 msg_pool_parm.size = BCMTR_MAX_RXQ_SIZE; /* <-- Define parameter in bcmtr_config */
171 msg_pool_parm.data_size = sizeof(bcmtr_ipc_data);
172 msg_pool_parm.data_release = bcmtr_msg_data_release;
173 err = bcmos_msg_pool_create(&bcmtr_rx_msg_pool[device], &msg_pool_parm);
174 if (err)
175 BCMOS_TRACE_RETURN(err, "Can't create rx pool\n");
176
177 /* Create RX queue set */
178 err = bcmos_msg_queue_create(&bcmtr_rxq[device], &msgq_parm);
179 if (err)
180 {
181 bcmos_msg_pool_destroy(&bcmtr_rx_msg_pool[device]);
182 BCMOS_TRACE_RETURN(err, "Can't create rxq\n");
183 }
184
185 /* Register with trmux */
186 err = bcmtrmux_channel_register(device, &mux_channel, _bcmtr_direct_rx_from_trmux, (void *)NULL );
187 if (err)
188 {
189 bcmos_msg_pool_destroy(&bcmtr_rx_msg_pool[device]);
190 bcmos_msg_queue_destroy(&bcmtr_rxq[device]);
191 BCMOS_TRACE_RETURN(err, "Can't register with trmux\n");
192 }
193
194 rx_pool_created[device] = BCMOS_TRUE;
195 rxq_created[device] = BCMOS_TRUE;
196 *ch = (bcmtr_plugin_channel)((device << 8) | mux_channel);
197
198 return BCM_ERR_OK;
199}
200
201/** Send data */
202static bcmos_errno bcmtr_direct_send(bcmtr_plugin_channel ch, bcmolt_subchannel subch, bcmolt_buf *buf,
203 bcmtr_send_flags flags)
204{
205 bcmolt_devid device = (bcmolt_devid)(ch >> 8);
206 bcmtrmux_channel muxch = (bcmtrmux_channel)(ch & 0xff);
207 bcmos_buf *sysb;
208
209 /* Do zero-copy conversion from bcmolt_buf --> bcmos_buf. It is possible because room
210 * for bcmos_buf header is reserved in the beginning of bcmolt_buf
211 */
212 sysb = bcmtr_oltbuf_to_sysbuf(buf);
213 if (!sysb)
214 return BCM_ERR_NOMEM;
215 bcmtrmux_rx_from_host(device, muxch, sysb);
216
217 return BCM_ERR_OK;
218}
219
220/* Receive from trmux. Called in trmux context */
221static void _bcmtr_direct_rx_from_trmux(bcmolt_devid device, bcmos_buf *sysb, bcmtrmux_channel channel, void *data)
222{
223 bcmos_msg *msg;
224 bcmtr_ipc_data *ipc_data;
225 bcmos_errno err;
226
227 msg = bcmos_msg_pool_alloc(&bcmtr_rx_msg_pool[device]);
228 if (!msg)
229 {
230 /* <-- add some statistic here */
231 bcmos_buf_free(sysb);
232 return;
233 }
234 ipc_data = msg->data;
235 err = bcmtr_sysbuf_to_oltbuf(sysb, &ipc_data->buf);
236 if (err)
237 {
238 /* <-- add some statistic here */
239 bcmos_buf_free(sysb);
240 bcmos_msg_free(msg);
241 return;
242 }
243 ipc_data->subch = channel;
244 err = bcmos_msg_send(&bcmtr_rxq[device], msg, BCMOS_MSG_SEND_AUTO_FREE);
245 if (err)
246 {
247 /* <-- add some statistic here */
248 }
249}
250
251/** Receive data */
252static bcmos_errno bcmtr_direct_recv(bcmtr_plugin_channel ch, bcmolt_subchannel *subch, bcmolt_buf *buf)
253{
254 bcmolt_devid device = (bcmolt_devid)(ch >> 8);
255 bcmos_msg *msg;
256 bcmtr_ipc_data *data;
257 bcmos_errno err;
258
259 err = bcmos_msg_recv(&bcmtr_rxq[device], BCMTR_MSG_TIMEOUT, &msg);
260 if (err)
261 {
262 if (err != BCM_ERR_TIMEOUT)
263 err = BCM_ERR_COMM_FAIL;
264 return err;
265 }
266
267 data = msg->data;
268 *buf = data->buf;
269 *subch = data->subch;
270 /* Prevent buffer release when releasing OS message */
271 data->buf.start = data->buf.curr = NULL;
272 bcmos_msg_free(msg);
273
274 return BCM_ERR_OK;
275}
276
277/** Initialize plugin callbacks
278 * \param[in,out] driver Transport plugin driver structure
279 * \return error code
280 */
281bcmos_errno bcmtr_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver)
282{
283 driver->open = bcmtr_direct_open;
284 driver->close = bcmtr_direct_close;
285 driver->recv = bcmtr_direct_recv;
286 driver->send = bcmtr_direct_send;
287
288 return BCM_ERR_OK;
289}
290