| .. | .. |
|---|
| 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 | } |
|---|