blob: fee0e869d272ad5966eb01415b7656302ca881cf [file] [log] [blame]
Neale Ranns812ed392017-10-16 04:20:13 -07001/*
2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "vom/hw.hpp"
Neale Ranns9ef1c0a2017-11-03 04:39:05 -070017#include "vom/hw_cmds.hpp"
Neale Ranns812ed392017-10-16 04:20:13 -070018#include "vom/logger.hpp"
19
Neale Ranns812ed392017-10-16 04:20:13 -070020namespace VOM {
21HW::cmd_q::cmd_q()
22 : m_enabled(true)
23 , m_connected(false)
24 , m_conn()
25{
26}
27
28HW::cmd_q::~cmd_q()
29{
30 m_connected = false;
31
32 if (m_rx_thread && m_rx_thread->joinable()) {
33 m_rx_thread->join();
34 }
35}
36
37HW::cmd_q&
38HW::cmd_q::operator=(const HW::cmd_q& f)
39{
40 return (*this);
41}
42
43/**
44 * Run the connect/dispatch thread.
45 */
46void
47HW::cmd_q::rx_run()
48{
49 while (m_connected) {
50 m_conn.ctx().dispatch();
51 }
52}
53
54void
55HW::cmd_q::enqueue(cmd* c)
56{
57 std::shared_ptr<cmd> sp(c);
58
59 m_queue.push_back(sp);
60}
61
62void
63HW::cmd_q::enqueue(std::shared_ptr<cmd> c)
64{
65 m_queue.push_back(c);
66}
67
68void
69HW::cmd_q::enqueue(std::queue<cmd*>& cmds)
70{
71 while (cmds.size()) {
72 std::shared_ptr<cmd> sp(cmds.front());
73
74 m_queue.push_back(sp);
75 cmds.pop();
76 }
77}
78
79void
80HW::cmd_q::dequeue(cmd* c)
81{
82 c->retire(m_conn);
83 m_pending.erase(c);
84}
85
86void
87HW::cmd_q::dequeue(std::shared_ptr<cmd> c)
88{
89 c->retire(m_conn);
90 m_pending.erase(c.get());
91}
92
93void
94HW::cmd_q::connect()
95{
96 if (m_connected) {
97 m_conn.disconnect();
98 }
99
100 m_connected = false;
101
102 if (m_rx_thread && m_rx_thread->joinable()) {
103 m_rx_thread->join();
104 }
105
106 m_conn.connect();
107
108 m_connected = true;
109 m_rx_thread.reset(new std::thread(&HW::cmd_q::rx_run, this));
110}
111
112void
113HW::cmd_q::enable()
114{
115 m_enabled = true;
116}
117
118void
119HW::cmd_q::disable()
120{
121 m_enabled = false;
122}
123
124rc_t
125HW::cmd_q::write()
126{
127 rc_t rc = rc_t::OK;
128
129 /*
130 * The queue is enabled, Execute each command in the queue.
131 * If one execution fails, abort the rest
132 */
133 auto it = m_queue.begin();
134
135 while (it != m_queue.end()) {
136 std::shared_ptr<cmd> c = *it;
137
138 VOM_LOG(log_level_t::DEBUG) << *c;
139
140 if (m_enabled) {
141 /*
142 * before we issue the command we must move it to the pending
143 * store
144 * ince a async event can be recieved before the command
145 * completes
146 */
147 m_pending[c.get()] = c;
148
149 rc = c->issue(m_conn);
150
151 if (rc_t::INPROGRESS == rc) {
152 /*
153 * this command completes asynchronously
154 * leave the command in the pending store
155 */
156 } else {
157 /*
158 * the command completed, remove from the pending store
159 */
160 m_pending.erase(c.get());
161
162 if (rc_t::OK == rc) {
163 /*
164 * move to the next
165 */
166 } else {
167 /*
168 * barf out without issuing the rest
169 */
170 break;
171 }
172 }
173 } else {
174 /*
175 * The HW is disabled, so set each command as succeeded
176 */
177 c->succeeded();
178 }
179
180 ++it;
181 }
182
183 /*
184 * erase all objects in the queue
185 */
186 m_queue.erase(m_queue.begin(), m_queue.end());
187
188 return (rc);
189}
190
191/*
192 * The single Command Queue
193 */
194HW::cmd_q* HW::m_cmdQ;
195HW::item<bool> HW::m_poll_state;
196
197/**
198 * Initialse the connection to VPP
199 */
200void
201HW::init(HW::cmd_q* f)
202{
203 m_cmdQ = f;
204}
205
206/**
207 * Initialse the connection to VPP
208 */
209void
210HW::init()
211{
212 m_cmdQ = new cmd_q();
213}
214
215void
216HW::enqueue(cmd* cmd)
217{
218 m_cmdQ->enqueue(cmd);
219}
220
221void
222HW::enqueue(std::shared_ptr<cmd> cmd)
223{
224 m_cmdQ->enqueue(cmd);
225}
226
227void
228HW::enqueue(std::queue<cmd*>& cmds)
229{
230 m_cmdQ->enqueue(cmds);
231}
232
233void
234HW::dequeue(cmd* cmd)
235{
236 m_cmdQ->dequeue(cmd);
237}
238
239void
240HW::dequeue(std::shared_ptr<cmd> cmd)
241{
242 m_cmdQ->dequeue(cmd);
243}
244
245void
246HW::connect()
247{
248 m_cmdQ->connect();
249}
250
251void
252HW::enable()
253{
254 m_cmdQ->enable();
255}
256
257void
258HW::disable()
259{
260 m_cmdQ->disable();
261}
262
263rc_t
264HW::write()
265{
266 return (m_cmdQ->write());
267}
268
269bool
270HW::poll()
271{
Neale Ranns9ef1c0a2017-11-03 04:39:05 -0700272 std::shared_ptr<cmd> poll(new hw_cmds::poll(m_poll_state));
Neale Ranns812ed392017-10-16 04:20:13 -0700273
274 HW::enqueue(poll);
275 HW::write();
276
277 return (m_poll_state);
Neale Ranns9ef1c0a2017-11-03 04:39:05 -0700278 return (true);
Neale Ranns812ed392017-10-16 04:20:13 -0700279}
280
281template <>
282std::string
283HW::item<bool>::to_string() const
284{
285 std::ostringstream os;
286
287 os << "hw-item:["
288 << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
289 return (os.str());
290}
291
292template <>
293std::string
294HW::item<unsigned int>::to_string() const
295{
296 std::ostringstream os;
297
298 os << "hw-item:["
299 << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
300 return (os.str());
301}
Neale Ranns812ed392017-10-16 04:20:13 -0700302}
303
304/*
305 * fd.io coding-style-patch-verification: ON
306 *
307 * Local Variables:
308 * eval: (c-set-style "mozilla")
309 * End:
310 */