.. | .. |
---|
1 | | -/* |
---|
2 | | - * aQuantia Corporation Network Driver |
---|
3 | | - * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
| 2 | +/* Atlantic Network Driver |
---|
4 | 3 | * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
| 4 | + * Copyright (C) 2014-2019 aQuantia Corporation |
---|
| 5 | + * Copyright (C) 2019-2020 Marvell International Ltd. |
---|
8 | 6 | */ |
---|
9 | 7 | |
---|
10 | 8 | /* File aq_vec.c: Definition of common structure for vector of Rx and Tx rings. |
---|
.. | .. |
---|
45 | 43 | if (!self) { |
---|
46 | 44 | err = -EINVAL; |
---|
47 | 45 | } else { |
---|
48 | | - for (i = 0U, ring = self->ring[0]; |
---|
49 | | - self->tx_rings > i; ++i, ring = self->ring[i]) { |
---|
| 46 | + for (i = 0U; self->tx_rings > i; ++i) { |
---|
| 47 | + ring = self->ring[i]; |
---|
| 48 | + u64_stats_update_begin(&ring[AQ_VEC_RX_ID].stats.rx.syncp); |
---|
| 49 | + ring[AQ_VEC_RX_ID].stats.rx.polls++; |
---|
| 50 | + u64_stats_update_end(&ring[AQ_VEC_RX_ID].stats.rx.syncp); |
---|
50 | 51 | if (self->aq_hw_ops->hw_ring_tx_head_update) { |
---|
51 | 52 | err = self->aq_hw_ops->hw_ring_tx_head_update( |
---|
52 | 53 | self->aq_hw, |
---|
.. | .. |
---|
107 | 108 | struct aq_nic_cfg_s *aq_nic_cfg) |
---|
108 | 109 | { |
---|
109 | 110 | struct aq_vec_s *self = NULL; |
---|
110 | | - struct aq_ring_s *ring = NULL; |
---|
111 | | - unsigned int i = 0U; |
---|
112 | | - int err = 0; |
---|
113 | 111 | |
---|
114 | 112 | self = kzalloc(sizeof(*self), GFP_KERNEL); |
---|
115 | | - if (!self) { |
---|
116 | | - err = -ENOMEM; |
---|
| 113 | + if (!self) |
---|
117 | 114 | goto err_exit; |
---|
118 | | - } |
---|
119 | 115 | |
---|
120 | 116 | self->aq_nic = aq_nic; |
---|
121 | 117 | self->aq_ring_param.vec_idx = idx; |
---|
.. | .. |
---|
131 | 127 | netif_napi_add(aq_nic_get_ndev(aq_nic), &self->napi, |
---|
132 | 128 | aq_vec_poll, AQ_CFG_NAPI_WEIGHT); |
---|
133 | 129 | |
---|
| 130 | +err_exit: |
---|
| 131 | + return self; |
---|
| 132 | +} |
---|
| 133 | + |
---|
| 134 | +int aq_vec_ring_alloc(struct aq_vec_s *self, struct aq_nic_s *aq_nic, |
---|
| 135 | + unsigned int idx, struct aq_nic_cfg_s *aq_nic_cfg) |
---|
| 136 | +{ |
---|
| 137 | + struct aq_ring_s *ring = NULL; |
---|
| 138 | + unsigned int i = 0U; |
---|
| 139 | + int err = 0; |
---|
| 140 | + |
---|
134 | 141 | for (i = 0; i < aq_nic_cfg->tcs; ++i) { |
---|
135 | | - unsigned int idx_ring = AQ_NIC_TCVEC2RING(self->nic, |
---|
136 | | - self->tx_rings, |
---|
137 | | - self->aq_ring_param.vec_idx); |
---|
| 142 | + const unsigned int idx_ring = AQ_NIC_CFG_TCVEC2RING(aq_nic_cfg, |
---|
| 143 | + i, idx); |
---|
138 | 144 | |
---|
139 | 145 | ring = aq_ring_tx_alloc(&self->ring[i][AQ_VEC_TX_ID], aq_nic, |
---|
140 | 146 | idx_ring, aq_nic_cfg); |
---|
.. | .. |
---|
159 | 165 | |
---|
160 | 166 | err_exit: |
---|
161 | 167 | if (err < 0) { |
---|
162 | | - aq_vec_free(self); |
---|
| 168 | + aq_vec_ring_free(self); |
---|
163 | 169 | self = NULL; |
---|
164 | 170 | } |
---|
165 | | - return self; |
---|
| 171 | + |
---|
| 172 | + return err; |
---|
166 | 173 | } |
---|
167 | 174 | |
---|
168 | 175 | int aq_vec_init(struct aq_vec_s *self, const struct aq_hw_ops *aq_hw_ops, |
---|
.. | .. |
---|
175 | 182 | self->aq_hw_ops = aq_hw_ops; |
---|
176 | 183 | self->aq_hw = aq_hw; |
---|
177 | 184 | |
---|
178 | | - for (i = 0U, ring = self->ring[0]; |
---|
179 | | - self->tx_rings > i; ++i, ring = self->ring[i]) { |
---|
180 | | - err = aq_ring_init(&ring[AQ_VEC_TX_ID]); |
---|
| 185 | + for (i = 0U; self->tx_rings > i; ++i) { |
---|
| 186 | + ring = self->ring[i]; |
---|
| 187 | + err = aq_ring_init(&ring[AQ_VEC_TX_ID], ATL_RING_TX); |
---|
181 | 188 | if (err < 0) |
---|
182 | 189 | goto err_exit; |
---|
183 | 190 | |
---|
.. | .. |
---|
187 | 194 | if (err < 0) |
---|
188 | 195 | goto err_exit; |
---|
189 | 196 | |
---|
190 | | - err = aq_ring_init(&ring[AQ_VEC_RX_ID]); |
---|
| 197 | + err = aq_ring_init(&ring[AQ_VEC_RX_ID], ATL_RING_RX); |
---|
191 | 198 | if (err < 0) |
---|
192 | 199 | goto err_exit; |
---|
193 | 200 | |
---|
.. | .. |
---|
217 | 224 | unsigned int i = 0U; |
---|
218 | 225 | int err = 0; |
---|
219 | 226 | |
---|
220 | | - for (i = 0U, ring = self->ring[0]; |
---|
221 | | - self->tx_rings > i; ++i, ring = self->ring[i]) { |
---|
| 227 | + for (i = 0U; self->tx_rings > i; ++i) { |
---|
| 228 | + ring = self->ring[i]; |
---|
222 | 229 | err = self->aq_hw_ops->hw_ring_tx_start(self->aq_hw, |
---|
223 | 230 | &ring[AQ_VEC_TX_ID]); |
---|
224 | 231 | if (err < 0) |
---|
.. | .. |
---|
241 | 248 | struct aq_ring_s *ring = NULL; |
---|
242 | 249 | unsigned int i = 0U; |
---|
243 | 250 | |
---|
244 | | - for (i = 0U, ring = self->ring[0]; |
---|
245 | | - self->tx_rings > i; ++i, ring = self->ring[i]) { |
---|
| 251 | + for (i = 0U; self->tx_rings > i; ++i) { |
---|
| 252 | + ring = self->ring[i]; |
---|
246 | 253 | self->aq_hw_ops->hw_ring_tx_stop(self->aq_hw, |
---|
247 | 254 | &ring[AQ_VEC_TX_ID]); |
---|
248 | 255 | |
---|
.. | .. |
---|
261 | 268 | if (!self) |
---|
262 | 269 | goto err_exit; |
---|
263 | 270 | |
---|
264 | | - for (i = 0U, ring = self->ring[0]; |
---|
265 | | - self->tx_rings > i; ++i, ring = self->ring[i]) { |
---|
| 271 | + for (i = 0U; self->tx_rings > i; ++i) { |
---|
| 272 | + ring = self->ring[i]; |
---|
266 | 273 | aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]); |
---|
267 | 274 | aq_ring_rx_deinit(&ring[AQ_VEC_RX_ID]); |
---|
268 | 275 | } |
---|
| 276 | + |
---|
269 | 277 | err_exit:; |
---|
270 | 278 | } |
---|
271 | 279 | |
---|
272 | 280 | void aq_vec_free(struct aq_vec_s *self) |
---|
| 281 | +{ |
---|
| 282 | + if (!self) |
---|
| 283 | + goto err_exit; |
---|
| 284 | + |
---|
| 285 | + netif_napi_del(&self->napi); |
---|
| 286 | + |
---|
| 287 | + kfree(self); |
---|
| 288 | + |
---|
| 289 | +err_exit:; |
---|
| 290 | +} |
---|
| 291 | + |
---|
| 292 | +void aq_vec_ring_free(struct aq_vec_s *self) |
---|
273 | 293 | { |
---|
274 | 294 | struct aq_ring_s *ring = NULL; |
---|
275 | 295 | unsigned int i = 0U; |
---|
.. | .. |
---|
277 | 297 | if (!self) |
---|
278 | 298 | goto err_exit; |
---|
279 | 299 | |
---|
280 | | - for (i = 0U, ring = self->ring[0]; |
---|
281 | | - self->tx_rings > i; ++i, ring = self->ring[i]) { |
---|
| 300 | + for (i = 0U; self->tx_rings > i; ++i) { |
---|
| 301 | + ring = self->ring[i]; |
---|
282 | 302 | aq_ring_free(&ring[AQ_VEC_TX_ID]); |
---|
283 | | - aq_ring_free(&ring[AQ_VEC_RX_ID]); |
---|
| 303 | + if (i < self->rx_rings) |
---|
| 304 | + aq_ring_free(&ring[AQ_VEC_RX_ID]); |
---|
284 | 305 | } |
---|
285 | 306 | |
---|
286 | | - netif_napi_del(&self->napi); |
---|
287 | | - |
---|
288 | | - kfree(self); |
---|
289 | | - |
---|
| 307 | + self->tx_rings = 0; |
---|
| 308 | + self->rx_rings = 0; |
---|
290 | 309 | err_exit:; |
---|
291 | 310 | } |
---|
292 | 311 | |
---|
.. | .. |
---|
334 | 353 | return &self->aq_ring_param.affinity_mask; |
---|
335 | 354 | } |
---|
336 | 355 | |
---|
337 | | -void aq_vec_add_stats(struct aq_vec_s *self, |
---|
338 | | - struct aq_ring_stats_rx_s *stats_rx, |
---|
339 | | - struct aq_ring_stats_tx_s *stats_tx) |
---|
| 356 | +bool aq_vec_is_valid_tc(struct aq_vec_s *self, const unsigned int tc) |
---|
340 | 357 | { |
---|
341 | | - struct aq_ring_s *ring = NULL; |
---|
342 | | - unsigned int r = 0U; |
---|
343 | | - |
---|
344 | | - for (r = 0U, ring = self->ring[0]; |
---|
345 | | - self->tx_rings > r; ++r, ring = self->ring[r]) { |
---|
346 | | - struct aq_ring_stats_tx_s *tx = &ring[AQ_VEC_TX_ID].stats.tx; |
---|
347 | | - struct aq_ring_stats_rx_s *rx = &ring[AQ_VEC_RX_ID].stats.rx; |
---|
348 | | - |
---|
349 | | - stats_rx->packets += rx->packets; |
---|
350 | | - stats_rx->bytes += rx->bytes; |
---|
351 | | - stats_rx->errors += rx->errors; |
---|
352 | | - stats_rx->jumbo_packets += rx->jumbo_packets; |
---|
353 | | - stats_rx->lro_packets += rx->lro_packets; |
---|
354 | | - |
---|
355 | | - stats_tx->packets += tx->packets; |
---|
356 | | - stats_tx->bytes += tx->bytes; |
---|
357 | | - stats_tx->errors += tx->errors; |
---|
358 | | - stats_tx->queue_restarts += tx->queue_restarts; |
---|
359 | | - } |
---|
| 358 | + return tc < self->rx_rings && tc < self->tx_rings; |
---|
360 | 359 | } |
---|
361 | 360 | |
---|
362 | | -int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count) |
---|
| 361 | +unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u64 *data) |
---|
363 | 362 | { |
---|
364 | | - unsigned int count = 0U; |
---|
365 | | - struct aq_ring_stats_rx_s stats_rx; |
---|
366 | | - struct aq_ring_stats_tx_s stats_tx; |
---|
| 363 | + unsigned int count; |
---|
367 | 364 | |
---|
368 | | - memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); |
---|
369 | | - memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); |
---|
370 | | - aq_vec_add_stats(self, &stats_rx, &stats_tx); |
---|
| 365 | + if (!aq_vec_is_valid_tc(self, tc)) |
---|
| 366 | + return 0; |
---|
371 | 367 | |
---|
372 | | - /* This data should mimic aq_ethtool_queue_stat_names structure |
---|
373 | | - */ |
---|
374 | | - data[count] += stats_rx.packets; |
---|
375 | | - data[++count] += stats_tx.packets; |
---|
376 | | - data[++count] += stats_tx.queue_restarts; |
---|
377 | | - data[++count] += stats_rx.jumbo_packets; |
---|
378 | | - data[++count] += stats_rx.lro_packets; |
---|
379 | | - data[++count] += stats_rx.errors; |
---|
| 368 | + count = aq_ring_fill_stats_data(&self->ring[tc][AQ_VEC_RX_ID], data); |
---|
| 369 | + count += aq_ring_fill_stats_data(&self->ring[tc][AQ_VEC_TX_ID], data + count); |
---|
380 | 370 | |
---|
381 | | - if (p_count) |
---|
382 | | - *p_count = ++count; |
---|
383 | | - |
---|
384 | | - return 0; |
---|
| 371 | + return count; |
---|
385 | 372 | } |
---|