Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
0004  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
0005  */
0006 
0007 #include "efclib.h"
0008 #include "../libefc_sli/sli4.h"
0009 #include "efc_cmds.h"
0010 #include "efc_sm.h"
0011 
0012 static void
0013 efc_nport_free_resources(struct efc_nport *nport, int evt, void *data)
0014 {
0015     struct efc *efc = nport->efc;
0016 
0017     /* Clear the nport attached flag */
0018     nport->attached = false;
0019 
0020     /* Free the service parameters buffer */
0021     if (nport->dma.virt) {
0022         dma_free_coherent(&efc->pci->dev, nport->dma.size,
0023                   nport->dma.virt, nport->dma.phys);
0024         memset(&nport->dma, 0, sizeof(struct efc_dma));
0025     }
0026 
0027     /* Free the SLI resources */
0028     sli_resource_free(efc->sli, SLI4_RSRC_VPI, nport->indicator);
0029 
0030     efc_nport_cb(efc, evt, nport);
0031 }
0032 
0033 static int
0034 efc_nport_get_mbox_status(struct efc_nport *nport, u8 *mqe, int status)
0035 {
0036     struct efc *efc = nport->efc;
0037     struct sli4_mbox_command_header *hdr =
0038             (struct sli4_mbox_command_header *)mqe;
0039 
0040     if (status || le16_to_cpu(hdr->status)) {
0041         efc_log_debug(efc, "bad status vpi=%#x st=%x hdr=%x\n",
0042                   nport->indicator, status, le16_to_cpu(hdr->status));
0043         return -EIO;
0044     }
0045 
0046     return 0;
0047 }
0048 
0049 static int
0050 efc_nport_free_unreg_vpi_cb(struct efc *efc, int status, u8 *mqe, void *arg)
0051 {
0052     struct efc_nport *nport = arg;
0053     int evt = EFC_EVT_NPORT_FREE_OK;
0054     int rc;
0055 
0056     rc = efc_nport_get_mbox_status(nport, mqe, status);
0057     if (rc)
0058         evt = EFC_EVT_NPORT_FREE_FAIL;
0059 
0060     efc_nport_free_resources(nport, evt, mqe);
0061     return rc;
0062 }
0063 
0064 static void
0065 efc_nport_free_unreg_vpi(struct efc_nport *nport)
0066 {
0067     struct efc *efc = nport->efc;
0068     int rc;
0069     u8 data[SLI4_BMBX_SIZE];
0070 
0071     rc = sli_cmd_unreg_vpi(efc->sli, data, nport->indicator,
0072                    SLI4_UNREG_TYPE_PORT);
0073     if (rc) {
0074         efc_log_err(efc, "UNREG_VPI format failure\n");
0075         efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_FAIL, data);
0076         return;
0077     }
0078 
0079     rc = efc->tt.issue_mbox_rqst(efc->base, data,
0080                      efc_nport_free_unreg_vpi_cb, nport);
0081     if (rc) {
0082         efc_log_err(efc, "UNREG_VPI command failure\n");
0083         efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_FAIL, data);
0084     }
0085 }
0086 
0087 static void
0088 efc_nport_send_evt(struct efc_nport *nport, int evt, void *data)
0089 {
0090     struct efc *efc = nport->efc;
0091 
0092     /* Now inform the registered callbacks */
0093     efc_nport_cb(efc, evt, nport);
0094 
0095     /* Set the nport attached flag */
0096     if (evt == EFC_EVT_NPORT_ATTACH_OK)
0097         nport->attached = true;
0098 
0099     /* If there is a pending free request, then handle it now */
0100     if (nport->free_req_pending)
0101         efc_nport_free_unreg_vpi(nport);
0102 }
0103 
0104 static int
0105 efc_nport_alloc_init_vpi_cb(struct efc *efc, int status, u8 *mqe, void *arg)
0106 {
0107     struct efc_nport *nport = arg;
0108 
0109     if (efc_nport_get_mbox_status(nport, mqe, status)) {
0110         efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, mqe);
0111         return -EIO;
0112     }
0113 
0114     efc_nport_send_evt(nport, EFC_EVT_NPORT_ALLOC_OK, mqe);
0115     return 0;
0116 }
0117 
0118 static void
0119 efc_nport_alloc_init_vpi(struct efc_nport *nport)
0120 {
0121     struct efc *efc = nport->efc;
0122     u8 data[SLI4_BMBX_SIZE];
0123     int rc;
0124 
0125     /* If there is a pending free request, then handle it now */
0126     if (nport->free_req_pending) {
0127         efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_OK, data);
0128         return;
0129     }
0130 
0131     rc = sli_cmd_init_vpi(efc->sli, data,
0132                   nport->indicator, nport->domain->indicator);
0133     if (rc) {
0134         efc_log_err(efc, "INIT_VPI format failure\n");
0135         efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
0136         return;
0137     }
0138 
0139     rc = efc->tt.issue_mbox_rqst(efc->base, data,
0140             efc_nport_alloc_init_vpi_cb, nport);
0141     if (rc) {
0142         efc_log_err(efc, "INIT_VPI command failure\n");
0143         efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
0144     }
0145 }
0146 
0147 static int
0148 efc_nport_alloc_read_sparm64_cb(struct efc *efc, int status, u8 *mqe, void *arg)
0149 {
0150     struct efc_nport *nport = arg;
0151     u8 *payload = NULL;
0152 
0153     if (efc_nport_get_mbox_status(nport, mqe, status)) {
0154         efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, mqe);
0155         return -EIO;
0156     }
0157 
0158     payload = nport->dma.virt;
0159 
0160     memcpy(&nport->sli_wwpn, payload + SLI4_READ_SPARM64_WWPN_OFFSET,
0161            sizeof(nport->sli_wwpn));
0162     memcpy(&nport->sli_wwnn, payload + SLI4_READ_SPARM64_WWNN_OFFSET,
0163            sizeof(nport->sli_wwnn));
0164 
0165     dma_free_coherent(&efc->pci->dev, nport->dma.size, nport->dma.virt,
0166               nport->dma.phys);
0167     memset(&nport->dma, 0, sizeof(struct efc_dma));
0168     efc_nport_alloc_init_vpi(nport);
0169     return 0;
0170 }
0171 
0172 static void
0173 efc_nport_alloc_read_sparm64(struct efc *efc, struct efc_nport *nport)
0174 {
0175     u8 data[SLI4_BMBX_SIZE];
0176     int rc;
0177 
0178     /* Allocate memory for the service parameters */
0179     nport->dma.size = EFC_SPARAM_DMA_SZ;
0180     nport->dma.virt = dma_alloc_coherent(&efc->pci->dev,
0181                          nport->dma.size, &nport->dma.phys,
0182                          GFP_KERNEL);
0183     if (!nport->dma.virt) {
0184         efc_log_err(efc, "Failed to allocate DMA memory\n");
0185         efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
0186         return;
0187     }
0188 
0189     rc = sli_cmd_read_sparm64(efc->sli, data,
0190                   &nport->dma, nport->indicator);
0191     if (rc) {
0192         efc_log_err(efc, "READ_SPARM64 format failure\n");
0193         efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
0194         return;
0195     }
0196 
0197     rc = efc->tt.issue_mbox_rqst(efc->base, data,
0198                      efc_nport_alloc_read_sparm64_cb, nport);
0199     if (rc) {
0200         efc_log_err(efc, "READ_SPARM64 command failure\n");
0201         efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
0202     }
0203 }
0204 
0205 int
0206 efc_cmd_nport_alloc(struct efc *efc, struct efc_nport *nport,
0207             struct efc_domain *domain, u8 *wwpn)
0208 {
0209     u32 index;
0210 
0211     nport->indicator = U32_MAX;
0212     nport->free_req_pending = false;
0213 
0214     if (wwpn)
0215         memcpy(&nport->sli_wwpn, wwpn, sizeof(nport->sli_wwpn));
0216 
0217     /*
0218      * allocate a VPI object for the port and stores it in the
0219      * indicator field of the port object.
0220      */
0221     if (sli_resource_alloc(efc->sli, SLI4_RSRC_VPI,
0222                    &nport->indicator, &index)) {
0223         efc_log_err(efc, "VPI allocation failure\n");
0224         return -EIO;
0225     }
0226 
0227     if (domain) {
0228         /*
0229          * If the WWPN is NULL, fetch the default
0230          * WWPN and WWNN before initializing the VPI
0231          */
0232         if (!wwpn)
0233             efc_nport_alloc_read_sparm64(efc, nport);
0234         else
0235             efc_nport_alloc_init_vpi(nport);
0236     } else if (!wwpn) {
0237         /* domain NULL and wwpn non-NULL */
0238         efc_log_err(efc, "need WWN for physical port\n");
0239         sli_resource_free(efc->sli, SLI4_RSRC_VPI, nport->indicator);
0240         return -EIO;
0241     }
0242 
0243     return 0;
0244 }
0245 
0246 static int
0247 efc_nport_attach_reg_vpi_cb(struct efc *efc, int status, u8 *mqe,
0248                 void *arg)
0249 {
0250     struct efc_nport *nport = arg;
0251 
0252     nport->attaching = false;
0253     if (efc_nport_get_mbox_status(nport, mqe, status)) {
0254         efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, mqe);
0255         return -EIO;
0256     }
0257 
0258     efc_nport_send_evt(nport, EFC_EVT_NPORT_ATTACH_OK, mqe);
0259     return 0;
0260 }
0261 
0262 int
0263 efc_cmd_nport_attach(struct efc *efc, struct efc_nport *nport, u32 fc_id)
0264 {
0265     u8 buf[SLI4_BMBX_SIZE];
0266     int rc = 0;
0267 
0268     if (!nport) {
0269         efc_log_err(efc, "bad param(s) nport=%p\n", nport);
0270         return -EIO;
0271     }
0272 
0273     nport->fc_id = fc_id;
0274 
0275     /* register previously-allocated VPI with the device */
0276     rc = sli_cmd_reg_vpi(efc->sli, buf, nport->fc_id,
0277                  nport->sli_wwpn, nport->indicator,
0278                 nport->domain->indicator, false);
0279     if (rc) {
0280         efc_log_err(efc, "REG_VPI format failure\n");
0281         efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf);
0282         return rc;
0283     }
0284 
0285     rc = efc->tt.issue_mbox_rqst(efc->base, buf,
0286                      efc_nport_attach_reg_vpi_cb, nport);
0287     if (rc) {
0288         efc_log_err(efc, "REG_VPI command failure\n");
0289         efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf);
0290     } else {
0291         nport->attaching = true;
0292     }
0293 
0294     return rc;
0295 }
0296 
0297 int
0298 efc_cmd_nport_free(struct efc *efc, struct efc_nport *nport)
0299 {
0300     if (!nport) {
0301         efc_log_err(efc, "bad parameter(s) nport=%p\n", nport);
0302         return -EIO;
0303     }
0304 
0305     /* Issue the UNREG_VPI command to free the assigned VPI context */
0306     if (nport->attached)
0307         efc_nport_free_unreg_vpi(nport);
0308     else if (nport->attaching)
0309         nport->free_req_pending = true;
0310     else
0311         efc_sm_post_event(&nport->sm, EFC_EVT_NPORT_FREE_OK, NULL);
0312 
0313     return 0;
0314 }
0315 
0316 static int
0317 efc_domain_get_mbox_status(struct efc_domain *domain, u8 *mqe, int status)
0318 {
0319     struct efc *efc = domain->efc;
0320     struct sli4_mbox_command_header *hdr =
0321             (struct sli4_mbox_command_header *)mqe;
0322 
0323     if (status || le16_to_cpu(hdr->status)) {
0324         efc_log_debug(efc, "bad status vfi=%#x st=%x hdr=%x\n",
0325                   domain->indicator, status,
0326                   le16_to_cpu(hdr->status));
0327         return -EIO;
0328     }
0329 
0330     return 0;
0331 }
0332 
0333 static void
0334 efc_domain_free_resources(struct efc_domain *domain, int evt, void *data)
0335 {
0336     struct efc *efc = domain->efc;
0337 
0338     /* Free the service parameters buffer */
0339     if (domain->dma.virt) {
0340         dma_free_coherent(&efc->pci->dev,
0341                   domain->dma.size, domain->dma.virt,
0342                   domain->dma.phys);
0343         memset(&domain->dma, 0, sizeof(struct efc_dma));
0344     }
0345 
0346     /* Free the SLI resources */
0347     sli_resource_free(efc->sli, SLI4_RSRC_VFI, domain->indicator);
0348 
0349     efc_domain_cb(efc, evt, domain);
0350 }
0351 
0352 static void
0353 efc_domain_send_nport_evt(struct efc_domain *domain,
0354               int port_evt, int domain_evt, void *data)
0355 {
0356     struct efc *efc = domain->efc;
0357 
0358     /* Send alloc/attach ok to the physical nport */
0359     efc_nport_send_evt(domain->nport, port_evt, NULL);
0360 
0361     /* Now inform the registered callbacks */
0362     efc_domain_cb(efc, domain_evt, domain);
0363 }
0364 
0365 static int
0366 efc_domain_alloc_read_sparm64_cb(struct efc *efc, int status, u8 *mqe,
0367                  void *arg)
0368 {
0369     struct efc_domain *domain = arg;
0370 
0371     if (efc_domain_get_mbox_status(domain, mqe, status)) {
0372         efc_domain_free_resources(domain,
0373                       EFC_HW_DOMAIN_ALLOC_FAIL, mqe);
0374         return -EIO;
0375     }
0376 
0377     efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ALLOC_OK,
0378                   EFC_HW_DOMAIN_ALLOC_OK, mqe);
0379     return 0;
0380 }
0381 
0382 static void
0383 efc_domain_alloc_read_sparm64(struct efc_domain *domain)
0384 {
0385     struct efc *efc = domain->efc;
0386     u8 data[SLI4_BMBX_SIZE];
0387     int rc;
0388 
0389     rc = sli_cmd_read_sparm64(efc->sli, data, &domain->dma, 0);
0390     if (rc) {
0391         efc_log_err(efc, "READ_SPARM64 format failure\n");
0392         efc_domain_free_resources(domain,
0393                       EFC_HW_DOMAIN_ALLOC_FAIL, data);
0394         return;
0395     }
0396 
0397     rc = efc->tt.issue_mbox_rqst(efc->base, data,
0398                      efc_domain_alloc_read_sparm64_cb, domain);
0399     if (rc) {
0400         efc_log_err(efc, "READ_SPARM64 command failure\n");
0401         efc_domain_free_resources(domain,
0402                       EFC_HW_DOMAIN_ALLOC_FAIL, data);
0403     }
0404 }
0405 
0406 static int
0407 efc_domain_alloc_init_vfi_cb(struct efc *efc, int status, u8 *mqe,
0408                  void *arg)
0409 {
0410     struct efc_domain *domain = arg;
0411 
0412     if (efc_domain_get_mbox_status(domain, mqe, status)) {
0413         efc_domain_free_resources(domain,
0414                       EFC_HW_DOMAIN_ALLOC_FAIL, mqe);
0415         return -EIO;
0416     }
0417 
0418     efc_domain_alloc_read_sparm64(domain);
0419     return 0;
0420 }
0421 
0422 static void
0423 efc_domain_alloc_init_vfi(struct efc_domain *domain)
0424 {
0425     struct efc *efc = domain->efc;
0426     struct efc_nport *nport = domain->nport;
0427     u8 data[SLI4_BMBX_SIZE];
0428     int rc;
0429 
0430     /*
0431      * For FC, the HW alread registered an FCFI.
0432      * Copy FCF information into the domain and jump to INIT_VFI.
0433      */
0434     domain->fcf_indicator = efc->fcfi;
0435     rc = sli_cmd_init_vfi(efc->sli, data, domain->indicator,
0436                   domain->fcf_indicator, nport->indicator);
0437     if (rc) {
0438         efc_log_err(efc, "INIT_VFI format failure\n");
0439         efc_domain_free_resources(domain,
0440                       EFC_HW_DOMAIN_ALLOC_FAIL, data);
0441         return;
0442     }
0443 
0444     efc_log_err(efc, "%s issue mbox\n", __func__);
0445     rc = efc->tt.issue_mbox_rqst(efc->base, data,
0446                      efc_domain_alloc_init_vfi_cb, domain);
0447     if (rc) {
0448         efc_log_err(efc, "INIT_VFI command failure\n");
0449         efc_domain_free_resources(domain,
0450                       EFC_HW_DOMAIN_ALLOC_FAIL, data);
0451     }
0452 }
0453 
0454 int
0455 efc_cmd_domain_alloc(struct efc *efc, struct efc_domain *domain, u32 fcf)
0456 {
0457     u32 index;
0458 
0459     if (!domain || !domain->nport) {
0460         efc_log_err(efc, "bad parameter(s) domain=%p nport=%p\n",
0461                 domain, domain ? domain->nport : NULL);
0462         return -EIO;
0463     }
0464 
0465     /* allocate memory for the service parameters */
0466     domain->dma.size = EFC_SPARAM_DMA_SZ;
0467     domain->dma.virt = dma_alloc_coherent(&efc->pci->dev,
0468                           domain->dma.size,
0469                           &domain->dma.phys, GFP_KERNEL);
0470     if (!domain->dma.virt) {
0471         efc_log_err(efc, "Failed to allocate DMA memory\n");
0472         return -EIO;
0473     }
0474 
0475     domain->fcf = fcf;
0476     domain->fcf_indicator = U32_MAX;
0477     domain->indicator = U32_MAX;
0478 
0479     if (sli_resource_alloc(efc->sli, SLI4_RSRC_VFI, &domain->indicator,
0480                    &index)) {
0481         efc_log_err(efc, "VFI allocation failure\n");
0482 
0483         dma_free_coherent(&efc->pci->dev,
0484                   domain->dma.size, domain->dma.virt,
0485                   domain->dma.phys);
0486         memset(&domain->dma, 0, sizeof(struct efc_dma));
0487 
0488         return -EIO;
0489     }
0490 
0491     efc_domain_alloc_init_vfi(domain);
0492     return 0;
0493 }
0494 
0495 static int
0496 efc_domain_attach_reg_vfi_cb(struct efc *efc, int status, u8 *mqe,
0497                  void *arg)
0498 {
0499     struct efc_domain *domain = arg;
0500 
0501     if (efc_domain_get_mbox_status(domain, mqe, status)) {
0502         efc_domain_free_resources(domain,
0503                       EFC_HW_DOMAIN_ATTACH_FAIL, mqe);
0504         return -EIO;
0505     }
0506 
0507     efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ATTACH_OK,
0508                   EFC_HW_DOMAIN_ATTACH_OK, mqe);
0509     return 0;
0510 }
0511 
0512 int
0513 efc_cmd_domain_attach(struct efc *efc, struct efc_domain *domain, u32 fc_id)
0514 {
0515     u8 buf[SLI4_BMBX_SIZE];
0516     int rc = 0;
0517 
0518     if (!domain) {
0519         efc_log_err(efc, "bad param(s) domain=%p\n", domain);
0520         return -EIO;
0521     }
0522 
0523     domain->nport->fc_id = fc_id;
0524 
0525     rc = sli_cmd_reg_vfi(efc->sli, buf, SLI4_BMBX_SIZE, domain->indicator,
0526                  domain->fcf_indicator, domain->dma,
0527                  domain->nport->indicator, domain->nport->sli_wwpn,
0528                  domain->nport->fc_id);
0529     if (rc) {
0530         efc_log_err(efc, "REG_VFI format failure\n");
0531         goto cleanup;
0532     }
0533 
0534     rc = efc->tt.issue_mbox_rqst(efc->base, buf,
0535                      efc_domain_attach_reg_vfi_cb, domain);
0536     if (rc) {
0537         efc_log_err(efc, "REG_VFI command failure\n");
0538         goto cleanup;
0539     }
0540 
0541     return rc;
0542 
0543 cleanup:
0544     efc_domain_free_resources(domain, EFC_HW_DOMAIN_ATTACH_FAIL, buf);
0545 
0546     return rc;
0547 }
0548 
0549 static int
0550 efc_domain_free_unreg_vfi_cb(struct efc *efc, int status, u8 *mqe, void *arg)
0551 {
0552     struct efc_domain *domain = arg;
0553     int evt = EFC_HW_DOMAIN_FREE_OK;
0554     int rc;
0555 
0556     rc = efc_domain_get_mbox_status(domain, mqe, status);
0557     if (rc) {
0558         evt = EFC_HW_DOMAIN_FREE_FAIL;
0559         rc = -EIO;
0560     }
0561 
0562     efc_domain_free_resources(domain, evt, mqe);
0563     return rc;
0564 }
0565 
0566 static void
0567 efc_domain_free_unreg_vfi(struct efc_domain *domain)
0568 {
0569     struct efc *efc = domain->efc;
0570     int rc;
0571     u8 data[SLI4_BMBX_SIZE];
0572 
0573     rc = sli_cmd_unreg_vfi(efc->sli, data, domain->indicator,
0574                    SLI4_UNREG_TYPE_DOMAIN);
0575     if (rc) {
0576         efc_log_err(efc, "UNREG_VFI format failure\n");
0577         goto cleanup;
0578     }
0579 
0580     rc = efc->tt.issue_mbox_rqst(efc->base, data,
0581                      efc_domain_free_unreg_vfi_cb, domain);
0582     if (rc) {
0583         efc_log_err(efc, "UNREG_VFI command failure\n");
0584         goto cleanup;
0585     }
0586 
0587     return;
0588 
0589 cleanup:
0590     efc_domain_free_resources(domain, EFC_HW_DOMAIN_FREE_FAIL, data);
0591 }
0592 
0593 int
0594 efc_cmd_domain_free(struct efc *efc, struct efc_domain *domain)
0595 {
0596     if (!domain) {
0597         efc_log_err(efc, "bad parameter(s) domain=%p\n", domain);
0598         return -EIO;
0599     }
0600 
0601     efc_domain_free_unreg_vfi(domain);
0602     return 0;
0603 }
0604 
0605 int
0606 efc_cmd_node_alloc(struct efc *efc, struct efc_remote_node *rnode, u32 fc_addr,
0607            struct efc_nport *nport)
0608 {
0609     /* Check for invalid indicator */
0610     if (rnode->indicator != U32_MAX) {
0611         efc_log_err(efc,
0612                 "RPI allocation failure addr=%#x rpi=%#x\n",
0613                 fc_addr, rnode->indicator);
0614         return -EIO;
0615     }
0616 
0617     /* NULL SLI port indicates an unallocated remote node */
0618     rnode->nport = NULL;
0619 
0620     if (sli_resource_alloc(efc->sli, SLI4_RSRC_RPI,
0621                    &rnode->indicator, &rnode->index)) {
0622         efc_log_err(efc, "RPI allocation failure addr=%#x\n",
0623                 fc_addr);
0624         return -EIO;
0625     }
0626 
0627     rnode->fc_id = fc_addr;
0628     rnode->nport = nport;
0629 
0630     return 0;
0631 }
0632 
0633 static int
0634 efc_cmd_node_attach_cb(struct efc *efc, int status, u8 *mqe, void *arg)
0635 {
0636     struct efc_remote_node *rnode = arg;
0637     struct sli4_mbox_command_header *hdr =
0638                 (struct sli4_mbox_command_header *)mqe;
0639     int evt = 0;
0640 
0641     if (status || le16_to_cpu(hdr->status)) {
0642         efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status,
0643                   le16_to_cpu(hdr->status));
0644         rnode->attached = false;
0645         evt = EFC_EVT_NODE_ATTACH_FAIL;
0646     } else {
0647         rnode->attached = true;
0648         evt = EFC_EVT_NODE_ATTACH_OK;
0649     }
0650 
0651     efc_remote_node_cb(efc, evt, rnode);
0652 
0653     return 0;
0654 }
0655 
0656 int
0657 efc_cmd_node_attach(struct efc *efc, struct efc_remote_node *rnode,
0658             struct efc_dma *sparms)
0659 {
0660     int rc = -EIO;
0661     u8 buf[SLI4_BMBX_SIZE];
0662 
0663     if (!rnode || !sparms) {
0664         efc_log_err(efc, "bad parameter(s) rnode=%p sparms=%p\n",
0665                 rnode, sparms);
0666         return -EIO;
0667     }
0668 
0669     /*
0670      * If the attach count is non-zero, this RPI has already been reg'd.
0671      * Otherwise, register the RPI
0672      */
0673     if (rnode->index == U32_MAX) {
0674         efc_log_err(efc, "bad parameter rnode->index invalid\n");
0675         return -EIO;
0676     }
0677 
0678     /* Update a remote node object with the remote port's service params */
0679     if (!sli_cmd_reg_rpi(efc->sli, buf, rnode->indicator,
0680                  rnode->nport->indicator, rnode->fc_id, sparms, 0, 0))
0681         rc = efc->tt.issue_mbox_rqst(efc->base, buf,
0682                          efc_cmd_node_attach_cb, rnode);
0683 
0684     return rc;
0685 }
0686 
0687 int
0688 efc_node_free_resources(struct efc *efc, struct efc_remote_node *rnode)
0689 {
0690     int rc = 0;
0691 
0692     if (!rnode) {
0693         efc_log_err(efc, "bad parameter rnode=%p\n", rnode);
0694         return -EIO;
0695     }
0696 
0697     if (rnode->nport) {
0698         if (rnode->attached) {
0699             efc_log_err(efc, "rnode is still attached\n");
0700             return -EIO;
0701         }
0702         if (rnode->indicator != U32_MAX) {
0703             if (sli_resource_free(efc->sli, SLI4_RSRC_RPI,
0704                           rnode->indicator)) {
0705                 efc_log_err(efc,
0706                         "RPI free fail RPI %d addr=%#x\n",
0707                         rnode->indicator, rnode->fc_id);
0708                 rc = -EIO;
0709             } else {
0710                 rnode->indicator = U32_MAX;
0711                 rnode->index = U32_MAX;
0712             }
0713         }
0714     }
0715 
0716     return rc;
0717 }
0718 
0719 static int
0720 efc_cmd_node_free_cb(struct efc *efc, int status, u8 *mqe, void *arg)
0721 {
0722     struct efc_remote_node *rnode = arg;
0723     struct sli4_mbox_command_header *hdr =
0724                 (struct sli4_mbox_command_header *)mqe;
0725     int evt = EFC_EVT_NODE_FREE_FAIL;
0726     int rc = 0;
0727 
0728     if (status || le16_to_cpu(hdr->status)) {
0729         efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status,
0730                   le16_to_cpu(hdr->status));
0731 
0732         /*
0733          * In certain cases, a non-zero MQE status is OK (all must be
0734          * true):
0735          *   - node is attached
0736          *   - status is 0x1400
0737          */
0738         if (!rnode->attached ||
0739             (le16_to_cpu(hdr->status) != SLI4_MBX_STATUS_RPI_NOT_REG))
0740             rc = -EIO;
0741     }
0742 
0743     if (!rc) {
0744         rnode->attached = false;
0745         evt = EFC_EVT_NODE_FREE_OK;
0746     }
0747 
0748     efc_remote_node_cb(efc, evt, rnode);
0749 
0750     return rc;
0751 }
0752 
0753 int
0754 efc_cmd_node_detach(struct efc *efc, struct efc_remote_node *rnode)
0755 {
0756     u8 buf[SLI4_BMBX_SIZE];
0757     int rc = -EIO;
0758 
0759     if (!rnode) {
0760         efc_log_err(efc, "bad parameter rnode=%p\n", rnode);
0761         return -EIO;
0762     }
0763 
0764     if (rnode->nport) {
0765         if (!rnode->attached)
0766             return -EIO;
0767 
0768         rc = -EIO;
0769 
0770         if (!sli_cmd_unreg_rpi(efc->sli, buf, rnode->indicator,
0771                        SLI4_RSRC_RPI, U32_MAX))
0772             rc = efc->tt.issue_mbox_rqst(efc->base, buf,
0773                     efc_cmd_node_free_cb, rnode);
0774 
0775         if (rc != 0) {
0776             efc_log_err(efc, "UNREG_RPI failed\n");
0777             rc = -EIO;
0778         }
0779     }
0780 
0781     return rc;
0782 }