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 return p_ooo_info; 163 164 no_history_mem: 165 kfree(p_ooo_info->p_archipelagos_mem); 166 no_archipelagos_mem: 167 kfree(p_ooo_info->p_isles_mem); 168 no_isles_mem: 169 kfree(p_ooo_info); 170 return NULL; 171 } 172 173 void qed_ooo_release_connection_isles(struct qed_hwfn *p_hwfn, 174 struct qed_ooo_info *p_ooo_info, u32 cid) 175 { 176 struct qed_ooo_archipelago *p_archipelago; 177 struct qed_ooo_buffer *p_buffer; 178 struct qed_ooo_isle *p_isle; 179 bool b_found = false; 180 181 if (list_empty(&p_ooo_info->archipelagos_list)) 182 return; 183 184 list_for_each_entry(p_archipelago, 185 &p_ooo_info->archipelagos_list, list_entry) { 186 if (p_archipelago->cid == cid) { 187 list_del(&p_archipelago->list_entry); 188 b_found = true; 189 break; 190 } 191 } 192 193 if (!b_found) 194 return; 195 196 while (!list_empty(&p_archipelago->isles_list)) { 197 p_isle = list_first_entry(&p_archipelago->isles_list, 198 struct qed_ooo_isle, list_entry); 199 200 list_del(&p_isle->list_entry); 201 202 while (!list_empty(&p_isle->buffers_list)) { 203 p_buffer = list_first_entry(&p_isle->buffers_list, 204 struct qed_ooo_buffer, 205 list_entry); 206 207 if (!p_buffer) 208 break; 209 210 list_del(&p_buffer->list_entry); 211 list_add_tail(&p_buffer->list_entry, 212 &p_ooo_info->free_buffers_list); 213 } 214 list_add_tail(&p_isle->list_entry, 215 &p_ooo_info->free_isles_list); 216 } 217 218 list_add_tail(&p_archipelago->list_entry, 219 &p_ooo_info->free_archipelagos_list); 220 } 221 222 void qed_ooo_release_all_isles(struct qed_hwfn *p_hwfn, 223 struct qed_ooo_info *p_ooo_info) 224 { 225 struct qed_ooo_archipelago *p_arch; 226 struct qed_ooo_buffer *p_buffer; 227 struct qed_ooo_isle *p_isle; 228 229 while (!list_empty(&p_ooo_info->archipelagos_list)) { 230 p_arch = list_first_entry(&p_ooo_info->archipelagos_list, 231 struct qed_ooo_archipelago, 232 list_entry); 233 234 list_del(&p_arch->list_entry); 235 236 while (!list_empty(&p_arch->isles_list)) { 237 p_isle = list_first_entry(&p_arch->isles_list, 238 struct qed_ooo_isle, 239 list_entry); 240 241 list_del(&p_isle->list_entry); 242 243 while (!list_empty(&p_isle->buffers_list)) { 244 p_buffer = 245 list_first_entry(&p_isle->buffers_list, 246 struct qed_ooo_buffer, 247 list_entry); 248 249 if (!p_buffer) 250 break; 251 252 list_del(&p_buffer->list_entry); 253 list_add_tail(&p_buffer->list_entry, 254 &p_ooo_info->free_buffers_list); 255 } 256 list_add_tail(&p_isle->list_entry, 257 &p_ooo_info->free_isles_list); 258 } 259 list_add_tail(&p_arch->list_entry, 260 &p_ooo_info->free_archipelagos_list); 261 } 262 if (!list_empty(&p_ooo_info->ready_buffers_list)) 263 list_splice_tail_init(&p_ooo_info->ready_buffers_list, 264 &p_ooo_info->free_buffers_list); 265 } 266 267 void qed_ooo_setup(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info) 268 { 269 qed_ooo_release_all_isles(p_hwfn, p_ooo_info); 270 memset(p_ooo_info->ooo_history.p_cqes, 0, 271 p_ooo_info->ooo_history.num_of_cqes * 272 sizeof(struct ooo_opaque)); 273 p_ooo_info->ooo_history.head_idx = 0; 274 } 275 276 void qed_ooo_free(struct qed_hwfn *p_hwfn, struct qed_ooo_info *p_ooo_info) 277 { 278 struct qed_ooo_buffer *p_buffer; 279 280 qed_ooo_release_all_isles(p_hwfn, p_ooo_info); 281 while (!list_empty(&p_ooo_info->free_buffers_list)) { 282 p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 283 struct qed_ooo_buffer, list_entry); 284 285 if (!p_buffer) 286 break; 287 288 list_del(&p_buffer->list_entry); 289 dma_free_coherent(&p_hwfn->cdev->pdev->dev, 290 p_buffer->rx_buffer_size, 291 p_buffer->rx_buffer_virt_addr, 292 p_buffer->rx_buffer_phys_addr); 293 kfree(p_buffer); 294 } 295 296 kfree(p_ooo_info->p_isles_mem); 297 kfree(p_ooo_info->p_archipelagos_mem); 298 kfree(p_ooo_info->ooo_history.p_cqes); 299 kfree(p_ooo_info); 300 } 301 302 void qed_ooo_put_free_buffer(struct qed_hwfn *p_hwfn, 303 struct qed_ooo_info *p_ooo_info, 304 struct qed_ooo_buffer *p_buffer) 305 { 306 list_add_tail(&p_buffer->list_entry, &p_ooo_info->free_buffers_list); 307 } 308 309 struct qed_ooo_buffer *qed_ooo_get_free_buffer(struct qed_hwfn *p_hwfn, 310 struct qed_ooo_info *p_ooo_info) 311 { 312 struct qed_ooo_buffer *p_buffer = NULL; 313 314 if (!list_empty(&p_ooo_info->free_buffers_list)) { 315 p_buffer = list_first_entry(&p_ooo_info->free_buffers_list, 316 struct qed_ooo_buffer, list_entry); 317 318 list_del(&p_buffer->list_entry); 319 } 320 321 return p_buffer; 322 } 323 324 void qed_ooo_put_ready_buffer(struct qed_hwfn *p_hwfn, 325 struct qed_ooo_info *p_ooo_info, 326 struct qed_ooo_buffer *p_buffer, u8 on_tail) 327 { 328 if (on_tail) 329 list_add_tail(&p_buffer->list_entry, 330 &p_ooo_info->ready_buffers_list); 331 else 332 list_add(&p_buffer->list_entry, 333 &p_ooo_info->ready_buffers_list); 334 } 335 336 struct qed_ooo_buffer *qed_ooo_get_ready_buffer(struct qed_hwfn *p_hwfn, 337 struct qed_ooo_info *p_ooo_info) 338 { 339 struct qed_ooo_buffer *p_buffer = NULL; 340 341 if (!list_empty(&p_ooo_info->ready_buffers_list)) { 342 p_buffer = list_first_entry(&p_ooo_info->ready_buffers_list, 343 struct qed_ooo_buffer, list_entry); 344 345 list_del(&p_buffer->list_entry); 346 } 347 348 return p_buffer; 349 } 350 351 void qed_ooo_delete_isles(struct qed_hwfn *p_hwfn, 352 struct qed_ooo_info *p_ooo_info, 353 u32 cid, u8 drop_isle, u8 drop_size) 354 { 355 struct qed_ooo_archipelago *p_archipelago = NULL; 356 struct qed_ooo_isle *p_isle = NULL; 357 u8 isle_idx; 358 359 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 360 for (isle_idx = 0; isle_idx < drop_size; isle_idx++) { 361 p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, drop_isle); 362 if (!p_isle) { 363 DP_NOTICE(p_hwfn, 364 "Isle %d is not found(cid %d)\n", 365 drop_isle, cid); 366 return; 367 } 368 if (list_empty(&p_isle->buffers_list)) 369 DP_NOTICE(p_hwfn, 370 "Isle %d is empty(cid %d)\n", drop_isle, cid); 371 else 372 list_splice_tail_init(&p_isle->buffers_list, 373 &p_ooo_info->free_buffers_list); 374 375 list_del(&p_isle->list_entry); 376 p_ooo_info->cur_isles_number--; 377 list_add(&p_isle->list_entry, &p_ooo_info->free_isles_list); 378 } 379 380 if (list_empty(&p_archipelago->isles_list)) { 381 list_del(&p_archipelago->list_entry); 382 list_add(&p_archipelago->list_entry, 383 &p_ooo_info->free_archipelagos_list); 384 } 385 } 386 387 void qed_ooo_add_new_isle(struct qed_hwfn *p_hwfn, 388 struct qed_ooo_info *p_ooo_info, 389 u32 cid, u8 ooo_isle, 390 struct qed_ooo_buffer *p_buffer) 391 { 392 struct qed_ooo_archipelago *p_archipelago = NULL; 393 struct qed_ooo_isle *p_prev_isle = NULL; 394 struct qed_ooo_isle *p_isle = NULL; 395 396 if (ooo_isle > 1) { 397 p_prev_isle = qed_ooo_seek_isle(p_hwfn, 398 p_ooo_info, cid, ooo_isle - 1); 399 if (!p_prev_isle) { 400 DP_NOTICE(p_hwfn, 401 "Isle %d is not found(cid %d)\n", 402 ooo_isle - 1, cid); 403 return; 404 } 405 } 406 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 407 if (!p_archipelago && (ooo_isle != 1)) { 408 DP_NOTICE(p_hwfn, 409 "Connection %d is not found in OOO list\n", cid); 410 return; 411 } 412 413 if (!list_empty(&p_ooo_info->free_isles_list)) { 414 p_isle = list_first_entry(&p_ooo_info->free_isles_list, 415 struct qed_ooo_isle, list_entry); 416 417 list_del(&p_isle->list_entry); 418 if (!list_empty(&p_isle->buffers_list)) { 419 DP_NOTICE(p_hwfn, "Free isle is not empty\n"); 420 INIT_LIST_HEAD(&p_isle->buffers_list); 421 } 422 } else { 423 DP_NOTICE(p_hwfn, "No more free isles\n"); 424 return; 425 } 426 427 if (!p_archipelago && 428 !list_empty(&p_ooo_info->free_archipelagos_list)) { 429 p_archipelago = 430 list_first_entry(&p_ooo_info->free_archipelagos_list, 431 struct qed_ooo_archipelago, list_entry); 432 433 list_del(&p_archipelago->list_entry); 434 if (!list_empty(&p_archipelago->isles_list)) { 435 DP_NOTICE(p_hwfn, 436 "Free OOO connection is not empty\n"); 437 INIT_LIST_HEAD(&p_archipelago->isles_list); 438 } 439 p_archipelago->cid = cid; 440 list_add(&p_archipelago->list_entry, 441 &p_ooo_info->archipelagos_list); 442 } else if (!p_archipelago) { 443 DP_NOTICE(p_hwfn, "No more free OOO connections\n"); 444 list_add(&p_isle->list_entry, 445 &p_ooo_info->free_isles_list); 446 list_add(&p_buffer->list_entry, 447 &p_ooo_info->free_buffers_list); 448 return; 449 } 450 451 list_add(&p_buffer->list_entry, &p_isle->buffers_list); 452 p_ooo_info->cur_isles_number++; 453 p_ooo_info->gen_isles_number++; 454 455 if (p_ooo_info->cur_isles_number > p_ooo_info->max_isles_number) 456 p_ooo_info->max_isles_number = p_ooo_info->cur_isles_number; 457 458 if (!p_prev_isle) 459 list_add(&p_isle->list_entry, &p_archipelago->isles_list); 460 else 461 list_add(&p_isle->list_entry, &p_prev_isle->list_entry); 462 } 463 464 void qed_ooo_add_new_buffer(struct qed_hwfn *p_hwfn, 465 struct qed_ooo_info *p_ooo_info, 466 u32 cid, 467 u8 ooo_isle, 468 struct qed_ooo_buffer *p_buffer, u8 buffer_side) 469 { 470 struct qed_ooo_isle *p_isle = NULL; 471 472 p_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, ooo_isle); 473 if (!p_isle) { 474 DP_NOTICE(p_hwfn, 475 "Isle %d is not found(cid %d)\n", ooo_isle, cid); 476 return; 477 } 478 479 if (buffer_side == QED_OOO_LEFT_BUF) 480 list_add(&p_buffer->list_entry, &p_isle->buffers_list); 481 else 482 list_add_tail(&p_buffer->list_entry, &p_isle->buffers_list); 483 } 484 485 void qed_ooo_join_isles(struct qed_hwfn *p_hwfn, 486 struct qed_ooo_info *p_ooo_info, u32 cid, u8 left_isle) 487 { 488 struct qed_ooo_archipelago *p_archipelago = NULL; 489 struct qed_ooo_isle *p_right_isle = NULL; 490 struct qed_ooo_isle *p_left_isle = NULL; 491 492 p_right_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 493 left_isle + 1); 494 if (!p_right_isle) { 495 DP_NOTICE(p_hwfn, 496 "Right isle %d is not found(cid %d)\n", 497 left_isle + 1, cid); 498 return; 499 } 500 501 p_archipelago = qed_ooo_seek_archipelago(p_hwfn, p_ooo_info, cid); 502 list_del(&p_right_isle->list_entry); 503 p_ooo_info->cur_isles_number--; 504 if (left_isle) { 505 p_left_isle = qed_ooo_seek_isle(p_hwfn, p_ooo_info, cid, 506 left_isle); 507 if (!p_left_isle) { 508 DP_NOTICE(p_hwfn, 509 "Left isle %d is not found(cid %d)\n", 510 left_isle, cid); 511 return; 512 } 513 list_splice_tail_init(&p_right_isle->buffers_list, 514 &p_left_isle->buffers_list); 515 } else { 516 list_splice_tail_init(&p_right_isle->buffers_list, 517 &p_ooo_info->ready_buffers_list); 518 if (list_empty(&p_archipelago->isles_list)) { 519 list_del(&p_archipelago->list_entry); 520 list_add(&p_archipelago->list_entry, 521 &p_ooo_info->free_archipelagos_list); 522 } 523 } 524 list_add_tail(&p_right_isle->list_entry, &p_ooo_info->free_isles_list); 525 } 526