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