aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-08-02 11:10:31 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-08-01 13:24:10 -0400
commit51ef4c26891a734bc8416b639ad460a8162926bc (patch)
tree8279e11bf1a0a3200e8aa9bb3d956345ef73533c /drivers/scsi/lpfc/lpfc_sli.c
parent78b2d852a88cd2a55e3ab632109de045d58b83e3 (diff)
[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes
- Fix vport ndlp ref counting errors - Fix use after free of ndlp structure - Use the correct flag to check for LOADING setting. - Fix driver unload bugs (related to shost references) after link down or rscn - Fix up HBQ initialization - Fix port_list locking around driver unload. - Fix references to hostdata as a phba - Fix GFFID type offset to work correctly with big endian structure. - Only call pci_disable_msi if the pci_enable_msi succeeded - Fix vport_delete wait/fail if in discovery - Put a reference on the nameservers ndlp when performing CT traffic. - Remove unbalanced hba unlock. - Fix up HBQ processing - Fix lpfc debugfs discovery trace output for ELS rsp cmpl - Send ADISC when rpi is 0 - Stop FDISC retrying forever - Unable to retrieve correct config parameter for vport - Fix sli_validate_fcp_iocb, sli_sum_iocb, sli_abort_iocb to be vport-aware. - Fix index-out-of-range error in iocb. Spotted by Coverity. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c128
1 files changed, 79 insertions, 49 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 5417bc26f18..c54a9ea336a 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -545,7 +545,8 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
545 return NULL; 545 return NULL;
546 } 546 }
547 547
548 return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx; 548 return (struct lpfc_hbq_entry *) phba->hbqs[hbqno].hbq_virt +
549 hbqp->hbqPutIdx;
549} 550}
550 551
551void 552void
@@ -553,18 +554,21 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba)
553{ 554{
554 struct lpfc_dmabuf *dmabuf, *next_dmabuf; 555 struct lpfc_dmabuf *dmabuf, *next_dmabuf;
555 struct hbq_dmabuf *hbq_buf; 556 struct hbq_dmabuf *hbq_buf;
557 int i, hbq_count;
556 558
559 hbq_count = lpfc_sli_hbq_count();
557 /* Return all memory used by all HBQs */ 560 /* Return all memory used by all HBQs */
558 list_for_each_entry_safe(dmabuf, next_dmabuf, 561 for (i = 0; i < hbq_count; ++i) {
559 &phba->hbq_buffer_list, list) { 562 list_for_each_entry_safe(dmabuf, next_dmabuf,
560 hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf); 563 &phba->hbqs[i].hbq_buffer_list, list) {
561 list_del(&hbq_buf->dbuf.list); 564 hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf);
562 lpfc_hbq_free(phba, hbq_buf->dbuf.virt, hbq_buf->dbuf.phys); 565 list_del(&hbq_buf->dbuf.list);
563 kfree(hbq_buf); 566 (phba->hbqs[i].hbq_free_buffer)(phba, hbq_buf);
567 }
564 } 568 }
565} 569}
566 570
567static void 571static struct lpfc_hbq_entry *
568lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, 572lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
569 struct hbq_dmabuf *hbq_buf) 573 struct hbq_dmabuf *hbq_buf)
570{ 574{
@@ -578,7 +582,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
578 582
579 hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr)); 583 hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr));
580 hbqe->bde.addrLow = le32_to_cpu(putPaddrLow(physaddr)); 584 hbqe->bde.addrLow = le32_to_cpu(putPaddrLow(physaddr));
581 hbqe->bde.tus.f.bdeSize = FCELSSIZE; 585 hbqe->bde.tus.f.bdeSize = hbq_buf->size;
582 hbqe->bde.tus.f.bdeFlags = 0; 586 hbqe->bde.tus.f.bdeFlags = 0;
583 hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w); 587 hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w);
584 hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag); 588 hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag);
@@ -587,8 +591,9 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
587 writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno); 591 writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno);
588 /* flush */ 592 /* flush */
589 readl(phba->hbq_put + hbqno); 593 readl(phba->hbq_put + hbqno);
590 list_add_tail(&hbq_buf->dbuf.list, &phba->hbq_buffer_list); 594 list_add_tail(&hbq_buf->dbuf.list, &hbqp->hbq_buffer_list);
591 } 595 }
596 return hbqe;
592} 597}
593 598
594static struct lpfc_hbq_init lpfc_els_hbq = { 599static struct lpfc_hbq_init lpfc_els_hbq = {
@@ -596,14 +601,26 @@ static struct lpfc_hbq_init lpfc_els_hbq = {
596 .entry_count = 200, 601 .entry_count = 200,
597 .mask_count = 0, 602 .mask_count = 0,
598 .profile = 0, 603 .profile = 0,
599 .ring_mask = 1 << LPFC_ELS_RING, 604 .ring_mask = (1 << LPFC_ELS_RING),
600 .buffer_count = 0, 605 .buffer_count = 0,
601 .init_count = 20, 606 .init_count = 20,
602 .add_count = 5, 607 .add_count = 5,
603}; 608};
604 609
610static struct lpfc_hbq_init lpfc_extra_hbq = {
611 .rn = 1,
612 .entry_count = 200,
613 .mask_count = 0,
614 .profile = 0,
615 .ring_mask = (1 << LPFC_EXTRA_RING),
616 .buffer_count = 0,
617 .init_count = 0,
618 .add_count = 5,
619};
620
605struct lpfc_hbq_init *lpfc_hbq_defs[] = { 621struct lpfc_hbq_init *lpfc_hbq_defs[] = {
606 &lpfc_els_hbq, 622 &lpfc_els_hbq,
623 &lpfc_extra_hbq,
607}; 624};
608 625
609int 626int
@@ -612,6 +629,10 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
612 uint32_t i, start, end; 629 uint32_t i, start, end;
613 struct hbq_dmabuf *hbq_buffer; 630 struct hbq_dmabuf *hbq_buffer;
614 631
632 if (!phba->hbqs[hbqno].hbq_alloc_buffer) {
633 return 0;
634 }
635
615 start = lpfc_hbq_defs[hbqno]->buffer_count; 636 start = lpfc_hbq_defs[hbqno]->buffer_count;
616 end = count + lpfc_hbq_defs[hbqno]->buffer_count; 637 end = count + lpfc_hbq_defs[hbqno]->buffer_count;
617 if (end > lpfc_hbq_defs[hbqno]->entry_count) { 638 if (end > lpfc_hbq_defs[hbqno]->entry_count) {
@@ -620,17 +641,14 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count)
620 641
621 /* Populate HBQ entries */ 642 /* Populate HBQ entries */
622 for (i = start; i < end; i++) { 643 for (i = start; i < end; i++) {
623 hbq_buffer = kmalloc(sizeof(struct hbq_dmabuf), 644 hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
624 GFP_KERNEL);
625 if (!hbq_buffer) 645 if (!hbq_buffer)
626 return 1; 646 return 1;
627 hbq_buffer->dbuf.virt = lpfc_hbq_alloc(phba, MEM_PRI,
628 &hbq_buffer->dbuf.phys);
629 if (hbq_buffer->dbuf.virt == NULL)
630 return 1;
631 hbq_buffer->tag = (i | (hbqno << 16)); 647 hbq_buffer->tag = (i | (hbqno << 16));
632 lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer); 648 if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer))
633 lpfc_hbq_defs[hbqno]->buffer_count++; 649 lpfc_hbq_defs[hbqno]->buffer_count++;
650 else
651 (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
634 } 652 }
635 return 0; 653 return 0;
636} 654}
@@ -654,10 +672,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
654{ 672{
655 struct lpfc_dmabuf *d_buf; 673 struct lpfc_dmabuf *d_buf;
656 struct hbq_dmabuf *hbq_buf; 674 struct hbq_dmabuf *hbq_buf;
675 uint32_t hbqno;
676
677 hbqno = tag >> 16;
678 if (hbqno > LPFC_MAX_HBQS)
679 return NULL;
657 680
658 list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) { 681 list_for_each_entry(d_buf, &phba->hbqs[hbqno].hbq_buffer_list, list) {
659 hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); 682 hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
660 if ((hbq_buf->tag & 0xffff) == tag) { 683 if (hbq_buf->tag == tag) {
661 return hbq_buf; 684 return hbq_buf;
662 } 685 }
663 } 686 }
@@ -668,13 +691,15 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
668} 691}
669 692
670void 693void
671lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp) 694lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer)
672{ 695{
673 uint32_t hbqno; 696 uint32_t hbqno;
674 697
675 if (sp) { 698 if (hbq_buffer) {
676 hbqno = sp->tag >> 16; 699 hbqno = hbq_buffer->tag >> 16;
677 lpfc_sli_hbq_to_firmware(phba, hbqno, sp); 700 if (!lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) {
701 (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
702 }
678 } 703 }
679} 704}
680 705
@@ -904,21 +929,26 @@ static struct lpfc_dmabuf *
904lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) 929lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag)
905{ 930{
906 struct hbq_dmabuf *hbq_entry, *new_hbq_entry; 931 struct hbq_dmabuf *hbq_entry, *new_hbq_entry;
932 uint32_t hbqno;
933 void *virt; /* virtual address ptr */
934 dma_addr_t phys; /* mapped address */
907 935
908 hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); 936 hbq_entry = lpfc_sli_hbqbuf_find(phba, tag);
909 if (hbq_entry == NULL) 937 if (hbq_entry == NULL)
910 return NULL; 938 return NULL;
911 list_del(&hbq_entry->dbuf.list); 939 list_del(&hbq_entry->dbuf.list);
912 new_hbq_entry = kmalloc(sizeof(struct hbq_dmabuf), GFP_ATOMIC); 940
941 hbqno = tag >> 16;
942 new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba);
913 if (new_hbq_entry == NULL) 943 if (new_hbq_entry == NULL)
914 return &hbq_entry->dbuf; 944 return &hbq_entry->dbuf;
915 new_hbq_entry->dbuf = hbq_entry->dbuf;
916 new_hbq_entry->tag = -1; 945 new_hbq_entry->tag = -1;
917 hbq_entry->dbuf.virt = lpfc_hbq_alloc(phba, 0, &hbq_entry->dbuf.phys); 946 phys = new_hbq_entry->dbuf.phys;
918 if (hbq_entry->dbuf.virt == NULL) { 947 virt = new_hbq_entry->dbuf.virt;
919 kfree(new_hbq_entry); 948 new_hbq_entry->dbuf.phys = hbq_entry->dbuf.phys;
920 return &hbq_entry->dbuf; 949 new_hbq_entry->dbuf.virt = hbq_entry->dbuf.virt;
921 } 950 hbq_entry->dbuf.phys = phys;
951 hbq_entry->dbuf.virt = virt;
922 lpfc_sli_free_hbq(phba, hbq_entry); 952 lpfc_sli_free_hbq(phba, hbq_entry);
923 return &new_hbq_entry->dbuf; 953 return &new_hbq_entry->dbuf;
924} 954}
@@ -964,7 +994,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
964 irsp->un.ulpWord[3]); 994 irsp->un.ulpWord[3]);
965 if (irsp->ulpBdeCount == 2) 995 if (irsp->ulpBdeCount == 2)
966 saveq->context3 = lpfc_sli_replace_hbqbuff(phba, 996 saveq->context3 = lpfc_sli_replace_hbqbuff(phba,
967 irsp->un.ulpWord[15]); 997 irsp->unsli3.sli3Words[7]);
968 } 998 }
969 999
970 /* unSolicited Responses */ 1000 /* unSolicited Responses */
@@ -2189,8 +2219,8 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
2189 phba->hbqs[hbqno].local_hbqGetIdx = 0; 2219 phba->hbqs[hbqno].local_hbqGetIdx = 0;
2190 phba->hbqs[hbqno].entry_count = 2220 phba->hbqs[hbqno].entry_count =
2191 lpfc_hbq_defs[hbqno]->entry_count; 2221 lpfc_hbq_defs[hbqno]->entry_count;
2192 lpfc_config_hbq(phba, lpfc_hbq_defs[hbqno], hbq_entry_index, 2222 lpfc_config_hbq(phba, hbqno, lpfc_hbq_defs[hbqno],
2193 pmb); 2223 hbq_entry_index, pmb);
2194 hbq_entry_index += phba->hbqs[hbqno].entry_count; 2224 hbq_entry_index += phba->hbqs[hbqno].entry_count;
2195 2225
2196 if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { 2226 if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
@@ -3433,8 +3463,8 @@ abort_iotag_exit:
3433} 3463}
3434 3464
3435static int 3465static int
3436lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, 3466lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport,
3437 uint64_t lun_id, uint32_t ctx, 3467 uint16_t tgt_id, uint64_t lun_id,
3438 lpfc_ctx_cmd ctx_cmd) 3468 lpfc_ctx_cmd ctx_cmd)
3439{ 3469{
3440 struct lpfc_scsi_buf *lpfc_cmd; 3470 struct lpfc_scsi_buf *lpfc_cmd;
@@ -3444,6 +3474,9 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
3444 if (!(iocbq->iocb_flag & LPFC_IO_FCP)) 3474 if (!(iocbq->iocb_flag & LPFC_IO_FCP))
3445 return rc; 3475 return rc;
3446 3476
3477 if (iocbq->vport != vport)
3478 return rc;
3479
3447 lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); 3480 lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
3448 cmnd = lpfc_cmd->pCmd; 3481 cmnd = lpfc_cmd->pCmd;
3449 3482
@@ -3460,10 +3493,6 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
3460 if (cmnd->device->id == tgt_id) 3493 if (cmnd->device->id == tgt_id)
3461 rc = 0; 3494 rc = 0;
3462 break; 3495 break;
3463 case LPFC_CTX_CTX:
3464 if (iocbq->iocb.ulpContext == ctx)
3465 rc = 0;
3466 break;
3467 case LPFC_CTX_HOST: 3496 case LPFC_CTX_HOST:
3468 rc = 0; 3497 rc = 0;
3469 break; 3498 break;
@@ -3477,17 +3506,18 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id,
3477} 3506}
3478 3507
3479int 3508int
3480lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 3509lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
3481 uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) 3510 lpfc_ctx_cmd ctx_cmd)
3482{ 3511{
3512 struct lpfc_hba *phba = vport->phba;
3483 struct lpfc_iocbq *iocbq; 3513 struct lpfc_iocbq *iocbq;
3484 int sum, i; 3514 int sum, i;
3485 3515
3486 for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { 3516 for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) {
3487 iocbq = phba->sli.iocbq_lookup[i]; 3517 iocbq = phba->sli.iocbq_lookup[i];
3488 3518
3489 if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id, 3519 if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id,
3490 0, ctx_cmd) == 0) 3520 ctx_cmd) == 0)
3491 sum++; 3521 sum++;
3492 } 3522 }
3493 3523
@@ -3503,10 +3533,10 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
3503} 3533}
3504 3534
3505int 3535int
3506lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 3536lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
3507 uint16_t tgt_id, uint64_t lun_id, uint32_t ctx, 3537 uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd abort_cmd)
3508 lpfc_ctx_cmd abort_cmd)
3509{ 3538{
3539 struct lpfc_hba *phba = vport->phba;
3510 struct lpfc_iocbq *iocbq; 3540 struct lpfc_iocbq *iocbq;
3511 struct lpfc_iocbq *abtsiocb; 3541 struct lpfc_iocbq *abtsiocb;
3512 IOCB_t *cmd = NULL; 3542 IOCB_t *cmd = NULL;
@@ -3516,7 +3546,7 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
3516 for (i = 1; i <= phba->sli.last_iotag; i++) { 3546 for (i = 1; i <= phba->sli.last_iotag; i++) {
3517 iocbq = phba->sli.iocbq_lookup[i]; 3547 iocbq = phba->sli.iocbq_lookup[i];
3518 3548
3519 if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0, 3549 if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id,
3520 abort_cmd) != 0) 3550 abort_cmd) != 0)
3521 continue; 3551 continue;
3522 3552