aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_mbox.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-06-17 20:56:37 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-06-17 23:06:27 -0400
commited957684294618602b48f1950b0c9bbcb036583f (patch)
tree4e88dbb2e55013f973ad94099e2963dd507ea719 /drivers/scsi/lpfc/lpfc_mbox.c
parent2e0fef85e098f6794956b8b80b111179fbb4cbb7 (diff)
[SCSI] lpfc: NPIV: add SLI-3 interface
NPIV support is only available via new adapter interface extensions, termed SLI-3. This interface changes some of the basic behaviors such as command and response ring element sizes and data structures, as well as a change in buffer posting. Note: the new firmware extensions are found only on our mid-range and enterprise 4Gig adapters - so NPIV support is available only on these newer adapters. The latest firmware can be downloaded from the Emulex support page. 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_mbox.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c176
1 files changed, 159 insertions, 17 deletions
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 86757ec5305..977799c2b2c 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -232,6 +232,7 @@ lpfc_init_link(struct lpfc_hba * phba,
232 mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK; 232 mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK;
233 mb->mbxOwner = OWN_HOST; 233 mb->mbxOwner = OWN_HOST;
234 mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA; 234 mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA;
235 mb->un.varInitLnk.link_flags |= FLAGS_UNREG_LOGIN_ALL;
235 return; 236 return;
236} 237}
237 238
@@ -418,6 +419,10 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
418 for (i = 0; i < psli->num_rings; i++) { 419 for (i = 0; i < psli->num_rings; i++) {
419 pring = &psli->ring[i]; 420 pring = &psli->ring[i];
420 421
422 pring->sizeCiocb = phba->sli_rev == 3 ? SLI3_IOCB_CMD_SIZE:
423 SLI2_IOCB_CMD_SIZE;
424 pring->sizeRiocb = phba->sli_rev == 3 ? SLI3_IOCB_RSP_SIZE:
425 SLI2_IOCB_RSP_SIZE;
421 /* A ring MUST have both cmd and rsp entries defined to be 426 /* A ring MUST have both cmd and rsp entries defined to be
422 valid */ 427 valid */
423 if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) { 428 if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
@@ -432,8 +437,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
432 continue; 437 continue;
433 } 438 }
434 /* Command ring setup for ring */ 439 /* Command ring setup for ring */
435 pring->cmdringaddr = 440 pring->cmdringaddr = (void *)&phba->slim2p->IOCBs[iocbCnt];
436 (void *)&phba->slim2p->IOCBs[iocbCnt];
437 pcbp->rdsc[i].cmdEntries = pring->numCiocb; 441 pcbp->rdsc[i].cmdEntries = pring->numCiocb;
438 442
439 offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] - 443 offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
@@ -444,8 +448,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba)
444 iocbCnt += pring->numCiocb; 448 iocbCnt += pring->numCiocb;
445 449
446 /* Response ring setup for ring */ 450 /* Response ring setup for ring */
447 pring->rspringaddr = 451 pring->rspringaddr = (void *)&phba->slim2p->IOCBs[iocbCnt];
448 (void *)&phba->slim2p->IOCBs[iocbCnt];
449 452
450 pcbp->rdsc[i].rspEntries = pring->numRiocb; 453 pcbp->rdsc[i].rspEntries = pring->numRiocb;
451 offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] - 454 offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
@@ -463,11 +466,103 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
463 MAILBOX_t *mb = &pmb->mb; 466 MAILBOX_t *mb = &pmb->mb;
464 memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); 467 memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
465 mb->un.varRdRev.cv = 1; 468 mb->un.varRdRev.cv = 1;
469 mb->un.varRdRev.v3req = 1; /* Request SLI3 info */
466 mb->mbxCommand = MBX_READ_REV; 470 mb->mbxCommand = MBX_READ_REV;
467 mb->mbxOwner = OWN_HOST; 471 mb->mbxOwner = OWN_HOST;
468 return; 472 return;
469} 473}
470 474
475static void
476lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb,
477 struct lpfc_hbq_init *hbq_desc)
478{
479 hbqmb->profiles.profile2.seqlenbcnt = hbq_desc->seqlenbcnt;
480 hbqmb->profiles.profile2.maxlen = hbq_desc->maxlen;
481 hbqmb->profiles.profile2.seqlenoff = hbq_desc->seqlenoff;
482}
483
484static void
485lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb,
486 struct lpfc_hbq_init *hbq_desc)
487{
488 hbqmb->profiles.profile3.seqlenbcnt = hbq_desc->seqlenbcnt;
489 hbqmb->profiles.profile3.maxlen = hbq_desc->maxlen;
490 hbqmb->profiles.profile3.cmdcodeoff = hbq_desc->cmdcodeoff;
491 hbqmb->profiles.profile3.seqlenoff = hbq_desc->seqlenoff;
492 memcpy(&hbqmb->profiles.profile3.cmdmatch, hbq_desc->cmdmatch,
493 sizeof(hbqmb->profiles.profile3.cmdmatch));
494}
495
496static void
497lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb,
498 struct lpfc_hbq_init *hbq_desc)
499{
500 hbqmb->profiles.profile5.seqlenbcnt = hbq_desc->seqlenbcnt;
501 hbqmb->profiles.profile5.maxlen = hbq_desc->maxlen;
502 hbqmb->profiles.profile5.cmdcodeoff = hbq_desc->cmdcodeoff;
503 hbqmb->profiles.profile5.seqlenoff = hbq_desc->seqlenoff;
504 memcpy(&hbqmb->profiles.profile5.cmdmatch, hbq_desc->cmdmatch,
505 sizeof(hbqmb->profiles.profile5.cmdmatch));
506}
507
508void
509lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc,
510 uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb)
511{
512 int i;
513 MAILBOX_t *mb = &pmb->mb;
514 struct config_hbq_var *hbqmb = &mb->un.varCfgHbq;
515
516 memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
517 hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */
518 hbqmb->recvNotify = hbq_desc->rn; /* Receive
519 * Notification */
520 hbqmb->numMask = hbq_desc->mask_count; /* # R_CTL/TYPE masks
521 * # in words 0-19 */
522 hbqmb->profile = hbq_desc->profile; /* Selection profile:
523 * 0 = all,
524 * 7 = logentry */
525 hbqmb->ringMask = hbq_desc->ring_mask; /* Binds HBQ to a ring
526 * e.g. Ring0=b0001,
527 * ring2=b0100 */
528 hbqmb->headerLen = hbq_desc->headerLen; /* 0 if not profile 4
529 * or 5 */
530 hbqmb->logEntry = hbq_desc->logEntry; /* Set to 1 if this
531 * HBQ will be used
532 * for LogEntry
533 * buffers */
534 hbqmb->hbqaddrLow = putPaddrLow(phba->hbqslimp.phys) +
535 hbq_entry_index * sizeof(struct lpfc_hbq_entry);
536 hbqmb->hbqaddrHigh = putPaddrHigh(phba->hbqslimp.phys);
537
538 mb->mbxCommand = MBX_CONFIG_HBQ;
539 mb->mbxOwner = OWN_HOST;
540
541 /* Copy info for profiles 2,3,5. Other
542 * profiles this area is reserved
543 */
544 if (hbq_desc->profile == 2)
545 lpfc_build_hbq_profile2(hbqmb, hbq_desc);
546 else if (hbq_desc->profile == 3)
547 lpfc_build_hbq_profile3(hbqmb, hbq_desc);
548 else if (hbq_desc->profile == 5)
549 lpfc_build_hbq_profile5(hbqmb, hbq_desc);
550
551 /* Return if no rctl / type masks for this HBQ */
552 if (!hbq_desc->mask_count)
553 return;
554
555 /* Otherwise we setup specific rctl / type masks for this HBQ */
556 for (i = 0; i < hbq_desc->mask_count; i++) {
557 hbqmb->hbqMasks[i].tmatch = hbq_desc->hbqMasks[i].tmatch;
558 hbqmb->hbqMasks[i].tmask = hbq_desc->hbqMasks[i].tmask;
559 hbqmb->hbqMasks[i].rctlmatch = hbq_desc->hbqMasks[i].rctlmatch;
560 hbqmb->hbqMasks[i].rctlmask = hbq_desc->hbqMasks[i].rctlmask;
561 }
562
563 return;
564}
565
471void 566void
472lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) 567lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
473{ 568{
@@ -512,13 +607,14 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
512void 607void
513lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) 608lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
514{ 609{
610 MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr;
515 MAILBOX_t *mb = &pmb->mb; 611 MAILBOX_t *mb = &pmb->mb;
516 dma_addr_t pdma_addr; 612 dma_addr_t pdma_addr;
517 uint32_t bar_low, bar_high; 613 uint32_t bar_low, bar_high;
518 size_t offset; 614 size_t offset;
519 struct lpfc_hgp hgp; 615 struct lpfc_hgp hgp;
520 void __iomem *to_slim;
521 int i; 616 int i;
617 uint32_t pgp_offset;
522 618
523 memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); 619 memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
524 mb->mbxCommand = MBX_CONFIG_PORT; 620 mb->mbxCommand = MBX_CONFIG_PORT;
@@ -531,12 +627,21 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
531 mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr); 627 mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
532 mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr); 628 mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
533 629
630 /* If HBA supports SLI=3 ask for it */
631
632 mb->un.varCfgPort.sli_mode = phba->sli_rev;
633 if (phba->sli_rev == 3) {
634 mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
635 mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */
636 }
637
534 /* Now setup pcb */ 638 /* Now setup pcb */
535 phba->slim2p->pcb.type = TYPE_NATIVE_SLI2; 639 phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
536 phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2; 640 phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
537 641
538 /* Setup Mailbox pointers */ 642 /* Setup Mailbox pointers */
539 phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t); 643 phba->slim2p->pcb.mailBoxSize = offsetof(MAILBOX_t, us) +
644 sizeof(struct sli2_desc);
540 offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p; 645 offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
541 pdma_addr = phba->slim2p_mapping + offset; 646 pdma_addr = phba->slim2p_mapping + offset;
542 phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr); 647 phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
@@ -564,29 +669,70 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
564 pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low); 669 pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
565 pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high); 670 pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
566 671
672 /*
673 * Set up HGP - Port Memory
674 *
675 * The port expects the host get/put pointers to reside in memory
676 * following the "non-diagnostic" mode mailbox (32 words, 0x80 bytes)
677 * area of SLIM. In SLI-2 mode, there's an additional 16 reserved
678 * words (0x40 bytes). This area is not reserved if HBQs are
679 * configured in SLI-3.
680 *
681 * CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80
682 * RR0Get 0xc4 0x84
683 * CR1Put 0xc8 0x88
684 * RR1Get 0xcc 0x8c
685 * CR2Put 0xd0 0x90
686 * RR2Get 0xd4 0x94
687 * CR3Put 0xd8 0x98
688 * RR3Get 0xdc 0x9c
689 *
690 * Reserved 0xa0-0xbf
691 * If HBQs configured:
692 * HBQ 0 Put ptr 0xc0
693 * HBQ 1 Put ptr 0xc4
694 * HBQ 2 Put ptr 0xc8
695 * ......
696 * HBQ(M-1)Put Pointer 0xc0+(M-1)*4
697 *
698 */
699
700 if (phba->sli_rev == 3) {
701 phba->host_gp = &mb_slim->us.s3.host[0];
702 phba->hbq_put = &mb_slim->us.s3.hbq_put[0];
703 } else {
704 phba->host_gp = &mb_slim->us.s2.host[0];
705 phba->hbq_put = NULL;
706 }
567 707
568 /* mask off BAR0's flag bits 0 - 3 */ 708 /* mask off BAR0's flag bits 0 - 3 */
569 phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) + 709 phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
570 (SLIMOFF*sizeof(uint32_t)); 710 (void __iomem *) phba->host_gp -
711 (void __iomem *)phba->MBslimaddr;
571 if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64) 712 if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
572 phba->slim2p->pcb.hgpAddrHigh = bar_high; 713 phba->slim2p->pcb.hgpAddrHigh = bar_high;
573 else 714 else
574 phba->slim2p->pcb.hgpAddrHigh = 0; 715 phba->slim2p->pcb.hgpAddrHigh = 0;
575 /* write HGP data to SLIM at the required longword offset */ 716 /* write HGP data to SLIM at the required longword offset */
576 memset(&hgp, 0, sizeof(struct lpfc_hgp)); 717 memset(&hgp, 0, sizeof(struct lpfc_hgp));
577 to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
578 718
579 for (i=0; i < phba->sli.num_rings; i++) { 719 for (i=0; i < phba->sli.num_rings; i++) {
580 lpfc_memcpy_to_slim(to_slim, &hgp, sizeof(struct lpfc_hgp)); 720 lpfc_memcpy_to_slim(phba->host_gp + i, &hgp,
581 to_slim += sizeof (struct lpfc_hgp); 721 sizeof(*phba->host_gp));
582 } 722 }
583 723
584 /* Setup Port Group ring pointer */ 724 /* Setup Port Group ring pointer */
585 offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port - 725 if (phba->sli_rev == 3)
586 (uint8_t *)phba->slim2p; 726 pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s3_pgp.port -
587 pdma_addr = phba->slim2p_mapping + offset; 727 (uint8_t *)phba->slim2p;
728 else
729 pgp_offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
730 (uint8_t *)phba->slim2p;
731
732 pdma_addr = phba->slim2p_mapping + pgp_offset;
588 phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr); 733 phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
589 phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr); 734 phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
735 phba->hbq_get = &phba->slim2p->mbx.us.s3_pgp.hbq_get[0];
590 736
591 /* Use callback routine to setp rings in the pcb */ 737 /* Use callback routine to setp rings in the pcb */
592 lpfc_config_pcb_setup(phba); 738 lpfc_config_pcb_setup(phba);
@@ -603,10 +749,6 @@ lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
603 /* Swap PCB if needed */ 749 /* Swap PCB if needed */
604 lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb, 750 lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
605 sizeof (PCB_t)); 751 sizeof (PCB_t));
606
607 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
608 "%d:0405 Service Level Interface (SLI) 2 selected\n",
609 phba->brd_no);
610} 752}
611 753
612void 754void