nvme_qpair.c (248766) | nvme_qpair.c (248767) |
---|---|
1/*- 2 * Copyright (C) 2012 Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (C) 2012 Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/dev/nvme/nvme_qpair.c 248766 2013-03-26 21:48:41Z jimharris $"); | 28__FBSDID("$FreeBSD: head/sys/dev/nvme/nvme_qpair.c 248767 2013-03-26 21:58:38Z jimharris $"); |
29 30#include <sys/param.h> 31#include <sys/bus.h> 32 33#include <dev/pci/pcivar.h> 34 35#include "nvme_private.h" 36 --- 8 unchanged lines hidden (view full) --- 45 * to TLER will be marked. So for now, it seems 46 * NAMESPACE_NOT_READY is the only case where we should 47 * look at the DNR bit. 48 */ 49 switch (cpl->status.sct) { 50 case NVME_SCT_GENERIC: 51 switch (cpl->status.sc) { 52 case NVME_SC_ABORTED_BY_REQUEST: | 29 30#include <sys/param.h> 31#include <sys/bus.h> 32 33#include <dev/pci/pcivar.h> 34 35#include "nvme_private.h" 36 --- 8 unchanged lines hidden (view full) --- 45 * to TLER will be marked. So for now, it seems 46 * NAMESPACE_NOT_READY is the only case where we should 47 * look at the DNR bit. 48 */ 49 switch (cpl->status.sct) { 50 case NVME_SCT_GENERIC: 51 switch (cpl->status.sc) { 52 case NVME_SC_ABORTED_BY_REQUEST: |
53 return (1); | |
54 case NVME_SC_NAMESPACE_NOT_READY: 55 if (cpl->status.dnr) 56 return (0); 57 else 58 return (1); 59 case NVME_SC_INVALID_OPCODE: 60 case NVME_SC_INVALID_FIELD: 61 case NVME_SC_COMMAND_ID_CONFLICT: --- 88 unchanged lines hidden (view full) --- 150 } 151 } 152 153 mtx_unlock(&qpair->lock); 154} 155 156static void 157nvme_qpair_manual_complete_tracker(struct nvme_qpair *qpair, | 53 case NVME_SC_NAMESPACE_NOT_READY: 54 if (cpl->status.dnr) 55 return (0); 56 else 57 return (1); 58 case NVME_SC_INVALID_OPCODE: 59 case NVME_SC_INVALID_FIELD: 60 case NVME_SC_COMMAND_ID_CONFLICT: --- 88 unchanged lines hidden (view full) --- 149 } 150 } 151 152 mtx_unlock(&qpair->lock); 153} 154 155static void 156nvme_qpair_manual_complete_tracker(struct nvme_qpair *qpair, |
158 struct nvme_tracker *tr, uint32_t sct, uint32_t sc, | 157 struct nvme_tracker *tr, uint32_t sct, uint32_t sc, uint32_t dnr, |
159 boolean_t print_on_error) 160{ 161 struct nvme_completion cpl; 162 163 memset(&cpl, 0, sizeof(cpl)); 164 cpl.sqid = qpair->id; 165 cpl.cid = tr->cid; 166 cpl.status.sct = sct; 167 cpl.status.sc = sc; | 158 boolean_t print_on_error) 159{ 160 struct nvme_completion cpl; 161 162 memset(&cpl, 0, sizeof(cpl)); 163 cpl.sqid = qpair->id; 164 cpl.cid = tr->cid; 165 cpl.status.sct = sct; 166 cpl.status.sc = sc; |
167 cpl.status.dnr = dnr; |
|
168 nvme_qpair_complete_tracker(qpair, tr, &cpl, print_on_error); 169} 170 171void | 168 nvme_qpair_complete_tracker(qpair, tr, &cpl, print_on_error); 169} 170 171void |
172nvme_qpair_manual_complete_request(struct nvme_qpair *qpair, 173 struct nvme_request *req, uint32_t sct, uint32_t sc, 174 boolean_t print_on_error) 175{ 176 struct nvme_completion cpl; 177 boolean_t error; 178 179 memset(&cpl, 0, sizeof(cpl)); 180 cpl.sqid = qpair->id; 181 cpl.status.sct = sct; 182 cpl.status.sc = sc; 183 184 error = nvme_completion_is_error(&cpl); 185 186 if (error && print_on_error) { 187 nvme_dump_completion(&cpl); 188 nvme_dump_command(&req->cmd); 189 } 190 191 if (req->cb_fn) 192 req->cb_fn(req->cb_arg, &cpl); 193 194 nvme_free_request(req); 195} 196 197void |
|
172nvme_qpair_process_completions(struct nvme_qpair *qpair) 173{ 174 struct nvme_tracker *tr; 175 struct nvme_completion *cpl; 176 177 qpair->num_intr_handler_calls++; 178 179 if (!qpair->is_enabled) --- 178 unchanged lines hidden (view full) --- 358nvme_admin_qpair_abort_aers(struct nvme_qpair *qpair) 359{ 360 struct nvme_tracker *tr; 361 362 tr = TAILQ_FIRST(&qpair->outstanding_tr); 363 while (tr != NULL) { 364 if (tr->req->cmd.opc == NVME_OPC_ASYNC_EVENT_REQUEST) { 365 nvme_qpair_manual_complete_tracker(qpair, tr, | 198nvme_qpair_process_completions(struct nvme_qpair *qpair) 199{ 200 struct nvme_tracker *tr; 201 struct nvme_completion *cpl; 202 203 qpair->num_intr_handler_calls++; 204 205 if (!qpair->is_enabled) --- 178 unchanged lines hidden (view full) --- 384nvme_admin_qpair_abort_aers(struct nvme_qpair *qpair) 385{ 386 struct nvme_tracker *tr; 387 388 tr = TAILQ_FIRST(&qpair->outstanding_tr); 389 while (tr != NULL) { 390 if (tr->req->cmd.opc == NVME_OPC_ASYNC_EVENT_REQUEST) { 391 nvme_qpair_manual_complete_tracker(qpair, tr, |
366 NVME_SCT_GENERIC, NVME_SC_ABORTED_SQ_DELETION, | 392 NVME_SCT_GENERIC, NVME_SC_ABORTED_SQ_DELETION, 0, |
367 FALSE); 368 tr = TAILQ_FIRST(&qpair->outstanding_tr); 369 } else { 370 tr = TAILQ_NEXT(tr, tailq); 371 } 372 } 373} 374 --- 26 unchanged lines hidden (view full) --- 401 if (status->cdw0 == 1 && tr->qpair->act_tr[tr->cid] != NULL) { 402 /* 403 * An I/O has timed out, and the controller was unable to 404 * abort it for some reason. Construct a fake completion 405 * status, and then complete the I/O's tracker manually. 406 */ 407 printf("abort command failed, aborting command manually\n"); 408 nvme_qpair_manual_complete_tracker(tr->qpair, tr, | 393 FALSE); 394 tr = TAILQ_FIRST(&qpair->outstanding_tr); 395 } else { 396 tr = TAILQ_NEXT(tr, tailq); 397 } 398 } 399} 400 --- 26 unchanged lines hidden (view full) --- 427 if (status->cdw0 == 1 && tr->qpair->act_tr[tr->cid] != NULL) { 428 /* 429 * An I/O has timed out, and the controller was unable to 430 * abort it for some reason. Construct a fake completion 431 * status, and then complete the I/O's tracker manually. 432 */ 433 printf("abort command failed, aborting command manually\n"); 434 nvme_qpair_manual_complete_tracker(tr->qpair, tr, |
409 NVME_SCT_GENERIC, NVME_SC_ABORTED_BY_REQUEST, TRUE); | 435 NVME_SCT_GENERIC, NVME_SC_ABORTED_BY_REQUEST, 0, TRUE); |
410 } 411} 412 413static void 414nvme_timeout(void *arg) 415{ 416 struct nvme_tracker *tr = arg; 417 struct nvme_qpair *qpair = tr->qpair; --- 53 unchanged lines hidden (view full) --- 471_nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req) 472{ 473 struct nvme_tracker *tr; 474 int err; 475 476 mtx_assert(&qpair->lock, MA_OWNED); 477 478 tr = TAILQ_FIRST(&qpair->free_tr); | 436 } 437} 438 439static void 440nvme_timeout(void *arg) 441{ 442 struct nvme_tracker *tr = arg; 443 struct nvme_qpair *qpair = tr->qpair; --- 53 unchanged lines hidden (view full) --- 497_nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req) 498{ 499 struct nvme_tracker *tr; 500 int err; 501 502 mtx_assert(&qpair->lock, MA_OWNED); 503 504 tr = TAILQ_FIRST(&qpair->free_tr); |
505 req->qpair = qpair; |
|
479 480 if (tr == NULL || !qpair->is_enabled) { 481 /* 482 * No tracker is available, or the qpair is disabled due to | 506 507 if (tr == NULL || !qpair->is_enabled) { 508 /* 509 * No tracker is available, or the qpair is disabled due to |
483 * an in-progress controller-level reset. 484 * 485 * Put the request on the qpair's request queue to be processed 486 * when a tracker frees up via a command completion or when 487 * the controller reset is completed. | 510 * an in-progress controller-level reset or controller 511 * failure. |
488 */ | 512 */ |
489 STAILQ_INSERT_TAIL(&qpair->queued_req, req, stailq); | 513 514 if (qpair->ctrlr->is_failed) { 515 /* 516 * The controller has failed. Post the request to a 517 * task where it will be aborted, so that we do not 518 * invoke the request's callback in the context 519 * of the submission. 520 */ 521 nvme_ctrlr_post_failed_request(qpair->ctrlr, req); 522 } else { 523 /* 524 * Put the request on the qpair's request queue to be 525 * processed when a tracker frees up via a command 526 * completion or when the controller reset is 527 * completed. 528 */ 529 STAILQ_INSERT_TAIL(&qpair->queued_req, req, stailq); 530 } |
490 return; 491 } 492 493 TAILQ_REMOVE(&qpair->free_tr, tr, tailq); 494 TAILQ_INSERT_TAIL(&qpair->outstanding_tr, tr, tailq); 495 tr->req = req; 496 497 if (req->uio == NULL) { --- 71 unchanged lines hidden (view full) --- 569 * Manually abort each outstanding I/O. This normally results in a 570 * retry, unless the retry count on the associated request has 571 * reached its limit. 572 */ 573 TAILQ_FOREACH_SAFE(tr, &qpair->outstanding_tr, tailq, tr_temp) { 574 device_printf(qpair->ctrlr->dev, 575 "aborting outstanding i/o\n"); 576 nvme_qpair_manual_complete_tracker(qpair, tr, NVME_SCT_GENERIC, | 531 return; 532 } 533 534 TAILQ_REMOVE(&qpair->free_tr, tr, tailq); 535 TAILQ_INSERT_TAIL(&qpair->outstanding_tr, tr, tailq); 536 tr->req = req; 537 538 if (req->uio == NULL) { --- 71 unchanged lines hidden (view full) --- 610 * Manually abort each outstanding I/O. This normally results in a 611 * retry, unless the retry count on the associated request has 612 * reached its limit. 613 */ 614 TAILQ_FOREACH_SAFE(tr, &qpair->outstanding_tr, tailq, tr_temp) { 615 device_printf(qpair->ctrlr->dev, 616 "aborting outstanding i/o\n"); 617 nvme_qpair_manual_complete_tracker(qpair, tr, NVME_SCT_GENERIC, |
577 NVME_SC_ABORTED_BY_REQUEST, TRUE); | 618 NVME_SC_ABORTED_BY_REQUEST, 0, TRUE); |
578 } 579 580 mtx_lock(&qpair->lock); 581 582 nvme_qpair_enable(qpair); 583 584 STAILQ_INIT(&temp); 585 STAILQ_SWAP(&qpair->queued_req, &temp, nvme_request); --- 31 unchanged lines hidden (view full) --- 617} 618 619void 620nvme_io_qpair_disable(struct nvme_qpair *qpair) 621{ 622 623 nvme_qpair_disable(qpair); 624} | 619 } 620 621 mtx_lock(&qpair->lock); 622 623 nvme_qpair_enable(qpair); 624 625 STAILQ_INIT(&temp); 626 STAILQ_SWAP(&qpair->queued_req, &temp, nvme_request); --- 31 unchanged lines hidden (view full) --- 658} 659 660void 661nvme_io_qpair_disable(struct nvme_qpair *qpair) 662{ 663 664 nvme_qpair_disable(qpair); 665} |
666 667void 668nvme_qpair_fail(struct nvme_qpair *qpair) 669{ 670 struct nvme_tracker *tr; 671 struct nvme_request *req; 672 673 mtx_lock(&qpair->lock); 674 675 while (!STAILQ_EMPTY(&qpair->queued_req)) { 676 req = STAILQ_FIRST(&qpair->queued_req); 677 STAILQ_REMOVE_HEAD(&qpair->queued_req, stailq); 678 device_printf(qpair->ctrlr->dev, 679 "failing queued i/o\n"); 680 mtx_unlock(&qpair->lock); 681 nvme_qpair_manual_complete_request(qpair, req, NVME_SCT_GENERIC, 682 NVME_SC_ABORTED_BY_REQUEST, TRUE); 683 mtx_lock(&qpair->lock); 684 } 685 686 /* Manually abort each outstanding I/O. */ 687 while (!TAILQ_EMPTY(&qpair->outstanding_tr)) { 688 tr = TAILQ_FIRST(&qpair->outstanding_tr); 689 /* 690 * Do not remove the tracker. The abort_tracker path will 691 * do that for us. 692 */ 693 device_printf(qpair->ctrlr->dev, 694 "failing outstanding i/o\n"); 695 mtx_unlock(&qpair->lock); 696 nvme_qpair_manual_complete_tracker(qpair, tr, NVME_SCT_GENERIC, 697 NVME_SC_ABORTED_BY_REQUEST, 1 /* do not retry */, TRUE); 698 mtx_lock(&qpair->lock); 699 } 700 701 mtx_unlock(&qpair->lock); 702} 703 |
|