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