1291a2b48SSukumar Swaminathan /* 2291a2b48SSukumar Swaminathan * CDDL HEADER START 3291a2b48SSukumar Swaminathan * 4291a2b48SSukumar Swaminathan * The contents of this file are subject to the terms of the 5291a2b48SSukumar Swaminathan * Common Development and Distribution License (the "License"). 6291a2b48SSukumar Swaminathan * You may not use this file except in compliance with the License. 7291a2b48SSukumar Swaminathan * 8*8f23e9faSHans Rosenfeld * You can obtain a copy of the license at 9*8f23e9faSHans Rosenfeld * http://www.opensource.org/licenses/cddl1.txt. 10291a2b48SSukumar Swaminathan * See the License for the specific language governing permissions 11291a2b48SSukumar Swaminathan * and limitations under the License. 12291a2b48SSukumar Swaminathan * 13291a2b48SSukumar Swaminathan * When distributing Covered Code, include this CDDL HEADER in each 14291a2b48SSukumar Swaminathan * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15291a2b48SSukumar Swaminathan * If applicable, add the following below this CDDL HEADER, with the 16291a2b48SSukumar Swaminathan * fields enclosed by brackets "[]" replaced with your own identifying 17291a2b48SSukumar Swaminathan * information: Portions Copyright [yyyy] [name of copyright owner] 18291a2b48SSukumar Swaminathan * 19291a2b48SSukumar Swaminathan * CDDL HEADER END 20291a2b48SSukumar Swaminathan */ 21291a2b48SSukumar Swaminathan 22291a2b48SSukumar Swaminathan /* 23*8f23e9faSHans Rosenfeld * Copyright (c) 2004-2012 Emulex. All rights reserved. 2482527734SSukumar Swaminathan * Use is subject to license terms. 25291a2b48SSukumar Swaminathan */ 26291a2b48SSukumar Swaminathan 27291a2b48SSukumar Swaminathan #include <emlxs.h> 28291a2b48SSukumar Swaminathan 29291a2b48SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 3082527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI3_C); 31291a2b48SSukumar Swaminathan 3282527734SSukumar Swaminathan static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); 3382527734SSukumar Swaminathan static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba); 3482527734SSukumar Swaminathan static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, 35291a2b48SSukumar Swaminathan uint32_t ha_copy); 36291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 37291a2b48SSukumar Swaminathan static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); 38291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3982527734SSukumar Swaminathan 40291a2b48SSukumar Swaminathan static uint32_t emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); 41291a2b48SSukumar Swaminathan 4282527734SSukumar Swaminathan static uint32_t emlxs_disable_traffic_cop = 1; 43291a2b48SSukumar Swaminathan 4482527734SSukumar Swaminathan static int emlxs_sli3_map_hdw(emlxs_hba_t *hba); 45291a2b48SSukumar Swaminathan 4682527734SSukumar Swaminathan static void emlxs_sli3_unmap_hdw(emlxs_hba_t *hba); 47291a2b48SSukumar Swaminathan 4882527734SSukumar Swaminathan static int32_t emlxs_sli3_online(emlxs_hba_t *hba); 49291a2b48SSukumar Swaminathan 50*8f23e9faSHans Rosenfeld static void emlxs_sli3_offline(emlxs_hba_t *hba, 51*8f23e9faSHans Rosenfeld uint32_t reset_requested); 52291a2b48SSukumar Swaminathan 5382527734SSukumar Swaminathan static uint32_t emlxs_sli3_hba_reset(emlxs_hba_t *hba, 5482527734SSukumar Swaminathan uint32_t restart, uint32_t skip_post, 5582527734SSukumar Swaminathan uint32_t quiesce); 56291a2b48SSukumar Swaminathan 5782527734SSukumar Swaminathan static void emlxs_sli3_hba_kill(emlxs_hba_t *hba); 5882527734SSukumar Swaminathan static void emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba); 5982527734SSukumar Swaminathan static uint32_t emlxs_sli3_hba_init(emlxs_hba_t *hba); 60291a2b48SSukumar Swaminathan 6182527734SSukumar Swaminathan static uint32_t emlxs_sli2_bde_setup(emlxs_port_t *port, 6282527734SSukumar Swaminathan emlxs_buf_t *sbp); 6382527734SSukumar Swaminathan static uint32_t emlxs_sli3_bde_setup(emlxs_port_t *port, 6482527734SSukumar Swaminathan emlxs_buf_t *sbp); 6582527734SSukumar Swaminathan static uint32_t emlxs_sli2_fct_bde_setup(emlxs_port_t *port, 6682527734SSukumar Swaminathan emlxs_buf_t *sbp); 6782527734SSukumar Swaminathan static uint32_t emlxs_sli3_fct_bde_setup(emlxs_port_t *port, 6882527734SSukumar Swaminathan emlxs_buf_t *sbp); 69291a2b48SSukumar Swaminathan 70291a2b48SSukumar Swaminathan 7182527734SSukumar Swaminathan static void emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, 7282527734SSukumar Swaminathan CHANNEL *rp, IOCBQ *iocb_cmd); 73291a2b48SSukumar Swaminathan 74291a2b48SSukumar Swaminathan 7582527734SSukumar Swaminathan static uint32_t emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, 7682527734SSukumar Swaminathan MAILBOXQ *mbq, int32_t flg, 7782527734SSukumar Swaminathan uint32_t tmo); 78291a2b48SSukumar Swaminathan 79291a2b48SSukumar Swaminathan 8082527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 8182527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, 8282527734SSukumar Swaminathan emlxs_buf_t *cmd_sbp, int channel); 83291a2b48SSukumar Swaminathan 8482527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 85291a2b48SSukumar Swaminathan 8682527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, 8782527734SSukumar Swaminathan emlxs_buf_t *sbp, int ring); 88291a2b48SSukumar Swaminathan 8982527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, 9082527734SSukumar Swaminathan emlxs_buf_t *sbp); 91291a2b48SSukumar Swaminathan 9282527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_els_iocb(emlxs_port_t *port, 9382527734SSukumar Swaminathan emlxs_buf_t *sbp); 94291a2b48SSukumar Swaminathan 95291a2b48SSukumar Swaminathan 9682527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, 9782527734SSukumar Swaminathan emlxs_buf_t *sbp); 98291a2b48SSukumar Swaminathan 99291a2b48SSukumar Swaminathan 100*8f23e9faSHans Rosenfeld static void emlxs_sli3_poll_intr(emlxs_hba_t *hba); 101291a2b48SSukumar Swaminathan 10282527734SSukumar Swaminathan static int32_t emlxs_sli3_intx_intr(char *arg); 10382527734SSukumar Swaminathan #ifdef MSI_SUPPORT 10482527734SSukumar Swaminathan static uint32_t emlxs_sli3_msi_intr(char *arg1, char *arg2); 10582527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 106291a2b48SSukumar Swaminathan 10782527734SSukumar Swaminathan static void emlxs_sli3_enable_intr(emlxs_hba_t *hba); 10882527734SSukumar Swaminathan 10982527734SSukumar Swaminathan static void emlxs_sli3_disable_intr(emlxs_hba_t *hba, 11082527734SSukumar Swaminathan uint32_t att); 11182527734SSukumar Swaminathan 112a9800bebSGarrett D'Amore 11382527734SSukumar Swaminathan static void emlxs_handle_ff_error(emlxs_hba_t *hba); 11482527734SSukumar Swaminathan 11582527734SSukumar Swaminathan static uint32_t emlxs_handle_mb_event(emlxs_hba_t *hba); 11682527734SSukumar Swaminathan 11782527734SSukumar Swaminathan static void emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba); 11882527734SSukumar Swaminathan 11982527734SSukumar Swaminathan static uint32_t emlxs_mb_config_port(emlxs_hba_t *hba, 12082527734SSukumar Swaminathan MAILBOXQ *mbq, uint32_t sli_mode, 12182527734SSukumar Swaminathan uint32_t hbainit); 12282527734SSukumar Swaminathan static void emlxs_enable_latt(emlxs_hba_t *hba); 12382527734SSukumar Swaminathan 12482527734SSukumar Swaminathan static uint32_t emlxs_check_attention(emlxs_hba_t *hba); 12582527734SSukumar Swaminathan 12682527734SSukumar Swaminathan static uint32_t emlxs_get_attention(emlxs_hba_t *hba, 127a9800bebSGarrett D'Amore int32_t msgid); 12882527734SSukumar Swaminathan static void emlxs_proc_attention(emlxs_hba_t *hba, 12982527734SSukumar Swaminathan uint32_t ha_copy); 13082527734SSukumar Swaminathan /* static int emlxs_handle_rcv_seq(emlxs_hba_t *hba, */ 13182527734SSukumar Swaminathan /* CHANNEL *cp, IOCBQ *iocbq); */ 13282527734SSukumar Swaminathan /* static void emlxs_update_HBQ_index(emlxs_hba_t *hba, */ 13382527734SSukumar Swaminathan /* uint32_t hbq_id); */ 13482527734SSukumar Swaminathan /* static void emlxs_hbq_free_all(emlxs_hba_t *hba, */ 13582527734SSukumar Swaminathan /* uint32_t hbq_id); */ 13682527734SSukumar Swaminathan static uint32_t emlxs_hbq_setup(emlxs_hba_t *hba, 13782527734SSukumar Swaminathan uint32_t hbq_id); 138*8f23e9faSHans Rosenfeld static void emlxs_sli3_timer(emlxs_hba_t *hba); 139*8f23e9faSHans Rosenfeld 140*8f23e9faSHans Rosenfeld static void emlxs_sli3_poll_erratt(emlxs_hba_t *hba); 14182527734SSukumar Swaminathan 142*8f23e9faSHans Rosenfeld static uint32_t emlxs_sli3_reg_did(emlxs_port_t *port, 143*8f23e9faSHans Rosenfeld uint32_t did, SERV_PARM *param, 144*8f23e9faSHans Rosenfeld emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, 145*8f23e9faSHans Rosenfeld IOCBQ *iocbq); 146*8f23e9faSHans Rosenfeld 147*8f23e9faSHans Rosenfeld static uint32_t emlxs_sli3_unreg_node(emlxs_port_t *port, 148*8f23e9faSHans Rosenfeld NODELIST *node, emlxs_buf_t *sbp, 149*8f23e9faSHans Rosenfeld fc_unsol_buf_t *ubp, IOCBQ *iocbq); 15082527734SSukumar Swaminathan 15182527734SSukumar Swaminathan 15282527734SSukumar Swaminathan /* Define SLI3 API functions */ 15382527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli3_api = { 15482527734SSukumar Swaminathan emlxs_sli3_map_hdw, 15582527734SSukumar Swaminathan emlxs_sli3_unmap_hdw, 15682527734SSukumar Swaminathan emlxs_sli3_online, 15782527734SSukumar Swaminathan emlxs_sli3_offline, 15882527734SSukumar Swaminathan emlxs_sli3_hba_reset, 15982527734SSukumar Swaminathan emlxs_sli3_hba_kill, 16082527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd, 16182527734SSukumar Swaminathan emlxs_sli3_issue_mbox_cmd, 16282527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 16382527734SSukumar Swaminathan emlxs_sli3_prep_fct_iocb, 16482527734SSukumar Swaminathan #else 16582527734SSukumar Swaminathan NULL, 16682527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 16782527734SSukumar Swaminathan emlxs_sli3_prep_fcp_iocb, 16882527734SSukumar Swaminathan emlxs_sli3_prep_ip_iocb, 16982527734SSukumar Swaminathan emlxs_sli3_prep_els_iocb, 17082527734SSukumar Swaminathan emlxs_sli3_prep_ct_iocb, 17182527734SSukumar Swaminathan emlxs_sli3_poll_intr, 17282527734SSukumar Swaminathan emlxs_sli3_intx_intr, 17382527734SSukumar Swaminathan emlxs_sli3_msi_intr, 17482527734SSukumar Swaminathan emlxs_sli3_disable_intr, 17582527734SSukumar Swaminathan emlxs_sli3_timer, 176*8f23e9faSHans Rosenfeld emlxs_sli3_poll_erratt, 177*8f23e9faSHans Rosenfeld emlxs_sli3_reg_did, 178*8f23e9faSHans Rosenfeld emlxs_sli3_unreg_node 17982527734SSukumar Swaminathan }; 180291a2b48SSukumar Swaminathan 181291a2b48SSukumar Swaminathan 18282527734SSukumar Swaminathan /* 18382527734SSukumar Swaminathan * emlxs_sli3_online() 18482527734SSukumar Swaminathan * 18582527734SSukumar Swaminathan * This routine will start initialization of the SLI2/3 HBA. 18682527734SSukumar Swaminathan */ 18782527734SSukumar Swaminathan static int32_t 18882527734SSukumar Swaminathan emlxs_sli3_online(emlxs_hba_t *hba) 18982527734SSukumar Swaminathan { 19082527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 19182527734SSukumar Swaminathan emlxs_config_t *cfg; 19282527734SSukumar Swaminathan emlxs_vpd_t *vpd; 19382527734SSukumar Swaminathan MAILBOX *mb = NULL; 19482527734SSukumar Swaminathan MAILBOXQ *mbq = NULL; 19582527734SSukumar Swaminathan RING *rp; 19682527734SSukumar Swaminathan CHANNEL *cp; 19782527734SSukumar Swaminathan MATCHMAP *mp = NULL; 19882527734SSukumar Swaminathan MATCHMAP *mp1 = NULL; 19982527734SSukumar Swaminathan uint8_t *inptr; 20082527734SSukumar Swaminathan uint8_t *outptr; 20182527734SSukumar Swaminathan uint32_t status; 202a9800bebSGarrett D'Amore uint16_t i; 20382527734SSukumar Swaminathan uint32_t j; 20482527734SSukumar Swaminathan uint32_t read_rev_reset; 20582527734SSukumar Swaminathan uint32_t key = 0; 20682527734SSukumar Swaminathan uint32_t fw_check; 2076a573d82SSukumar Swaminathan uint32_t kern_update = 0; 20882527734SSukumar Swaminathan uint32_t rval = 0; 20982527734SSukumar Swaminathan uint32_t offset; 21082527734SSukumar Swaminathan uint8_t vpd_data[DMP_VPD_SIZE]; 21182527734SSukumar Swaminathan uint32_t MaxRbusSize; 21282527734SSukumar Swaminathan uint32_t MaxIbusSize; 21382527734SSukumar Swaminathan uint32_t sli_mode; 21482527734SSukumar Swaminathan uint32_t sli_mode_mask; 215291a2b48SSukumar Swaminathan 21682527734SSukumar Swaminathan cfg = &CFG; 21782527734SSukumar Swaminathan vpd = &VPD; 21882527734SSukumar Swaminathan MaxRbusSize = 0; 21982527734SSukumar Swaminathan MaxIbusSize = 0; 22082527734SSukumar Swaminathan read_rev_reset = 0; 22182527734SSukumar Swaminathan hba->chan_count = MAX_RINGS; 222291a2b48SSukumar Swaminathan 22382527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 22482527734SSukumar Swaminathan (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba)); 22582527734SSukumar Swaminathan } 226291a2b48SSukumar Swaminathan 227a9800bebSGarrett D'Amore /* Set the fw_check flag */ 228a9800bebSGarrett D'Amore fw_check = cfg[CFG_FW_CHECK].current; 2296a573d82SSukumar Swaminathan 230a9800bebSGarrett D'Amore if ((fw_check & 0x04) || 231a9800bebSGarrett D'Amore (hba->fw_flag & FW_UPDATE_KERNEL)) { 232a9800bebSGarrett D'Amore kern_update = 1; 233a9800bebSGarrett D'Amore } 2346a573d82SSukumar Swaminathan 2356a573d82SSukumar Swaminathan hba->mbox_queue_flag = 0; 2366a573d82SSukumar Swaminathan hba->sli.sli3.hc_copy = 0; 2376a573d82SSukumar Swaminathan hba->fc_edtov = FF_DEF_EDTOV; 2386a573d82SSukumar Swaminathan hba->fc_ratov = FF_DEF_RATOV; 2396a573d82SSukumar Swaminathan hba->fc_altov = FF_DEF_ALTOV; 2406a573d82SSukumar Swaminathan hba->fc_arbtov = FF_DEF_ARBTOV; 2416a573d82SSukumar Swaminathan 242a9800bebSGarrett D'Amore /* 243a9800bebSGarrett D'Amore * Get a buffer which will be used repeatedly for mailbox commands 244a9800bebSGarrett D'Amore */ 245a9800bebSGarrett D'Amore mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP); 2466a573d82SSukumar Swaminathan 247a9800bebSGarrett D'Amore mb = (MAILBOX *)mbq; 2486a573d82SSukumar Swaminathan 24982527734SSukumar Swaminathan /* Initialize sli mode based on configuration parameter */ 25082527734SSukumar Swaminathan switch (cfg[CFG_SLI_MODE].current) { 25182527734SSukumar Swaminathan case 2: /* SLI2 mode */ 25282527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 25382527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 25482527734SSukumar Swaminathan break; 255291a2b48SSukumar Swaminathan 25682527734SSukumar Swaminathan case 3: /* SLI3 mode */ 25782527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 25882527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 25982527734SSukumar Swaminathan break; 260291a2b48SSukumar Swaminathan 26182527734SSukumar Swaminathan case 0: /* Best available */ 26282527734SSukumar Swaminathan case 1: /* Best available */ 26382527734SSukumar Swaminathan default: 26482527734SSukumar Swaminathan if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) { 26582527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 26682527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 26782527734SSukumar Swaminathan } else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) { 26882527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 26982527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 270*8f23e9faSHans Rosenfeld } else { 271*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 272*8f23e9faSHans Rosenfeld "No SLI mode available."); 273*8f23e9faSHans Rosenfeld rval = EIO; 274*8f23e9faSHans Rosenfeld goto failed; 27582527734SSukumar Swaminathan } 276*8f23e9faSHans Rosenfeld break; 27782527734SSukumar Swaminathan } 27882527734SSukumar Swaminathan /* SBUS adapters only available in SLI2 */ 27982527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 28082527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 28182527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 282291a2b48SSukumar Swaminathan } 283291a2b48SSukumar Swaminathan 284*8f23e9faSHans Rosenfeld reset: 28582527734SSukumar Swaminathan /* Reset & Initialize the adapter */ 28682527734SSukumar Swaminathan if (emlxs_sli3_hba_init(hba)) { 28782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 28882527734SSukumar Swaminathan "Unable to init hba."); 289291a2b48SSukumar Swaminathan 29082527734SSukumar Swaminathan rval = EIO; 29182527734SSukumar Swaminathan goto failed; 29282527734SSukumar Swaminathan } 293291a2b48SSukumar Swaminathan 29482527734SSukumar Swaminathan #ifdef FMA_SUPPORT 29582527734SSukumar Swaminathan /* Access handle validation */ 29682527734SSukumar Swaminathan if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 29782527734SSukumar Swaminathan != DDI_FM_OK) || 29882527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 29982527734SSukumar Swaminathan != DDI_FM_OK) || 30082527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 30182527734SSukumar Swaminathan != DDI_FM_OK)) { 30282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 30382527734SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 30482527734SSukumar Swaminathan 30582527734SSukumar Swaminathan rval = EIO; 30682527734SSukumar Swaminathan goto failed; 307291a2b48SSukumar Swaminathan } 30882527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 309291a2b48SSukumar Swaminathan 310*8f23e9faSHans Rosenfeld /* Check for PEGASUS (This is a special case) */ 31182527734SSukumar Swaminathan /* We need to check for dual channel adapter */ 312*8f23e9faSHans Rosenfeld if (hba->model_info.device_id == PCI_DEVICE_ID_PEGASUS) { 31382527734SSukumar Swaminathan /* Try to determine if this is a DC adapter */ 31482527734SSukumar Swaminathan if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) { 31582527734SSukumar Swaminathan if (MaxRbusSize == REDUCED_SRAM_CFG) { 31682527734SSukumar Swaminathan /* LP9802DC */ 31782527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 31882527734SSukumar Swaminathan if (emlxs_pci_model[i].id == LP9802DC) { 31982527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 32082527734SSukumar Swaminathan &hba->model_info, 32182527734SSukumar Swaminathan sizeof (emlxs_model_t)); 32282527734SSukumar Swaminathan break; 32382527734SSukumar Swaminathan } 32482527734SSukumar Swaminathan } 32582527734SSukumar Swaminathan } else if (hba->model_info.id != LP9802) { 32682527734SSukumar Swaminathan /* LP9802 */ 32782527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 32882527734SSukumar Swaminathan if (emlxs_pci_model[i].id == LP9802) { 32982527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 33082527734SSukumar Swaminathan &hba->model_info, 33182527734SSukumar Swaminathan sizeof (emlxs_model_t)); 33282527734SSukumar Swaminathan break; 33382527734SSukumar Swaminathan } 33482527734SSukumar Swaminathan } 33582527734SSukumar Swaminathan } 33682527734SSukumar Swaminathan } 33782527734SSukumar Swaminathan } 338291a2b48SSukumar Swaminathan 339291a2b48SSukumar Swaminathan /* 34082527734SSukumar Swaminathan * Setup and issue mailbox READ REV command 341291a2b48SSukumar Swaminathan */ 34282527734SSukumar Swaminathan vpd->opFwRev = 0; 34382527734SSukumar Swaminathan vpd->postKernRev = 0; 34482527734SSukumar Swaminathan vpd->sli1FwRev = 0; 34582527734SSukumar Swaminathan vpd->sli2FwRev = 0; 34682527734SSukumar Swaminathan vpd->sli3FwRev = 0; 34782527734SSukumar Swaminathan vpd->sli4FwRev = 0; 34882527734SSukumar Swaminathan 34982527734SSukumar Swaminathan vpd->postKernName[0] = 0; 35082527734SSukumar Swaminathan vpd->opFwName[0] = 0; 35182527734SSukumar Swaminathan vpd->sli1FwName[0] = 0; 35282527734SSukumar Swaminathan vpd->sli2FwName[0] = 0; 35382527734SSukumar Swaminathan vpd->sli3FwName[0] = 0; 35482527734SSukumar Swaminathan vpd->sli4FwName[0] = 0; 35582527734SSukumar Swaminathan 35682527734SSukumar Swaminathan vpd->opFwLabel[0] = 0; 35782527734SSukumar Swaminathan vpd->sli1FwLabel[0] = 0; 35882527734SSukumar Swaminathan vpd->sli2FwLabel[0] = 0; 35982527734SSukumar Swaminathan vpd->sli3FwLabel[0] = 0; 36082527734SSukumar Swaminathan vpd->sli4FwLabel[0] = 0; 36182527734SSukumar Swaminathan 36282527734SSukumar Swaminathan /* Sanity check */ 36382527734SSukumar Swaminathan if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 36482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 36582527734SSukumar Swaminathan "Adapter / SLI mode mismatch mask:x%x", 36682527734SSukumar Swaminathan hba->model_info.sli_mask); 36782527734SSukumar Swaminathan 36882527734SSukumar Swaminathan rval = EIO; 36982527734SSukumar Swaminathan goto failed; 370291a2b48SSukumar Swaminathan } 371291a2b48SSukumar Swaminathan 37282527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_REV); 37382527734SSukumar Swaminathan emlxs_mb_read_rev(hba, mbq, 0); 37482527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 37582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 37682527734SSukumar Swaminathan "Unable to read rev. Mailbox cmd=%x status=%x", 37782527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 378291a2b48SSukumar Swaminathan 37982527734SSukumar Swaminathan rval = EIO; 38082527734SSukumar Swaminathan goto failed; 381291a2b48SSukumar Swaminathan } 382291a2b48SSukumar Swaminathan 38382527734SSukumar Swaminathan if (mb->un.varRdRev.rr == 0) { 38482527734SSukumar Swaminathan /* Old firmware */ 38582527734SSukumar Swaminathan if (read_rev_reset == 0) { 38682527734SSukumar Swaminathan read_rev_reset = 1; 387291a2b48SSukumar Swaminathan 38882527734SSukumar Swaminathan goto reset; 38982527734SSukumar Swaminathan } else { 39082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 39182527734SSukumar Swaminathan "Outdated firmware detected."); 39282527734SSukumar Swaminathan } 393291a2b48SSukumar Swaminathan 39482527734SSukumar Swaminathan vpd->rBit = 0; 39582527734SSukumar Swaminathan } else { 39682527734SSukumar Swaminathan if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) { 39782527734SSukumar Swaminathan if (read_rev_reset == 0) { 39882527734SSukumar Swaminathan read_rev_reset = 1; 399291a2b48SSukumar Swaminathan 40082527734SSukumar Swaminathan goto reset; 40182527734SSukumar Swaminathan } else { 40282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 40382527734SSukumar Swaminathan "Non-operational firmware detected. " 40482527734SSukumar Swaminathan "type=%x", 40582527734SSukumar Swaminathan mb->un.varRdRev.un.b.ProgType); 40682527734SSukumar Swaminathan } 40782527734SSukumar Swaminathan } 408291a2b48SSukumar Swaminathan 40982527734SSukumar Swaminathan vpd->rBit = 1; 41082527734SSukumar Swaminathan vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1; 41182527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel, 41282527734SSukumar Swaminathan 16); 41382527734SSukumar Swaminathan vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2; 41482527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel, 41582527734SSukumar Swaminathan 16); 416291a2b48SSukumar Swaminathan 41782527734SSukumar Swaminathan /* 41882527734SSukumar Swaminathan * Lets try to read the SLI3 version 41982527734SSukumar Swaminathan * Setup and issue mailbox READ REV(v3) command 42082527734SSukumar Swaminathan */ 42182527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_REV); 42282527734SSukumar Swaminathan 42382527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 42482527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 42582527734SSukumar Swaminathan 42682527734SSukumar Swaminathan emlxs_mb_read_rev(hba, mbq, 1); 42782527734SSukumar Swaminathan 42882527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 42982527734SSukumar Swaminathan MBX_SUCCESS) { 43082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 43182527734SSukumar Swaminathan "Unable to read rev (v3). Mailbox cmd=%x status=%x", 43282527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 43382527734SSukumar Swaminathan 43482527734SSukumar Swaminathan rval = EIO; 43582527734SSukumar Swaminathan goto failed; 43682527734SSukumar Swaminathan } 43782527734SSukumar Swaminathan 43882527734SSukumar Swaminathan if (mb->un.varRdRev.rf3) { 43982527734SSukumar Swaminathan /* 44082527734SSukumar Swaminathan * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1; 44182527734SSukumar Swaminathan * Not needed 44282527734SSukumar Swaminathan */ 44382527734SSukumar Swaminathan vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2; 44482527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName2, 44582527734SSukumar Swaminathan vpd->sli3FwLabel, 16); 44682527734SSukumar Swaminathan } 447291a2b48SSukumar Swaminathan } 448291a2b48SSukumar Swaminathan 44982527734SSukumar Swaminathan if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) { 45082527734SSukumar Swaminathan if (vpd->sli2FwRev) { 45182527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 45282527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 45382527734SSukumar Swaminathan } else { 45482527734SSukumar Swaminathan sli_mode = 0; 45582527734SSukumar Swaminathan sli_mode_mask = 0; 45682527734SSukumar Swaminathan } 457291a2b48SSukumar Swaminathan } 458291a2b48SSukumar Swaminathan 45982527734SSukumar Swaminathan else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) { 46082527734SSukumar Swaminathan if (vpd->sli3FwRev) { 46182527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 46282527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 463291a2b48SSukumar Swaminathan } else { 46482527734SSukumar Swaminathan sli_mode = 0; 46582527734SSukumar Swaminathan sli_mode_mask = 0; 466291a2b48SSukumar Swaminathan } 467291a2b48SSukumar Swaminathan } 468291a2b48SSukumar Swaminathan 46982527734SSukumar Swaminathan if (!(hba->model_info.sli_mask & sli_mode_mask)) { 47082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 47182527734SSukumar Swaminathan "Firmware not available. sli-mode=%d", 47282527734SSukumar Swaminathan cfg[CFG_SLI_MODE].current); 473291a2b48SSukumar Swaminathan 47482527734SSukumar Swaminathan rval = EIO; 47582527734SSukumar Swaminathan goto failed; 47682527734SSukumar Swaminathan } 477291a2b48SSukumar Swaminathan 47882527734SSukumar Swaminathan /* Save information as VPD data */ 47982527734SSukumar Swaminathan vpd->postKernRev = mb->un.varRdRev.postKernRev; 48082527734SSukumar Swaminathan vpd->opFwRev = mb->un.varRdRev.opFwRev; 48182527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16); 48282527734SSukumar Swaminathan vpd->biuRev = mb->un.varRdRev.biuRev; 48382527734SSukumar Swaminathan vpd->smRev = mb->un.varRdRev.smRev; 48482527734SSukumar Swaminathan vpd->smFwRev = mb->un.varRdRev.un.smFwRev; 48582527734SSukumar Swaminathan vpd->endecRev = mb->un.varRdRev.endecRev; 48682527734SSukumar Swaminathan vpd->fcphHigh = mb->un.varRdRev.fcphHigh; 48782527734SSukumar Swaminathan vpd->fcphLow = mb->un.varRdRev.fcphLow; 48882527734SSukumar Swaminathan vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh; 48982527734SSukumar Swaminathan vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow; 49082527734SSukumar Swaminathan 49182527734SSukumar Swaminathan /* Decode FW names */ 492*8f23e9faSHans Rosenfeld emlxs_decode_version(vpd->postKernRev, vpd->postKernName, 493*8f23e9faSHans Rosenfeld sizeof (vpd->postKernName)); 494*8f23e9faSHans Rosenfeld emlxs_decode_version(vpd->opFwRev, vpd->opFwName, 495*8f23e9faSHans Rosenfeld sizeof (vpd->opFwName)); 496*8f23e9faSHans Rosenfeld emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName, 497*8f23e9faSHans Rosenfeld sizeof (vpd->sli1FwName)); 498*8f23e9faSHans Rosenfeld emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName, 499*8f23e9faSHans Rosenfeld sizeof (vpd->sli2FwName)); 500*8f23e9faSHans Rosenfeld emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName, 501*8f23e9faSHans Rosenfeld sizeof (vpd->sli3FwName)); 502*8f23e9faSHans Rosenfeld emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName, 503*8f23e9faSHans Rosenfeld sizeof (vpd->sli4FwName)); 50482527734SSukumar Swaminathan 50582527734SSukumar Swaminathan /* Decode FW labels */ 506*8f23e9faSHans Rosenfeld emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel, 1, 507*8f23e9faSHans Rosenfeld sizeof (vpd->opFwLabel)); 508*8f23e9faSHans Rosenfeld emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel, 1, 509*8f23e9faSHans Rosenfeld sizeof (vpd->sli1FwLabel)); 510*8f23e9faSHans Rosenfeld emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel, 1, 511*8f23e9faSHans Rosenfeld sizeof (vpd->sli2FwLabel)); 512*8f23e9faSHans Rosenfeld emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel, 1, 513*8f23e9faSHans Rosenfeld sizeof (vpd->sli3FwLabel)); 514*8f23e9faSHans Rosenfeld emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel, 1, 515*8f23e9faSHans Rosenfeld sizeof (vpd->sli4FwLabel)); 51682527734SSukumar Swaminathan 51782527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 51882527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 51982527734SSukumar Swaminathan 52082527734SSukumar Swaminathan key = emlxs_get_key(hba, mbq); 52182527734SSukumar Swaminathan 52282527734SSukumar Swaminathan /* Get adapter VPD information */ 52382527734SSukumar Swaminathan offset = 0; 52482527734SSukumar Swaminathan bzero(vpd_data, sizeof (vpd_data)); 52582527734SSukumar Swaminathan vpd->port_index = (uint32_t)-1; 526291a2b48SSukumar Swaminathan 52782527734SSukumar Swaminathan while (offset < DMP_VPD_SIZE) { 52882527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 52982527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 530291a2b48SSukumar Swaminathan 53182527734SSukumar Swaminathan emlxs_mb_dump_vpd(hba, mbq, offset); 53282527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 53382527734SSukumar Swaminathan MBX_SUCCESS) { 53482527734SSukumar Swaminathan /* 53582527734SSukumar Swaminathan * Let it go through even if failed. 53682527734SSukumar Swaminathan * Not all adapter's have VPD info and thus will 53782527734SSukumar Swaminathan * fail here. This is not a problem 53882527734SSukumar Swaminathan */ 539291a2b48SSukumar Swaminathan 54082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 54182527734SSukumar Swaminathan "No VPD found. offset=%x status=%x", offset, 54282527734SSukumar Swaminathan mb->mbxStatus); 54382527734SSukumar Swaminathan break; 54482527734SSukumar Swaminathan } else { 54582527734SSukumar Swaminathan if (mb->un.varDmp.ra == 1) { 54682527734SSukumar Swaminathan uint32_t *lp1, *lp2; 54782527734SSukumar Swaminathan uint32_t bsize; 54882527734SSukumar Swaminathan uint32_t wsize; 549291a2b48SSukumar Swaminathan 55082527734SSukumar Swaminathan /* 55182527734SSukumar Swaminathan * mb->un.varDmp.word_cnt is actually byte 55282527734SSukumar Swaminathan * count for the dump reply 55382527734SSukumar Swaminathan */ 55482527734SSukumar Swaminathan bsize = mb->un.varDmp.word_cnt; 555291a2b48SSukumar Swaminathan 55682527734SSukumar Swaminathan /* Stop if no data was received */ 55782527734SSukumar Swaminathan if (bsize == 0) { 55882527734SSukumar Swaminathan break; 55982527734SSukumar Swaminathan } 560291a2b48SSukumar Swaminathan 56182527734SSukumar Swaminathan /* Check limit on byte size */ 56282527734SSukumar Swaminathan bsize = (bsize > 56382527734SSukumar Swaminathan (sizeof (vpd_data) - offset)) ? 56482527734SSukumar Swaminathan (sizeof (vpd_data) - offset) : bsize; 565291a2b48SSukumar Swaminathan 56682527734SSukumar Swaminathan /* 56782527734SSukumar Swaminathan * Convert size from bytes to words with 56882527734SSukumar Swaminathan * minimum of 1 word 56982527734SSukumar Swaminathan */ 57082527734SSukumar Swaminathan wsize = (bsize > 4) ? (bsize >> 2) : 1; 571291a2b48SSukumar Swaminathan 57282527734SSukumar Swaminathan /* 57382527734SSukumar Swaminathan * Transfer data into vpd_data buffer one 57482527734SSukumar Swaminathan * word at a time 57582527734SSukumar Swaminathan */ 57682527734SSukumar Swaminathan lp1 = (uint32_t *)&mb->un.varDmp.resp_offset; 57782527734SSukumar Swaminathan lp2 = (uint32_t *)&vpd_data[offset]; 578291a2b48SSukumar Swaminathan 57982527734SSukumar Swaminathan for (i = 0; i < wsize; i++) { 58082527734SSukumar Swaminathan status = *lp1++; 58182527734SSukumar Swaminathan *lp2++ = BE_SWAP32(status); 58282527734SSukumar Swaminathan } 583291a2b48SSukumar Swaminathan 58482527734SSukumar Swaminathan /* Increment total byte count saved */ 58582527734SSukumar Swaminathan offset += (wsize << 2); 586291a2b48SSukumar Swaminathan 58782527734SSukumar Swaminathan /* 58882527734SSukumar Swaminathan * Stop if less than a full transfer was 58982527734SSukumar Swaminathan * received 59082527734SSukumar Swaminathan */ 59182527734SSukumar Swaminathan if (wsize < DMP_VPD_DUMP_WCOUNT) { 59282527734SSukumar Swaminathan break; 59382527734SSukumar Swaminathan } 594291a2b48SSukumar Swaminathan 59582527734SSukumar Swaminathan } else { 59682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 59782527734SSukumar Swaminathan &emlxs_init_debug_msg, 59882527734SSukumar Swaminathan "No VPD acknowledgment. offset=%x", 59982527734SSukumar Swaminathan offset); 60082527734SSukumar Swaminathan break; 60182527734SSukumar Swaminathan } 60282527734SSukumar Swaminathan } 603291a2b48SSukumar Swaminathan 604291a2b48SSukumar Swaminathan } 605291a2b48SSukumar Swaminathan 60682527734SSukumar Swaminathan if (vpd_data[0]) { 60782527734SSukumar Swaminathan (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset); 608291a2b48SSukumar Swaminathan 60982527734SSukumar Swaminathan /* 61082527734SSukumar Swaminathan * If there is a VPD part number, and it does not 61182527734SSukumar Swaminathan * match the current default HBA model info, 61282527734SSukumar Swaminathan * replace the default data with an entry that 61382527734SSukumar Swaminathan * does match. 61482527734SSukumar Swaminathan * 61582527734SSukumar Swaminathan * After emlxs_parse_vpd model holds the VPD value 61682527734SSukumar Swaminathan * for V2 and part_num hold the value for PN. These 61782527734SSukumar Swaminathan * 2 values are NOT necessarily the same. 61882527734SSukumar Swaminathan */ 619291a2b48SSukumar Swaminathan 62082527734SSukumar Swaminathan rval = 0; 62182527734SSukumar Swaminathan if ((vpd->model[0] != 0) && 62282527734SSukumar Swaminathan (strcmp(&vpd->model[0], hba->model_info.model) != 0)) { 623291a2b48SSukumar Swaminathan 62482527734SSukumar Swaminathan /* First scan for a V2 match */ 625291a2b48SSukumar Swaminathan 62682527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 62782527734SSukumar Swaminathan if (strcmp(&vpd->model[0], 62882527734SSukumar Swaminathan emlxs_pci_model[i].model) == 0) { 62982527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 63082527734SSukumar Swaminathan &hba->model_info, 63182527734SSukumar Swaminathan sizeof (emlxs_model_t)); 63282527734SSukumar Swaminathan rval = 1; 63382527734SSukumar Swaminathan break; 63482527734SSukumar Swaminathan } 63582527734SSukumar Swaminathan } 63682527734SSukumar Swaminathan } 637291a2b48SSukumar Swaminathan 63882527734SSukumar Swaminathan if (!rval && (vpd->part_num[0] != 0) && 63982527734SSukumar Swaminathan (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) { 640291a2b48SSukumar Swaminathan 64182527734SSukumar Swaminathan /* Next scan for a PN match */ 642291a2b48SSukumar Swaminathan 64382527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 64482527734SSukumar Swaminathan if (strcmp(&vpd->part_num[0], 64582527734SSukumar Swaminathan emlxs_pci_model[i].model) == 0) { 64682527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 64782527734SSukumar Swaminathan &hba->model_info, 64882527734SSukumar Swaminathan sizeof (emlxs_model_t)); 64982527734SSukumar Swaminathan break; 65082527734SSukumar Swaminathan } 65182527734SSukumar Swaminathan } 65282527734SSukumar Swaminathan } 653291a2b48SSukumar Swaminathan 65482527734SSukumar Swaminathan /* 65582527734SSukumar Swaminathan * Now lets update hba->model_info with the real 65682527734SSukumar Swaminathan * VPD data, if any. 65782527734SSukumar Swaminathan */ 658291a2b48SSukumar Swaminathan 65982527734SSukumar Swaminathan /* 66082527734SSukumar Swaminathan * Replace the default model description with vpd data 66182527734SSukumar Swaminathan */ 66282527734SSukumar Swaminathan if (vpd->model_desc[0] != 0) { 663*8f23e9faSHans Rosenfeld (void) strncpy(hba->model_info.model_desc, 664*8f23e9faSHans Rosenfeld vpd->model_desc, 665*8f23e9faSHans Rosenfeld (sizeof (hba->model_info.model_desc)-1)); 666291a2b48SSukumar Swaminathan } 667291a2b48SSukumar Swaminathan 66882527734SSukumar Swaminathan /* Replace the default model with vpd data */ 66982527734SSukumar Swaminathan if (vpd->model[0] != 0) { 670*8f23e9faSHans Rosenfeld (void) strncpy(hba->model_info.model, vpd->model, 671*8f23e9faSHans Rosenfeld (sizeof (hba->model_info.model)-1)); 67282527734SSukumar Swaminathan } 67382527734SSukumar Swaminathan 67482527734SSukumar Swaminathan /* Replace the default program types with vpd data */ 67582527734SSukumar Swaminathan if (vpd->prog_types[0] != 0) { 67682527734SSukumar Swaminathan emlxs_parse_prog_types(hba, vpd->prog_types); 67782527734SSukumar Swaminathan } 678291a2b48SSukumar Swaminathan } 679291a2b48SSukumar Swaminathan 680291a2b48SSukumar Swaminathan /* 68182527734SSukumar Swaminathan * Since the adapter model may have changed with the vpd data 68282527734SSukumar Swaminathan * lets double check if adapter is not supported 683291a2b48SSukumar Swaminathan */ 68482527734SSukumar Swaminathan if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 68582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 68682527734SSukumar Swaminathan "Unsupported adapter found. " 68782527734SSukumar Swaminathan "Id:%d Device id:0x%x SSDID:0x%x Model:%s", 68882527734SSukumar Swaminathan hba->model_info.id, hba->model_info.device_id, 68982527734SSukumar Swaminathan hba->model_info.ssdid, hba->model_info.model); 69082527734SSukumar Swaminathan 69182527734SSukumar Swaminathan rval = EIO; 69282527734SSukumar Swaminathan goto failed; 69382527734SSukumar Swaminathan } 694291a2b48SSukumar Swaminathan 69582527734SSukumar Swaminathan /* Read the adapter's wakeup parms */ 69682527734SSukumar Swaminathan (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 69782527734SSukumar Swaminathan emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 698*8f23e9faSHans Rosenfeld vpd->boot_version, sizeof (vpd->boot_version)); 699291a2b48SSukumar Swaminathan 70082527734SSukumar Swaminathan /* Get fcode version property */ 70182527734SSukumar Swaminathan emlxs_get_fcode_version(hba); 702291a2b48SSukumar Swaminathan 70382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 70482527734SSukumar Swaminathan "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev, 70582527734SSukumar Swaminathan vpd->opFwRev, vpd->sli1FwRev); 706291a2b48SSukumar Swaminathan 70782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 70882527734SSukumar Swaminathan "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev, 70982527734SSukumar Swaminathan vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh); 710291a2b48SSukumar Swaminathan 71182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 71282527734SSukumar Swaminathan "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version); 713291a2b48SSukumar Swaminathan 71482527734SSukumar Swaminathan /* 71582527734SSukumar Swaminathan * If firmware checking is enabled and the adapter model indicates 71682527734SSukumar Swaminathan * a firmware image, then perform firmware version check 71782527734SSukumar Swaminathan */ 7186a573d82SSukumar Swaminathan hba->fw_flag = 0; 7196a573d82SSukumar Swaminathan hba->fw_timer = 0; 7206a573d82SSukumar Swaminathan 721*8f23e9faSHans Rosenfeld if (((fw_check & 0x1) && 722*8f23e9faSHans Rosenfeld (hba->model_info.flags & EMLXS_ORACLE_BRANDED) && 7236a573d82SSukumar Swaminathan hba->model_info.fwid) || ((fw_check & 0x2) && 72482527734SSukumar Swaminathan hba->model_info.fwid)) { 72582527734SSukumar Swaminathan emlxs_firmware_t *fw; 72682527734SSukumar Swaminathan 72782527734SSukumar Swaminathan /* Find firmware image indicated by adapter model */ 72882527734SSukumar Swaminathan fw = NULL; 72982527734SSukumar Swaminathan for (i = 0; i < emlxs_fw_count; i++) { 73082527734SSukumar Swaminathan if (emlxs_fw_table[i].id == hba->model_info.fwid) { 73182527734SSukumar Swaminathan fw = &emlxs_fw_table[i]; 73282527734SSukumar Swaminathan break; 73382527734SSukumar Swaminathan } 734291a2b48SSukumar Swaminathan } 735291a2b48SSukumar Swaminathan 736291a2b48SSukumar Swaminathan /* 73782527734SSukumar Swaminathan * If the image was found, then verify current firmware 73882527734SSukumar Swaminathan * versions of adapter 739291a2b48SSukumar Swaminathan */ 74082527734SSukumar Swaminathan if (fw) { 7416a573d82SSukumar Swaminathan if (!kern_update && 7426a573d82SSukumar Swaminathan ((fw->kern && (vpd->postKernRev != fw->kern)) || 7436a573d82SSukumar Swaminathan (fw->stub && (vpd->opFwRev != fw->stub)))) { 7446a573d82SSukumar Swaminathan 7456a573d82SSukumar Swaminathan hba->fw_flag |= FW_UPDATE_NEEDED; 7466a573d82SSukumar Swaminathan 7476a573d82SSukumar Swaminathan } else if ((fw->kern && (vpd->postKernRev != 7486a573d82SSukumar Swaminathan fw->kern)) || 74982527734SSukumar Swaminathan (fw->stub && (vpd->opFwRev != fw->stub)) || 75082527734SSukumar Swaminathan (fw->sli1 && (vpd->sli1FwRev != fw->sli1)) || 75182527734SSukumar Swaminathan (fw->sli2 && (vpd->sli2FwRev != fw->sli2)) || 75282527734SSukumar Swaminathan (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) || 75382527734SSukumar Swaminathan (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) { 75482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 75582527734SSukumar Swaminathan "Firmware update needed. " 75682527734SSukumar Swaminathan "Updating. id=%d fw=%d", 75782527734SSukumar Swaminathan hba->model_info.id, hba->model_info.fwid); 75882527734SSukumar Swaminathan 75982527734SSukumar Swaminathan #ifdef MODFW_SUPPORT 76082527734SSukumar Swaminathan /* 76182527734SSukumar Swaminathan * Load the firmware image now 76282527734SSukumar Swaminathan * If MODFW_SUPPORT is not defined, the 76382527734SSukumar Swaminathan * firmware image will already be defined 76482527734SSukumar Swaminathan * in the emlxs_fw_table 76582527734SSukumar Swaminathan */ 76682527734SSukumar Swaminathan emlxs_fw_load(hba, fw); 76782527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 768291a2b48SSukumar Swaminathan 76982527734SSukumar Swaminathan if (fw->image && fw->size) { 770*8f23e9faSHans Rosenfeld uint32_t rc; 771*8f23e9faSHans Rosenfeld 772*8f23e9faSHans Rosenfeld rc = emlxs_fw_download(hba, 773*8f23e9faSHans Rosenfeld (char *)fw->image, fw->size, 0); 774*8f23e9faSHans Rosenfeld if ((rc != FC_SUCCESS) && 775*8f23e9faSHans Rosenfeld (rc != EMLXS_REBOOT_REQUIRED)) { 77682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 77782527734SSukumar Swaminathan &emlxs_init_msg, 77882527734SSukumar Swaminathan "Firmware update failed."); 7796a573d82SSukumar Swaminathan hba->fw_flag |= 7806a573d82SSukumar Swaminathan FW_UPDATE_NEEDED; 78182527734SSukumar Swaminathan } 78282527734SSukumar Swaminathan #ifdef MODFW_SUPPORT 78382527734SSukumar Swaminathan /* 78482527734SSukumar Swaminathan * Unload the firmware image from 78582527734SSukumar Swaminathan * kernel memory 78682527734SSukumar Swaminathan */ 78782527734SSukumar Swaminathan emlxs_fw_unload(hba, fw); 78882527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 789291a2b48SSukumar Swaminathan 79082527734SSukumar Swaminathan fw_check = 0; 79182527734SSukumar Swaminathan 79282527734SSukumar Swaminathan goto reset; 79382527734SSukumar Swaminathan } 79482527734SSukumar Swaminathan 795*8f23e9faSHans Rosenfeld hba->fw_flag |= FW_UPDATE_NEEDED; 796*8f23e9faSHans Rosenfeld 79782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 79882527734SSukumar Swaminathan "Firmware image unavailable."); 79982527734SSukumar Swaminathan } else { 80082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 80182527734SSukumar Swaminathan "Firmware update not needed."); 80282527734SSukumar Swaminathan } 80382527734SSukumar Swaminathan } else { 80482527734SSukumar Swaminathan /* This should not happen */ 80582527734SSukumar Swaminathan 80682527734SSukumar Swaminathan /* 80782527734SSukumar Swaminathan * This means either the adapter database is not 80882527734SSukumar Swaminathan * correct or a firmware image is missing from the 80982527734SSukumar Swaminathan * compile 81082527734SSukumar Swaminathan */ 81182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 81282527734SSukumar Swaminathan "Firmware image unavailable. id=%d fw=%d", 81382527734SSukumar Swaminathan hba->model_info.id, hba->model_info.fwid); 814291a2b48SSukumar Swaminathan } 815291a2b48SSukumar Swaminathan } 816291a2b48SSukumar Swaminathan 81782527734SSukumar Swaminathan /* 81882527734SSukumar Swaminathan * Add our interrupt routine to kernel's interrupt chain & enable it 81982527734SSukumar Swaminathan * If MSI is enabled this will cause Solaris to program the MSI address 82082527734SSukumar Swaminathan * and data registers in PCI config space 82182527734SSukumar Swaminathan */ 82282527734SSukumar Swaminathan if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) { 82382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 82482527734SSukumar Swaminathan "Unable to add interrupt(s)."); 8254baa2c25SSukumar Swaminathan 82682527734SSukumar Swaminathan rval = EIO; 82782527734SSukumar Swaminathan goto failed; 82882527734SSukumar Swaminathan } 829291a2b48SSukumar Swaminathan 83082527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT); 831291a2b48SSukumar Swaminathan 83282527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 83382527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 834291a2b48SSukumar Swaminathan 83582527734SSukumar Swaminathan (void) emlxs_mb_config_port(hba, mbq, sli_mode, key); 83682527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 83782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 83882527734SSukumar Swaminathan "Unable to configure port. " 83982527734SSukumar Swaminathan "Mailbox cmd=%x status=%x slimode=%d key=%x", 84082527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus, sli_mode, key); 841291a2b48SSukumar Swaminathan 84282527734SSukumar Swaminathan for (sli_mode--; sli_mode > 0; sli_mode--) { 84382527734SSukumar Swaminathan /* Check if sli_mode is supported by this adapter */ 84482527734SSukumar Swaminathan if (hba->model_info.sli_mask & 84582527734SSukumar Swaminathan EMLXS_SLI_MASK(sli_mode)) { 84682527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI_MASK(sli_mode); 84782527734SSukumar Swaminathan break; 84882527734SSukumar Swaminathan } 84982527734SSukumar Swaminathan } 8504baa2c25SSukumar Swaminathan 85182527734SSukumar Swaminathan if (sli_mode) { 85282527734SSukumar Swaminathan fw_check = 0; 8534baa2c25SSukumar Swaminathan 85482527734SSukumar Swaminathan goto reset; 85582527734SSukumar Swaminathan } 856291a2b48SSukumar Swaminathan 85782527734SSukumar Swaminathan hba->flag &= ~FC_SLIM2_MODE; 85882527734SSukumar Swaminathan 85982527734SSukumar Swaminathan rval = EIO; 86082527734SSukumar Swaminathan goto failed; 861291a2b48SSukumar Swaminathan } 862291a2b48SSukumar Swaminathan 86382527734SSukumar Swaminathan /* Check if SLI3 mode was achieved */ 86482527734SSukumar Swaminathan if (mb->un.varCfgPort.rMA && 86582527734SSukumar Swaminathan (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) { 866291a2b48SSukumar Swaminathan 86782527734SSukumar Swaminathan if (mb->un.varCfgPort.vpi_max > 1) { 86882527734SSukumar Swaminathan hba->flag |= FC_NPIV_ENABLED; 869291a2b48SSukumar Swaminathan 87082527734SSukumar Swaminathan if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 87182527734SSukumar Swaminathan hba->vpi_max = 87282527734SSukumar Swaminathan min(mb->un.varCfgPort.vpi_max, 87382527734SSukumar Swaminathan MAX_VPORTS - 1); 87482527734SSukumar Swaminathan } else { 87582527734SSukumar Swaminathan hba->vpi_max = 87682527734SSukumar Swaminathan min(mb->un.varCfgPort.vpi_max, 87782527734SSukumar Swaminathan MAX_VPORTS_LIMITED - 1); 87882527734SSukumar Swaminathan } 87982527734SSukumar Swaminathan } 880291a2b48SSukumar Swaminathan 88182527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5) 88282527734SSukumar Swaminathan hba->fca_tran->fca_num_npivports = 88382527734SSukumar Swaminathan (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0; 88482527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */ 88582527734SSukumar Swaminathan 88682527734SSukumar Swaminathan if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) { 88782527734SSukumar Swaminathan hba->flag |= FC_HBQ_ENABLED; 888291a2b48SSukumar Swaminathan } 88982527734SSukumar Swaminathan 89082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 89182527734SSukumar Swaminathan "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max); 89282527734SSukumar Swaminathan } else { 89382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 89482527734SSukumar Swaminathan "SLI2 mode: flag=%x", hba->flag); 89582527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 89682527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 89782527734SSukumar Swaminathan hba->sli_mode = sli_mode; 898*8f23e9faSHans Rosenfeld #if (EMLXS_MODREV >= EMLXS_MODREV5) 899*8f23e9faSHans Rosenfeld hba->fca_tran->fca_num_npivports = 0; 900*8f23e9faSHans Rosenfeld #endif /* >= EMLXS_MODREV5 */ 901*8f23e9faSHans Rosenfeld 902291a2b48SSukumar Swaminathan } 903291a2b48SSukumar Swaminathan 90482527734SSukumar Swaminathan /* Get and save the current firmware version (based on sli_mode) */ 90582527734SSukumar Swaminathan emlxs_decode_firmware_rev(hba, vpd); 906291a2b48SSukumar Swaminathan 90782527734SSukumar Swaminathan emlxs_pcix_mxr_update(hba, 0); 908291a2b48SSukumar Swaminathan 90982527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 91082527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 911291a2b48SSukumar Swaminathan 91282527734SSukumar Swaminathan emlxs_mb_read_config(hba, mbq); 91382527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 91482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 91582527734SSukumar Swaminathan "Unable to read configuration. Mailbox cmd=%x status=%x", 91682527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 917291a2b48SSukumar Swaminathan 91882527734SSukumar Swaminathan rval = EIO; 91982527734SSukumar Swaminathan goto failed; 92082527734SSukumar Swaminathan } 921291a2b48SSukumar Swaminathan 92282527734SSukumar Swaminathan /* Save the link speed capabilities */ 923a9800bebSGarrett D'Amore vpd->link_speed = (uint16_t)mb->un.varRdConfig.lmt; 92482527734SSukumar Swaminathan emlxs_process_link_speed(hba); 925291a2b48SSukumar Swaminathan 92682527734SSukumar Swaminathan /* Set the max node count */ 92782527734SSukumar Swaminathan if (cfg[CFG_NUM_NODES].current > 0) { 92882527734SSukumar Swaminathan hba->max_nodes = 92982527734SSukumar Swaminathan min(cfg[CFG_NUM_NODES].current, 93082527734SSukumar Swaminathan mb->un.varRdConfig.max_rpi); 93182527734SSukumar Swaminathan } else { 93282527734SSukumar Swaminathan hba->max_nodes = mb->un.varRdConfig.max_rpi; 93382527734SSukumar Swaminathan } 934291a2b48SSukumar Swaminathan 93582527734SSukumar Swaminathan /* Set the io throttle */ 93682527734SSukumar Swaminathan hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE; 937*8f23e9faSHans Rosenfeld 938*8f23e9faSHans Rosenfeld /* Set max_iotag */ 939*8f23e9faSHans Rosenfeld if (cfg[CFG_NUM_IOTAGS].current) { 940*8f23e9faSHans Rosenfeld hba->max_iotag = (uint16_t)cfg[CFG_NUM_IOTAGS].current; 941*8f23e9faSHans Rosenfeld } else { 942*8f23e9faSHans Rosenfeld hba->max_iotag = mb->un.varRdConfig.max_xri; 943*8f23e9faSHans Rosenfeld } 944*8f23e9faSHans Rosenfeld 945*8f23e9faSHans Rosenfeld /* Set out-of-range iotag base */ 946*8f23e9faSHans Rosenfeld hba->fc_oor_iotag = hba->max_iotag; 947291a2b48SSukumar Swaminathan 94882527734SSukumar Swaminathan /* 94982527734SSukumar Swaminathan * Allocate some memory for buffers 95082527734SSukumar Swaminathan */ 95182527734SSukumar Swaminathan if (emlxs_mem_alloc_buffer(hba) == 0) { 95282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 95382527734SSukumar Swaminathan "Unable to allocate memory buffers."); 954291a2b48SSukumar Swaminathan 95582527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 95682527734SSukumar Swaminathan return (ENOMEM); 95782527734SSukumar Swaminathan } 958291a2b48SSukumar Swaminathan 95982527734SSukumar Swaminathan /* 96082527734SSukumar Swaminathan * Setup and issue mailbox RUN BIU DIAG command Setup test buffers 96182527734SSukumar Swaminathan */ 962*8f23e9faSHans Rosenfeld if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) || 963*8f23e9faSHans Rosenfeld ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0)) { 96482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 96582527734SSukumar Swaminathan "Unable to allocate diag buffers."); 96682527734SSukumar Swaminathan 96782527734SSukumar Swaminathan rval = ENOMEM; 96882527734SSukumar Swaminathan goto failed; 969291a2b48SSukumar Swaminathan } 970291a2b48SSukumar Swaminathan 97182527734SSukumar Swaminathan bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt, 97282527734SSukumar Swaminathan MEM_ELSBUF_SIZE); 97382527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE, 97482527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 975291a2b48SSukumar Swaminathan 97682527734SSukumar Swaminathan bzero(mp1->virt, MEM_ELSBUF_SIZE); 97782527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 97882527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 979291a2b48SSukumar Swaminathan 98082527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 98182527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 982291a2b48SSukumar Swaminathan 98382527734SSukumar Swaminathan (void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys); 98482527734SSukumar Swaminathan 98582527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 98682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 98782527734SSukumar Swaminathan "Unable to run BIU diag. Mailbox cmd=%x status=%x", 98882527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 98982527734SSukumar Swaminathan 99082527734SSukumar Swaminathan rval = EIO; 99182527734SSukumar Swaminathan goto failed; 992291a2b48SSukumar Swaminathan } 993291a2b48SSukumar Swaminathan 99482527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 99582527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 996291a2b48SSukumar Swaminathan 997b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 998b3660a96SSukumar Swaminathan if (mp->dma_handle) { 999b3660a96SSukumar Swaminathan if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) 1000b3660a96SSukumar Swaminathan != DDI_FM_OK) { 1001b3660a96SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1002b3660a96SSukumar Swaminathan &emlxs_invalid_dma_handle_msg, 1003*8f23e9faSHans Rosenfeld "sli3_online: hdl=%p", 1004b3660a96SSukumar Swaminathan mp->dma_handle); 1005b3660a96SSukumar Swaminathan rval = EIO; 1006b3660a96SSukumar Swaminathan goto failed; 1007b3660a96SSukumar Swaminathan } 1008b3660a96SSukumar Swaminathan } 1009b3660a96SSukumar Swaminathan 1010b3660a96SSukumar Swaminathan if (mp1->dma_handle) { 1011b3660a96SSukumar Swaminathan if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle) 1012b3660a96SSukumar Swaminathan != DDI_FM_OK) { 1013b3660a96SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1014b3660a96SSukumar Swaminathan &emlxs_invalid_dma_handle_msg, 1015*8f23e9faSHans Rosenfeld "sli3_online: hdl=%p", 1016b3660a96SSukumar Swaminathan mp1->dma_handle); 1017b3660a96SSukumar Swaminathan rval = EIO; 1018b3660a96SSukumar Swaminathan goto failed; 1019b3660a96SSukumar Swaminathan } 1020b3660a96SSukumar Swaminathan } 1021b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 1022b3660a96SSukumar Swaminathan 102382527734SSukumar Swaminathan outptr = mp->virt; 102482527734SSukumar Swaminathan inptr = mp1->virt; 102582527734SSukumar Swaminathan 102682527734SSukumar Swaminathan for (i = 0; i < MEM_ELSBUF_SIZE; i++) { 102782527734SSukumar Swaminathan if (*outptr++ != *inptr++) { 102882527734SSukumar Swaminathan outptr--; 102982527734SSukumar Swaminathan inptr--; 103082527734SSukumar Swaminathan 103182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 103282527734SSukumar Swaminathan "BIU diagnostic failed. " 103382527734SSukumar Swaminathan "offset %x value %x should be %x.", 103482527734SSukumar Swaminathan i, (uint32_t)*inptr, (uint32_t)*outptr); 103582527734SSukumar Swaminathan 103682527734SSukumar Swaminathan rval = EIO; 103782527734SSukumar Swaminathan goto failed; 103882527734SSukumar Swaminathan } 1039291a2b48SSukumar Swaminathan } 1040291a2b48SSukumar Swaminathan 1041fe199829SSukumar Swaminathan /* Free the buffers since we were polling */ 1042a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BUF, (void *)mp); 1043fe199829SSukumar Swaminathan mp = NULL; 1044a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BUF, (void *)mp1); 1045fe199829SSukumar Swaminathan mp1 = NULL; 1046fe199829SSukumar Swaminathan 104782527734SSukumar Swaminathan hba->channel_fcp = FC_FCP_RING; 104882527734SSukumar Swaminathan hba->channel_els = FC_ELS_RING; 104982527734SSukumar Swaminathan hba->channel_ip = FC_IP_RING; 105082527734SSukumar Swaminathan hba->channel_ct = FC_CT_RING; 105182527734SSukumar Swaminathan hba->sli.sli3.ring_count = MAX_RINGS; 1052291a2b48SSukumar Swaminathan 105382527734SSukumar Swaminathan hba->channel_tx_count = 0; 105482527734SSukumar Swaminathan hba->io_count = 0; 105582527734SSukumar Swaminathan hba->fc_iotag = 1; 1056291a2b48SSukumar Swaminathan 105782527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 105882527734SSukumar Swaminathan cp = &hba->chan[i]; 1059291a2b48SSukumar Swaminathan 106082527734SSukumar Swaminathan /* 1 to 1 mapping between ring and channel */ 106182527734SSukumar Swaminathan cp->iopath = (void *)&hba->sli.sli3.ring[i]; 1062291a2b48SSukumar Swaminathan 106382527734SSukumar Swaminathan cp->hba = hba; 106482527734SSukumar Swaminathan cp->channelno = i; 1065291a2b48SSukumar Swaminathan } 1066291a2b48SSukumar Swaminathan 106782527734SSukumar Swaminathan /* 106882527734SSukumar Swaminathan * Setup and issue mailbox CONFIGURE RING command 106982527734SSukumar Swaminathan */ 107082527734SSukumar Swaminathan for (i = 0; i < (uint32_t)hba->sli.sli3.ring_count; i++) { 107182527734SSukumar Swaminathan /* 107282527734SSukumar Swaminathan * Initialize cmd/rsp ring pointers 107382527734SSukumar Swaminathan */ 107482527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[i]; 1075291a2b48SSukumar Swaminathan 107682527734SSukumar Swaminathan /* 1 to 1 mapping between ring and channel */ 107782527734SSukumar Swaminathan rp->channelp = &hba->chan[i]; 1078291a2b48SSukumar Swaminathan 107982527734SSukumar Swaminathan rp->hba = hba; 108082527734SSukumar Swaminathan rp->ringno = (uint8_t)i; 108182527734SSukumar Swaminathan 108282527734SSukumar Swaminathan rp->fc_cmdidx = 0; 108382527734SSukumar Swaminathan rp->fc_rspidx = 0; 108482527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_CFGRING); 108582527734SSukumar Swaminathan 108682527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 108782527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 108882527734SSukumar Swaminathan 108982527734SSukumar Swaminathan emlxs_mb_config_ring(hba, i, mbq); 109082527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 109182527734SSukumar Swaminathan MBX_SUCCESS) { 109282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 109382527734SSukumar Swaminathan "Unable to configure ring. " 109482527734SSukumar Swaminathan "Mailbox cmd=%x status=%x", 109582527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 109682527734SSukumar Swaminathan 109782527734SSukumar Swaminathan rval = EIO; 109882527734SSukumar Swaminathan goto failed; 109982527734SSukumar Swaminathan } 1100291a2b48SSukumar Swaminathan } 1101291a2b48SSukumar Swaminathan 110282527734SSukumar Swaminathan /* 110382527734SSukumar Swaminathan * Setup link timers 110482527734SSukumar Swaminathan */ 110582527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK); 1106291a2b48SSukumar Swaminathan 110782527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 110882527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1109291a2b48SSukumar Swaminathan 111082527734SSukumar Swaminathan emlxs_mb_config_link(hba, mbq); 111182527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 111282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 111382527734SSukumar Swaminathan "Unable to configure link. Mailbox cmd=%x status=%x", 111482527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1115291a2b48SSukumar Swaminathan 111682527734SSukumar Swaminathan rval = EIO; 111782527734SSukumar Swaminathan goto failed; 111882527734SSukumar Swaminathan } 1119291a2b48SSukumar Swaminathan 112082527734SSukumar Swaminathan #ifdef MAX_RRDY_SUPPORT 112182527734SSukumar Swaminathan /* Set MAX_RRDY if one is provided */ 112282527734SSukumar Swaminathan if (cfg[CFG_MAX_RRDY].current) { 1123291a2b48SSukumar Swaminathan 112482527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 112582527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 112682527734SSukumar Swaminathan 112782527734SSukumar Swaminathan emlxs_mb_set_var(hba, (MAILBOX *)mbq, 0x00060412, 112882527734SSukumar Swaminathan cfg[CFG_MAX_RRDY].current); 112982527734SSukumar Swaminathan 113082527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 113182527734SSukumar Swaminathan MBX_SUCCESS) { 113282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 113382527734SSukumar Swaminathan "MAX_RRDY: Unable to set. status=%x " \ 113482527734SSukumar Swaminathan "value=%d", 113582527734SSukumar Swaminathan mb->mbxStatus, cfg[CFG_MAX_RRDY].current); 113682527734SSukumar Swaminathan } else { 113782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 113882527734SSukumar Swaminathan "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current); 113982527734SSukumar Swaminathan } 114082527734SSukumar Swaminathan } 114182527734SSukumar Swaminathan #endif /* MAX_RRDY_SUPPORT */ 114282527734SSukumar Swaminathan 114382527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 114482527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 114582527734SSukumar Swaminathan 114682527734SSukumar Swaminathan /* 114782527734SSukumar Swaminathan * We need to get login parameters for NID 114882527734SSukumar Swaminathan */ 114982527734SSukumar Swaminathan (void) emlxs_mb_read_sparam(hba, mbq); 1150a9800bebSGarrett D'Amore mp = (MATCHMAP *)mbq->bp; 115182527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 115282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 115382527734SSukumar Swaminathan "Unable to read parameters. Mailbox cmd=%x status=%x", 115482527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 115582527734SSukumar Swaminathan 115682527734SSukumar Swaminathan rval = EIO; 115782527734SSukumar Swaminathan goto failed; 115882527734SSukumar Swaminathan } 115982527734SSukumar Swaminathan 116082527734SSukumar Swaminathan /* Free the buffer since we were polling */ 1161a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BUF, (void *)mp); 116282527734SSukumar Swaminathan mp = NULL; 116382527734SSukumar Swaminathan 116482527734SSukumar Swaminathan /* If no serial number in VPD data, then use the WWPN */ 116582527734SSukumar Swaminathan if (vpd->serial_num[0] == 0) { 116682527734SSukumar Swaminathan outptr = (uint8_t *)&hba->wwpn.IEEE[0]; 116782527734SSukumar Swaminathan for (i = 0; i < 12; i++) { 116882527734SSukumar Swaminathan status = *outptr++; 116982527734SSukumar Swaminathan j = ((status & 0xf0) >> 4); 117082527734SSukumar Swaminathan if (j <= 9) { 117182527734SSukumar Swaminathan vpd->serial_num[i] = 117282527734SSukumar Swaminathan (char)((uint8_t)'0' + (uint8_t)j); 117382527734SSukumar Swaminathan } else { 117482527734SSukumar Swaminathan vpd->serial_num[i] = 117582527734SSukumar Swaminathan (char)((uint8_t)'A' + (uint8_t)(j - 10)); 117682527734SSukumar Swaminathan } 117782527734SSukumar Swaminathan 117882527734SSukumar Swaminathan i++; 117982527734SSukumar Swaminathan j = (status & 0xf); 118082527734SSukumar Swaminathan if (j <= 9) { 118182527734SSukumar Swaminathan vpd->serial_num[i] = 118282527734SSukumar Swaminathan (char)((uint8_t)'0' + (uint8_t)j); 118382527734SSukumar Swaminathan } else { 118482527734SSukumar Swaminathan vpd->serial_num[i] = 118582527734SSukumar Swaminathan (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1186291a2b48SSukumar Swaminathan } 1187291a2b48SSukumar Swaminathan } 118882527734SSukumar Swaminathan 1189291a2b48SSukumar Swaminathan /* 119082527734SSukumar Swaminathan * Set port number and port index to zero 119182527734SSukumar Swaminathan * The WWN's are unique to each port and therefore port_num 119282527734SSukumar Swaminathan * must equal zero. This effects the hba_fru_details structure 119382527734SSukumar Swaminathan * in fca_bind_port() 1194291a2b48SSukumar Swaminathan */ 119582527734SSukumar Swaminathan vpd->port_num[0] = 0; 119682527734SSukumar Swaminathan vpd->port_index = 0; 119782527734SSukumar Swaminathan } 1198291a2b48SSukumar Swaminathan 119982527734SSukumar Swaminathan /* 120082527734SSukumar Swaminathan * Make first attempt to set a port index 120182527734SSukumar Swaminathan * Check if this is a multifunction adapter 120282527734SSukumar Swaminathan */ 1203a9800bebSGarrett D'Amore if ((vpd->port_index == (uint32_t)-1) && 120482527734SSukumar Swaminathan (hba->model_info.chip >= EMLXS_THOR_CHIP)) { 120582527734SSukumar Swaminathan char *buffer; 120682527734SSukumar Swaminathan int32_t i; 1207291a2b48SSukumar Swaminathan 120882527734SSukumar Swaminathan /* 120982527734SSukumar Swaminathan * The port address looks like this: 121082527734SSukumar Swaminathan * 1 - for port index 0 121182527734SSukumar Swaminathan * 1,1 - for port index 1 121282527734SSukumar Swaminathan * 1,2 - for port index 2 121382527734SSukumar Swaminathan */ 121482527734SSukumar Swaminathan buffer = ddi_get_name_addr(hba->dip); 1215291a2b48SSukumar Swaminathan 121682527734SSukumar Swaminathan if (buffer) { 121782527734SSukumar Swaminathan vpd->port_index = 0; 1218291a2b48SSukumar Swaminathan 121982527734SSukumar Swaminathan /* Reverse scan for a comma */ 122082527734SSukumar Swaminathan for (i = strlen(buffer) - 1; i > 0; i--) { 122182527734SSukumar Swaminathan if (buffer[i] == ',') { 122282527734SSukumar Swaminathan /* Comma found - set index now */ 122382527734SSukumar Swaminathan vpd->port_index = 122482527734SSukumar Swaminathan emlxs_strtol(&buffer[i + 1], 10); 122582527734SSukumar Swaminathan break; 122682527734SSukumar Swaminathan } 122782527734SSukumar Swaminathan } 122882527734SSukumar Swaminathan } 122982527734SSukumar Swaminathan } 1230291a2b48SSukumar Swaminathan 123182527734SSukumar Swaminathan /* Make final attempt to set a port index */ 1232a9800bebSGarrett D'Amore if (vpd->port_index == (uint32_t)-1) { 123382527734SSukumar Swaminathan dev_info_t *p_dip; 123482527734SSukumar Swaminathan dev_info_t *c_dip; 1235291a2b48SSukumar Swaminathan 123682527734SSukumar Swaminathan p_dip = ddi_get_parent(hba->dip); 123782527734SSukumar Swaminathan c_dip = ddi_get_child(p_dip); 1238291a2b48SSukumar Swaminathan 123982527734SSukumar Swaminathan vpd->port_index = 0; 124082527734SSukumar Swaminathan while (c_dip && (hba->dip != c_dip)) { 124182527734SSukumar Swaminathan c_dip = ddi_get_next_sibling(c_dip); 124282527734SSukumar Swaminathan vpd->port_index++; 1243291a2b48SSukumar Swaminathan } 124482527734SSukumar Swaminathan } 1245291a2b48SSukumar Swaminathan 124682527734SSukumar Swaminathan if (vpd->port_num[0] == 0) { 1247*8f23e9faSHans Rosenfeld if (hba->model_info.channels == EMLXS_MULTI_CHANNEL) { 1248*8f23e9faSHans Rosenfeld (void) snprintf(vpd->port_num, 1249*8f23e9faSHans Rosenfeld (sizeof (vpd->port_num)-1), 1250*8f23e9faSHans Rosenfeld "%d", vpd->port_index); 125182527734SSukumar Swaminathan } 125282527734SSukumar Swaminathan } 1253291a2b48SSukumar Swaminathan 125482527734SSukumar Swaminathan if (vpd->id[0] == 0) { 1255*8f23e9faSHans Rosenfeld (void) strncpy(vpd->id, hba->model_info.model_desc, 1256*8f23e9faSHans Rosenfeld (sizeof (vpd->id)-1)); 125782527734SSukumar Swaminathan } 1258291a2b48SSukumar Swaminathan 125982527734SSukumar Swaminathan if (vpd->manufacturer[0] == 0) { 1260*8f23e9faSHans Rosenfeld (void) strncpy(vpd->manufacturer, hba->model_info.manufacturer, 1261*8f23e9faSHans Rosenfeld (sizeof (vpd->manufacturer)-1)); 126282527734SSukumar Swaminathan } 1263291a2b48SSukumar Swaminathan 126482527734SSukumar Swaminathan if (vpd->part_num[0] == 0) { 1265*8f23e9faSHans Rosenfeld (void) strncpy(vpd->part_num, hba->model_info.model, 1266*8f23e9faSHans Rosenfeld (sizeof (vpd->part_num)-1)); 126782527734SSukumar Swaminathan } 1268291a2b48SSukumar Swaminathan 126982527734SSukumar Swaminathan if (vpd->model_desc[0] == 0) { 1270*8f23e9faSHans Rosenfeld (void) strncpy(vpd->model_desc, hba->model_info.model_desc, 1271*8f23e9faSHans Rosenfeld (sizeof (vpd->model_desc)-1)); 127282527734SSukumar Swaminathan } 1273291a2b48SSukumar Swaminathan 127482527734SSukumar Swaminathan if (vpd->model[0] == 0) { 1275*8f23e9faSHans Rosenfeld (void) strncpy(vpd->model, hba->model_info.model, 1276*8f23e9faSHans Rosenfeld (sizeof (vpd->model)-1)); 127782527734SSukumar Swaminathan } 1278291a2b48SSukumar Swaminathan 127982527734SSukumar Swaminathan if (vpd->prog_types[0] == 0) { 1280*8f23e9faSHans Rosenfeld emlxs_build_prog_types(hba, vpd); 1281291a2b48SSukumar Swaminathan } 1282291a2b48SSukumar Swaminathan 128382527734SSukumar Swaminathan /* Create the symbolic names */ 1284*8f23e9faSHans Rosenfeld (void) snprintf(hba->snn, (sizeof (hba->snn)-1), 1285*8f23e9faSHans Rosenfeld "Emulex %s FV%s DV%s %s", 128682527734SSukumar Swaminathan hba->model_info.model, hba->vpd.fw_version, emlxs_version, 128782527734SSukumar Swaminathan (char *)utsname.nodename); 1288291a2b48SSukumar Swaminathan 1289*8f23e9faSHans Rosenfeld (void) snprintf(hba->spn, (sizeof (hba->spn)-1), 129082527734SSukumar Swaminathan "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 129182527734SSukumar Swaminathan hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, 129282527734SSukumar Swaminathan hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], 129382527734SSukumar Swaminathan hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1294291a2b48SSukumar Swaminathan 129582527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 129682527734SSukumar Swaminathan if ((hba->sparam.portName.nameType != NAME_IEEE) || 129782527734SSukumar Swaminathan (hba->sparam.portName.IEEEextMsn != 0) || 129882527734SSukumar Swaminathan (hba->sparam.portName.IEEEextLsb != 0)) { 1299291a2b48SSukumar Swaminathan 130082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1301*8f23e9faSHans Rosenfeld "WWPN doesn't conform to IP profile: " 1302*8f23e9faSHans Rosenfeld "nameType=%x. Disabling networking.", 130382527734SSukumar Swaminathan hba->sparam.portName.nameType); 1304*8f23e9faSHans Rosenfeld 1305*8f23e9faSHans Rosenfeld cfg[CFG_NETWORK_ON].current = 0; 130682527734SSukumar Swaminathan } 1307*8f23e9faSHans Rosenfeld } 1308291a2b48SSukumar Swaminathan 1309*8f23e9faSHans Rosenfeld if (cfg[CFG_NETWORK_ON].current) { 131082527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 131182527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1312291a2b48SSukumar Swaminathan 131382527734SSukumar Swaminathan /* Issue CONFIG FARP */ 131482527734SSukumar Swaminathan emlxs_mb_config_farp(hba, mbq); 131582527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 131682527734SSukumar Swaminathan MBX_SUCCESS) { 131782527734SSukumar Swaminathan /* 131882527734SSukumar Swaminathan * Let it go through even if failed. 131982527734SSukumar Swaminathan */ 132082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 132182527734SSukumar Swaminathan "Unable to configure FARP. " 132282527734SSukumar Swaminathan "Mailbox cmd=%x status=%x", 132382527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 132482527734SSukumar Swaminathan } 1325291a2b48SSukumar Swaminathan } 132682527734SSukumar Swaminathan #ifdef MSI_SUPPORT 132782527734SSukumar Swaminathan /* Configure MSI map if required */ 132882527734SSukumar Swaminathan if (hba->intr_count > 1) { 1329a9800bebSGarrett D'Amore 1330a9800bebSGarrett D'Amore if (hba->intr_type == DDI_INTR_TYPE_MSIX) { 1331a9800bebSGarrett D'Amore /* always start from 0 */ 1332a9800bebSGarrett D'Amore hba->last_msiid = 0; 1333a9800bebSGarrett D'Amore } 1334a9800bebSGarrett D'Amore 133582527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 133682527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1337291a2b48SSukumar Swaminathan 133882527734SSukumar Swaminathan emlxs_mb_config_msix(hba, mbq, hba->intr_map, hba->intr_count); 1339291a2b48SSukumar Swaminathan 134082527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) == 134182527734SSukumar Swaminathan MBX_SUCCESS) { 134282527734SSukumar Swaminathan goto msi_configured; 134382527734SSukumar Swaminathan } 1344291a2b48SSukumar Swaminathan 134582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 134682527734SSukumar Swaminathan "Unable to config MSIX. Mailbox cmd=0x%x status=0x%x", 134782527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1348291a2b48SSukumar Swaminathan 134982527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 135082527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1351291a2b48SSukumar Swaminathan 135282527734SSukumar Swaminathan emlxs_mb_config_msi(hba, mbq, hba->intr_map, hba->intr_count); 1353291a2b48SSukumar Swaminathan 135482527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) == 135582527734SSukumar Swaminathan MBX_SUCCESS) { 135682527734SSukumar Swaminathan goto msi_configured; 1357291a2b48SSukumar Swaminathan } 1358291a2b48SSukumar Swaminathan 1359291a2b48SSukumar Swaminathan 136082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 136182527734SSukumar Swaminathan "Unable to config MSI. Mailbox cmd=0x%x status=0x%x", 136282527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1363291a2b48SSukumar Swaminathan 136482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 136582527734SSukumar Swaminathan "Attempting single interrupt mode..."); 1366291a2b48SSukumar Swaminathan 136782527734SSukumar Swaminathan /* First cleanup old interrupts */ 136882527734SSukumar Swaminathan (void) emlxs_msi_remove(hba); 136982527734SSukumar Swaminathan (void) emlxs_msi_uninit(hba); 1370291a2b48SSukumar Swaminathan 137182527734SSukumar Swaminathan status = emlxs_msi_init(hba, 1); 1372291a2b48SSukumar Swaminathan 137382527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 137482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 137582527734SSukumar Swaminathan "Unable to initialize interrupt. status=%d", 137682527734SSukumar Swaminathan status); 1377291a2b48SSukumar Swaminathan 137882527734SSukumar Swaminathan rval = EIO; 137982527734SSukumar Swaminathan goto failed; 1380291a2b48SSukumar Swaminathan } 1381291a2b48SSukumar Swaminathan 138282527734SSukumar Swaminathan /* 138382527734SSukumar Swaminathan * Reset adapter - The adapter needs to be reset because 138482527734SSukumar Swaminathan * the bus cannot handle the MSI change without handshaking 138582527734SSukumar Swaminathan * with the adapter again 138682527734SSukumar Swaminathan */ 1387291a2b48SSukumar Swaminathan 138882527734SSukumar Swaminathan (void) emlxs_mem_free_buffer(hba); 138982527734SSukumar Swaminathan fw_check = 0; 139082527734SSukumar Swaminathan goto reset; 139182527734SSukumar Swaminathan } 1392291a2b48SSukumar Swaminathan 139382527734SSukumar Swaminathan msi_configured: 1394291a2b48SSukumar Swaminathan 139582527734SSukumar Swaminathan 1396a9800bebSGarrett D'Amore if ((hba->intr_count >= 1) && 1397a9800bebSGarrett D'Amore (hba->sli_mode == EMLXS_HBA_SLI3_MODE)) { 1398a9800bebSGarrett D'Amore /* intr_count is a sequence of msi id */ 1399a9800bebSGarrett D'Amore /* Setup msi2chan[msi_id] */ 1400a9800bebSGarrett D'Amore for (i = 0; i < hba->intr_count; i ++) { 1401a9800bebSGarrett D'Amore hba->msi2chan[i] = i; 1402a9800bebSGarrett D'Amore if (i >= hba->chan_count) 1403a9800bebSGarrett D'Amore hba->msi2chan[i] = (i - hba->chan_count); 1404a9800bebSGarrett D'Amore } 1405a9800bebSGarrett D'Amore } 140682527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 140782527734SSukumar Swaminathan 140882527734SSukumar Swaminathan /* 140982527734SSukumar Swaminathan * We always disable the firmware traffic cop feature 141082527734SSukumar Swaminathan */ 141182527734SSukumar Swaminathan if (emlxs_disable_traffic_cop) { 141282527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 141382527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 141482527734SSukumar Swaminathan 141582527734SSukumar Swaminathan emlxs_disable_tc(hba, mbq); 141682527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 141782527734SSukumar Swaminathan MBX_SUCCESS) { 141882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 141982527734SSukumar Swaminathan "Unable to disable traffic cop. " 142082527734SSukumar Swaminathan "Mailbox cmd=%x status=%x", 142182527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 142282527734SSukumar Swaminathan 142382527734SSukumar Swaminathan rval = EIO; 142482527734SSukumar Swaminathan goto failed; 1425291a2b48SSukumar Swaminathan } 142682527734SSukumar Swaminathan } 1427291a2b48SSukumar Swaminathan 142882527734SSukumar Swaminathan 142982527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 143082527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 143182527734SSukumar Swaminathan 143282527734SSukumar Swaminathan /* Register for async events */ 143382527734SSukumar Swaminathan emlxs_mb_async_event(hba, mbq); 143482527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 143582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 143682527734SSukumar Swaminathan "Async events disabled. Mailbox status=%x", 143782527734SSukumar Swaminathan mb->mbxStatus); 143882527734SSukumar Swaminathan } else { 143982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 144082527734SSukumar Swaminathan "Async events enabled."); 144182527734SSukumar Swaminathan hba->flag |= FC_ASYNC_EVENTS; 1442291a2b48SSukumar Swaminathan } 1443291a2b48SSukumar Swaminathan 144482527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN); 1445291a2b48SSukumar Swaminathan 144682527734SSukumar Swaminathan emlxs_sli3_enable_intr(hba); 1447291a2b48SSukumar Swaminathan 144882527734SSukumar Swaminathan if (hba->flag & FC_HBQ_ENABLED) { 1449*8f23e9faSHans Rosenfeld if (port->flag & EMLXS_TGT_ENABLED) { 145082527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) { 145182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 145282527734SSukumar Swaminathan &emlxs_init_failed_msg, 145382527734SSukumar Swaminathan "Unable to setup FCT HBQ."); 1454291a2b48SSukumar Swaminathan 145582527734SSukumar Swaminathan rval = ENOMEM; 1456*8f23e9faSHans Rosenfeld 1457*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT 1458*8f23e9faSHans Rosenfeld /* Check if we can fall back to just */ 1459*8f23e9faSHans Rosenfeld /* initiator mode */ 1460*8f23e9faSHans Rosenfeld if ((hba->pm_state == EMLXS_PM_IN_ATTACH) && 1461*8f23e9faSHans Rosenfeld (port->flag & EMLXS_INI_ENABLED) && 1462*8f23e9faSHans Rosenfeld (cfg[CFG_DTM_ENABLE].current == 1) && 1463*8f23e9faSHans Rosenfeld (cfg[CFG_TARGET_MODE].current == 0)) { 1464*8f23e9faSHans Rosenfeld 1465*8f23e9faSHans Rosenfeld cfg[CFG_DTM_ENABLE].current = 0; 1466*8f23e9faSHans Rosenfeld 1467*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 1468*8f23e9faSHans Rosenfeld &emlxs_init_failed_msg, 1469*8f23e9faSHans Rosenfeld "Disabling dynamic target mode. " 1470*8f23e9faSHans Rosenfeld "Enabling initiator mode only."); 1471*8f23e9faSHans Rosenfeld 1472*8f23e9faSHans Rosenfeld /* This will trigger the driver to */ 1473*8f23e9faSHans Rosenfeld /* reattach */ 1474*8f23e9faSHans Rosenfeld rval = EAGAIN; 1475*8f23e9faSHans Rosenfeld } 1476*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */ 147782527734SSukumar Swaminathan goto failed; 147882527734SSukumar Swaminathan } 147982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 148082527734SSukumar Swaminathan "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 148182527734SSukumar Swaminathan } 1482291a2b48SSukumar Swaminathan 148382527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 148482527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) { 148582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 148682527734SSukumar Swaminathan &emlxs_init_failed_msg, 148782527734SSukumar Swaminathan "Unable to setup IP HBQ."); 1488291a2b48SSukumar Swaminathan 148982527734SSukumar Swaminathan rval = ENOMEM; 149082527734SSukumar Swaminathan goto failed; 149182527734SSukumar Swaminathan } 149282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 149382527734SSukumar Swaminathan "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 149482527734SSukumar Swaminathan } 1495291a2b48SSukumar Swaminathan 149682527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) { 149782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 149882527734SSukumar Swaminathan "Unable to setup ELS HBQ."); 149982527734SSukumar Swaminathan rval = ENOMEM; 150082527734SSukumar Swaminathan goto failed; 150182527734SSukumar Swaminathan } 150282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 150382527734SSukumar Swaminathan "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1504291a2b48SSukumar Swaminathan 150582527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) { 150682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 150782527734SSukumar Swaminathan "Unable to setup CT HBQ."); 1508291a2b48SSukumar Swaminathan 150982527734SSukumar Swaminathan rval = ENOMEM; 151082527734SSukumar Swaminathan goto failed; 151182527734SSukumar Swaminathan } 151282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 151382527734SSukumar Swaminathan "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 151482527734SSukumar Swaminathan } else { 1515*8f23e9faSHans Rosenfeld if (port->flag & EMLXS_TGT_ENABLED) { 151682527734SSukumar Swaminathan /* Post the FCT unsol buffers */ 151782527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_FCT_RING]; 151882527734SSukumar Swaminathan for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) { 151982527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 152082527734SSukumar Swaminathan } 152182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 152282527734SSukumar Swaminathan "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 152382527734SSukumar Swaminathan } 1524291a2b48SSukumar Swaminathan 152582527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 152682527734SSukumar Swaminathan /* Post the IP unsol buffers */ 152782527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_IP_RING]; 152882527734SSukumar Swaminathan for (j = 0; j < MEM_IPBUF_COUNT; j += 2) { 152982527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 153082527734SSukumar Swaminathan } 153182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 153282527734SSukumar Swaminathan "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 153382527734SSukumar Swaminathan } 1534291a2b48SSukumar Swaminathan 153582527734SSukumar Swaminathan /* Post the ELS unsol buffers */ 153682527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_ELS_RING]; 153782527734SSukumar Swaminathan for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) { 153882527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 153982527734SSukumar Swaminathan } 154082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 154182527734SSukumar Swaminathan "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1542291a2b48SSukumar Swaminathan 154382527734SSukumar Swaminathan 154482527734SSukumar Swaminathan /* Post the CT unsol buffers */ 154582527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_CT_RING]; 154682527734SSukumar Swaminathan for (j = 0; j < MEM_CTBUF_COUNT; j += 2) { 154782527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 154882527734SSukumar Swaminathan } 154982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 155082527734SSukumar Swaminathan "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1551291a2b48SSukumar Swaminathan } 1552291a2b48SSukumar Swaminathan 1553a9800bebSGarrett D'Amore (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 1554291a2b48SSukumar Swaminathan 1555*8f23e9faSHans Rosenfeld /* Check persist-linkdown */ 1556*8f23e9faSHans Rosenfeld if (cfg[CFG_PERSIST_LINKDOWN].current) { 1557*8f23e9faSHans Rosenfeld EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST); 1558*8f23e9faSHans Rosenfeld return (0); 1559*8f23e9faSHans Rosenfeld } 1560*8f23e9faSHans Rosenfeld 1561*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT 1562*8f23e9faSHans Rosenfeld if ((port->mode == MODE_TARGET) && 1563*8f23e9faSHans Rosenfeld !(port->fct_flags & FCT_STATE_PORT_ONLINE)) { 1564*8f23e9faSHans Rosenfeld emlxs_enable_latt(hba); 1565*8f23e9faSHans Rosenfeld return (0); 1566*8f23e9faSHans Rosenfeld } 1567*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */ 1568*8f23e9faSHans Rosenfeld 156982527734SSukumar Swaminathan /* 157082527734SSukumar Swaminathan * Setup and issue mailbox INITIALIZE LINK command 157182527734SSukumar Swaminathan * At this point, the interrupt will be generated by the HW 157282527734SSukumar Swaminathan */ 1573*8f23e9faSHans Rosenfeld mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX); 1574*8f23e9faSHans Rosenfeld if (mbq == NULL) { 1575*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1576*8f23e9faSHans Rosenfeld "Unable to allocate mailbox buffer."); 1577a9800bebSGarrett D'Amore 1578*8f23e9faSHans Rosenfeld rval = EIO; 1579*8f23e9faSHans Rosenfeld goto failed; 1580*8f23e9faSHans Rosenfeld } 1581*8f23e9faSHans Rosenfeld mb = (MAILBOX *)mbq; 1582a9800bebSGarrett D'Amore 1583*8f23e9faSHans Rosenfeld emlxs_mb_init_link(hba, mbq, cfg[CFG_TOPOLOGY].current, 1584*8f23e9faSHans Rosenfeld cfg[CFG_LINK_SPEED].current); 1585291a2b48SSukumar Swaminathan 1586*8f23e9faSHans Rosenfeld rval = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 1587*8f23e9faSHans Rosenfeld if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) { 1588*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1589*8f23e9faSHans Rosenfeld "Unable to initialize link. " \ 1590*8f23e9faSHans Rosenfeld "Mailbox cmd=%x status=%x", 1591*8f23e9faSHans Rosenfeld mb->mbxCommand, mb->mbxStatus); 1592*8f23e9faSHans Rosenfeld 1593*8f23e9faSHans Rosenfeld emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 1594*8f23e9faSHans Rosenfeld mbq = NULL; 1595*8f23e9faSHans Rosenfeld rval = EIO; 1596*8f23e9faSHans Rosenfeld goto failed; 1597*8f23e9faSHans Rosenfeld } 1598*8f23e9faSHans Rosenfeld 1599*8f23e9faSHans Rosenfeld /* 1600*8f23e9faSHans Rosenfeld * Enable link attention interrupt 1601*8f23e9faSHans Rosenfeld */ 1602*8f23e9faSHans Rosenfeld emlxs_enable_latt(hba); 1603*8f23e9faSHans Rosenfeld 1604*8f23e9faSHans Rosenfeld /* Wait for link to come up */ 1605*8f23e9faSHans Rosenfeld i = cfg[CFG_LINKUP_DELAY].current; 1606*8f23e9faSHans Rosenfeld while (i && (hba->state < FC_LINK_UP)) { 1607*8f23e9faSHans Rosenfeld /* Check for hardware error */ 1608*8f23e9faSHans Rosenfeld if (hba->state == FC_ERROR) { 1609*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 1610*8f23e9faSHans Rosenfeld &emlxs_init_failed_msg, 1611*8f23e9faSHans Rosenfeld "Adapter error."); 1612291a2b48SSukumar Swaminathan 1613a9800bebSGarrett D'Amore mbq = NULL; 161482527734SSukumar Swaminathan rval = EIO; 161582527734SSukumar Swaminathan goto failed; 161682527734SSukumar Swaminathan } 1617291a2b48SSukumar Swaminathan 1618*8f23e9faSHans Rosenfeld BUSYWAIT_MS(1000); 1619*8f23e9faSHans Rosenfeld i--; 162082527734SSukumar Swaminathan } 162182527734SSukumar Swaminathan 162282527734SSukumar Swaminathan /* 162382527734SSukumar Swaminathan * The leadvile driver will now handle the FLOGI at the driver level 162482527734SSukumar Swaminathan */ 1625291a2b48SSukumar Swaminathan 1626291a2b48SSukumar Swaminathan return (0); 1627291a2b48SSukumar Swaminathan 162882527734SSukumar Swaminathan failed: 1629291a2b48SSukumar Swaminathan 163082527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 1631291a2b48SSukumar Swaminathan 163282527734SSukumar Swaminathan if (hba->intr_flags & EMLXS_MSI_ADDED) { 163382527734SSukumar Swaminathan (void) EMLXS_INTR_REMOVE(hba); 163482527734SSukumar Swaminathan } 1635291a2b48SSukumar Swaminathan 163682527734SSukumar Swaminathan if (mp) { 1637a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BUF, (void *)mp); 163882527734SSukumar Swaminathan mp = NULL; 163982527734SSukumar Swaminathan } 1640291a2b48SSukumar Swaminathan 164182527734SSukumar Swaminathan if (mp1) { 1642a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_BUF, (void *)mp1); 164382527734SSukumar Swaminathan mp1 = NULL; 164482527734SSukumar Swaminathan } 1645291a2b48SSukumar Swaminathan 164682527734SSukumar Swaminathan (void) emlxs_mem_free_buffer(hba); 1647291a2b48SSukumar Swaminathan 164882527734SSukumar Swaminathan if (mbq) { 164982527734SSukumar Swaminathan (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 165082527734SSukumar Swaminathan mbq = NULL; 165182527734SSukumar Swaminathan mb = NULL; 1652291a2b48SSukumar Swaminathan } 1653291a2b48SSukumar Swaminathan 165482527734SSukumar Swaminathan if (rval == 0) { 165582527734SSukumar Swaminathan rval = EIO; 165682527734SSukumar Swaminathan } 1657291a2b48SSukumar Swaminathan 165882527734SSukumar Swaminathan return (rval); 1659291a2b48SSukumar Swaminathan 166082527734SSukumar Swaminathan } /* emlxs_sli3_online() */ 1661291a2b48SSukumar Swaminathan 1662291a2b48SSukumar Swaminathan 1663*8f23e9faSHans Rosenfeld /*ARGSUSED*/ 166482527734SSukumar Swaminathan static void 1665*8f23e9faSHans Rosenfeld emlxs_sli3_offline(emlxs_hba_t *hba, uint32_t reset_requested) 166682527734SSukumar Swaminathan { 166782527734SSukumar Swaminathan /* Reverse emlxs_sli3_online */ 1668291a2b48SSukumar Swaminathan 166982527734SSukumar Swaminathan /* Kill the adapter */ 167082527734SSukumar Swaminathan emlxs_sli3_hba_kill(hba); 1671291a2b48SSukumar Swaminathan 167282527734SSukumar Swaminathan /* Free driver shared memory */ 167382527734SSukumar Swaminathan (void) emlxs_mem_free_buffer(hba); 1674291a2b48SSukumar Swaminathan 167582527734SSukumar Swaminathan } /* emlxs_sli3_offline() */ 1676291a2b48SSukumar Swaminathan 1677291a2b48SSukumar Swaminathan 167882527734SSukumar Swaminathan static int 167982527734SSukumar Swaminathan emlxs_sli3_map_hdw(emlxs_hba_t *hba) 1680291a2b48SSukumar Swaminathan { 168182527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 168282527734SSukumar Swaminathan dev_info_t *dip; 168382527734SSukumar Swaminathan ddi_device_acc_attr_t dev_attr; 168482527734SSukumar Swaminathan int status; 1685291a2b48SSukumar Swaminathan 168682527734SSukumar Swaminathan dip = (dev_info_t *)hba->dip; 168782527734SSukumar Swaminathan dev_attr = emlxs_dev_acc_attr; 1688291a2b48SSukumar Swaminathan 168982527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 1690291a2b48SSukumar Swaminathan 169182527734SSukumar Swaminathan if (hba->sli.sli3.slim_acc_handle == 0) { 169282527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, 169382527734SSukumar Swaminathan SBUS_DFLY_SLIM_RINDEX, 169482527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.slim_addr, 169582527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle); 169682527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 169782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 169882527734SSukumar Swaminathan &emlxs_attach_failed_msg, 169982527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup SLIM failed. " 170082527734SSukumar Swaminathan "status=%x", status); 170182527734SSukumar Swaminathan goto failed; 170282527734SSukumar Swaminathan } 170382527734SSukumar Swaminathan } 170482527734SSukumar Swaminathan if (hba->sli.sli3.csr_acc_handle == 0) { 170582527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, 170682527734SSukumar Swaminathan SBUS_DFLY_CSR_RINDEX, 170782527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.csr_addr, 170882527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle); 170982527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 171082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 171182527734SSukumar Swaminathan &emlxs_attach_failed_msg, 171282527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup DFLY CSR " 171382527734SSukumar Swaminathan "failed. status=%x", status); 171482527734SSukumar Swaminathan goto failed; 171582527734SSukumar Swaminathan } 171682527734SSukumar Swaminathan } 171782527734SSukumar Swaminathan if (hba->sli.sli3.sbus_flash_acc_handle == 0) { 171882527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, SBUS_FLASH_RDWR, 171982527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.sbus_flash_addr, 0, 0, 172082527734SSukumar Swaminathan &dev_attr, &hba->sli.sli3.sbus_flash_acc_handle); 172182527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 172282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 172382527734SSukumar Swaminathan &emlxs_attach_failed_msg, 172482527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup Fcode Flash " 172582527734SSukumar Swaminathan "failed. status=%x", status); 172682527734SSukumar Swaminathan goto failed; 172782527734SSukumar Swaminathan } 172882527734SSukumar Swaminathan } 172982527734SSukumar Swaminathan if (hba->sli.sli3.sbus_core_acc_handle == 0) { 173082527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, SBUS_TITAN_CORE_RINDEX, 173182527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.sbus_core_addr, 0, 0, 173282527734SSukumar Swaminathan &dev_attr, &hba->sli.sli3.sbus_core_acc_handle); 173382527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 173482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 173582527734SSukumar Swaminathan &emlxs_attach_failed_msg, 173682527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup TITAN CORE " 173782527734SSukumar Swaminathan "failed. status=%x", status); 173882527734SSukumar Swaminathan goto failed; 173982527734SSukumar Swaminathan } 1740291a2b48SSukumar Swaminathan } 1741291a2b48SSukumar Swaminathan 174282527734SSukumar Swaminathan if (hba->sli.sli3.sbus_csr_handle == 0) { 174382527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, SBUS_TITAN_CSR_RINDEX, 174482527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.sbus_csr_addr, 174582527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.sbus_csr_handle); 174682527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 174782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 174882527734SSukumar Swaminathan &emlxs_attach_failed_msg, 174982527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup TITAN CSR " 175082527734SSukumar Swaminathan "failed. status=%x", status); 175182527734SSukumar Swaminathan goto failed; 1752291a2b48SSukumar Swaminathan } 1753291a2b48SSukumar Swaminathan } 175482527734SSukumar Swaminathan } else { /* ****** PCI ****** */ 1755291a2b48SSukumar Swaminathan 175682527734SSukumar Swaminathan if (hba->sli.sli3.slim_acc_handle == 0) { 175782527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, PCI_SLIM_RINDEX, 175882527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.slim_addr, 175982527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle); 176082527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 176182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 176282527734SSukumar Swaminathan &emlxs_attach_failed_msg, 176382527734SSukumar Swaminathan "(PCI) ddi_regs_map_setup SLIM failed. " 176482527734SSukumar Swaminathan "stat=%d mem=%p attr=%p hdl=%p", 176582527734SSukumar Swaminathan status, &hba->sli.sli3.slim_addr, &dev_attr, 176682527734SSukumar Swaminathan &hba->sli.sli3.slim_acc_handle); 176782527734SSukumar Swaminathan goto failed; 176882527734SSukumar Swaminathan } 1769291a2b48SSukumar Swaminathan } 1770291a2b48SSukumar Swaminathan 177182527734SSukumar Swaminathan /* 177282527734SSukumar Swaminathan * Map in control registers, using memory-mapped version of 177382527734SSukumar Swaminathan * the registers rather than the I/O space-mapped registers. 177482527734SSukumar Swaminathan */ 177582527734SSukumar Swaminathan if (hba->sli.sli3.csr_acc_handle == 0) { 177682527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, PCI_CSR_RINDEX, 177782527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.csr_addr, 177882527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle); 177982527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 178082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 178182527734SSukumar Swaminathan &emlxs_attach_failed_msg, 178282527734SSukumar Swaminathan "ddi_regs_map_setup CSR failed. status=%x", 178382527734SSukumar Swaminathan status); 178482527734SSukumar Swaminathan goto failed; 178582527734SSukumar Swaminathan } 178682527734SSukumar Swaminathan } 1787291a2b48SSukumar Swaminathan } 1788291a2b48SSukumar Swaminathan 178982527734SSukumar Swaminathan if (hba->sli.sli3.slim2.virt == 0) { 179082527734SSukumar Swaminathan MBUF_INFO *buf_info; 179182527734SSukumar Swaminathan MBUF_INFO bufinfo; 1792291a2b48SSukumar Swaminathan 179382527734SSukumar Swaminathan buf_info = &bufinfo; 1794291a2b48SSukumar Swaminathan 179582527734SSukumar Swaminathan bzero(buf_info, sizeof (MBUF_INFO)); 179682527734SSukumar Swaminathan buf_info->size = SLI_SLIM2_SIZE; 179782527734SSukumar Swaminathan buf_info->flags = 179882527734SSukumar Swaminathan FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; 179982527734SSukumar Swaminathan buf_info->align = ddi_ptob(dip, 1L); 1800291a2b48SSukumar Swaminathan 180182527734SSukumar Swaminathan (void) emlxs_mem_alloc(hba, buf_info); 1802291a2b48SSukumar Swaminathan 180382527734SSukumar Swaminathan if (buf_info->virt == NULL) { 180482527734SSukumar Swaminathan goto failed; 1805291a2b48SSukumar Swaminathan } 180682527734SSukumar Swaminathan 1807a9800bebSGarrett D'Amore hba->sli.sli3.slim2.virt = buf_info->virt; 180882527734SSukumar Swaminathan hba->sli.sli3.slim2.phys = buf_info->phys; 180982527734SSukumar Swaminathan hba->sli.sli3.slim2.size = SLI_SLIM2_SIZE; 181082527734SSukumar Swaminathan hba->sli.sli3.slim2.data_handle = buf_info->data_handle; 181182527734SSukumar Swaminathan hba->sli.sli3.slim2.dma_handle = buf_info->dma_handle; 181282527734SSukumar Swaminathan bzero((char *)hba->sli.sli3.slim2.virt, SLI_SLIM2_SIZE); 1813291a2b48SSukumar Swaminathan } 1814291a2b48SSukumar Swaminathan 181582527734SSukumar Swaminathan /* offset from beginning of register space */ 181682527734SSukumar Swaminathan hba->sli.sli3.ha_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 181782527734SSukumar Swaminathan (sizeof (uint32_t) * HA_REG_OFFSET)); 181882527734SSukumar Swaminathan hba->sli.sli3.ca_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 181982527734SSukumar Swaminathan (sizeof (uint32_t) * CA_REG_OFFSET)); 182082527734SSukumar Swaminathan hba->sli.sli3.hs_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 182182527734SSukumar Swaminathan (sizeof (uint32_t) * HS_REG_OFFSET)); 182282527734SSukumar Swaminathan hba->sli.sli3.hc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 182382527734SSukumar Swaminathan (sizeof (uint32_t) * HC_REG_OFFSET)); 182482527734SSukumar Swaminathan hba->sli.sli3.bc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 182582527734SSukumar Swaminathan (sizeof (uint32_t) * BC_REG_OFFSET)); 1826291a2b48SSukumar Swaminathan 182782527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 182882527734SSukumar Swaminathan /* offset from beginning of register space */ 182982527734SSukumar Swaminathan /* for TITAN registers */ 183082527734SSukumar Swaminathan hba->sli.sli3.shc_reg_addr = 183182527734SSukumar Swaminathan (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 183282527734SSukumar Swaminathan (sizeof (uint32_t) * SBUS_CTRL_REG_OFFSET)); 183382527734SSukumar Swaminathan hba->sli.sli3.shs_reg_addr = 183482527734SSukumar Swaminathan (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 183582527734SSukumar Swaminathan (sizeof (uint32_t) * SBUS_STAT_REG_OFFSET)); 183682527734SSukumar Swaminathan hba->sli.sli3.shu_reg_addr = 183782527734SSukumar Swaminathan (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 183882527734SSukumar Swaminathan (sizeof (uint32_t) * SBUS_UPDATE_REG_OFFSET)); 183982527734SSukumar Swaminathan } 184082527734SSukumar Swaminathan hba->chan_count = MAX_RINGS; 1841291a2b48SSukumar Swaminathan 184282527734SSukumar Swaminathan return (0); 1843291a2b48SSukumar Swaminathan 184482527734SSukumar Swaminathan failed: 1845291a2b48SSukumar Swaminathan 184682527734SSukumar Swaminathan emlxs_sli3_unmap_hdw(hba); 184782527734SSukumar Swaminathan return (ENOMEM); 1848291a2b48SSukumar Swaminathan 184982527734SSukumar Swaminathan } /* emlxs_sli3_map_hdw() */ 1850291a2b48SSukumar Swaminathan 1851291a2b48SSukumar Swaminathan 185282527734SSukumar Swaminathan static void 185382527734SSukumar Swaminathan emlxs_sli3_unmap_hdw(emlxs_hba_t *hba) 185482527734SSukumar Swaminathan { 185582527734SSukumar Swaminathan MBUF_INFO bufinfo; 185682527734SSukumar Swaminathan MBUF_INFO *buf_info = &bufinfo; 1857291a2b48SSukumar Swaminathan 185882527734SSukumar Swaminathan if (hba->sli.sli3.csr_acc_handle) { 185982527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.csr_acc_handle); 186082527734SSukumar Swaminathan hba->sli.sli3.csr_acc_handle = 0; 186182527734SSukumar Swaminathan } 1862291a2b48SSukumar Swaminathan 186382527734SSukumar Swaminathan if (hba->sli.sli3.slim_acc_handle) { 186482527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.slim_acc_handle); 186582527734SSukumar Swaminathan hba->sli.sli3.slim_acc_handle = 0; 186682527734SSukumar Swaminathan } 1867291a2b48SSukumar Swaminathan 186882527734SSukumar Swaminathan if (hba->sli.sli3.sbus_flash_acc_handle) { 186982527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.sbus_flash_acc_handle); 187082527734SSukumar Swaminathan hba->sli.sli3.sbus_flash_acc_handle = 0; 187182527734SSukumar Swaminathan } 1872291a2b48SSukumar Swaminathan 187382527734SSukumar Swaminathan if (hba->sli.sli3.sbus_core_acc_handle) { 187482527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.sbus_core_acc_handle); 187582527734SSukumar Swaminathan hba->sli.sli3.sbus_core_acc_handle = 0; 187682527734SSukumar Swaminathan } 1877291a2b48SSukumar Swaminathan 187882527734SSukumar Swaminathan if (hba->sli.sli3.sbus_csr_handle) { 187982527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.sbus_csr_handle); 188082527734SSukumar Swaminathan hba->sli.sli3.sbus_csr_handle = 0; 188182527734SSukumar Swaminathan } 1882291a2b48SSukumar Swaminathan 188382527734SSukumar Swaminathan if (hba->sli.sli3.slim2.virt) { 188482527734SSukumar Swaminathan bzero(buf_info, sizeof (MBUF_INFO)); 1885291a2b48SSukumar Swaminathan 188682527734SSukumar Swaminathan if (hba->sli.sli3.slim2.phys) { 188782527734SSukumar Swaminathan buf_info->phys = hba->sli.sli3.slim2.phys; 188882527734SSukumar Swaminathan buf_info->data_handle = hba->sli.sli3.slim2.data_handle; 188982527734SSukumar Swaminathan buf_info->dma_handle = hba->sli.sli3.slim2.dma_handle; 189082527734SSukumar Swaminathan buf_info->flags = FC_MBUF_DMA; 189182527734SSukumar Swaminathan } 1892291a2b48SSukumar Swaminathan 1893a9800bebSGarrett D'Amore buf_info->virt = hba->sli.sli3.slim2.virt; 189482527734SSukumar Swaminathan buf_info->size = hba->sli.sli3.slim2.size; 189582527734SSukumar Swaminathan emlxs_mem_free(hba, buf_info); 1896291a2b48SSukumar Swaminathan 1897a9800bebSGarrett D'Amore hba->sli.sli3.slim2.virt = NULL; 1898291a2b48SSukumar Swaminathan } 1899291a2b48SSukumar Swaminathan 1900291a2b48SSukumar Swaminathan 190182527734SSukumar Swaminathan return; 1902291a2b48SSukumar Swaminathan 190382527734SSukumar Swaminathan } /* emlxs_sli3_unmap_hdw() */ 1904291a2b48SSukumar Swaminathan 1905291a2b48SSukumar Swaminathan 190682527734SSukumar Swaminathan static uint32_t 190782527734SSukumar Swaminathan emlxs_sli3_hba_init(emlxs_hba_t *hba) 190882527734SSukumar Swaminathan { 190982527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 191082527734SSukumar Swaminathan emlxs_port_t *vport; 191182527734SSukumar Swaminathan emlxs_config_t *cfg; 1912a9800bebSGarrett D'Amore uint16_t i; 1913*8f23e9faSHans Rosenfeld VPIobj_t *vpip; 19144baa2c25SSukumar Swaminathan 191582527734SSukumar Swaminathan cfg = &CFG; 191682527734SSukumar Swaminathan i = 0; 1917291a2b48SSukumar Swaminathan 191882527734SSukumar Swaminathan /* Restart the adapter */ 191982527734SSukumar Swaminathan if (emlxs_sli3_hba_reset(hba, 1, 0, 0)) { 192082527734SSukumar Swaminathan return (1); 192182527734SSukumar Swaminathan } 1922291a2b48SSukumar Swaminathan 192382527734SSukumar Swaminathan hba->channel_fcp = FC_FCP_RING; 192482527734SSukumar Swaminathan hba->channel_els = FC_ELS_RING; 192582527734SSukumar Swaminathan hba->channel_ip = FC_IP_RING; 192682527734SSukumar Swaminathan hba->channel_ct = FC_CT_RING; 192782527734SSukumar Swaminathan hba->chan_count = MAX_RINGS; 192882527734SSukumar Swaminathan hba->sli.sli3.ring_count = MAX_RINGS; 1929291a2b48SSukumar Swaminathan 1930291a2b48SSukumar Swaminathan /* 193182527734SSukumar Swaminathan * WARNING: There is a max of 6 ring masks allowed 1932291a2b48SSukumar Swaminathan */ 193382527734SSukumar Swaminathan /* RING 0 - FCP */ 1934*8f23e9faSHans Rosenfeld if (port->flag & EMLXS_TGT_ENABLED) { 193582527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_FCP_RING] = 1; 193682527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_FCP_CMND; 193782527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0; 1938*8f23e9faSHans Rosenfeld hba->sli.sli3.ring_tval[i] = FC_TYPE_SCSI_FCP; 193982527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 194082527734SSukumar Swaminathan } else { 194182527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_FCP_RING] = 0; 1942291a2b48SSukumar Swaminathan } 1943291a2b48SSukumar Swaminathan 194482527734SSukumar Swaminathan hba->sli.sli3.ring[FC_FCP_RING].fc_numCiocb = SLIM_IOCB_CMD_R0_ENTRIES; 194582527734SSukumar Swaminathan hba->sli.sli3.ring[FC_FCP_RING].fc_numRiocb = SLIM_IOCB_RSP_R0_ENTRIES; 1946291a2b48SSukumar Swaminathan 194782527734SSukumar Swaminathan /* RING 1 - IP */ 194882527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 194982527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_IP_RING] = 1; 195082527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_UNSOL_DATA; /* Unsol Data */ 195182527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0xFF; 1952*8f23e9faSHans Rosenfeld hba->sli.sli3.ring_tval[i] = FC_TYPE_IS8802_SNAP; /* LLC/SNAP */ 195382527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 1954291a2b48SSukumar Swaminathan } else { 195582527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_IP_RING] = 0; 1956291a2b48SSukumar Swaminathan } 1957291a2b48SSukumar Swaminathan 195882527734SSukumar Swaminathan hba->sli.sli3.ring[FC_IP_RING].fc_numCiocb = SLIM_IOCB_CMD_R1_ENTRIES; 195982527734SSukumar Swaminathan hba->sli.sli3.ring[FC_IP_RING].fc_numRiocb = SLIM_IOCB_RSP_R1_ENTRIES; 19604baa2c25SSukumar Swaminathan 196182527734SSukumar Swaminathan /* RING 2 - ELS */ 196282527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_ELS_RING] = 1; 196382527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_ELS_REQ; /* ELS request/rsp */ 196482527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0xFE; 1965*8f23e9faSHans Rosenfeld hba->sli.sli3.ring_tval[i] = FC_TYPE_EXTENDED_LS; /* ELS */ 196682527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 1967291a2b48SSukumar Swaminathan 196882527734SSukumar Swaminathan hba->sli.sli3.ring[FC_ELS_RING].fc_numCiocb = SLIM_IOCB_CMD_R2_ENTRIES; 196982527734SSukumar Swaminathan hba->sli.sli3.ring[FC_ELS_RING].fc_numRiocb = SLIM_IOCB_RSP_R2_ENTRIES; 1970291a2b48SSukumar Swaminathan 197182527734SSukumar Swaminathan /* RING 3 - CT */ 197282527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_CT_RING] = 1; 197382527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_UNSOL_CTL; /* CT request/rsp */ 197482527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0xFE; 1975*8f23e9faSHans Rosenfeld hba->sli.sli3.ring_tval[i] = FC_TYPE_FC_SERVICES; /* CT */ 197682527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 1977291a2b48SSukumar Swaminathan 197882527734SSukumar Swaminathan hba->sli.sli3.ring[FC_CT_RING].fc_numCiocb = SLIM_IOCB_CMD_R3_ENTRIES; 197982527734SSukumar Swaminathan hba->sli.sli3.ring[FC_CT_RING].fc_numRiocb = SLIM_IOCB_RSP_R3_ENTRIES; 1980291a2b48SSukumar Swaminathan 198182527734SSukumar Swaminathan if (i > 6) { 198282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 1983*8f23e9faSHans Rosenfeld "hba_init: Too many ring masks defined. cnt=%d", i); 198482527734SSukumar Swaminathan return (1); 198582527734SSukumar Swaminathan } 198682527734SSukumar Swaminathan 198782527734SSukumar Swaminathan /* Initialize all the port objects */ 198882527734SSukumar Swaminathan hba->vpi_max = 0; 198982527734SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 199082527734SSukumar Swaminathan vport = &VPORT(i); 199182527734SSukumar Swaminathan vport->hba = hba; 199282527734SSukumar Swaminathan vport->vpi = i; 1993*8f23e9faSHans Rosenfeld 1994*8f23e9faSHans Rosenfeld vpip = &vport->VPIobj; 1995*8f23e9faSHans Rosenfeld vpip->index = i; 1996*8f23e9faSHans Rosenfeld vpip->VPI = i; 1997*8f23e9faSHans Rosenfeld vpip->port = vport; 1998*8f23e9faSHans Rosenfeld vpip->state = VPI_STATE_OFFLINE; 1999*8f23e9faSHans Rosenfeld vport->vpip = vpip; 200082527734SSukumar Swaminathan } 200182527734SSukumar Swaminathan 200282527734SSukumar Swaminathan /* 200382527734SSukumar Swaminathan * Initialize the max_node count to a default value if needed 200482527734SSukumar Swaminathan * This determines how many node objects we preallocate in the pool 200582527734SSukumar Swaminathan * The actual max_nodes will be set later based on adapter info 200682527734SSukumar Swaminathan */ 200782527734SSukumar Swaminathan if (hba->max_nodes == 0) { 200882527734SSukumar Swaminathan if (cfg[CFG_NUM_NODES].current > 0) { 200982527734SSukumar Swaminathan hba->max_nodes = cfg[CFG_NUM_NODES].current; 201082527734SSukumar Swaminathan } else if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 201182527734SSukumar Swaminathan hba->max_nodes = 4096; 201282527734SSukumar Swaminathan } else { 201382527734SSukumar Swaminathan hba->max_nodes = 512; 201482527734SSukumar Swaminathan } 201582527734SSukumar Swaminathan } 2016291a2b48SSukumar Swaminathan 201782527734SSukumar Swaminathan return (0); 2018291a2b48SSukumar Swaminathan 201982527734SSukumar Swaminathan } /* emlxs_sli3_hba_init() */ 2020291a2b48SSukumar Swaminathan 2021291a2b48SSukumar Swaminathan 202282527734SSukumar Swaminathan /* 202382527734SSukumar Swaminathan * 0: quiesce indicates the call is not from quiesce routine. 202482527734SSukumar Swaminathan * 1: quiesce indicates the call is from quiesce routine. 202582527734SSukumar Swaminathan */ 202682527734SSukumar Swaminathan static uint32_t 202782527734SSukumar Swaminathan emlxs_sli3_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post, 202882527734SSukumar Swaminathan uint32_t quiesce) 2029291a2b48SSukumar Swaminathan { 203082527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 203182527734SSukumar Swaminathan MAILBOX *swpmb; 203282527734SSukumar Swaminathan MAILBOX *mb; 203382527734SSukumar Swaminathan uint32_t word0; 203482527734SSukumar Swaminathan uint16_t cfg_value; 2035*8f23e9faSHans Rosenfeld uint32_t status = 0; 203682527734SSukumar Swaminathan uint32_t status1; 203782527734SSukumar Swaminathan uint32_t status2; 203882527734SSukumar Swaminathan uint32_t i; 203982527734SSukumar Swaminathan uint32_t ready; 204082527734SSukumar Swaminathan emlxs_port_t *vport; 204182527734SSukumar Swaminathan RING *rp; 204282527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 2043291a2b48SSukumar Swaminathan 204482527734SSukumar Swaminathan if (!cfg[CFG_RESET_ENABLE].current) { 204582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 204682527734SSukumar Swaminathan "Adapter reset disabled."); 204782527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 2048291a2b48SSukumar Swaminathan 204982527734SSukumar Swaminathan return (1); 2050291a2b48SSukumar Swaminathan } 2051291a2b48SSukumar Swaminathan 205282527734SSukumar Swaminathan /* Kill the adapter first */ 205382527734SSukumar Swaminathan if (quiesce == 0) { 205482527734SSukumar Swaminathan emlxs_sli3_hba_kill(hba); 205582527734SSukumar Swaminathan } else { 205682527734SSukumar Swaminathan emlxs_sli3_hba_kill4quiesce(hba); 2057291a2b48SSukumar Swaminathan } 2058291a2b48SSukumar Swaminathan 205982527734SSukumar Swaminathan if (restart) { 206082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 206182527734SSukumar Swaminathan "Restarting."); 206282527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_START); 2063291a2b48SSukumar Swaminathan 206482527734SSukumar Swaminathan ready = (HS_FFRDY | HS_MBRDY); 206582527734SSukumar Swaminathan } else { 206682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 206782527734SSukumar Swaminathan "Resetting."); 206882527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_WARM_START); 2069291a2b48SSukumar Swaminathan 207082527734SSukumar Swaminathan ready = HS_MBRDY; 2071291a2b48SSukumar Swaminathan } 2072291a2b48SSukumar Swaminathan 207382527734SSukumar Swaminathan hba->flag &= ~(FC_SLIM2_MODE | FC_HARDWARE_ERROR); 2074291a2b48SSukumar Swaminathan 207582527734SSukumar Swaminathan mb = FC_SLIM1_MAILBOX(hba); 207682527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 2077291a2b48SSukumar Swaminathan 207882527734SSukumar Swaminathan reset: 2079291a2b48SSukumar Swaminathan 2080*8f23e9faSHans Rosenfeld i = 0; 2081*8f23e9faSHans Rosenfeld 208282527734SSukumar Swaminathan /* Save reset time */ 208382527734SSukumar Swaminathan HBASTATS.ResetTime = hba->timer_tics; 2084291a2b48SSukumar Swaminathan 208582527734SSukumar Swaminathan if (restart) { 208682527734SSukumar Swaminathan /* First put restart command in mailbox */ 208782527734SSukumar Swaminathan word0 = 0; 208882527734SSukumar Swaminathan swpmb->mbxCommand = MBX_RESTART; 208982527734SSukumar Swaminathan swpmb->mbxHc = 1; 209082527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb), word0); 209182527734SSukumar Swaminathan 209282527734SSukumar Swaminathan /* Only skip post after emlxs_sli3_online is completed */ 209382527734SSukumar Swaminathan if (skip_post) { 209482527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1), 209582527734SSukumar Swaminathan 1); 209682527734SSukumar Swaminathan } else { 209782527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1), 209882527734SSukumar Swaminathan 0); 2099291a2b48SSukumar Swaminathan } 2100291a2b48SSukumar Swaminathan 210182527734SSukumar Swaminathan } 2102291a2b48SSukumar Swaminathan 210382527734SSukumar Swaminathan /* 210482527734SSukumar Swaminathan * Turn off SERR, PERR in PCI cmd register 210582527734SSukumar Swaminathan */ 210682527734SSukumar Swaminathan cfg_value = ddi_get16(hba->pci_acc_handle, 210782527734SSukumar Swaminathan (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER)); 2108291a2b48SSukumar Swaminathan 210982527734SSukumar Swaminathan ddi_put16(hba->pci_acc_handle, 211082527734SSukumar Swaminathan (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 211182527734SSukumar Swaminathan (uint16_t)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL))); 2112291a2b48SSukumar Swaminathan 211382527734SSukumar Swaminathan hba->sli.sli3.hc_copy = HC_INITFF; 211482527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 2115291a2b48SSukumar Swaminathan 211682527734SSukumar Swaminathan /* Wait 1 msec before restoring PCI config */ 2117*8f23e9faSHans Rosenfeld BUSYWAIT_MS(1); 2118291a2b48SSukumar Swaminathan 211982527734SSukumar Swaminathan /* Restore PCI cmd register */ 212082527734SSukumar Swaminathan ddi_put16(hba->pci_acc_handle, 212182527734SSukumar Swaminathan (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 212282527734SSukumar Swaminathan (uint16_t)cfg_value); 2123291a2b48SSukumar Swaminathan 212482527734SSukumar Swaminathan /* Wait 3 seconds before checking */ 2125*8f23e9faSHans Rosenfeld BUSYWAIT_MS(3000); 212682527734SSukumar Swaminathan i += 3; 2127291a2b48SSukumar Swaminathan 212882527734SSukumar Swaminathan /* Wait for reset completion */ 212982527734SSukumar Swaminathan while (i < 30) { 213082527734SSukumar Swaminathan /* Check status register to see what current state is */ 213182527734SSukumar Swaminathan status = READ_CSR_REG(hba, FC_HS_REG(hba)); 2132291a2b48SSukumar Swaminathan 213382527734SSukumar Swaminathan /* Check to see if any errors occurred during init */ 213482527734SSukumar Swaminathan if (status & HS_FFERM) { 213582527734SSukumar Swaminathan status1 = READ_SLIM_ADDR(hba, ((volatile uint8_t *) 213682527734SSukumar Swaminathan hba->sli.sli3.slim_addr + 0xa8)); 213782527734SSukumar Swaminathan status2 = READ_SLIM_ADDR(hba, ((volatile uint8_t *) 213882527734SSukumar Swaminathan hba->sli.sli3.slim_addr + 0xac)); 2139291a2b48SSukumar Swaminathan 214082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 214182527734SSukumar Swaminathan "HS_FFERM: status=0x%x status1=0x%x status2=0x%x", 214282527734SSukumar Swaminathan status, status1, status2); 2143291a2b48SSukumar Swaminathan 214482527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 214582527734SSukumar Swaminathan return (1); 2146291a2b48SSukumar Swaminathan } 2147291a2b48SSukumar Swaminathan 214882527734SSukumar Swaminathan if ((status & ready) == ready) { 214982527734SSukumar Swaminathan /* Reset Done !! */ 215082527734SSukumar Swaminathan goto done; 215182527734SSukumar Swaminathan } 2152291a2b48SSukumar Swaminathan 215382527734SSukumar Swaminathan /* 215482527734SSukumar Swaminathan * Check every 1 second for 15 seconds, then reset board 215582527734SSukumar Swaminathan * again (w/post), then check every 1 second for 15 * seconds. 215682527734SSukumar Swaminathan */ 2157*8f23e9faSHans Rosenfeld BUSYWAIT_MS(1000); 215882527734SSukumar Swaminathan i++; 2159291a2b48SSukumar Swaminathan 216082527734SSukumar Swaminathan /* Reset again (w/post) at 15 seconds */ 216182527734SSukumar Swaminathan if (i == 15) { 216282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 216382527734SSukumar Swaminathan "Reset failed. Retrying..."); 2164291a2b48SSukumar Swaminathan 216582527734SSukumar Swaminathan goto reset; 2166291a2b48SSukumar Swaminathan } 2167291a2b48SSukumar Swaminathan } 2168291a2b48SSukumar Swaminathan 216982527734SSukumar Swaminathan #ifdef FMA_SUPPORT 217082527734SSukumar Swaminathan reset_fail: 217182527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2172291a2b48SSukumar Swaminathan 217382527734SSukumar Swaminathan /* Timeout occurred */ 217482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 217582527734SSukumar Swaminathan "Timeout: status=0x%x", status); 217682527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 2177291a2b48SSukumar Swaminathan 217882527734SSukumar Swaminathan /* Log a dump event */ 217982527734SSukumar Swaminathan emlxs_log_dump_event(port, NULL, 0); 2180291a2b48SSukumar Swaminathan 218182527734SSukumar Swaminathan return (1); 2182291a2b48SSukumar Swaminathan 218382527734SSukumar Swaminathan done: 2184291a2b48SSukumar Swaminathan 218582527734SSukumar Swaminathan /* Initialize hc_copy */ 218682527734SSukumar Swaminathan hba->sli.sli3.hc_copy = READ_CSR_REG(hba, FC_HC_REG(hba)); 2187291a2b48SSukumar Swaminathan 21884baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 21894baa2c25SSukumar Swaminathan /* Access handle validation */ 219082527734SSukumar Swaminathan if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 21914baa2c25SSukumar Swaminathan != DDI_FM_OK) || 219282527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 219382527734SSukumar Swaminathan != DDI_FM_OK) || 219482527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 21954baa2c25SSukumar Swaminathan != DDI_FM_OK)) { 21964baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 21974baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 219882527734SSukumar Swaminathan goto reset_fail; 21994baa2c25SSukumar Swaminathan } 22004baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 22014baa2c25SSukumar Swaminathan 220282527734SSukumar Swaminathan /* Reset the hba structure */ 220382527734SSukumar Swaminathan hba->flag &= FC_RESET_MASK; 220482527734SSukumar Swaminathan hba->channel_tx_count = 0; 220582527734SSukumar Swaminathan hba->io_count = 0; 220682527734SSukumar Swaminathan hba->iodone_count = 0; 220782527734SSukumar Swaminathan hba->topology = 0; 220882527734SSukumar Swaminathan hba->linkspeed = 0; 220982527734SSukumar Swaminathan hba->heartbeat_active = 0; 221082527734SSukumar Swaminathan hba->discovery_timer = 0; 221182527734SSukumar Swaminathan hba->linkup_timer = 0; 221282527734SSukumar Swaminathan hba->loopback_tics = 0; 2213291a2b48SSukumar Swaminathan 221482527734SSukumar Swaminathan /* Reset the ring objects */ 221582527734SSukumar Swaminathan for (i = 0; i < MAX_RINGS; i++) { 221682527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[i]; 221782527734SSukumar Swaminathan rp->fc_mpon = 0; 221882527734SSukumar Swaminathan rp->fc_mpoff = 0; 221982527734SSukumar Swaminathan } 2220291a2b48SSukumar Swaminathan 222182527734SSukumar Swaminathan /* Reset the port objects */ 222282527734SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 222382527734SSukumar Swaminathan vport = &VPORT(i); 2224291a2b48SSukumar Swaminathan 222582527734SSukumar Swaminathan vport->flag &= EMLXS_PORT_RESET_MASK; 222682527734SSukumar Swaminathan vport->did = 0; 222782527734SSukumar Swaminathan vport->prev_did = 0; 222882527734SSukumar Swaminathan vport->lip_type = 0; 222982527734SSukumar Swaminathan bzero(&vport->fabric_sparam, sizeof (SERV_PARM)); 2230a9800bebSGarrett D'Amore bzero(&vport->prev_fabric_sparam, sizeof (SERV_PARM)); 223182527734SSukumar Swaminathan 223282527734SSukumar Swaminathan bzero((caddr_t)&vport->node_base, sizeof (NODELIST)); 223382527734SSukumar Swaminathan vport->node_base.nlp_Rpi = 0; 223482527734SSukumar Swaminathan vport->node_base.nlp_DID = 0xffffff; 223582527734SSukumar Swaminathan vport->node_base.nlp_list_next = NULL; 223682527734SSukumar Swaminathan vport->node_base.nlp_list_prev = NULL; 223782527734SSukumar Swaminathan vport->node_base.nlp_active = 1; 223882527734SSukumar Swaminathan vport->node_count = 0; 223982527734SSukumar Swaminathan 224082527734SSukumar Swaminathan if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) { 224182527734SSukumar Swaminathan vport->ub_count = EMLXS_UB_TOKEN_OFFSET; 2242291a2b48SSukumar Swaminathan } 224382527734SSukumar Swaminathan } 2244291a2b48SSukumar Swaminathan 224582527734SSukumar Swaminathan return (0); 2246291a2b48SSukumar Swaminathan 224782527734SSukumar Swaminathan } /* emlxs_sli3_hba_reset */ 2248291a2b48SSukumar Swaminathan 2249291a2b48SSukumar Swaminathan 225082527734SSukumar Swaminathan #define BPL_CMD 0 225182527734SSukumar Swaminathan #define BPL_RESP 1 225282527734SSukumar Swaminathan #define BPL_DATA 2 2253291a2b48SSukumar Swaminathan 225482527734SSukumar Swaminathan static ULP_BDE64 * 2255*8f23e9faSHans Rosenfeld emlxs_pkt_to_bpl(fc_packet_t *pkt, ULP_BDE64 *bpl, uint32_t bpl_type) 225682527734SSukumar Swaminathan { 225782527734SSukumar Swaminathan ddi_dma_cookie_t *cp; 225882527734SSukumar Swaminathan uint_t i; 225982527734SSukumar Swaminathan int32_t size; 226082527734SSukumar Swaminathan uint_t cookie_cnt; 2261*8f23e9faSHans Rosenfeld uint8_t bdeFlags; 2262291a2b48SSukumar Swaminathan 226382527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3) 226482527734SSukumar Swaminathan switch (bpl_type) { 226582527734SSukumar Swaminathan case BPL_CMD: 226682527734SSukumar Swaminathan cp = pkt->pkt_cmd_cookie; 226782527734SSukumar Swaminathan cookie_cnt = pkt->pkt_cmd_cookie_cnt; 226882527734SSukumar Swaminathan size = (int32_t)pkt->pkt_cmdlen; 2269*8f23e9faSHans Rosenfeld bdeFlags = 0; 227082527734SSukumar Swaminathan break; 2271291a2b48SSukumar Swaminathan 227282527734SSukumar Swaminathan case BPL_RESP: 227382527734SSukumar Swaminathan cp = pkt->pkt_resp_cookie; 227482527734SSukumar Swaminathan cookie_cnt = pkt->pkt_resp_cookie_cnt; 227582527734SSukumar Swaminathan size = (int32_t)pkt->pkt_rsplen; 2276*8f23e9faSHans Rosenfeld bdeFlags = BUFF_USE_RCV; 227782527734SSukumar Swaminathan break; 2278291a2b48SSukumar Swaminathan 2279291a2b48SSukumar Swaminathan 228082527734SSukumar Swaminathan case BPL_DATA: 228182527734SSukumar Swaminathan cp = pkt->pkt_data_cookie; 228282527734SSukumar Swaminathan cookie_cnt = pkt->pkt_data_cookie_cnt; 228382527734SSukumar Swaminathan size = (int32_t)pkt->pkt_datalen; 2284*8f23e9faSHans Rosenfeld bdeFlags = (pkt->pkt_tran_type == FC_PKT_FCP_READ) ? 2285*8f23e9faSHans Rosenfeld BUFF_USE_RCV : 0; 228682527734SSukumar Swaminathan break; 2287*8f23e9faSHans Rosenfeld 2288*8f23e9faSHans Rosenfeld default: 2289*8f23e9faSHans Rosenfeld return (NULL); 229082527734SSukumar Swaminathan } 2291291a2b48SSukumar Swaminathan 229282527734SSukumar Swaminathan #else 229382527734SSukumar Swaminathan switch (bpl_type) { 229482527734SSukumar Swaminathan case BPL_CMD: 229582527734SSukumar Swaminathan cp = &pkt->pkt_cmd_cookie; 229682527734SSukumar Swaminathan cookie_cnt = 1; 229782527734SSukumar Swaminathan size = (int32_t)pkt->pkt_cmdlen; 2298*8f23e9faSHans Rosenfeld bdeFlags = 0; 229982527734SSukumar Swaminathan break; 2300291a2b48SSukumar Swaminathan 230182527734SSukumar Swaminathan case BPL_RESP: 230282527734SSukumar Swaminathan cp = &pkt->pkt_resp_cookie; 230382527734SSukumar Swaminathan cookie_cnt = 1; 230482527734SSukumar Swaminathan size = (int32_t)pkt->pkt_rsplen; 2305*8f23e9faSHans Rosenfeld bdeFlags = BUFF_USE_RCV; 230682527734SSukumar Swaminathan break; 2307291a2b48SSukumar Swaminathan 2308291a2b48SSukumar Swaminathan 230982527734SSukumar Swaminathan case BPL_DATA: 231082527734SSukumar Swaminathan cp = &pkt->pkt_data_cookie; 231182527734SSukumar Swaminathan cookie_cnt = 1; 231282527734SSukumar Swaminathan size = (int32_t)pkt->pkt_datalen; 2313*8f23e9faSHans Rosenfeld bdeFlags = (pkt->pkt_tran_type == FC_PKT_FCP_READ) ? 2314*8f23e9faSHans Rosenfeld BUFF_USE_RCV : 0; 231582527734SSukumar Swaminathan break; 2316*8f23e9faSHans Rosenfeld 2317*8f23e9faSHans Rosenfeld default: 2318*8f23e9faSHans Rosenfeld return (NULL); 231982527734SSukumar Swaminathan } 232082527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */ 2321291a2b48SSukumar Swaminathan 232282527734SSukumar Swaminathan for (i = 0; i < cookie_cnt && size > 0; i++, cp++) { 232382527734SSukumar Swaminathan bpl->addrHigh = 232482527734SSukumar Swaminathan BE_SWAP32(PADDR_HI(cp->dmac_laddress)); 232582527734SSukumar Swaminathan bpl->addrLow = 232682527734SSukumar Swaminathan BE_SWAP32(PADDR_LO(cp->dmac_laddress)); 232782527734SSukumar Swaminathan bpl->tus.f.bdeSize = MIN(size, cp->dmac_size); 232882527734SSukumar Swaminathan bpl->tus.f.bdeFlags = bdeFlags; 232982527734SSukumar Swaminathan bpl->tus.w = BE_SWAP32(bpl->tus.w); 2330291a2b48SSukumar Swaminathan 233182527734SSukumar Swaminathan bpl++; 233282527734SSukumar Swaminathan size -= cp->dmac_size; 233382527734SSukumar Swaminathan } 2334291a2b48SSukumar Swaminathan 233582527734SSukumar Swaminathan return (bpl); 2336291a2b48SSukumar Swaminathan 233782527734SSukumar Swaminathan } /* emlxs_pkt_to_bpl */ 2338291a2b48SSukumar Swaminathan 2339291a2b48SSukumar Swaminathan 234082527734SSukumar Swaminathan static uint32_t 234182527734SSukumar Swaminathan emlxs_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 234282527734SSukumar Swaminathan { 234382527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 234482527734SSukumar Swaminathan fc_packet_t *pkt; 234582527734SSukumar Swaminathan MATCHMAP *bmp; 234682527734SSukumar Swaminathan ULP_BDE64 *bpl; 234782527734SSukumar Swaminathan uint64_t bp; 234882527734SSukumar Swaminathan IOCB *iocb; 234982527734SSukumar Swaminathan IOCBQ *iocbq; 235082527734SSukumar Swaminathan CHANNEL *cp; 235182527734SSukumar Swaminathan uint32_t data_cookie_cnt; 2352*8f23e9faSHans Rosenfeld uint32_t channelno; 2353291a2b48SSukumar Swaminathan 235482527734SSukumar Swaminathan cp = sbp->channel; 235582527734SSukumar Swaminathan iocb = (IOCB *) & sbp->iocbq; 235682527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 2357291a2b48SSukumar Swaminathan 2358*8f23e9faSHans Rosenfeld if (hba->sli.sli3.bpl_table) { 2359*8f23e9faSHans Rosenfeld bmp = hba->sli.sli3.bpl_table[sbp->iotag]; 2360*8f23e9faSHans Rosenfeld } else { 2361*8f23e9faSHans Rosenfeld bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL); 2362*8f23e9faSHans Rosenfeld } 2363291a2b48SSukumar Swaminathan 236482527734SSukumar Swaminathan if (!bmp) { 236582527734SSukumar Swaminathan return (1); 236682527734SSukumar Swaminathan } 2367291a2b48SSukumar Swaminathan 236882527734SSukumar Swaminathan sbp->bmp = bmp; 236982527734SSukumar Swaminathan bpl = (ULP_BDE64 *)bmp->virt; 237082527734SSukumar Swaminathan bp = bmp->phys; 2371291a2b48SSukumar Swaminathan 237282527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3) 237382527734SSukumar Swaminathan data_cookie_cnt = pkt->pkt_data_cookie_cnt; 237482527734SSukumar Swaminathan #else 237582527734SSukumar Swaminathan data_cookie_cnt = 1; 237682527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */ 2377291a2b48SSukumar Swaminathan 237882527734SSukumar Swaminathan iocbq = &sbp->iocbq; 237982527734SSukumar Swaminathan 2380*8f23e9faSHans Rosenfeld channelno = (iocbq->flag & IOCB_FCP_CMD)? FC_FCP_RING:cp->channelno; 2381*8f23e9faSHans Rosenfeld switch (channelno) { 2382*8f23e9faSHans Rosenfeld case FC_FCP_RING: 2383*8f23e9faSHans Rosenfeld 238482527734SSukumar Swaminathan /* CMD payload */ 2385*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD); 2386*8f23e9faSHans Rosenfeld if (! bpl) { 2387*8f23e9faSHans Rosenfeld return (1); 2388*8f23e9faSHans Rosenfeld } 2389*8f23e9faSHans Rosenfeld 2390*8f23e9faSHans Rosenfeld /* Check if response & data payloads are needed */ 2391*8f23e9faSHans Rosenfeld if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 2392*8f23e9faSHans Rosenfeld break; 2393*8f23e9faSHans Rosenfeld } 2394*8f23e9faSHans Rosenfeld 2395*8f23e9faSHans Rosenfeld /* RSP payload */ 2396*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP); 2397*8f23e9faSHans Rosenfeld if (! bpl) { 2398*8f23e9faSHans Rosenfeld return (1); 2399*8f23e9faSHans Rosenfeld } 2400*8f23e9faSHans Rosenfeld 2401*8f23e9faSHans Rosenfeld /* Check if data payload is needed */ 2402*8f23e9faSHans Rosenfeld if ((pkt->pkt_datalen == 0) || 2403*8f23e9faSHans Rosenfeld (data_cookie_cnt == 0)) { 2404*8f23e9faSHans Rosenfeld break; 2405291a2b48SSukumar Swaminathan } 2406291a2b48SSukumar Swaminathan 2407*8f23e9faSHans Rosenfeld /* DATA payload */ 2408*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_DATA); 2409*8f23e9faSHans Rosenfeld if (! bpl) { 2410*8f23e9faSHans Rosenfeld return (1); 2411*8f23e9faSHans Rosenfeld } 241282527734SSukumar Swaminathan break; 2413291a2b48SSukumar Swaminathan 241482527734SSukumar Swaminathan case FC_IP_RING: 241582527734SSukumar Swaminathan 241682527734SSukumar Swaminathan /* CMD payload */ 2417*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD); 2418*8f23e9faSHans Rosenfeld if (! bpl) { 2419*8f23e9faSHans Rosenfeld return (1); 2420*8f23e9faSHans Rosenfeld } 2421291a2b48SSukumar Swaminathan break; 2422291a2b48SSukumar Swaminathan 242382527734SSukumar Swaminathan case FC_ELS_RING: 2424291a2b48SSukumar Swaminathan 242582527734SSukumar Swaminathan /* CMD payload */ 2426*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD); 2427*8f23e9faSHans Rosenfeld if (! bpl) { 2428*8f23e9faSHans Rosenfeld return (1); 2429*8f23e9faSHans Rosenfeld } 2430291a2b48SSukumar Swaminathan 2431*8f23e9faSHans Rosenfeld /* Check if response payload is needed */ 2432*8f23e9faSHans Rosenfeld if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 2433*8f23e9faSHans Rosenfeld break; 243482527734SSukumar Swaminathan } 2435291a2b48SSukumar Swaminathan 2436*8f23e9faSHans Rosenfeld /* RSP payload */ 2437*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP); 2438*8f23e9faSHans Rosenfeld if (! bpl) { 2439*8f23e9faSHans Rosenfeld return (1); 2440*8f23e9faSHans Rosenfeld } 244182527734SSukumar Swaminathan break; 2442291a2b48SSukumar Swaminathan 244382527734SSukumar Swaminathan case FC_CT_RING: 2444291a2b48SSukumar Swaminathan 244582527734SSukumar Swaminathan /* CMD payload */ 2446*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_CMD); 2447*8f23e9faSHans Rosenfeld if (! bpl) { 2448*8f23e9faSHans Rosenfeld return (1); 2449*8f23e9faSHans Rosenfeld } 2450291a2b48SSukumar Swaminathan 2451*8f23e9faSHans Rosenfeld /* Check if response payload is needed */ 2452*8f23e9faSHans Rosenfeld if ((pkt->pkt_tran_type == FC_PKT_OUTBOUND) && 2453*8f23e9faSHans Rosenfeld (pkt->pkt_cmd_fhdr.type != EMLXS_MENLO_TYPE)) { 2454*8f23e9faSHans Rosenfeld break; 245582527734SSukumar Swaminathan } 2456291a2b48SSukumar Swaminathan 2457*8f23e9faSHans Rosenfeld /* RSP payload */ 2458*8f23e9faSHans Rosenfeld bpl = emlxs_pkt_to_bpl(pkt, bpl, BPL_RESP); 2459*8f23e9faSHans Rosenfeld if (! bpl) { 2460*8f23e9faSHans Rosenfeld return (1); 2461*8f23e9faSHans Rosenfeld } 246282527734SSukumar Swaminathan break; 2463291a2b48SSukumar Swaminathan 2464291a2b48SSukumar Swaminathan } 2465291a2b48SSukumar Swaminathan 246682527734SSukumar Swaminathan iocb->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL; 246782527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrHigh = PADDR_HI(bp); 246882527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrLow = PADDR_LO(bp); 2469*8f23e9faSHans Rosenfeld iocb->un.genreq64.bdl.bdeSize = 2470*8f23e9faSHans Rosenfeld (uint32_t)(((uintptr_t)bpl - (uintptr_t)bmp->virt) & 0xFFFFFFFF); 247182527734SSukumar Swaminathan iocb->ULPBDECOUNT = 1; 247282527734SSukumar Swaminathan iocb->ULPLE = 1; 2473291a2b48SSukumar Swaminathan 247482527734SSukumar Swaminathan return (0); 2475291a2b48SSukumar Swaminathan 247682527734SSukumar Swaminathan } /* emlxs_sli2_bde_setup */ 2477291a2b48SSukumar Swaminathan 2478291a2b48SSukumar Swaminathan 247982527734SSukumar Swaminathan static uint32_t 248082527734SSukumar Swaminathan emlxs_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 248182527734SSukumar Swaminathan { 248282527734SSukumar Swaminathan ddi_dma_cookie_t *cp_cmd; 248382527734SSukumar Swaminathan ddi_dma_cookie_t *cp_resp; 248482527734SSukumar Swaminathan ddi_dma_cookie_t *cp_data; 248582527734SSukumar Swaminathan fc_packet_t *pkt; 248682527734SSukumar Swaminathan ULP_BDE64 *bde; 248782527734SSukumar Swaminathan int data_cookie_cnt; 248882527734SSukumar Swaminathan uint32_t i; 2489*8f23e9faSHans Rosenfeld uint32_t channelno; 249082527734SSukumar Swaminathan IOCB *iocb; 249182527734SSukumar Swaminathan IOCBQ *iocbq; 249282527734SSukumar Swaminathan CHANNEL *cp; 2493291a2b48SSukumar Swaminathan 249482527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 249582527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3) 249682527734SSukumar Swaminathan if ((pkt->pkt_cmd_cookie_cnt > 1) || 249782527734SSukumar Swaminathan (pkt->pkt_resp_cookie_cnt > 1) || 249882527734SSukumar Swaminathan ((pkt->pkt_cmd_cookie_cnt + pkt->pkt_resp_cookie_cnt + 249982527734SSukumar Swaminathan pkt->pkt_data_cookie_cnt) > SLI3_MAX_BDE)) { 250082527734SSukumar Swaminathan i = emlxs_sli2_bde_setup(port, sbp); 250182527734SSukumar Swaminathan return (i); 250282527734SSukumar Swaminathan } 2503291a2b48SSukumar Swaminathan 250482527734SSukumar Swaminathan cp_cmd = pkt->pkt_cmd_cookie; 250582527734SSukumar Swaminathan cp_resp = pkt->pkt_resp_cookie; 250682527734SSukumar Swaminathan cp_data = pkt->pkt_data_cookie; 250782527734SSukumar Swaminathan data_cookie_cnt = pkt->pkt_data_cookie_cnt; 250882527734SSukumar Swaminathan #else 250982527734SSukumar Swaminathan cp_cmd = &pkt->pkt_cmd_cookie; 251082527734SSukumar Swaminathan cp_resp = &pkt->pkt_resp_cookie; 251182527734SSukumar Swaminathan cp_data = &pkt->pkt_data_cookie; 251282527734SSukumar Swaminathan data_cookie_cnt = 1; 251382527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */ 2514291a2b48SSukumar Swaminathan 2515*8f23e9faSHans Rosenfeld cp = sbp->channel; 251682527734SSukumar Swaminathan iocbq = &sbp->iocbq; 2517*8f23e9faSHans Rosenfeld iocb = (IOCB *)iocbq; 2518*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde_count = 0; 2519291a2b48SSukumar Swaminathan 2520*8f23e9faSHans Rosenfeld channelno = (iocbq->flag & IOCB_FCP_CMD)? FC_FCP_RING:cp->channelno; 2521*8f23e9faSHans Rosenfeld switch (channelno) { 252282527734SSukumar Swaminathan case FC_FCP_RING: 252382527734SSukumar Swaminathan /* CMD payload */ 252482527734SSukumar Swaminathan iocb->un.fcpi64.bdl.addrHigh = 252582527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 252682527734SSukumar Swaminathan iocb->un.fcpi64.bdl.addrLow = 252782527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 252882527734SSukumar Swaminathan iocb->un.fcpi64.bdl.bdeSize = pkt->pkt_cmdlen; 252982527734SSukumar Swaminathan iocb->un.fcpi64.bdl.bdeFlags = 0; 2530291a2b48SSukumar Swaminathan 2531*8f23e9faSHans Rosenfeld /* Check if a response & data payload are needed */ 2532*8f23e9faSHans Rosenfeld if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 2533*8f23e9faSHans Rosenfeld break; 253482527734SSukumar Swaminathan } 2535*8f23e9faSHans Rosenfeld 2536*8f23e9faSHans Rosenfeld /* RSP payload */ 2537*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.addrHigh = 2538*8f23e9faSHans Rosenfeld PADDR_HI(cp_resp->dmac_laddress); 2539*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.addrLow = 2540*8f23e9faSHans Rosenfeld PADDR_LO(cp_resp->dmac_laddress); 2541*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen; 2542*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 0; 2543*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde_count = 1; 2544*8f23e9faSHans Rosenfeld 2545*8f23e9faSHans Rosenfeld /* Check if a data payload is needed */ 2546*8f23e9faSHans Rosenfeld if ((pkt->pkt_datalen == 0) || 2547*8f23e9faSHans Rosenfeld (data_cookie_cnt == 0)) { 2548*8f23e9faSHans Rosenfeld break; 2549*8f23e9faSHans Rosenfeld } 2550*8f23e9faSHans Rosenfeld 2551*8f23e9faSHans Rosenfeld /* DATA payload */ 2552*8f23e9faSHans Rosenfeld bde = (ULP_BDE64 *)&iocb->unsli3.ext_iocb.ebde2; 2553*8f23e9faSHans Rosenfeld for (i = 0; i < data_cookie_cnt; i++) { 2554*8f23e9faSHans Rosenfeld bde->addrHigh = PADDR_HI(cp_data->dmac_laddress); 2555*8f23e9faSHans Rosenfeld bde->addrLow = PADDR_LO(cp_data->dmac_laddress); 2556*8f23e9faSHans Rosenfeld bde->tus.f.bdeSize = cp_data->dmac_size; 2557*8f23e9faSHans Rosenfeld bde->tus.f.bdeFlags = 0; 2558*8f23e9faSHans Rosenfeld cp_data++; 2559*8f23e9faSHans Rosenfeld bde++; 2560*8f23e9faSHans Rosenfeld } 2561*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde_count += data_cookie_cnt; 2562291a2b48SSukumar Swaminathan 256382527734SSukumar Swaminathan break; 2564291a2b48SSukumar Swaminathan 256582527734SSukumar Swaminathan case FC_IP_RING: 256682527734SSukumar Swaminathan /* CMD payload */ 256782527734SSukumar Swaminathan iocb->un.xseq64.bdl.addrHigh = 256882527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 256982527734SSukumar Swaminathan iocb->un.xseq64.bdl.addrLow = 257082527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 257182527734SSukumar Swaminathan iocb->un.xseq64.bdl.bdeSize = pkt->pkt_cmdlen; 257282527734SSukumar Swaminathan iocb->un.xseq64.bdl.bdeFlags = 0; 2573291a2b48SSukumar Swaminathan 257482527734SSukumar Swaminathan break; 2575291a2b48SSukumar Swaminathan 257682527734SSukumar Swaminathan case FC_ELS_RING: 2577291a2b48SSukumar Swaminathan 257882527734SSukumar Swaminathan /* CMD payload */ 257982527734SSukumar Swaminathan iocb->un.elsreq64.bdl.addrHigh = 258082527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 258182527734SSukumar Swaminathan iocb->un.elsreq64.bdl.addrLow = 258282527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 258382527734SSukumar Swaminathan iocb->un.elsreq64.bdl.bdeSize = pkt->pkt_cmdlen; 258482527734SSukumar Swaminathan iocb->un.elsreq64.bdl.bdeFlags = 0; 2585291a2b48SSukumar Swaminathan 2586*8f23e9faSHans Rosenfeld /* Check if a response payload is needed */ 2587*8f23e9faSHans Rosenfeld if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 2588*8f23e9faSHans Rosenfeld break; 258982527734SSukumar Swaminathan } 2590291a2b48SSukumar Swaminathan 2591*8f23e9faSHans Rosenfeld /* RSP payload */ 2592*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.addrHigh = 2593*8f23e9faSHans Rosenfeld PADDR_HI(cp_resp->dmac_laddress); 2594*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.addrLow = 2595*8f23e9faSHans Rosenfeld PADDR_LO(cp_resp->dmac_laddress); 2596*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen; 2597*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = BUFF_USE_RCV; 2598*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde_count = 1; 259982527734SSukumar Swaminathan break; 2600291a2b48SSukumar Swaminathan 260182527734SSukumar Swaminathan case FC_CT_RING: 2602291a2b48SSukumar Swaminathan 260382527734SSukumar Swaminathan /* CMD payload */ 260482527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrHigh = 260582527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 260682527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrLow = 260782527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 260882527734SSukumar Swaminathan iocb->un.genreq64.bdl.bdeSize = pkt->pkt_cmdlen; 260982527734SSukumar Swaminathan iocb->un.genreq64.bdl.bdeFlags = 0; 2610291a2b48SSukumar Swaminathan 2611*8f23e9faSHans Rosenfeld /* Check if a response payload is needed */ 2612*8f23e9faSHans Rosenfeld if ((pkt->pkt_tran_type == FC_PKT_OUTBOUND) && 2613*8f23e9faSHans Rosenfeld (pkt->pkt_cmd_fhdr.type != EMLXS_MENLO_TYPE)) { 2614*8f23e9faSHans Rosenfeld break; 261582527734SSukumar Swaminathan } 2616291a2b48SSukumar Swaminathan 2617*8f23e9faSHans Rosenfeld /* RSP payload */ 2618*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.addrHigh = 2619*8f23e9faSHans Rosenfeld PADDR_HI(cp_resp->dmac_laddress); 2620*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.addrLow = 2621*8f23e9faSHans Rosenfeld PADDR_LO(cp_resp->dmac_laddress); 2622*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = pkt->pkt_rsplen; 2623*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = BUFF_USE_RCV; 2624*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde_count = 1; 262582527734SSukumar Swaminathan break; 2626291a2b48SSukumar Swaminathan } 2627291a2b48SSukumar Swaminathan 262882527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 262982527734SSukumar Swaminathan iocb->ULPLE = 0; 2630291a2b48SSukumar Swaminathan 263182527734SSukumar Swaminathan return (0); 2632291a2b48SSukumar Swaminathan 263382527734SSukumar Swaminathan } /* emlxs_sli3_bde_setup */ 2634291a2b48SSukumar Swaminathan 2635291a2b48SSukumar Swaminathan 263682527734SSukumar Swaminathan /* Only used for FCP Data xfers */ 263782527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 263882527734SSukumar Swaminathan /*ARGSUSED*/ 263982527734SSukumar Swaminathan static uint32_t 264082527734SSukumar Swaminathan emlxs_sli2_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 264182527734SSukumar Swaminathan { 264282527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 264382527734SSukumar Swaminathan scsi_task_t *fct_task; 264482527734SSukumar Swaminathan MATCHMAP *bmp; 264582527734SSukumar Swaminathan ULP_BDE64 *bpl; 264682527734SSukumar Swaminathan uint64_t bp; 264782527734SSukumar Swaminathan uint8_t bdeFlags; 264882527734SSukumar Swaminathan IOCB *iocb; 264982527734SSukumar Swaminathan uint32_t size; 2650*8f23e9faSHans Rosenfeld MATCHMAP *mp; 2651291a2b48SSukumar Swaminathan 2652*8f23e9faSHans Rosenfeld iocb = (IOCB *)&sbp->iocbq.iocb; 265382527734SSukumar Swaminathan sbp->bmp = NULL; 2654291a2b48SSukumar Swaminathan 265582527734SSukumar Swaminathan if (!sbp->fct_buf) { 265682527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = 0; 265782527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = 0; 265882527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = 0; 265982527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = 0; 266082527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 266182527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 0; 266282527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 266382527734SSukumar Swaminathan iocb->ULPLE = 1; 266482527734SSukumar Swaminathan return (0); 2665291a2b48SSukumar Swaminathan } 2666*8f23e9faSHans Rosenfeld 2667*8f23e9faSHans Rosenfeld if (hba->sli.sli3.bpl_table) { 2668*8f23e9faSHans Rosenfeld bmp = hba->sli.sli3.bpl_table[sbp->iotag]; 2669*8f23e9faSHans Rosenfeld } else { 2670*8f23e9faSHans Rosenfeld bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL); 2671*8f23e9faSHans Rosenfeld } 2672291a2b48SSukumar Swaminathan 267382527734SSukumar Swaminathan if (!bmp) { 267482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2675*8f23e9faSHans Rosenfeld "fct_sli2_bde_setup: Unable to BPL buffer. iotag=%d", 267682527734SSukumar Swaminathan sbp->iotag); 2677291a2b48SSukumar Swaminathan 267882527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = 0; 267982527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = 0; 268082527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = 0; 268182527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = 0; 268282527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 268382527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 0; 268482527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 268582527734SSukumar Swaminathan iocb->ULPLE = 1; 268682527734SSukumar Swaminathan return (1); 268782527734SSukumar Swaminathan } 2688291a2b48SSukumar Swaminathan 268982527734SSukumar Swaminathan bpl = (ULP_BDE64 *)bmp->virt; 269082527734SSukumar Swaminathan bp = bmp->phys; 2691291a2b48SSukumar Swaminathan 269282527734SSukumar Swaminathan fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific; 2693291a2b48SSukumar Swaminathan 269482527734SSukumar Swaminathan size = sbp->fct_buf->db_data_size; 2695*8f23e9faSHans Rosenfeld mp = (MATCHMAP *)sbp->fct_buf->db_port_private; 2696291a2b48SSukumar Swaminathan 269782527734SSukumar Swaminathan bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0; 2698291a2b48SSukumar Swaminathan 269982527734SSukumar Swaminathan /* Init the buffer list */ 2700*8f23e9faSHans Rosenfeld bpl->addrHigh = BE_SWAP32(PADDR_HI(mp->phys)); 2701*8f23e9faSHans Rosenfeld bpl->addrLow = BE_SWAP32(PADDR_LO(mp->phys)); 2702*8f23e9faSHans Rosenfeld bpl->tus.f.bdeSize = size; 2703*8f23e9faSHans Rosenfeld bpl->tus.f.bdeFlags = bdeFlags; 2704*8f23e9faSHans Rosenfeld bpl->tus.w = BE_SWAP32(bpl->tus.w); 2705291a2b48SSukumar Swaminathan 270682527734SSukumar Swaminathan /* Init the IOCB */ 270782527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bp); 270882527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bp); 2709*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.bdeSize = sizeof (ULP_BDE64); 271082527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = BUFF_TYPE_BDL; 2711291a2b48SSukumar Swaminathan 271282527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 271382527734SSukumar Swaminathan (fct_task->task_flags & TF_WRITE_DATA) ? size : 0; 271482527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 2715291a2b48SSukumar Swaminathan 271682527734SSukumar Swaminathan iocb->ULPBDECOUNT = 1; 271782527734SSukumar Swaminathan iocb->ULPLE = 1; 271882527734SSukumar Swaminathan sbp->bmp = bmp; 2719291a2b48SSukumar Swaminathan 272082527734SSukumar Swaminathan return (0); 2721291a2b48SSukumar Swaminathan 272282527734SSukumar Swaminathan } /* emlxs_sli2_fct_bde_setup */ 272382527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2724291a2b48SSukumar Swaminathan 2725291a2b48SSukumar Swaminathan 272682527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 272782527734SSukumar Swaminathan /*ARGSUSED*/ 272882527734SSukumar Swaminathan static uint32_t 272982527734SSukumar Swaminathan emlxs_sli3_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 273082527734SSukumar Swaminathan { 273182527734SSukumar Swaminathan scsi_task_t *fct_task; 273282527734SSukumar Swaminathan IOCB *iocb; 2733*8f23e9faSHans Rosenfeld MATCHMAP *mp; 273482527734SSukumar Swaminathan uint32_t bdeFlags; 2735*8f23e9faSHans Rosenfeld uint32_t size; 2736291a2b48SSukumar Swaminathan 273782527734SSukumar Swaminathan iocb = (IOCB *)&sbp->iocbq; 2738291a2b48SSukumar Swaminathan 273982527734SSukumar Swaminathan if (!sbp->fct_buf) { 274082527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = 0; 274182527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = 0; 274282527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = 0; 274382527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = 0; 274482527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 274582527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 0; 274682527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 274782527734SSukumar Swaminathan iocb->ULPLE = 0; 274882527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count = 0; 274982527734SSukumar Swaminathan return (0); 2750291a2b48SSukumar Swaminathan } 2751291a2b48SSukumar Swaminathan 275282527734SSukumar Swaminathan fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific; 2753291a2b48SSukumar Swaminathan 275482527734SSukumar Swaminathan size = sbp->fct_buf->db_data_size; 2755*8f23e9faSHans Rosenfeld mp = (MATCHMAP *)sbp->fct_buf->db_port_private; 2756291a2b48SSukumar Swaminathan 275782527734SSukumar Swaminathan bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0; 2758291a2b48SSukumar Swaminathan 275982527734SSukumar Swaminathan /* Init first BDE */ 2760*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(mp->phys); 2761*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.addrLow = PADDR_LO(mp->phys); 2762*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.bdeSize = size; 276382527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = bdeFlags; 2764291a2b48SSukumar Swaminathan 2765*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde_count = 0; 276682527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 276782527734SSukumar Swaminathan (fct_task->task_flags & TF_WRITE_DATA) ? size : 0; 276882527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 2769291a2b48SSukumar Swaminathan 277082527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 277182527734SSukumar Swaminathan iocb->ULPLE = 0; 2772291a2b48SSukumar Swaminathan 277382527734SSukumar Swaminathan return (0); 2774291a2b48SSukumar Swaminathan 277582527734SSukumar Swaminathan } /* emlxs_sli3_fct_bde_setup */ 277682527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2777291a2b48SSukumar Swaminathan 2778291a2b48SSukumar Swaminathan 277982527734SSukumar Swaminathan static void 278082527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2781291a2b48SSukumar Swaminathan { 278282527734SSukumar Swaminathan #ifdef FMA_SUPPORT 278382527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 278482527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 278582527734SSukumar Swaminathan PGP *pgp; 278682527734SSukumar Swaminathan emlxs_buf_t *sbp; 278782527734SSukumar Swaminathan SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 2788291a2b48SSukumar Swaminathan RING *rp; 278982527734SSukumar Swaminathan uint32_t nextIdx; 279082527734SSukumar Swaminathan uint32_t status; 279182527734SSukumar Swaminathan void *ioa2; 279282527734SSukumar Swaminathan off_t offset; 279382527734SSukumar Swaminathan uint32_t count = 0; 279482527734SSukumar Swaminathan uint32_t flag; 279582527734SSukumar Swaminathan uint32_t channelno; 279682527734SSukumar Swaminathan int32_t throttle; 2797*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT 2798*8f23e9faSHans Rosenfeld int32_t node_throttle; 2799*8f23e9faSHans Rosenfeld NODELIST *marked_node = NULL; 2800*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */ 2801291a2b48SSukumar Swaminathan 280282527734SSukumar Swaminathan channelno = cp->channelno; 280382527734SSukumar Swaminathan rp = (RING *)cp->iopath; 2804291a2b48SSukumar Swaminathan 280582527734SSukumar Swaminathan throttle = 0; 2806291a2b48SSukumar Swaminathan 280782527734SSukumar Swaminathan /* Check if FCP ring and adapter is not ready */ 280882527734SSukumar Swaminathan /* We may use any ring for FCP_CMD */ 280982527734SSukumar Swaminathan if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) { 281082527734SSukumar Swaminathan if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port || 2811*8f23e9faSHans Rosenfeld (((emlxs_port_t *)iocbq->port)->mode == MODE_INITIATOR)) { 281282527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 281382527734SSukumar Swaminathan return; 281482527734SSukumar Swaminathan } 2815291a2b48SSukumar Swaminathan } 2816291a2b48SSukumar Swaminathan 281782527734SSukumar Swaminathan /* Attempt to acquire CMD_RING lock */ 281882527734SSukumar Swaminathan if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) { 281982527734SSukumar Swaminathan /* Queue it for later */ 282082527734SSukumar Swaminathan if (iocbq) { 282182527734SSukumar Swaminathan if ((hba->io_count - 282282527734SSukumar Swaminathan hba->channel_tx_count) > 10) { 282382527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 282482527734SSukumar Swaminathan return; 282582527734SSukumar Swaminathan } else { 2826291a2b48SSukumar Swaminathan 282782527734SSukumar Swaminathan /* 282882527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, 282982527734SSukumar Swaminathan * &emlxs_ring_watchdog_msg, 283082527734SSukumar Swaminathan * "%s host=%d port=%d cnt=%d,%d RACE 283182527734SSukumar Swaminathan * CONDITION3 DETECTED.", 283282527734SSukumar Swaminathan * emlxs_ring_xlate(channelno), 283382527734SSukumar Swaminathan * rp->fc_cmdidx, rp->fc_port_cmdidx, 283482527734SSukumar Swaminathan * hba->channel_tx_count, 283582527734SSukumar Swaminathan * hba->io_count); 283682527734SSukumar Swaminathan */ 283782527734SSukumar Swaminathan mutex_enter(&EMLXS_CMD_RING_LOCK(channelno)); 283882527734SSukumar Swaminathan } 283982527734SSukumar Swaminathan } else { 284082527734SSukumar Swaminathan return; 284182527734SSukumar Swaminathan } 2842291a2b48SSukumar Swaminathan } 284382527734SSukumar Swaminathan /* CMD_RING_LOCK acquired */ 2844291a2b48SSukumar Swaminathan 284582527734SSukumar Swaminathan /* Throttle check only applies to non special iocb */ 284682527734SSukumar Swaminathan if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) { 284782527734SSukumar Swaminathan /* Check if HBA is full */ 284882527734SSukumar Swaminathan throttle = hba->io_throttle - hba->io_active; 284982527734SSukumar Swaminathan if (throttle <= 0) { 285082527734SSukumar Swaminathan /* Hitting adapter throttle limit */ 285182527734SSukumar Swaminathan /* Queue it for later */ 285282527734SSukumar Swaminathan if (iocbq) { 285382527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2854291a2b48SSukumar Swaminathan } 285582527734SSukumar Swaminathan 285682527734SSukumar Swaminathan goto busy; 2857291a2b48SSukumar Swaminathan } 2858291a2b48SSukumar Swaminathan } 2859291a2b48SSukumar Swaminathan 286082527734SSukumar Swaminathan /* Read adapter's get index */ 286182527734SSukumar Swaminathan pgp = (PGP *) 286282527734SSukumar Swaminathan &((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[channelno]; 286382527734SSukumar Swaminathan offset = 286482527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) - 286582527734SSukumar Swaminathan (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 286682527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 286782527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 286882527734SSukumar Swaminathan rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2869291a2b48SSukumar Swaminathan 287082527734SSukumar Swaminathan /* Calculate the next put index */ 287182527734SSukumar Swaminathan nextIdx = 287282527734SSukumar Swaminathan (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 2873291a2b48SSukumar Swaminathan 287482527734SSukumar Swaminathan /* Check if ring is full */ 287582527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 287682527734SSukumar Swaminathan /* Try one more time */ 287782527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 287882527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 287982527734SSukumar Swaminathan rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2880291a2b48SSukumar Swaminathan 288182527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 288282527734SSukumar Swaminathan /* Queue it for later */ 288382527734SSukumar Swaminathan if (iocbq) { 288482527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 288582527734SSukumar Swaminathan } 2886291a2b48SSukumar Swaminathan 288782527734SSukumar Swaminathan goto busy; 288882527734SSukumar Swaminathan } 2889291a2b48SSukumar Swaminathan } 2890291a2b48SSukumar Swaminathan 289182527734SSukumar Swaminathan /* 289282527734SSukumar Swaminathan * We have a command ring slot available 289382527734SSukumar Swaminathan * Make sure we have an iocb to send 289482527734SSukumar Swaminathan */ 289582527734SSukumar Swaminathan if (iocbq) { 289682527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2897291a2b48SSukumar Swaminathan 289882527734SSukumar Swaminathan /* Check if the ring already has iocb's waiting */ 289982527734SSukumar Swaminathan if (cp->nodeq.q_first != NULL) { 290082527734SSukumar Swaminathan /* Put the current iocbq on the tx queue */ 290182527734SSukumar Swaminathan emlxs_tx_put(iocbq, 0); 2902291a2b48SSukumar Swaminathan 290382527734SSukumar Swaminathan /* 290482527734SSukumar Swaminathan * Attempt to replace it with the next iocbq 290582527734SSukumar Swaminathan * in the tx queue 290682527734SSukumar Swaminathan */ 290782527734SSukumar Swaminathan iocbq = emlxs_tx_get(cp, 0); 290882527734SSukumar Swaminathan } 2909291a2b48SSukumar Swaminathan 291082527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2911291a2b48SSukumar Swaminathan } else { 291282527734SSukumar Swaminathan /* Try to get the next iocb on the tx queue */ 291382527734SSukumar Swaminathan iocbq = emlxs_tx_get(cp, 1); 2914291a2b48SSukumar Swaminathan } 2915291a2b48SSukumar Swaminathan 291682527734SSukumar Swaminathan sendit: 291782527734SSukumar Swaminathan count = 0; 2918291a2b48SSukumar Swaminathan 291982527734SSukumar Swaminathan /* Process each iocbq */ 292082527734SSukumar Swaminathan while (iocbq) { 292182527734SSukumar Swaminathan sbp = iocbq->sbp; 2922*8f23e9faSHans Rosenfeld 2923*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT 2924*8f23e9faSHans Rosenfeld if (sbp && sbp->node && sbp->node->io_throttle) { 2925*8f23e9faSHans Rosenfeld node_throttle = sbp->node->io_throttle - 2926*8f23e9faSHans Rosenfeld sbp->node->io_active; 2927*8f23e9faSHans Rosenfeld if (node_throttle <= 0) { 2928*8f23e9faSHans Rosenfeld /* Node is busy */ 2929*8f23e9faSHans Rosenfeld /* Queue this iocb and get next iocb from */ 2930*8f23e9faSHans Rosenfeld /* channel */ 2931*8f23e9faSHans Rosenfeld 2932*8f23e9faSHans Rosenfeld if (!marked_node) { 2933*8f23e9faSHans Rosenfeld marked_node = sbp->node; 2934*8f23e9faSHans Rosenfeld } 2935*8f23e9faSHans Rosenfeld 2936*8f23e9faSHans Rosenfeld mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2937*8f23e9faSHans Rosenfeld emlxs_tx_put(iocbq, 0); 2938*8f23e9faSHans Rosenfeld 2939*8f23e9faSHans Rosenfeld if (cp->nodeq.q_first == marked_node) { 2940*8f23e9faSHans Rosenfeld mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2941*8f23e9faSHans Rosenfeld goto busy; 2942*8f23e9faSHans Rosenfeld } 2943*8f23e9faSHans Rosenfeld 2944*8f23e9faSHans Rosenfeld iocbq = emlxs_tx_get(cp, 0); 2945*8f23e9faSHans Rosenfeld mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2946*8f23e9faSHans Rosenfeld continue; 2947*8f23e9faSHans Rosenfeld } 2948*8f23e9faSHans Rosenfeld } 2949*8f23e9faSHans Rosenfeld marked_node = 0; 2950*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */ 2951*8f23e9faSHans Rosenfeld 295282527734SSukumar Swaminathan if (sbp && (sbp->pkt_flags & PACKET_DELAY_REQUIRED)) { 295382527734SSukumar Swaminathan /* 295482527734SSukumar Swaminathan * Update adapter if needed, since we are about to 295582527734SSukumar Swaminathan * delay here 295682527734SSukumar Swaminathan */ 295782527734SSukumar Swaminathan if (count) { 295882527734SSukumar Swaminathan count = 0; 2959291a2b48SSukumar Swaminathan 296082527734SSukumar Swaminathan /* Update the adapter's cmd put index */ 296182527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 296282527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channelno]. 296382527734SSukumar Swaminathan cmdPutInx = 296482527734SSukumar Swaminathan BE_SWAP32(rp->fc_cmdidx); 2965291a2b48SSukumar Swaminathan 296682527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 296782527734SSukumar Swaminathan offset = (off_t) 296882527734SSukumar Swaminathan ((uint64_t) 296982527734SSukumar Swaminathan ((unsigned long)&(slim2p->mbx.us. 297082527734SSukumar Swaminathan s2.host[channelno].cmdPutInx)) - 297182527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 297282527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2. 297382527734SSukumar Swaminathan dma_handle, offset, 4, 297482527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 297582527734SSukumar Swaminathan } else { 297682527734SSukumar Swaminathan ioa2 = (void *) 297782527734SSukumar Swaminathan ((char *)hba->sli.sli3.slim_addr + 297882527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + 297982527734SSukumar Swaminathan ((channelno * 2) * 298082527734SSukumar Swaminathan sizeof (uint32_t))); 298182527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, 298282527734SSukumar Swaminathan (volatile uint32_t *)ioa2, 298382527734SSukumar Swaminathan rp->fc_cmdidx); 298482527734SSukumar Swaminathan } 2985291a2b48SSukumar Swaminathan 298682527734SSukumar Swaminathan status = (CA_R0ATT << (channelno * 4)); 298782527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), 298882527734SSukumar Swaminathan (volatile uint32_t)status); 2989291a2b48SSukumar Swaminathan 299082527734SSukumar Swaminathan } 299182527734SSukumar Swaminathan /* Perform delay */ 299282527734SSukumar Swaminathan if ((channelno == FC_ELS_RING) && 299382527734SSukumar Swaminathan !(iocbq->flag & IOCB_FCP_CMD)) { 299482527734SSukumar Swaminathan drv_usecwait(100000); 299582527734SSukumar Swaminathan } else { 299682527734SSukumar Swaminathan drv_usecwait(20000); 299782527734SSukumar Swaminathan } 299882527734SSukumar Swaminathan } 299982527734SSukumar Swaminathan 300082527734SSukumar Swaminathan /* 300182527734SSukumar Swaminathan * At this point, we have a command ring slot available 300282527734SSukumar Swaminathan * and an iocb to send 300382527734SSukumar Swaminathan */ 300482527734SSukumar Swaminathan flag = iocbq->flag; 3005291a2b48SSukumar Swaminathan 300682527734SSukumar Swaminathan /* Send the iocb */ 300782527734SSukumar Swaminathan emlxs_sli3_issue_iocb(hba, rp, iocbq); 300882527734SSukumar Swaminathan /* 300982527734SSukumar Swaminathan * After this, the sbp / iocb should not be 301082527734SSukumar Swaminathan * accessed in the xmit path. 301182527734SSukumar Swaminathan */ 3012291a2b48SSukumar Swaminathan 301382527734SSukumar Swaminathan count++; 301482527734SSukumar Swaminathan if (iocbq && (!(flag & IOCB_SPECIAL))) { 301582527734SSukumar Swaminathan /* Check if HBA is full */ 301682527734SSukumar Swaminathan throttle = hba->io_throttle - hba->io_active; 301782527734SSukumar Swaminathan if (throttle <= 0) { 301882527734SSukumar Swaminathan goto busy; 301982527734SSukumar Swaminathan } 302082527734SSukumar Swaminathan } 3021291a2b48SSukumar Swaminathan 302282527734SSukumar Swaminathan /* Calculate the next put index */ 302382527734SSukumar Swaminathan nextIdx = 302482527734SSukumar Swaminathan (rp->fc_cmdidx + 1 >= 302582527734SSukumar Swaminathan rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 3026291a2b48SSukumar Swaminathan 302782527734SSukumar Swaminathan /* Check if ring is full */ 302882527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 302982527734SSukumar Swaminathan /* Try one more time */ 303082527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 303182527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORKERNEL); 303282527734SSukumar Swaminathan rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 3033291a2b48SSukumar Swaminathan 303482527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 303582527734SSukumar Swaminathan goto busy; 303682527734SSukumar Swaminathan } 303782527734SSukumar Swaminathan } 3038291a2b48SSukumar Swaminathan 303982527734SSukumar Swaminathan /* Get the next iocb from the tx queue if there is one */ 304082527734SSukumar Swaminathan iocbq = emlxs_tx_get(cp, 1); 3041291a2b48SSukumar Swaminathan } 3042291a2b48SSukumar Swaminathan 304382527734SSukumar Swaminathan if (count) { 304482527734SSukumar Swaminathan /* Update the adapter's cmd put index */ 304582527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 304682527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channelno]. 304782527734SSukumar Swaminathan cmdPutInx = BE_SWAP32(rp->fc_cmdidx); 3048291a2b48SSukumar Swaminathan 304982527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 305082527734SSukumar Swaminathan offset = (off_t) 305182527734SSukumar Swaminathan ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 305282527734SSukumar Swaminathan host[channelno].cmdPutInx)) - 305382527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 305482527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 305582527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORDEV); 305682527734SSukumar Swaminathan } else { 305782527734SSukumar Swaminathan ioa2 = 305882527734SSukumar Swaminathan (void *)((char *)hba->sli.sli3.slim_addr + 305982527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + 306082527734SSukumar Swaminathan ((channelno * 2) * sizeof (uint32_t))); 306182527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 306282527734SSukumar Swaminathan rp->fc_cmdidx); 306382527734SSukumar Swaminathan } 3064291a2b48SSukumar Swaminathan 306582527734SSukumar Swaminathan status = (CA_R0ATT << (channelno * 4)); 306682527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), 306782527734SSukumar Swaminathan (volatile uint32_t)status); 3068291a2b48SSukumar Swaminathan 306982527734SSukumar Swaminathan /* Check tx queue one more time before releasing */ 307082527734SSukumar Swaminathan if ((iocbq = emlxs_tx_get(cp, 1))) { 307182527734SSukumar Swaminathan /* 307282527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_watchdog_msg, 307382527734SSukumar Swaminathan * "%s host=%d port=%d RACE CONDITION1 307482527734SSukumar Swaminathan * DETECTED.", emlxs_ring_xlate(channelno), 307582527734SSukumar Swaminathan * rp->fc_cmdidx, rp->fc_port_cmdidx); 307682527734SSukumar Swaminathan */ 307782527734SSukumar Swaminathan goto sendit; 307882527734SSukumar Swaminathan } 3079291a2b48SSukumar Swaminathan } 3080291a2b48SSukumar Swaminathan 308182527734SSukumar Swaminathan #ifdef FMA_SUPPORT 308282527734SSukumar Swaminathan /* Access handle validation */ 308382527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 308482527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 308582527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 3086291a2b48SSukumar Swaminathan 308782527734SSukumar Swaminathan mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); 3088291a2b48SSukumar Swaminathan 308982527734SSukumar Swaminathan return; 3090291a2b48SSukumar Swaminathan 309182527734SSukumar Swaminathan busy: 3092291a2b48SSukumar Swaminathan 3093291a2b48SSukumar Swaminathan /* 309482527734SSukumar Swaminathan * Set ring to SET R0CE_REQ in Chip Att register. 309582527734SSukumar Swaminathan * Chip will tell us when an entry is freed. 3096291a2b48SSukumar Swaminathan */ 309782527734SSukumar Swaminathan if (count) { 309882527734SSukumar Swaminathan /* Update the adapter's cmd put index */ 309982527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 310082527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channelno].cmdPutInx = 310182527734SSukumar Swaminathan BE_SWAP32(rp->fc_cmdidx); 3102291a2b48SSukumar Swaminathan 310382527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 310482527734SSukumar Swaminathan offset = (off_t) 310582527734SSukumar Swaminathan ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 310682527734SSukumar Swaminathan host[channelno].cmdPutInx)) - 310782527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 310882527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 310982527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORDEV); 311082527734SSukumar Swaminathan } else { 311182527734SSukumar Swaminathan ioa2 = 311282527734SSukumar Swaminathan (void *)((char *)hba->sli.sli3.slim_addr + 311382527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + 311482527734SSukumar Swaminathan ((channelno * 2) * sizeof (uint32_t))); 311582527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 311682527734SSukumar Swaminathan rp->fc_cmdidx); 3117291a2b48SSukumar Swaminathan } 311882527734SSukumar Swaminathan } 3119291a2b48SSukumar Swaminathan 312082527734SSukumar Swaminathan status = ((CA_R0ATT | CA_R0CE_REQ) << (channelno * 4)); 312182527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), (volatile uint32_t)status); 312282527734SSukumar Swaminathan 312382527734SSukumar Swaminathan if (throttle <= 0) { 312482527734SSukumar Swaminathan HBASTATS.IocbThrottled++; 312582527734SSukumar Swaminathan } else { 312682527734SSukumar Swaminathan HBASTATS.IocbRingFull[channelno]++; 3127291a2b48SSukumar Swaminathan } 3128291a2b48SSukumar Swaminathan 312982527734SSukumar Swaminathan #ifdef FMA_SUPPORT 313082527734SSukumar Swaminathan /* Access handle validation */ 313182527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 313282527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 313382527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 3134291a2b48SSukumar Swaminathan 313582527734SSukumar Swaminathan mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); 3136291a2b48SSukumar Swaminathan 3137291a2b48SSukumar Swaminathan return; 3138291a2b48SSukumar Swaminathan 313982527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb_cmd() */ 3140291a2b48SSukumar Swaminathan 3141291a2b48SSukumar Swaminathan 314282527734SSukumar Swaminathan /* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */ 314382527734SSukumar Swaminathan /* MBX_WAIT - returns MBX_TIMEOUT or mailbox_status */ 314482527734SSukumar Swaminathan /* MBX_SLEEP - returns MBX_TIMEOUT or mailbox_status */ 314582527734SSukumar Swaminathan /* MBX_POLL - returns MBX_TIMEOUT or mailbox_status */ 3146291a2b48SSukumar Swaminathan 314782527734SSukumar Swaminathan static uint32_t 314882527734SSukumar Swaminathan emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, 314982527734SSukumar Swaminathan uint32_t tmo) 3150291a2b48SSukumar Swaminathan { 3151a9800bebSGarrett D'Amore emlxs_port_t *port; 315282527734SSukumar Swaminathan SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 315382527734SSukumar Swaminathan MAILBOX *mbox; 315482527734SSukumar Swaminathan MAILBOX *mb; 315582527734SSukumar Swaminathan volatile uint32_t word0; 315682527734SSukumar Swaminathan volatile uint32_t ldata; 315782527734SSukumar Swaminathan off_t offset; 315882527734SSukumar Swaminathan MATCHMAP *mbox_bp; 315982527734SSukumar Swaminathan uint32_t tmo_local; 316082527734SSukumar Swaminathan MAILBOX *swpmb; 3161291a2b48SSukumar Swaminathan 3162a9800bebSGarrett D'Amore if (!mbq->port) { 3163a9800bebSGarrett D'Amore mbq->port = &PPORT; 3164a9800bebSGarrett D'Amore } 3165a9800bebSGarrett D'Amore 3166a9800bebSGarrett D'Amore port = (emlxs_port_t *)mbq->port; 3167a9800bebSGarrett D'Amore 316882527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 316982527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 3170291a2b48SSukumar Swaminathan 317182527734SSukumar Swaminathan mb->mbxStatus = MBX_SUCCESS; 3172291a2b48SSukumar Swaminathan 317382527734SSukumar Swaminathan /* Check for minimum timeouts */ 317482527734SSukumar Swaminathan switch (mb->mbxCommand) { 317582527734SSukumar Swaminathan /* Mailbox commands that erase/write flash */ 317682527734SSukumar Swaminathan case MBX_DOWN_LOAD: 317782527734SSukumar Swaminathan case MBX_UPDATE_CFG: 317882527734SSukumar Swaminathan case MBX_LOAD_AREA: 317982527734SSukumar Swaminathan case MBX_LOAD_EXP_ROM: 318082527734SSukumar Swaminathan case MBX_WRITE_NV: 318182527734SSukumar Swaminathan case MBX_FLASH_WR_ULA: 318282527734SSukumar Swaminathan case MBX_DEL_LD_ENTRY: 318382527734SSukumar Swaminathan case MBX_LOAD_SM: 318482527734SSukumar Swaminathan if (tmo < 300) { 318582527734SSukumar Swaminathan tmo = 300; 3186291a2b48SSukumar Swaminathan } 318782527734SSukumar Swaminathan break; 3188291a2b48SSukumar Swaminathan 318982527734SSukumar Swaminathan default: 319082527734SSukumar Swaminathan if (tmo < 30) { 319182527734SSukumar Swaminathan tmo = 30; 319282527734SSukumar Swaminathan } 319382527734SSukumar Swaminathan break; 319482527734SSukumar Swaminathan } 3195291a2b48SSukumar Swaminathan 319682527734SSukumar Swaminathan /* Convert tmo seconds to 10 millisecond tics */ 319782527734SSukumar Swaminathan tmo_local = tmo * 100; 3198291a2b48SSukumar Swaminathan 319982527734SSukumar Swaminathan /* Adjust wait flag */ 320082527734SSukumar Swaminathan if (flag != MBX_NOWAIT) { 320182527734SSukumar Swaminathan /* If interrupt is enabled, use sleep, otherwise poll */ 320282527734SSukumar Swaminathan if (hba->sli.sli3.hc_copy & HC_MBINT_ENA) { 320382527734SSukumar Swaminathan flag = MBX_SLEEP; 3204291a2b48SSukumar Swaminathan } else { 320582527734SSukumar Swaminathan flag = MBX_POLL; 3206291a2b48SSukumar Swaminathan } 320782527734SSukumar Swaminathan } 3208291a2b48SSukumar Swaminathan 320982527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 3210291a2b48SSukumar Swaminathan 321182527734SSukumar Swaminathan /* Check for hardware error */ 321282527734SSukumar Swaminathan if (hba->flag & FC_HARDWARE_ERROR) { 321382527734SSukumar Swaminathan mb->mbxStatus = (hba->flag & FC_OVERTEMP_EVENT) ? 321482527734SSukumar Swaminathan MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR; 3215291a2b48SSukumar Swaminathan 321682527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3217291a2b48SSukumar Swaminathan 321882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 321982527734SSukumar Swaminathan "Hardware error reported. %s failed. status=%x mb=%p", 3220*8f23e9faSHans Rosenfeld emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb); 3221291a2b48SSukumar Swaminathan 322282527734SSukumar Swaminathan return (MBX_HARDWARE_ERROR); 3223291a2b48SSukumar Swaminathan } 3224291a2b48SSukumar Swaminathan 322582527734SSukumar Swaminathan if (hba->mbox_queue_flag) { 322682527734SSukumar Swaminathan /* If we are not polling, then queue it for later */ 322782527734SSukumar Swaminathan if (flag == MBX_NOWAIT) { 322882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 322982527734SSukumar Swaminathan "Busy. %s: mb=%p NoWait.", 323082527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3231291a2b48SSukumar Swaminathan 323282527734SSukumar Swaminathan emlxs_mb_put(hba, mbq); 3233291a2b48SSukumar Swaminathan 323482527734SSukumar Swaminathan HBASTATS.MboxBusy++; 3235291a2b48SSukumar Swaminathan 323682527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3237291a2b48SSukumar Swaminathan 323882527734SSukumar Swaminathan return (MBX_BUSY); 323982527734SSukumar Swaminathan } 3240291a2b48SSukumar Swaminathan 324182527734SSukumar Swaminathan while (hba->mbox_queue_flag) { 324282527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3243291a2b48SSukumar Swaminathan 324482527734SSukumar Swaminathan if (tmo_local-- == 0) { 324582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 324682527734SSukumar Swaminathan &emlxs_mbox_event_msg, 324782527734SSukumar Swaminathan "Timeout. %s: mb=%p tmo=%d Waiting.", 324882527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 324982527734SSukumar Swaminathan tmo); 3250291a2b48SSukumar Swaminathan 325182527734SSukumar Swaminathan /* Non-lethalStatus mailbox timeout */ 325282527734SSukumar Swaminathan /* Does not indicate a hardware error */ 325382527734SSukumar Swaminathan mb->mbxStatus = MBX_TIMEOUT; 325482527734SSukumar Swaminathan return (MBX_TIMEOUT); 325582527734SSukumar Swaminathan } 3256291a2b48SSukumar Swaminathan 3257*8f23e9faSHans Rosenfeld BUSYWAIT_MS(10); 325882527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 3259*8f23e9faSHans Rosenfeld 3260*8f23e9faSHans Rosenfeld /* Check for hardware error */ 3261*8f23e9faSHans Rosenfeld if (hba->flag & FC_HARDWARE_ERROR) { 3262*8f23e9faSHans Rosenfeld mb->mbxStatus = 3263*8f23e9faSHans Rosenfeld (hba->flag & FC_OVERTEMP_EVENT) ? 3264*8f23e9faSHans Rosenfeld MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR; 3265*8f23e9faSHans Rosenfeld 3266*8f23e9faSHans Rosenfeld mutex_exit(&EMLXS_PORT_LOCK); 3267*8f23e9faSHans Rosenfeld 3268*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 3269*8f23e9faSHans Rosenfeld &emlxs_mbox_detail_msg, 3270*8f23e9faSHans Rosenfeld "Hardware error reported. %s failed. " 3271*8f23e9faSHans Rosenfeld "status=%x mb=%p", 3272*8f23e9faSHans Rosenfeld emlxs_mb_cmd_xlate(mb->mbxCommand), 3273*8f23e9faSHans Rosenfeld mb->mbxStatus, mb); 3274*8f23e9faSHans Rosenfeld 3275*8f23e9faSHans Rosenfeld return (MBX_HARDWARE_ERROR); 3276*8f23e9faSHans Rosenfeld } 32774baa2c25SSukumar Swaminathan } 3278291a2b48SSukumar Swaminathan } 3279291a2b48SSukumar Swaminathan 328082527734SSukumar Swaminathan /* Initialize mailbox area */ 328182527734SSukumar Swaminathan emlxs_mb_init(hba, mbq, flag, tmo); 3282291a2b48SSukumar Swaminathan 328382527734SSukumar Swaminathan switch (flag) { 328482527734SSukumar Swaminathan case MBX_NOWAIT: 3285291a2b48SSukumar Swaminathan 328682527734SSukumar Swaminathan if (mb->mbxCommand != MBX_HEARTBEAT) { 328782527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 328882527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 328982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 329082527734SSukumar Swaminathan &emlxs_mbox_detail_msg, 329182527734SSukumar Swaminathan "Sending. %s: mb=%p NoWait.", 329282527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 329382527734SSukumar Swaminathan } 329482527734SSukumar Swaminathan } 3295291a2b48SSukumar Swaminathan 329682527734SSukumar Swaminathan break; 3297291a2b48SSukumar Swaminathan 329882527734SSukumar Swaminathan case MBX_SLEEP: 329982527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 330082527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 330182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 330282527734SSukumar Swaminathan "Sending. %s: mb=%p Sleep.", 330382527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 330482527734SSukumar Swaminathan } 3305291a2b48SSukumar Swaminathan 330682527734SSukumar Swaminathan break; 3307291a2b48SSukumar Swaminathan 330882527734SSukumar Swaminathan case MBX_POLL: 330982527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 331082527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 331182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 331282527734SSukumar Swaminathan "Sending. %s: mb=%p Polled.", 331382527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 331482527734SSukumar Swaminathan } 331582527734SSukumar Swaminathan break; 331682527734SSukumar Swaminathan } 3317291a2b48SSukumar Swaminathan 331882527734SSukumar Swaminathan mb->mbxOwner = OWN_CHIP; 3319291a2b48SSukumar Swaminathan 332082527734SSukumar Swaminathan /* Clear the attention bit */ 332182527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT); 3322291a2b48SSukumar Swaminathan 332382527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 332482527734SSukumar Swaminathan /* First copy command data */ 332582527734SSukumar Swaminathan mbox = FC_SLIM2_MAILBOX(hba); 332682527734SSukumar Swaminathan offset = 332782527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)mbox) 332882527734SSukumar Swaminathan - (uint64_t)((unsigned long)slim2p)); 3329291a2b48SSukumar Swaminathan 333082527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 333182527734SSukumar Swaminathan if (mbq->extbuf) { 333282527734SSukumar Swaminathan uint32_t *mbox_ext = 333382527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + 333482527734SSukumar Swaminathan MBOX_EXTENSION_OFFSET); 333582527734SSukumar Swaminathan off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 3336291a2b48SSukumar Swaminathan 333782527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbq->extbuf, 333882527734SSukumar Swaminathan (uint8_t *)mbox_ext, mbq->extsize); 3339291a2b48SSukumar Swaminathan 334082527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 334182527734SSukumar Swaminathan offset_ext, mbq->extsize, 334282527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 3343291a2b48SSukumar Swaminathan } 334482527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 3345291a2b48SSukumar Swaminathan 334682527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox, 334782527734SSukumar Swaminathan MAILBOX_CMD_BSIZE); 3348291a2b48SSukumar Swaminathan 334982527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 335082527734SSukumar Swaminathan MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV); 335182527734SSukumar Swaminathan } else { /* SLIM 1 */ 3352291a2b48SSukumar Swaminathan 335382527734SSukumar Swaminathan mbox = FC_SLIM1_MAILBOX(hba); 3354291a2b48SSukumar Swaminathan 335582527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 335682527734SSukumar Swaminathan if (mbq->extbuf) { 335782527734SSukumar Swaminathan uint32_t *mbox_ext = 335882527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + 335982527734SSukumar Swaminathan MBOX_EXTENSION_OFFSET); 336082527734SSukumar Swaminathan WRITE_SLIM_COPY(hba, (uint32_t *)mbq->extbuf, 336182527734SSukumar Swaminathan mbox_ext, (mbq->extsize / 4)); 336282527734SSukumar Swaminathan } 336382527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 3364291a2b48SSukumar Swaminathan 336582527734SSukumar Swaminathan /* First copy command data */ 336682527734SSukumar Swaminathan WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords, 336782527734SSukumar Swaminathan (MAILBOX_CMD_WSIZE - 1)); 3368291a2b48SSukumar Swaminathan 336982527734SSukumar Swaminathan /* copy over last word, with mbxOwner set */ 337082527734SSukumar Swaminathan ldata = *((volatile uint32_t *)mb); 337182527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata); 3372291a2b48SSukumar Swaminathan } 3373291a2b48SSukumar Swaminathan 337482527734SSukumar Swaminathan /* Interrupt board to do it right away */ 337582527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 3376291a2b48SSukumar Swaminathan 337782527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3378291a2b48SSukumar Swaminathan 33794baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 33804baa2c25SSukumar Swaminathan /* Access handle validation */ 338182527734SSukumar Swaminathan if ((emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 338282527734SSukumar Swaminathan != DDI_FM_OK) || 338382527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 33844baa2c25SSukumar Swaminathan != DDI_FM_OK)) { 33854baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 33864baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 338782527734SSukumar Swaminathan return (MBX_HARDWARE_ERROR); 33884baa2c25SSukumar Swaminathan } 33894baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 33904baa2c25SSukumar Swaminathan 339182527734SSukumar Swaminathan switch (flag) { 339282527734SSukumar Swaminathan case MBX_NOWAIT: 339382527734SSukumar Swaminathan return (MBX_SUCCESS); 3394291a2b48SSukumar Swaminathan 339582527734SSukumar Swaminathan case MBX_SLEEP: 33964baa2c25SSukumar Swaminathan 339782527734SSukumar Swaminathan /* Wait for completion */ 339882527734SSukumar Swaminathan /* The driver clock is timing the mailbox. */ 339982527734SSukumar Swaminathan /* emlxs_mb_fini() will be called externally. */ 3400291a2b48SSukumar Swaminathan 340182527734SSukumar Swaminathan mutex_enter(&EMLXS_MBOX_LOCK); 340282527734SSukumar Swaminathan while (!(mbq->flag & MBQ_COMPLETED)) { 340382527734SSukumar Swaminathan cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK); 340482527734SSukumar Swaminathan } 340582527734SSukumar Swaminathan mutex_exit(&EMLXS_MBOX_LOCK); 3406291a2b48SSukumar Swaminathan 340782527734SSukumar Swaminathan if (mb->mbxStatus == MBX_TIMEOUT) { 340882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg, 340982527734SSukumar Swaminathan "Timeout. %s: mb=%p tmo=%d. Sleep.", 341082527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo); 341182527734SSukumar Swaminathan } else { 341282527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 341382527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 341482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 341582527734SSukumar Swaminathan &emlxs_mbox_detail_msg, 341682527734SSukumar Swaminathan "Completed. %s: mb=%p status=%x Sleep.", 341782527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 341882527734SSukumar Swaminathan mb->mbxStatus); 341982527734SSukumar Swaminathan } 342082527734SSukumar Swaminathan } 3421291a2b48SSukumar Swaminathan 342282527734SSukumar Swaminathan break; 3423291a2b48SSukumar Swaminathan 342482527734SSukumar Swaminathan case MBX_POLL: 3425291a2b48SSukumar Swaminathan 342682527734SSukumar Swaminathan /* Convert tmo seconds to 500 usec tics */ 342782527734SSukumar Swaminathan tmo_local = tmo * 2000; 3428291a2b48SSukumar Swaminathan 342982527734SSukumar Swaminathan /* Get first word of mailbox */ 343082527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 343182527734SSukumar Swaminathan mbox = FC_SLIM2_MAILBOX(hba); 343282527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mbox) - 343382527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 3434291a2b48SSukumar Swaminathan 343582527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 343682527734SSukumar Swaminathan offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 343782527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 343882527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 343982527734SSukumar Swaminathan } else { 344082527734SSukumar Swaminathan mbox = FC_SLIM1_MAILBOX(hba); 344182527734SSukumar Swaminathan word0 = 344282527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 34434baa2c25SSukumar Swaminathan } 34444baa2c25SSukumar Swaminathan 344582527734SSukumar Swaminathan /* Wait for command to complete */ 344682527734SSukumar Swaminathan while ((swpmb->mbxOwner == OWN_CHIP) && 344782527734SSukumar Swaminathan !(mbq->flag & MBQ_COMPLETED)) { 344882527734SSukumar Swaminathan if (!hba->timer_id && (tmo_local-- == 0)) { 344982527734SSukumar Swaminathan /* self time */ 345082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 345182527734SSukumar Swaminathan &emlxs_mbox_timeout_msg, 3452*8f23e9faSHans Rosenfeld "%s: mb=%p tmo=%d Polled.", 3453*8f23e9faSHans Rosenfeld emlxs_mb_cmd_xlate(mb->mbxCommand), 3454*8f23e9faSHans Rosenfeld mb, tmo); 3455291a2b48SSukumar Swaminathan 345682527734SSukumar Swaminathan hba->flag |= FC_MBOX_TIMEOUT; 345782527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 345882527734SSukumar Swaminathan emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 3459291a2b48SSukumar Swaminathan 346082527734SSukumar Swaminathan break; 346182527734SSukumar Swaminathan } 3462291a2b48SSukumar Swaminathan 3463*8f23e9faSHans Rosenfeld BUSYWAIT_US(500); 3464291a2b48SSukumar Swaminathan 346582527734SSukumar Swaminathan /* Get first word of mailbox */ 346682527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 346782527734SSukumar Swaminathan EMLXS_MPDATA_SYNC( 346882527734SSukumar Swaminathan hba->sli.sli3.slim2.dma_handle, offset, 346982527734SSukumar Swaminathan sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 347082527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 347182527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 347282527734SSukumar Swaminathan } else { 347382527734SSukumar Swaminathan word0 = 347482527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 347582527734SSukumar Swaminathan ((volatile uint32_t *)mbox)); 347682527734SSukumar Swaminathan } 3477291a2b48SSukumar Swaminathan 347882527734SSukumar Swaminathan } /* while */ 3479291a2b48SSukumar Swaminathan 348082527734SSukumar Swaminathan if (mb->mbxStatus == MBX_TIMEOUT) { 348182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg, 348282527734SSukumar Swaminathan "Timeout. %s: mb=%p tmo=%d. Polled.", 348382527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo); 348482527734SSukumar Swaminathan 348582527734SSukumar Swaminathan break; 3486291a2b48SSukumar Swaminathan } 3487291a2b48SSukumar Swaminathan 3488*8f23e9faSHans Rosenfeld /* Check for config port command */ 3489*8f23e9faSHans Rosenfeld if ((swpmb->mbxCommand == MBX_CONFIG_PORT) && 3490*8f23e9faSHans Rosenfeld (swpmb->mbxStatus == MBX_SUCCESS)) { 3491*8f23e9faSHans Rosenfeld /* Setup host mbox for cmpl */ 3492*8f23e9faSHans Rosenfeld mbox = FC_SLIM2_MAILBOX(hba); 3493*8f23e9faSHans Rosenfeld offset = (off_t)((uint64_t)((unsigned long)mbox) 3494*8f23e9faSHans Rosenfeld - (uint64_t)((unsigned long)slim2p)); 3495*8f23e9faSHans Rosenfeld 3496*8f23e9faSHans Rosenfeld hba->flag |= FC_SLIM2_MODE; 3497*8f23e9faSHans Rosenfeld } 3498*8f23e9faSHans Rosenfeld 3499*8f23e9faSHans Rosenfeld /* copy results back to user */ 3500*8f23e9faSHans Rosenfeld if (hba->flag & FC_SLIM2_MODE) { 3501*8f23e9faSHans Rosenfeld EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 350282527734SSukumar Swaminathan offset, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); 3503291a2b48SSukumar Swaminathan 350482527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb, 350582527734SSukumar Swaminathan MAILBOX_CMD_BSIZE); 350682527734SSukumar Swaminathan } else { 350782527734SSukumar Swaminathan READ_SLIM_COPY(hba, (uint32_t *)mb, 350882527734SSukumar Swaminathan (uint32_t *)mbox, MAILBOX_CMD_WSIZE); 350982527734SSukumar Swaminathan } 3510291a2b48SSukumar Swaminathan 351182527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 351282527734SSukumar Swaminathan if (mbq->extbuf) { 351382527734SSukumar Swaminathan uint32_t *mbox_ext = 351482527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + 351582527734SSukumar Swaminathan MBOX_EXTENSION_OFFSET); 351682527734SSukumar Swaminathan off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 3517291a2b48SSukumar Swaminathan 351882527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 351982527734SSukumar Swaminathan EMLXS_MPDATA_SYNC( 352082527734SSukumar Swaminathan hba->sli.sli3.slim2.dma_handle, offset_ext, 352182527734SSukumar Swaminathan mbq->extsize, DDI_DMA_SYNC_FORKERNEL); 3522291a2b48SSukumar Swaminathan 352382527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox_ext, 352482527734SSukumar Swaminathan (uint8_t *)mbq->extbuf, mbq->extsize); 352582527734SSukumar Swaminathan } else { 352682527734SSukumar Swaminathan READ_SLIM_COPY(hba, 352782527734SSukumar Swaminathan (uint32_t *)mbq->extbuf, mbox_ext, 352882527734SSukumar Swaminathan (mbq->extsize / 4)); 352982527734SSukumar Swaminathan } 353082527734SSukumar Swaminathan } 353182527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 3532291a2b48SSukumar Swaminathan 353382527734SSukumar Swaminathan /* Sync the memory buffer */ 353482527734SSukumar Swaminathan if (mbq->bp) { 353582527734SSukumar Swaminathan mbox_bp = (MATCHMAP *)mbq->bp; 353682527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, 353782527734SSukumar Swaminathan mbox_bp->size, DDI_DMA_SYNC_FORKERNEL); 353882527734SSukumar Swaminathan } 3539291a2b48SSukumar Swaminathan 354082527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 354182527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 354282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 354382527734SSukumar Swaminathan "Completed. %s: mb=%p status=%x Polled.", 354482527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 354582527734SSukumar Swaminathan mb->mbxStatus); 354682527734SSukumar Swaminathan } 3547291a2b48SSukumar Swaminathan 354882527734SSukumar Swaminathan /* Process the result */ 354982527734SSukumar Swaminathan if (!(mbq->flag & MBQ_PASSTHRU)) { 355082527734SSukumar Swaminathan if (mbq->mbox_cmpl) { 355182527734SSukumar Swaminathan (void) (mbq->mbox_cmpl)(hba, mbq); 355282527734SSukumar Swaminathan } 355382527734SSukumar Swaminathan } 3554291a2b48SSukumar Swaminathan 355582527734SSukumar Swaminathan /* Clear the attention bit */ 355682527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT); 35574baa2c25SSukumar Swaminathan 355882527734SSukumar Swaminathan /* Clean up the mailbox area */ 355982527734SSukumar Swaminathan emlxs_mb_fini(hba, NULL, mb->mbxStatus); 3560291a2b48SSukumar Swaminathan 356182527734SSukumar Swaminathan break; 3562291a2b48SSukumar Swaminathan 356382527734SSukumar Swaminathan } /* switch (flag) */ 356482527734SSukumar Swaminathan 356582527734SSukumar Swaminathan return (mb->mbxStatus); 356682527734SSukumar Swaminathan 356782527734SSukumar Swaminathan } /* emlxs_sli3_issue_mbox_cmd() */ 356882527734SSukumar Swaminathan 356982527734SSukumar Swaminathan 357082527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 3571*8f23e9faSHans Rosenfeld /*ARGSUSED*/ 357282527734SSukumar Swaminathan static uint32_t 357382527734SSukumar Swaminathan emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, 357482527734SSukumar Swaminathan int channel) 3575291a2b48SSukumar Swaminathan { 357682527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 357782527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 357882527734SSukumar Swaminathan fct_cmd_t *fct_cmd; 357982527734SSukumar Swaminathan stmf_data_buf_t *dbuf; 358082527734SSukumar Swaminathan scsi_task_t *fct_task; 3581*8f23e9faSHans Rosenfeld fc_packet_t *pkt; 358282527734SSukumar Swaminathan uint32_t did; 358382527734SSukumar Swaminathan IOCBQ *iocbq; 358482527734SSukumar Swaminathan IOCB *iocb; 358582527734SSukumar Swaminathan uint32_t timeout; 358682527734SSukumar Swaminathan uint32_t iotag; 358782527734SSukumar Swaminathan emlxs_node_t *ndlp; 358882527734SSukumar Swaminathan CHANNEL *cp; 3589*8f23e9faSHans Rosenfeld ddi_dma_cookie_t *cp_cmd; 3590291a2b48SSukumar Swaminathan 3591*8f23e9faSHans Rosenfeld pkt = PRIV2PKT(cmd_sbp); 3592291a2b48SSukumar Swaminathan 359382527734SSukumar Swaminathan cp = (CHANNEL *)cmd_sbp->channel; 3594291a2b48SSukumar Swaminathan 359582527734SSukumar Swaminathan iocbq = &cmd_sbp->iocbq; 359682527734SSukumar Swaminathan iocb = &iocbq->iocb; 3597291a2b48SSukumar Swaminathan 3598291a2b48SSukumar Swaminathan 359982527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 360082527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, cmd_sbp); 3601291a2b48SSukumar Swaminathan 360282527734SSukumar Swaminathan if (!iotag) { 360382527734SSukumar Swaminathan /* No more command slots available, retry later */ 360482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3605*8f23e9faSHans Rosenfeld "Adapter Busy. Unable to allocate iotag. did=0x%x", 3606*8f23e9faSHans Rosenfeld cmd_sbp->did); 36074baa2c25SSukumar Swaminathan 360882527734SSukumar Swaminathan return (IOERR_NO_RESOURCES); 3609291a2b48SSukumar Swaminathan } 3610291a2b48SSukumar Swaminathan 3611291a2b48SSukumar Swaminathan 3612*8f23e9faSHans Rosenfeld /* Point of no return */ 3613*8f23e9faSHans Rosenfeld 3614*8f23e9faSHans Rosenfeld if (iocb->ULPCOMMAND == CMD_ABORT_XRI_CX) { 3615*8f23e9faSHans Rosenfeld 3616*8f23e9faSHans Rosenfeld ndlp = cmd_sbp->node; 3617*8f23e9faSHans Rosenfeld cp->ulpSendCmd++; 3618*8f23e9faSHans Rosenfeld 3619*8f23e9faSHans Rosenfeld /* Initalize iocbq */ 3620*8f23e9faSHans Rosenfeld iocbq->port = (void *)port; 3621*8f23e9faSHans Rosenfeld iocbq->node = (void *)ndlp; 3622*8f23e9faSHans Rosenfeld iocbq->channel = (void *)cp; 3623*8f23e9faSHans Rosenfeld 3624*8f23e9faSHans Rosenfeld /* 3625*8f23e9faSHans Rosenfeld * Don't give the abort priority, we want the IOCB 3626*8f23e9faSHans Rosenfeld * we are aborting to be processed first. 3627*8f23e9faSHans Rosenfeld */ 3628*8f23e9faSHans Rosenfeld iocbq->flag |= IOCB_SPECIAL; 3629*8f23e9faSHans Rosenfeld 3630*8f23e9faSHans Rosenfeld iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id; 3631*8f23e9faSHans Rosenfeld iocb->ULPIOTAG = (uint16_t)iotag; 3632*8f23e9faSHans Rosenfeld iocb->ULPLE = 1; 3633*8f23e9faSHans Rosenfeld iocb->ULPCLASS = cmd_sbp->class; 3634*8f23e9faSHans Rosenfeld iocb->ULPOWNER = OWN_CHIP; 3635291a2b48SSukumar Swaminathan 3636*8f23e9faSHans Rosenfeld if (hba->state >= FC_LINK_UP) { 3637*8f23e9faSHans Rosenfeld /* Create the abort IOCB */ 3638*8f23e9faSHans Rosenfeld iocb->un.acxri.abortType = ABORT_TYPE_ABTS; 3639*8f23e9faSHans Rosenfeld iocb->ULPCOMMAND = CMD_ABORT_XRI_CX; 3640*8f23e9faSHans Rosenfeld 3641*8f23e9faSHans Rosenfeld } else { 3642*8f23e9faSHans Rosenfeld /* Create the close IOCB */ 3643*8f23e9faSHans Rosenfeld iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX; 3644*8f23e9faSHans Rosenfeld 3645*8f23e9faSHans Rosenfeld } 3646*8f23e9faSHans Rosenfeld 3647*8f23e9faSHans Rosenfeld iocb->ULPRSVDBYTE = 3648*8f23e9faSHans Rosenfeld ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3649*8f23e9faSHans Rosenfeld /* Set the pkt timer */ 3650*8f23e9faSHans Rosenfeld cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 3651*8f23e9faSHans Rosenfeld ((pkt->pkt_timeout > 0xff) ? 0 : 10); 3652*8f23e9faSHans Rosenfeld 3653*8f23e9faSHans Rosenfeld return (IOERR_SUCCESS); 3654*8f23e9faSHans Rosenfeld 3655*8f23e9faSHans Rosenfeld } else if (iocb->ULPCOMMAND == CMD_FCP_TRSP64_CX) { 3656*8f23e9faSHans Rosenfeld 3657*8f23e9faSHans Rosenfeld ndlp = cmd_sbp->node; 3658*8f23e9faSHans Rosenfeld cp->ulpSendCmd++; 3659*8f23e9faSHans Rosenfeld 3660*8f23e9faSHans Rosenfeld /* Initalize iocbq */ 3661*8f23e9faSHans Rosenfeld iocbq->port = (void *)port; 3662*8f23e9faSHans Rosenfeld iocbq->node = (void *)ndlp; 3663*8f23e9faSHans Rosenfeld iocbq->channel = (void *)cp; 3664*8f23e9faSHans Rosenfeld 3665*8f23e9faSHans Rosenfeld #if (EMLXS_MODREV >= EMLXS_MODREV3) 3666*8f23e9faSHans Rosenfeld cp_cmd = pkt->pkt_cmd_cookie; 3667*8f23e9faSHans Rosenfeld #else 3668*8f23e9faSHans Rosenfeld cp_cmd = &pkt->pkt_cmd_cookie; 3669*8f23e9faSHans Rosenfeld #endif /* >= EMLXS_MODREV3 */ 3670*8f23e9faSHans Rosenfeld 3671*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(cp_cmd->dmac_laddress); 3672*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.addrLow = PADDR_LO(cp_cmd->dmac_laddress); 3673*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.bdeSize = pkt->pkt_cmdlen; 3674*8f23e9faSHans Rosenfeld iocb->un.fcpt64.bdl.bdeFlags = 0; 3675*8f23e9faSHans Rosenfeld 3676*8f23e9faSHans Rosenfeld if (hba->sli_mode < 3) { 3677*8f23e9faSHans Rosenfeld iocb->ULPBDECOUNT = 1; 3678*8f23e9faSHans Rosenfeld iocb->ULPLE = 1; 3679*8f23e9faSHans Rosenfeld } else { /* SLI3 */ 3680*8f23e9faSHans Rosenfeld 3681*8f23e9faSHans Rosenfeld iocb->ULPBDECOUNT = 0; 3682*8f23e9faSHans Rosenfeld iocb->ULPLE = 0; 3683*8f23e9faSHans Rosenfeld iocb->unsli3.ext_iocb.ebde_count = 0; 3684*8f23e9faSHans Rosenfeld } 3685*8f23e9faSHans Rosenfeld 3686*8f23e9faSHans Rosenfeld /* Initalize iocb */ 3687*8f23e9faSHans Rosenfeld iocb->ULPCONTEXT = (uint16_t)pkt->pkt_cmd_fhdr.rx_id; 3688*8f23e9faSHans Rosenfeld iocb->ULPIOTAG = (uint16_t)iotag; 3689*8f23e9faSHans Rosenfeld iocb->ULPRSVDBYTE = 3690*8f23e9faSHans Rosenfeld ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3691*8f23e9faSHans Rosenfeld iocb->ULPOWNER = OWN_CHIP; 3692*8f23e9faSHans Rosenfeld iocb->ULPCLASS = cmd_sbp->class; 3693*8f23e9faSHans Rosenfeld iocb->ULPCOMMAND = CMD_FCP_TRSP64_CX; 3694*8f23e9faSHans Rosenfeld 3695*8f23e9faSHans Rosenfeld /* Set the pkt timer */ 3696*8f23e9faSHans Rosenfeld cmd_sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 3697*8f23e9faSHans Rosenfeld ((pkt->pkt_timeout > 0xff) ? 0 : 10); 3698*8f23e9faSHans Rosenfeld 3699*8f23e9faSHans Rosenfeld if (pkt->pkt_cmdlen) { 3700*8f23e9faSHans Rosenfeld EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 3701*8f23e9faSHans Rosenfeld DDI_DMA_SYNC_FORDEV); 3702*8f23e9faSHans Rosenfeld } 3703*8f23e9faSHans Rosenfeld 3704*8f23e9faSHans Rosenfeld return (IOERR_SUCCESS); 3705*8f23e9faSHans Rosenfeld } 3706*8f23e9faSHans Rosenfeld 3707*8f23e9faSHans Rosenfeld dbuf = cmd_sbp->fct_buf; 3708*8f23e9faSHans Rosenfeld fct_cmd = cmd_sbp->fct_cmd; 3709*8f23e9faSHans Rosenfeld fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 3710*8f23e9faSHans Rosenfeld ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private; 3711*8f23e9faSHans Rosenfeld did = fct_cmd->cmd_rportid; 3712291a2b48SSukumar Swaminathan 371382527734SSukumar Swaminathan iocbq->channel = (void *)cmd_sbp->channel; 3714291a2b48SSukumar Swaminathan 371582527734SSukumar Swaminathan if (emlxs_fct_bde_setup(port, cmd_sbp)) { 371682527734SSukumar Swaminathan /* Unregister the packet */ 371782527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cmd_sbp->channel, iotag, 0); 3718291a2b48SSukumar Swaminathan 371982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 372082527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 3721291a2b48SSukumar Swaminathan 372282527734SSukumar Swaminathan return (IOERR_INTERNAL_ERROR); 372382527734SSukumar Swaminathan } 3724*8f23e9faSHans Rosenfeld 3725*8f23e9faSHans Rosenfeld if (cfg[CFG_TIMEOUT_ENABLE].current) { 3726*8f23e9faSHans Rosenfeld timeout = 3727*8f23e9faSHans Rosenfeld ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov); 3728*8f23e9faSHans Rosenfeld } else { 3729*8f23e9faSHans Rosenfeld timeout = 0x80000000; 3730*8f23e9faSHans Rosenfeld } 3731*8f23e9faSHans Rosenfeld 3732*8f23e9faSHans Rosenfeld cmd_sbp->ticks = 3733*8f23e9faSHans Rosenfeld hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10); 3734*8f23e9faSHans Rosenfeld 3735*8f23e9faSHans Rosenfeld /* Initalize iocbq */ 3736*8f23e9faSHans Rosenfeld iocbq->port = (void *)port; 3737*8f23e9faSHans Rosenfeld iocbq->node = (void *)ndlp; 3738291a2b48SSukumar Swaminathan 373982527734SSukumar Swaminathan /* Initalize iocb */ 374082527734SSukumar Swaminathan iocb->ULPCONTEXT = (uint16_t)fct_cmd->cmd_rxid; 3741a9800bebSGarrett D'Amore iocb->ULPIOTAG = (uint16_t)iotag; 374282527734SSukumar Swaminathan iocb->ULPRSVDBYTE = ((timeout > 0xff) ? 0 : timeout); 374382527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 374482527734SSukumar Swaminathan iocb->ULPCLASS = cmd_sbp->class; 3745291a2b48SSukumar Swaminathan 374682527734SSukumar Swaminathan iocb->ULPPU = 1; /* Wd4 is relative offset */ 374782527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = dbuf->db_relative_offset; 3748291a2b48SSukumar Swaminathan 374982527734SSukumar Swaminathan if (fct_task->task_flags & TF_WRITE_DATA) { 375082527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX; 375182527734SSukumar Swaminathan } else { /* TF_READ_DATA */ 3752291a2b48SSukumar Swaminathan 375382527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX; 3754291a2b48SSukumar Swaminathan 37556a573d82SSukumar Swaminathan if ((hba->sli_mode == EMLXS_HBA_SLI3_MODE) && 3756*8f23e9faSHans Rosenfeld (dbuf->db_data_size >= 3757a9800bebSGarrett D'Amore fct_task->task_expected_xfer_length)) { 375882527734SSukumar Swaminathan iocb->ULPCT = 0x1; 375982527734SSukumar Swaminathan /* enable auto-rsp AP feature */ 3760a9800bebSGarrett D'Amore } 376182527734SSukumar Swaminathan } 3762291a2b48SSukumar Swaminathan 376382527734SSukumar Swaminathan return (IOERR_SUCCESS); 3764291a2b48SSukumar Swaminathan 376582527734SSukumar Swaminathan } /* emlxs_sli3_prep_fct_iocb() */ 3766291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3767291a2b48SSukumar Swaminathan 376882527734SSukumar Swaminathan /* ARGSUSED */ 376982527734SSukumar Swaminathan static uint32_t 377082527734SSukumar Swaminathan emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) 377182527734SSukumar Swaminathan { 377282527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 377382527734SSukumar Swaminathan fc_packet_t *pkt; 377482527734SSukumar Swaminathan CHANNEL *cp; 377582527734SSukumar Swaminathan IOCBQ *iocbq; 377682527734SSukumar Swaminathan IOCB *iocb; 377782527734SSukumar Swaminathan NODELIST *ndlp; 377882527734SSukumar Swaminathan uint16_t iotag; 377982527734SSukumar Swaminathan uint32_t did; 378082527734SSukumar Swaminathan 378182527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 378282527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 378382527734SSukumar Swaminathan cp = &hba->chan[FC_FCP_RING]; 378482527734SSukumar Swaminathan 378582527734SSukumar Swaminathan iocbq = &sbp->iocbq; 378682527734SSukumar Swaminathan iocb = &iocbq->iocb; 378782527734SSukumar Swaminathan 378882527734SSukumar Swaminathan /* Find target node object */ 378982527734SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 379082527734SSukumar Swaminathan 379182527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 379282527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 379382527734SSukumar Swaminathan 379482527734SSukumar Swaminathan if (!iotag) { 379582527734SSukumar Swaminathan /* 379682527734SSukumar Swaminathan * No more command slots available, retry later 379782527734SSukumar Swaminathan */ 379882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 379982527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag: did=0x%x", did); 380082527734SSukumar Swaminathan 380182527734SSukumar Swaminathan return (FC_TRAN_BUSY); 380282527734SSukumar Swaminathan } 380382527734SSukumar Swaminathan 380482527734SSukumar Swaminathan /* Initalize iocbq */ 380582527734SSukumar Swaminathan iocbq->port = (void *) port; 380682527734SSukumar Swaminathan iocbq->channel = (void *) cp; 380782527734SSukumar Swaminathan 380882527734SSukumar Swaminathan /* Indicate this is a FCP cmd */ 380982527734SSukumar Swaminathan iocbq->flag |= IOCB_FCP_CMD; 381082527734SSukumar Swaminathan 381182527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 381282527734SSukumar Swaminathan /* Unregister the packet */ 381382527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 381482527734SSukumar Swaminathan 381582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 381682527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 381782527734SSukumar Swaminathan 381882527734SSukumar Swaminathan return (FC_TRAN_BUSY); 381982527734SSukumar Swaminathan } 382082527734SSukumar Swaminathan /* Point of no return */ 382182527734SSukumar Swaminathan 382282527734SSukumar Swaminathan /* Initalize iocb */ 382382527734SSukumar Swaminathan iocb->ULPCONTEXT = ndlp->nlp_Rpi; 382482527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 382582527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 382682527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 382782527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 382882527734SSukumar Swaminathan 382982527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 383082527734SSukumar Swaminathan case FC_TRAN_CLASS1: 383182527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 383282527734SSukumar Swaminathan break; 383382527734SSukumar Swaminathan case FC_TRAN_CLASS2: 383482527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 383582527734SSukumar Swaminathan /* iocb->ULPCLASS = CLASS3; */ 383682527734SSukumar Swaminathan break; 383782527734SSukumar Swaminathan case FC_TRAN_CLASS3: 383882527734SSukumar Swaminathan default: 383982527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 384082527734SSukumar Swaminathan break; 384182527734SSukumar Swaminathan } 384282527734SSukumar Swaminathan 384382527734SSukumar Swaminathan /* if device is FCP-2 device, set the following bit */ 384482527734SSukumar Swaminathan /* that says to run the FC-TAPE protocol. */ 384582527734SSukumar Swaminathan if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { 384682527734SSukumar Swaminathan iocb->ULPFCP2RCVY = 1; 384782527734SSukumar Swaminathan } 384882527734SSukumar Swaminathan 384982527734SSukumar Swaminathan if (pkt->pkt_datalen == 0) { 385082527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR; 385182527734SSukumar Swaminathan } else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) { 385282527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR; 3853*8f23e9faSHans Rosenfeld iocb->ULPPU = PARM_XFER_CHECK; 385482527734SSukumar Swaminathan iocb->un.fcpi64.fcpi_parm = pkt->pkt_datalen; 385582527734SSukumar Swaminathan } else { 385682527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR; 385782527734SSukumar Swaminathan } 385882527734SSukumar Swaminathan 385982527734SSukumar Swaminathan return (FC_SUCCESS); 386082527734SSukumar Swaminathan 386182527734SSukumar Swaminathan } /* emlxs_sli3_prep_fcp_iocb() */ 386282527734SSukumar Swaminathan 386382527734SSukumar Swaminathan 386482527734SSukumar Swaminathan static uint32_t 386582527734SSukumar Swaminathan emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 386682527734SSukumar Swaminathan { 386782527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 386882527734SSukumar Swaminathan fc_packet_t *pkt; 386982527734SSukumar Swaminathan IOCBQ *iocbq; 387082527734SSukumar Swaminathan IOCB *iocb; 387182527734SSukumar Swaminathan CHANNEL *cp; 387282527734SSukumar Swaminathan NODELIST *ndlp; 387382527734SSukumar Swaminathan uint16_t iotag; 387482527734SSukumar Swaminathan uint32_t did; 387582527734SSukumar Swaminathan 387682527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 387782527734SSukumar Swaminathan cp = &hba->chan[FC_IP_RING]; 387882527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 387982527734SSukumar Swaminathan 388082527734SSukumar Swaminathan iocbq = &sbp->iocbq; 388182527734SSukumar Swaminathan iocb = &iocbq->iocb; 388282527734SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 388382527734SSukumar Swaminathan 388482527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 388582527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 388682527734SSukumar Swaminathan 388782527734SSukumar Swaminathan if (!iotag) { 388882527734SSukumar Swaminathan /* 388982527734SSukumar Swaminathan * No more command slots available, retry later 389082527734SSukumar Swaminathan */ 389182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 389282527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag: did=0x%x", did); 389382527734SSukumar Swaminathan 389482527734SSukumar Swaminathan return (FC_TRAN_BUSY); 389582527734SSukumar Swaminathan } 389682527734SSukumar Swaminathan 389782527734SSukumar Swaminathan /* Initalize iocbq */ 389882527734SSukumar Swaminathan iocbq->port = (void *) port; 389982527734SSukumar Swaminathan iocbq->channel = (void *) cp; 390082527734SSukumar Swaminathan 390182527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 390282527734SSukumar Swaminathan /* Unregister the packet */ 390382527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 390482527734SSukumar Swaminathan 390582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 390682527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 390782527734SSukumar Swaminathan 390882527734SSukumar Swaminathan return (FC_TRAN_BUSY); 390982527734SSukumar Swaminathan } 391082527734SSukumar Swaminathan /* Point of no return */ 391182527734SSukumar Swaminathan 391282527734SSukumar Swaminathan /* Initalize iocb */ 391382527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Fctl = 0; 391482527734SSukumar Swaminathan 391582527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_FIRST_SEQ) { 391682527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Fctl |= FSEQ; 391782527734SSukumar Swaminathan } 391882527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) { 391982527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Fctl |= SI; 392082527734SSukumar Swaminathan } 392182527734SSukumar Swaminathan 392282527734SSukumar Swaminathan /* network headers */ 392382527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; 392482527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 392582527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type; 392682527734SSukumar Swaminathan 392782527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 392882527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 392982527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 393082527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 393182527734SSukumar Swaminathan 393282527734SSukumar Swaminathan if (pkt->pkt_tran_type == FC_PKT_BROADCAST) { 393382527734SSukumar Swaminathan HBASTATS.IpBcastIssued++; 393482527734SSukumar Swaminathan 393582527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_BCAST64_CN; 393682527734SSukumar Swaminathan iocb->ULPCONTEXT = 0; 393782527734SSukumar Swaminathan 3938a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { 393982527734SSukumar Swaminathan if (hba->topology != TOPOLOGY_LOOP) { 394082527734SSukumar Swaminathan iocb->ULPCT = 0x1; 394182527734SSukumar Swaminathan } 394282527734SSukumar Swaminathan iocb->ULPCONTEXT = port->vpi; 394382527734SSukumar Swaminathan } 394482527734SSukumar Swaminathan } else { 394582527734SSukumar Swaminathan HBASTATS.IpSeqIssued++; 394682527734SSukumar Swaminathan 394782527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX; 394882527734SSukumar Swaminathan iocb->ULPCONTEXT = ndlp->nlp_Xri; 394982527734SSukumar Swaminathan } 395082527734SSukumar Swaminathan 395182527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 395282527734SSukumar Swaminathan case FC_TRAN_CLASS1: 395382527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 395482527734SSukumar Swaminathan break; 395582527734SSukumar Swaminathan case FC_TRAN_CLASS2: 395682527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 395782527734SSukumar Swaminathan break; 395882527734SSukumar Swaminathan case FC_TRAN_CLASS3: 395982527734SSukumar Swaminathan default: 396082527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 396182527734SSukumar Swaminathan break; 396282527734SSukumar Swaminathan } 396382527734SSukumar Swaminathan 396482527734SSukumar Swaminathan return (FC_SUCCESS); 396582527734SSukumar Swaminathan 396682527734SSukumar Swaminathan } /* emlxs_sli3_prep_ip_iocb() */ 396782527734SSukumar Swaminathan 396882527734SSukumar Swaminathan 396982527734SSukumar Swaminathan static uint32_t 397082527734SSukumar Swaminathan emlxs_sli3_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 397182527734SSukumar Swaminathan { 397282527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 397382527734SSukumar Swaminathan fc_packet_t *pkt; 397482527734SSukumar Swaminathan IOCBQ *iocbq; 397582527734SSukumar Swaminathan IOCB *iocb; 397682527734SSukumar Swaminathan CHANNEL *cp; 397782527734SSukumar Swaminathan uint16_t iotag; 397882527734SSukumar Swaminathan uint32_t did; 397982527734SSukumar Swaminathan uint32_t cmd; 398082527734SSukumar Swaminathan 398182527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 398282527734SSukumar Swaminathan cp = &hba->chan[FC_ELS_RING]; 398382527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 398482527734SSukumar Swaminathan 398582527734SSukumar Swaminathan iocbq = &sbp->iocbq; 398682527734SSukumar Swaminathan iocb = &iocbq->iocb; 398782527734SSukumar Swaminathan 398882527734SSukumar Swaminathan 398982527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 399082527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 399182527734SSukumar Swaminathan 399282527734SSukumar Swaminathan if (!iotag) { 399382527734SSukumar Swaminathan /* 399482527734SSukumar Swaminathan * No more command slots available, retry later 399582527734SSukumar Swaminathan */ 399682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 399782527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 399882527734SSukumar Swaminathan 399982527734SSukumar Swaminathan return (FC_TRAN_BUSY); 400082527734SSukumar Swaminathan } 400182527734SSukumar Swaminathan /* Initalize iocbq */ 400282527734SSukumar Swaminathan iocbq->port = (void *) port; 400382527734SSukumar Swaminathan iocbq->channel = (void *) cp; 400482527734SSukumar Swaminathan 400582527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 400682527734SSukumar Swaminathan /* Unregister the packet */ 400782527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 400882527734SSukumar Swaminathan 400982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 401082527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 401182527734SSukumar Swaminathan 401282527734SSukumar Swaminathan return (FC_TRAN_BUSY); 401382527734SSukumar Swaminathan } 401482527734SSukumar Swaminathan /* Point of no return */ 401582527734SSukumar Swaminathan 401682527734SSukumar Swaminathan /* Initalize iocb */ 401782527734SSukumar Swaminathan if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 401882527734SSukumar Swaminathan /* ELS Response */ 401982527734SSukumar Swaminathan iocb->ULPCONTEXT = (volatile uint16_t) pkt->pkt_cmd_fhdr.rx_id; 402082527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX; 402182527734SSukumar Swaminathan } else { 402282527734SSukumar Swaminathan /* ELS Request */ 402382527734SSukumar Swaminathan iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did; 402482527734SSukumar Swaminathan iocb->ULPCONTEXT = 402582527734SSukumar Swaminathan (did == BCAST_DID) ? pkt->pkt_cmd_fhdr.seq_id : 0; 402682527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR; 402782527734SSukumar Swaminathan 4028a9800bebSGarrett D'Amore if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { 4029a9800bebSGarrett D'Amore if (hba->topology != TOPOLOGY_LOOP) { 4030a9800bebSGarrett D'Amore cmd = *((uint32_t *)pkt->pkt_cmd); 4031a9800bebSGarrett D'Amore cmd &= ELS_CMD_MASK; 403282527734SSukumar Swaminathan 4033a9800bebSGarrett D'Amore if ((cmd == ELS_CMD_FLOGI) || 4034a9800bebSGarrett D'Amore (cmd == ELS_CMD_FDISC)) { 4035a9800bebSGarrett D'Amore iocb->ULPCT = 0x2; 4036a9800bebSGarrett D'Amore } else { 4037a9800bebSGarrett D'Amore iocb->ULPCT = 0x1; 4038a9800bebSGarrett D'Amore } 403982527734SSukumar Swaminathan } 4040a9800bebSGarrett D'Amore iocb->ULPCONTEXT = port->vpi; 404182527734SSukumar Swaminathan } 404282527734SSukumar Swaminathan } 404382527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 404482527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 404582527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 404682527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 404782527734SSukumar Swaminathan 404882527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 404982527734SSukumar Swaminathan case FC_TRAN_CLASS1: 405082527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 405182527734SSukumar Swaminathan break; 405282527734SSukumar Swaminathan case FC_TRAN_CLASS2: 405382527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 405482527734SSukumar Swaminathan break; 405582527734SSukumar Swaminathan case FC_TRAN_CLASS3: 405682527734SSukumar Swaminathan default: 405782527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 405882527734SSukumar Swaminathan break; 405982527734SSukumar Swaminathan } 406082527734SSukumar Swaminathan sbp->class = iocb->ULPCLASS; 406182527734SSukumar Swaminathan 406282527734SSukumar Swaminathan return (FC_SUCCESS); 406382527734SSukumar Swaminathan 406482527734SSukumar Swaminathan } /* emlxs_sli3_prep_els_iocb() */ 406582527734SSukumar Swaminathan 406682527734SSukumar Swaminathan 406782527734SSukumar Swaminathan static uint32_t 406882527734SSukumar Swaminathan emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 406982527734SSukumar Swaminathan { 407082527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 407182527734SSukumar Swaminathan fc_packet_t *pkt; 407282527734SSukumar Swaminathan IOCBQ *iocbq; 407382527734SSukumar Swaminathan IOCB *iocb; 407482527734SSukumar Swaminathan CHANNEL *cp; 407582527734SSukumar Swaminathan NODELIST *ndlp; 407682527734SSukumar Swaminathan uint16_t iotag; 407782527734SSukumar Swaminathan uint32_t did; 407882527734SSukumar Swaminathan 407982527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 408082527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 408182527734SSukumar Swaminathan cp = &hba->chan[FC_CT_RING]; 408282527734SSukumar Swaminathan 408382527734SSukumar Swaminathan iocbq = &sbp->iocbq; 408482527734SSukumar Swaminathan iocb = &iocbq->iocb; 408582527734SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 408682527734SSukumar Swaminathan 408782527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 408882527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 408982527734SSukumar Swaminathan 409082527734SSukumar Swaminathan if (!iotag) { 409182527734SSukumar Swaminathan /* 409282527734SSukumar Swaminathan * No more command slots available, retry later 409382527734SSukumar Swaminathan */ 409482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 409582527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 409682527734SSukumar Swaminathan 409782527734SSukumar Swaminathan return (FC_TRAN_BUSY); 409882527734SSukumar Swaminathan } 409982527734SSukumar Swaminathan 410082527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 410182527734SSukumar Swaminathan /* Unregister the packet */ 410282527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 410382527734SSukumar Swaminathan 410482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 410582527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 410682527734SSukumar Swaminathan 410782527734SSukumar Swaminathan return (FC_TRAN_BUSY); 410882527734SSukumar Swaminathan } 410982527734SSukumar Swaminathan 411082527734SSukumar Swaminathan /* Point of no return */ 411182527734SSukumar Swaminathan 411282527734SSukumar Swaminathan /* Initalize iocbq */ 411382527734SSukumar Swaminathan iocbq->port = (void *) port; 411482527734SSukumar Swaminathan iocbq->channel = (void *) cp; 411582527734SSukumar Swaminathan 411682527734SSukumar Swaminathan /* Fill in rest of iocb */ 411782527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Fctl = LA; 411882527734SSukumar Swaminathan 411982527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) { 412082527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Fctl |= LSEQ; 412182527734SSukumar Swaminathan } 412282527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) { 412382527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Fctl |= SI; 412482527734SSukumar Swaminathan } 412582527734SSukumar Swaminathan 412682527734SSukumar Swaminathan /* Initalize iocb */ 412782527734SSukumar Swaminathan if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 412882527734SSukumar Swaminathan /* CT Response */ 412982527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX; 413082527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; 413182527734SSukumar Swaminathan iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id; 413282527734SSukumar Swaminathan } else { 413382527734SSukumar Swaminathan /* CT Request */ 413482527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CR; 413582527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Dfctl = 0; 413682527734SSukumar Swaminathan iocb->ULPCONTEXT = ndlp->nlp_Rpi; 413782527734SSukumar Swaminathan } 413882527734SSukumar Swaminathan 413982527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 414082527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type; 414182527734SSukumar Swaminathan 414282527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 414382527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 414482527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 414582527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 414682527734SSukumar Swaminathan 414782527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 414882527734SSukumar Swaminathan case FC_TRAN_CLASS1: 414982527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 415082527734SSukumar Swaminathan break; 415182527734SSukumar Swaminathan case FC_TRAN_CLASS2: 415282527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 415382527734SSukumar Swaminathan break; 415482527734SSukumar Swaminathan case FC_TRAN_CLASS3: 415582527734SSukumar Swaminathan default: 415682527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 415782527734SSukumar Swaminathan break; 415882527734SSukumar Swaminathan } 415982527734SSukumar Swaminathan 416082527734SSukumar Swaminathan return (FC_SUCCESS); 416182527734SSukumar Swaminathan 416282527734SSukumar Swaminathan } /* emlxs_sli3_prep_ct_iocb() */ 416382527734SSukumar Swaminathan 416482527734SSukumar Swaminathan 4165291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 416682527734SSukumar Swaminathan static uint32_t 416782527734SSukumar Swaminathan emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 416882527734SSukumar Swaminathan { 416982527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 417082527734SSukumar Swaminathan uint32_t rval; 417182527734SSukumar Swaminathan 4172*8f23e9faSHans Rosenfeld if (sbp->fct_buf->db_sglist_length != 1) { 417382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 4174*8f23e9faSHans Rosenfeld "fct_bde_setup: Only 1 sglist entry supported: %d", 4175*8f23e9faSHans Rosenfeld sbp->fct_buf->db_sglist_length); 417682527734SSukumar Swaminathan return (1); 417782527734SSukumar Swaminathan } 417882527734SSukumar Swaminathan 4179*8f23e9faSHans Rosenfeld if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) { 418082527734SSukumar Swaminathan rval = emlxs_sli2_fct_bde_setup(port, sbp); 418182527734SSukumar Swaminathan } else { 418282527734SSukumar Swaminathan rval = emlxs_sli3_fct_bde_setup(port, sbp); 418382527734SSukumar Swaminathan } 418482527734SSukumar Swaminathan 418582527734SSukumar Swaminathan return (rval); 418682527734SSukumar Swaminathan 418782527734SSukumar Swaminathan } /* emlxs_fct_bde_setup() */ 4188291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4189291a2b48SSukumar Swaminathan 4190*8f23e9faSHans Rosenfeld 419182527734SSukumar Swaminathan static uint32_t 419282527734SSukumar Swaminathan emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 419382527734SSukumar Swaminathan { 419482527734SSukumar Swaminathan uint32_t rval; 419582527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 419682527734SSukumar Swaminathan 4197a9800bebSGarrett D'Amore if (hba->sli_mode < EMLXS_HBA_SLI3_MODE) { 419882527734SSukumar Swaminathan rval = emlxs_sli2_bde_setup(port, sbp); 419982527734SSukumar Swaminathan } else { 420082527734SSukumar Swaminathan rval = emlxs_sli3_bde_setup(port, sbp); 420182527734SSukumar Swaminathan } 420282527734SSukumar Swaminathan 420382527734SSukumar Swaminathan return (rval); 420482527734SSukumar Swaminathan 420582527734SSukumar Swaminathan } /* emlxs_bde_setup() */ 420682527734SSukumar Swaminathan 420782527734SSukumar Swaminathan 420882527734SSukumar Swaminathan static void 4209*8f23e9faSHans Rosenfeld emlxs_sli3_poll_intr(emlxs_hba_t *hba) 421082527734SSukumar Swaminathan { 421182527734SSukumar Swaminathan uint32_t ha_copy; 421282527734SSukumar Swaminathan 4213*8f23e9faSHans Rosenfeld /* Check attention bits once and process if required */ 421482527734SSukumar Swaminathan 4215*8f23e9faSHans Rosenfeld ha_copy = emlxs_check_attention(hba); 421682527734SSukumar Swaminathan 4217*8f23e9faSHans Rosenfeld if (ha_copy == 0) { 4218*8f23e9faSHans Rosenfeld return; 421982527734SSukumar Swaminathan } 422082527734SSukumar Swaminathan 422182527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 422282527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, -1); 422382527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 422482527734SSukumar Swaminathan 422582527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 422682527734SSukumar Swaminathan 422782527734SSukumar Swaminathan return; 422882527734SSukumar Swaminathan 422982527734SSukumar Swaminathan } /* emlxs_sli3_poll_intr() */ 423082527734SSukumar Swaminathan 4231*8f23e9faSHans Rosenfeld 423282527734SSukumar Swaminathan #ifdef MSI_SUPPORT 423382527734SSukumar Swaminathan static uint32_t 423482527734SSukumar Swaminathan emlxs_sli3_msi_intr(char *arg1, char *arg2) 423582527734SSukumar Swaminathan { 423682527734SSukumar Swaminathan emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 423782527734SSukumar Swaminathan #ifdef FMA_SUPPORT 423882527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 423982527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 424082527734SSukumar Swaminathan uint16_t msgid; 424182527734SSukumar Swaminathan uint32_t hc_copy; 424282527734SSukumar Swaminathan uint32_t ha_copy; 424382527734SSukumar Swaminathan uint32_t restore = 0; 4244291a2b48SSukumar Swaminathan 424582527734SSukumar Swaminathan /* 424682527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 4247*8f23e9faSHans Rosenfeld * "sli3_msi_intr: arg1=%p arg2=%p", arg1, arg2); 424882527734SSukumar Swaminathan */ 4249291a2b48SSukumar Swaminathan 425082527734SSukumar Swaminathan /* Check for legacy interrupt handling */ 425182527734SSukumar Swaminathan if (hba->intr_type == DDI_INTR_TYPE_FIXED) { 425282527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4253291a2b48SSukumar Swaminathan 425482527734SSukumar Swaminathan if (hba->flag & FC_OFFLINE_MODE) { 425582527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4256291a2b48SSukumar Swaminathan 425782527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 425882527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 425982527734SSukumar Swaminathan } else { 426082527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 426182527734SSukumar Swaminathan } 4262291a2b48SSukumar Swaminathan } 4263291a2b48SSukumar Swaminathan 426482527734SSukumar Swaminathan /* Get host attention bits */ 426582527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, -1); 4266291a2b48SSukumar Swaminathan 426782527734SSukumar Swaminathan if (ha_copy == 0) { 426882527734SSukumar Swaminathan if (hba->intr_unclaimed) { 426982527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 427082527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 427182527734SSukumar Swaminathan } 4272291a2b48SSukumar Swaminathan 427382527734SSukumar Swaminathan hba->intr_unclaimed = 1; 427482527734SSukumar Swaminathan } else { 427582527734SSukumar Swaminathan hba->intr_unclaimed = 0; 4276291a2b48SSukumar Swaminathan } 4277291a2b48SSukumar Swaminathan 427882527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4279291a2b48SSukumar Swaminathan 428082527734SSukumar Swaminathan /* Process the interrupt */ 428182527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 4282291a2b48SSukumar Swaminathan 428382527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 428482527734SSukumar Swaminathan } 4285291a2b48SSukumar Swaminathan 428682527734SSukumar Swaminathan /* DDI_INTR_TYPE_MSI */ 428782527734SSukumar Swaminathan /* DDI_INTR_TYPE_MSIX */ 4288291a2b48SSukumar Swaminathan 428982527734SSukumar Swaminathan /* Get MSI message id */ 429082527734SSukumar Swaminathan msgid = (uint16_t)((unsigned long)arg2); 4291291a2b48SSukumar Swaminathan 429282527734SSukumar Swaminathan /* Validate the message id */ 429382527734SSukumar Swaminathan if (msgid >= hba->intr_count) { 429482527734SSukumar Swaminathan msgid = 0; 429582527734SSukumar Swaminathan } 4296291a2b48SSukumar Swaminathan 429782527734SSukumar Swaminathan mutex_enter(&EMLXS_INTR_LOCK(msgid)); 4298291a2b48SSukumar Swaminathan 429982527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 430082527734SSukumar Swaminathan 430182527734SSukumar Swaminathan /* Check if adapter is offline */ 430282527734SSukumar Swaminathan if (hba->flag & FC_OFFLINE_MODE) { 430382527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 430482527734SSukumar Swaminathan mutex_exit(&EMLXS_INTR_LOCK(msgid)); 430582527734SSukumar Swaminathan 430682527734SSukumar Swaminathan /* Always claim an MSI interrupt */ 430782527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 430882527734SSukumar Swaminathan } 430982527734SSukumar Swaminathan 431082527734SSukumar Swaminathan /* Disable interrupts associated with this msgid */ 431182527734SSukumar Swaminathan if (msgid == 0 && (hba->model_info.chip == EMLXS_ZEPHYR_CHIP)) { 431282527734SSukumar Swaminathan hc_copy = hba->sli.sli3.hc_copy & ~hba->intr_mask; 431382527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hc_copy); 431482527734SSukumar Swaminathan restore = 1; 431582527734SSukumar Swaminathan } 431682527734SSukumar Swaminathan 431782527734SSukumar Swaminathan /* Get host attention bits */ 431882527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, msgid); 431982527734SSukumar Swaminathan 432082527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 432182527734SSukumar Swaminathan 432282527734SSukumar Swaminathan /* Process the interrupt */ 432382527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 432482527734SSukumar Swaminathan 432582527734SSukumar Swaminathan /* Restore interrupts */ 432682527734SSukumar Swaminathan if (restore) { 432782527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 432882527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 432982527734SSukumar Swaminathan #ifdef FMA_SUPPORT 433082527734SSukumar Swaminathan /* Access handle validation */ 433182527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 433282527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 433382527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 433482527734SSukumar Swaminathan } 433582527734SSukumar Swaminathan 433682527734SSukumar Swaminathan mutex_exit(&EMLXS_INTR_LOCK(msgid)); 433782527734SSukumar Swaminathan 433882527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 433982527734SSukumar Swaminathan 434082527734SSukumar Swaminathan } /* emlxs_sli3_msi_intr() */ 434182527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 434282527734SSukumar Swaminathan 434382527734SSukumar Swaminathan 434482527734SSukumar Swaminathan static int 434582527734SSukumar Swaminathan emlxs_sli3_intx_intr(char *arg) 434682527734SSukumar Swaminathan { 434782527734SSukumar Swaminathan emlxs_hba_t *hba = (emlxs_hba_t *)arg; 434882527734SSukumar Swaminathan uint32_t ha_copy = 0; 434982527734SSukumar Swaminathan 435082527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 435182527734SSukumar Swaminathan 435282527734SSukumar Swaminathan if (hba->flag & FC_OFFLINE_MODE) { 435382527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 435482527734SSukumar Swaminathan 435582527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 435682527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 435782527734SSukumar Swaminathan } else { 435882527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 4359291a2b48SSukumar Swaminathan } 436082527734SSukumar Swaminathan } 4361291a2b48SSukumar Swaminathan 436282527734SSukumar Swaminathan /* Get host attention bits */ 436382527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, -1); 4364291a2b48SSukumar Swaminathan 436582527734SSukumar Swaminathan if (ha_copy == 0) { 436682527734SSukumar Swaminathan if (hba->intr_unclaimed) { 436782527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 436882527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 4369291a2b48SSukumar Swaminathan } 4370291a2b48SSukumar Swaminathan 437182527734SSukumar Swaminathan hba->intr_unclaimed = 1; 437282527734SSukumar Swaminathan } else { 437382527734SSukumar Swaminathan hba->intr_unclaimed = 0; 437482527734SSukumar Swaminathan } 437582527734SSukumar Swaminathan 437682527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 437782527734SSukumar Swaminathan 437882527734SSukumar Swaminathan /* Process the interrupt */ 437982527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 438082527734SSukumar Swaminathan 438182527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 438282527734SSukumar Swaminathan 438382527734SSukumar Swaminathan } /* emlxs_sli3_intx_intr() */ 438482527734SSukumar Swaminathan 438582527734SSukumar Swaminathan 438682527734SSukumar Swaminathan /* EMLXS_PORT_LOCK must be held when call this routine */ 438782527734SSukumar Swaminathan static uint32_t 4388a9800bebSGarrett D'Amore emlxs_get_attention(emlxs_hba_t *hba, int32_t msgid) 438982527734SSukumar Swaminathan { 439082527734SSukumar Swaminathan #ifdef FMA_SUPPORT 439182527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 439282527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 439382527734SSukumar Swaminathan uint32_t ha_copy = 0; 439482527734SSukumar Swaminathan uint32_t ha_copy2; 439582527734SSukumar Swaminathan uint32_t mask = hba->sli.sli3.hc_copy; 439682527734SSukumar Swaminathan 439782527734SSukumar Swaminathan #ifdef MSI_SUPPORT 439882527734SSukumar Swaminathan 439982527734SSukumar Swaminathan read_ha_register: 440082527734SSukumar Swaminathan 440182527734SSukumar Swaminathan /* Check for default MSI interrupt */ 440282527734SSukumar Swaminathan if (msgid == 0) { 440382527734SSukumar Swaminathan /* Read host attention register to determine interrupt source */ 440482527734SSukumar Swaminathan ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 440582527734SSukumar Swaminathan 440682527734SSukumar Swaminathan /* Filter out MSI non-default attention bits */ 440782527734SSukumar Swaminathan ha_copy2 &= ~(hba->intr_cond); 440882527734SSukumar Swaminathan } 440982527734SSukumar Swaminathan 441082527734SSukumar Swaminathan /* Check for polled or fixed type interrupt */ 441182527734SSukumar Swaminathan else if (msgid == -1) { 441282527734SSukumar Swaminathan /* Read host attention register to determine interrupt source */ 441382527734SSukumar Swaminathan ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 441482527734SSukumar Swaminathan } 441582527734SSukumar Swaminathan 441682527734SSukumar Swaminathan /* Otherwise, assume a mapped MSI interrupt */ 441782527734SSukumar Swaminathan else { 441882527734SSukumar Swaminathan /* Convert MSI msgid to mapped attention bits */ 441982527734SSukumar Swaminathan ha_copy2 = hba->intr_map[msgid]; 442082527734SSukumar Swaminathan } 442182527734SSukumar Swaminathan 442282527734SSukumar Swaminathan #else /* !MSI_SUPPORT */ 442382527734SSukumar Swaminathan 442482527734SSukumar Swaminathan /* Read host attention register to determine interrupt source */ 442582527734SSukumar Swaminathan ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 442682527734SSukumar Swaminathan 442782527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 442882527734SSukumar Swaminathan 442982527734SSukumar Swaminathan /* Check if Hardware error interrupt is enabled */ 443082527734SSukumar Swaminathan if ((ha_copy2 & HA_ERATT) && !(mask & HC_ERINT_ENA)) { 443182527734SSukumar Swaminathan ha_copy2 &= ~HA_ERATT; 443282527734SSukumar Swaminathan } 443382527734SSukumar Swaminathan 443482527734SSukumar Swaminathan /* Check if link interrupt is enabled */ 443582527734SSukumar Swaminathan if ((ha_copy2 & HA_LATT) && !(mask & HC_LAINT_ENA)) { 443682527734SSukumar Swaminathan ha_copy2 &= ~HA_LATT; 443782527734SSukumar Swaminathan } 443882527734SSukumar Swaminathan 443982527734SSukumar Swaminathan /* Check if Mailbox interrupt is enabled */ 444082527734SSukumar Swaminathan if ((ha_copy2 & HA_MBATT) && !(mask & HC_MBINT_ENA)) { 444182527734SSukumar Swaminathan ha_copy2 &= ~HA_MBATT; 444282527734SSukumar Swaminathan } 444382527734SSukumar Swaminathan 444482527734SSukumar Swaminathan /* Check if ring0 interrupt is enabled */ 444582527734SSukumar Swaminathan if ((ha_copy2 & HA_R0ATT) && !(mask & HC_R0INT_ENA)) { 444682527734SSukumar Swaminathan ha_copy2 &= ~HA_R0ATT; 444782527734SSukumar Swaminathan } 444882527734SSukumar Swaminathan 444982527734SSukumar Swaminathan /* Check if ring1 interrupt is enabled */ 445082527734SSukumar Swaminathan if ((ha_copy2 & HA_R1ATT) && !(mask & HC_R1INT_ENA)) { 445182527734SSukumar Swaminathan ha_copy2 &= ~HA_R1ATT; 445282527734SSukumar Swaminathan } 445382527734SSukumar Swaminathan 445482527734SSukumar Swaminathan /* Check if ring2 interrupt is enabled */ 445582527734SSukumar Swaminathan if ((ha_copy2 & HA_R2ATT) && !(mask & HC_R2INT_ENA)) { 445682527734SSukumar Swaminathan ha_copy2 &= ~HA_R2ATT; 445782527734SSukumar Swaminathan } 445882527734SSukumar Swaminathan 445982527734SSukumar Swaminathan /* Check if ring3 interrupt is enabled */ 446082527734SSukumar Swaminathan if ((ha_copy2 & HA_R3ATT) && !(mask & HC_R3INT_ENA)) { 446182527734SSukumar Swaminathan ha_copy2 &= ~HA_R3ATT; 446282527734SSukumar Swaminathan } 4463291a2b48SSukumar Swaminathan 446482527734SSukumar Swaminathan /* Accumulate attention bits */ 446582527734SSukumar Swaminathan ha_copy |= ha_copy2; 4466291a2b48SSukumar Swaminathan 446782527734SSukumar Swaminathan /* Clear attentions except for error, link, and autoclear(MSIX) */ 446882527734SSukumar Swaminathan ha_copy2 &= ~(HA_ERATT | HA_LATT); /* | hba->intr_autoClear */ 4469291a2b48SSukumar Swaminathan 447082527734SSukumar Swaminathan if (ha_copy2) { 447182527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), ha_copy2); 447282527734SSukumar Swaminathan } 4473291a2b48SSukumar Swaminathan 44744baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 447582527734SSukumar Swaminathan /* Access handle validation */ 447682527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 44774baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4478291a2b48SSukumar Swaminathan 447982527734SSukumar Swaminathan return (ha_copy); 4480291a2b48SSukumar Swaminathan 448182527734SSukumar Swaminathan } /* emlxs_get_attention() */ 4482291a2b48SSukumar Swaminathan 4483291a2b48SSukumar Swaminathan 448482527734SSukumar Swaminathan static void 448582527734SSukumar Swaminathan emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy) 448682527734SSukumar Swaminathan { 44874baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 448882527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 44894baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 44904baa2c25SSukumar Swaminathan 449182527734SSukumar Swaminathan /* ha_copy should be pre-filtered */ 4492291a2b48SSukumar Swaminathan 449382527734SSukumar Swaminathan /* 449482527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4495*8f23e9faSHans Rosenfeld * "proc_attention: ha_copy=%x", ha_copy); 449682527734SSukumar Swaminathan */ 4497291a2b48SSukumar Swaminathan 449882527734SSukumar Swaminathan if (hba->state < FC_WARM_START) { 449982527734SSukumar Swaminathan return; 4500291a2b48SSukumar Swaminathan } 4501291a2b48SSukumar Swaminathan 450282527734SSukumar Swaminathan if (!ha_copy) { 450382527734SSukumar Swaminathan return; 450482527734SSukumar Swaminathan } 4505291a2b48SSukumar Swaminathan 450682527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 450782527734SSukumar Swaminathan (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba)); 450882527734SSukumar Swaminathan } 4509291a2b48SSukumar Swaminathan 451082527734SSukumar Swaminathan /* Adapter error */ 451182527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 451282527734SSukumar Swaminathan HBASTATS.IntrEvent[6]++; 451382527734SSukumar Swaminathan emlxs_handle_ff_error(hba); 451482527734SSukumar Swaminathan return; 451582527734SSukumar Swaminathan } 4516291a2b48SSukumar Swaminathan 451782527734SSukumar Swaminathan /* Mailbox interrupt */ 451882527734SSukumar Swaminathan if (ha_copy & HA_MBATT) { 451982527734SSukumar Swaminathan HBASTATS.IntrEvent[5]++; 452082527734SSukumar Swaminathan (void) emlxs_handle_mb_event(hba); 452182527734SSukumar Swaminathan } 4522291a2b48SSukumar Swaminathan 452382527734SSukumar Swaminathan /* Link Attention interrupt */ 452482527734SSukumar Swaminathan if (ha_copy & HA_LATT) { 452582527734SSukumar Swaminathan HBASTATS.IntrEvent[4]++; 452682527734SSukumar Swaminathan emlxs_sli3_handle_link_event(hba); 452782527734SSukumar Swaminathan } 4528291a2b48SSukumar Swaminathan 452982527734SSukumar Swaminathan /* event on ring 0 - FCP Ring */ 453082527734SSukumar Swaminathan if (ha_copy & HA_R0ATT) { 453182527734SSukumar Swaminathan HBASTATS.IntrEvent[0]++; 453282527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 0, ha_copy); 453382527734SSukumar Swaminathan } 4534291a2b48SSukumar Swaminathan 453582527734SSukumar Swaminathan /* event on ring 1 - IP Ring */ 453682527734SSukumar Swaminathan if (ha_copy & HA_R1ATT) { 453782527734SSukumar Swaminathan HBASTATS.IntrEvent[1]++; 453882527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 1, ha_copy); 453982527734SSukumar Swaminathan } 4540291a2b48SSukumar Swaminathan 454182527734SSukumar Swaminathan /* event on ring 2 - ELS Ring */ 454282527734SSukumar Swaminathan if (ha_copy & HA_R2ATT) { 454382527734SSukumar Swaminathan HBASTATS.IntrEvent[2]++; 454482527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 2, ha_copy); 454582527734SSukumar Swaminathan } 4546291a2b48SSukumar Swaminathan 454782527734SSukumar Swaminathan /* event on ring 3 - CT Ring */ 454882527734SSukumar Swaminathan if (ha_copy & HA_R3ATT) { 454982527734SSukumar Swaminathan HBASTATS.IntrEvent[3]++; 455082527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 3, ha_copy); 455182527734SSukumar Swaminathan } 4552291a2b48SSukumar Swaminathan 455382527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 455482527734SSukumar Swaminathan WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), SBUS_STAT_IP); 4555291a2b48SSukumar Swaminathan } 4556291a2b48SSukumar Swaminathan 455782527734SSukumar Swaminathan /* Set heartbeat flag to show activity */ 455882527734SSukumar Swaminathan hba->heartbeat_flag = 1; 4559291a2b48SSukumar Swaminathan 456082527734SSukumar Swaminathan #ifdef FMA_SUPPORT 456182527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 456282527734SSukumar Swaminathan /* Access handle validation */ 456382527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle); 4564291a2b48SSukumar Swaminathan } 456582527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4566291a2b48SSukumar Swaminathan 456782527734SSukumar Swaminathan return; 4568291a2b48SSukumar Swaminathan 456982527734SSukumar Swaminathan } /* emlxs_proc_attention() */ 4570291a2b48SSukumar Swaminathan 4571291a2b48SSukumar Swaminathan 457282527734SSukumar Swaminathan /* 457382527734SSukumar Swaminathan * emlxs_handle_ff_error() 457482527734SSukumar Swaminathan * 457582527734SSukumar Swaminathan * Description: Processes a FireFly error 457682527734SSukumar Swaminathan * Runs at Interrupt level 457782527734SSukumar Swaminathan */ 457882527734SSukumar Swaminathan static void 457982527734SSukumar Swaminathan emlxs_handle_ff_error(emlxs_hba_t *hba) 458082527734SSukumar Swaminathan { 458182527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 458282527734SSukumar Swaminathan uint32_t status; 458382527734SSukumar Swaminathan uint32_t status1; 458482527734SSukumar Swaminathan uint32_t status2; 458582527734SSukumar Swaminathan int i = 0; 4586291a2b48SSukumar Swaminathan 458782527734SSukumar Swaminathan /* do what needs to be done, get error from STATUS REGISTER */ 458882527734SSukumar Swaminathan status = READ_CSR_REG(hba, FC_HS_REG(hba)); 4589291a2b48SSukumar Swaminathan 459082527734SSukumar Swaminathan /* Clear Chip error bit */ 459182527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_ERATT); 4592291a2b48SSukumar Swaminathan 459382527734SSukumar Swaminathan /* If HS_FFER1 is set, then wait until the HS_FFER1 bit clears */ 459482527734SSukumar Swaminathan if (status & HS_FFER1) { 459582527734SSukumar Swaminathan 459682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 459782527734SSukumar Swaminathan "HS_FFER1 received"); 459882527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 4599*8f23e9faSHans Rosenfeld (void) emlxs_offline(hba, 1); 460082527734SSukumar Swaminathan while ((status & HS_FFER1) && (i < 300)) { 460182527734SSukumar Swaminathan status = 460282527734SSukumar Swaminathan READ_CSR_REG(hba, FC_HS_REG(hba)); 4603*8f23e9faSHans Rosenfeld BUSYWAIT_MS(1000); 460482527734SSukumar Swaminathan i++; 4605291a2b48SSukumar Swaminathan } 460682527734SSukumar Swaminathan } 4607291a2b48SSukumar Swaminathan 460882527734SSukumar Swaminathan if (i == 300) { 460982527734SSukumar Swaminathan /* 5 minutes is up, shutdown HBA */ 461082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 461182527734SSukumar Swaminathan "HS_FFER1 clear timeout"); 4612291a2b48SSukumar Swaminathan 461382527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 461482527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); 4615291a2b48SSukumar Swaminathan 461682527734SSukumar Swaminathan goto done; 4617291a2b48SSukumar Swaminathan } 4618291a2b48SSukumar Swaminathan 461982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 462082527734SSukumar Swaminathan "HS_FFER1 cleared"); 462182527734SSukumar Swaminathan 462282527734SSukumar Swaminathan if (status & HS_OVERTEMP) { 462382527734SSukumar Swaminathan status1 = 462482527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 462582527734SSukumar Swaminathan ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xb0)); 462682527734SSukumar Swaminathan 462782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 462882527734SSukumar Swaminathan "Maximum adapter temperature exceeded (%d �C).", status1); 462982527734SSukumar Swaminathan 463082527734SSukumar Swaminathan hba->temperature = status1; 463182527734SSukumar Swaminathan hba->flag |= FC_OVERTEMP_EVENT; 463282527734SSukumar Swaminathan 463382527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 463482527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, 463582527734SSukumar Swaminathan NULL, NULL); 463682527734SSukumar Swaminathan 463782527734SSukumar Swaminathan } else { 463882527734SSukumar Swaminathan status1 = 463982527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 464082527734SSukumar Swaminathan ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xa8)); 464182527734SSukumar Swaminathan status2 = 464282527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 464382527734SSukumar Swaminathan ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xac)); 464482527734SSukumar Swaminathan 464582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 464682527734SSukumar Swaminathan "Host Error Attention: " 464782527734SSukumar Swaminathan "status=0x%x status1=0x%x status2=0x%x", 464882527734SSukumar Swaminathan status, status1, status2); 464982527734SSukumar Swaminathan 465082527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 4651291a2b48SSukumar Swaminathan 465282527734SSukumar Swaminathan if (status & HS_FFER6) { 465382527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_restart_thread, 465482527734SSukumar Swaminathan NULL, NULL); 465582527734SSukumar Swaminathan } else { 465682527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, 465782527734SSukumar Swaminathan NULL, NULL); 4658291a2b48SSukumar Swaminathan } 4659291a2b48SSukumar Swaminathan } 4660291a2b48SSukumar Swaminathan 466182527734SSukumar Swaminathan done: 466282527734SSukumar Swaminathan #ifdef FMA_SUPPORT 466382527734SSukumar Swaminathan /* Access handle validation */ 466482527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 466582527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 466682527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4667291a2b48SSukumar Swaminathan 466882527734SSukumar Swaminathan return; 4669291a2b48SSukumar Swaminathan 467082527734SSukumar Swaminathan } /* emlxs_handle_ff_error() */ 4671291a2b48SSukumar Swaminathan 4672291a2b48SSukumar Swaminathan 467382527734SSukumar Swaminathan /* 467482527734SSukumar Swaminathan * emlxs_sli3_handle_link_event() 467582527734SSukumar Swaminathan * 467682527734SSukumar Swaminathan * Description: Process a Link Attention. 467782527734SSukumar Swaminathan */ 467882527734SSukumar Swaminathan static void 467982527734SSukumar Swaminathan emlxs_sli3_handle_link_event(emlxs_hba_t *hba) 468082527734SSukumar Swaminathan { 468182527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 468282527734SSukumar Swaminathan MAILBOXQ *mbq; 468382527734SSukumar Swaminathan int rc; 4684291a2b48SSukumar Swaminathan 468582527734SSukumar Swaminathan HBASTATS.LinkEvent++; 4686291a2b48SSukumar Swaminathan 468782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_event_msg, "event=%x", 468882527734SSukumar Swaminathan HBASTATS.LinkEvent); 4689291a2b48SSukumar Swaminathan 469082527734SSukumar Swaminathan /* Make sure link is declared down */ 469182527734SSukumar Swaminathan emlxs_linkdown(hba); 4692291a2b48SSukumar Swaminathan 469382527734SSukumar Swaminathan /* Get a buffer which will be used for mailbox commands */ 4694*8f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) { 469582527734SSukumar Swaminathan /* Get link attention message */ 469682527734SSukumar Swaminathan if (emlxs_mb_read_la(hba, mbq) == 0) { 469782527734SSukumar Swaminathan rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, 469882527734SSukumar Swaminathan MBX_NOWAIT, 0); 469982527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 4700a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, 4701a9800bebSGarrett D'Amore (void *)mbq); 470282527734SSukumar Swaminathan } 4703291a2b48SSukumar Swaminathan 470482527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4705291a2b48SSukumar Swaminathan 470682527734SSukumar Swaminathan /* 470782527734SSukumar Swaminathan * Clear Link Attention in HA REG 470882527734SSukumar Swaminathan */ 470982527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_LATT); 4710291a2b48SSukumar Swaminathan 471182527734SSukumar Swaminathan #ifdef FMA_SUPPORT 471282527734SSukumar Swaminathan /* Access handle validation */ 471382527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 471482527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4715291a2b48SSukumar Swaminathan 471682527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 471782527734SSukumar Swaminathan } else { 4718a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 4719291a2b48SSukumar Swaminathan } 4720291a2b48SSukumar Swaminathan } 4721291a2b48SSukumar Swaminathan 472282527734SSukumar Swaminathan } /* emlxs_sli3_handle_link_event() */ 4723291a2b48SSukumar Swaminathan 4724291a2b48SSukumar Swaminathan 472582527734SSukumar Swaminathan /* 472682527734SSukumar Swaminathan * emlxs_sli3_handle_ring_event() 472782527734SSukumar Swaminathan * 472882527734SSukumar Swaminathan * Description: Process a Ring Attention. 472982527734SSukumar Swaminathan */ 4730291a2b48SSukumar Swaminathan static void 473182527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, 473282527734SSukumar Swaminathan uint32_t ha_copy) 4733291a2b48SSukumar Swaminathan { 473482527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 473582527734SSukumar Swaminathan SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 473682527734SSukumar Swaminathan CHANNEL *cp; 473782527734SSukumar Swaminathan RING *rp; 473882527734SSukumar Swaminathan IOCB *entry; 473982527734SSukumar Swaminathan IOCBQ *iocbq; 474082527734SSukumar Swaminathan IOCBQ local_iocbq; 474182527734SSukumar Swaminathan PGP *pgp; 474282527734SSukumar Swaminathan uint32_t count; 474382527734SSukumar Swaminathan volatile uint32_t chipatt; 474482527734SSukumar Swaminathan void *ioa2; 474582527734SSukumar Swaminathan uint32_t reg; 474682527734SSukumar Swaminathan uint32_t channel_no; 4747291a2b48SSukumar Swaminathan off_t offset; 474882527734SSukumar Swaminathan IOCBQ *rsp_head = NULL; 474982527734SSukumar Swaminathan IOCBQ *rsp_tail = NULL; 475082527734SSukumar Swaminathan emlxs_buf_t *sbp = NULL; 4751291a2b48SSukumar Swaminathan 475282527734SSukumar Swaminathan count = 0; 475382527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ring_no]; 475482527734SSukumar Swaminathan cp = rp->channelp; 475582527734SSukumar Swaminathan channel_no = cp->channelno; 4756291a2b48SSukumar Swaminathan 475782527734SSukumar Swaminathan /* 475882527734SSukumar Swaminathan * Isolate this ring's host attention bits 475982527734SSukumar Swaminathan * This makes all ring attention bits equal 476082527734SSukumar Swaminathan * to Ring0 attention bits 476182527734SSukumar Swaminathan */ 476282527734SSukumar Swaminathan reg = (ha_copy >> (ring_no * 4)) & 0x0f; 4763291a2b48SSukumar Swaminathan 476482527734SSukumar Swaminathan /* 476582527734SSukumar Swaminathan * Gather iocb entries off response ring. 476682527734SSukumar Swaminathan * Ensure entry is owned by the host. 476782527734SSukumar Swaminathan */ 476882527734SSukumar Swaminathan pgp = (PGP *)&slim2p->mbx.us.s2.port[ring_no]; 476982527734SSukumar Swaminathan offset = 477082527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) - 477182527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 477282527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 477382527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 477482527734SSukumar Swaminathan rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx); 4775291a2b48SSukumar Swaminathan 477682527734SSukumar Swaminathan /* While ring is not empty */ 477782527734SSukumar Swaminathan while (rp->fc_rspidx != rp->fc_port_rspidx) { 477882527734SSukumar Swaminathan HBASTATS.IocbReceived[channel_no]++; 4779291a2b48SSukumar Swaminathan 478082527734SSukumar Swaminathan /* Get the next response ring iocb */ 478182527734SSukumar Swaminathan entry = 478282527734SSukumar Swaminathan (IOCB *)(((char *)rp->fc_rspringaddr + 478382527734SSukumar Swaminathan (rp->fc_rspidx * hba->sli.sli3.iocb_rsp_size))); 4784291a2b48SSukumar Swaminathan 478582527734SSukumar Swaminathan /* DMA sync the response ring iocb for the adapter */ 478682527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)entry) 478782527734SSukumar Swaminathan - (uint64_t)((unsigned long)slim2p)); 478882527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 478982527734SSukumar Swaminathan hba->sli.sli3.iocb_rsp_size, DDI_DMA_SYNC_FORKERNEL); 4790291a2b48SSukumar Swaminathan 479182527734SSukumar Swaminathan count++; 4792291a2b48SSukumar Swaminathan 479382527734SSukumar Swaminathan /* Copy word6 and word7 to local iocb for now */ 479482527734SSukumar Swaminathan iocbq = &local_iocbq; 4795291a2b48SSukumar Swaminathan 479682527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry + (sizeof (uint32_t) * 6), 479782527734SSukumar Swaminathan (uint8_t *)iocbq + (sizeof (uint32_t) * 6), 479882527734SSukumar Swaminathan (sizeof (uint32_t) * 2)); 4799291a2b48SSukumar Swaminathan 480082527734SSukumar Swaminathan /* when LE is not set, entire Command has not been received */ 480182527734SSukumar Swaminathan if (!iocbq->iocb.ULPLE) { 480282527734SSukumar Swaminathan /* This should never happen */ 480382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_error_msg, 480482527734SSukumar Swaminathan "ulpLE is not set. " 4805*8f23e9faSHans Rosenfeld "ring=%d iotag=%d cmd=%x status=%x", 480682527734SSukumar Swaminathan channel_no, iocbq->iocb.ULPIOTAG, 480782527734SSukumar Swaminathan iocbq->iocb.ULPCOMMAND, iocbq->iocb.ULPSTATUS); 4808291a2b48SSukumar Swaminathan 480982527734SSukumar Swaminathan goto next; 4810291a2b48SSukumar Swaminathan } 4811291a2b48SSukumar Swaminathan 4812*8f23e9faSHans Rosenfeld sbp = NULL; 481382527734SSukumar Swaminathan switch (iocbq->iocb.ULPCOMMAND) { 481482527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 481582527734SSukumar Swaminathan case CMD_CLOSE_XRI_CX: 481682527734SSukumar Swaminathan case CMD_CLOSE_XRI_CN: 481782527734SSukumar Swaminathan case CMD_ABORT_XRI_CX: 4818*8f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) { 4819*8f23e9faSHans Rosenfeld sbp = emlxs_unregister_pkt(cp, 4820*8f23e9faSHans Rosenfeld iocbq->iocb.ULPIOTAG, 0); 482182527734SSukumar Swaminathan } 482282527734SSukumar Swaminathan break; 482382527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4824291a2b48SSukumar Swaminathan 482582527734SSukumar Swaminathan /* Ring 0 registered commands */ 482682527734SSukumar Swaminathan case CMD_FCP_ICMND_CR: 482782527734SSukumar Swaminathan case CMD_FCP_ICMND_CX: 482882527734SSukumar Swaminathan case CMD_FCP_IREAD_CR: 482982527734SSukumar Swaminathan case CMD_FCP_IREAD_CX: 483082527734SSukumar Swaminathan case CMD_FCP_IWRITE_CR: 483182527734SSukumar Swaminathan case CMD_FCP_IWRITE_CX: 483282527734SSukumar Swaminathan case CMD_FCP_ICMND64_CR: 483382527734SSukumar Swaminathan case CMD_FCP_ICMND64_CX: 483482527734SSukumar Swaminathan case CMD_FCP_IREAD64_CR: 483582527734SSukumar Swaminathan case CMD_FCP_IREAD64_CX: 483682527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CR: 483782527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CX: 483882527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 483982527734SSukumar Swaminathan case CMD_FCP_TSEND_CX: 484082527734SSukumar Swaminathan case CMD_FCP_TSEND64_CX: 484182527734SSukumar Swaminathan case CMD_FCP_TRECEIVE_CX: 484282527734SSukumar Swaminathan case CMD_FCP_TRECEIVE64_CX: 484382527734SSukumar Swaminathan case CMD_FCP_TRSP_CX: 484482527734SSukumar Swaminathan case CMD_FCP_TRSP64_CX: 484582527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4846291a2b48SSukumar Swaminathan 484782527734SSukumar Swaminathan /* Ring 1 registered commands */ 484882527734SSukumar Swaminathan case CMD_XMIT_BCAST_CN: 484982527734SSukumar Swaminathan case CMD_XMIT_BCAST_CX: 485082527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE_CX: 485182527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE_CR: 485282527734SSukumar Swaminathan case CMD_XMIT_BCAST64_CN: 485382527734SSukumar Swaminathan case CMD_XMIT_BCAST64_CX: 485482527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE64_CX: 485582527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE64_CR: 485682527734SSukumar Swaminathan case CMD_CREATE_XRI_CR: 485782527734SSukumar Swaminathan case CMD_CREATE_XRI_CX: 4858291a2b48SSukumar Swaminathan 485982527734SSukumar Swaminathan /* Ring 2 registered commands */ 486082527734SSukumar Swaminathan case CMD_ELS_REQUEST_CR: 486182527734SSukumar Swaminathan case CMD_ELS_REQUEST_CX: 486282527734SSukumar Swaminathan case CMD_XMIT_ELS_RSP_CX: 486382527734SSukumar Swaminathan case CMD_ELS_REQUEST64_CR: 486482527734SSukumar Swaminathan case CMD_ELS_REQUEST64_CX: 486582527734SSukumar Swaminathan case CMD_XMIT_ELS_RSP64_CX: 4866291a2b48SSukumar Swaminathan 486782527734SSukumar Swaminathan /* Ring 3 registered commands */ 486882527734SSukumar Swaminathan case CMD_GEN_REQUEST64_CR: 486982527734SSukumar Swaminathan case CMD_GEN_REQUEST64_CX: 4870291a2b48SSukumar Swaminathan 487182527734SSukumar Swaminathan sbp = 487282527734SSukumar Swaminathan emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0); 487382527734SSukumar Swaminathan break; 487482527734SSukumar Swaminathan } 4875291a2b48SSukumar Swaminathan 487682527734SSukumar Swaminathan /* If packet is stale, then drop it. */ 487782527734SSukumar Swaminathan if (sbp == STALE_PACKET) { 487882527734SSukumar Swaminathan cp->hbaCmplCmd_sbp++; 487982527734SSukumar Swaminathan /* Copy entry to the local iocbq */ 488082527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry, 488182527734SSukumar Swaminathan (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4882291a2b48SSukumar Swaminathan 488382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg, 488482527734SSukumar Swaminathan "channelno=%d iocb=%p cmd=%x status=%x " 4885*8f23e9faSHans Rosenfeld "error=%x iotag=%d context=%x info=%x", 488682527734SSukumar Swaminathan channel_no, iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND, 488782527734SSukumar Swaminathan iocbq->iocb.ULPSTATUS, 488882527734SSukumar Swaminathan (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError, 488982527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPIOTAG, 489082527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPCONTEXT, 489182527734SSukumar Swaminathan (uint8_t)iocbq->iocb.ULPRSVDBYTE); 4892291a2b48SSukumar Swaminathan 489382527734SSukumar Swaminathan goto next; 4894291a2b48SSukumar Swaminathan } 4895291a2b48SSukumar Swaminathan 489682527734SSukumar Swaminathan /* 489782527734SSukumar Swaminathan * If a packet was found, then queue the packet's 489882527734SSukumar Swaminathan * iocb for deferred processing 489982527734SSukumar Swaminathan */ 490082527734SSukumar Swaminathan else if (sbp) { 490182527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 490282527734SSukumar Swaminathan fct_cmd_t *fct_cmd; 490382527734SSukumar Swaminathan emlxs_buf_t *cmd_sbp; 4904291a2b48SSukumar Swaminathan 490582527734SSukumar Swaminathan fct_cmd = sbp->fct_cmd; 490682527734SSukumar Swaminathan if (fct_cmd) { 490782527734SSukumar Swaminathan cmd_sbp = 490882527734SSukumar Swaminathan (emlxs_buf_t *)fct_cmd->cmd_fca_private; 490982527734SSukumar Swaminathan mutex_enter(&cmd_sbp->fct_mtx); 491082527734SSukumar Swaminathan EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 491182527734SSukumar Swaminathan EMLXS_FCT_IOCB_COMPLETE); 491282527734SSukumar Swaminathan mutex_exit(&cmd_sbp->fct_mtx); 491382527734SSukumar Swaminathan } 491482527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 491582527734SSukumar Swaminathan cp->hbaCmplCmd_sbp++; 49161a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&hba->io_active); 4917*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT 4918*8f23e9faSHans Rosenfeld if (sbp->node) { 4919*8f23e9faSHans Rosenfeld atomic_dec_32(&sbp->node->io_active); 4920*8f23e9faSHans Rosenfeld } 4921*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */ 4922291a2b48SSukumar Swaminathan 492382527734SSukumar Swaminathan /* Copy entry to sbp's iocbq */ 492482527734SSukumar Swaminathan iocbq = &sbp->iocbq; 492582527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry, 492682527734SSukumar Swaminathan (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4927291a2b48SSukumar Swaminathan 492882527734SSukumar Swaminathan iocbq->next = NULL; 4929291a2b48SSukumar Swaminathan 493082527734SSukumar Swaminathan /* 493182527734SSukumar Swaminathan * If this is NOT a polled command completion 493282527734SSukumar Swaminathan * or a driver allocated pkt, then defer pkt 493382527734SSukumar Swaminathan * completion. 493482527734SSukumar Swaminathan */ 493582527734SSukumar Swaminathan if (!(sbp->pkt_flags & 493682527734SSukumar Swaminathan (PACKET_POLLED | PACKET_ALLOCATED))) { 493782527734SSukumar Swaminathan /* Add the IOCB to the local list */ 493882527734SSukumar Swaminathan if (!rsp_head) { 493982527734SSukumar Swaminathan rsp_head = iocbq; 494082527734SSukumar Swaminathan } else { 494182527734SSukumar Swaminathan rsp_tail->next = iocbq; 494282527734SSukumar Swaminathan } 4943291a2b48SSukumar Swaminathan 494482527734SSukumar Swaminathan rsp_tail = iocbq; 4945291a2b48SSukumar Swaminathan 494682527734SSukumar Swaminathan goto next; 494782527734SSukumar Swaminathan } 494882527734SSukumar Swaminathan } else { 494982527734SSukumar Swaminathan cp->hbaCmplCmd++; 495082527734SSukumar Swaminathan /* Copy entry to the local iocbq */ 495182527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry, 495282527734SSukumar Swaminathan (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4953291a2b48SSukumar Swaminathan 495482527734SSukumar Swaminathan iocbq->next = NULL; 495582527734SSukumar Swaminathan iocbq->bp = NULL; 495682527734SSukumar Swaminathan iocbq->port = &PPORT; 495782527734SSukumar Swaminathan iocbq->channel = cp; 495882527734SSukumar Swaminathan iocbq->node = NULL; 495982527734SSukumar Swaminathan iocbq->sbp = NULL; 496082527734SSukumar Swaminathan iocbq->flag = 0; 496182527734SSukumar Swaminathan } 4962291a2b48SSukumar Swaminathan 496382527734SSukumar Swaminathan /* process the channel event now */ 496482527734SSukumar Swaminathan emlxs_proc_channel_event(hba, cp, iocbq); 4965291a2b48SSukumar Swaminathan 496682527734SSukumar Swaminathan next: 496782527734SSukumar Swaminathan /* Increment the driver's local response get index */ 496882527734SSukumar Swaminathan if (++rp->fc_rspidx >= rp->fc_numRiocb) { 496982527734SSukumar Swaminathan rp->fc_rspidx = 0; 497082527734SSukumar Swaminathan } 4971291a2b48SSukumar Swaminathan 497282527734SSukumar Swaminathan } /* while (TRUE) */ 4973291a2b48SSukumar Swaminathan 497482527734SSukumar Swaminathan if (rsp_head) { 497582527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 497682527734SSukumar Swaminathan if (cp->rsp_head == NULL) { 497782527734SSukumar Swaminathan cp->rsp_head = rsp_head; 497882527734SSukumar Swaminathan cp->rsp_tail = rsp_tail; 497982527734SSukumar Swaminathan } else { 498082527734SSukumar Swaminathan cp->rsp_tail->next = rsp_head; 498182527734SSukumar Swaminathan cp->rsp_tail = rsp_tail; 498282527734SSukumar Swaminathan } 498382527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 4984291a2b48SSukumar Swaminathan 498582527734SSukumar Swaminathan emlxs_thread_trigger2(&cp->intr_thread, emlxs_proc_channel, cp); 498682527734SSukumar Swaminathan } 4987291a2b48SSukumar Swaminathan 498882527734SSukumar Swaminathan /* Check if at least one response entry was processed */ 498982527734SSukumar Swaminathan if (count) { 499082527734SSukumar Swaminathan /* Update response get index for the adapter */ 499182527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 499282527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channel_no].rspGetInx 499382527734SSukumar Swaminathan = BE_SWAP32(rp->fc_rspidx); 4994291a2b48SSukumar Swaminathan 499582527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 499682527734SSukumar Swaminathan offset = (off_t) 499782527734SSukumar Swaminathan ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 499882527734SSukumar Swaminathan host[channel_no].rspGetInx)) 499982527734SSukumar Swaminathan - (uint64_t)((unsigned long)slim2p)); 500082527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 500182527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORDEV); 500282527734SSukumar Swaminathan } else { 500382527734SSukumar Swaminathan ioa2 = 500482527734SSukumar Swaminathan (void *)((char *)hba->sli.sli3.slim_addr + 500582527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + (((channel_no * 2) + 500682527734SSukumar Swaminathan 1) * sizeof (uint32_t))); 500782527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 500882527734SSukumar Swaminathan rp->fc_rspidx); 500982527734SSukumar Swaminathan #ifdef FMA_SUPPORT 501082527734SSukumar Swaminathan /* Access handle validation */ 501182527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, 501282527734SSukumar Swaminathan hba->sli.sli3.slim_acc_handle); 501382527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5014291a2b48SSukumar Swaminathan } 5015291a2b48SSukumar Swaminathan 501682527734SSukumar Swaminathan if (reg & HA_R0RE_REQ) { 501782527734SSukumar Swaminathan /* HBASTATS.chipRingFree++; */ 5018291a2b48SSukumar Swaminathan 501982527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 5020291a2b48SSukumar Swaminathan 502182527734SSukumar Swaminathan /* Tell the adapter we serviced the ring */ 502282527734SSukumar Swaminathan chipatt = ((CA_R0ATT | CA_R0RE_RSP) << 502382527734SSukumar Swaminathan (channel_no * 4)); 502482527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), chipatt); 5025291a2b48SSukumar Swaminathan 502682527734SSukumar Swaminathan #ifdef FMA_SUPPORT 502782527734SSukumar Swaminathan /* Access handle validation */ 502882527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 502982527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 503082527734SSukumar Swaminathan 503182527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5032291a2b48SSukumar Swaminathan } 503382527734SSukumar Swaminathan } 5034291a2b48SSukumar Swaminathan 503582527734SSukumar Swaminathan if ((reg & HA_R0CE_RSP) || hba->channel_tx_count) { 503682527734SSukumar Swaminathan /* HBASTATS.hostRingFree++; */ 5037291a2b48SSukumar Swaminathan 503882527734SSukumar Swaminathan /* Cmd ring may be available. Try sending more iocbs */ 503982527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd(hba, cp, 0); 5040291a2b48SSukumar Swaminathan } 5041291a2b48SSukumar Swaminathan 504282527734SSukumar Swaminathan /* HBASTATS.ringEvent++; */ 5043291a2b48SSukumar Swaminathan 504482527734SSukumar Swaminathan return; 5045291a2b48SSukumar Swaminathan 504682527734SSukumar Swaminathan } /* emlxs_sli3_handle_ring_event() */ 5047291a2b48SSukumar Swaminathan 5048291a2b48SSukumar Swaminathan 504982527734SSukumar Swaminathan extern int 505082527734SSukumar Swaminathan emlxs_handle_rcv_seq(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 505182527734SSukumar Swaminathan { 505282527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 505382527734SSukumar Swaminathan IOCB *iocb; 505482527734SSukumar Swaminathan RING *rp; 505582527734SSukumar Swaminathan MATCHMAP *mp = NULL; 505682527734SSukumar Swaminathan uint64_t bdeAddr; 505782527734SSukumar Swaminathan uint32_t vpi = 0; 505882527734SSukumar Swaminathan uint32_t channelno; 505982527734SSukumar Swaminathan uint32_t size = 0; 506082527734SSukumar Swaminathan uint32_t *RcvError; 506182527734SSukumar Swaminathan uint32_t *RcvDropped; 506282527734SSukumar Swaminathan uint32_t *UbPosted; 506382527734SSukumar Swaminathan emlxs_msg_t *dropped_msg; 506482527734SSukumar Swaminathan char error_str[64]; 506582527734SSukumar Swaminathan uint32_t buf_type; 506682527734SSukumar Swaminathan uint32_t *word; 5067291a2b48SSukumar Swaminathan 506882527734SSukumar Swaminathan channelno = cp->channelno; 506982527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[channelno]; 5070291a2b48SSukumar Swaminathan 507182527734SSukumar Swaminathan iocb = &iocbq->iocb; 507282527734SSukumar Swaminathan word = (uint32_t *)iocb; 5073291a2b48SSukumar Swaminathan 507482527734SSukumar Swaminathan switch (channelno) { 507582527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 507682527734SSukumar Swaminathan case FC_FCT_RING: 507782527734SSukumar Swaminathan HBASTATS.FctRingEvent++; 507882527734SSukumar Swaminathan RcvError = &HBASTATS.FctRingError; 507982527734SSukumar Swaminathan RcvDropped = &HBASTATS.FctRingDropped; 508082527734SSukumar Swaminathan UbPosted = &HBASTATS.FctUbPosted; 508182527734SSukumar Swaminathan dropped_msg = &emlxs_fct_detail_msg; 508282527734SSukumar Swaminathan buf_type = MEM_FCTBUF; 508382527734SSukumar Swaminathan break; 508482527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 5085291a2b48SSukumar Swaminathan 508682527734SSukumar Swaminathan case FC_IP_RING: 508782527734SSukumar Swaminathan HBASTATS.IpRcvEvent++; 508882527734SSukumar Swaminathan RcvError = &HBASTATS.IpDropped; 508982527734SSukumar Swaminathan RcvDropped = &HBASTATS.IpDropped; 509082527734SSukumar Swaminathan UbPosted = &HBASTATS.IpUbPosted; 509182527734SSukumar Swaminathan dropped_msg = &emlxs_unsol_ip_dropped_msg; 509282527734SSukumar Swaminathan buf_type = MEM_IPBUF; 509382527734SSukumar Swaminathan break; 5094291a2b48SSukumar Swaminathan 509582527734SSukumar Swaminathan case FC_ELS_RING: 509682527734SSukumar Swaminathan HBASTATS.ElsRcvEvent++; 509782527734SSukumar Swaminathan RcvError = &HBASTATS.ElsRcvError; 509882527734SSukumar Swaminathan RcvDropped = &HBASTATS.ElsRcvDropped; 509982527734SSukumar Swaminathan UbPosted = &HBASTATS.ElsUbPosted; 510082527734SSukumar Swaminathan dropped_msg = &emlxs_unsol_els_dropped_msg; 510182527734SSukumar Swaminathan buf_type = MEM_ELSBUF; 510282527734SSukumar Swaminathan break; 510382527734SSukumar Swaminathan 510482527734SSukumar Swaminathan case FC_CT_RING: 510582527734SSukumar Swaminathan HBASTATS.CtRcvEvent++; 510682527734SSukumar Swaminathan RcvError = &HBASTATS.CtRcvError; 510782527734SSukumar Swaminathan RcvDropped = &HBASTATS.CtRcvDropped; 510882527734SSukumar Swaminathan UbPosted = &HBASTATS.CtUbPosted; 510982527734SSukumar Swaminathan dropped_msg = &emlxs_unsol_ct_dropped_msg; 511082527734SSukumar Swaminathan buf_type = MEM_CTBUF; 511182527734SSukumar Swaminathan break; 511282527734SSukumar Swaminathan 511382527734SSukumar Swaminathan default: 511482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 511582527734SSukumar Swaminathan "channel=%d cmd=%x %s %x %x %x %x", 511682527734SSukumar Swaminathan channelno, iocb->ULPCOMMAND, 511782527734SSukumar Swaminathan emlxs_state_xlate(iocb->ULPSTATUS), word[4], word[5], 511882527734SSukumar Swaminathan word[6], word[7]); 511982527734SSukumar Swaminathan return (1); 512082527734SSukumar Swaminathan } 512182527734SSukumar Swaminathan 512282527734SSukumar Swaminathan if (iocb->ULPSTATUS) { 512382527734SSukumar Swaminathan if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) && 512482527734SSukumar Swaminathan (iocb->un.grsp.perr.statLocalError == 512582527734SSukumar Swaminathan IOERR_RCV_BUFFER_TIMEOUT)) { 5126*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Out of posted buffers:", 5127*8f23e9faSHans Rosenfeld sizeof (error_str)); 5128*8f23e9faSHans Rosenfeld iocb->ULPBDECOUNT = 0; 512982527734SSukumar Swaminathan } else if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) && 513082527734SSukumar Swaminathan (iocb->un.grsp.perr.statLocalError == 513182527734SSukumar Swaminathan IOERR_RCV_BUFFER_WAITING)) { 5132*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Buffer waiting:", 5133*8f23e9faSHans Rosenfeld sizeof (error_str)); 5134*8f23e9faSHans Rosenfeld iocb->ULPBDECOUNT = 0; 513582527734SSukumar Swaminathan goto done; 513682527734SSukumar Swaminathan } else if (iocb->ULPSTATUS == IOSTAT_NEED_BUFF_ENTRY) { 5137*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Need Buffer Entry:", 5138*8f23e9faSHans Rosenfeld sizeof (error_str)); 5139*8f23e9faSHans Rosenfeld iocb->ULPBDECOUNT = 0; 514082527734SSukumar Swaminathan goto done; 514182527734SSukumar Swaminathan } else { 5142*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "General error:", 5143*8f23e9faSHans Rosenfeld sizeof (error_str)); 5144291a2b48SSukumar Swaminathan } 5145291a2b48SSukumar Swaminathan 514682527734SSukumar Swaminathan goto failed; 5147291a2b48SSukumar Swaminathan } 5148291a2b48SSukumar Swaminathan 514982527734SSukumar Swaminathan if (hba->flag & FC_HBQ_ENABLED) { 515082527734SSukumar Swaminathan HBQ_INIT_t *hbq; 515182527734SSukumar Swaminathan HBQE_t *hbqE; 515282527734SSukumar Swaminathan uint32_t hbqe_tag; 5153*8f23e9faSHans Rosenfeld uint32_t hbq_id; 5154291a2b48SSukumar Swaminathan 515582527734SSukumar Swaminathan (*UbPosted)--; 5156291a2b48SSukumar Swaminathan 515782527734SSukumar Swaminathan hbqE = (HBQE_t *)iocb; 515882527734SSukumar Swaminathan hbq_id = hbqE->unt.ext.HBQ_tag; 515982527734SSukumar Swaminathan hbqe_tag = hbqE->unt.ext.HBQE_tag; 5160291a2b48SSukumar Swaminathan 516182527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 5162291a2b48SSukumar Swaminathan 516382527734SSukumar Swaminathan if (hbqe_tag >= hbq->HBQ_numEntries) { 5164*8f23e9faSHans Rosenfeld (void) snprintf(error_str, sizeof (error_str), 5165*8f23e9faSHans Rosenfeld "Invalid HBQE iotag=%d:", hbqe_tag); 516682527734SSukumar Swaminathan goto dropped; 516782527734SSukumar Swaminathan } 5168291a2b48SSukumar Swaminathan 516982527734SSukumar Swaminathan mp = hba->sli.sli3.hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag]; 5170291a2b48SSukumar Swaminathan 517182527734SSukumar Swaminathan size = iocb->unsli3.ext_rcv.seq_len; 517282527734SSukumar Swaminathan } else { 517382527734SSukumar Swaminathan bdeAddr = 517482527734SSukumar Swaminathan PADDR(iocb->un.cont64[0].addrHigh, 517582527734SSukumar Swaminathan iocb->un.cont64[0].addrLow); 5176291a2b48SSukumar Swaminathan 517782527734SSukumar Swaminathan /* Check for invalid buffer */ 517882527734SSukumar Swaminathan if (iocb->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID) { 5179*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Invalid buffer:", 5180*8f23e9faSHans Rosenfeld sizeof (error_str)); 518182527734SSukumar Swaminathan goto dropped; 5182291a2b48SSukumar Swaminathan } 5183291a2b48SSukumar Swaminathan 518482527734SSukumar Swaminathan mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr); 5185291a2b48SSukumar Swaminathan 518682527734SSukumar Swaminathan size = iocb->un.rcvseq64.rcvBde.tus.f.bdeSize; 5187291a2b48SSukumar Swaminathan } 5188291a2b48SSukumar Swaminathan 518982527734SSukumar Swaminathan if (!mp) { 5190*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Buffer not mapped:", 5191*8f23e9faSHans Rosenfeld sizeof (error_str)); 519282527734SSukumar Swaminathan goto dropped; 519382527734SSukumar Swaminathan } 5194291a2b48SSukumar Swaminathan 5195b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT 5196b3660a96SSukumar Swaminathan if (mp->dma_handle) { 5197b3660a96SSukumar Swaminathan if (emlxs_fm_check_dma_handle(hba, mp->dma_handle) 5198b3660a96SSukumar Swaminathan != DDI_FM_OK) { 5199b3660a96SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 5200b3660a96SSukumar Swaminathan &emlxs_invalid_dma_handle_msg, 5201*8f23e9faSHans Rosenfeld "handle_rcv_seq: hdl=%p", 5202b3660a96SSukumar Swaminathan mp->dma_handle); 5203b3660a96SSukumar Swaminathan goto dropped; 5204b3660a96SSukumar Swaminathan } 5205b3660a96SSukumar Swaminathan } 5206b3660a96SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5207b3660a96SSukumar Swaminathan 520882527734SSukumar Swaminathan if (!size) { 5209*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Buffer empty:", sizeof (error_str)); 521082527734SSukumar Swaminathan goto dropped; 521182527734SSukumar Swaminathan } 5212291a2b48SSukumar Swaminathan 521382527734SSukumar Swaminathan /* To avoid we drop the broadcast packets */ 521482527734SSukumar Swaminathan if (channelno != FC_IP_RING) { 521582527734SSukumar Swaminathan /* Get virtual port */ 521682527734SSukumar Swaminathan if (hba->flag & FC_NPIV_ENABLED) { 521782527734SSukumar Swaminathan vpi = iocb->unsli3.ext_rcv.vpi; 521882527734SSukumar Swaminathan if (vpi >= hba->vpi_max) { 5219*8f23e9faSHans Rosenfeld (void) snprintf(error_str, sizeof (error_str), 522082527734SSukumar Swaminathan "Invalid VPI=%d:", vpi); 522182527734SSukumar Swaminathan goto dropped; 522282527734SSukumar Swaminathan } 5223291a2b48SSukumar Swaminathan 522482527734SSukumar Swaminathan port = &VPORT(vpi); 522582527734SSukumar Swaminathan } 52264baa2c25SSukumar Swaminathan } 52274baa2c25SSukumar Swaminathan 522882527734SSukumar Swaminathan /* Process request */ 522982527734SSukumar Swaminathan switch (channelno) { 523082527734SSukumar Swaminathan case FC_FCT_RING: 5231*8f23e9faSHans Rosenfeld if (port->mode == MODE_INITIATOR) { 5232*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Target mode disabled:", 5233*8f23e9faSHans Rosenfeld sizeof (error_str)); 5234*8f23e9faSHans Rosenfeld goto dropped; 5235*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT 5236*8f23e9faSHans Rosenfeld } else if (port->mode == MODE_TARGET) { 5237*8f23e9faSHans Rosenfeld (void) emlxs_fct_handle_unsol_req(port, cp, iocbq, mp, 5238*8f23e9faSHans Rosenfeld size); 523982527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 5240*8f23e9faSHans Rosenfeld } else { 5241*8f23e9faSHans Rosenfeld (void) snprintf(error_str, sizeof (error_str), 5242*8f23e9faSHans Rosenfeld "Invalid mode=%x:", port->mode); 5243*8f23e9faSHans Rosenfeld goto dropped; 5244*8f23e9faSHans Rosenfeld } 5245*8f23e9faSHans Rosenfeld break; 5246291a2b48SSukumar Swaminathan 524782527734SSukumar Swaminathan case FC_IP_RING: 5248*8f23e9faSHans Rosenfeld if (port->mode == MODE_INITIATOR) { 5249*8f23e9faSHans Rosenfeld (void) emlxs_ip_handle_unsol_req(port, cp, iocbq, 5250*8f23e9faSHans Rosenfeld mp, size); 5251*8f23e9faSHans Rosenfeld #ifdef SFCT_SUPPORT 5252*8f23e9faSHans Rosenfeld } else if (port->mode == MODE_TARGET) { 5253*8f23e9faSHans Rosenfeld (void) strlcpy(error_str, "Initiator mode disabled:", 5254*8f23e9faSHans Rosenfeld sizeof (error_str)); 5255*8f23e9faSHans Rosenfeld goto dropped; 5256*8f23e9faSHans Rosenfeld #endif /* SFCT_SUPPORT */ 5257*8f23e9faSHans Rosenfeld } else { 5258*8f23e9faSHans Rosenfeld (void) snprintf(error_str, sizeof (error_str), 5259*8f23e9faSHans Rosenfeld "Invalid mode=%x:", port->mode); 5260*8f23e9faSHans Rosenfeld goto dropped; 5261*8f23e9faSHans Rosenfeld } 526282527734SSukumar Swaminathan break; 5263291a2b48SSukumar Swaminathan 526482527734SSukumar Swaminathan case FC_ELS_RING: 5265*8f23e9faSHans Rosenfeld if (port->mode == MODE_INITIATOR) { 526682527734SSukumar Swaminathan (void) emlxs_els_handle_unsol_req(port, cp, iocbq, mp, 526782527734SSukumar Swaminathan size); 526882527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 5269*8f23e9faSHans Rosenfeld } else if (port->mode == MODE_TARGET) { 527082527734SSukumar Swaminathan (void) emlxs_fct_handle_unsol_els(port, cp, iocbq, mp, 527182527734SSukumar Swaminathan size); 527282527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 5273*8f23e9faSHans Rosenfeld } else { 5274*8f23e9faSHans Rosenfeld (void) snprintf(error_str, sizeof (error_str), 5275*8f23e9faSHans Rosenfeld "Invalid mode=%x:", port->mode); 5276*8f23e9faSHans Rosenfeld goto dropped; 5277*8f23e9faSHans Rosenfeld } 527882527734SSukumar Swaminathan break; 5279291a2b48SSukumar Swaminathan 528082527734SSukumar Swaminathan case FC_CT_RING: 528182527734SSukumar Swaminathan (void) emlxs_ct_handle_unsol_req(port, cp, iocbq, mp, size); 528282527734SSukumar Swaminathan break; 528382527734SSukumar Swaminathan } 5284291a2b48SSukumar Swaminathan 528582527734SSukumar Swaminathan goto done; 5286291a2b48SSukumar Swaminathan 528782527734SSukumar Swaminathan dropped: 528882527734SSukumar Swaminathan (*RcvDropped)++; 5289291a2b48SSukumar Swaminathan 529082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 529182527734SSukumar Swaminathan "%s: cmd=%x %s %x %x %x %x", 529282527734SSukumar Swaminathan error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS), 529382527734SSukumar Swaminathan word[4], word[5], word[6], word[7]); 5294291a2b48SSukumar Swaminathan 529582527734SSukumar Swaminathan if (channelno == FC_FCT_RING) { 529682527734SSukumar Swaminathan uint32_t sid; 5297291a2b48SSukumar Swaminathan 5298*8f23e9faSHans Rosenfeld if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { 529982527734SSukumar Swaminathan emlxs_node_t *ndlp; 530082527734SSukumar Swaminathan ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG); 5301*8f23e9faSHans Rosenfeld if (! ndlp) { 5302*8f23e9faSHans Rosenfeld goto done; 5303*8f23e9faSHans Rosenfeld } 530482527734SSukumar Swaminathan sid = ndlp->nlp_DID; 530582527734SSukumar Swaminathan } else { 530682527734SSukumar Swaminathan sid = iocb->un.ulpWord[4] & 0xFFFFFF; 530782527734SSukumar Swaminathan } 5308291a2b48SSukumar Swaminathan 530982527734SSukumar Swaminathan emlxs_send_logo(port, sid); 5310291a2b48SSukumar Swaminathan } 5311291a2b48SSukumar Swaminathan 531282527734SSukumar Swaminathan goto done; 5313291a2b48SSukumar Swaminathan 531482527734SSukumar Swaminathan failed: 531582527734SSukumar Swaminathan (*RcvError)++; 5316291a2b48SSukumar Swaminathan 531782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 531882527734SSukumar Swaminathan "%s: cmd=%x %s %x %x %x %x hba:%x %x", 531982527734SSukumar Swaminathan error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS), 532082527734SSukumar Swaminathan word[4], word[5], word[6], word[7], hba->state, hba->flag); 5321291a2b48SSukumar Swaminathan 532282527734SSukumar Swaminathan done: 5323291a2b48SSukumar Swaminathan 532482527734SSukumar Swaminathan if (hba->flag & FC_HBQ_ENABLED) { 5325*8f23e9faSHans Rosenfeld if (iocb->ULPBDECOUNT) { 5326*8f23e9faSHans Rosenfeld HBQE_t *hbqE; 5327*8f23e9faSHans Rosenfeld uint32_t hbq_id; 5328*8f23e9faSHans Rosenfeld 5329*8f23e9faSHans Rosenfeld hbqE = (HBQE_t *)iocb; 5330*8f23e9faSHans Rosenfeld hbq_id = hbqE->unt.ext.HBQ_tag; 5331*8f23e9faSHans Rosenfeld 5332*8f23e9faSHans Rosenfeld emlxs_update_HBQ_index(hba, hbq_id); 5333*8f23e9faSHans Rosenfeld } 533482527734SSukumar Swaminathan } else { 533582527734SSukumar Swaminathan if (mp) { 5336a9800bebSGarrett D'Amore emlxs_mem_put(hba, buf_type, (void *)mp); 5337291a2b48SSukumar Swaminathan } 5338*8f23e9faSHans Rosenfeld 5339*8f23e9faSHans Rosenfeld if (iocb->ULPBDECOUNT) { 5340*8f23e9faSHans Rosenfeld (void) emlxs_post_buffer(hba, rp, 1); 5341*8f23e9faSHans Rosenfeld } 5342291a2b48SSukumar Swaminathan } 5343291a2b48SSukumar Swaminathan 534482527734SSukumar Swaminathan return (0); 5345291a2b48SSukumar Swaminathan 534682527734SSukumar Swaminathan } /* emlxs_handle_rcv_seq() */ 5347291a2b48SSukumar Swaminathan 5348291a2b48SSukumar Swaminathan 534982527734SSukumar Swaminathan /* EMLXS_CMD_RING_LOCK must be held when calling this function */ 535082527734SSukumar Swaminathan static void 535182527734SSukumar Swaminathan emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 5352291a2b48SSukumar Swaminathan { 535382527734SSukumar Swaminathan emlxs_port_t *port; 535482527734SSukumar Swaminathan IOCB *icmd; 535582527734SSukumar Swaminathan IOCB *iocb; 535682527734SSukumar Swaminathan emlxs_buf_t *sbp; 535782527734SSukumar Swaminathan off_t offset; 535882527734SSukumar Swaminathan uint32_t ringno; 5359291a2b48SSukumar Swaminathan 536082527734SSukumar Swaminathan ringno = rp->ringno; 536182527734SSukumar Swaminathan sbp = iocbq->sbp; 536282527734SSukumar Swaminathan icmd = &iocbq->iocb; 536382527734SSukumar Swaminathan port = iocbq->port; 5364291a2b48SSukumar Swaminathan 536582527734SSukumar Swaminathan HBASTATS.IocbIssued[ringno]++; 5366291a2b48SSukumar Swaminathan 536782527734SSukumar Swaminathan /* Check for ULP pkt request */ 536882527734SSukumar Swaminathan if (sbp) { 536982527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 5370291a2b48SSukumar Swaminathan 537182527734SSukumar Swaminathan if (sbp->node == NULL) { 537282527734SSukumar Swaminathan /* Set node to base node by default */ 537382527734SSukumar Swaminathan iocbq->node = (void *)&port->node_base; 537482527734SSukumar Swaminathan sbp->node = (void *)&port->node_base; 537582527734SSukumar Swaminathan } 5376291a2b48SSukumar Swaminathan 537782527734SSukumar Swaminathan sbp->pkt_flags |= PACKET_IN_CHIPQ; 537882527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 5379291a2b48SSukumar Swaminathan 53801a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&hba->io_active); 5381*8f23e9faSHans Rosenfeld #ifdef NODE_THROTTLE_SUPPORT 5382*8f23e9faSHans Rosenfeld if (sbp->node) { 5383*8f23e9faSHans Rosenfeld atomic_inc_32(&sbp->node->io_active); 5384*8f23e9faSHans Rosenfeld } 5385*8f23e9faSHans Rosenfeld #endif /* NODE_THROTTLE_SUPPORT */ 5386291a2b48SSukumar Swaminathan 538782527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 538882527734SSukumar Swaminathan #ifdef FCT_IO_TRACE 538982527734SSukumar Swaminathan if (sbp->fct_cmd) { 539082527734SSukumar Swaminathan emlxs_fct_io_trace(port, sbp->fct_cmd, 539182527734SSukumar Swaminathan EMLXS_FCT_IOCB_ISSUED); 539282527734SSukumar Swaminathan emlxs_fct_io_trace(port, sbp->fct_cmd, 539382527734SSukumar Swaminathan icmd->ULPCOMMAND); 539482527734SSukumar Swaminathan } 539582527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */ 539682527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 5397291a2b48SSukumar Swaminathan 539882527734SSukumar Swaminathan rp->channelp->hbaSendCmd_sbp++; 539982527734SSukumar Swaminathan iocbq->channel = rp->channelp; 5400291a2b48SSukumar Swaminathan } else { 540182527734SSukumar Swaminathan rp->channelp->hbaSendCmd++; 5402291a2b48SSukumar Swaminathan } 5403291a2b48SSukumar Swaminathan 540482527734SSukumar Swaminathan /* get the next available command ring iocb */ 540582527734SSukumar Swaminathan iocb = 540682527734SSukumar Swaminathan (IOCB *)(((char *)rp->fc_cmdringaddr + 540782527734SSukumar Swaminathan (rp->fc_cmdidx * hba->sli.sli3.iocb_cmd_size))); 5408291a2b48SSukumar Swaminathan 540982527734SSukumar Swaminathan /* Copy the local iocb to the command ring iocb */ 541082527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)icmd, (uint8_t *)iocb, 541182527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size); 5412291a2b48SSukumar Swaminathan 541382527734SSukumar Swaminathan /* DMA sync the command ring iocb for the adapter */ 541482527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)iocb) 541582527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 541682527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 541782527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size, DDI_DMA_SYNC_FORDEV); 5418291a2b48SSukumar Swaminathan 541982527734SSukumar Swaminathan /* 542082527734SSukumar Swaminathan * After this, the sbp / iocb should not be 542182527734SSukumar Swaminathan * accessed in the xmit path. 542282527734SSukumar Swaminathan */ 542382527734SSukumar Swaminathan 542482527734SSukumar Swaminathan /* Free the local iocb if there is no sbp tracking it */ 542582527734SSukumar Swaminathan if (!sbp) { 5426a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_IOCB, (void *)iocbq); 5427291a2b48SSukumar Swaminathan } 5428291a2b48SSukumar Swaminathan 542982527734SSukumar Swaminathan /* update local ring index to next available ring index */ 543082527734SSukumar Swaminathan rp->fc_cmdidx = 543182527734SSukumar Swaminathan (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 5432291a2b48SSukumar Swaminathan 5433291a2b48SSukumar Swaminathan 543482527734SSukumar Swaminathan return; 54354baa2c25SSukumar Swaminathan 543682527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb() */ 5437291a2b48SSukumar Swaminathan 5438291a2b48SSukumar Swaminathan 543982527734SSukumar Swaminathan static void 544082527734SSukumar Swaminathan emlxs_sli3_hba_kill(emlxs_hba_t *hba) 544182527734SSukumar Swaminathan { 544282527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 544382527734SSukumar Swaminathan MAILBOX *swpmb; 544482527734SSukumar Swaminathan MAILBOX *mb2; 544582527734SSukumar Swaminathan MAILBOX *mb1; 544682527734SSukumar Swaminathan uint32_t word0; 544782527734SSukumar Swaminathan uint32_t j; 544882527734SSukumar Swaminathan uint32_t interlock_failed; 544982527734SSukumar Swaminathan uint32_t ha_copy; 545082527734SSukumar Swaminathan uint32_t value; 545182527734SSukumar Swaminathan off_t offset; 545282527734SSukumar Swaminathan uint32_t size; 5453291a2b48SSukumar Swaminathan 545482527734SSukumar Swaminathan /* Perform adapter interlock to kill adapter */ 545582527734SSukumar Swaminathan interlock_failed = 0; 5456291a2b48SSukumar Swaminathan 545782527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 545882527734SSukumar Swaminathan if (hba->flag & FC_INTERLOCKED) { 545982527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5460291a2b48SSukumar Swaminathan 546182527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5462291a2b48SSukumar Swaminathan 546382527734SSukumar Swaminathan return; 546482527734SSukumar Swaminathan } 5465291a2b48SSukumar Swaminathan 546682527734SSukumar Swaminathan j = 0; 546782527734SSukumar Swaminathan while (j++ < 10000) { 546882527734SSukumar Swaminathan if (hba->mbox_queue_flag == 0) { 546982527734SSukumar Swaminathan break; 547082527734SSukumar Swaminathan } 5471291a2b48SSukumar Swaminathan 547282527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5473*8f23e9faSHans Rosenfeld BUSYWAIT_US(100); 547482527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 547582527734SSukumar Swaminathan } 5476291a2b48SSukumar Swaminathan 547782527734SSukumar Swaminathan if (hba->mbox_queue_flag != 0) { 547882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 547982527734SSukumar Swaminathan "Interlock failed. Mailbox busy."); 548082527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 548182527734SSukumar Swaminathan return; 548282527734SSukumar Swaminathan } 5483291a2b48SSukumar Swaminathan 548482527734SSukumar Swaminathan hba->flag |= FC_INTERLOCKED; 548582527734SSukumar Swaminathan hba->mbox_queue_flag = 1; 5486291a2b48SSukumar Swaminathan 548782527734SSukumar Swaminathan /* Disable all host interrupts */ 548882527734SSukumar Swaminathan hba->sli.sli3.hc_copy = 0; 548982527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 549082527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff); 5491291a2b48SSukumar Swaminathan 549282527734SSukumar Swaminathan mb2 = FC_SLIM2_MAILBOX(hba); 549382527734SSukumar Swaminathan mb1 = FC_SLIM1_MAILBOX(hba); 549482527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 5495291a2b48SSukumar Swaminathan 549682527734SSukumar Swaminathan if (!(hba->flag & FC_SLIM2_MODE)) { 549782527734SSukumar Swaminathan goto mode_B; 549882527734SSukumar Swaminathan } 5499291a2b48SSukumar Swaminathan 550082527734SSukumar Swaminathan mode_A: 5501291a2b48SSukumar Swaminathan 550282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 550382527734SSukumar Swaminathan "Attempting SLIM2 Interlock..."); 5504291a2b48SSukumar Swaminathan 550582527734SSukumar Swaminathan interlock_A: 5506291a2b48SSukumar Swaminathan 5507a9800bebSGarrett D'Amore value = 0x55555555; 550882527734SSukumar Swaminathan word0 = 0; 550982527734SSukumar Swaminathan swpmb->mbxCommand = MBX_KILL_BOARD; 551082527734SSukumar Swaminathan swpmb->mbxOwner = OWN_CHIP; 5511291a2b48SSukumar Swaminathan 551282527734SSukumar Swaminathan /* Write value to SLIM */ 551382527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 551482527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0); 5515291a2b48SSukumar Swaminathan 551682527734SSukumar Swaminathan /* Send Kill board request */ 551782527734SSukumar Swaminathan mb2->un.varWords[0] = value; 551882527734SSukumar Swaminathan mb2->mbxCommand = MBX_KILL_BOARD; 551982527734SSukumar Swaminathan mb2->mbxOwner = OWN_CHIP; 5520291a2b48SSukumar Swaminathan 552182527734SSukumar Swaminathan /* Sync the memory */ 552282527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mb2) 552382527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 552482527734SSukumar Swaminathan size = (sizeof (uint32_t) * 2); 5525291a2b48SSukumar Swaminathan 552682527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size); 5527291a2b48SSukumar Swaminathan 552882527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size, 552982527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 5530291a2b48SSukumar Swaminathan 553182527734SSukumar Swaminathan /* interrupt board to do it right away */ 553282527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5533291a2b48SSukumar Swaminathan 553482527734SSukumar Swaminathan /* First wait for command acceptence */ 553582527734SSukumar Swaminathan j = 0; 553682527734SSukumar Swaminathan while (j++ < 1000) { 553782527734SSukumar Swaminathan value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5538291a2b48SSukumar Swaminathan 5539a9800bebSGarrett D'Amore if (value == 0xAAAAAAAA) { 554082527734SSukumar Swaminathan break; 5541291a2b48SSukumar Swaminathan } 5542291a2b48SSukumar Swaminathan 5543*8f23e9faSHans Rosenfeld BUSYWAIT_US(50); 554482527734SSukumar Swaminathan } 5545291a2b48SSukumar Swaminathan 5546a9800bebSGarrett D'Amore if (value == 0xAAAAAAAA) { 554782527734SSukumar Swaminathan /* Now wait for mailbox ownership to clear */ 554882527734SSukumar Swaminathan while (j++ < 10000) { 554982527734SSukumar Swaminathan word0 = 555082527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5551291a2b48SSukumar Swaminathan 555282527734SSukumar Swaminathan if (swpmb->mbxOwner == 0) { 555382527734SSukumar Swaminathan break; 55544baa2c25SSukumar Swaminathan } 555582527734SSukumar Swaminathan 5556*8f23e9faSHans Rosenfeld BUSYWAIT_US(50); 5557291a2b48SSukumar Swaminathan } 5558291a2b48SSukumar Swaminathan 555982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 556082527734SSukumar Swaminathan "Interlock succeeded."); 5561291a2b48SSukumar Swaminathan 556282527734SSukumar Swaminathan goto done; 556382527734SSukumar Swaminathan } 5564291a2b48SSukumar Swaminathan 556582527734SSukumar Swaminathan /* Interlock failed !!! */ 556682527734SSukumar Swaminathan interlock_failed = 1; 5567291a2b48SSukumar Swaminathan 556882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Interlock failed."); 5569291a2b48SSukumar Swaminathan 557082527734SSukumar Swaminathan mode_B: 5571291a2b48SSukumar Swaminathan 557282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 557382527734SSukumar Swaminathan "Attempting SLIM1 Interlock..."); 5574291a2b48SSukumar Swaminathan 557582527734SSukumar Swaminathan interlock_B: 55764baa2c25SSukumar Swaminathan 5577a9800bebSGarrett D'Amore value = 0x55555555; 557882527734SSukumar Swaminathan word0 = 0; 557982527734SSukumar Swaminathan swpmb->mbxCommand = MBX_KILL_BOARD; 558082527734SSukumar Swaminathan swpmb->mbxOwner = OWN_CHIP; 55814baa2c25SSukumar Swaminathan 558282527734SSukumar Swaminathan /* Write KILL BOARD to mailbox */ 558382527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 558482527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb1), word0); 5585291a2b48SSukumar Swaminathan 558682527734SSukumar Swaminathan /* interrupt board to do it right away */ 558782527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5588291a2b48SSukumar Swaminathan 558982527734SSukumar Swaminathan /* First wait for command acceptence */ 559082527734SSukumar Swaminathan j = 0; 559182527734SSukumar Swaminathan while (j++ < 1000) { 559282527734SSukumar Swaminathan value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5593291a2b48SSukumar Swaminathan 5594a9800bebSGarrett D'Amore if (value == 0xAAAAAAAA) { 559582527734SSukumar Swaminathan break; 5596291a2b48SSukumar Swaminathan } 559782527734SSukumar Swaminathan 5598*8f23e9faSHans Rosenfeld BUSYWAIT_US(50); 5599291a2b48SSukumar Swaminathan } 5600291a2b48SSukumar Swaminathan 5601a9800bebSGarrett D'Amore if (value == 0xAAAAAAAA) { 560282527734SSukumar Swaminathan /* Now wait for mailbox ownership to clear */ 560382527734SSukumar Swaminathan while (j++ < 10000) { 560482527734SSukumar Swaminathan word0 = 560582527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5606291a2b48SSukumar Swaminathan 560782527734SSukumar Swaminathan if (swpmb->mbxOwner == 0) { 560882527734SSukumar Swaminathan break; 560982527734SSukumar Swaminathan } 5610291a2b48SSukumar Swaminathan 5611*8f23e9faSHans Rosenfeld BUSYWAIT_US(50); 5612291a2b48SSukumar Swaminathan } 5613291a2b48SSukumar Swaminathan 561482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 561582527734SSukumar Swaminathan "Interlock succeeded."); 5616291a2b48SSukumar Swaminathan 561782527734SSukumar Swaminathan goto done; 561882527734SSukumar Swaminathan } 5619291a2b48SSukumar Swaminathan 562082527734SSukumar Swaminathan /* Interlock failed !!! */ 5621291a2b48SSukumar Swaminathan 562282527734SSukumar Swaminathan /* If this is the first time then try again */ 562382527734SSukumar Swaminathan if (interlock_failed == 0) { 562482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 562582527734SSukumar Swaminathan "Interlock failed. Retrying..."); 5626291a2b48SSukumar Swaminathan 562782527734SSukumar Swaminathan /* Try again */ 562882527734SSukumar Swaminathan interlock_failed = 1; 562982527734SSukumar Swaminathan goto interlock_B; 5630291a2b48SSukumar Swaminathan } 5631291a2b48SSukumar Swaminathan 5632291a2b48SSukumar Swaminathan /* 563382527734SSukumar Swaminathan * Now check for error attention to indicate the board has 563482527734SSukumar Swaminathan * been kiilled 5635291a2b48SSukumar Swaminathan */ 563682527734SSukumar Swaminathan j = 0; 563782527734SSukumar Swaminathan while (j++ < 10000) { 563882527734SSukumar Swaminathan ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 5639bb63f56eSSukumar Swaminathan 564082527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 564182527734SSukumar Swaminathan break; 564282527734SSukumar Swaminathan } 56433be114edSSukumar Swaminathan 5644*8f23e9faSHans Rosenfeld BUSYWAIT_US(50); 564582527734SSukumar Swaminathan } 5646291a2b48SSukumar Swaminathan 564782527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 564882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 564982527734SSukumar Swaminathan "Interlock failed. Board killed."); 565082527734SSukumar Swaminathan } else { 565182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 565282527734SSukumar Swaminathan "Interlock failed. Board not killed."); 565382527734SSukumar Swaminathan } 5654291a2b48SSukumar Swaminathan 565582527734SSukumar Swaminathan done: 5656291a2b48SSukumar Swaminathan 565782527734SSukumar Swaminathan hba->mbox_queue_flag = 0; 5658291a2b48SSukumar Swaminathan 565982527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5660291a2b48SSukumar Swaminathan 566182527734SSukumar Swaminathan #ifdef FMA_SUPPORT 566282527734SSukumar Swaminathan /* Access handle validation */ 566382527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 566482527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 566582527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5666291a2b48SSukumar Swaminathan 566782527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5668291a2b48SSukumar Swaminathan 566982527734SSukumar Swaminathan return; 5670291a2b48SSukumar Swaminathan 567182527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill() */ 5672291a2b48SSukumar Swaminathan 5673291a2b48SSukumar Swaminathan 567482527734SSukumar Swaminathan static void 567582527734SSukumar Swaminathan emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba) 567682527734SSukumar Swaminathan { 567782527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 567882527734SSukumar Swaminathan MAILBOX *swpmb; 567982527734SSukumar Swaminathan MAILBOX *mb2; 568082527734SSukumar Swaminathan MAILBOX *mb1; 568182527734SSukumar Swaminathan uint32_t word0; 568282527734SSukumar Swaminathan off_t offset; 568382527734SSukumar Swaminathan uint32_t j; 568482527734SSukumar Swaminathan uint32_t value; 568582527734SSukumar Swaminathan uint32_t size; 5686291a2b48SSukumar Swaminathan 568782527734SSukumar Swaminathan /* Disable all host interrupts */ 568882527734SSukumar Swaminathan hba->sli.sli3.hc_copy = 0; 568982527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 569082527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff); 5691291a2b48SSukumar Swaminathan 569282527734SSukumar Swaminathan mb2 = FC_SLIM2_MAILBOX(hba); 569382527734SSukumar Swaminathan mb1 = FC_SLIM1_MAILBOX(hba); 569482527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 5695291a2b48SSukumar Swaminathan 5696a9800bebSGarrett D'Amore value = 0x55555555; 569782527734SSukumar Swaminathan word0 = 0; 569882527734SSukumar Swaminathan swpmb->mbxCommand = MBX_KILL_BOARD; 569982527734SSukumar Swaminathan swpmb->mbxOwner = OWN_CHIP; 5700291a2b48SSukumar Swaminathan 570182527734SSukumar Swaminathan /* Write value to SLIM */ 570282527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 570382527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0); 5704291a2b48SSukumar Swaminathan 570582527734SSukumar Swaminathan /* Send Kill board request */ 570682527734SSukumar Swaminathan mb2->un.varWords[0] = value; 570782527734SSukumar Swaminathan mb2->mbxCommand = MBX_KILL_BOARD; 570882527734SSukumar Swaminathan mb2->mbxOwner = OWN_CHIP; 5709291a2b48SSukumar Swaminathan 571082527734SSukumar Swaminathan /* Sync the memory */ 571182527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mb2) 571282527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 571382527734SSukumar Swaminathan size = (sizeof (uint32_t) * 2); 5714291a2b48SSukumar Swaminathan 571582527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size); 5716291a2b48SSukumar Swaminathan 571782527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size, 571882527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 5719291a2b48SSukumar Swaminathan 572082527734SSukumar Swaminathan /* interrupt board to do it right away */ 572182527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5722291a2b48SSukumar Swaminathan 572382527734SSukumar Swaminathan /* First wait for command acceptence */ 572482527734SSukumar Swaminathan j = 0; 572582527734SSukumar Swaminathan while (j++ < 1000) { 572682527734SSukumar Swaminathan value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5727291a2b48SSukumar Swaminathan 5728a9800bebSGarrett D'Amore if (value == 0xAAAAAAAA) { 572982527734SSukumar Swaminathan break; 573082527734SSukumar Swaminathan } 5731*8f23e9faSHans Rosenfeld BUSYWAIT_US(50); 573282527734SSukumar Swaminathan } 5733a9800bebSGarrett D'Amore if (value == 0xAAAAAAAA) { 573482527734SSukumar Swaminathan /* Now wait for mailbox ownership to clear */ 573582527734SSukumar Swaminathan while (j++ < 10000) { 573682527734SSukumar Swaminathan word0 = 573782527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 573882527734SSukumar Swaminathan if (swpmb->mbxOwner == 0) { 573982527734SSukumar Swaminathan break; 5740291a2b48SSukumar Swaminathan } 5741*8f23e9faSHans Rosenfeld BUSYWAIT_US(50); 5742291a2b48SSukumar Swaminathan } 574382527734SSukumar Swaminathan goto done; 574482527734SSukumar Swaminathan } 5745291a2b48SSukumar Swaminathan 574682527734SSukumar Swaminathan done: 574782527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5748291a2b48SSukumar Swaminathan 574982527734SSukumar Swaminathan #ifdef FMA_SUPPORT 575082527734SSukumar Swaminathan /* Access handle validation */ 575182527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 575282527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 575382527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 575482527734SSukumar Swaminathan return; 5755291a2b48SSukumar Swaminathan 575682527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill4quiesce */ 5757291a2b48SSukumar Swaminathan 5758291a2b48SSukumar Swaminathan 5759291a2b48SSukumar Swaminathan 5760291a2b48SSukumar Swaminathan 576182527734SSukumar Swaminathan /* 576282527734SSukumar Swaminathan * emlxs_handle_mb_event 576382527734SSukumar Swaminathan * 576482527734SSukumar Swaminathan * Description: Process a Mailbox Attention. 576582527734SSukumar Swaminathan * Called from host_interrupt to process MBATT 576682527734SSukumar Swaminathan * 576782527734SSukumar Swaminathan * Returns: 576882527734SSukumar Swaminathan * 576982527734SSukumar Swaminathan */ 577082527734SSukumar Swaminathan static uint32_t 577182527734SSukumar Swaminathan emlxs_handle_mb_event(emlxs_hba_t *hba) 577282527734SSukumar Swaminathan { 577382527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 577482527734SSukumar Swaminathan MAILBOX *mb; 577582527734SSukumar Swaminathan MAILBOX *swpmb; 577682527734SSukumar Swaminathan MAILBOX *mbox; 5777a9800bebSGarrett D'Amore MAILBOXQ *mbq = NULL; 577882527734SSukumar Swaminathan volatile uint32_t word0; 577982527734SSukumar Swaminathan MATCHMAP *mbox_bp; 578082527734SSukumar Swaminathan off_t offset; 578182527734SSukumar Swaminathan uint32_t i; 578282527734SSukumar Swaminathan int rc; 578382527734SSukumar Swaminathan 578482527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 5785291a2b48SSukumar Swaminathan 5786a9800bebSGarrett D'Amore mutex_enter(&EMLXS_PORT_LOCK); 578782527734SSukumar Swaminathan switch (hba->mbox_queue_flag) { 578882527734SSukumar Swaminathan case 0: 578982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, 579082527734SSukumar Swaminathan "No mailbox active."); 5791a9800bebSGarrett D'Amore 5792a9800bebSGarrett D'Amore mutex_exit(&EMLXS_PORT_LOCK); 579382527734SSukumar Swaminathan return (0); 5794291a2b48SSukumar Swaminathan 579582527734SSukumar Swaminathan case MBX_POLL: 5796291a2b48SSukumar Swaminathan 579782527734SSukumar Swaminathan /* Mark mailbox complete, this should wake up any polling */ 579882527734SSukumar Swaminathan /* threads. This can happen if interrupts are enabled while */ 579982527734SSukumar Swaminathan /* a polled mailbox command is outstanding. If we don't set */ 580082527734SSukumar Swaminathan /* MBQ_COMPLETED here, the polling thread may wait until */ 580182527734SSukumar Swaminathan /* timeout error occurs */ 5802291a2b48SSukumar Swaminathan 580382527734SSukumar Swaminathan mutex_enter(&EMLXS_MBOX_LOCK); 580482527734SSukumar Swaminathan mbq = (MAILBOXQ *)hba->mbox_mbq; 580582527734SSukumar Swaminathan if (mbq) { 5806a9800bebSGarrett D'Amore port = (emlxs_port_t *)mbq->port; 580782527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 580882527734SSukumar Swaminathan "Mailbox event. Completing Polled command."); 580982527734SSukumar Swaminathan mbq->flag |= MBQ_COMPLETED; 581082527734SSukumar Swaminathan } 5811a9800bebSGarrett D'Amore mutex_exit(&EMLXS_MBOX_LOCK); 5812291a2b48SSukumar Swaminathan 5813a9800bebSGarrett D'Amore mutex_exit(&EMLXS_PORT_LOCK); 581482527734SSukumar Swaminathan return (0); 5815291a2b48SSukumar Swaminathan 581682527734SSukumar Swaminathan case MBX_SLEEP: 581782527734SSukumar Swaminathan case MBX_NOWAIT: 5818a9800bebSGarrett D'Amore /* Check mbox_timer, it acts as a service flag too */ 5819a9800bebSGarrett D'Amore /* The first to service the mbox queue will clear the timer */ 5820a9800bebSGarrett D'Amore if (hba->mbox_timer) { 5821a9800bebSGarrett D'Amore hba->mbox_timer = 0; 5822a9800bebSGarrett D'Amore 5823a9800bebSGarrett D'Amore mutex_enter(&EMLXS_MBOX_LOCK); 5824a9800bebSGarrett D'Amore mbq = (MAILBOXQ *)hba->mbox_mbq; 5825a9800bebSGarrett D'Amore mutex_exit(&EMLXS_MBOX_LOCK); 5826a9800bebSGarrett D'Amore } 5827a9800bebSGarrett D'Amore 5828a9800bebSGarrett D'Amore if (!mbq) { 5829a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5830a9800bebSGarrett D'Amore "Mailbox event. No service required."); 5831a9800bebSGarrett D'Amore mutex_exit(&EMLXS_PORT_LOCK); 5832a9800bebSGarrett D'Amore return (0); 5833a9800bebSGarrett D'Amore } 5834a9800bebSGarrett D'Amore 583582527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 5836a9800bebSGarrett D'Amore mutex_exit(&EMLXS_PORT_LOCK); 583782527734SSukumar Swaminathan break; 5838291a2b48SSukumar Swaminathan 583982527734SSukumar Swaminathan default: 584082527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg, 584182527734SSukumar Swaminathan "Invalid Mailbox flag (%x)."); 5842a9800bebSGarrett D'Amore 5843a9800bebSGarrett D'Amore mutex_exit(&EMLXS_PORT_LOCK); 584482527734SSukumar Swaminathan return (0); 584582527734SSukumar Swaminathan } 5846291a2b48SSukumar Swaminathan 5847a9800bebSGarrett D'Amore /* Set port context */ 5848a9800bebSGarrett D'Amore port = (emlxs_port_t *)mbq->port; 5849a9800bebSGarrett D'Amore 585082527734SSukumar Swaminathan /* Get first word of mailbox */ 585182527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 585282527734SSukumar Swaminathan mbox = FC_SLIM2_MAILBOX(hba); 585382527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mbox) 585482527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5855291a2b48SSukumar Swaminathan 585682527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 585782527734SSukumar Swaminathan sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 585882527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 585982527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 586082527734SSukumar Swaminathan } else { 586182527734SSukumar Swaminathan mbox = FC_SLIM1_MAILBOX(hba); 586282527734SSukumar Swaminathan word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 586382527734SSukumar Swaminathan } 5864291a2b48SSukumar Swaminathan 586582527734SSukumar Swaminathan i = 0; 586682527734SSukumar Swaminathan while (swpmb->mbxOwner == OWN_CHIP) { 586782527734SSukumar Swaminathan if (i++ > 10000) { 586882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, 586982527734SSukumar Swaminathan "OWN_CHIP: %s: status=%x", 587082527734SSukumar Swaminathan emlxs_mb_cmd_xlate(swpmb->mbxCommand), 587182527734SSukumar Swaminathan swpmb->mbxStatus); 5872291a2b48SSukumar Swaminathan 587382527734SSukumar Swaminathan return (1); 587482527734SSukumar Swaminathan } 5875291a2b48SSukumar Swaminathan 587682527734SSukumar Swaminathan /* Get first word of mailbox */ 587782527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 587882527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 587982527734SSukumar Swaminathan offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 588082527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 588182527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 588282527734SSukumar Swaminathan } else { 588382527734SSukumar Swaminathan word0 = 588482527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 588582527734SSukumar Swaminathan } 5886a9800bebSGarrett D'Amore } 5887291a2b48SSukumar Swaminathan 588882527734SSukumar Swaminathan /* Now that we are the owner, DMA Sync entire mailbox if needed */ 588982527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 589082527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 589182527734SSukumar Swaminathan MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); 5892291a2b48SSukumar Swaminathan 589382527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb, 589482527734SSukumar Swaminathan MAILBOX_CMD_BSIZE); 589582527734SSukumar Swaminathan } else { 589682527734SSukumar Swaminathan READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox, 589782527734SSukumar Swaminathan MAILBOX_CMD_WSIZE); 589882527734SSukumar Swaminathan } 5899291a2b48SSukumar Swaminathan 590082527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 590182527734SSukumar Swaminathan if (mbq->extbuf) { 590282527734SSukumar Swaminathan uint32_t *mbox_ext = 590382527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + MBOX_EXTENSION_OFFSET); 590482527734SSukumar Swaminathan off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 5905291a2b48SSukumar Swaminathan 590682527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 590782527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 590882527734SSukumar Swaminathan offset_ext, mbq->extsize, 590982527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 591082527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox_ext, 591182527734SSukumar Swaminathan (uint8_t *)mbq->extbuf, mbq->extsize); 591282527734SSukumar Swaminathan } else { 591382527734SSukumar Swaminathan READ_SLIM_COPY(hba, (uint32_t *)mbq->extbuf, 591482527734SSukumar Swaminathan mbox_ext, (mbq->extsize / 4)); 5915291a2b48SSukumar Swaminathan } 591682527734SSukumar Swaminathan } 591782527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 5918291a2b48SSukumar Swaminathan 59194baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 592082527734SSukumar Swaminathan if (!(hba->flag & FC_SLIM2_MODE)) { 592182527734SSukumar Swaminathan /* Access handle validation */ 592282527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 592382527734SSukumar Swaminathan } 59244baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5925291a2b48SSukumar Swaminathan 592682527734SSukumar Swaminathan /* Now sync the memory buffer if one was used */ 592782527734SSukumar Swaminathan if (mbq->bp) { 592882527734SSukumar Swaminathan mbox_bp = (MATCHMAP *)mbq->bp; 592982527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size, 593082527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 593182527734SSukumar Swaminathan } 5932291a2b48SSukumar Swaminathan 593382527734SSukumar Swaminathan /* Mailbox has been completely received at this point */ 5934291a2b48SSukumar Swaminathan 593582527734SSukumar Swaminathan if (mb->mbxCommand == MBX_HEARTBEAT) { 593682527734SSukumar Swaminathan hba->heartbeat_active = 0; 593782527734SSukumar Swaminathan goto done; 5938291a2b48SSukumar Swaminathan } 5939291a2b48SSukumar Swaminathan 594082527734SSukumar Swaminathan if (hba->mbox_queue_flag == MBX_SLEEP) { 594182527734SSukumar Swaminathan if (swpmb->mbxCommand != MBX_DOWN_LOAD && 594282527734SSukumar Swaminathan swpmb->mbxCommand != MBX_DUMP_MEMORY) { 594382527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 594482527734SSukumar Swaminathan "Received. %s: status=%x Sleep.", 594582527734SSukumar Swaminathan emlxs_mb_cmd_xlate(swpmb->mbxCommand), 594682527734SSukumar Swaminathan swpmb->mbxStatus); 5947291a2b48SSukumar Swaminathan } 594882527734SSukumar Swaminathan } else { 594982527734SSukumar Swaminathan if (swpmb->mbxCommand != MBX_DOWN_LOAD && 595082527734SSukumar Swaminathan swpmb->mbxCommand != MBX_DUMP_MEMORY) { 595182527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 595282527734SSukumar Swaminathan "Completed. %s: status=%x", 595382527734SSukumar Swaminathan emlxs_mb_cmd_xlate(swpmb->mbxCommand), 595482527734SSukumar Swaminathan swpmb->mbxStatus); 5955291a2b48SSukumar Swaminathan } 595682527734SSukumar Swaminathan } 5957291a2b48SSukumar Swaminathan 595882527734SSukumar Swaminathan /* Filter out passthru mailbox */ 595982527734SSukumar Swaminathan if (mbq->flag & MBQ_PASSTHRU) { 596082527734SSukumar Swaminathan goto done; 596182527734SSukumar Swaminathan } 5962291a2b48SSukumar Swaminathan 596382527734SSukumar Swaminathan if (mb->mbxStatus) { 596482527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 596582527734SSukumar Swaminathan "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand), 596682527734SSukumar Swaminathan (uint32_t)mb->mbxStatus); 596782527734SSukumar Swaminathan } 5968291a2b48SSukumar Swaminathan 596982527734SSukumar Swaminathan if (mbq->mbox_cmpl) { 597082527734SSukumar Swaminathan rc = (mbq->mbox_cmpl)(hba, mbq); 597182527734SSukumar Swaminathan /* If mbox was retried, return immediately */ 597282527734SSukumar Swaminathan if (rc) { 597382527734SSukumar Swaminathan return (0); 597482527734SSukumar Swaminathan } 597582527734SSukumar Swaminathan } 5976291a2b48SSukumar Swaminathan 597782527734SSukumar Swaminathan done: 5978291a2b48SSukumar Swaminathan 597982527734SSukumar Swaminathan /* Clean up the mailbox area */ 598082527734SSukumar Swaminathan emlxs_mb_fini(hba, mb, mb->mbxStatus); 598182527734SSukumar Swaminathan 598282527734SSukumar Swaminathan mbq = (MAILBOXQ *)emlxs_mb_get(hba); 598382527734SSukumar Swaminathan if (mbq) { 598482527734SSukumar Swaminathan /* Attempt to send pending mailboxes */ 598582527734SSukumar Swaminathan rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 598682527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 5987a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 5988291a2b48SSukumar Swaminathan } 598982527734SSukumar Swaminathan } 599082527734SSukumar Swaminathan return (0); 5991291a2b48SSukumar Swaminathan 599282527734SSukumar Swaminathan } /* emlxs_handle_mb_event() */ 5993291a2b48SSukumar Swaminathan 5994291a2b48SSukumar Swaminathan 5995*8f23e9faSHans Rosenfeld static void 599682527734SSukumar Swaminathan emlxs_sli3_timer(emlxs_hba_t *hba) 599782527734SSukumar Swaminathan { 599882527734SSukumar Swaminathan /* Perform SLI3 level timer checks */ 5999291a2b48SSukumar Swaminathan 600082527734SSukumar Swaminathan emlxs_sli3_timer_check_mbox(hba); 6001291a2b48SSukumar Swaminathan 600282527734SSukumar Swaminathan } /* emlxs_sli3_timer() */ 6003291a2b48SSukumar Swaminathan 600482527734SSukumar Swaminathan 600582527734SSukumar Swaminathan static void 600682527734SSukumar Swaminathan emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba) 6007291a2b48SSukumar Swaminathan { 6008291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 6009291a2b48SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 601082527734SSukumar Swaminathan MAILBOX *mb = NULL; 6011291a2b48SSukumar Swaminathan uint32_t word0; 6012291a2b48SSukumar Swaminathan uint32_t offset; 6013291a2b48SSukumar Swaminathan uint32_t ha_copy = 0; 6014291a2b48SSukumar Swaminathan 6015291a2b48SSukumar Swaminathan if (!cfg[CFG_TIMEOUT_ENABLE].current) { 6016291a2b48SSukumar Swaminathan return; 6017291a2b48SSukumar Swaminathan } 6018291a2b48SSukumar Swaminathan 6019291a2b48SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 6020291a2b48SSukumar Swaminathan 6021291a2b48SSukumar Swaminathan /* Return if timer hasn't expired */ 6022291a2b48SSukumar Swaminathan if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) { 6023291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 6024291a2b48SSukumar Swaminathan return; 6025291a2b48SSukumar Swaminathan } 6026291a2b48SSukumar Swaminathan 6027291a2b48SSukumar Swaminathan /* Mailbox timed out, first check for error attention */ 6028291a2b48SSukumar Swaminathan ha_copy = emlxs_check_attention(hba); 6029291a2b48SSukumar Swaminathan 6030291a2b48SSukumar Swaminathan if (ha_copy & HA_ERATT) { 6031a9800bebSGarrett D'Amore hba->mbox_timer = 0; 6032291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 6033291a2b48SSukumar Swaminathan emlxs_handle_ff_error(hba); 6034291a2b48SSukumar Swaminathan return; 6035291a2b48SSukumar Swaminathan } 6036291a2b48SSukumar Swaminathan 6037291a2b48SSukumar Swaminathan if (hba->mbox_queue_flag) { 6038291a2b48SSukumar Swaminathan /* Get first word of mailbox */ 6039291a2b48SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 6040291a2b48SSukumar Swaminathan mb = FC_SLIM2_MAILBOX(hba); 604182527734SSukumar Swaminathan offset = 604282527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)mb) - (uint64_t) 604382527734SSukumar Swaminathan ((unsigned long)hba->sli.sli3.slim2.virt)); 6044291a2b48SSukumar Swaminathan 604582527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 604682527734SSukumar Swaminathan offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 6047291a2b48SSukumar Swaminathan word0 = *((volatile uint32_t *)mb); 604882527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 6049291a2b48SSukumar Swaminathan } else { 6050291a2b48SSukumar Swaminathan mb = FC_SLIM1_MAILBOX(hba); 6051291a2b48SSukumar Swaminathan word0 = 6052291a2b48SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb)); 60534baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 60544baa2c25SSukumar Swaminathan /* Access handle validation */ 605582527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, 605682527734SSukumar Swaminathan hba->sli.sli3.slim_acc_handle); 60574baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6058291a2b48SSukumar Swaminathan } 6059291a2b48SSukumar Swaminathan 6060291a2b48SSukumar Swaminathan mb = (MAILBOX *)&word0; 6061291a2b48SSukumar Swaminathan 6062291a2b48SSukumar Swaminathan /* Check if mailbox has actually completed */ 6063291a2b48SSukumar Swaminathan if (mb->mbxOwner == OWN_HOST) { 6064291a2b48SSukumar Swaminathan /* Read host attention register to determine */ 6065291a2b48SSukumar Swaminathan /* interrupt source */ 6066291a2b48SSukumar Swaminathan uint32_t ha_copy = emlxs_check_attention(hba); 6067291a2b48SSukumar Swaminathan 6068291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 6069291a2b48SSukumar Swaminathan "Mailbox attention missed: %s. Forcing event. " 6070291a2b48SSukumar Swaminathan "hc=%x ha=%x", emlxs_mb_cmd_xlate(mb->mbxCommand), 607182527734SSukumar Swaminathan hba->sli.sli3.hc_copy, ha_copy); 6072291a2b48SSukumar Swaminathan 6073291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 6074291a2b48SSukumar Swaminathan 6075291a2b48SSukumar Swaminathan (void) emlxs_handle_mb_event(hba); 6076291a2b48SSukumar Swaminathan 6077291a2b48SSukumar Swaminathan return; 6078291a2b48SSukumar Swaminathan } 6079291a2b48SSukumar Swaminathan 6080a9800bebSGarrett D'Amore /* The first to service the mbox queue will clear the timer */ 6081a9800bebSGarrett D'Amore /* We will service the mailbox here */ 6082a9800bebSGarrett D'Amore hba->mbox_timer = 0; 6083a9800bebSGarrett D'Amore 6084a9800bebSGarrett D'Amore mutex_enter(&EMLXS_MBOX_LOCK); 6085a9800bebSGarrett D'Amore mb = (MAILBOX *)hba->mbox_mbq; 6086a9800bebSGarrett D'Amore mutex_exit(&EMLXS_MBOX_LOCK); 6087291a2b48SSukumar Swaminathan } 6088291a2b48SSukumar Swaminathan 608982527734SSukumar Swaminathan if (mb) { 609082527734SSukumar Swaminathan switch (hba->mbox_queue_flag) { 609182527734SSukumar Swaminathan case MBX_NOWAIT: 609282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 609382527734SSukumar Swaminathan "%s: Nowait.", 609482527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand)); 609582527734SSukumar Swaminathan break; 6096291a2b48SSukumar Swaminathan 609782527734SSukumar Swaminathan case MBX_SLEEP: 609882527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 609982527734SSukumar Swaminathan "%s: mb=%p Sleep.", 610082527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), 610182527734SSukumar Swaminathan mb); 610282527734SSukumar Swaminathan break; 6103291a2b48SSukumar Swaminathan 610482527734SSukumar Swaminathan case MBX_POLL: 610582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 610682527734SSukumar Swaminathan "%s: mb=%p Polled.", 610782527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), 610882527734SSukumar Swaminathan mb); 610982527734SSukumar Swaminathan break; 6110291a2b48SSukumar Swaminathan 611182527734SSukumar Swaminathan default: 611282527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 611382527734SSukumar Swaminathan "%s: mb=%p (%d).", 611482527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), 611582527734SSukumar Swaminathan mb, hba->mbox_queue_flag); 611682527734SSukumar Swaminathan break; 611782527734SSukumar Swaminathan } 611882527734SSukumar Swaminathan } else { 6119291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL); 6120291a2b48SSukumar Swaminathan } 6121291a2b48SSukumar Swaminathan 6122291a2b48SSukumar Swaminathan hba->flag |= FC_MBOX_TIMEOUT; 612382527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR); 6124291a2b48SSukumar Swaminathan 6125291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 6126291a2b48SSukumar Swaminathan 6127291a2b48SSukumar Swaminathan /* Perform mailbox cleanup */ 6128291a2b48SSukumar Swaminathan /* This will wake any sleeping or polling threads */ 6129291a2b48SSukumar Swaminathan emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 6130291a2b48SSukumar Swaminathan 6131291a2b48SSukumar Swaminathan /* Trigger adapter shutdown */ 6132bb63f56eSSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); 6133291a2b48SSukumar Swaminathan 6134291a2b48SSukumar Swaminathan return; 6135291a2b48SSukumar Swaminathan 613682527734SSukumar Swaminathan } /* emlxs_sli3_timer_check_mbox() */ 6137291a2b48SSukumar Swaminathan 6138291a2b48SSukumar Swaminathan 6139291a2b48SSukumar Swaminathan /* 6140291a2b48SSukumar Swaminathan * emlxs_mb_config_port Issue a CONFIG_PORT mailbox command 6141291a2b48SSukumar Swaminathan */ 614282527734SSukumar Swaminathan static uint32_t 614382527734SSukumar Swaminathan emlxs_mb_config_port(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t sli_mode, 6144291a2b48SSukumar Swaminathan uint32_t hbainit) 6145291a2b48SSukumar Swaminathan { 614682527734SSukumar Swaminathan MAILBOX *mb = (MAILBOX *)mbq; 6147291a2b48SSukumar Swaminathan emlxs_vpd_t *vpd = &VPD; 6148291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 6149291a2b48SSukumar Swaminathan emlxs_config_t *cfg; 6150291a2b48SSukumar Swaminathan RING *rp; 6151291a2b48SSukumar Swaminathan uint64_t pcb; 6152291a2b48SSukumar Swaminathan uint64_t mbx; 6153291a2b48SSukumar Swaminathan uint64_t hgp; 6154291a2b48SSukumar Swaminathan uint64_t pgp; 6155291a2b48SSukumar Swaminathan uint64_t rgp; 6156291a2b48SSukumar Swaminathan MAILBOX *mbox; 6157291a2b48SSukumar Swaminathan SLIM2 *slim; 6158291a2b48SSukumar Swaminathan SLI2_RDSC *rdsc; 6159291a2b48SSukumar Swaminathan uint64_t offset; 6160291a2b48SSukumar Swaminathan uint32_t Laddr; 6161291a2b48SSukumar Swaminathan uint32_t i; 6162291a2b48SSukumar Swaminathan 6163291a2b48SSukumar Swaminathan cfg = &CFG; 6164291a2b48SSukumar Swaminathan bzero((void *)mb, MAILBOX_CMD_BSIZE); 6165291a2b48SSukumar Swaminathan mbox = NULL; 6166291a2b48SSukumar Swaminathan slim = NULL; 6167291a2b48SSukumar Swaminathan 6168291a2b48SSukumar Swaminathan mb->mbxCommand = MBX_CONFIG_PORT; 6169291a2b48SSukumar Swaminathan mb->mbxOwner = OWN_HOST; 617082527734SSukumar Swaminathan mbq->mbox_cmpl = NULL; 6171291a2b48SSukumar Swaminathan 6172291a2b48SSukumar Swaminathan mb->un.varCfgPort.pcbLen = sizeof (PCB); 6173291a2b48SSukumar Swaminathan mb->un.varCfgPort.hbainit[0] = hbainit; 6174291a2b48SSukumar Swaminathan 617582527734SSukumar Swaminathan pcb = hba->sli.sli3.slim2.phys + 617682527734SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->pcb)); 617782527734SSukumar Swaminathan mb->un.varCfgPort.pcbLow = PADDR_LO(pcb); 617882527734SSukumar Swaminathan mb->un.varCfgPort.pcbHigh = PADDR_HI(pcb); 6179291a2b48SSukumar Swaminathan 6180291a2b48SSukumar Swaminathan /* Set Host pointers in SLIM flag */ 6181291a2b48SSukumar Swaminathan mb->un.varCfgPort.hps = 1; 6182291a2b48SSukumar Swaminathan 6183291a2b48SSukumar Swaminathan /* Initialize hba structure for assumed default SLI2 mode */ 6184291a2b48SSukumar Swaminathan /* If config port succeeds, then we will update it then */ 6185291a2b48SSukumar Swaminathan hba->sli_mode = sli_mode; 618682527734SSukumar Swaminathan hba->vpi_max = 0; 6187291a2b48SSukumar Swaminathan hba->flag &= ~FC_NPIV_ENABLED; 6188291a2b48SSukumar Swaminathan 618982527734SSukumar Swaminathan if (sli_mode == EMLXS_HBA_SLI3_MODE) { 6190291a2b48SSukumar Swaminathan mb->un.varCfgPort.sli_mode = EMLXS_HBA_SLI3_MODE; 6191291a2b48SSukumar Swaminathan mb->un.varCfgPort.cerbm = 1; 6192291a2b48SSukumar Swaminathan mb->un.varCfgPort.max_hbq = EMLXS_NUM_HBQ; 6193291a2b48SSukumar Swaminathan 6194291a2b48SSukumar Swaminathan if (cfg[CFG_NPIV_ENABLE].current) { 6195291a2b48SSukumar Swaminathan if (vpd->feaLevelHigh >= 0x09) { 6196291a2b48SSukumar Swaminathan if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 6197291a2b48SSukumar Swaminathan mb->un.varCfgPort.vpi_max = 6198291a2b48SSukumar Swaminathan MAX_VPORTS - 1; 6199291a2b48SSukumar Swaminathan } else { 6200291a2b48SSukumar Swaminathan mb->un.varCfgPort.vpi_max = 6201291a2b48SSukumar Swaminathan MAX_VPORTS_LIMITED - 1; 6202291a2b48SSukumar Swaminathan } 6203291a2b48SSukumar Swaminathan 6204291a2b48SSukumar Swaminathan mb->un.varCfgPort.cmv = 1; 6205291a2b48SSukumar Swaminathan } else { 6206291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 6207291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 6208291a2b48SSukumar Swaminathan "CFGPORT: Firmware does not support NPIV. " 6209291a2b48SSukumar Swaminathan "level=%d", vpd->feaLevelHigh); 6210291a2b48SSukumar Swaminathan } 6211291a2b48SSukumar Swaminathan 6212291a2b48SSukumar Swaminathan } 6213291a2b48SSukumar Swaminathan } 6214291a2b48SSukumar Swaminathan 6215291a2b48SSukumar Swaminathan /* 6216291a2b48SSukumar Swaminathan * Now setup pcb 6217291a2b48SSukumar Swaminathan */ 621882527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.type = TYPE_NATIVE_SLI2; 621982527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2; 622082527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.maxRing = 622182527734SSukumar Swaminathan (hba->sli.sli3.ring_count - 1); 622282527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mailBoxSize = 6223291a2b48SSukumar Swaminathan sizeof (MAILBOX) + MBOX_EXTENSION_SIZE; 6224291a2b48SSukumar Swaminathan 622582527734SSukumar Swaminathan mbx = hba->sli.sli3.slim2.phys + 622682527734SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->mbx)); 622782527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrHigh = PADDR_HI(mbx); 622882527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrLow = PADDR_LO(mbx); 6229291a2b48SSukumar Swaminathan 6230291a2b48SSukumar Swaminathan 6231291a2b48SSukumar Swaminathan /* 6232291a2b48SSukumar Swaminathan * Set up HGP - Port Memory 6233291a2b48SSukumar Swaminathan * 6234291a2b48SSukumar Swaminathan * CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80 6235291a2b48SSukumar Swaminathan * RR0Get 0xc4 0x84 6236291a2b48SSukumar Swaminathan * CR1Put 0xc8 0x88 6237291a2b48SSukumar Swaminathan * RR1Get 0xcc 0x8c 6238291a2b48SSukumar Swaminathan * CR2Put 0xd0 0x90 6239291a2b48SSukumar Swaminathan * RR2Get 0xd4 0x94 6240291a2b48SSukumar Swaminathan * CR3Put 0xd8 0x98 6241291a2b48SSukumar Swaminathan * RR3Get 0xdc 0x9c 6242291a2b48SSukumar Swaminathan * 6243291a2b48SSukumar Swaminathan * Reserved 0xa0-0xbf 6244291a2b48SSukumar Swaminathan * 6245291a2b48SSukumar Swaminathan * If HBQs configured: 6246291a2b48SSukumar Swaminathan * HBQ 0 Put ptr 0xc0 6247291a2b48SSukumar Swaminathan * HBQ 1 Put ptr 0xc4 6248291a2b48SSukumar Swaminathan * HBQ 2 Put ptr 0xc8 6249291a2b48SSukumar Swaminathan * ... 6250291a2b48SSukumar Swaminathan * HBQ(M-1)Put Pointer 0xc0+(M-1)*4 6251291a2b48SSukumar Swaminathan */ 6252291a2b48SSukumar Swaminathan 6253291a2b48SSukumar Swaminathan if (sli_mode >= EMLXS_HBA_SLI3_MODE) { 6254291a2b48SSukumar Swaminathan /* ERBM is enabled */ 625582527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset = 0x80; 625682527734SSukumar Swaminathan hba->sli.sli3.hgp_hbq_offset = 0xC0; 6257291a2b48SSukumar Swaminathan 625882527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size = SLI3_IOCB_CMD_SIZE; 625982527734SSukumar Swaminathan hba->sli.sli3.iocb_rsp_size = SLI3_IOCB_RSP_SIZE; 6260291a2b48SSukumar Swaminathan 626182527734SSukumar Swaminathan } else { /* SLI2 */ 6262291a2b48SSukumar Swaminathan /* ERBM is disabled */ 626382527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset = 0xC0; 626482527734SSukumar Swaminathan hba->sli.sli3.hgp_hbq_offset = 0; 6265291a2b48SSukumar Swaminathan 626682527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size = SLI2_IOCB_CMD_SIZE; 626782527734SSukumar Swaminathan hba->sli.sli3.iocb_rsp_size = SLI2_IOCB_RSP_SIZE; 6268291a2b48SSukumar Swaminathan } 6269291a2b48SSukumar Swaminathan 6270291a2b48SSukumar Swaminathan /* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */ 6271291a2b48SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 627282527734SSukumar Swaminathan hgp = hba->sli.sli3.slim2.phys + 6273291a2b48SSukumar Swaminathan (uint64_t)((unsigned long)&(mbox->us.s2.host)); 627482527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh = 627582527734SSukumar Swaminathan PADDR_HI(hgp); 627682527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow = 627782527734SSukumar Swaminathan PADDR_LO(hgp); 6278291a2b48SSukumar Swaminathan } else { 627982527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh = 6280291a2b48SSukumar Swaminathan (uint32_t)ddi_get32(hba->pci_acc_handle, 6281291a2b48SSukumar Swaminathan (uint32_t *)(hba->pci_addr + PCI_BAR_1_REGISTER)); 6282291a2b48SSukumar Swaminathan 6283291a2b48SSukumar Swaminathan Laddr = 6284291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 6285291a2b48SSukumar Swaminathan (uint32_t *)(hba->pci_addr + PCI_BAR_0_REGISTER)); 6286291a2b48SSukumar Swaminathan Laddr &= ~0x4; 628782527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow = 628882527734SSukumar Swaminathan (uint32_t)(Laddr + hba->sli.sli3.hgp_ring_offset); 6289291a2b48SSukumar Swaminathan 62904baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 62914baa2c25SSukumar Swaminathan /* Access handle validation */ 629282527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle); 62934baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 629482527734SSukumar Swaminathan 6295291a2b48SSukumar Swaminathan } 6296291a2b48SSukumar Swaminathan 629782527734SSukumar Swaminathan pgp = hba->sli.sli3.slim2.phys + 629882527734SSukumar Swaminathan (uint64_t)((unsigned long)&(mbox->us.s2.port)); 629982527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrHigh = 630082527734SSukumar Swaminathan PADDR_HI(pgp); 630182527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrLow = 630282527734SSukumar Swaminathan PADDR_LO(pgp); 6303291a2b48SSukumar Swaminathan 6304291a2b48SSukumar Swaminathan offset = 0; 6305291a2b48SSukumar Swaminathan for (i = 0; i < 4; i++) { 630682527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[i]; 630782527734SSukumar Swaminathan rdsc = &((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.rdsc[i]; 6308291a2b48SSukumar Swaminathan 6309291a2b48SSukumar Swaminathan /* Setup command ring */ 631082527734SSukumar Swaminathan rgp = hba->sli.sli3.slim2.phys + 6311291a2b48SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->IOCBs[offset])); 631282527734SSukumar Swaminathan rdsc->cmdAddrHigh = PADDR_HI(rgp); 631382527734SSukumar Swaminathan rdsc->cmdAddrLow = PADDR_LO(rgp); 6314291a2b48SSukumar Swaminathan rdsc->cmdEntries = rp->fc_numCiocb; 6315291a2b48SSukumar Swaminathan 6316291a2b48SSukumar Swaminathan rp->fc_cmdringaddr = 631782527734SSukumar Swaminathan (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset]; 631882527734SSukumar Swaminathan offset += rdsc->cmdEntries * hba->sli.sli3.iocb_cmd_size; 6319291a2b48SSukumar Swaminathan 6320291a2b48SSukumar Swaminathan /* Setup response ring */ 632182527734SSukumar Swaminathan rgp = hba->sli.sli3.slim2.phys + 6322291a2b48SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->IOCBs[offset])); 632382527734SSukumar Swaminathan rdsc->rspAddrHigh = PADDR_HI(rgp); 632482527734SSukumar Swaminathan rdsc->rspAddrLow = PADDR_LO(rgp); 6325291a2b48SSukumar Swaminathan rdsc->rspEntries = rp->fc_numRiocb; 6326291a2b48SSukumar Swaminathan 6327291a2b48SSukumar Swaminathan rp->fc_rspringaddr = 632882527734SSukumar Swaminathan (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset]; 632982527734SSukumar Swaminathan offset += rdsc->rspEntries * hba->sli.sli3.iocb_rsp_size; 6330291a2b48SSukumar Swaminathan } 6331291a2b48SSukumar Swaminathan 633282527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *) 633382527734SSukumar Swaminathan (&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb), 633482527734SSukumar Swaminathan (uint8_t *)(&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb), 633582527734SSukumar Swaminathan sizeof (PCB)); 6336291a2b48SSukumar Swaminathan 633782527734SSukumar Swaminathan offset = ((uint64_t)((unsigned long) 633882527734SSukumar Swaminathan &(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb)) - 633982527734SSukumar Swaminathan (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 634082527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, (off_t)offset, 634182527734SSukumar Swaminathan sizeof (PCB), DDI_DMA_SYNC_FORDEV); 6342291a2b48SSukumar Swaminathan 6343291a2b48SSukumar Swaminathan return (0); 6344291a2b48SSukumar Swaminathan 6345291a2b48SSukumar Swaminathan } /* emlxs_mb_config_port() */ 6346291a2b48SSukumar Swaminathan 6347291a2b48SSukumar Swaminathan 634882527734SSukumar Swaminathan static uint32_t 6349291a2b48SSukumar Swaminathan emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id) 6350291a2b48SSukumar Swaminathan { 6351291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 6352291a2b48SSukumar Swaminathan HBQ_INIT_t *hbq; 6353291a2b48SSukumar Swaminathan MATCHMAP *mp; 6354291a2b48SSukumar Swaminathan HBQE_t *hbqE; 6355291a2b48SSukumar Swaminathan MAILBOX *mb; 635682527734SSukumar Swaminathan MAILBOXQ *mbq; 6357291a2b48SSukumar Swaminathan void *ioa2; 6358291a2b48SSukumar Swaminathan uint32_t j; 6359291a2b48SSukumar Swaminathan uint32_t count; 6360291a2b48SSukumar Swaminathan uint32_t size; 6361291a2b48SSukumar Swaminathan uint32_t ringno; 6362291a2b48SSukumar Swaminathan uint32_t seg; 6363291a2b48SSukumar Swaminathan 6364291a2b48SSukumar Swaminathan switch (hbq_id) { 6365291a2b48SSukumar Swaminathan case EMLXS_ELS_HBQ_ID: 6366291a2b48SSukumar Swaminathan count = MEM_ELSBUF_COUNT; 6367291a2b48SSukumar Swaminathan size = MEM_ELSBUF_SIZE; 6368291a2b48SSukumar Swaminathan ringno = FC_ELS_RING; 6369291a2b48SSukumar Swaminathan seg = MEM_ELSBUF; 6370291a2b48SSukumar Swaminathan HBASTATS.ElsUbPosted = count; 6371291a2b48SSukumar Swaminathan break; 6372291a2b48SSukumar Swaminathan 6373291a2b48SSukumar Swaminathan case EMLXS_IP_HBQ_ID: 6374291a2b48SSukumar Swaminathan count = MEM_IPBUF_COUNT; 6375291a2b48SSukumar Swaminathan size = MEM_IPBUF_SIZE; 6376291a2b48SSukumar Swaminathan ringno = FC_IP_RING; 6377291a2b48SSukumar Swaminathan seg = MEM_IPBUF; 6378291a2b48SSukumar Swaminathan HBASTATS.IpUbPosted = count; 6379291a2b48SSukumar Swaminathan break; 6380291a2b48SSukumar Swaminathan 6381291a2b48SSukumar Swaminathan case EMLXS_CT_HBQ_ID: 6382291a2b48SSukumar Swaminathan count = MEM_CTBUF_COUNT; 6383291a2b48SSukumar Swaminathan size = MEM_CTBUF_SIZE; 6384291a2b48SSukumar Swaminathan ringno = FC_CT_RING; 6385291a2b48SSukumar Swaminathan seg = MEM_CTBUF; 6386291a2b48SSukumar Swaminathan HBASTATS.CtUbPosted = count; 6387291a2b48SSukumar Swaminathan break; 6388291a2b48SSukumar Swaminathan 6389291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 6390291a2b48SSukumar Swaminathan case EMLXS_FCT_HBQ_ID: 6391291a2b48SSukumar Swaminathan count = MEM_FCTBUF_COUNT; 6392291a2b48SSukumar Swaminathan size = MEM_FCTBUF_SIZE; 6393291a2b48SSukumar Swaminathan ringno = FC_FCT_RING; 6394291a2b48SSukumar Swaminathan seg = MEM_FCTBUF; 6395291a2b48SSukumar Swaminathan HBASTATS.FctUbPosted = count; 6396291a2b48SSukumar Swaminathan break; 6397291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 6398291a2b48SSukumar Swaminathan 6399291a2b48SSukumar Swaminathan default: 6400291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6401*8f23e9faSHans Rosenfeld "hbq_setup: Invalid HBQ id. (%x)", hbq_id); 6402291a2b48SSukumar Swaminathan return (1); 6403291a2b48SSukumar Swaminathan } 6404291a2b48SSukumar Swaminathan 6405291a2b48SSukumar Swaminathan /* Configure HBQ */ 640682527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6407291a2b48SSukumar Swaminathan hbq->HBQ_numEntries = count; 6408291a2b48SSukumar Swaminathan 6409291a2b48SSukumar Swaminathan /* Get a Mailbox buffer to setup mailbox commands for CONFIG_HBQ */ 6410*8f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX)) == 0) { 6411291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6412*8f23e9faSHans Rosenfeld "hbq_setup: Unable to get mailbox."); 6413291a2b48SSukumar Swaminathan return (1); 6414291a2b48SSukumar Swaminathan } 641582527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 6416291a2b48SSukumar Swaminathan 6417291a2b48SSukumar Swaminathan /* Allocate HBQ Host buffer and Initialize the HBQEs */ 6418291a2b48SSukumar Swaminathan if (emlxs_hbq_alloc(hba, hbq_id)) { 6419291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6420*8f23e9faSHans Rosenfeld "hbq_setup: Unable to allocate HBQ."); 6421a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6422291a2b48SSukumar Swaminathan return (1); 6423291a2b48SSukumar Swaminathan } 6424291a2b48SSukumar Swaminathan 6425291a2b48SSukumar Swaminathan hbq->HBQ_recvNotify = 1; 6426291a2b48SSukumar Swaminathan hbq->HBQ_num_mask = 0; /* Bind to ring */ 6427291a2b48SSukumar Swaminathan hbq->HBQ_profile = 0; /* Selection profile */ 6428291a2b48SSukumar Swaminathan /* 0=all, 7=logentry */ 6429291a2b48SSukumar Swaminathan hbq->HBQ_ringMask = 1 << ringno; /* b0100 * ringno - Binds */ 6430291a2b48SSukumar Swaminathan /* HBQ to a ring */ 6431291a2b48SSukumar Swaminathan /* Ring0=b0001, Ring1=b0010, */ 6432291a2b48SSukumar Swaminathan /* Ring2=b0100 */ 6433291a2b48SSukumar Swaminathan hbq->HBQ_headerLen = 0; /* 0 if not profile 4 or 5 */ 6434291a2b48SSukumar Swaminathan hbq->HBQ_logEntry = 0; /* Set to 1 if this HBQ will */ 6435291a2b48SSukumar Swaminathan /* be used for */ 6436291a2b48SSukumar Swaminathan hbq->HBQ_id = hbq_id; 6437291a2b48SSukumar Swaminathan hbq->HBQ_PutIdx_next = 0; 6438291a2b48SSukumar Swaminathan hbq->HBQ_PutIdx = hbq->HBQ_numEntries - 1; 6439291a2b48SSukumar Swaminathan hbq->HBQ_GetIdx = 0; 6440291a2b48SSukumar Swaminathan hbq->HBQ_PostBufCnt = hbq->HBQ_numEntries; 6441291a2b48SSukumar Swaminathan bzero(hbq->HBQ_PostBufs, sizeof (hbq->HBQ_PostBufs)); 6442291a2b48SSukumar Swaminathan 6443291a2b48SSukumar Swaminathan /* Fill in POST BUFFERs in HBQE */ 6444291a2b48SSukumar Swaminathan hbqE = (HBQE_t *)hbq->HBQ_host_buf.virt; 6445291a2b48SSukumar Swaminathan for (j = 0; j < hbq->HBQ_numEntries; j++, hbqE++) { 6446291a2b48SSukumar Swaminathan /* Allocate buffer to post */ 6447291a2b48SSukumar Swaminathan if ((mp = (MATCHMAP *)emlxs_mem_get(hba, 6448*8f23e9faSHans Rosenfeld seg)) == 0) { 6449291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6450*8f23e9faSHans Rosenfeld "hbq_setup: Unable to allocate HBQ buffer. " 6451291a2b48SSukumar Swaminathan "cnt=%d", j); 6452291a2b48SSukumar Swaminathan emlxs_hbq_free_all(hba, hbq_id); 6453291a2b48SSukumar Swaminathan return (1); 6454291a2b48SSukumar Swaminathan } 6455291a2b48SSukumar Swaminathan 6456291a2b48SSukumar Swaminathan hbq->HBQ_PostBufs[j] = mp; 6457291a2b48SSukumar Swaminathan 6458291a2b48SSukumar Swaminathan hbqE->unt.ext.HBQ_tag = hbq_id; 6459291a2b48SSukumar Swaminathan hbqE->unt.ext.HBQE_tag = j; 6460291a2b48SSukumar Swaminathan hbqE->bde.tus.f.bdeSize = size; 6461291a2b48SSukumar Swaminathan hbqE->bde.tus.f.bdeFlags = 0; 646282527734SSukumar Swaminathan hbqE->unt.w = BE_SWAP32(hbqE->unt.w); 646382527734SSukumar Swaminathan hbqE->bde.tus.w = BE_SWAP32(hbqE->bde.tus.w); 6464291a2b48SSukumar Swaminathan hbqE->bde.addrLow = 646582527734SSukumar Swaminathan BE_SWAP32(PADDR_LO(mp->phys)); 6466291a2b48SSukumar Swaminathan hbqE->bde.addrHigh = 646782527734SSukumar Swaminathan BE_SWAP32(PADDR_HI(mp->phys)); 6468291a2b48SSukumar Swaminathan } 6469291a2b48SSukumar Swaminathan 6470291a2b48SSukumar Swaminathan /* Issue CONFIG_HBQ */ 647182527734SSukumar Swaminathan emlxs_mb_config_hbq(hba, mbq, hbq_id); 647282527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 6473291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 6474*8f23e9faSHans Rosenfeld "hbq_setup: Unable to config HBQ. cmd=%x status=%x", 6475291a2b48SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 6476291a2b48SSukumar Swaminathan 6477a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6478291a2b48SSukumar Swaminathan emlxs_hbq_free_all(hba, hbq_id); 6479291a2b48SSukumar Swaminathan return (1); 6480291a2b48SSukumar Swaminathan } 6481291a2b48SSukumar Swaminathan 6482291a2b48SSukumar Swaminathan /* Setup HBQ Get/Put indexes */ 648382527734SSukumar Swaminathan ioa2 = (void *)((char *)hba->sli.sli3.slim_addr + 648482527734SSukumar Swaminathan (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t)))); 6485291a2b48SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, hbq->HBQ_PutIdx); 6486291a2b48SSukumar Swaminathan 648782527734SSukumar Swaminathan hba->sli.sli3.hbq_count++; 6488291a2b48SSukumar Swaminathan 6489a9800bebSGarrett D'Amore emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6490291a2b48SSukumar Swaminathan 64914baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64924baa2c25SSukumar Swaminathan /* Access handle validation */ 649382527734SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 64944baa2c25SSukumar Swaminathan != DDI_FM_OK) { 64954baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 64964baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 64974baa2c25SSukumar Swaminathan emlxs_hbq_free_all(hba, hbq_id); 64984baa2c25SSukumar Swaminathan return (1); 64994baa2c25SSukumar Swaminathan } 65004baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 65014baa2c25SSukumar Swaminathan 6502291a2b48SSukumar Swaminathan return (0); 6503291a2b48SSukumar Swaminathan 650482527734SSukumar Swaminathan } /* emlxs_hbq_setup() */ 6505291a2b48SSukumar Swaminathan 6506291a2b48SSukumar Swaminathan 650782527734SSukumar Swaminathan extern void 6508291a2b48SSukumar Swaminathan emlxs_hbq_free_all(emlxs_hba_t *hba, uint32_t hbq_id) 6509291a2b48SSukumar Swaminathan { 6510291a2b48SSukumar Swaminathan HBQ_INIT_t *hbq; 6511291a2b48SSukumar Swaminathan MBUF_INFO *buf_info; 6512291a2b48SSukumar Swaminathan MBUF_INFO bufinfo; 6513291a2b48SSukumar Swaminathan uint32_t seg; 6514291a2b48SSukumar Swaminathan uint32_t j; 6515291a2b48SSukumar Swaminathan 6516291a2b48SSukumar Swaminathan switch (hbq_id) { 6517291a2b48SSukumar Swaminathan case EMLXS_ELS_HBQ_ID: 6518291a2b48SSukumar Swaminathan seg = MEM_ELSBUF; 6519291a2b48SSukumar Swaminathan HBASTATS.ElsUbPosted = 0; 6520291a2b48SSukumar Swaminathan break; 6521291a2b48SSukumar Swaminathan 6522291a2b48SSukumar Swaminathan case EMLXS_IP_HBQ_ID: 6523291a2b48SSukumar Swaminathan seg = MEM_IPBUF; 6524291a2b48SSukumar Swaminathan HBASTATS.IpUbPosted = 0; 6525291a2b48SSukumar Swaminathan break; 6526291a2b48SSukumar Swaminathan 6527291a2b48SSukumar Swaminathan case EMLXS_CT_HBQ_ID: 6528291a2b48SSukumar Swaminathan seg = MEM_CTBUF; 6529291a2b48SSukumar Swaminathan HBASTATS.CtUbPosted = 0; 6530291a2b48SSukumar Swaminathan break; 6531291a2b48SSukumar Swaminathan 6532291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 6533291a2b48SSukumar Swaminathan case EMLXS_FCT_HBQ_ID: 6534291a2b48SSukumar Swaminathan seg = MEM_FCTBUF; 6535291a2b48SSukumar Swaminathan HBASTATS.FctUbPosted = 0; 6536291a2b48SSukumar Swaminathan break; 6537291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 6538291a2b48SSukumar Swaminathan 6539291a2b48SSukumar Swaminathan default: 6540291a2b48SSukumar Swaminathan return; 6541291a2b48SSukumar Swaminathan } 6542291a2b48SSukumar Swaminathan 6543291a2b48SSukumar Swaminathan 654482527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6545291a2b48SSukumar Swaminathan 6546291a2b48SSukumar Swaminathan if (hbq->HBQ_host_buf.virt != 0) { 6547291a2b48SSukumar Swaminathan for (j = 0; j < hbq->HBQ_PostBufCnt; j++) { 6548a9800bebSGarrett D'Amore emlxs_mem_put(hba, seg, 6549a9800bebSGarrett D'Amore (void *)hbq->HBQ_PostBufs[j]); 6550291a2b48SSukumar Swaminathan hbq->HBQ_PostBufs[j] = NULL; 6551291a2b48SSukumar Swaminathan } 6552291a2b48SSukumar Swaminathan hbq->HBQ_PostBufCnt = 0; 6553291a2b48SSukumar Swaminathan 6554291a2b48SSukumar Swaminathan buf_info = &bufinfo; 6555291a2b48SSukumar Swaminathan bzero(buf_info, sizeof (MBUF_INFO)); 6556291a2b48SSukumar Swaminathan 6557291a2b48SSukumar Swaminathan buf_info->size = hbq->HBQ_host_buf.size; 6558291a2b48SSukumar Swaminathan buf_info->virt = hbq->HBQ_host_buf.virt; 6559291a2b48SSukumar Swaminathan buf_info->phys = hbq->HBQ_host_buf.phys; 6560291a2b48SSukumar Swaminathan buf_info->dma_handle = hbq->HBQ_host_buf.dma_handle; 6561291a2b48SSukumar Swaminathan buf_info->data_handle = hbq->HBQ_host_buf.data_handle; 6562291a2b48SSukumar Swaminathan buf_info->flags = FC_MBUF_DMA; 6563291a2b48SSukumar Swaminathan 6564291a2b48SSukumar Swaminathan emlxs_mem_free(hba, buf_info); 6565291a2b48SSukumar Swaminathan 6566291a2b48SSukumar Swaminathan hbq->HBQ_host_buf.virt = NULL; 6567291a2b48SSukumar Swaminathan } 6568291a2b48SSukumar Swaminathan 6569291a2b48SSukumar Swaminathan return; 6570291a2b48SSukumar Swaminathan 657182527734SSukumar Swaminathan } /* emlxs_hbq_free_all() */ 6572291a2b48SSukumar Swaminathan 6573291a2b48SSukumar Swaminathan 657482527734SSukumar Swaminathan extern void 6575291a2b48SSukumar Swaminathan emlxs_update_HBQ_index(emlxs_hba_t *hba, uint32_t hbq_id) 6576291a2b48SSukumar Swaminathan { 65774baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 65784baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 65794baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6580291a2b48SSukumar Swaminathan void *ioa2; 6581291a2b48SSukumar Swaminathan uint32_t status; 6582291a2b48SSukumar Swaminathan uint32_t HBQ_PortGetIdx; 6583291a2b48SSukumar Swaminathan HBQ_INIT_t *hbq; 6584291a2b48SSukumar Swaminathan 6585291a2b48SSukumar Swaminathan switch (hbq_id) { 6586291a2b48SSukumar Swaminathan case EMLXS_ELS_HBQ_ID: 6587291a2b48SSukumar Swaminathan HBASTATS.ElsUbPosted++; 6588291a2b48SSukumar Swaminathan break; 6589291a2b48SSukumar Swaminathan 6590291a2b48SSukumar Swaminathan case EMLXS_IP_HBQ_ID: 6591291a2b48SSukumar Swaminathan HBASTATS.IpUbPosted++; 6592291a2b48SSukumar Swaminathan break; 6593291a2b48SSukumar Swaminathan 6594291a2b48SSukumar Swaminathan case EMLXS_CT_HBQ_ID: 6595291a2b48SSukumar Swaminathan HBASTATS.CtUbPosted++; 6596291a2b48SSukumar Swaminathan break; 6597291a2b48SSukumar Swaminathan 6598291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 6599291a2b48SSukumar Swaminathan case EMLXS_FCT_HBQ_ID: 6600291a2b48SSukumar Swaminathan HBASTATS.FctUbPosted++; 6601291a2b48SSukumar Swaminathan break; 6602291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 6603291a2b48SSukumar Swaminathan 6604291a2b48SSukumar Swaminathan default: 6605291a2b48SSukumar Swaminathan return; 6606291a2b48SSukumar Swaminathan } 6607291a2b48SSukumar Swaminathan 660882527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6609291a2b48SSukumar Swaminathan 6610291a2b48SSukumar Swaminathan hbq->HBQ_PutIdx = 6611291a2b48SSukumar Swaminathan (hbq->HBQ_PutIdx + 1 >= 6612291a2b48SSukumar Swaminathan hbq->HBQ_numEntries) ? 0 : hbq->HBQ_PutIdx + 1; 6613291a2b48SSukumar Swaminathan 6614291a2b48SSukumar Swaminathan if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) { 6615291a2b48SSukumar Swaminathan HBQ_PortGetIdx = 661682527734SSukumar Swaminathan BE_SWAP32(((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2. 6617291a2b48SSukumar Swaminathan HBQ_PortGetIdx[hbq_id]); 6618291a2b48SSukumar Swaminathan 6619291a2b48SSukumar Swaminathan hbq->HBQ_GetIdx = HBQ_PortGetIdx; 6620291a2b48SSukumar Swaminathan 6621291a2b48SSukumar Swaminathan if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) { 6622291a2b48SSukumar Swaminathan return; 6623291a2b48SSukumar Swaminathan } 6624291a2b48SSukumar Swaminathan } 6625291a2b48SSukumar Swaminathan 662682527734SSukumar Swaminathan ioa2 = (void *)((char *)hba->sli.sli3.slim_addr + 662782527734SSukumar Swaminathan (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t)))); 6628291a2b48SSukumar Swaminathan status = hbq->HBQ_PutIdx; 6629291a2b48SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, status); 6630291a2b48SSukumar Swaminathan 66314baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 66324baa2c25SSukumar Swaminathan /* Access handle validation */ 663382527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 66344baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 66354baa2c25SSukumar Swaminathan 6636291a2b48SSukumar Swaminathan return; 6637291a2b48SSukumar Swaminathan 663882527734SSukumar Swaminathan } /* emlxs_update_HBQ_index() */ 6639291a2b48SSukumar Swaminathan 6640291a2b48SSukumar Swaminathan 664182527734SSukumar Swaminathan static void 664282527734SSukumar Swaminathan emlxs_sli3_enable_intr(emlxs_hba_t *hba) 6643291a2b48SSukumar Swaminathan { 66444baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 66454baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 66464baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6647291a2b48SSukumar Swaminathan uint32_t status; 6648291a2b48SSukumar Swaminathan 6649291a2b48SSukumar Swaminathan /* Enable mailbox, error attention interrupts */ 665082527734SSukumar Swaminathan status = (uint32_t)(HC_MBINT_ENA); 6651291a2b48SSukumar Swaminathan 6652291a2b48SSukumar Swaminathan /* Enable ring interrupts */ 665382527734SSukumar Swaminathan if (hba->sli.sli3.ring_count >= 4) { 6654291a2b48SSukumar Swaminathan status |= 6655291a2b48SSukumar Swaminathan (HC_R3INT_ENA | HC_R2INT_ENA | HC_R1INT_ENA | 6656291a2b48SSukumar Swaminathan HC_R0INT_ENA); 665782527734SSukumar Swaminathan } else if (hba->sli.sli3.ring_count == 3) { 6658291a2b48SSukumar Swaminathan status |= (HC_R2INT_ENA | HC_R1INT_ENA | HC_R0INT_ENA); 665982527734SSukumar Swaminathan } else if (hba->sli.sli3.ring_count == 2) { 6660291a2b48SSukumar Swaminathan status |= (HC_R1INT_ENA | HC_R0INT_ENA); 666182527734SSukumar Swaminathan } else if (hba->sli.sli3.ring_count == 1) { 6662291a2b48SSukumar Swaminathan status |= (HC_R0INT_ENA); 6663291a2b48SSukumar Swaminathan } 6664291a2b48SSukumar Swaminathan 666582527734SSukumar Swaminathan hba->sli.sli3.hc_copy = status; 666682527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 66674baa2c25SSukumar Swaminathan 66684baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 66694baa2c25SSukumar Swaminathan /* Access handle validation */ 667082527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 66714baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6672291a2b48SSukumar Swaminathan 667382527734SSukumar Swaminathan } /* emlxs_sli3_enable_intr() */ 667482527734SSukumar Swaminathan 667582527734SSukumar Swaminathan 667682527734SSukumar Swaminathan static void 6677291a2b48SSukumar Swaminathan emlxs_enable_latt(emlxs_hba_t *hba) 6678291a2b48SSukumar Swaminathan { 66794baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 66804baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 66814baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 66824baa2c25SSukumar Swaminathan 6683291a2b48SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 668482527734SSukumar Swaminathan hba->sli.sli3.hc_copy |= HC_LAINT_ENA; 668582527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 66864baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 66874baa2c25SSukumar Swaminathan /* Access handle validation */ 668882527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 66894baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6690291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 6691291a2b48SSukumar Swaminathan 669282527734SSukumar Swaminathan } /* emlxs_enable_latt() */ 669382527734SSukumar Swaminathan 669482527734SSukumar Swaminathan 669582527734SSukumar Swaminathan static void 669682527734SSukumar Swaminathan emlxs_sli3_disable_intr(emlxs_hba_t *hba, uint32_t att) 6697291a2b48SSukumar Swaminathan { 66984baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 66994baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 67004baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 67014baa2c25SSukumar Swaminathan 6702291a2b48SSukumar Swaminathan /* Disable all adapter interrupts */ 670382527734SSukumar Swaminathan hba->sli.sli3.hc_copy = att; 670482527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 67054baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 67064baa2c25SSukumar Swaminathan /* Access handle validation */ 670782527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 67084baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6709291a2b48SSukumar Swaminathan 671082527734SSukumar Swaminathan } /* emlxs_sli3_disable_intr() */ 671182527734SSukumar Swaminathan 671282527734SSukumar Swaminathan 671382527734SSukumar Swaminathan static uint32_t 6714291a2b48SSukumar Swaminathan emlxs_check_attention(emlxs_hba_t *hba) 6715291a2b48SSukumar Swaminathan { 67164baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 67174baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 67184baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6719291a2b48SSukumar Swaminathan uint32_t ha_copy; 6720291a2b48SSukumar Swaminathan 672182527734SSukumar Swaminathan ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 67224baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 67234baa2c25SSukumar Swaminathan /* Access handle validation */ 672482527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 67254baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6726291a2b48SSukumar Swaminathan return (ha_copy); 672782527734SSukumar Swaminathan 672882527734SSukumar Swaminathan } /* emlxs_check_attention() */ 672982527734SSukumar Swaminathan 6730*8f23e9faSHans Rosenfeld 6731*8f23e9faSHans Rosenfeld static void 673282527734SSukumar Swaminathan emlxs_sli3_poll_erratt(emlxs_hba_t *hba) 673382527734SSukumar Swaminathan { 673482527734SSukumar Swaminathan uint32_t ha_copy; 673582527734SSukumar Swaminathan 673682527734SSukumar Swaminathan ha_copy = emlxs_check_attention(hba); 673782527734SSukumar Swaminathan 673882527734SSukumar Swaminathan /* Adapter error */ 673982527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 674082527734SSukumar Swaminathan HBASTATS.IntrEvent[6]++; 674182527734SSukumar Swaminathan emlxs_handle_ff_error(hba); 674282527734SSukumar Swaminathan } 6743*8f23e9faSHans Rosenfeld 6744*8f23e9faSHans Rosenfeld } /* emlxs_sli3_poll_erratt() */ 6745*8f23e9faSHans Rosenfeld 6746*8f23e9faSHans Rosenfeld 6747*8f23e9faSHans Rosenfeld static uint32_t 6748*8f23e9faSHans Rosenfeld emlxs_sli3_reg_did_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 6749*8f23e9faSHans Rosenfeld { 6750*8f23e9faSHans Rosenfeld emlxs_port_t *port = (emlxs_port_t *)mbq->port; 6751*8f23e9faSHans Rosenfeld MAILBOXQ *mboxq; 6752*8f23e9faSHans Rosenfeld MAILBOX *mb; 6753*8f23e9faSHans Rosenfeld MATCHMAP *mp; 6754*8f23e9faSHans Rosenfeld NODELIST *ndlp; 6755*8f23e9faSHans Rosenfeld emlxs_port_t *vport; 6756*8f23e9faSHans Rosenfeld SERV_PARM *sp; 6757*8f23e9faSHans Rosenfeld int32_t i; 6758*8f23e9faSHans Rosenfeld uint32_t control; 6759*8f23e9faSHans Rosenfeld uint32_t ldata; 6760*8f23e9faSHans Rosenfeld uint32_t ldid; 6761*8f23e9faSHans Rosenfeld uint16_t lrpi; 6762*8f23e9faSHans Rosenfeld uint16_t lvpi; 6763*8f23e9faSHans Rosenfeld uint32_t rval; 6764*8f23e9faSHans Rosenfeld 6765*8f23e9faSHans Rosenfeld mb = (MAILBOX *)mbq; 6766*8f23e9faSHans Rosenfeld 6767*8f23e9faSHans Rosenfeld if (mb->mbxStatus) { 6768*8f23e9faSHans Rosenfeld if (mb->mbxStatus == MBXERR_NO_RESOURCES) { 6769*8f23e9faSHans Rosenfeld control = mb->un.varRegLogin.un.sp.bdeSize; 6770*8f23e9faSHans Rosenfeld if (control == 0) { 6771*8f23e9faSHans Rosenfeld /* Special handle for vport PLOGI */ 6772*8f23e9faSHans Rosenfeld if (mbq->iocbq == (uint8_t *)1) { 6773*8f23e9faSHans Rosenfeld mbq->iocbq = NULL; 6774*8f23e9faSHans Rosenfeld } 6775*8f23e9faSHans Rosenfeld return (0); 6776*8f23e9faSHans Rosenfeld } 6777*8f23e9faSHans Rosenfeld emlxs_mb_retry(hba, mbq); 6778*8f23e9faSHans Rosenfeld return (1); 6779*8f23e9faSHans Rosenfeld } 6780*8f23e9faSHans Rosenfeld if (mb->mbxStatus == MBXERR_RPI_FULL) { 6781*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, 6782*8f23e9faSHans Rosenfeld &emlxs_node_create_failed_msg, 6783*8f23e9faSHans Rosenfeld "Limit reached. count=%d", port->node_count); 6784*8f23e9faSHans Rosenfeld } 6785*8f23e9faSHans Rosenfeld 6786*8f23e9faSHans Rosenfeld /* Special handle for vport PLOGI */ 6787*8f23e9faSHans Rosenfeld if (mbq->iocbq == (uint8_t *)1) { 6788*8f23e9faSHans Rosenfeld mbq->iocbq = NULL; 6789*8f23e9faSHans Rosenfeld } 6790*8f23e9faSHans Rosenfeld 6791*8f23e9faSHans Rosenfeld return (0); 6792*8f23e9faSHans Rosenfeld } 6793*8f23e9faSHans Rosenfeld 6794*8f23e9faSHans Rosenfeld mp = (MATCHMAP *)mbq->bp; 6795*8f23e9faSHans Rosenfeld if (!mp) { 6796*8f23e9faSHans Rosenfeld return (0); 6797*8f23e9faSHans Rosenfeld } 6798*8f23e9faSHans Rosenfeld 6799*8f23e9faSHans Rosenfeld ldata = mb->un.varWords[5]; 6800*8f23e9faSHans Rosenfeld lvpi = (ldata & 0xffff); 6801*8f23e9faSHans Rosenfeld port = &VPORT(lvpi); 6802*8f23e9faSHans Rosenfeld 6803*8f23e9faSHans Rosenfeld /* First copy command data */ 6804*8f23e9faSHans Rosenfeld ldata = mb->un.varWords[0]; /* get rpi */ 6805*8f23e9faSHans Rosenfeld lrpi = ldata & 0xffff; 6806*8f23e9faSHans Rosenfeld 6807*8f23e9faSHans Rosenfeld ldata = mb->un.varWords[1]; /* get did */ 6808*8f23e9faSHans Rosenfeld ldid = ldata & MASK_DID; 6809*8f23e9faSHans Rosenfeld 6810*8f23e9faSHans Rosenfeld sp = (SERV_PARM *)mp->virt; 6811*8f23e9faSHans Rosenfeld 6812*8f23e9faSHans Rosenfeld /* Create or update the node */ 6813*8f23e9faSHans Rosenfeld ndlp = emlxs_node_create(port, ldid, lrpi, sp); 6814*8f23e9faSHans Rosenfeld 6815*8f23e9faSHans Rosenfeld if (ndlp == NULL) { 6816*8f23e9faSHans Rosenfeld emlxs_ub_priv_t *ub_priv; 6817*8f23e9faSHans Rosenfeld 6818*8f23e9faSHans Rosenfeld /* 6819*8f23e9faSHans Rosenfeld * Fake a mailbox error, so the mbox_fini 6820*8f23e9faSHans Rosenfeld * can take appropriate action 6821*8f23e9faSHans Rosenfeld */ 6822*8f23e9faSHans Rosenfeld mb->mbxStatus = MBXERR_RPI_FULL; 6823*8f23e9faSHans Rosenfeld if (mbq->ubp) { 6824*8f23e9faSHans Rosenfeld ub_priv = ((fc_unsol_buf_t *)mbq->ubp)->ub_fca_private; 6825*8f23e9faSHans Rosenfeld ub_priv->flags |= EMLXS_UB_REPLY; 6826*8f23e9faSHans Rosenfeld } 6827*8f23e9faSHans Rosenfeld 6828*8f23e9faSHans Rosenfeld /* This must be (0xFFFFFE) which was registered by vport */ 6829*8f23e9faSHans Rosenfeld if (lrpi == 0) { 6830*8f23e9faSHans Rosenfeld return (0); 6831*8f23e9faSHans Rosenfeld } 6832*8f23e9faSHans Rosenfeld 6833*8f23e9faSHans Rosenfeld if (!(mboxq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) { 6834*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6835*8f23e9faSHans Rosenfeld "reg_did_mbcmpl:failed. Unable to allocate mbox"); 6836*8f23e9faSHans Rosenfeld return (0); 6837*8f23e9faSHans Rosenfeld } 6838*8f23e9faSHans Rosenfeld 6839*8f23e9faSHans Rosenfeld mb = (MAILBOX *)mboxq->mbox; 6840*8f23e9faSHans Rosenfeld mb->un.varUnregLogin.rpi = lrpi; 6841*8f23e9faSHans Rosenfeld mb->un.varUnregLogin.vpi = lvpi; 6842*8f23e9faSHans Rosenfeld 6843*8f23e9faSHans Rosenfeld mb->mbxCommand = MBX_UNREG_LOGIN; 6844*8f23e9faSHans Rosenfeld mb->mbxOwner = OWN_HOST; 6845*8f23e9faSHans Rosenfeld mboxq->sbp = NULL; 6846*8f23e9faSHans Rosenfeld mboxq->ubp = NULL; 6847*8f23e9faSHans Rosenfeld mboxq->iocbq = NULL; 6848*8f23e9faSHans Rosenfeld mboxq->mbox_cmpl = NULL; 6849*8f23e9faSHans Rosenfeld mboxq->context = NULL; 6850*8f23e9faSHans Rosenfeld mboxq->port = (void *)port; 6851*8f23e9faSHans Rosenfeld 6852*8f23e9faSHans Rosenfeld rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mboxq, MBX_NOWAIT, 0); 6853*8f23e9faSHans Rosenfeld if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 6854*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 6855*8f23e9faSHans Rosenfeld "reg_did_mbcmpl:failed. Unable to send request."); 6856*8f23e9faSHans Rosenfeld 6857*8f23e9faSHans Rosenfeld emlxs_mem_put(hba, MEM_MBOX, (void *)mboxq); 6858*8f23e9faSHans Rosenfeld return (0); 6859*8f23e9faSHans Rosenfeld } 6860*8f23e9faSHans Rosenfeld 6861*8f23e9faSHans Rosenfeld return (0); 6862*8f23e9faSHans Rosenfeld } 6863*8f23e9faSHans Rosenfeld 6864*8f23e9faSHans Rosenfeld if (ndlp->nlp_DID == FABRIC_DID) { 6865*8f23e9faSHans Rosenfeld /* FLOGI/FDISC successfully completed on this port */ 6866*8f23e9faSHans Rosenfeld mutex_enter(&EMLXS_PORT_LOCK); 6867*8f23e9faSHans Rosenfeld port->flag |= EMLXS_PORT_FLOGI_CMPL; 6868*8f23e9faSHans Rosenfeld mutex_exit(&EMLXS_PORT_LOCK); 6869*8f23e9faSHans Rosenfeld 6870*8f23e9faSHans Rosenfeld /* If CLEAR_LA has been sent, then attempt to */ 6871*8f23e9faSHans Rosenfeld /* register the vpi now */ 6872*8f23e9faSHans Rosenfeld if (hba->state == FC_READY) { 6873*8f23e9faSHans Rosenfeld (void) emlxs_mb_reg_vpi(port, NULL); 6874*8f23e9faSHans Rosenfeld } 6875*8f23e9faSHans Rosenfeld 6876*8f23e9faSHans Rosenfeld /* 6877*8f23e9faSHans Rosenfeld * If NPIV Fabric support has just been established on 6878*8f23e9faSHans Rosenfeld * the physical port, then notify the vports of the 6879*8f23e9faSHans Rosenfeld * link up 6880*8f23e9faSHans Rosenfeld */ 6881*8f23e9faSHans Rosenfeld if ((lvpi == 0) && 6882*8f23e9faSHans Rosenfeld (hba->flag & FC_NPIV_ENABLED) && 6883*8f23e9faSHans Rosenfeld (hba->flag & FC_NPIV_SUPPORTED)) { 6884*8f23e9faSHans Rosenfeld /* Skip the physical port */ 6885*8f23e9faSHans Rosenfeld for (i = 1; i < MAX_VPORTS; i++) { 6886*8f23e9faSHans Rosenfeld vport = &VPORT(i); 6887*8f23e9faSHans Rosenfeld 6888*8f23e9faSHans Rosenfeld if (!(vport->flag & EMLXS_PORT_BOUND) || 6889*8f23e9faSHans Rosenfeld !(vport->flag & 6890*8f23e9faSHans Rosenfeld EMLXS_PORT_ENABLED)) { 6891*8f23e9faSHans Rosenfeld continue; 6892*8f23e9faSHans Rosenfeld } 6893*8f23e9faSHans Rosenfeld 6894*8f23e9faSHans Rosenfeld emlxs_port_online(vport); 6895*8f23e9faSHans Rosenfeld } 6896*8f23e9faSHans Rosenfeld } 6897*8f23e9faSHans Rosenfeld } 6898*8f23e9faSHans Rosenfeld 6899*8f23e9faSHans Rosenfeld /* Check for special restricted login flag */ 6900*8f23e9faSHans Rosenfeld if (mbq->iocbq == (uint8_t *)1) { 6901*8f23e9faSHans Rosenfeld mbq->iocbq = NULL; 6902*8f23e9faSHans Rosenfeld (void) EMLXS_SLI_UNREG_NODE(port, ndlp, NULL, NULL, NULL); 6903*8f23e9faSHans Rosenfeld return (0); 6904*8f23e9faSHans Rosenfeld } 6905*8f23e9faSHans Rosenfeld 6906*8f23e9faSHans Rosenfeld /* Needed for FCT trigger in emlxs_mb_deferred_cmpl */ 6907*8f23e9faSHans Rosenfeld if (mbq->sbp) { 6908*8f23e9faSHans Rosenfeld ((emlxs_buf_t *)mbq->sbp)->node = ndlp; 6909*8f23e9faSHans Rosenfeld } 6910*8f23e9faSHans Rosenfeld 6911*8f23e9faSHans Rosenfeld #ifdef DHCHAP_SUPPORT 6912*8f23e9faSHans Rosenfeld if (mbq->sbp || mbq->ubp) { 6913*8f23e9faSHans Rosenfeld if (emlxs_dhc_auth_start(port, ndlp, mbq->sbp, 6914*8f23e9faSHans Rosenfeld mbq->ubp) == 0) { 6915*8f23e9faSHans Rosenfeld /* Auth started - auth completion will */ 6916*8f23e9faSHans Rosenfeld /* handle sbp and ubp now */ 6917*8f23e9faSHans Rosenfeld mbq->sbp = NULL; 6918*8f23e9faSHans Rosenfeld mbq->ubp = NULL; 6919*8f23e9faSHans Rosenfeld } 6920*8f23e9faSHans Rosenfeld } 6921*8f23e9faSHans Rosenfeld #endif /* DHCHAP_SUPPORT */ 6922*8f23e9faSHans Rosenfeld 6923*8f23e9faSHans Rosenfeld return (0); 6924*8f23e9faSHans Rosenfeld 6925*8f23e9faSHans Rosenfeld } /* emlxs_sli3_reg_did_mbcmpl() */ 6926*8f23e9faSHans Rosenfeld 6927*8f23e9faSHans Rosenfeld 6928*8f23e9faSHans Rosenfeld static uint32_t 6929*8f23e9faSHans Rosenfeld emlxs_sli3_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param, 6930*8f23e9faSHans Rosenfeld emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq) 6931*8f23e9faSHans Rosenfeld { 6932*8f23e9faSHans Rosenfeld emlxs_hba_t *hba = HBA; 6933*8f23e9faSHans Rosenfeld MATCHMAP *mp; 6934*8f23e9faSHans Rosenfeld MAILBOXQ *mbq; 6935*8f23e9faSHans Rosenfeld MAILBOX *mb; 6936*8f23e9faSHans Rosenfeld uint32_t rval; 6937*8f23e9faSHans Rosenfeld 6938*8f23e9faSHans Rosenfeld /* Check for invalid node ids to register */ 6939*8f23e9faSHans Rosenfeld if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) { 6940*8f23e9faSHans Rosenfeld return (1); 6941*8f23e9faSHans Rosenfeld } 6942*8f23e9faSHans Rosenfeld 6943*8f23e9faSHans Rosenfeld if (did & 0xff000000) { 6944*8f23e9faSHans Rosenfeld return (1); 6945*8f23e9faSHans Rosenfeld } 6946*8f23e9faSHans Rosenfeld 6947*8f23e9faSHans Rosenfeld if ((rval = emlxs_mb_check_sparm(hba, param))) { 6948*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 6949*8f23e9faSHans Rosenfeld "Invalid service parameters. did=%06x rval=%d", did, 6950*8f23e9faSHans Rosenfeld rval); 6951*8f23e9faSHans Rosenfeld 6952*8f23e9faSHans Rosenfeld return (1); 6953*8f23e9faSHans Rosenfeld } 6954*8f23e9faSHans Rosenfeld 6955*8f23e9faSHans Rosenfeld /* Check if the node limit has been reached */ 6956*8f23e9faSHans Rosenfeld if (port->node_count >= hba->max_nodes) { 6957*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 6958*8f23e9faSHans Rosenfeld "Limit reached. did=%06x count=%d", did, 6959*8f23e9faSHans Rosenfeld port->node_count); 6960*8f23e9faSHans Rosenfeld 6961*8f23e9faSHans Rosenfeld return (1); 6962*8f23e9faSHans Rosenfeld } 6963*8f23e9faSHans Rosenfeld 6964*8f23e9faSHans Rosenfeld if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) { 6965*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 6966*8f23e9faSHans Rosenfeld "Unable to allocate mailbox. did=%x", did); 6967*8f23e9faSHans Rosenfeld 6968*8f23e9faSHans Rosenfeld return (1); 6969*8f23e9faSHans Rosenfeld } 6970*8f23e9faSHans Rosenfeld mb = (MAILBOX *)mbq->mbox; 6971*8f23e9faSHans Rosenfeld bzero((void *)mb, MAILBOX_CMD_BSIZE); 6972*8f23e9faSHans Rosenfeld 6973*8f23e9faSHans Rosenfeld /* Build login request */ 6974*8f23e9faSHans Rosenfeld if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) { 6975*8f23e9faSHans Rosenfeld emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 6976*8f23e9faSHans Rosenfeld 6977*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 6978*8f23e9faSHans Rosenfeld "Unable to allocate buffer. did=%x", did); 6979*8f23e9faSHans Rosenfeld return (1); 6980*8f23e9faSHans Rosenfeld } 6981*8f23e9faSHans Rosenfeld bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM)); 6982*8f23e9faSHans Rosenfeld 6983*8f23e9faSHans Rosenfeld mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM); 6984*8f23e9faSHans Rosenfeld mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys); 6985*8f23e9faSHans Rosenfeld mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys); 6986*8f23e9faSHans Rosenfeld mb->un.varRegLogin.did = did; 6987*8f23e9faSHans Rosenfeld mb->un.varWords[30] = 0; /* flags */ 6988*8f23e9faSHans Rosenfeld mb->mbxCommand = MBX_REG_LOGIN64; 6989*8f23e9faSHans Rosenfeld mb->mbxOwner = OWN_HOST; 6990*8f23e9faSHans Rosenfeld mb->un.varRegLogin.vpi = port->vpi; 6991*8f23e9faSHans Rosenfeld mb->un.varRegLogin.rpi = 0; 6992*8f23e9faSHans Rosenfeld 6993*8f23e9faSHans Rosenfeld mbq->sbp = (void *)sbp; 6994*8f23e9faSHans Rosenfeld mbq->ubp = (void *)ubp; 6995*8f23e9faSHans Rosenfeld mbq->iocbq = (void *)iocbq; 6996*8f23e9faSHans Rosenfeld mbq->bp = (void *)mp; 6997*8f23e9faSHans Rosenfeld mbq->mbox_cmpl = emlxs_sli3_reg_did_mbcmpl; 6998*8f23e9faSHans Rosenfeld mbq->context = NULL; 6999*8f23e9faSHans Rosenfeld mbq->port = (void *)port; 7000*8f23e9faSHans Rosenfeld 7001*8f23e9faSHans Rosenfeld rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 7002*8f23e9faSHans Rosenfeld if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 7003*8f23e9faSHans Rosenfeld emlxs_mem_put(hba, MEM_BUF, (void *)mp); 7004*8f23e9faSHans Rosenfeld emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 7005*8f23e9faSHans Rosenfeld 7006*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg, 7007*8f23e9faSHans Rosenfeld "Unable to send mbox. did=%x", did); 7008*8f23e9faSHans Rosenfeld return (1); 7009*8f23e9faSHans Rosenfeld } 7010*8f23e9faSHans Rosenfeld 7011*8f23e9faSHans Rosenfeld return (0); 7012*8f23e9faSHans Rosenfeld 7013*8f23e9faSHans Rosenfeld } /* emlxs_sli3_reg_did() */ 7014*8f23e9faSHans Rosenfeld 7015*8f23e9faSHans Rosenfeld 7016*8f23e9faSHans Rosenfeld /*ARGSUSED*/ 7017*8f23e9faSHans Rosenfeld static uint32_t 7018*8f23e9faSHans Rosenfeld emlxs_sli3_unreg_node_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq) 7019*8f23e9faSHans Rosenfeld { 7020*8f23e9faSHans Rosenfeld emlxs_port_t *port = (emlxs_port_t *)mbq->port; 7021*8f23e9faSHans Rosenfeld MAILBOX *mb; 7022*8f23e9faSHans Rosenfeld NODELIST *node; 7023*8f23e9faSHans Rosenfeld uint16_t rpi; 7024*8f23e9faSHans Rosenfeld 7025*8f23e9faSHans Rosenfeld node = (NODELIST *)mbq->context; 7026*8f23e9faSHans Rosenfeld mb = (MAILBOX *)mbq; 7027*8f23e9faSHans Rosenfeld rpi = (node)? node->nlp_Rpi:0xffff; 7028*8f23e9faSHans Rosenfeld 7029*8f23e9faSHans Rosenfeld if (mb->mbxStatus) { 7030*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7031*8f23e9faSHans Rosenfeld "unreg_node_mbcmpl:failed. node=%p rpi=%d status=%x", 7032*8f23e9faSHans Rosenfeld node, rpi, mb->mbxStatus); 7033*8f23e9faSHans Rosenfeld 7034*8f23e9faSHans Rosenfeld return (0); 7035*8f23e9faSHans Rosenfeld } 7036*8f23e9faSHans Rosenfeld 7037*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7038*8f23e9faSHans Rosenfeld "unreg_node_mbcmpl: node=%p rpi=%d", 7039*8f23e9faSHans Rosenfeld node, rpi); 7040*8f23e9faSHans Rosenfeld 7041*8f23e9faSHans Rosenfeld if (node) { 7042*8f23e9faSHans Rosenfeld emlxs_node_rm(port, node); 7043*8f23e9faSHans Rosenfeld 7044*8f23e9faSHans Rosenfeld } else { /* All nodes */ 7045*8f23e9faSHans Rosenfeld emlxs_node_destroy_all(port); 7046*8f23e9faSHans Rosenfeld } 7047*8f23e9faSHans Rosenfeld 7048*8f23e9faSHans Rosenfeld return (0); 7049*8f23e9faSHans Rosenfeld 7050*8f23e9faSHans Rosenfeld } /* emlxs_sli3_unreg_node_mbcmpl */ 7051*8f23e9faSHans Rosenfeld 7052*8f23e9faSHans Rosenfeld 7053*8f23e9faSHans Rosenfeld static uint32_t 7054*8f23e9faSHans Rosenfeld emlxs_sli3_unreg_node(emlxs_port_t *port, NODELIST *node, emlxs_buf_t *sbp, 7055*8f23e9faSHans Rosenfeld fc_unsol_buf_t *ubp, IOCBQ *iocbq) 7056*8f23e9faSHans Rosenfeld { 7057*8f23e9faSHans Rosenfeld emlxs_hba_t *hba = HBA; 7058*8f23e9faSHans Rosenfeld MAILBOXQ *mbq; 7059*8f23e9faSHans Rosenfeld MAILBOX *mb; 7060*8f23e9faSHans Rosenfeld uint16_t rpi; 7061*8f23e9faSHans Rosenfeld uint32_t rval; 7062*8f23e9faSHans Rosenfeld 7063*8f23e9faSHans Rosenfeld if (node) { 7064*8f23e9faSHans Rosenfeld /* Check for base node */ 7065*8f23e9faSHans Rosenfeld if (node == &port->node_base) { 7066*8f23e9faSHans Rosenfeld /* just flush base node */ 7067*8f23e9faSHans Rosenfeld (void) emlxs_tx_node_flush(port, &port->node_base, 7068*8f23e9faSHans Rosenfeld 0, 0, 0); 7069*8f23e9faSHans Rosenfeld (void) emlxs_chipq_node_flush(port, 0, 7070*8f23e9faSHans Rosenfeld &port->node_base, 0); 7071*8f23e9faSHans Rosenfeld 7072*8f23e9faSHans Rosenfeld port->did = 0; 7073*8f23e9faSHans Rosenfeld 7074*8f23e9faSHans Rosenfeld /* Return now */ 7075*8f23e9faSHans Rosenfeld return (1); 7076*8f23e9faSHans Rosenfeld } 7077*8f23e9faSHans Rosenfeld 7078*8f23e9faSHans Rosenfeld rpi = (uint16_t)node->nlp_Rpi; 7079*8f23e9faSHans Rosenfeld 7080*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7081*8f23e9faSHans Rosenfeld "unreg_node:%p rpi=%d", node, rpi); 7082*8f23e9faSHans Rosenfeld 7083*8f23e9faSHans Rosenfeld /* This node must be (0xFFFFFE) which registered by vport */ 7084*8f23e9faSHans Rosenfeld if (rpi == 0) { 7085*8f23e9faSHans Rosenfeld emlxs_node_rm(port, node); 7086*8f23e9faSHans Rosenfeld return (0); 7087*8f23e9faSHans Rosenfeld } 7088*8f23e9faSHans Rosenfeld 7089*8f23e9faSHans Rosenfeld } else { /* Unreg all nodes */ 7090*8f23e9faSHans Rosenfeld rpi = 0xffff; 7091*8f23e9faSHans Rosenfeld 7092*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7093*8f23e9faSHans Rosenfeld "unreg_node: All"); 7094*8f23e9faSHans Rosenfeld } 7095*8f23e9faSHans Rosenfeld 7096*8f23e9faSHans Rosenfeld if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) { 7097*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7098*8f23e9faSHans Rosenfeld "unreg_node:failed. Unable to allocate mbox"); 7099*8f23e9faSHans Rosenfeld return (1); 7100*8f23e9faSHans Rosenfeld } 7101*8f23e9faSHans Rosenfeld 7102*8f23e9faSHans Rosenfeld mb = (MAILBOX *)mbq->mbox; 7103*8f23e9faSHans Rosenfeld mb->un.varUnregLogin.rpi = rpi; 7104*8f23e9faSHans Rosenfeld mb->un.varUnregLogin.vpi = port->vpip->VPI; 7105*8f23e9faSHans Rosenfeld 7106*8f23e9faSHans Rosenfeld mb->mbxCommand = MBX_UNREG_LOGIN; 7107*8f23e9faSHans Rosenfeld mb->mbxOwner = OWN_HOST; 7108*8f23e9faSHans Rosenfeld mbq->sbp = (void *)sbp; 7109*8f23e9faSHans Rosenfeld mbq->ubp = (void *)ubp; 7110*8f23e9faSHans Rosenfeld mbq->iocbq = (void *)iocbq; 7111*8f23e9faSHans Rosenfeld mbq->mbox_cmpl = emlxs_sli3_unreg_node_mbcmpl; 7112*8f23e9faSHans Rosenfeld mbq->context = (void *)node; 7113*8f23e9faSHans Rosenfeld mbq->port = (void *)port; 7114*8f23e9faSHans Rosenfeld 7115*8f23e9faSHans Rosenfeld rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0); 7116*8f23e9faSHans Rosenfeld if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) { 7117*8f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 7118*8f23e9faSHans Rosenfeld "unreg_node:failed. Unable to send request."); 7119*8f23e9faSHans Rosenfeld 7120*8f23e9faSHans Rosenfeld emlxs_mem_put(hba, MEM_MBOX, (void *)mbq); 7121*8f23e9faSHans Rosenfeld return (1); 7122*8f23e9faSHans Rosenfeld } 7123*8f23e9faSHans Rosenfeld 7124*8f23e9faSHans Rosenfeld return (0); 7125*8f23e9faSHans Rosenfeld 7126*8f23e9faSHans Rosenfeld } /* emlxs_sli3_unreg_node() */ 7127