diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_mbox.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 674 |
1 files changed, 631 insertions, 43 deletions
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 134fc7fc2127..b9b451c09010 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2008 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2009 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -28,8 +28,10 @@ | |||
28 | 28 | ||
29 | #include <scsi/scsi.h> | 29 | #include <scsi/scsi.h> |
30 | 30 | ||
31 | #include "lpfc_hw4.h" | ||
31 | #include "lpfc_hw.h" | 32 | #include "lpfc_hw.h" |
32 | #include "lpfc_sli.h" | 33 | #include "lpfc_sli.h" |
34 | #include "lpfc_sli4.h" | ||
33 | #include "lpfc_nl.h" | 35 | #include "lpfc_nl.h" |
34 | #include "lpfc_disc.h" | 36 | #include "lpfc_disc.h" |
35 | #include "lpfc_scsi.h" | 37 | #include "lpfc_scsi.h" |
@@ -39,6 +41,44 @@ | |||
39 | #include "lpfc_compat.h" | 41 | #include "lpfc_compat.h" |
40 | 42 | ||
41 | /** | 43 | /** |
44 | * lpfc_dump_static_vport - Dump HBA's static vport information. | ||
45 | * @phba: pointer to lpfc hba data structure. | ||
46 | * @pmb: pointer to the driver internal queue element for mailbox command. | ||
47 | * @offset: offset for dumping vport info. | ||
48 | * | ||
49 | * The dump mailbox command provides a method for the device driver to obtain | ||
50 | * various types of information from the HBA device. | ||
51 | * | ||
52 | * This routine prepares the mailbox command for dumping list of static | ||
53 | * vports to be created. | ||
54 | **/ | ||
55 | void | ||
56 | lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, | ||
57 | uint16_t offset) | ||
58 | { | ||
59 | MAILBOX_t *mb; | ||
60 | void *ctx; | ||
61 | |||
62 | mb = &pmb->u.mb; | ||
63 | ctx = pmb->context2; | ||
64 | |||
65 | /* Setup to dump vport info region */ | ||
66 | memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); | ||
67 | mb->mbxCommand = MBX_DUMP_MEMORY; | ||
68 | mb->un.varDmp.cv = 1; | ||
69 | mb->un.varDmp.type = DMP_NV_PARAMS; | ||
70 | mb->un.varDmp.entry_index = offset; | ||
71 | mb->un.varDmp.region_id = DMP_REGION_VPORT; | ||
72 | mb->un.varDmp.word_cnt = DMP_RSP_SIZE/sizeof(uint32_t); | ||
73 | mb->un.varDmp.co = 0; | ||
74 | mb->un.varDmp.resp_offset = 0; | ||
75 | pmb->context2 = ctx; | ||
76 | mb->mbxOwner = OWN_HOST; | ||
77 | |||
78 | return; | ||
79 | } | ||
80 | |||
81 | /** | ||
42 | * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory | 82 | * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory |
43 | * @phba: pointer to lpfc hba data structure. | 83 | * @phba: pointer to lpfc hba data structure. |
44 | * @pmb: pointer to the driver internal queue element for mailbox command. | 84 | * @pmb: pointer to the driver internal queue element for mailbox command. |
@@ -58,7 +98,7 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) | |||
58 | MAILBOX_t *mb; | 98 | MAILBOX_t *mb; |
59 | void *ctx; | 99 | void *ctx; |
60 | 100 | ||
61 | mb = &pmb->mb; | 101 | mb = &pmb->u.mb; |
62 | ctx = pmb->context2; | 102 | ctx = pmb->context2; |
63 | 103 | ||
64 | /* Setup to dump VPD region */ | 104 | /* Setup to dump VPD region */ |
@@ -90,7 +130,7 @@ lpfc_dump_wakeup_param(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
90 | MAILBOX_t *mb; | 130 | MAILBOX_t *mb; |
91 | void *ctx; | 131 | void *ctx; |
92 | 132 | ||
93 | mb = &pmb->mb; | 133 | mb = &pmb->u.mb; |
94 | /* Save context so that we can restore after memset */ | 134 | /* Save context so that we can restore after memset */ |
95 | ctx = pmb->context2; | 135 | ctx = pmb->context2; |
96 | 136 | ||
@@ -125,7 +165,7 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
125 | { | 165 | { |
126 | MAILBOX_t *mb; | 166 | MAILBOX_t *mb; |
127 | 167 | ||
128 | mb = &pmb->mb; | 168 | mb = &pmb->u.mb; |
129 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 169 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
130 | mb->mbxCommand = MBX_READ_NV; | 170 | mb->mbxCommand = MBX_READ_NV; |
131 | mb->mbxOwner = OWN_HOST; | 171 | mb->mbxOwner = OWN_HOST; |
@@ -151,7 +191,7 @@ lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, | |||
151 | { | 191 | { |
152 | MAILBOX_t *mb; | 192 | MAILBOX_t *mb; |
153 | 193 | ||
154 | mb = &pmb->mb; | 194 | mb = &pmb->u.mb; |
155 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 195 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
156 | mb->mbxCommand = MBX_ASYNCEVT_ENABLE; | 196 | mb->mbxCommand = MBX_ASYNCEVT_ENABLE; |
157 | mb->un.varCfgAsyncEvent.ring = ring; | 197 | mb->un.varCfgAsyncEvent.ring = ring; |
@@ -177,7 +217,7 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
177 | { | 217 | { |
178 | MAILBOX_t *mb; | 218 | MAILBOX_t *mb; |
179 | 219 | ||
180 | mb = &pmb->mb; | 220 | mb = &pmb->u.mb; |
181 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 221 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
182 | mb->mbxCommand = MBX_HEARTBEAT; | 222 | mb->mbxCommand = MBX_HEARTBEAT; |
183 | mb->mbxOwner = OWN_HOST; | 223 | mb->mbxOwner = OWN_HOST; |
@@ -211,7 +251,7 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) | |||
211 | struct lpfc_sli *psli; | 251 | struct lpfc_sli *psli; |
212 | 252 | ||
213 | psli = &phba->sli; | 253 | psli = &phba->sli; |
214 | mb = &pmb->mb; | 254 | mb = &pmb->u.mb; |
215 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 255 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
216 | 256 | ||
217 | INIT_LIST_HEAD(&mp->list); | 257 | INIT_LIST_HEAD(&mp->list); |
@@ -248,7 +288,7 @@ lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
248 | { | 288 | { |
249 | MAILBOX_t *mb; | 289 | MAILBOX_t *mb; |
250 | 290 | ||
251 | mb = &pmb->mb; | 291 | mb = &pmb->u.mb; |
252 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 292 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
253 | 293 | ||
254 | mb->un.varClearLA.eventTag = phba->fc_eventTag; | 294 | mb->un.varClearLA.eventTag = phba->fc_eventTag; |
@@ -275,7 +315,7 @@ void | |||
275 | lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | 315 | lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) |
276 | { | 316 | { |
277 | struct lpfc_vport *vport = phba->pport; | 317 | struct lpfc_vport *vport = phba->pport; |
278 | MAILBOX_t *mb = &pmb->mb; | 318 | MAILBOX_t *mb = &pmb->u.mb; |
279 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 319 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
280 | 320 | ||
281 | /* NEW_FEATURE | 321 | /* NEW_FEATURE |
@@ -321,7 +361,7 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
321 | int | 361 | int |
322 | lpfc_config_msi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | 362 | lpfc_config_msi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
323 | { | 363 | { |
324 | MAILBOX_t *mb = &pmb->mb; | 364 | MAILBOX_t *mb = &pmb->u.mb; |
325 | uint32_t attentionConditions[2]; | 365 | uint32_t attentionConditions[2]; |
326 | 366 | ||
327 | /* Sanity check */ | 367 | /* Sanity check */ |
@@ -405,7 +445,7 @@ lpfc_init_link(struct lpfc_hba * phba, | |||
405 | struct lpfc_sli *psli; | 445 | struct lpfc_sli *psli; |
406 | MAILBOX_t *mb; | 446 | MAILBOX_t *mb; |
407 | 447 | ||
408 | mb = &pmb->mb; | 448 | mb = &pmb->u.mb; |
409 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 449 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
410 | 450 | ||
411 | psli = &phba->sli; | 451 | psli = &phba->sli; |
@@ -492,7 +532,7 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) | |||
492 | struct lpfc_sli *psli; | 532 | struct lpfc_sli *psli; |
493 | 533 | ||
494 | psli = &phba->sli; | 534 | psli = &phba->sli; |
495 | mb = &pmb->mb; | 535 | mb = &pmb->u.mb; |
496 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 536 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
497 | 537 | ||
498 | mb->mbxOwner = OWN_HOST; | 538 | mb->mbxOwner = OWN_HOST; |
@@ -515,7 +555,7 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) | |||
515 | mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); | 555 | mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); |
516 | mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); | 556 | mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); |
517 | mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); | 557 | mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); |
518 | mb->un.varRdSparm.vpi = vpi; | 558 | mb->un.varRdSparm.vpi = vpi + phba->vpi_base; |
519 | 559 | ||
520 | /* save address for completion */ | 560 | /* save address for completion */ |
521 | pmb->context1 = mp; | 561 | pmb->context1 = mp; |
@@ -544,10 +584,12 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did, | |||
544 | { | 584 | { |
545 | MAILBOX_t *mb; | 585 | MAILBOX_t *mb; |
546 | 586 | ||
547 | mb = &pmb->mb; | 587 | mb = &pmb->u.mb; |
548 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 588 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
549 | 589 | ||
550 | mb->un.varUnregDID.did = did; | 590 | mb->un.varUnregDID.did = did; |
591 | if (vpi != 0xffff) | ||
592 | vpi += phba->vpi_base; | ||
551 | mb->un.varUnregDID.vpi = vpi; | 593 | mb->un.varUnregDID.vpi = vpi; |
552 | 594 | ||
553 | mb->mbxCommand = MBX_UNREG_D_ID; | 595 | mb->mbxCommand = MBX_UNREG_D_ID; |
@@ -573,7 +615,7 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
573 | { | 615 | { |
574 | MAILBOX_t *mb; | 616 | MAILBOX_t *mb; |
575 | 617 | ||
576 | mb = &pmb->mb; | 618 | mb = &pmb->u.mb; |
577 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 619 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
578 | 620 | ||
579 | mb->mbxCommand = MBX_READ_CONFIG; | 621 | mb->mbxCommand = MBX_READ_CONFIG; |
@@ -598,7 +640,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
598 | { | 640 | { |
599 | MAILBOX_t *mb; | 641 | MAILBOX_t *mb; |
600 | 642 | ||
601 | mb = &pmb->mb; | 643 | mb = &pmb->u.mb; |
602 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 644 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
603 | 645 | ||
604 | mb->mbxCommand = MBX_READ_LNK_STAT; | 646 | mb->mbxCommand = MBX_READ_LNK_STAT; |
@@ -607,7 +649,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
607 | } | 649 | } |
608 | 650 | ||
609 | /** | 651 | /** |
610 | * lpfc_reg_login - Prepare a mailbox command for registering remote login | 652 | * lpfc_reg_rpi - Prepare a mailbox command for registering remote login |
611 | * @phba: pointer to lpfc hba data structure. | 653 | * @phba: pointer to lpfc hba data structure. |
612 | * @vpi: virtual N_Port identifier. | 654 | * @vpi: virtual N_Port identifier. |
613 | * @did: remote port identifier. | 655 | * @did: remote port identifier. |
@@ -631,17 +673,23 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
631 | * 1 - DMA memory allocation failed | 673 | * 1 - DMA memory allocation failed |
632 | **/ | 674 | **/ |
633 | int | 675 | int |
634 | lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, | 676 | lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, |
635 | uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag) | 677 | uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag) |
636 | { | 678 | { |
637 | MAILBOX_t *mb = &pmb->mb; | 679 | MAILBOX_t *mb = &pmb->u.mb; |
638 | uint8_t *sparam; | 680 | uint8_t *sparam; |
639 | struct lpfc_dmabuf *mp; | 681 | struct lpfc_dmabuf *mp; |
640 | 682 | ||
641 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 683 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
642 | 684 | ||
643 | mb->un.varRegLogin.rpi = 0; | 685 | mb->un.varRegLogin.rpi = 0; |
644 | mb->un.varRegLogin.vpi = vpi; | 686 | if (phba->sli_rev == LPFC_SLI_REV4) { |
687 | mb->un.varRegLogin.rpi = lpfc_sli4_alloc_rpi(phba); | ||
688 | if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR) | ||
689 | return 1; | ||
690 | } | ||
691 | |||
692 | mb->un.varRegLogin.vpi = vpi + phba->vpi_base; | ||
645 | mb->un.varRegLogin.did = did; | 693 | mb->un.varRegLogin.did = did; |
646 | mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ | 694 | mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ |
647 | 695 | ||
@@ -697,15 +745,16 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, | |||
697 | { | 745 | { |
698 | MAILBOX_t *mb; | 746 | MAILBOX_t *mb; |
699 | 747 | ||
700 | mb = &pmb->mb; | 748 | mb = &pmb->u.mb; |
701 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 749 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
702 | 750 | ||
703 | mb->un.varUnregLogin.rpi = (uint16_t) rpi; | 751 | mb->un.varUnregLogin.rpi = (uint16_t) rpi; |
704 | mb->un.varUnregLogin.rsvd1 = 0; | 752 | mb->un.varUnregLogin.rsvd1 = 0; |
705 | mb->un.varUnregLogin.vpi = vpi; | 753 | mb->un.varUnregLogin.vpi = vpi + phba->vpi_base; |
706 | 754 | ||
707 | mb->mbxCommand = MBX_UNREG_LOGIN; | 755 | mb->mbxCommand = MBX_UNREG_LOGIN; |
708 | mb->mbxOwner = OWN_HOST; | 756 | mb->mbxOwner = OWN_HOST; |
757 | |||
709 | return; | 758 | return; |
710 | } | 759 | } |
711 | 760 | ||
@@ -725,15 +774,15 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, | |||
725 | * This routine prepares the mailbox command for registering a virtual N_Port. | 774 | * This routine prepares the mailbox command for registering a virtual N_Port. |
726 | **/ | 775 | **/ |
727 | void | 776 | void |
728 | lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid, | 777 | lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) |
729 | LPFC_MBOXQ_t *pmb) | ||
730 | { | 778 | { |
731 | MAILBOX_t *mb = &pmb->mb; | 779 | MAILBOX_t *mb = &pmb->u.mb; |
732 | 780 | ||
733 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 781 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
734 | 782 | ||
735 | mb->un.varRegVpi.vpi = vpi; | 783 | mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; |
736 | mb->un.varRegVpi.sid = sid; | 784 | mb->un.varRegVpi.sid = vport->fc_myDID; |
785 | mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; | ||
737 | 786 | ||
738 | mb->mbxCommand = MBX_REG_VPI; | 787 | mb->mbxCommand = MBX_REG_VPI; |
739 | mb->mbxOwner = OWN_HOST; | 788 | mb->mbxOwner = OWN_HOST; |
@@ -760,10 +809,10 @@ lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid, | |||
760 | void | 809 | void |
761 | lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb) | 810 | lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb) |
762 | { | 811 | { |
763 | MAILBOX_t *mb = &pmb->mb; | 812 | MAILBOX_t *mb = &pmb->u.mb; |
764 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 813 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
765 | 814 | ||
766 | mb->un.varUnregVpi.vpi = vpi; | 815 | mb->un.varUnregVpi.vpi = vpi + phba->vpi_base; |
767 | 816 | ||
768 | mb->mbxCommand = MBX_UNREG_VPI; | 817 | mb->mbxCommand = MBX_UNREG_VPI; |
769 | mb->mbxOwner = OWN_HOST; | 818 | mb->mbxOwner = OWN_HOST; |
@@ -852,7 +901,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) | |||
852 | void | 901 | void |
853 | lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | 902 | lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) |
854 | { | 903 | { |
855 | MAILBOX_t *mb = &pmb->mb; | 904 | MAILBOX_t *mb = &pmb->u.mb; |
856 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 905 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
857 | mb->un.varRdRev.cv = 1; | 906 | mb->un.varRdRev.cv = 1; |
858 | mb->un.varRdRev.v3req = 1; /* Request SLI3 info */ | 907 | mb->un.varRdRev.v3req = 1; /* Request SLI3 info */ |
@@ -945,7 +994,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, | |||
945 | uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb) | 994 | uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb) |
946 | { | 995 | { |
947 | int i; | 996 | int i; |
948 | MAILBOX_t *mb = &pmb->mb; | 997 | MAILBOX_t *mb = &pmb->u.mb; |
949 | struct config_hbq_var *hbqmb = &mb->un.varCfgHbq; | 998 | struct config_hbq_var *hbqmb = &mb->un.varCfgHbq; |
950 | 999 | ||
951 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); | 1000 | memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); |
@@ -1020,7 +1069,7 @@ void | |||
1020 | lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) | 1069 | lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) |
1021 | { | 1070 | { |
1022 | int i; | 1071 | int i; |
1023 | MAILBOX_t *mb = &pmb->mb; | 1072 | MAILBOX_t *mb = &pmb->u.mb; |
1024 | struct lpfc_sli *psli; | 1073 | struct lpfc_sli *psli; |
1025 | struct lpfc_sli_ring *pring; | 1074 | struct lpfc_sli_ring *pring; |
1026 | 1075 | ||
@@ -1075,7 +1124,7 @@ void | |||
1075 | lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | 1124 | lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
1076 | { | 1125 | { |
1077 | MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr; | 1126 | MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr; |
1078 | MAILBOX_t *mb = &pmb->mb; | 1127 | MAILBOX_t *mb = &pmb->u.mb; |
1079 | dma_addr_t pdma_addr; | 1128 | dma_addr_t pdma_addr; |
1080 | uint32_t bar_low, bar_high; | 1129 | uint32_t bar_low, bar_high; |
1081 | size_t offset; | 1130 | size_t offset; |
@@ -1099,21 +1148,22 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1099 | 1148 | ||
1100 | /* If HBA supports SLI=3 ask for it */ | 1149 | /* If HBA supports SLI=3 ask for it */ |
1101 | 1150 | ||
1102 | if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { | 1151 | if (phba->sli_rev == LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) { |
1103 | if (phba->cfg_enable_bg) | 1152 | if (phba->cfg_enable_bg) |
1104 | mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */ | 1153 | mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */ |
1154 | mb->un.varCfgPort.cdss = 1; /* Configure Security */ | ||
1105 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ | 1155 | mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ |
1106 | mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */ | 1156 | mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */ |
1107 | mb->un.varCfgPort.cinb = 1; /* Interrupt Notification Block */ | 1157 | mb->un.varCfgPort.cinb = 1; /* Interrupt Notification Block */ |
1108 | mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); | 1158 | mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); |
1109 | if (phba->max_vpi && phba->cfg_enable_npiv && | 1159 | if (phba->max_vpi && phba->cfg_enable_npiv && |
1110 | phba->vpd.sli3Feat.cmv) { | 1160 | phba->vpd.sli3Feat.cmv) { |
1111 | mb->un.varCfgPort.max_vpi = phba->max_vpi; | 1161 | mb->un.varCfgPort.max_vpi = LPFC_MAX_VPI; |
1112 | mb->un.varCfgPort.cmv = 1; | 1162 | mb->un.varCfgPort.cmv = 1; |
1113 | } else | 1163 | } else |
1114 | mb->un.varCfgPort.max_vpi = phba->max_vpi = 0; | 1164 | mb->un.varCfgPort.max_vpi = phba->max_vpi = 0; |
1115 | } else | 1165 | } else |
1116 | phba->sli_rev = 2; | 1166 | phba->sli_rev = LPFC_SLI_REV2; |
1117 | mb->un.varCfgPort.sli_mode = phba->sli_rev; | 1167 | mb->un.varCfgPort.sli_mode = phba->sli_rev; |
1118 | 1168 | ||
1119 | /* Now setup pcb */ | 1169 | /* Now setup pcb */ |
@@ -1245,7 +1295,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1245 | void | 1295 | void |
1246 | lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | 1296 | lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) |
1247 | { | 1297 | { |
1248 | MAILBOX_t *mb = &pmb->mb; | 1298 | MAILBOX_t *mb = &pmb->u.mb; |
1249 | 1299 | ||
1250 | memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); | 1300 | memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); |
1251 | mb->mbxCommand = MBX_KILL_BOARD; | 1301 | mb->mbxCommand = MBX_KILL_BOARD; |
@@ -1305,29 +1355,98 @@ lpfc_mbox_get(struct lpfc_hba * phba) | |||
1305 | } | 1355 | } |
1306 | 1356 | ||
1307 | /** | 1357 | /** |
1358 | * __lpfc_mbox_cmpl_put - Put mailbox cmd into mailbox cmd complete list | ||
1359 | * @phba: pointer to lpfc hba data structure. | ||
1360 | * @mbq: pointer to the driver internal queue element for mailbox command. | ||
1361 | * | ||
1362 | * This routine put the completed mailbox command into the mailbox command | ||
1363 | * complete list. This is the unlocked version of the routine. The mailbox | ||
1364 | * complete list is used by the driver worker thread to process mailbox | ||
1365 | * complete callback functions outside the driver interrupt handler. | ||
1366 | **/ | ||
1367 | void | ||
1368 | __lpfc_mbox_cmpl_put(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbq) | ||
1369 | { | ||
1370 | list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl); | ||
1371 | } | ||
1372 | |||
1373 | /** | ||
1308 | * lpfc_mbox_cmpl_put - Put mailbox command into mailbox command complete list | 1374 | * lpfc_mbox_cmpl_put - Put mailbox command into mailbox command complete list |
1309 | * @phba: pointer to lpfc hba data structure. | 1375 | * @phba: pointer to lpfc hba data structure. |
1310 | * @mbq: pointer to the driver internal queue element for mailbox command. | 1376 | * @mbq: pointer to the driver internal queue element for mailbox command. |
1311 | * | 1377 | * |
1312 | * This routine put the completed mailbox command into the mailbox command | 1378 | * This routine put the completed mailbox command into the mailbox command |
1313 | * complete list. This routine is called from driver interrupt handler | 1379 | * complete list. This is the locked version of the routine. The mailbox |
1314 | * context.The mailbox complete list is used by the driver worker thread | 1380 | * complete list is used by the driver worker thread to process mailbox |
1315 | * to process mailbox complete callback functions outside the driver interrupt | 1381 | * complete callback functions outside the driver interrupt handler. |
1316 | * handler. | ||
1317 | **/ | 1382 | **/ |
1318 | void | 1383 | void |
1319 | lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) | 1384 | lpfc_mbox_cmpl_put(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbq) |
1320 | { | 1385 | { |
1321 | unsigned long iflag; | 1386 | unsigned long iflag; |
1322 | 1387 | ||
1323 | /* This function expects to be called from interrupt context */ | 1388 | /* This function expects to be called from interrupt context */ |
1324 | spin_lock_irqsave(&phba->hbalock, iflag); | 1389 | spin_lock_irqsave(&phba->hbalock, iflag); |
1325 | list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl); | 1390 | __lpfc_mbox_cmpl_put(phba, mbq); |
1326 | spin_unlock_irqrestore(&phba->hbalock, iflag); | 1391 | spin_unlock_irqrestore(&phba->hbalock, iflag); |
1327 | return; | 1392 | return; |
1328 | } | 1393 | } |
1329 | 1394 | ||
1330 | /** | 1395 | /** |
1396 | * lpfc_mbox_cmd_check - Check the validality of a mailbox command | ||
1397 | * @phba: pointer to lpfc hba data structure. | ||
1398 | * @mboxq: pointer to the driver internal queue element for mailbox command. | ||
1399 | * | ||
1400 | * This routine is to check whether a mailbox command is valid to be issued. | ||
1401 | * This check will be performed by both the mailbox issue API when a client | ||
1402 | * is to issue a mailbox command to the mailbox transport. | ||
1403 | * | ||
1404 | * Return 0 - pass the check, -ENODEV - fail the check | ||
1405 | **/ | ||
1406 | int | ||
1407 | lpfc_mbox_cmd_check(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | ||
1408 | { | ||
1409 | /* Mailbox command that have a completion handler must also have a | ||
1410 | * vport specified. | ||
1411 | */ | ||
1412 | if (mboxq->mbox_cmpl && mboxq->mbox_cmpl != lpfc_sli_def_mbox_cmpl && | ||
1413 | mboxq->mbox_cmpl != lpfc_sli_wake_mbox_wait) { | ||
1414 | if (!mboxq->vport) { | ||
1415 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT, | ||
1416 | "1814 Mbox x%x failed, no vport\n", | ||
1417 | mboxq->u.mb.mbxCommand); | ||
1418 | dump_stack(); | ||
1419 | return -ENODEV; | ||
1420 | } | ||
1421 | } | ||
1422 | return 0; | ||
1423 | } | ||
1424 | |||
1425 | /** | ||
1426 | * lpfc_mbox_dev_check - Check the device state for issuing a mailbox command | ||
1427 | * @phba: pointer to lpfc hba data structure. | ||
1428 | * | ||
1429 | * This routine is to check whether the HBA device is ready for posting a | ||
1430 | * mailbox command. It is used by the mailbox transport API at the time the | ||
1431 | * to post a mailbox command to the device. | ||
1432 | * | ||
1433 | * Return 0 - pass the check, -ENODEV - fail the check | ||
1434 | **/ | ||
1435 | int | ||
1436 | lpfc_mbox_dev_check(struct lpfc_hba *phba) | ||
1437 | { | ||
1438 | /* If the PCI channel is in offline state, do not issue mbox */ | ||
1439 | if (unlikely(pci_channel_offline(phba->pcidev))) | ||
1440 | return -ENODEV; | ||
1441 | |||
1442 | /* If the HBA is in error state, do not issue mbox */ | ||
1443 | if (phba->link_state == LPFC_HBA_ERROR) | ||
1444 | return -ENODEV; | ||
1445 | |||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1449 | /** | ||
1331 | * lpfc_mbox_tmo_val - Retrieve mailbox command timeout value | 1450 | * lpfc_mbox_tmo_val - Retrieve mailbox command timeout value |
1332 | * @phba: pointer to lpfc hba data structure. | 1451 | * @phba: pointer to lpfc hba data structure. |
1333 | * @cmd: mailbox command code. | 1452 | * @cmd: mailbox command code. |
@@ -1350,6 +1469,475 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) | |||
1350 | case MBX_WRITE_WWN: /* 0x98 */ | 1469 | case MBX_WRITE_WWN: /* 0x98 */ |
1351 | case MBX_LOAD_EXP_ROM: /* 0x9C */ | 1470 | case MBX_LOAD_EXP_ROM: /* 0x9C */ |
1352 | return LPFC_MBOX_TMO_FLASH_CMD; | 1471 | return LPFC_MBOX_TMO_FLASH_CMD; |
1472 | case MBX_SLI4_CONFIG: /* 0x9b */ | ||
1473 | return LPFC_MBOX_SLI4_CONFIG_TMO; | ||
1353 | } | 1474 | } |
1354 | return LPFC_MBOX_TMO; | 1475 | return LPFC_MBOX_TMO; |
1355 | } | 1476 | } |
1477 | |||
1478 | /** | ||
1479 | * lpfc_sli4_mbx_sge_set - Set a sge entry in non-embedded mailbox command | ||
1480 | * @mbox: pointer to lpfc mbox command. | ||
1481 | * @sgentry: sge entry index. | ||
1482 | * @phyaddr: physical address for the sge | ||
1483 | * @length: Length of the sge. | ||
1484 | * | ||
1485 | * This routine sets up an entry in the non-embedded mailbox command at the sge | ||
1486 | * index location. | ||
1487 | **/ | ||
1488 | void | ||
1489 | lpfc_sli4_mbx_sge_set(struct lpfcMboxq *mbox, uint32_t sgentry, | ||
1490 | dma_addr_t phyaddr, uint32_t length) | ||
1491 | { | ||
1492 | struct lpfc_mbx_nembed_cmd *nembed_sge; | ||
1493 | |||
1494 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) | ||
1495 | &mbox->u.mqe.un.nembed_cmd; | ||
1496 | nembed_sge->sge[sgentry].pa_lo = putPaddrLow(phyaddr); | ||
1497 | nembed_sge->sge[sgentry].pa_hi = putPaddrHigh(phyaddr); | ||
1498 | nembed_sge->sge[sgentry].length = length; | ||
1499 | } | ||
1500 | |||
1501 | /** | ||
1502 | * lpfc_sli4_mbx_sge_get - Get a sge entry from non-embedded mailbox command | ||
1503 | * @mbox: pointer to lpfc mbox command. | ||
1504 | * @sgentry: sge entry index. | ||
1505 | * | ||
1506 | * This routine gets an entry from the non-embedded mailbox command at the sge | ||
1507 | * index location. | ||
1508 | **/ | ||
1509 | void | ||
1510 | lpfc_sli4_mbx_sge_get(struct lpfcMboxq *mbox, uint32_t sgentry, | ||
1511 | struct lpfc_mbx_sge *sge) | ||
1512 | { | ||
1513 | struct lpfc_mbx_nembed_cmd *nembed_sge; | ||
1514 | |||
1515 | nembed_sge = (struct lpfc_mbx_nembed_cmd *) | ||
1516 | &mbox->u.mqe.un.nembed_cmd; | ||
1517 | sge->pa_lo = nembed_sge->sge[sgentry].pa_lo; | ||
1518 | sge->pa_hi = nembed_sge->sge[sgentry].pa_hi; | ||
1519 | sge->length = nembed_sge->sge[sgentry].length; | ||
1520 | } | ||
1521 | |||
1522 | /** | ||
1523 | * lpfc_sli4_mbox_cmd_free - Free a sli4 mailbox command | ||
1524 | * @phba: pointer to lpfc hba data structure. | ||
1525 | * @mbox: pointer to lpfc mbox command. | ||
1526 | * | ||
1527 | * This routine frees SLI4 specific mailbox command for sending IOCTL command. | ||
1528 | **/ | ||
1529 | void | ||
1530 | lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox) | ||
1531 | { | ||
1532 | struct lpfc_mbx_sli4_config *sli4_cfg; | ||
1533 | struct lpfc_mbx_sge sge; | ||
1534 | dma_addr_t phyaddr; | ||
1535 | uint32_t sgecount, sgentry; | ||
1536 | |||
1537 | sli4_cfg = &mbox->u.mqe.un.sli4_config; | ||
1538 | |||
1539 | /* For embedded mbox command, just free the mbox command */ | ||
1540 | if (bf_get(lpfc_mbox_hdr_emb, &sli4_cfg->header.cfg_mhdr)) { | ||
1541 | mempool_free(mbox, phba->mbox_mem_pool); | ||
1542 | return; | ||
1543 | } | ||
1544 | |||
1545 | /* For non-embedded mbox command, we need to free the pages first */ | ||
1546 | sgecount = bf_get(lpfc_mbox_hdr_sge_cnt, &sli4_cfg->header.cfg_mhdr); | ||
1547 | /* There is nothing we can do if there is no sge address array */ | ||
1548 | if (unlikely(!mbox->sge_array)) { | ||
1549 | mempool_free(mbox, phba->mbox_mem_pool); | ||
1550 | return; | ||
1551 | } | ||
1552 | /* Each non-embedded DMA memory was allocated in the length of a page */ | ||
1553 | for (sgentry = 0; sgentry < sgecount; sgentry++) { | ||
1554 | lpfc_sli4_mbx_sge_get(mbox, sgentry, &sge); | ||
1555 | phyaddr = getPaddr(sge.pa_hi, sge.pa_lo); | ||
1556 | dma_free_coherent(&phba->pcidev->dev, PAGE_SIZE, | ||
1557 | mbox->sge_array->addr[sgentry], phyaddr); | ||
1558 | } | ||
1559 | /* Free the sge address array memory */ | ||
1560 | kfree(mbox->sge_array); | ||
1561 | /* Finally, free the mailbox command itself */ | ||
1562 | mempool_free(mbox, phba->mbox_mem_pool); | ||
1563 | } | ||
1564 | |||
1565 | /** | ||
1566 | * lpfc_sli4_config - Initialize the SLI4 Config Mailbox command | ||
1567 | * @phba: pointer to lpfc hba data structure. | ||
1568 | * @mbox: pointer to lpfc mbox command. | ||
1569 | * @subsystem: The sli4 config sub mailbox subsystem. | ||
1570 | * @opcode: The sli4 config sub mailbox command opcode. | ||
1571 | * @length: Length of the sli4 config mailbox command. | ||
1572 | * | ||
1573 | * This routine sets up the header fields of SLI4 specific mailbox command | ||
1574 | * for sending IOCTL command. | ||
1575 | * | ||
1576 | * Return: the actual length of the mbox command allocated (mostly useful | ||
1577 | * for none embedded mailbox command). | ||
1578 | **/ | ||
1579 | int | ||
1580 | lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox, | ||
1581 | uint8_t subsystem, uint8_t opcode, uint32_t length, bool emb) | ||
1582 | { | ||
1583 | struct lpfc_mbx_sli4_config *sli4_config; | ||
1584 | union lpfc_sli4_cfg_shdr *cfg_shdr = NULL; | ||
1585 | uint32_t alloc_len; | ||
1586 | uint32_t resid_len; | ||
1587 | uint32_t pagen, pcount; | ||
1588 | void *viraddr; | ||
1589 | dma_addr_t phyaddr; | ||
1590 | |||
1591 | /* Set up SLI4 mailbox command header fields */ | ||
1592 | memset(mbox, 0, sizeof(*mbox)); | ||
1593 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_SLI4_CONFIG); | ||
1594 | |||
1595 | /* Set up SLI4 ioctl command header fields */ | ||
1596 | sli4_config = &mbox->u.mqe.un.sli4_config; | ||
1597 | |||
1598 | /* Setup for the embedded mbox command */ | ||
1599 | if (emb) { | ||
1600 | /* Set up main header fields */ | ||
1601 | bf_set(lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr, 1); | ||
1602 | sli4_config->header.cfg_mhdr.payload_length = | ||
1603 | LPFC_MBX_CMD_HDR_LENGTH + length; | ||
1604 | /* Set up sub-header fields following main header */ | ||
1605 | bf_set(lpfc_mbox_hdr_opcode, | ||
1606 | &sli4_config->header.cfg_shdr.request, opcode); | ||
1607 | bf_set(lpfc_mbox_hdr_subsystem, | ||
1608 | &sli4_config->header.cfg_shdr.request, subsystem); | ||
1609 | sli4_config->header.cfg_shdr.request.request_length = length; | ||
1610 | return length; | ||
1611 | } | ||
1612 | |||
1613 | /* Setup for the none-embedded mbox command */ | ||
1614 | pcount = (PAGE_ALIGN(length))/PAGE_SIZE; | ||
1615 | pcount = (pcount > LPFC_SLI4_MBX_SGE_MAX_PAGES) ? | ||
1616 | LPFC_SLI4_MBX_SGE_MAX_PAGES : pcount; | ||
1617 | /* Allocate record for keeping SGE virtual addresses */ | ||
1618 | mbox->sge_array = kmalloc(sizeof(struct lpfc_mbx_nembed_sge_virt), | ||
1619 | GFP_KERNEL); | ||
1620 | if (!mbox->sge_array) | ||
1621 | return 0; | ||
1622 | |||
1623 | for (pagen = 0, alloc_len = 0; pagen < pcount; pagen++) { | ||
1624 | /* The DMA memory is always allocated in the length of a | ||
1625 | * page even though the last SGE might not fill up to a | ||
1626 | * page, this is used as a priori size of PAGE_SIZE for | ||
1627 | * the later DMA memory free. | ||
1628 | */ | ||
1629 | viraddr = dma_alloc_coherent(&phba->pcidev->dev, PAGE_SIZE, | ||
1630 | &phyaddr, GFP_KERNEL); | ||
1631 | /* In case of malloc fails, proceed with whatever we have */ | ||
1632 | if (!viraddr) | ||
1633 | break; | ||
1634 | mbox->sge_array->addr[pagen] = viraddr; | ||
1635 | /* Keep the first page for later sub-header construction */ | ||
1636 | if (pagen == 0) | ||
1637 | cfg_shdr = (union lpfc_sli4_cfg_shdr *)viraddr; | ||
1638 | resid_len = length - alloc_len; | ||
1639 | if (resid_len > PAGE_SIZE) { | ||
1640 | lpfc_sli4_mbx_sge_set(mbox, pagen, phyaddr, | ||
1641 | PAGE_SIZE); | ||
1642 | alloc_len += PAGE_SIZE; | ||
1643 | } else { | ||
1644 | lpfc_sli4_mbx_sge_set(mbox, pagen, phyaddr, | ||
1645 | resid_len); | ||
1646 | alloc_len = length; | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | /* Set up main header fields in mailbox command */ | ||
1651 | sli4_config->header.cfg_mhdr.payload_length = alloc_len; | ||
1652 | bf_set(lpfc_mbox_hdr_sge_cnt, &sli4_config->header.cfg_mhdr, pagen); | ||
1653 | |||
1654 | /* Set up sub-header fields into the first page */ | ||
1655 | if (pagen > 0) { | ||
1656 | bf_set(lpfc_mbox_hdr_opcode, &cfg_shdr->request, opcode); | ||
1657 | bf_set(lpfc_mbox_hdr_subsystem, &cfg_shdr->request, subsystem); | ||
1658 | cfg_shdr->request.request_length = | ||
1659 | alloc_len - sizeof(union lpfc_sli4_cfg_shdr); | ||
1660 | } | ||
1661 | /* The sub-header is in DMA memory, which needs endian converstion */ | ||
1662 | lpfc_sli_pcimem_bcopy(cfg_shdr, cfg_shdr, | ||
1663 | sizeof(union lpfc_sli4_cfg_shdr)); | ||
1664 | |||
1665 | return alloc_len; | ||
1666 | } | ||
1667 | |||
1668 | /** | ||
1669 | * lpfc_sli4_mbox_opcode_get - Get the opcode from a sli4 mailbox command | ||
1670 | * @phba: pointer to lpfc hba data structure. | ||
1671 | * @mbox: pointer to lpfc mbox command. | ||
1672 | * | ||
1673 | * This routine gets the opcode from a SLI4 specific mailbox command for | ||
1674 | * sending IOCTL command. If the mailbox command is not MBX_SLI4_CONFIG | ||
1675 | * (0x9B) or if the IOCTL sub-header is not present, opcode 0x0 shall be | ||
1676 | * returned. | ||
1677 | **/ | ||
1678 | uint8_t | ||
1679 | lpfc_sli4_mbox_opcode_get(struct lpfc_hba *phba, struct lpfcMboxq *mbox) | ||
1680 | { | ||
1681 | struct lpfc_mbx_sli4_config *sli4_cfg; | ||
1682 | union lpfc_sli4_cfg_shdr *cfg_shdr; | ||
1683 | |||
1684 | if (mbox->u.mb.mbxCommand != MBX_SLI4_CONFIG) | ||
1685 | return 0; | ||
1686 | sli4_cfg = &mbox->u.mqe.un.sli4_config; | ||
1687 | |||
1688 | /* For embedded mbox command, get opcode from embedded sub-header*/ | ||
1689 | if (bf_get(lpfc_mbox_hdr_emb, &sli4_cfg->header.cfg_mhdr)) { | ||
1690 | cfg_shdr = &mbox->u.mqe.un.sli4_config.header.cfg_shdr; | ||
1691 | return bf_get(lpfc_mbox_hdr_opcode, &cfg_shdr->request); | ||
1692 | } | ||
1693 | |||
1694 | /* For non-embedded mbox command, get opcode from first dma page */ | ||
1695 | if (unlikely(!mbox->sge_array)) | ||
1696 | return 0; | ||
1697 | cfg_shdr = (union lpfc_sli4_cfg_shdr *)mbox->sge_array->addr[0]; | ||
1698 | return bf_get(lpfc_mbox_hdr_opcode, &cfg_shdr->request); | ||
1699 | } | ||
1700 | |||
1701 | /** | ||
1702 | * lpfc_request_features: Configure SLI4 REQUEST_FEATURES mailbox | ||
1703 | * @mboxq: pointer to lpfc mbox command. | ||
1704 | * | ||
1705 | * This routine sets up the mailbox for an SLI4 REQUEST_FEATURES | ||
1706 | * mailbox command. | ||
1707 | **/ | ||
1708 | void | ||
1709 | lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq) | ||
1710 | { | ||
1711 | /* Set up SLI4 mailbox command header fields */ | ||
1712 | memset(mboxq, 0, sizeof(LPFC_MBOXQ_t)); | ||
1713 | bf_set(lpfc_mqe_command, &mboxq->u.mqe, MBX_SLI4_REQ_FTRS); | ||
1714 | |||
1715 | /* Set up host requested features. */ | ||
1716 | bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1); | ||
1717 | |||
1718 | /* Virtual fabrics and FIPs are not supported yet. */ | ||
1719 | bf_set(lpfc_mbx_rq_ftr_rq_ifip, &mboxq->u.mqe.un.req_ftrs, 0); | ||
1720 | |||
1721 | /* Enable DIF (block guard) only if configured to do so. */ | ||
1722 | if (phba->cfg_enable_bg) | ||
1723 | bf_set(lpfc_mbx_rq_ftr_rq_dif, &mboxq->u.mqe.un.req_ftrs, 1); | ||
1724 | |||
1725 | /* Enable NPIV only if configured to do so. */ | ||
1726 | if (phba->max_vpi && phba->cfg_enable_npiv) | ||
1727 | bf_set(lpfc_mbx_rq_ftr_rq_npiv, &mboxq->u.mqe.un.req_ftrs, 1); | ||
1728 | |||
1729 | return; | ||
1730 | } | ||
1731 | |||
1732 | /** | ||
1733 | * lpfc_init_vfi - Initialize the INIT_VFI mailbox command | ||
1734 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1735 | * @vport: Vport associated with the VF. | ||
1736 | * | ||
1737 | * This routine initializes @mbox to all zeros and then fills in the mailbox | ||
1738 | * fields from @vport. INIT_VFI configures virtual fabrics identified by VFI | ||
1739 | * in the context of an FCF. The driver issues this command to setup a VFI | ||
1740 | * before issuing a FLOGI to login to the VSAN. The driver should also issue a | ||
1741 | * REG_VFI after a successful VSAN login. | ||
1742 | **/ | ||
1743 | void | ||
1744 | lpfc_init_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport) | ||
1745 | { | ||
1746 | struct lpfc_mbx_init_vfi *init_vfi; | ||
1747 | |||
1748 | memset(mbox, 0, sizeof(*mbox)); | ||
1749 | init_vfi = &mbox->u.mqe.un.init_vfi; | ||
1750 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VFI); | ||
1751 | bf_set(lpfc_init_vfi_vr, init_vfi, 1); | ||
1752 | bf_set(lpfc_init_vfi_vt, init_vfi, 1); | ||
1753 | bf_set(lpfc_init_vfi_vfi, init_vfi, vport->vfi + vport->phba->vfi_base); | ||
1754 | bf_set(lpfc_init_vfi_fcfi, init_vfi, vport->phba->fcf.fcfi); | ||
1755 | } | ||
1756 | |||
1757 | /** | ||
1758 | * lpfc_reg_vfi - Initialize the REG_VFI mailbox command | ||
1759 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1760 | * @vport: vport associated with the VF. | ||
1761 | * @phys: BDE DMA bus address used to send the service parameters to the HBA. | ||
1762 | * | ||
1763 | * This routine initializes @mbox to all zeros and then fills in the mailbox | ||
1764 | * fields from @vport, and uses @buf as a DMAable buffer to send the vport's | ||
1765 | * fc service parameters to the HBA for this VFI. REG_VFI configures virtual | ||
1766 | * fabrics identified by VFI in the context of an FCF. | ||
1767 | **/ | ||
1768 | void | ||
1769 | lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) | ||
1770 | { | ||
1771 | struct lpfc_mbx_reg_vfi *reg_vfi; | ||
1772 | |||
1773 | memset(mbox, 0, sizeof(*mbox)); | ||
1774 | reg_vfi = &mbox->u.mqe.un.reg_vfi; | ||
1775 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_VFI); | ||
1776 | bf_set(lpfc_reg_vfi_vp, reg_vfi, 1); | ||
1777 | bf_set(lpfc_reg_vfi_vfi, reg_vfi, vport->vfi + vport->phba->vfi_base); | ||
1778 | bf_set(lpfc_reg_vfi_fcfi, reg_vfi, vport->phba->fcf.fcfi); | ||
1779 | bf_set(lpfc_reg_vfi_vpi, reg_vfi, vport->vpi + vport->phba->vpi_base); | ||
1780 | reg_vfi->bde.addrHigh = putPaddrHigh(phys); | ||
1781 | reg_vfi->bde.addrLow = putPaddrLow(phys); | ||
1782 | reg_vfi->bde.tus.f.bdeSize = sizeof(vport->fc_sparam); | ||
1783 | reg_vfi->bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; | ||
1784 | bf_set(lpfc_reg_vfi_nport_id, reg_vfi, vport->fc_myDID); | ||
1785 | } | ||
1786 | |||
1787 | /** | ||
1788 | * lpfc_init_vpi - Initialize the INIT_VPI mailbox command | ||
1789 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1790 | * @vpi: VPI to be initialized. | ||
1791 | * | ||
1792 | * The INIT_VPI mailbox command supports virtual N_Ports. The driver uses the | ||
1793 | * command to activate a virtual N_Port. The HBA assigns a MAC address to use | ||
1794 | * with the virtual N Port. The SLI Host issues this command before issuing a | ||
1795 | * FDISC to connect to the Fabric. The SLI Host should issue a REG_VPI after a | ||
1796 | * successful virtual NPort login. | ||
1797 | **/ | ||
1798 | void | ||
1799 | lpfc_init_vpi(struct lpfcMboxq *mbox, uint16_t vpi) | ||
1800 | { | ||
1801 | memset(mbox, 0, sizeof(*mbox)); | ||
1802 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI); | ||
1803 | bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi, vpi); | ||
1804 | } | ||
1805 | |||
1806 | /** | ||
1807 | * lpfc_unreg_vfi - Initialize the UNREG_VFI mailbox command | ||
1808 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1809 | * @vfi: VFI to be unregistered. | ||
1810 | * | ||
1811 | * The UNREG_VFI mailbox command causes the SLI Host to put a virtual fabric | ||
1812 | * (logical NPort) into the inactive state. The SLI Host must have logged out | ||
1813 | * and unregistered all remote N_Ports to abort any activity on the virtual | ||
1814 | * fabric. The SLI Port posts the mailbox response after marking the virtual | ||
1815 | * fabric inactive. | ||
1816 | **/ | ||
1817 | void | ||
1818 | lpfc_unreg_vfi(struct lpfcMboxq *mbox, uint16_t vfi) | ||
1819 | { | ||
1820 | memset(mbox, 0, sizeof(*mbox)); | ||
1821 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_VFI); | ||
1822 | bf_set(lpfc_unreg_vfi_vfi, &mbox->u.mqe.un.unreg_vfi, vfi); | ||
1823 | } | ||
1824 | |||
1825 | /** | ||
1826 | * lpfc_dump_fcoe_param - Dump config region 23 to get FCoe parameters. | ||
1827 | * @phba: pointer to the hba structure containing. | ||
1828 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1829 | * | ||
1830 | * This function create a SLI4 dump mailbox command to dump FCoE | ||
1831 | * parameters stored in region 23. | ||
1832 | **/ | ||
1833 | int | ||
1834 | lpfc_dump_fcoe_param(struct lpfc_hba *phba, | ||
1835 | struct lpfcMboxq *mbox) | ||
1836 | { | ||
1837 | struct lpfc_dmabuf *mp = NULL; | ||
1838 | MAILBOX_t *mb; | ||
1839 | |||
1840 | memset(mbox, 0, sizeof(*mbox)); | ||
1841 | mb = &mbox->u.mb; | ||
1842 | |||
1843 | mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); | ||
1844 | if (mp) | ||
1845 | mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); | ||
1846 | |||
1847 | if (!mp || !mp->virt) { | ||
1848 | kfree(mp); | ||
1849 | /* dump_fcoe_param failed to allocate memory */ | ||
1850 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, | ||
1851 | "2569 lpfc_dump_fcoe_param: memory" | ||
1852 | " allocation failed \n"); | ||
1853 | return 1; | ||
1854 | } | ||
1855 | |||
1856 | memset(mp->virt, 0, LPFC_BPL_SIZE); | ||
1857 | INIT_LIST_HEAD(&mp->list); | ||
1858 | |||
1859 | /* save address for completion */ | ||
1860 | mbox->context1 = (uint8_t *) mp; | ||
1861 | |||
1862 | mb->mbxCommand = MBX_DUMP_MEMORY; | ||
1863 | mb->un.varDmp.type = DMP_NV_PARAMS; | ||
1864 | mb->un.varDmp.region_id = DMP_REGION_FCOEPARAM; | ||
1865 | mb->un.varDmp.sli4_length = DMP_FCOEPARAM_RGN_SIZE; | ||
1866 | mb->un.varWords[3] = putPaddrLow(mp->phys); | ||
1867 | mb->un.varWords[4] = putPaddrHigh(mp->phys); | ||
1868 | return 0; | ||
1869 | } | ||
1870 | |||
1871 | /** | ||
1872 | * lpfc_reg_fcfi - Initialize the REG_FCFI mailbox command | ||
1873 | * @phba: pointer to the hba structure containing the FCF index and RQ ID. | ||
1874 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1875 | * | ||
1876 | * The REG_FCFI mailbox command supports Fibre Channel Forwarders (FCFs). The | ||
1877 | * SLI Host uses the command to activate an FCF after it has acquired FCF | ||
1878 | * information via a READ_FCF mailbox command. This mailbox command also is used | ||
1879 | * to indicate where received unsolicited frames from this FCF will be sent. By | ||
1880 | * default this routine will set up the FCF to forward all unsolicited frames | ||
1881 | * the the RQ ID passed in the @phba. This can be overridden by the caller for | ||
1882 | * more complicated setups. | ||
1883 | **/ | ||
1884 | void | ||
1885 | lpfc_reg_fcfi(struct lpfc_hba *phba, struct lpfcMboxq *mbox) | ||
1886 | { | ||
1887 | struct lpfc_mbx_reg_fcfi *reg_fcfi; | ||
1888 | |||
1889 | memset(mbox, 0, sizeof(*mbox)); | ||
1890 | reg_fcfi = &mbox->u.mqe.un.reg_fcfi; | ||
1891 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_REG_FCFI); | ||
1892 | bf_set(lpfc_reg_fcfi_rq_id0, reg_fcfi, phba->sli4_hba.hdr_rq->queue_id); | ||
1893 | bf_set(lpfc_reg_fcfi_rq_id1, reg_fcfi, REG_FCF_INVALID_QID); | ||
1894 | bf_set(lpfc_reg_fcfi_rq_id2, reg_fcfi, REG_FCF_INVALID_QID); | ||
1895 | bf_set(lpfc_reg_fcfi_rq_id3, reg_fcfi, REG_FCF_INVALID_QID); | ||
1896 | bf_set(lpfc_reg_fcfi_info_index, reg_fcfi, phba->fcf.fcf_indx); | ||
1897 | /* reg_fcf addr mode is bit wise inverted value of fcf addr_mode */ | ||
1898 | bf_set(lpfc_reg_fcfi_mam, reg_fcfi, | ||
1899 | (~phba->fcf.addr_mode) & 0x3); | ||
1900 | if (phba->fcf.fcf_flag & FCF_VALID_VLAN) { | ||
1901 | bf_set(lpfc_reg_fcfi_vv, reg_fcfi, 1); | ||
1902 | bf_set(lpfc_reg_fcfi_vlan_tag, reg_fcfi, phba->fcf.vlan_id); | ||
1903 | } | ||
1904 | } | ||
1905 | |||
1906 | /** | ||
1907 | * lpfc_unreg_fcfi - Initialize the UNREG_FCFI mailbox command | ||
1908 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1909 | * @fcfi: FCFI to be unregistered. | ||
1910 | * | ||
1911 | * The UNREG_FCFI mailbox command supports Fibre Channel Forwarders (FCFs). | ||
1912 | * The SLI Host uses the command to inactivate an FCFI. | ||
1913 | **/ | ||
1914 | void | ||
1915 | lpfc_unreg_fcfi(struct lpfcMboxq *mbox, uint16_t fcfi) | ||
1916 | { | ||
1917 | memset(mbox, 0, sizeof(*mbox)); | ||
1918 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_UNREG_FCFI); | ||
1919 | bf_set(lpfc_unreg_fcfi, &mbox->u.mqe.un.unreg_fcfi, fcfi); | ||
1920 | } | ||
1921 | |||
1922 | /** | ||
1923 | * lpfc_resume_rpi - Initialize the RESUME_RPI mailbox command | ||
1924 | * @mbox: pointer to lpfc mbox command to initialize. | ||
1925 | * @ndlp: The nodelist structure that describes the RPI to resume. | ||
1926 | * | ||
1927 | * The RESUME_RPI mailbox command is used to restart I/O to an RPI after a | ||
1928 | * link event. | ||
1929 | **/ | ||
1930 | void | ||
1931 | lpfc_resume_rpi(struct lpfcMboxq *mbox, struct lpfc_nodelist *ndlp) | ||
1932 | { | ||
1933 | struct lpfc_mbx_resume_rpi *resume_rpi; | ||
1934 | |||
1935 | memset(mbox, 0, sizeof(*mbox)); | ||
1936 | resume_rpi = &mbox->u.mqe.un.resume_rpi; | ||
1937 | bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_RESUME_RPI); | ||
1938 | bf_set(lpfc_resume_rpi_rpi, resume_rpi, ndlp->nlp_rpi); | ||
1939 | bf_set(lpfc_resume_rpi_vpi, resume_rpi, | ||
1940 | ndlp->vport->vpi + ndlp->vport->phba->vpi_base); | ||
1941 | bf_set(lpfc_resume_rpi_vfi, resume_rpi, | ||
1942 | ndlp->vport->vfi + ndlp->vport->phba->vfi_base); | ||
1943 | } | ||