1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 3 4 #include <linux/dma-mapping.h> 5 6 #include "ionic_fw.h" 7 #include "ionic_ibdev.h" 8 9 static int ionic_v1_stat_normalize(struct ionic_v1_stat *hw_stats, 10 int hw_stats_count) 11 { 12 int hw_stat_i; 13 14 for (hw_stat_i = 0; hw_stat_i < hw_stats_count; ++hw_stat_i) { 15 struct ionic_v1_stat *stat = &hw_stats[hw_stat_i]; 16 17 stat->type_off = be32_to_cpu(stat->be_type_off); 18 stat->name[sizeof(stat->name) - 1] = 0; 19 if (ionic_v1_stat_type(stat) == IONIC_V1_STAT_TYPE_NONE) 20 break; 21 } 22 23 return hw_stat_i; 24 } 25 26 static void ionic_fill_stats_desc(struct rdma_stat_desc *hw_stats_hdrs, 27 struct ionic_v1_stat *hw_stats, 28 int hw_stats_count) 29 { 30 int hw_stat_i; 31 32 for (hw_stat_i = 0; hw_stat_i < hw_stats_count; ++hw_stat_i) { 33 struct ionic_v1_stat *stat = &hw_stats[hw_stat_i]; 34 35 hw_stats_hdrs[hw_stat_i].name = stat->name; 36 } 37 } 38 39 static u64 ionic_v1_stat_val(struct ionic_v1_stat *stat, 40 void *vals_buf, size_t vals_len) 41 { 42 unsigned int off = ionic_v1_stat_off(stat); 43 int type = ionic_v1_stat_type(stat); 44 45 #define __ionic_v1_stat_validate(__type) \ 46 ((off + sizeof(__type) <= vals_len) && \ 47 (IS_ALIGNED(off, sizeof(__type)))) 48 49 switch (type) { 50 case IONIC_V1_STAT_TYPE_8: 51 if (__ionic_v1_stat_validate(u8)) 52 return *(u8 *)(vals_buf + off); 53 break; 54 case IONIC_V1_STAT_TYPE_LE16: 55 if (__ionic_v1_stat_validate(__le16)) 56 return le16_to_cpu(*(__le16 *)(vals_buf + off)); 57 break; 58 case IONIC_V1_STAT_TYPE_LE32: 59 if (__ionic_v1_stat_validate(__le32)) 60 return le32_to_cpu(*(__le32 *)(vals_buf + off)); 61 break; 62 case IONIC_V1_STAT_TYPE_LE64: 63 if (__ionic_v1_stat_validate(__le64)) 64 return le64_to_cpu(*(__le64 *)(vals_buf + off)); 65 break; 66 case IONIC_V1_STAT_TYPE_BE16: 67 if (__ionic_v1_stat_validate(__be16)) 68 return be16_to_cpu(*(__be16 *)(vals_buf + off)); 69 break; 70 case IONIC_V1_STAT_TYPE_BE32: 71 if (__ionic_v1_stat_validate(__be32)) 72 return be32_to_cpu(*(__be32 *)(vals_buf + off)); 73 break; 74 case IONIC_V1_STAT_TYPE_BE64: 75 if (__ionic_v1_stat_validate(__be64)) 76 return be64_to_cpu(*(__be64 *)(vals_buf + off)); 77 break; 78 } 79 80 return ~0ull; 81 #undef __ionic_v1_stat_validate 82 } 83 84 static int ionic_hw_stats_cmd(struct ionic_ibdev *dev, 85 dma_addr_t dma, size_t len, int qid, int op) 86 { 87 struct ionic_admin_wr wr = { 88 .work = COMPLETION_INITIALIZER_ONSTACK(wr.work), 89 .wqe = { 90 .op = op, 91 .len = cpu_to_le16(IONIC_ADMIN_STATS_HDRS_IN_V1_LEN), 92 .cmd.stats = { 93 .dma_addr = cpu_to_le64(dma), 94 .length = cpu_to_le32(len), 95 .id_ver = cpu_to_le32(qid), 96 }, 97 } 98 }; 99 100 if (dev->lif_cfg.admin_opcodes <= op) 101 return -EBADRQC; 102 103 ionic_admin_post(dev, &wr); 104 105 return ionic_admin_wait(dev, &wr, IONIC_ADMIN_F_INTERRUPT); 106 } 107 108 static int ionic_init_hw_stats(struct ionic_ibdev *dev) 109 { 110 dma_addr_t hw_stats_dma; 111 int rc, hw_stats_count; 112 113 if (dev->hw_stats_hdrs) 114 return 0; 115 116 dev->hw_stats_count = 0; 117 118 /* buffer for current values from the device */ 119 dev->hw_stats_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); 120 if (!dev->hw_stats_buf) { 121 rc = -ENOMEM; 122 goto err_buf; 123 } 124 125 /* buffer for names, sizes, offsets of values */ 126 dev->hw_stats = kzalloc(PAGE_SIZE, GFP_KERNEL); 127 if (!dev->hw_stats) { 128 rc = -ENOMEM; 129 goto err_hw_stats; 130 } 131 132 /* request the names, sizes, offsets */ 133 hw_stats_dma = dma_map_single(dev->lif_cfg.hwdev, dev->hw_stats, 134 PAGE_SIZE, DMA_FROM_DEVICE); 135 rc = dma_mapping_error(dev->lif_cfg.hwdev, hw_stats_dma); 136 if (rc) 137 goto err_dma; 138 139 rc = ionic_hw_stats_cmd(dev, hw_stats_dma, PAGE_SIZE, 0, 140 IONIC_V1_ADMIN_STATS_HDRS); 141 if (rc) 142 goto err_cmd; 143 144 dma_unmap_single(dev->lif_cfg.hwdev, hw_stats_dma, PAGE_SIZE, DMA_FROM_DEVICE); 145 146 /* normalize and count the number of hw_stats */ 147 hw_stats_count = 148 ionic_v1_stat_normalize(dev->hw_stats, 149 PAGE_SIZE / sizeof(*dev->hw_stats)); 150 if (!hw_stats_count) { 151 rc = -ENODATA; 152 goto err_dma; 153 } 154 155 dev->hw_stats_count = hw_stats_count; 156 157 /* alloc and init array of names, for alloc_hw_stats */ 158 dev->hw_stats_hdrs = kzalloc_objs(*dev->hw_stats_hdrs, hw_stats_count); 159 if (!dev->hw_stats_hdrs) { 160 rc = -ENOMEM; 161 goto err_dma; 162 } 163 164 ionic_fill_stats_desc(dev->hw_stats_hdrs, dev->hw_stats, 165 hw_stats_count); 166 167 return 0; 168 169 err_cmd: 170 dma_unmap_single(dev->lif_cfg.hwdev, hw_stats_dma, PAGE_SIZE, DMA_FROM_DEVICE); 171 err_dma: 172 kfree(dev->hw_stats); 173 err_hw_stats: 174 kfree(dev->hw_stats_buf); 175 err_buf: 176 dev->hw_stats_count = 0; 177 dev->hw_stats = NULL; 178 dev->hw_stats_buf = NULL; 179 dev->hw_stats_hdrs = NULL; 180 return rc; 181 } 182 183 static struct rdma_hw_stats *ionic_alloc_hw_stats(struct ib_device *ibdev, 184 u32 port) 185 { 186 struct ionic_ibdev *dev = to_ionic_ibdev(ibdev); 187 188 if (port != 1) 189 return NULL; 190 191 return rdma_alloc_hw_stats_struct(dev->hw_stats_hdrs, 192 dev->hw_stats_count, 193 RDMA_HW_STATS_DEFAULT_LIFESPAN); 194 } 195 196 static int ionic_get_hw_stats(struct ib_device *ibdev, 197 struct rdma_hw_stats *hw_stats, 198 u32 port, int index) 199 { 200 struct ionic_ibdev *dev = to_ionic_ibdev(ibdev); 201 dma_addr_t hw_stats_dma; 202 int rc, hw_stat_i; 203 204 if (port != 1) 205 return -EINVAL; 206 207 hw_stats_dma = dma_map_single(dev->lif_cfg.hwdev, dev->hw_stats_buf, 208 PAGE_SIZE, DMA_FROM_DEVICE); 209 rc = dma_mapping_error(dev->lif_cfg.hwdev, hw_stats_dma); 210 if (rc) 211 goto err_dma; 212 213 rc = ionic_hw_stats_cmd(dev, hw_stats_dma, PAGE_SIZE, 214 0, IONIC_V1_ADMIN_STATS_VALS); 215 if (rc) 216 goto err_cmd; 217 218 dma_unmap_single(dev->lif_cfg.hwdev, hw_stats_dma, 219 PAGE_SIZE, DMA_FROM_DEVICE); 220 221 for (hw_stat_i = 0; hw_stat_i < dev->hw_stats_count; ++hw_stat_i) 222 hw_stats->value[hw_stat_i] = 223 ionic_v1_stat_val(&dev->hw_stats[hw_stat_i], 224 dev->hw_stats_buf, PAGE_SIZE); 225 226 return hw_stat_i; 227 228 err_cmd: 229 dma_unmap_single(dev->lif_cfg.hwdev, hw_stats_dma, 230 PAGE_SIZE, DMA_FROM_DEVICE); 231 err_dma: 232 return rc; 233 } 234 235 static struct rdma_hw_stats * 236 ionic_counter_alloc_stats(struct rdma_counter *counter) 237 { 238 struct ionic_rdma_counter *cntr = to_ionic_rdma_counter(counter); 239 struct ionic_ibdev *dev = to_ionic_ibdev(counter->device); 240 struct rdma_hw_stats *stats; 241 int id; 242 243 cntr->vals = kzalloc(PAGE_SIZE, GFP_KERNEL); 244 if (!cntr->vals) 245 return NULL; 246 247 id = ida_alloc_max(&dev->counter_stats->counter_ida, 248 IONIC_MAX_QPID, GFP_KERNEL); 249 if (id < 0) 250 goto err_ida; 251 252 counter->id = id; 253 254 stats = rdma_alloc_hw_stats_struct(dev->counter_stats->stats_hdrs, 255 dev->counter_stats->queue_stats_count, 256 RDMA_HW_STATS_DEFAULT_LIFESPAN); 257 if (!stats) 258 goto err_hw_stats; 259 260 return stats; 261 262 err_hw_stats: 263 ida_free(&dev->counter_stats->counter_ida, id); 264 err_ida: 265 kfree(cntr->vals); 266 267 return NULL; 268 } 269 270 static int ionic_counter_dealloc(struct rdma_counter *counter) 271 { 272 struct ionic_ibdev *dev = to_ionic_ibdev(counter->device); 273 struct ionic_rdma_counter *cntr = to_ionic_rdma_counter(counter); 274 275 ida_free(&dev->counter_stats->counter_ida, counter->id); 276 kfree(cntr->vals); 277 278 return 0; 279 } 280 281 static int ionic_counter_bind_qp(struct rdma_counter *counter, 282 struct ib_qp *ibqp, 283 u32 port) 284 { 285 struct ionic_rdma_counter *cntr = to_ionic_rdma_counter(counter); 286 struct ionic_qp *qp = to_ionic_qp(ibqp); 287 288 list_add_tail(&qp->qp_list_counter, &cntr->qp_list); 289 ibqp->counter = counter; 290 291 return 0; 292 } 293 294 static int ionic_counter_unbind_qp(struct ib_qp *ibqp, u32 port) 295 { 296 struct ionic_qp *qp = to_ionic_qp(ibqp); 297 298 if (ibqp->counter) { 299 list_del(&qp->qp_list_counter); 300 ibqp->counter = NULL; 301 } 302 303 return 0; 304 } 305 306 static int ionic_counter_update_stats(struct rdma_counter *counter) 307 { 308 struct ionic_rdma_counter *cntr = to_ionic_rdma_counter(counter); 309 struct ionic_ibdev *dev = to_ionic_ibdev(counter->device); 310 struct ionic_counter_stats *cs = dev->counter_stats; 311 dma_addr_t hw_stats_dma; 312 struct ionic_qp *qp; 313 int rc, stat_i = 0; 314 315 hw_stats_dma = dma_map_single(dev->lif_cfg.hwdev, cntr->vals, 316 PAGE_SIZE, DMA_FROM_DEVICE); 317 rc = dma_mapping_error(dev->lif_cfg.hwdev, hw_stats_dma); 318 if (rc) 319 return rc; 320 321 memset(counter->stats->value, 0, 322 sizeof(u64) * counter->stats->num_counters); 323 324 list_for_each_entry(qp, &cntr->qp_list, qp_list_counter) { 325 rc = ionic_hw_stats_cmd(dev, hw_stats_dma, PAGE_SIZE, 326 qp->qpid, 327 IONIC_V1_ADMIN_QP_STATS_VALS); 328 if (rc) 329 goto err_cmd; 330 331 for (stat_i = 0; stat_i < cs->queue_stats_count; ++stat_i) 332 counter->stats->value[stat_i] += 333 ionic_v1_stat_val(&cs->hdr[stat_i], 334 cntr->vals, 335 PAGE_SIZE); 336 } 337 338 dma_unmap_single(dev->lif_cfg.hwdev, hw_stats_dma, PAGE_SIZE, DMA_FROM_DEVICE); 339 return stat_i; 340 341 err_cmd: 342 dma_unmap_single(dev->lif_cfg.hwdev, hw_stats_dma, PAGE_SIZE, DMA_FROM_DEVICE); 343 344 return rc; 345 } 346 347 static int ionic_alloc_counters(struct ionic_ibdev *dev) 348 { 349 struct ionic_counter_stats *cs = dev->counter_stats; 350 int rc, hw_stats_count; 351 dma_addr_t hdr_dma; 352 353 /* buffer for names, sizes, offsets of values */ 354 cs->hdr = kzalloc(PAGE_SIZE, GFP_KERNEL); 355 if (!cs->hdr) 356 return -ENOMEM; 357 358 hdr_dma = dma_map_single(dev->lif_cfg.hwdev, cs->hdr, 359 PAGE_SIZE, DMA_FROM_DEVICE); 360 rc = dma_mapping_error(dev->lif_cfg.hwdev, hdr_dma); 361 if (rc) 362 goto err_dma; 363 364 rc = ionic_hw_stats_cmd(dev, hdr_dma, PAGE_SIZE, 0, 365 IONIC_V1_ADMIN_QP_STATS_HDRS); 366 if (rc) 367 goto err_cmd; 368 369 dma_unmap_single(dev->lif_cfg.hwdev, hdr_dma, PAGE_SIZE, DMA_FROM_DEVICE); 370 371 /* normalize and count the number of hw_stats */ 372 hw_stats_count = ionic_v1_stat_normalize(cs->hdr, 373 PAGE_SIZE / sizeof(*cs->hdr)); 374 if (!hw_stats_count) { 375 rc = -ENODATA; 376 goto err_dma; 377 } 378 379 cs->queue_stats_count = hw_stats_count; 380 381 /* alloc and init array of names */ 382 cs->stats_hdrs = kzalloc_objs(*cs->stats_hdrs, hw_stats_count); 383 if (!cs->stats_hdrs) { 384 rc = -ENOMEM; 385 goto err_dma; 386 } 387 388 ionic_fill_stats_desc(cs->stats_hdrs, cs->hdr, hw_stats_count); 389 390 return 0; 391 392 err_cmd: 393 dma_unmap_single(dev->lif_cfg.hwdev, hdr_dma, PAGE_SIZE, DMA_FROM_DEVICE); 394 err_dma: 395 kfree(cs->hdr); 396 397 return rc; 398 } 399 400 static const struct ib_device_ops ionic_hw_stats_ops = { 401 .driver_id = RDMA_DRIVER_IONIC, 402 .alloc_hw_port_stats = ionic_alloc_hw_stats, 403 .get_hw_stats = ionic_get_hw_stats, 404 }; 405 406 static void ionic_counter_init(struct rdma_counter *counter) 407 { 408 struct ionic_rdma_counter *cntr = to_ionic_rdma_counter(counter); 409 410 INIT_LIST_HEAD(&cntr->qp_list); 411 } 412 413 static const struct ib_device_ops ionic_counter_stats_ops = { 414 .counter_alloc_stats = ionic_counter_alloc_stats, 415 .counter_dealloc = ionic_counter_dealloc, 416 .counter_bind_qp = ionic_counter_bind_qp, 417 .counter_unbind_qp = ionic_counter_unbind_qp, 418 .counter_update_stats = ionic_counter_update_stats, 419 .counter_init = ionic_counter_init, 420 421 INIT_RDMA_OBJ_SIZE(rdma_counter, ionic_rdma_counter, rdma_counter), 422 }; 423 424 void ionic_stats_init(struct ionic_ibdev *dev) 425 { 426 u16 stats_type = dev->lif_cfg.stats_type; 427 int rc; 428 429 if (stats_type & IONIC_LIF_RDMA_STAT_GLOBAL) { 430 rc = ionic_init_hw_stats(dev); 431 if (rc) 432 ibdev_dbg(&dev->ibdev, "Failed to init hw stats\n"); 433 else 434 ib_set_device_ops(&dev->ibdev, &ionic_hw_stats_ops); 435 } 436 437 if (stats_type & IONIC_LIF_RDMA_STAT_QP) { 438 dev->counter_stats = kzalloc_obj(*dev->counter_stats); 439 if (!dev->counter_stats) 440 return; 441 442 rc = ionic_alloc_counters(dev); 443 if (rc) { 444 ibdev_dbg(&dev->ibdev, "Failed to init counter stats\n"); 445 kfree(dev->counter_stats); 446 dev->counter_stats = NULL; 447 return; 448 } 449 450 ida_init(&dev->counter_stats->counter_ida); 451 452 ib_set_device_ops(&dev->ibdev, &ionic_counter_stats_ops); 453 } 454 } 455 456 void ionic_stats_cleanup(struct ionic_ibdev *dev) 457 { 458 if (dev->counter_stats) { 459 ida_destroy(&dev->counter_stats->counter_ida); 460 kfree(dev->counter_stats->hdr); 461 kfree(dev->counter_stats->stats_hdrs); 462 kfree(dev->counter_stats); 463 dev->counter_stats = NULL; 464 } 465 466 kfree(dev->hw_stats); 467 kfree(dev->hw_stats_buf); 468 kfree(dev->hw_stats_hdrs); 469 } 470