1 /* QLogic qed NIC Driver 2 * Copyright (c) 2015-2017 QLogic Corporation 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and /or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33 #include <linux/types.h> 34 #include <linux/dma-mapping.h> 35 #include <linux/kernel.h> 36 #include <linux/list.h> 37 #include <linux/pci.h> 38 #include <linux/slab.h> 39 #include <linux/string.h> 40 #include "qed.h" 41 #include "qed_iscsi.h" 42 #include "qed_ll2.h" 43 #include "qed_ooo.h" 44 45 static struct qed_ooo_archipelago 46 *qed_ooo_seek_archipelago(struct qed_hwfn *p_hwfn, 47 struct qed_ooo_info 48 *p_ooo_info, 49 u32 cid) 50 { 51 struct qed_ooo_archipelago *p_archipelago = NULL; 52 53 list_for_each_entry(p_archipelago, 54 &p_ooo_info->archipelagos_list, list_entry) { 55 if (p_archipelago->cid == cid) 56 return p_archipelago; 57 } 58 59 return NULL; 60 } 61 62 static struct qed_ooo_isle *qed_ooo_seek_isle(struct qed_hwfn *p_hwfn, 63 struct qed_ooo_info *p_ooo_info, 64 u32 cid, u8 isle) 65 { 66 struct qed_ooo_archipelago *p_archipelago = NULL; 67 struct qed_ooo_isle *p_isle = NULL; 68 u8 the_num_of_isle = 1; 69 70 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 71 if (!p_archipelago) { 72 DP_NOTICE(p_hwfn, 73 "Connection %d is not found in OOO list\n", cid); 74 return NULL; 75 } 76 77 list_for_each_entry(p_isle, &p_archipelago->isles_list, list_entry) { 78 if (the_num_of_isle == isle) 79 return p_isle; 80 the_num_of_isle++; 81 } 82 83 return NULL; 84 } 85 86 void qed_ooo_save_history_entry(struct qed_hwfn *p_hwfn, 87 struct qed_ooo_info *p_ooo_info, 88 struct ooo_opaque *p_cqe) 89 { 90 struct qed_ooo_history *p_history = &p_ooo_info->ooo_history; 91 92 if (p_history->head_idx == p_history->num_of_cqes) 93 p_history->head_idx = 0; 94 p_history->p_cqes[p_history->head_idx] = *p_cqe; 95 p_history->head_idx++; 96 } 97 98 struct qed_ooo_info *qed_ooo_alloc(struct qed_hwfn *p_hwfn) 99 { 100 struct qed_ooo_info *p_ooo_info; 101 u16 max_num_archipelagos = 0; 102 u16 max_num_isles = 0; 103 u32 i; 104 105 if (p_hwfn->hw_info.personality != QED_PCI_ISCSI) { 106 DP_NOTICE(p_hwfn, 107 "Failed to allocate qed_ooo_info: unknown personality\n"); 108 return NULL; 109 } 110 111 max_num_archipelagos = p_hwfn->pf_params.iscsi_pf_params.num_cons; 112 max_num_isles = QED_MAX_NUM_ISLES + max_num_archipelagos; 113 114 if (!max_num_archipelagos) { 115 DP_NOTICE(p_hwfn, 116 "Failed to allocate qed_ooo_info: unknown amount of connections\n"); 117 return NULL; 118 } 119 120 p_ooo_info = kzalloc(sizeof(*p_ooo_info), GFP_KERNEL); 121 if (!p_ooo_info) 122 return NULL; 123 124 INIT_LIST_HEAD(&p_ooo_info->free_buffers_list); 125 INIT_LIST_HEAD(&p_ooo_info->ready_buffers_list); 126 INIT_LIST_HEAD(&p_ooo_info->free_isles_list); 127 INIT_LIST_HEAD(&p_ooo_info->free_archipelagos_list); 128 INIT_LIST_HEAD(&p_ooo_info->archipelagos_list); 129 130 p_ooo_info->p_isles_mem = kcalloc(max_num_isles, 131 sizeof(struct qed_ooo_isle), 132 GFP_KERNEL); 133 if (!p_ooo_info->p_isles_mem) 134 goto no_isles_mem; 135 136 for (i = 0; i < max_num_isles; i++) { 137 INIT_LIST_HEAD(&p_ooo_info->p_isles_mem[i].buffers_list); 138 list_add_tail(&p_ooo_info->p_isles_mem[i].list_entry, 139 &p_ooo_info->free_isles_list); 140 } 141 142 p_ooo_info->p_archipelagos_mem = 143 kcalloc(max_num_archipelagos, 144 sizeof(struct qed_ooo_archipelago), 145 GFP_KERNEL); 146 if (!p_ooo_info->p_archipelagos_mem) 147 goto no_archipelagos_mem; 148 149 for (i = 0; i < max_num_archipelagos; i++) { 150 INIT_LIST_HEAD(&p_ooo_info->p_archipelagos_mem[i].isles_list); 151 list_add_tail(&p_ooo_info->p_archipelagos_mem[i].list_entry, 152 &p_ooo_info->free_archipelagos_list); 153 } 154 155 p_ooo_info->ooo_history.p_cqes = 156 kcalloc(QED_MAX_NUM_OOO_HISTORY_ENTRIES, 157 sizeof(struct ooo_opaque), 158 GFP_KERNEL); 159 if (!p_ooo_info->ooo_history.p_cqes) 160 goto no_history_mem; 161 162 p_ooo_info->ooo_history.num_of_cqes = QED_MAX_NUM_OOO_HISTORY_ENTRIES; 163 164 return p_ooo_info; 165 166 no_history_mem: 167 kfree(p_ooo_info->p_archipelagos_mem); 168 no_archipelagos_mem: 169 kfree(p_ooo_info->p_isles_mem); 170 no_isles_mem: 171 kfree(p_ooo_info); 172 return NULL; 173 } 174 175 void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn, 176 struct qed_ooo_info *p_ooo_info, u32 cid) 177 { 178 struct qed_ooo_archipelago *p_archipelago; 179 struct qed_ooo_buffer *p_buffer; 180 struct qed_ooo_isle *p_isle; 181 bool b_found = false; 182 183 if (list_empty(&p_ooo_info->archipelagos_list)) 184 return; 185 186 list_for_each_entry(p_archipelago, 187 &p_ooo_info->archipelagos_list, list_entry) { 188 if (p_archipelago->cid == cid) { 189 list_del(&p_archipelago->list_entry); 190 b_found = true; 191 break; 192 } 193 } 194 195 if (!b_found) 196 return; 197 198 while (!list_empty(&p_archipelago->isles_list)) { 199 p_isle = list_first_entry(&p_archipelago->isles_list, 200 struct qed_ooo_isle, list_entry); 201 202 list_del(&p_isle->list_entry); 203 204 while (!list_empty(&p_isle->buffers_list)) { 205 p_buffer = list_first_entry(&p_isle->buffers_list, 206 struct qed_ooo_buffer, 207 list_entry); 208 209 if (!p_buffer) 210 break; 211 212 list_del(&p_buffer->list_entry); 213 list_add_tail(&p_buffer->list_entry, 214 &p_ooo_info->free_buffers_list); 215 } 216 list_add_tail(&p_isle->list_entry, 217 &p_ooo_info->free_isles_list); 218 } 219 220 list_add_tail(&p_archipelago->list_entry, 221 &p_ooo_info->free_archipelagos_list); 222 } 223 224 void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn, 225 struct qed_ooo_info *p_ooo_info) 226 { 227 struct qed_ooo_archipelago *p_arch; 228 struct qed_ooo_buffer *p_buffer; 229 struct qed_ooo_isle *p_isle; 230 231 while (!list_empty(&p_ooo_info->archipelagos_list)) { 232 p_arch = list_first_entry(&p_ooo_info->archipelagos_list, 233 struct qed_ooo_archipelago, 234 list_entry); 235 236 list_del(&p_arch->list_entry); 237 238 while (!list_empty(&p_arch->isles_list)) { 239 p_isle = list_first_entry(&p_arch->isles_list, 240 struct qed_ooo_isle, 241 list_entry); 242 243 list_del(&p_isle->list_entry); 244 245 while (!list_empty(&p_isle->buffers_list)) { 246 p_buffer = 247 list_first_entry(&p_isle->buffers_list, 248 struct qed_ooo_buffer, 249 list_entry); 250 251 if (!p_buffer) 252 break; 253 254 list_del(&p_buffer->list_entry); 255 list_add_tail(&p_buffer->list_entry, 256 &p_ooo_info->free_buffers_list); 257 } 258 list_add_tail(&p_isle->list_entry, 259 &p_ooo_info->free_isles_list); 260 } 261 list_add_tail(&p_arch->list_entry, 262 &p_ooo_info->free_archipelagos_list); 263 } 264 if (!list_empty(&p_ooo_info->ready_buffers_list)) 265 list_splice_tail_init(&p_ooo_info->ready_buffers_list, 266 &p_ooo_info->free_buffers_list); 267 } 268 269 void qed_ooo_setup(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info) 270 { 271 qed_ooo_release_all_isles(p_hwfn, p_ooo_info); 272 memset(p_ooo_info->ooo_history.p_cqes, 0, 273 p_ooo_info->ooo_history.num_of_cqes * 274 sizeof(struct ooo_opaque)); 275 p_ooo_info->ooo_history.head_idx = 0; 276 } 277 278 void qed_ooo_free(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info) 279 { 280 struct qed_ooo_buffer *p_buffer; 281 282 qed_ooo_release_all_isles(p_hwfn, p_ooo_info); 283 while (!list_empty(&p_ooo_info->free_buffers_list)) { 284 p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 285 struct qed_ooo_buffer, list_entry); 286 287 if (!p_buffer) 288 break; 289 290 list_del(&p_buffer->list_entry); 291 dma_free_coherent(&p_hwfn->cdev->pdev->dev, 292 p_buffer->rx_buffer_size, 293 p_buffer->rx_buffer_virt_addr, 294 p_buffer->rx_buffer_phys_addr); 295 kfree(p_buffer); 296 } 297 298 kfree(p_ooo_info->p_isles_mem); 299 kfree(p_ooo_info->p_archipelagos_mem); 300 kfree(p_ooo_info->ooo_history.p_cqes); 301 kfree(p_ooo_info); 302 } 303 304 void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn, 305 struct qed_ooo_info *p_ooo_info, 306 struct qed_ooo_buffer *p_buffer) 307 { 308 list_add_tail(&p_buffer->list_entry, &p_ooo_info->free_buffers_list); 309 } 310 311 struct qed_ooo_buffer *qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn, 312 struct qed_ooo_info *p_ooo_info) 313 { 314 struct qed_ooo_buffer *p_buffer = NULL; 315 316 if (!list_empty(&p_ooo_info->free_buffers_list)) { 317 p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 318 struct qed_ooo_buffer, list_entry); 319 320 list_del(&p_buffer->list_entry); 321 } 322 323 return p_buffer; 324 } 325 326 void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn, 327 struct qed_ooo_info *p_ooo_info, 328 struct qed_ooo_buffer *p_buffer, u8 on_tail) 329 { 330 if (on_tail) 331 list_add_tail(&p_buffer->list_entry, 332 &p_ooo_info->ready_buffers_list); 333 else 334 list_add(&p_buffer->list_entry, 335 &p_ooo_info->ready_buffers_list); 336 } 337 338 struct qed_ooo_buffer *qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn, 339 struct qed_ooo_info *p_ooo_info) 340 { 341 struct qed_ooo_buffer *p_buffer = NULL; 342 343 if (!list_empty(&p_ooo_info->ready_buffers_list)) { 344 p_buffer = list_first_entry(&p_ooo_info->ready_buffers_list, 345 struct qed_ooo_buffer, list_entry); 346 347 list_del(&p_buffer->list_entry); 348 } 349 350 return p_buffer; 351 } 352 353 void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn, 354 struct qed_ooo_info *p_ooo_info, 355 u32 cid, u8 drop_isle, u8 drop_size) 356 { 357 struct qed_ooo_archipelago *p_archipelago = NULL; 358 struct qed_ooo_isle *p_isle = NULL; 359 u8 isle_idx; 360 361 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 362 for (isle_idx = 0; isle_idx < drop_size; isle_idx++) { 363 p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, drop_isle); 364 if (!p_isle) { 365 DP_NOTICE(p_hwfn, 366 "Isle %d is not found(cid %d)\n", 367 drop_isle, cid); 368 return; 369 } 370 if (list_empty(&p_isle->buffers_list)) 371 DP_NOTICE(p_hwfn, 372 "Isle %d is empty(cid %d)\n", drop_isle, cid); 373 else 374 list_splice_tail_init(&p_isle->buffers_list, 375 &p_ooo_info->free_buffers_list); 376 377 list_del(&p_isle->list_entry); 378 p_ooo_info->cur_isles_number--; 379 list_add(&p_isle->list_entry, &p_ooo_info->free_isles_list); 380 } 381 382 if (list_empty(&p_archipelago->isles_list)) { 383 list_del(&p_archipelago->list_entry); 384 list_add(&p_archipelago->list_entry, 385 &p_ooo_info->free_archipelagos_list); 386 } 387 } 388 389 void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn, 390 struct qed_ooo_info *p_ooo_info, 391 u32 cid, u8 ooo_isle, 392 struct qed_ooo_buffer *p_buffer) 393 { 394 struct qed_ooo_archipelago *p_archipelago = NULL; 395 struct qed_ooo_isle *p_prev_isle = NULL; 396 struct qed_ooo_isle *p_isle = NULL; 397 398 if (ooo_isle > 1) { 399 p_prev_isle = qed_ooo_seek_isle(p_hwfn, 400 p_ooo_info, cid, ooo_isle - 1); 401 if (!p_prev_isle) { 402 DP_NOTICE(p_hwfn, 403 "Isle %d is not found(cid %d)\n", 404 ooo_isle - 1, cid); 405 return; 406 } 407 } 408 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 409 if (!p_archipelago && (ooo_isle != 1)) { 410 DP_NOTICE(p_hwfn, 411 "Connection %d is not found in OOO list\n", cid); 412 return; 413 } 414 415 if (!list_empty(&p_ooo_info->free_isles_list)) { 416 p_isle = list_first_entry(&p_ooo_info->free_isles_list, 417 struct qed_ooo_isle, list_entry); 418 419 list_del(&p_isle->list_entry); 420 if (!list_empty(&p_isle->buffers_list)) { 421 DP_NOTICE(p_hwfn, "Free isle is not empty\n"); 422 INIT_LIST_HEAD(&p_isle->buffers_list); 423 } 424 } else { 425 DP_NOTICE(p_hwfn, "No more free isles\n"); 426 return; 427 } 428 429 if (!p_archipelago && 430 !list_empty(&p_ooo_info->free_archipelagos_list)) { 431 p_archipelago = 432 list_first_entry(&p_ooo_info->free_archipelagos_list, 433 struct qed_ooo_archipelago, list_entry); 434 435 list_del(&p_archipelago->list_entry); 436 if (!list_empty(&p_archipelago->isles_list)) { 437 DP_NOTICE(p_hwfn, 438 "Free OOO connection is not empty\n"); 439 INIT_LIST_HEAD(&p_archipelago->isles_list); 440 } 441 p_archipelago->cid = cid; 442 list_add(&p_archipelago->list_entry, 443 &p_ooo_info->archipelagos_list); 444 } else if (!p_archipelago) { 445 DP_NOTICE(p_hwfn, "No more free OOO connections\n"); 446 list_add(&p_isle->list_entry, 447 &p_ooo_info->free_isles_list); 448 list_add(&p_buffer->list_entry, 449 &p_ooo_info->free_buffers_list); 450 return; 451 } 452 453 list_add(&p_buffer->list_entry, &p_isle->buffers_list); 454 p_ooo_info->cur_isles_number++; 455 p_ooo_info->gen_isles_number++; 456 457 if (p_ooo_info->cur_isles_number > p_ooo_info->max_isles_number) 458 p_ooo_info->max_isles_number = p_ooo_info->cur_isles_number; 459 460 if (!p_prev_isle) 461 list_add(&p_isle->list_entry, &p_archipelago->isles_list); 462 else 463 list_add(&p_isle->list_entry, &p_prev_isle->list_entry); 464 } 465 466 void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn, 467 struct qed_ooo_info *p_ooo_info, 468 u32 cid, 469 u8 ooo_isle, 470 struct qed_ooo_buffer *p_buffer, u8 buffer_side) 471 { 472 struct qed_ooo_isle *p_isle = NULL; 473 474 p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, ooo_isle); 475 if (!p_isle) { 476 DP_NOTICE(p_hwfn, 477 "Isle %d is not found(cid %d)\n", ooo_isle, cid); 478 return; 479 } 480 481 if (buffer_side == QED_OOO_LEFT_BUF) 482 list_add(&p_buffer->list_entry, &p_isle->buffers_list); 483 else 484 list_add_tail(&p_buffer->list_entry, &p_isle->buffers_list); 485 } 486 487 void qed_ooo_join_isles(struct qed_hwfn *p_hwfn, 488 struct qed_ooo_info *p_ooo_info, u32 cid, u8 left_isle) 489 { 490 struct qed_ooo_archipelago *p_archipelago = NULL; 491 struct qed_ooo_isle *p_right_isle = NULL; 492 struct qed_ooo_isle *p_left_isle = NULL; 493 494 p_right_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 495 left_isle + 1); 496 if (!p_right_isle) { 497 DP_NOTICE(p_hwfn, 498 "Right isle %d is not found(cid %d)\n", 499 left_isle + 1, cid); 500 return; 501 } 502 503 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 504 list_del(&p_right_isle->list_entry); 505 p_ooo_info->cur_isles_number--; 506 if (left_isle) { 507 p_left_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 508 left_isle); 509 if (!p_left_isle) { 510 DP_NOTICE(p_hwfn, 511 "Left isle %d is not found(cid %d)\n", 512 left_isle, cid); 513 return; 514 } 515 list_splice_tail_init(&p_right_isle->buffers_list, 516 &p_left_isle->buffers_list); 517 } else { 518 list_splice_tail_init(&p_right_isle->buffers_list, 519 &p_ooo_info->ready_buffers_list); 520 if (list_empty(&p_archipelago->isles_list)) { 521 list_del(&p_archipelago->list_entry); 522 list_add(&p_archipelago->list_entry, 523 &p_ooo_info->free_archipelagos_list); 524 } 525 } 526 list_add_tail(&p_right_isle->list_entry, &p_ooo_info->free_isles_list); 527 } 528