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 * 8291a2b48SSukumar Swaminathan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9291a2b48SSukumar Swaminathan * or http://www.opensolaris.org/os/licensing. 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 /* 23291a2b48SSukumar Swaminathan * Copyright 2009 Emulex. All rights reserved. 24*82527734SSukumar Swaminathan * Use is subject to license terms. 25291a2b48SSukumar Swaminathan */ 26291a2b48SSukumar Swaminathan 27*82527734SSukumar Swaminathan 28291a2b48SSukumar Swaminathan #include <emlxs.h> 29291a2b48SSukumar Swaminathan 30291a2b48SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 31*82527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_SLI3_C); 32291a2b48SSukumar Swaminathan 33*82527734SSukumar Swaminathan static void emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq); 34*82527734SSukumar Swaminathan static void emlxs_sli3_handle_link_event(emlxs_hba_t *hba); 35*82527734SSukumar Swaminathan static void emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, 36291a2b48SSukumar Swaminathan uint32_t ha_copy); 37*82527734SSukumar Swaminathan static int emlxs_sli3_mb_handle_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq); 38291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 39291a2b48SSukumar Swaminathan static uint32_t emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); 40291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 41*82527734SSukumar Swaminathan 42291a2b48SSukumar Swaminathan static uint32_t emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp); 43291a2b48SSukumar Swaminathan 44*82527734SSukumar Swaminathan static uint32_t emlxs_disable_traffic_cop = 1; 45291a2b48SSukumar Swaminathan 46*82527734SSukumar Swaminathan static int emlxs_sli3_map_hdw(emlxs_hba_t *hba); 47291a2b48SSukumar Swaminathan 48*82527734SSukumar Swaminathan static void emlxs_sli3_unmap_hdw(emlxs_hba_t *hba); 49291a2b48SSukumar Swaminathan 50*82527734SSukumar Swaminathan static int32_t emlxs_sli3_online(emlxs_hba_t *hba); 51291a2b48SSukumar Swaminathan 52*82527734SSukumar Swaminathan static void emlxs_sli3_offline(emlxs_hba_t *hba); 53291a2b48SSukumar Swaminathan 54*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_hba_reset(emlxs_hba_t *hba, 55*82527734SSukumar Swaminathan uint32_t restart, uint32_t skip_post, 56*82527734SSukumar Swaminathan uint32_t quiesce); 57291a2b48SSukumar Swaminathan 58*82527734SSukumar Swaminathan static void emlxs_sli3_hba_kill(emlxs_hba_t *hba); 59*82527734SSukumar Swaminathan static void emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba); 60*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_hba_init(emlxs_hba_t *hba); 61291a2b48SSukumar Swaminathan 62*82527734SSukumar Swaminathan static uint32_t emlxs_sli2_bde_setup(emlxs_port_t *port, 63*82527734SSukumar Swaminathan emlxs_buf_t *sbp); 64*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_bde_setup(emlxs_port_t *port, 65*82527734SSukumar Swaminathan emlxs_buf_t *sbp); 66*82527734SSukumar Swaminathan static uint32_t emlxs_sli2_fct_bde_setup(emlxs_port_t *port, 67*82527734SSukumar Swaminathan emlxs_buf_t *sbp); 68*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_fct_bde_setup(emlxs_port_t *port, 69*82527734SSukumar Swaminathan emlxs_buf_t *sbp); 70291a2b48SSukumar Swaminathan 71291a2b48SSukumar Swaminathan 72*82527734SSukumar Swaminathan static void emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, 73*82527734SSukumar Swaminathan CHANNEL *rp, IOCBQ *iocb_cmd); 74291a2b48SSukumar Swaminathan 75291a2b48SSukumar Swaminathan 76*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, 77*82527734SSukumar Swaminathan MAILBOXQ *mbq, int32_t flg, 78*82527734SSukumar Swaminathan uint32_t tmo); 79291a2b48SSukumar Swaminathan 80291a2b48SSukumar Swaminathan 81*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 82*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, 83*82527734SSukumar Swaminathan emlxs_buf_t *cmd_sbp, int channel); 84291a2b48SSukumar Swaminathan 85*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 86291a2b48SSukumar Swaminathan 87*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, 88*82527734SSukumar Swaminathan emlxs_buf_t *sbp, int ring); 89291a2b48SSukumar Swaminathan 90*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, 91*82527734SSukumar Swaminathan emlxs_buf_t *sbp); 92291a2b48SSukumar Swaminathan 93*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_els_iocb(emlxs_port_t *port, 94*82527734SSukumar Swaminathan emlxs_buf_t *sbp); 95291a2b48SSukumar Swaminathan 96291a2b48SSukumar Swaminathan 97*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, 98*82527734SSukumar Swaminathan emlxs_buf_t *sbp); 99291a2b48SSukumar Swaminathan 100291a2b48SSukumar Swaminathan 101*82527734SSukumar Swaminathan static void emlxs_sli3_poll_intr(emlxs_hba_t *hba, 102*82527734SSukumar Swaminathan uint32_t att_bit); 103291a2b48SSukumar Swaminathan 104*82527734SSukumar Swaminathan static int32_t emlxs_sli3_intx_intr(char *arg); 105*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT 106*82527734SSukumar Swaminathan static uint32_t emlxs_sli3_msi_intr(char *arg1, char *arg2); 107*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 108291a2b48SSukumar Swaminathan 109*82527734SSukumar Swaminathan static void emlxs_sli3_enable_intr(emlxs_hba_t *hba); 110*82527734SSukumar Swaminathan 111*82527734SSukumar Swaminathan static void emlxs_sli3_disable_intr(emlxs_hba_t *hba, 112*82527734SSukumar Swaminathan uint32_t att); 113*82527734SSukumar Swaminathan 114*82527734SSukumar Swaminathan static uint32_t emlxs_reset_ring(emlxs_hba_t *hba, 115*82527734SSukumar Swaminathan uint32_t ringno); 116*82527734SSukumar Swaminathan static void emlxs_handle_ff_error(emlxs_hba_t *hba); 117*82527734SSukumar Swaminathan 118*82527734SSukumar Swaminathan static uint32_t emlxs_handle_mb_event(emlxs_hba_t *hba); 119*82527734SSukumar Swaminathan 120*82527734SSukumar Swaminathan static void emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba); 121*82527734SSukumar Swaminathan 122*82527734SSukumar Swaminathan static uint32_t emlxs_mb_config_port(emlxs_hba_t *hba, 123*82527734SSukumar Swaminathan MAILBOXQ *mbq, uint32_t sli_mode, 124*82527734SSukumar Swaminathan uint32_t hbainit); 125*82527734SSukumar Swaminathan static void emlxs_enable_latt(emlxs_hba_t *hba); 126*82527734SSukumar Swaminathan 127*82527734SSukumar Swaminathan static uint32_t emlxs_check_attention(emlxs_hba_t *hba); 128*82527734SSukumar Swaminathan 129*82527734SSukumar Swaminathan static uint32_t emlxs_get_attention(emlxs_hba_t *hba, 130*82527734SSukumar Swaminathan uint32_t msgid); 131*82527734SSukumar Swaminathan static void emlxs_proc_attention(emlxs_hba_t *hba, 132*82527734SSukumar Swaminathan uint32_t ha_copy); 133*82527734SSukumar Swaminathan /* static int emlxs_handle_rcv_seq(emlxs_hba_t *hba, */ 134*82527734SSukumar Swaminathan /* CHANNEL *cp, IOCBQ *iocbq); */ 135*82527734SSukumar Swaminathan /* static void emlxs_update_HBQ_index(emlxs_hba_t *hba, */ 136*82527734SSukumar Swaminathan /* uint32_t hbq_id); */ 137*82527734SSukumar Swaminathan /* static void emlxs_hbq_free_all(emlxs_hba_t *hba, */ 138*82527734SSukumar Swaminathan /* uint32_t hbq_id); */ 139*82527734SSukumar Swaminathan static uint32_t emlxs_hbq_setup(emlxs_hba_t *hba, 140*82527734SSukumar Swaminathan uint32_t hbq_id); 141*82527734SSukumar Swaminathan extern void emlxs_sli3_timer(emlxs_hba_t *hba); 142*82527734SSukumar Swaminathan 143*82527734SSukumar Swaminathan extern void emlxs_sli3_poll_erratt(emlxs_hba_t *hba); 144*82527734SSukumar Swaminathan 145*82527734SSukumar Swaminathan 146*82527734SSukumar Swaminathan /* Define SLI3 API functions */ 147*82527734SSukumar Swaminathan emlxs_sli_api_t emlxs_sli3_api = { 148*82527734SSukumar Swaminathan emlxs_sli3_map_hdw, 149*82527734SSukumar Swaminathan emlxs_sli3_unmap_hdw, 150*82527734SSukumar Swaminathan emlxs_sli3_online, 151*82527734SSukumar Swaminathan emlxs_sli3_offline, 152*82527734SSukumar Swaminathan emlxs_sli3_hba_reset, 153*82527734SSukumar Swaminathan emlxs_sli3_hba_kill, 154*82527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd, 155*82527734SSukumar Swaminathan emlxs_sli3_issue_mbox_cmd, 156*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 157*82527734SSukumar Swaminathan emlxs_sli3_prep_fct_iocb, 158*82527734SSukumar Swaminathan #else 159*82527734SSukumar Swaminathan NULL, 160*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 161*82527734SSukumar Swaminathan emlxs_sli3_prep_fcp_iocb, 162*82527734SSukumar Swaminathan emlxs_sli3_prep_ip_iocb, 163*82527734SSukumar Swaminathan emlxs_sli3_prep_els_iocb, 164*82527734SSukumar Swaminathan emlxs_sli3_prep_ct_iocb, 165*82527734SSukumar Swaminathan emlxs_sli3_poll_intr, 166*82527734SSukumar Swaminathan emlxs_sli3_intx_intr, 167*82527734SSukumar Swaminathan emlxs_sli3_msi_intr, 168*82527734SSukumar Swaminathan emlxs_sli3_disable_intr, 169*82527734SSukumar Swaminathan emlxs_sli3_timer, 170*82527734SSukumar Swaminathan emlxs_sli3_poll_erratt 171*82527734SSukumar Swaminathan }; 172291a2b48SSukumar Swaminathan 173291a2b48SSukumar Swaminathan 174*82527734SSukumar Swaminathan /* 175*82527734SSukumar Swaminathan * emlxs_sli3_online() 176*82527734SSukumar Swaminathan * 177*82527734SSukumar Swaminathan * This routine will start initialization of the SLI2/3 HBA. 178*82527734SSukumar Swaminathan */ 179*82527734SSukumar Swaminathan static int32_t 180*82527734SSukumar Swaminathan emlxs_sli3_online(emlxs_hba_t *hba) 181*82527734SSukumar Swaminathan { 182*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 183*82527734SSukumar Swaminathan emlxs_config_t *cfg; 184*82527734SSukumar Swaminathan emlxs_vpd_t *vpd; 185*82527734SSukumar Swaminathan MAILBOX *mb = NULL; 186*82527734SSukumar Swaminathan MAILBOXQ *mbq = NULL; 187*82527734SSukumar Swaminathan RING *rp; 188*82527734SSukumar Swaminathan CHANNEL *cp; 189*82527734SSukumar Swaminathan MATCHMAP *mp = NULL; 190*82527734SSukumar Swaminathan MATCHMAP *mp1 = NULL; 191*82527734SSukumar Swaminathan uint8_t *inptr; 192*82527734SSukumar Swaminathan uint8_t *outptr; 193*82527734SSukumar Swaminathan uint32_t status; 194*82527734SSukumar Swaminathan uint32_t i; 195*82527734SSukumar Swaminathan uint32_t j; 196*82527734SSukumar Swaminathan uint32_t read_rev_reset; 197*82527734SSukumar Swaminathan uint32_t key = 0; 198*82527734SSukumar Swaminathan uint32_t fw_check; 199*82527734SSukumar Swaminathan uint32_t rval = 0; 200*82527734SSukumar Swaminathan uint32_t offset; 201*82527734SSukumar Swaminathan uint8_t vpd_data[DMP_VPD_SIZE]; 202*82527734SSukumar Swaminathan uint32_t MaxRbusSize; 203*82527734SSukumar Swaminathan uint32_t MaxIbusSize; 204*82527734SSukumar Swaminathan uint32_t sli_mode; 205*82527734SSukumar Swaminathan uint32_t sli_mode_mask; 206291a2b48SSukumar Swaminathan 207*82527734SSukumar Swaminathan cfg = &CFG; 208*82527734SSukumar Swaminathan vpd = &VPD; 209*82527734SSukumar Swaminathan MaxRbusSize = 0; 210*82527734SSukumar Swaminathan MaxIbusSize = 0; 211*82527734SSukumar Swaminathan read_rev_reset = 0; 212*82527734SSukumar Swaminathan hba->chan_count = MAX_RINGS; 213291a2b48SSukumar Swaminathan 214*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 215*82527734SSukumar Swaminathan (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba)); 216*82527734SSukumar Swaminathan } 217291a2b48SSukumar Swaminathan 218*82527734SSukumar Swaminathan /* Initialize sli mode based on configuration parameter */ 219*82527734SSukumar Swaminathan switch (cfg[CFG_SLI_MODE].current) { 220*82527734SSukumar Swaminathan case 2: /* SLI2 mode */ 221*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 222*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 223*82527734SSukumar Swaminathan break; 224291a2b48SSukumar Swaminathan 225*82527734SSukumar Swaminathan case 3: /* SLI3 mode */ 226*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 227*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 228*82527734SSukumar Swaminathan break; 229291a2b48SSukumar Swaminathan 230*82527734SSukumar Swaminathan case 0: /* Best available */ 231*82527734SSukumar Swaminathan case 1: /* Best available */ 232*82527734SSukumar Swaminathan default: 233*82527734SSukumar Swaminathan if (hba->model_info.sli_mask & EMLXS_SLI3_MASK) { 234*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 235*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 236*82527734SSukumar Swaminathan } else if (hba->model_info.sli_mask & EMLXS_SLI2_MASK) { 237*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 238*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 239*82527734SSukumar Swaminathan } 240*82527734SSukumar Swaminathan } 241*82527734SSukumar Swaminathan /* SBUS adapters only available in SLI2 */ 242*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 243*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 244*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 245291a2b48SSukumar Swaminathan } 246291a2b48SSukumar Swaminathan 247*82527734SSukumar Swaminathan /* Set the fw_check flag */ 248*82527734SSukumar Swaminathan fw_check = cfg[CFG_FW_CHECK].current; 249291a2b48SSukumar Swaminathan 250*82527734SSukumar Swaminathan hba->mbox_queue_flag = 0; 251*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy = 0; 252*82527734SSukumar Swaminathan hba->fc_edtov = FF_DEF_EDTOV; 253*82527734SSukumar Swaminathan hba->fc_ratov = FF_DEF_RATOV; 254*82527734SSukumar Swaminathan hba->fc_altov = FF_DEF_ALTOV; 255*82527734SSukumar Swaminathan hba->fc_arbtov = FF_DEF_ARBTOV; 256291a2b48SSukumar Swaminathan 257291a2b48SSukumar Swaminathan /* 258*82527734SSukumar Swaminathan * Get a buffer which will be used repeatedly for mailbox commands 259291a2b48SSukumar Swaminathan */ 260*82527734SSukumar Swaminathan mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)), KM_SLEEP); 261291a2b48SSukumar Swaminathan 262*82527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 263*82527734SSukumar Swaminathan reset: 264291a2b48SSukumar Swaminathan 265*82527734SSukumar Swaminathan /* Reset & Initialize the adapter */ 266*82527734SSukumar Swaminathan if (emlxs_sli3_hba_init(hba)) { 267*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 268*82527734SSukumar Swaminathan "Unable to init hba."); 269291a2b48SSukumar Swaminathan 270*82527734SSukumar Swaminathan rval = EIO; 271*82527734SSukumar Swaminathan goto failed; 272*82527734SSukumar Swaminathan } 273291a2b48SSukumar Swaminathan 274*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 275*82527734SSukumar Swaminathan /* Access handle validation */ 276*82527734SSukumar Swaminathan if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 277*82527734SSukumar Swaminathan != DDI_FM_OK) || 278*82527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 279*82527734SSukumar Swaminathan != DDI_FM_OK) || 280*82527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 281*82527734SSukumar Swaminathan != DDI_FM_OK)) { 282*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 283*82527734SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 284*82527734SSukumar Swaminathan 285*82527734SSukumar Swaminathan rval = EIO; 286*82527734SSukumar Swaminathan goto failed; 287291a2b48SSukumar Swaminathan } 288*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 289291a2b48SSukumar Swaminathan 290*82527734SSukumar Swaminathan /* Check for the LP9802 (This is a special case) */ 291*82527734SSukumar Swaminathan /* We need to check for dual channel adapter */ 292*82527734SSukumar Swaminathan if (hba->model_info.device_id == PCI_DEVICE_ID_LP9802) { 293*82527734SSukumar Swaminathan /* Try to determine if this is a DC adapter */ 294*82527734SSukumar Swaminathan if (emlxs_get_max_sram(hba, &MaxRbusSize, &MaxIbusSize) == 0) { 295*82527734SSukumar Swaminathan if (MaxRbusSize == REDUCED_SRAM_CFG) { 296*82527734SSukumar Swaminathan /* LP9802DC */ 297*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 298*82527734SSukumar Swaminathan if (emlxs_pci_model[i].id == LP9802DC) { 299*82527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 300*82527734SSukumar Swaminathan &hba->model_info, 301*82527734SSukumar Swaminathan sizeof (emlxs_model_t)); 302*82527734SSukumar Swaminathan break; 303*82527734SSukumar Swaminathan } 304*82527734SSukumar Swaminathan } 305*82527734SSukumar Swaminathan } else if (hba->model_info.id != LP9802) { 306*82527734SSukumar Swaminathan /* LP9802 */ 307*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 308*82527734SSukumar Swaminathan if (emlxs_pci_model[i].id == LP9802) { 309*82527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 310*82527734SSukumar Swaminathan &hba->model_info, 311*82527734SSukumar Swaminathan sizeof (emlxs_model_t)); 312*82527734SSukumar Swaminathan break; 313*82527734SSukumar Swaminathan } 314*82527734SSukumar Swaminathan } 315*82527734SSukumar Swaminathan } 316*82527734SSukumar Swaminathan } 317*82527734SSukumar Swaminathan } 318291a2b48SSukumar Swaminathan 319291a2b48SSukumar Swaminathan /* 320*82527734SSukumar Swaminathan * Setup and issue mailbox READ REV command 321291a2b48SSukumar Swaminathan */ 322*82527734SSukumar Swaminathan vpd->opFwRev = 0; 323*82527734SSukumar Swaminathan vpd->postKernRev = 0; 324*82527734SSukumar Swaminathan vpd->sli1FwRev = 0; 325*82527734SSukumar Swaminathan vpd->sli2FwRev = 0; 326*82527734SSukumar Swaminathan vpd->sli3FwRev = 0; 327*82527734SSukumar Swaminathan vpd->sli4FwRev = 0; 328*82527734SSukumar Swaminathan 329*82527734SSukumar Swaminathan vpd->postKernName[0] = 0; 330*82527734SSukumar Swaminathan vpd->opFwName[0] = 0; 331*82527734SSukumar Swaminathan vpd->sli1FwName[0] = 0; 332*82527734SSukumar Swaminathan vpd->sli2FwName[0] = 0; 333*82527734SSukumar Swaminathan vpd->sli3FwName[0] = 0; 334*82527734SSukumar Swaminathan vpd->sli4FwName[0] = 0; 335*82527734SSukumar Swaminathan 336*82527734SSukumar Swaminathan vpd->opFwLabel[0] = 0; 337*82527734SSukumar Swaminathan vpd->sli1FwLabel[0] = 0; 338*82527734SSukumar Swaminathan vpd->sli2FwLabel[0] = 0; 339*82527734SSukumar Swaminathan vpd->sli3FwLabel[0] = 0; 340*82527734SSukumar Swaminathan vpd->sli4FwLabel[0] = 0; 341*82527734SSukumar Swaminathan 342*82527734SSukumar Swaminathan /* Sanity check */ 343*82527734SSukumar Swaminathan if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 344*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 345*82527734SSukumar Swaminathan "Adapter / SLI mode mismatch mask:x%x", 346*82527734SSukumar Swaminathan hba->model_info.sli_mask); 347*82527734SSukumar Swaminathan 348*82527734SSukumar Swaminathan rval = EIO; 349*82527734SSukumar Swaminathan goto failed; 350291a2b48SSukumar Swaminathan } 351291a2b48SSukumar Swaminathan 352*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_REV); 353*82527734SSukumar Swaminathan emlxs_mb_read_rev(hba, mbq, 0); 354*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 355*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 356*82527734SSukumar Swaminathan "Unable to read rev. Mailbox cmd=%x status=%x", 357*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 358291a2b48SSukumar Swaminathan 359*82527734SSukumar Swaminathan rval = EIO; 360*82527734SSukumar Swaminathan goto failed; 361291a2b48SSukumar Swaminathan } 362291a2b48SSukumar Swaminathan 363*82527734SSukumar Swaminathan if (mb->un.varRdRev.rr == 0) { 364*82527734SSukumar Swaminathan /* Old firmware */ 365*82527734SSukumar Swaminathan if (read_rev_reset == 0) { 366*82527734SSukumar Swaminathan read_rev_reset = 1; 367291a2b48SSukumar Swaminathan 368*82527734SSukumar Swaminathan goto reset; 369*82527734SSukumar Swaminathan } else { 370*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 371*82527734SSukumar Swaminathan "Outdated firmware detected."); 372*82527734SSukumar Swaminathan } 373291a2b48SSukumar Swaminathan 374*82527734SSukumar Swaminathan vpd->rBit = 0; 375*82527734SSukumar Swaminathan } else { 376*82527734SSukumar Swaminathan if (mb->un.varRdRev.un.b.ProgType != FUNC_FIRMWARE) { 377*82527734SSukumar Swaminathan if (read_rev_reset == 0) { 378*82527734SSukumar Swaminathan read_rev_reset = 1; 379291a2b48SSukumar Swaminathan 380*82527734SSukumar Swaminathan goto reset; 381*82527734SSukumar Swaminathan } else { 382*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 383*82527734SSukumar Swaminathan "Non-operational firmware detected. " 384*82527734SSukumar Swaminathan "type=%x", 385*82527734SSukumar Swaminathan mb->un.varRdRev.un.b.ProgType); 386*82527734SSukumar Swaminathan } 387*82527734SSukumar Swaminathan } 388291a2b48SSukumar Swaminathan 389*82527734SSukumar Swaminathan vpd->rBit = 1; 390*82527734SSukumar Swaminathan vpd->sli1FwRev = mb->un.varRdRev.sliFwRev1; 391*82527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName1, vpd->sli1FwLabel, 392*82527734SSukumar Swaminathan 16); 393*82527734SSukumar Swaminathan vpd->sli2FwRev = mb->un.varRdRev.sliFwRev2; 394*82527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName2, vpd->sli2FwLabel, 395*82527734SSukumar Swaminathan 16); 396291a2b48SSukumar Swaminathan 397*82527734SSukumar Swaminathan /* 398*82527734SSukumar Swaminathan * Lets try to read the SLI3 version 399*82527734SSukumar Swaminathan * Setup and issue mailbox READ REV(v3) command 400*82527734SSukumar Swaminathan */ 401*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_REV); 402*82527734SSukumar Swaminathan 403*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 404*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 405*82527734SSukumar Swaminathan 406*82527734SSukumar Swaminathan emlxs_mb_read_rev(hba, mbq, 1); 407*82527734SSukumar Swaminathan 408*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 409*82527734SSukumar Swaminathan MBX_SUCCESS) { 410*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 411*82527734SSukumar Swaminathan "Unable to read rev (v3). Mailbox cmd=%x status=%x", 412*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 413*82527734SSukumar Swaminathan 414*82527734SSukumar Swaminathan rval = EIO; 415*82527734SSukumar Swaminathan goto failed; 416*82527734SSukumar Swaminathan } 417*82527734SSukumar Swaminathan 418*82527734SSukumar Swaminathan if (mb->un.varRdRev.rf3) { 419*82527734SSukumar Swaminathan /* 420*82527734SSukumar Swaminathan * vpd->sli2FwRev = mb->un.varRdRev.sliFwRev1; 421*82527734SSukumar Swaminathan * Not needed 422*82527734SSukumar Swaminathan */ 423*82527734SSukumar Swaminathan vpd->sli3FwRev = mb->un.varRdRev.sliFwRev2; 424*82527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.sliFwName2, 425*82527734SSukumar Swaminathan vpd->sli3FwLabel, 16); 426*82527734SSukumar Swaminathan } 427291a2b48SSukumar Swaminathan } 428291a2b48SSukumar Swaminathan 429*82527734SSukumar Swaminathan 430*82527734SSukumar Swaminathan if ((sli_mode == EMLXS_HBA_SLI3_MODE) && (vpd->sli3FwRev == 0)) { 431*82527734SSukumar Swaminathan if (vpd->sli2FwRev) { 432*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 433*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 434*82527734SSukumar Swaminathan } else { 435*82527734SSukumar Swaminathan sli_mode = 0; 436*82527734SSukumar Swaminathan sli_mode_mask = 0; 437*82527734SSukumar Swaminathan } 438291a2b48SSukumar Swaminathan } 439291a2b48SSukumar Swaminathan 440*82527734SSukumar Swaminathan else if ((sli_mode == EMLXS_HBA_SLI2_MODE) && (vpd->sli2FwRev == 0)) { 441*82527734SSukumar Swaminathan if (vpd->sli3FwRev) { 442*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI3_MODE; 443*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI3_MASK; 444291a2b48SSukumar Swaminathan } else { 445*82527734SSukumar Swaminathan sli_mode = 0; 446*82527734SSukumar Swaminathan sli_mode_mask = 0; 447291a2b48SSukumar Swaminathan } 448291a2b48SSukumar Swaminathan } 449291a2b48SSukumar Swaminathan 450*82527734SSukumar Swaminathan if (!(hba->model_info.sli_mask & sli_mode_mask)) { 451*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 452*82527734SSukumar Swaminathan "Firmware not available. sli-mode=%d", 453*82527734SSukumar Swaminathan cfg[CFG_SLI_MODE].current); 454291a2b48SSukumar Swaminathan 455*82527734SSukumar Swaminathan rval = EIO; 456*82527734SSukumar Swaminathan goto failed; 457*82527734SSukumar Swaminathan } 458291a2b48SSukumar Swaminathan 459*82527734SSukumar Swaminathan /* Save information as VPD data */ 460*82527734SSukumar Swaminathan vpd->postKernRev = mb->un.varRdRev.postKernRev; 461*82527734SSukumar Swaminathan vpd->opFwRev = mb->un.varRdRev.opFwRev; 462*82527734SSukumar Swaminathan bcopy((char *)mb->un.varRdRev.opFwName, vpd->opFwLabel, 16); 463*82527734SSukumar Swaminathan vpd->biuRev = mb->un.varRdRev.biuRev; 464*82527734SSukumar Swaminathan vpd->smRev = mb->un.varRdRev.smRev; 465*82527734SSukumar Swaminathan vpd->smFwRev = mb->un.varRdRev.un.smFwRev; 466*82527734SSukumar Swaminathan vpd->endecRev = mb->un.varRdRev.endecRev; 467*82527734SSukumar Swaminathan vpd->fcphHigh = mb->un.varRdRev.fcphHigh; 468*82527734SSukumar Swaminathan vpd->fcphLow = mb->un.varRdRev.fcphLow; 469*82527734SSukumar Swaminathan vpd->feaLevelHigh = mb->un.varRdRev.feaLevelHigh; 470*82527734SSukumar Swaminathan vpd->feaLevelLow = mb->un.varRdRev.feaLevelLow; 471*82527734SSukumar Swaminathan 472*82527734SSukumar Swaminathan /* Decode FW names */ 473*82527734SSukumar Swaminathan emlxs_decode_version(vpd->postKernRev, vpd->postKernName); 474*82527734SSukumar Swaminathan emlxs_decode_version(vpd->opFwRev, vpd->opFwName); 475*82527734SSukumar Swaminathan emlxs_decode_version(vpd->sli1FwRev, vpd->sli1FwName); 476*82527734SSukumar Swaminathan emlxs_decode_version(vpd->sli2FwRev, vpd->sli2FwName); 477*82527734SSukumar Swaminathan emlxs_decode_version(vpd->sli3FwRev, vpd->sli3FwName); 478*82527734SSukumar Swaminathan emlxs_decode_version(vpd->sli4FwRev, vpd->sli4FwName); 479*82527734SSukumar Swaminathan 480*82527734SSukumar Swaminathan /* Decode FW labels */ 481*82527734SSukumar Swaminathan emlxs_decode_label(vpd->opFwLabel, vpd->opFwLabel, 1); 482*82527734SSukumar Swaminathan emlxs_decode_label(vpd->sli1FwLabel, vpd->sli1FwLabel, 1); 483*82527734SSukumar Swaminathan emlxs_decode_label(vpd->sli2FwLabel, vpd->sli2FwLabel, 1); 484*82527734SSukumar Swaminathan emlxs_decode_label(vpd->sli3FwLabel, vpd->sli3FwLabel, 1); 485*82527734SSukumar Swaminathan emlxs_decode_label(vpd->sli4FwLabel, vpd->sli4FwLabel, 1); 486*82527734SSukumar Swaminathan 487*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 488*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 489*82527734SSukumar Swaminathan 490*82527734SSukumar Swaminathan key = emlxs_get_key(hba, mbq); 491*82527734SSukumar Swaminathan 492*82527734SSukumar Swaminathan /* Get adapter VPD information */ 493*82527734SSukumar Swaminathan offset = 0; 494*82527734SSukumar Swaminathan bzero(vpd_data, sizeof (vpd_data)); 495*82527734SSukumar Swaminathan vpd->port_index = (uint32_t)-1; 496291a2b48SSukumar Swaminathan 497*82527734SSukumar Swaminathan while (offset < DMP_VPD_SIZE) { 498*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 499*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 500291a2b48SSukumar Swaminathan 501*82527734SSukumar Swaminathan emlxs_mb_dump_vpd(hba, mbq, offset); 502*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 503*82527734SSukumar Swaminathan MBX_SUCCESS) { 504*82527734SSukumar Swaminathan /* 505*82527734SSukumar Swaminathan * Let it go through even if failed. 506*82527734SSukumar Swaminathan * Not all adapter's have VPD info and thus will 507*82527734SSukumar Swaminathan * fail here. This is not a problem 508*82527734SSukumar Swaminathan */ 509291a2b48SSukumar Swaminathan 510*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 511*82527734SSukumar Swaminathan "No VPD found. offset=%x status=%x", offset, 512*82527734SSukumar Swaminathan mb->mbxStatus); 513*82527734SSukumar Swaminathan break; 514*82527734SSukumar Swaminathan } else { 515*82527734SSukumar Swaminathan if (mb->un.varDmp.ra == 1) { 516*82527734SSukumar Swaminathan uint32_t *lp1, *lp2; 517*82527734SSukumar Swaminathan uint32_t bsize; 518*82527734SSukumar Swaminathan uint32_t wsize; 519291a2b48SSukumar Swaminathan 520*82527734SSukumar Swaminathan /* 521*82527734SSukumar Swaminathan * mb->un.varDmp.word_cnt is actually byte 522*82527734SSukumar Swaminathan * count for the dump reply 523*82527734SSukumar Swaminathan */ 524*82527734SSukumar Swaminathan bsize = mb->un.varDmp.word_cnt; 525291a2b48SSukumar Swaminathan 526*82527734SSukumar Swaminathan /* Stop if no data was received */ 527*82527734SSukumar Swaminathan if (bsize == 0) { 528*82527734SSukumar Swaminathan break; 529*82527734SSukumar Swaminathan } 530291a2b48SSukumar Swaminathan 531*82527734SSukumar Swaminathan /* Check limit on byte size */ 532*82527734SSukumar Swaminathan bsize = (bsize > 533*82527734SSukumar Swaminathan (sizeof (vpd_data) - offset)) ? 534*82527734SSukumar Swaminathan (sizeof (vpd_data) - offset) : bsize; 535291a2b48SSukumar Swaminathan 536*82527734SSukumar Swaminathan /* 537*82527734SSukumar Swaminathan * Convert size from bytes to words with 538*82527734SSukumar Swaminathan * minimum of 1 word 539*82527734SSukumar Swaminathan */ 540*82527734SSukumar Swaminathan wsize = (bsize > 4) ? (bsize >> 2) : 1; 541291a2b48SSukumar Swaminathan 542*82527734SSukumar Swaminathan /* 543*82527734SSukumar Swaminathan * Transfer data into vpd_data buffer one 544*82527734SSukumar Swaminathan * word at a time 545*82527734SSukumar Swaminathan */ 546*82527734SSukumar Swaminathan lp1 = (uint32_t *)&mb->un.varDmp.resp_offset; 547*82527734SSukumar Swaminathan lp2 = (uint32_t *)&vpd_data[offset]; 548291a2b48SSukumar Swaminathan 549*82527734SSukumar Swaminathan for (i = 0; i < wsize; i++) { 550*82527734SSukumar Swaminathan status = *lp1++; 551*82527734SSukumar Swaminathan *lp2++ = BE_SWAP32(status); 552*82527734SSukumar Swaminathan } 553291a2b48SSukumar Swaminathan 554*82527734SSukumar Swaminathan /* Increment total byte count saved */ 555*82527734SSukumar Swaminathan offset += (wsize << 2); 556291a2b48SSukumar Swaminathan 557*82527734SSukumar Swaminathan /* 558*82527734SSukumar Swaminathan * Stop if less than a full transfer was 559*82527734SSukumar Swaminathan * received 560*82527734SSukumar Swaminathan */ 561*82527734SSukumar Swaminathan if (wsize < DMP_VPD_DUMP_WCOUNT) { 562*82527734SSukumar Swaminathan break; 563*82527734SSukumar Swaminathan } 564291a2b48SSukumar Swaminathan 565*82527734SSukumar Swaminathan } else { 566*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 567*82527734SSukumar Swaminathan &emlxs_init_debug_msg, 568*82527734SSukumar Swaminathan "No VPD acknowledgment. offset=%x", 569*82527734SSukumar Swaminathan offset); 570*82527734SSukumar Swaminathan break; 571*82527734SSukumar Swaminathan } 572*82527734SSukumar Swaminathan } 573291a2b48SSukumar Swaminathan 574291a2b48SSukumar Swaminathan } 575291a2b48SSukumar Swaminathan 576*82527734SSukumar Swaminathan if (vpd_data[0]) { 577*82527734SSukumar Swaminathan (void) emlxs_parse_vpd(hba, (uint8_t *)vpd_data, offset); 578291a2b48SSukumar Swaminathan 579*82527734SSukumar Swaminathan /* 580*82527734SSukumar Swaminathan * If there is a VPD part number, and it does not 581*82527734SSukumar Swaminathan * match the current default HBA model info, 582*82527734SSukumar Swaminathan * replace the default data with an entry that 583*82527734SSukumar Swaminathan * does match. 584*82527734SSukumar Swaminathan * 585*82527734SSukumar Swaminathan * After emlxs_parse_vpd model holds the VPD value 586*82527734SSukumar Swaminathan * for V2 and part_num hold the value for PN. These 587*82527734SSukumar Swaminathan * 2 values are NOT necessarily the same. 588*82527734SSukumar Swaminathan */ 589291a2b48SSukumar Swaminathan 590*82527734SSukumar Swaminathan rval = 0; 591*82527734SSukumar Swaminathan if ((vpd->model[0] != 0) && 592*82527734SSukumar Swaminathan (strcmp(&vpd->model[0], hba->model_info.model) != 0)) { 593291a2b48SSukumar Swaminathan 594*82527734SSukumar Swaminathan /* First scan for a V2 match */ 595291a2b48SSukumar Swaminathan 596*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 597*82527734SSukumar Swaminathan if (strcmp(&vpd->model[0], 598*82527734SSukumar Swaminathan emlxs_pci_model[i].model) == 0) { 599*82527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 600*82527734SSukumar Swaminathan &hba->model_info, 601*82527734SSukumar Swaminathan sizeof (emlxs_model_t)); 602*82527734SSukumar Swaminathan rval = 1; 603*82527734SSukumar Swaminathan break; 604*82527734SSukumar Swaminathan } 605*82527734SSukumar Swaminathan } 606*82527734SSukumar Swaminathan } 607291a2b48SSukumar Swaminathan 608*82527734SSukumar Swaminathan if (!rval && (vpd->part_num[0] != 0) && 609*82527734SSukumar Swaminathan (strcmp(&vpd->part_num[0], hba->model_info.model) != 0)) { 610291a2b48SSukumar Swaminathan 611*82527734SSukumar Swaminathan /* Next scan for a PN match */ 612291a2b48SSukumar Swaminathan 613*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 614*82527734SSukumar Swaminathan if (strcmp(&vpd->part_num[0], 615*82527734SSukumar Swaminathan emlxs_pci_model[i].model) == 0) { 616*82527734SSukumar Swaminathan bcopy(&emlxs_pci_model[i], 617*82527734SSukumar Swaminathan &hba->model_info, 618*82527734SSukumar Swaminathan sizeof (emlxs_model_t)); 619*82527734SSukumar Swaminathan break; 620*82527734SSukumar Swaminathan } 621*82527734SSukumar Swaminathan } 622*82527734SSukumar Swaminathan } 623291a2b48SSukumar Swaminathan 624*82527734SSukumar Swaminathan /* 625*82527734SSukumar Swaminathan * Now lets update hba->model_info with the real 626*82527734SSukumar Swaminathan * VPD data, if any. 627*82527734SSukumar Swaminathan */ 628291a2b48SSukumar Swaminathan 629*82527734SSukumar Swaminathan /* 630*82527734SSukumar Swaminathan * Replace the default model description with vpd data 631*82527734SSukumar Swaminathan */ 632*82527734SSukumar Swaminathan if (vpd->model_desc[0] != 0) { 633*82527734SSukumar Swaminathan (void) strcpy(hba->model_info.model_desc, 634*82527734SSukumar Swaminathan vpd->model_desc); 635291a2b48SSukumar Swaminathan } 636291a2b48SSukumar Swaminathan 637*82527734SSukumar Swaminathan /* Replace the default model with vpd data */ 638*82527734SSukumar Swaminathan if (vpd->model[0] != 0) { 639*82527734SSukumar Swaminathan (void) strcpy(hba->model_info.model, vpd->model); 640*82527734SSukumar Swaminathan } 641*82527734SSukumar Swaminathan 642*82527734SSukumar Swaminathan /* Replace the default program types with vpd data */ 643*82527734SSukumar Swaminathan if (vpd->prog_types[0] != 0) { 644*82527734SSukumar Swaminathan emlxs_parse_prog_types(hba, vpd->prog_types); 645*82527734SSukumar Swaminathan } 646291a2b48SSukumar Swaminathan } 647291a2b48SSukumar Swaminathan 648291a2b48SSukumar Swaminathan /* 649*82527734SSukumar Swaminathan * Since the adapter model may have changed with the vpd data 650*82527734SSukumar Swaminathan * lets double check if adapter is not supported 651291a2b48SSukumar Swaminathan */ 652*82527734SSukumar Swaminathan if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 653*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 654*82527734SSukumar Swaminathan "Unsupported adapter found. " 655*82527734SSukumar Swaminathan "Id:%d Device id:0x%x SSDID:0x%x Model:%s", 656*82527734SSukumar Swaminathan hba->model_info.id, hba->model_info.device_id, 657*82527734SSukumar Swaminathan hba->model_info.ssdid, hba->model_info.model); 658*82527734SSukumar Swaminathan 659*82527734SSukumar Swaminathan rval = EIO; 660*82527734SSukumar Swaminathan goto failed; 661*82527734SSukumar Swaminathan } 662291a2b48SSukumar Swaminathan 663*82527734SSukumar Swaminathan /* Read the adapter's wakeup parms */ 664*82527734SSukumar Swaminathan (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 665*82527734SSukumar Swaminathan emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 666*82527734SSukumar Swaminathan vpd->boot_version); 667291a2b48SSukumar Swaminathan 668*82527734SSukumar Swaminathan /* Get fcode version property */ 669*82527734SSukumar Swaminathan emlxs_get_fcode_version(hba); 670291a2b48SSukumar Swaminathan 671*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 672*82527734SSukumar Swaminathan "Firmware: kern=%08x stub=%08x sli1=%08x", vpd->postKernRev, 673*82527734SSukumar Swaminathan vpd->opFwRev, vpd->sli1FwRev); 674291a2b48SSukumar Swaminathan 675*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 676*82527734SSukumar Swaminathan "Firmware: sli2=%08x sli3=%08x sli4=%08x fl=%x", vpd->sli2FwRev, 677*82527734SSukumar Swaminathan vpd->sli3FwRev, vpd->sli4FwRev, vpd->feaLevelHigh); 678291a2b48SSukumar Swaminathan 679*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 680*82527734SSukumar Swaminathan "BIOS: boot=%s fcode=%s", vpd->boot_version, vpd->fcode_version); 681291a2b48SSukumar Swaminathan 682*82527734SSukumar Swaminathan /* 683*82527734SSukumar Swaminathan * If firmware checking is enabled and the adapter model indicates 684*82527734SSukumar Swaminathan * a firmware image, then perform firmware version check 685*82527734SSukumar Swaminathan */ 686*82527734SSukumar Swaminathan if (((fw_check == 1) && (hba->model_info.flags & EMLXS_SUN_BRANDED) && 687*82527734SSukumar Swaminathan hba->model_info.fwid) || ((fw_check == 2) && 688*82527734SSukumar Swaminathan hba->model_info.fwid)) { 689*82527734SSukumar Swaminathan emlxs_firmware_t *fw; 690*82527734SSukumar Swaminathan 691*82527734SSukumar Swaminathan /* Find firmware image indicated by adapter model */ 692*82527734SSukumar Swaminathan fw = NULL; 693*82527734SSukumar Swaminathan for (i = 0; i < emlxs_fw_count; i++) { 694*82527734SSukumar Swaminathan if (emlxs_fw_table[i].id == hba->model_info.fwid) { 695*82527734SSukumar Swaminathan fw = &emlxs_fw_table[i]; 696*82527734SSukumar Swaminathan break; 697*82527734SSukumar Swaminathan } 698291a2b48SSukumar Swaminathan } 699291a2b48SSukumar Swaminathan 700291a2b48SSukumar Swaminathan /* 701*82527734SSukumar Swaminathan * If the image was found, then verify current firmware 702*82527734SSukumar Swaminathan * versions of adapter 703291a2b48SSukumar Swaminathan */ 704*82527734SSukumar Swaminathan if (fw) { 705*82527734SSukumar Swaminathan if ((fw->kern && (vpd->postKernRev != fw->kern)) || 706*82527734SSukumar Swaminathan (fw->stub && (vpd->opFwRev != fw->stub)) || 707*82527734SSukumar Swaminathan (fw->sli1 && (vpd->sli1FwRev != fw->sli1)) || 708*82527734SSukumar Swaminathan (fw->sli2 && (vpd->sli2FwRev != fw->sli2)) || 709*82527734SSukumar Swaminathan (fw->sli3 && (vpd->sli3FwRev != fw->sli3)) || 710*82527734SSukumar Swaminathan (fw->sli4 && (vpd->sli4FwRev != fw->sli4))) { 711*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 712*82527734SSukumar Swaminathan "Firmware update needed. " 713*82527734SSukumar Swaminathan "Updating. id=%d fw=%d", 714*82527734SSukumar Swaminathan hba->model_info.id, hba->model_info.fwid); 715*82527734SSukumar Swaminathan 716*82527734SSukumar Swaminathan #ifdef MODFW_SUPPORT 717*82527734SSukumar Swaminathan /* 718*82527734SSukumar Swaminathan * Load the firmware image now 719*82527734SSukumar Swaminathan * If MODFW_SUPPORT is not defined, the 720*82527734SSukumar Swaminathan * firmware image will already be defined 721*82527734SSukumar Swaminathan * in the emlxs_fw_table 722*82527734SSukumar Swaminathan */ 723*82527734SSukumar Swaminathan emlxs_fw_load(hba, fw); 724*82527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 725291a2b48SSukumar Swaminathan 726*82527734SSukumar Swaminathan if (fw->image && fw->size) { 727*82527734SSukumar Swaminathan if (emlxs_fw_download(hba, 728*82527734SSukumar Swaminathan (char *)fw->image, fw->size, 0)) { 729*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 730*82527734SSukumar Swaminathan &emlxs_init_msg, 731*82527734SSukumar Swaminathan "Firmware update failed."); 732*82527734SSukumar Swaminathan } 733*82527734SSukumar Swaminathan #ifdef MODFW_SUPPORT 734*82527734SSukumar Swaminathan /* 735*82527734SSukumar Swaminathan * Unload the firmware image from 736*82527734SSukumar Swaminathan * kernel memory 737*82527734SSukumar Swaminathan */ 738*82527734SSukumar Swaminathan emlxs_fw_unload(hba, fw); 739*82527734SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 740291a2b48SSukumar Swaminathan 741*82527734SSukumar Swaminathan fw_check = 0; 742*82527734SSukumar Swaminathan 743*82527734SSukumar Swaminathan goto reset; 744*82527734SSukumar Swaminathan } 745*82527734SSukumar Swaminathan 746*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 747*82527734SSukumar Swaminathan "Firmware image unavailable."); 748*82527734SSukumar Swaminathan } else { 749*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 750*82527734SSukumar Swaminathan "Firmware update not needed."); 751*82527734SSukumar Swaminathan } 752*82527734SSukumar Swaminathan } else { 753*82527734SSukumar Swaminathan /* This should not happen */ 754*82527734SSukumar Swaminathan 755*82527734SSukumar Swaminathan /* 756*82527734SSukumar Swaminathan * This means either the adapter database is not 757*82527734SSukumar Swaminathan * correct or a firmware image is missing from the 758*82527734SSukumar Swaminathan * compile 759*82527734SSukumar Swaminathan */ 760*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 761*82527734SSukumar Swaminathan "Firmware image unavailable. id=%d fw=%d", 762*82527734SSukumar Swaminathan hba->model_info.id, hba->model_info.fwid); 763291a2b48SSukumar Swaminathan } 764291a2b48SSukumar Swaminathan } 765291a2b48SSukumar Swaminathan 766*82527734SSukumar Swaminathan /* 767*82527734SSukumar Swaminathan * Add our interrupt routine to kernel's interrupt chain & enable it 768*82527734SSukumar Swaminathan * If MSI is enabled this will cause Solaris to program the MSI address 769*82527734SSukumar Swaminathan * and data registers in PCI config space 770*82527734SSukumar Swaminathan */ 771*82527734SSukumar Swaminathan if (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) { 772*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 773*82527734SSukumar Swaminathan "Unable to add interrupt(s)."); 7744baa2c25SSukumar Swaminathan 775*82527734SSukumar Swaminathan rval = EIO; 776*82527734SSukumar Swaminathan goto failed; 777*82527734SSukumar Swaminathan } 778291a2b48SSukumar Swaminathan 779*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_CFGPORT); 780291a2b48SSukumar Swaminathan 781*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 782*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 783291a2b48SSukumar Swaminathan 784*82527734SSukumar Swaminathan (void) emlxs_mb_config_port(hba, mbq, sli_mode, key); 785*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 786*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 787*82527734SSukumar Swaminathan "Unable to configure port. " 788*82527734SSukumar Swaminathan "Mailbox cmd=%x status=%x slimode=%d key=%x", 789*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus, sli_mode, key); 790291a2b48SSukumar Swaminathan 791*82527734SSukumar Swaminathan for (sli_mode--; sli_mode > 0; sli_mode--) { 792*82527734SSukumar Swaminathan /* Check if sli_mode is supported by this adapter */ 793*82527734SSukumar Swaminathan if (hba->model_info.sli_mask & 794*82527734SSukumar Swaminathan EMLXS_SLI_MASK(sli_mode)) { 795*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI_MASK(sli_mode); 796*82527734SSukumar Swaminathan break; 797*82527734SSukumar Swaminathan } 798*82527734SSukumar Swaminathan } 7994baa2c25SSukumar Swaminathan 800*82527734SSukumar Swaminathan if (sli_mode) { 801*82527734SSukumar Swaminathan fw_check = 0; 8024baa2c25SSukumar Swaminathan 803*82527734SSukumar Swaminathan goto reset; 804*82527734SSukumar Swaminathan } 805291a2b48SSukumar Swaminathan 806*82527734SSukumar Swaminathan hba->flag &= ~FC_SLIM2_MODE; 807*82527734SSukumar Swaminathan 808*82527734SSukumar Swaminathan rval = EIO; 809*82527734SSukumar Swaminathan goto failed; 810291a2b48SSukumar Swaminathan } 811291a2b48SSukumar Swaminathan 812*82527734SSukumar Swaminathan /* Check if SLI3 mode was achieved */ 813*82527734SSukumar Swaminathan if (mb->un.varCfgPort.rMA && 814*82527734SSukumar Swaminathan (mb->un.varCfgPort.sli_mode == EMLXS_HBA_SLI3_MODE)) { 815291a2b48SSukumar Swaminathan 816*82527734SSukumar Swaminathan if (mb->un.varCfgPort.vpi_max > 1) { 817*82527734SSukumar Swaminathan hba->flag |= FC_NPIV_ENABLED; 818291a2b48SSukumar Swaminathan 819*82527734SSukumar Swaminathan if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 820*82527734SSukumar Swaminathan hba->vpi_max = 821*82527734SSukumar Swaminathan min(mb->un.varCfgPort.vpi_max, 822*82527734SSukumar Swaminathan MAX_VPORTS - 1); 823*82527734SSukumar Swaminathan } else { 824*82527734SSukumar Swaminathan hba->vpi_max = 825*82527734SSukumar Swaminathan min(mb->un.varCfgPort.vpi_max, 826*82527734SSukumar Swaminathan MAX_VPORTS_LIMITED - 1); 827*82527734SSukumar Swaminathan } 828*82527734SSukumar Swaminathan } 829291a2b48SSukumar Swaminathan 830*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV5) 831*82527734SSukumar Swaminathan hba->fca_tran->fca_num_npivports = 832*82527734SSukumar Swaminathan (cfg[CFG_NPIV_ENABLE].current) ? hba->vpi_max : 0; 833*82527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV5 */ 834*82527734SSukumar Swaminathan 835*82527734SSukumar Swaminathan if (mb->un.varCfgPort.gerbm && mb->un.varCfgPort.max_hbq) { 836*82527734SSukumar Swaminathan hba->flag |= FC_HBQ_ENABLED; 837291a2b48SSukumar Swaminathan } 838*82527734SSukumar Swaminathan 839*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 840*82527734SSukumar Swaminathan "SLI3 mode: flag=%x vpi_max=%d", hba->flag, hba->vpi_max); 841*82527734SSukumar Swaminathan } else { 842*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 843*82527734SSukumar Swaminathan "SLI2 mode: flag=%x", hba->flag); 844*82527734SSukumar Swaminathan sli_mode = EMLXS_HBA_SLI2_MODE; 845*82527734SSukumar Swaminathan sli_mode_mask = EMLXS_SLI2_MASK; 846*82527734SSukumar Swaminathan hba->sli_mode = sli_mode; 847291a2b48SSukumar Swaminathan } 848291a2b48SSukumar Swaminathan 849*82527734SSukumar Swaminathan /* Get and save the current firmware version (based on sli_mode) */ 850*82527734SSukumar Swaminathan emlxs_decode_firmware_rev(hba, vpd); 851291a2b48SSukumar Swaminathan 852*82527734SSukumar Swaminathan emlxs_pcix_mxr_update(hba, 0); 853291a2b48SSukumar Swaminathan 854*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 855*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 856291a2b48SSukumar Swaminathan 857*82527734SSukumar Swaminathan emlxs_mb_read_config(hba, mbq); 858*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 859*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 860*82527734SSukumar Swaminathan "Unable to read configuration. Mailbox cmd=%x status=%x", 861*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 862291a2b48SSukumar Swaminathan 863*82527734SSukumar Swaminathan rval = EIO; 864*82527734SSukumar Swaminathan goto failed; 865*82527734SSukumar Swaminathan } 866291a2b48SSukumar Swaminathan 867*82527734SSukumar Swaminathan /* Save the link speed capabilities */ 868*82527734SSukumar Swaminathan vpd->link_speed = mb->un.varRdConfig.lmt; 869*82527734SSukumar Swaminathan emlxs_process_link_speed(hba); 870291a2b48SSukumar Swaminathan 871*82527734SSukumar Swaminathan /* Set the max node count */ 872*82527734SSukumar Swaminathan if (cfg[CFG_NUM_NODES].current > 0) { 873*82527734SSukumar Swaminathan hba->max_nodes = 874*82527734SSukumar Swaminathan min(cfg[CFG_NUM_NODES].current, 875*82527734SSukumar Swaminathan mb->un.varRdConfig.max_rpi); 876*82527734SSukumar Swaminathan } else { 877*82527734SSukumar Swaminathan hba->max_nodes = mb->un.varRdConfig.max_rpi; 878*82527734SSukumar Swaminathan } 879291a2b48SSukumar Swaminathan 880*82527734SSukumar Swaminathan /* Set the io throttle */ 881*82527734SSukumar Swaminathan hba->io_throttle = mb->un.varRdConfig.max_xri - IO_THROTTLE_RESERVE; 882*82527734SSukumar Swaminathan hba->max_iotag = mb->un.varRdConfig.max_xri; 883291a2b48SSukumar Swaminathan 884*82527734SSukumar Swaminathan /* 885*82527734SSukumar Swaminathan * Allocate some memory for buffers 886*82527734SSukumar Swaminathan */ 887*82527734SSukumar Swaminathan if (emlxs_mem_alloc_buffer(hba) == 0) { 888*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 889*82527734SSukumar Swaminathan "Unable to allocate memory buffers."); 890291a2b48SSukumar Swaminathan 891*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 892*82527734SSukumar Swaminathan return (ENOMEM); 893*82527734SSukumar Swaminathan } 894291a2b48SSukumar Swaminathan 895*82527734SSukumar Swaminathan /* 896*82527734SSukumar Swaminathan * Setup and issue mailbox RUN BIU DIAG command Setup test buffers 897*82527734SSukumar Swaminathan */ 898*82527734SSukumar Swaminathan if (((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) || 899*82527734SSukumar Swaminathan ((mp1 = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0)) { 900*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 901*82527734SSukumar Swaminathan "Unable to allocate diag buffers."); 902*82527734SSukumar Swaminathan 903*82527734SSukumar Swaminathan rval = ENOMEM; 904*82527734SSukumar Swaminathan goto failed; 905291a2b48SSukumar Swaminathan } 906291a2b48SSukumar Swaminathan 907*82527734SSukumar Swaminathan bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt, 908*82527734SSukumar Swaminathan MEM_ELSBUF_SIZE); 909*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE, 910*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 911291a2b48SSukumar Swaminathan 912*82527734SSukumar Swaminathan bzero(mp1->virt, MEM_ELSBUF_SIZE); 913*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 914*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 915291a2b48SSukumar Swaminathan 916*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 917*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 918291a2b48SSukumar Swaminathan 919*82527734SSukumar Swaminathan (void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys); 920*82527734SSukumar Swaminathan 921*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 922*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 923*82527734SSukumar Swaminathan "Unable to run BIU diag. Mailbox cmd=%x status=%x", 924*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 925*82527734SSukumar Swaminathan 926*82527734SSukumar Swaminathan rval = EIO; 927*82527734SSukumar Swaminathan goto failed; 928291a2b48SSukumar Swaminathan } 929291a2b48SSukumar Swaminathan 930*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE, 931*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 932291a2b48SSukumar Swaminathan 933*82527734SSukumar Swaminathan outptr = mp->virt; 934*82527734SSukumar Swaminathan inptr = mp1->virt; 935*82527734SSukumar Swaminathan 936*82527734SSukumar Swaminathan for (i = 0; i < MEM_ELSBUF_SIZE; i++) { 937*82527734SSukumar Swaminathan if (*outptr++ != *inptr++) { 938*82527734SSukumar Swaminathan outptr--; 939*82527734SSukumar Swaminathan inptr--; 940*82527734SSukumar Swaminathan 941*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 942*82527734SSukumar Swaminathan "BIU diagnostic failed. " 943*82527734SSukumar Swaminathan "offset %x value %x should be %x.", 944*82527734SSukumar Swaminathan i, (uint32_t)*inptr, (uint32_t)*outptr); 945*82527734SSukumar Swaminathan 946*82527734SSukumar Swaminathan rval = EIO; 947*82527734SSukumar Swaminathan goto failed; 948*82527734SSukumar Swaminathan } 949291a2b48SSukumar Swaminathan } 950291a2b48SSukumar Swaminathan 951*82527734SSukumar Swaminathan hba->channel_fcp = FC_FCP_RING; 952*82527734SSukumar Swaminathan hba->channel_els = FC_ELS_RING; 953*82527734SSukumar Swaminathan hba->channel_ip = FC_IP_RING; 954*82527734SSukumar Swaminathan hba->channel_ct = FC_CT_RING; 955*82527734SSukumar Swaminathan hba->sli.sli3.ring_count = MAX_RINGS; 956291a2b48SSukumar Swaminathan 957*82527734SSukumar Swaminathan hba->channel_tx_count = 0; 958*82527734SSukumar Swaminathan hba->io_count = 0; 959*82527734SSukumar Swaminathan hba->fc_iotag = 1; 960291a2b48SSukumar Swaminathan 961*82527734SSukumar Swaminathan /* 962*82527734SSukumar Swaminathan * OutOfRange (oor) iotags are used for abort or 963*82527734SSukumar Swaminathan * close XRI commands 964*82527734SSukumar Swaminathan */ 965*82527734SSukumar Swaminathan hba->fc_oor_iotag = hba->max_iotag; 966291a2b48SSukumar Swaminathan 967*82527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 968*82527734SSukumar Swaminathan cp = &hba->chan[i]; 969291a2b48SSukumar Swaminathan 970*82527734SSukumar Swaminathan /* 1 to 1 mapping between ring and channel */ 971*82527734SSukumar Swaminathan cp->iopath = (void *)&hba->sli.sli3.ring[i]; 972291a2b48SSukumar Swaminathan 973*82527734SSukumar Swaminathan cp->hba = hba; 974*82527734SSukumar Swaminathan cp->channelno = i; 975291a2b48SSukumar Swaminathan } 976291a2b48SSukumar Swaminathan 977*82527734SSukumar Swaminathan /* 978*82527734SSukumar Swaminathan * Setup and issue mailbox CONFIGURE RING command 979*82527734SSukumar Swaminathan */ 980*82527734SSukumar Swaminathan for (i = 0; i < (uint32_t)hba->sli.sli3.ring_count; i++) { 981*82527734SSukumar Swaminathan /* 982*82527734SSukumar Swaminathan * Initialize cmd/rsp ring pointers 983*82527734SSukumar Swaminathan */ 984*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[i]; 985291a2b48SSukumar Swaminathan 986*82527734SSukumar Swaminathan /* 1 to 1 mapping between ring and channel */ 987*82527734SSukumar Swaminathan rp->channelp = &hba->chan[i]; 988291a2b48SSukumar Swaminathan 989*82527734SSukumar Swaminathan rp->hba = hba; 990*82527734SSukumar Swaminathan rp->ringno = (uint8_t)i; 991*82527734SSukumar Swaminathan 992*82527734SSukumar Swaminathan rp->fc_cmdidx = 0; 993*82527734SSukumar Swaminathan rp->fc_rspidx = 0; 994*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_CFGRING); 995*82527734SSukumar Swaminathan 996*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 997*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 998*82527734SSukumar Swaminathan 999*82527734SSukumar Swaminathan emlxs_mb_config_ring(hba, i, mbq); 1000*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1001*82527734SSukumar Swaminathan MBX_SUCCESS) { 1002*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1003*82527734SSukumar Swaminathan "Unable to configure ring. " 1004*82527734SSukumar Swaminathan "Mailbox cmd=%x status=%x", 1005*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1006*82527734SSukumar Swaminathan 1007*82527734SSukumar Swaminathan rval = EIO; 1008*82527734SSukumar Swaminathan goto failed; 1009*82527734SSukumar Swaminathan } 1010291a2b48SSukumar Swaminathan } 1011291a2b48SSukumar Swaminathan 1012*82527734SSukumar Swaminathan /* 1013*82527734SSukumar Swaminathan * Setup link timers 1014*82527734SSukumar Swaminathan */ 1015*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_INITLINK); 1016291a2b48SSukumar Swaminathan 1017*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1018*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1019291a2b48SSukumar Swaminathan 1020*82527734SSukumar Swaminathan emlxs_mb_config_link(hba, mbq); 1021*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1022*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1023*82527734SSukumar Swaminathan "Unable to configure link. Mailbox cmd=%x status=%x", 1024*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1025291a2b48SSukumar Swaminathan 1026*82527734SSukumar Swaminathan rval = EIO; 1027*82527734SSukumar Swaminathan goto failed; 1028*82527734SSukumar Swaminathan } 1029291a2b48SSukumar Swaminathan 1030*82527734SSukumar Swaminathan #ifdef MAX_RRDY_SUPPORT 1031*82527734SSukumar Swaminathan /* Set MAX_RRDY if one is provided */ 1032*82527734SSukumar Swaminathan if (cfg[CFG_MAX_RRDY].current) { 1033291a2b48SSukumar Swaminathan 1034*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1035*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1036*82527734SSukumar Swaminathan 1037*82527734SSukumar Swaminathan emlxs_mb_set_var(hba, (MAILBOX *)mbq, 0x00060412, 1038*82527734SSukumar Swaminathan cfg[CFG_MAX_RRDY].current); 1039*82527734SSukumar Swaminathan 1040*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1041*82527734SSukumar Swaminathan MBX_SUCCESS) { 1042*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1043*82527734SSukumar Swaminathan "MAX_RRDY: Unable to set. status=%x " \ 1044*82527734SSukumar Swaminathan "value=%d", 1045*82527734SSukumar Swaminathan mb->mbxStatus, cfg[CFG_MAX_RRDY].current); 1046*82527734SSukumar Swaminathan } else { 1047*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1048*82527734SSukumar Swaminathan "MAX_RRDY: %d", cfg[CFG_MAX_RRDY].current); 1049*82527734SSukumar Swaminathan } 1050*82527734SSukumar Swaminathan } 1051*82527734SSukumar Swaminathan #endif /* MAX_RRDY_SUPPORT */ 1052*82527734SSukumar Swaminathan 1053*82527734SSukumar Swaminathan /* Free the buffer since we were polling */ 1054*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 1055*82527734SSukumar Swaminathan mp = NULL; 1056*82527734SSukumar Swaminathan 1057*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1058*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1059*82527734SSukumar Swaminathan 1060*82527734SSukumar Swaminathan /* 1061*82527734SSukumar Swaminathan * We need to get login parameters for NID 1062*82527734SSukumar Swaminathan */ 1063*82527734SSukumar Swaminathan (void) emlxs_mb_read_sparam(hba, mbq); 1064*82527734SSukumar Swaminathan mp = (MATCHMAP *)(mbq->bp); 1065*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1066*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1067*82527734SSukumar Swaminathan "Unable to read parameters. Mailbox cmd=%x status=%x", 1068*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1069*82527734SSukumar Swaminathan 1070*82527734SSukumar Swaminathan rval = EIO; 1071*82527734SSukumar Swaminathan goto failed; 1072*82527734SSukumar Swaminathan } 1073*82527734SSukumar Swaminathan 1074*82527734SSukumar Swaminathan /* Free the buffer since we were polling */ 1075*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 1076*82527734SSukumar Swaminathan mp = NULL; 1077*82527734SSukumar Swaminathan 1078*82527734SSukumar Swaminathan /* If no serial number in VPD data, then use the WWPN */ 1079*82527734SSukumar Swaminathan if (vpd->serial_num[0] == 0) { 1080*82527734SSukumar Swaminathan outptr = (uint8_t *)&hba->wwpn.IEEE[0]; 1081*82527734SSukumar Swaminathan for (i = 0; i < 12; i++) { 1082*82527734SSukumar Swaminathan status = *outptr++; 1083*82527734SSukumar Swaminathan j = ((status & 0xf0) >> 4); 1084*82527734SSukumar Swaminathan if (j <= 9) { 1085*82527734SSukumar Swaminathan vpd->serial_num[i] = 1086*82527734SSukumar Swaminathan (char)((uint8_t)'0' + (uint8_t)j); 1087*82527734SSukumar Swaminathan } else { 1088*82527734SSukumar Swaminathan vpd->serial_num[i] = 1089*82527734SSukumar Swaminathan (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1090*82527734SSukumar Swaminathan } 1091*82527734SSukumar Swaminathan 1092*82527734SSukumar Swaminathan i++; 1093*82527734SSukumar Swaminathan j = (status & 0xf); 1094*82527734SSukumar Swaminathan if (j <= 9) { 1095*82527734SSukumar Swaminathan vpd->serial_num[i] = 1096*82527734SSukumar Swaminathan (char)((uint8_t)'0' + (uint8_t)j); 1097*82527734SSukumar Swaminathan } else { 1098*82527734SSukumar Swaminathan vpd->serial_num[i] = 1099*82527734SSukumar Swaminathan (char)((uint8_t)'A' + (uint8_t)(j - 10)); 1100291a2b48SSukumar Swaminathan } 1101291a2b48SSukumar Swaminathan } 1102*82527734SSukumar Swaminathan 1103291a2b48SSukumar Swaminathan /* 1104*82527734SSukumar Swaminathan * Set port number and port index to zero 1105*82527734SSukumar Swaminathan * The WWN's are unique to each port and therefore port_num 1106*82527734SSukumar Swaminathan * must equal zero. This effects the hba_fru_details structure 1107*82527734SSukumar Swaminathan * in fca_bind_port() 1108291a2b48SSukumar Swaminathan */ 1109*82527734SSukumar Swaminathan vpd->port_num[0] = 0; 1110*82527734SSukumar Swaminathan vpd->port_index = 0; 1111*82527734SSukumar Swaminathan } 1112291a2b48SSukumar Swaminathan 1113*82527734SSukumar Swaminathan /* 1114*82527734SSukumar Swaminathan * Make first attempt to set a port index 1115*82527734SSukumar Swaminathan * Check if this is a multifunction adapter 1116*82527734SSukumar Swaminathan */ 1117*82527734SSukumar Swaminathan if ((vpd->port_index == -1) && 1118*82527734SSukumar Swaminathan (hba->model_info.chip >= EMLXS_THOR_CHIP)) { 1119*82527734SSukumar Swaminathan char *buffer; 1120*82527734SSukumar Swaminathan int32_t i; 1121291a2b48SSukumar Swaminathan 1122*82527734SSukumar Swaminathan /* 1123*82527734SSukumar Swaminathan * The port address looks like this: 1124*82527734SSukumar Swaminathan * 1 - for port index 0 1125*82527734SSukumar Swaminathan * 1,1 - for port index 1 1126*82527734SSukumar Swaminathan * 1,2 - for port index 2 1127*82527734SSukumar Swaminathan */ 1128*82527734SSukumar Swaminathan buffer = ddi_get_name_addr(hba->dip); 1129291a2b48SSukumar Swaminathan 1130*82527734SSukumar Swaminathan if (buffer) { 1131*82527734SSukumar Swaminathan vpd->port_index = 0; 1132291a2b48SSukumar Swaminathan 1133*82527734SSukumar Swaminathan /* Reverse scan for a comma */ 1134*82527734SSukumar Swaminathan for (i = strlen(buffer) - 1; i > 0; i--) { 1135*82527734SSukumar Swaminathan if (buffer[i] == ',') { 1136*82527734SSukumar Swaminathan /* Comma found - set index now */ 1137*82527734SSukumar Swaminathan vpd->port_index = 1138*82527734SSukumar Swaminathan emlxs_strtol(&buffer[i + 1], 10); 1139*82527734SSukumar Swaminathan break; 1140*82527734SSukumar Swaminathan } 1141*82527734SSukumar Swaminathan } 1142*82527734SSukumar Swaminathan } 1143*82527734SSukumar Swaminathan } 1144291a2b48SSukumar Swaminathan 1145*82527734SSukumar Swaminathan /* Make final attempt to set a port index */ 1146*82527734SSukumar Swaminathan if (vpd->port_index == -1) { 1147*82527734SSukumar Swaminathan dev_info_t *p_dip; 1148*82527734SSukumar Swaminathan dev_info_t *c_dip; 1149291a2b48SSukumar Swaminathan 1150*82527734SSukumar Swaminathan p_dip = ddi_get_parent(hba->dip); 1151*82527734SSukumar Swaminathan c_dip = ddi_get_child(p_dip); 1152291a2b48SSukumar Swaminathan 1153*82527734SSukumar Swaminathan vpd->port_index = 0; 1154*82527734SSukumar Swaminathan while (c_dip && (hba->dip != c_dip)) { 1155*82527734SSukumar Swaminathan c_dip = ddi_get_next_sibling(c_dip); 1156*82527734SSukumar Swaminathan vpd->port_index++; 1157291a2b48SSukumar Swaminathan } 1158*82527734SSukumar Swaminathan } 1159291a2b48SSukumar Swaminathan 1160*82527734SSukumar Swaminathan if (vpd->port_num[0] == 0) { 1161*82527734SSukumar Swaminathan if (hba->model_info.channels > 1) { 1162*82527734SSukumar Swaminathan (void) sprintf(vpd->port_num, "%d", vpd->port_index); 1163*82527734SSukumar Swaminathan } 1164*82527734SSukumar Swaminathan } 1165291a2b48SSukumar Swaminathan 1166*82527734SSukumar Swaminathan if (vpd->id[0] == 0) { 1167*82527734SSukumar Swaminathan (void) strcpy(vpd->id, hba->model_info.model_desc); 1168*82527734SSukumar Swaminathan } 1169291a2b48SSukumar Swaminathan 1170*82527734SSukumar Swaminathan if (vpd->manufacturer[0] == 0) { 1171*82527734SSukumar Swaminathan (void) strcpy(vpd->manufacturer, hba->model_info.manufacturer); 1172*82527734SSukumar Swaminathan } 1173291a2b48SSukumar Swaminathan 1174*82527734SSukumar Swaminathan if (vpd->part_num[0] == 0) { 1175*82527734SSukumar Swaminathan (void) strcpy(vpd->part_num, hba->model_info.model); 1176*82527734SSukumar Swaminathan } 1177291a2b48SSukumar Swaminathan 1178*82527734SSukumar Swaminathan if (vpd->model_desc[0] == 0) { 1179*82527734SSukumar Swaminathan (void) strcpy(vpd->model_desc, hba->model_info.model_desc); 1180*82527734SSukumar Swaminathan } 1181291a2b48SSukumar Swaminathan 1182*82527734SSukumar Swaminathan if (vpd->model[0] == 0) { 1183*82527734SSukumar Swaminathan (void) strcpy(vpd->model, hba->model_info.model); 1184*82527734SSukumar Swaminathan } 1185291a2b48SSukumar Swaminathan 1186*82527734SSukumar Swaminathan if (vpd->prog_types[0] == 0) { 1187*82527734SSukumar Swaminathan emlxs_build_prog_types(hba, vpd->prog_types); 1188291a2b48SSukumar Swaminathan } 1189291a2b48SSukumar Swaminathan 1190*82527734SSukumar Swaminathan /* Create the symbolic names */ 1191*82527734SSukumar Swaminathan (void) sprintf(hba->snn, "Emulex %s FV%s DV%s %s", 1192*82527734SSukumar Swaminathan hba->model_info.model, hba->vpd.fw_version, emlxs_version, 1193*82527734SSukumar Swaminathan (char *)utsname.nodename); 1194291a2b48SSukumar Swaminathan 1195*82527734SSukumar Swaminathan (void) sprintf(hba->spn, 1196*82527734SSukumar Swaminathan "Emulex PPN-%01x%01x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 1197*82527734SSukumar Swaminathan hba->wwpn.nameType, hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, 1198*82527734SSukumar Swaminathan hba->wwpn.IEEE[0], hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], 1199*82527734SSukumar Swaminathan hba->wwpn.IEEE[3], hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1200291a2b48SSukumar Swaminathan 1201*82527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 1202*82527734SSukumar Swaminathan if ((hba->sparam.portName.nameType != NAME_IEEE) || 1203*82527734SSukumar Swaminathan (hba->sparam.portName.IEEEextMsn != 0) || 1204*82527734SSukumar Swaminathan (hba->sparam.portName.IEEEextLsb != 0)) { 1205291a2b48SSukumar Swaminathan 1206*82527734SSukumar Swaminathan cfg[CFG_NETWORK_ON].current = 0; 1207291a2b48SSukumar Swaminathan 1208*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1209*82527734SSukumar Swaminathan "WWPN doesn't conform to IP profile: nameType=%x", 1210*82527734SSukumar Swaminathan hba->sparam.portName.nameType); 1211*82527734SSukumar Swaminathan } 1212291a2b48SSukumar Swaminathan 1213*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1214*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1215291a2b48SSukumar Swaminathan 1216*82527734SSukumar Swaminathan /* Issue CONFIG FARP */ 1217*82527734SSukumar Swaminathan emlxs_mb_config_farp(hba, mbq); 1218*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1219*82527734SSukumar Swaminathan MBX_SUCCESS) { 1220*82527734SSukumar Swaminathan /* 1221*82527734SSukumar Swaminathan * Let it go through even if failed. 1222*82527734SSukumar Swaminathan */ 1223*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 1224*82527734SSukumar Swaminathan "Unable to configure FARP. " 1225*82527734SSukumar Swaminathan "Mailbox cmd=%x status=%x", 1226*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1227*82527734SSukumar Swaminathan } 1228291a2b48SSukumar Swaminathan } 1229*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT 1230*82527734SSukumar Swaminathan /* Configure MSI map if required */ 1231*82527734SSukumar Swaminathan if (hba->intr_count > 1) { 1232*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1233*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1234291a2b48SSukumar Swaminathan 1235*82527734SSukumar Swaminathan emlxs_mb_config_msix(hba, mbq, hba->intr_map, hba->intr_count); 1236291a2b48SSukumar Swaminathan 1237*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) == 1238*82527734SSukumar Swaminathan MBX_SUCCESS) { 1239*82527734SSukumar Swaminathan goto msi_configured; 1240*82527734SSukumar Swaminathan } 1241291a2b48SSukumar Swaminathan 1242*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1243*82527734SSukumar Swaminathan "Unable to config MSIX. Mailbox cmd=0x%x status=0x%x", 1244*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1245291a2b48SSukumar Swaminathan 1246*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1247*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1248291a2b48SSukumar Swaminathan 1249*82527734SSukumar Swaminathan emlxs_mb_config_msi(hba, mbq, hba->intr_map, hba->intr_count); 1250291a2b48SSukumar Swaminathan 1251*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) == 1252*82527734SSukumar Swaminathan MBX_SUCCESS) { 1253*82527734SSukumar Swaminathan goto msi_configured; 1254291a2b48SSukumar Swaminathan } 1255291a2b48SSukumar Swaminathan 1256291a2b48SSukumar Swaminathan 1257*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1258*82527734SSukumar Swaminathan "Unable to config MSI. Mailbox cmd=0x%x status=0x%x", 1259*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1260291a2b48SSukumar Swaminathan 1261*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1262*82527734SSukumar Swaminathan "Attempting single interrupt mode..."); 1263291a2b48SSukumar Swaminathan 1264*82527734SSukumar Swaminathan /* First cleanup old interrupts */ 1265*82527734SSukumar Swaminathan (void) emlxs_msi_remove(hba); 1266*82527734SSukumar Swaminathan (void) emlxs_msi_uninit(hba); 1267291a2b48SSukumar Swaminathan 1268*82527734SSukumar Swaminathan status = emlxs_msi_init(hba, 1); 1269291a2b48SSukumar Swaminathan 1270*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1271*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1272*82527734SSukumar Swaminathan "Unable to initialize interrupt. status=%d", 1273*82527734SSukumar Swaminathan status); 1274291a2b48SSukumar Swaminathan 1275*82527734SSukumar Swaminathan rval = EIO; 1276*82527734SSukumar Swaminathan goto failed; 1277291a2b48SSukumar Swaminathan } 1278291a2b48SSukumar Swaminathan 1279*82527734SSukumar Swaminathan /* 1280*82527734SSukumar Swaminathan * Reset adapter - The adapter needs to be reset because 1281*82527734SSukumar Swaminathan * the bus cannot handle the MSI change without handshaking 1282*82527734SSukumar Swaminathan * with the adapter again 1283*82527734SSukumar Swaminathan */ 1284291a2b48SSukumar Swaminathan 1285*82527734SSukumar Swaminathan (void) emlxs_mem_free_buffer(hba); 1286*82527734SSukumar Swaminathan fw_check = 0; 1287*82527734SSukumar Swaminathan goto reset; 1288*82527734SSukumar Swaminathan } 1289291a2b48SSukumar Swaminathan 1290*82527734SSukumar Swaminathan msi_configured: 1291291a2b48SSukumar Swaminathan 1292*82527734SSukumar Swaminathan 1293*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 1294*82527734SSukumar Swaminathan 1295*82527734SSukumar Swaminathan /* 1296*82527734SSukumar Swaminathan * We always disable the firmware traffic cop feature 1297*82527734SSukumar Swaminathan */ 1298*82527734SSukumar Swaminathan if (emlxs_disable_traffic_cop) { 1299*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1300*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1301*82527734SSukumar Swaminathan 1302*82527734SSukumar Swaminathan emlxs_disable_tc(hba, mbq); 1303*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != 1304*82527734SSukumar Swaminathan MBX_SUCCESS) { 1305*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1306*82527734SSukumar Swaminathan "Unable to disable traffic cop. " 1307*82527734SSukumar Swaminathan "Mailbox cmd=%x status=%x", 1308*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1309*82527734SSukumar Swaminathan 1310*82527734SSukumar Swaminathan rval = EIO; 1311*82527734SSukumar Swaminathan goto failed; 1312291a2b48SSukumar Swaminathan } 1313*82527734SSukumar Swaminathan } 1314291a2b48SSukumar Swaminathan 1315*82527734SSukumar Swaminathan 1316*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1317*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1318*82527734SSukumar Swaminathan 1319*82527734SSukumar Swaminathan /* Register for async events */ 1320*82527734SSukumar Swaminathan emlxs_mb_async_event(hba, mbq); 1321*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 1322*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1323*82527734SSukumar Swaminathan "Async events disabled. Mailbox status=%x", 1324*82527734SSukumar Swaminathan mb->mbxStatus); 1325*82527734SSukumar Swaminathan } else { 1326*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1327*82527734SSukumar Swaminathan "Async events enabled."); 1328*82527734SSukumar Swaminathan hba->flag |= FC_ASYNC_EVENTS; 1329291a2b48SSukumar Swaminathan } 1330291a2b48SSukumar Swaminathan 1331*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN); 1332291a2b48SSukumar Swaminathan 1333*82527734SSukumar Swaminathan emlxs_sli3_enable_intr(hba); 1334291a2b48SSukumar Swaminathan 1335*82527734SSukumar Swaminathan if (hba->flag & FC_HBQ_ENABLED) { 1336*82527734SSukumar Swaminathan if (hba->tgt_mode) { 1337*82527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_FCT_HBQ_ID)) { 1338*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1339*82527734SSukumar Swaminathan &emlxs_init_failed_msg, 1340*82527734SSukumar Swaminathan "Unable to setup FCT HBQ."); 1341291a2b48SSukumar Swaminathan 1342*82527734SSukumar Swaminathan rval = ENOMEM; 1343*82527734SSukumar Swaminathan goto failed; 1344*82527734SSukumar Swaminathan } 1345*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1346*82527734SSukumar Swaminathan "FCT Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1347*82527734SSukumar Swaminathan } 1348291a2b48SSukumar Swaminathan 1349*82527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 1350*82527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_IP_HBQ_ID)) { 1351*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1352*82527734SSukumar Swaminathan &emlxs_init_failed_msg, 1353*82527734SSukumar Swaminathan "Unable to setup IP HBQ."); 1354291a2b48SSukumar Swaminathan 1355*82527734SSukumar Swaminathan rval = ENOMEM; 1356*82527734SSukumar Swaminathan goto failed; 1357*82527734SSukumar Swaminathan } 1358*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1359*82527734SSukumar Swaminathan "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1360*82527734SSukumar Swaminathan } 1361291a2b48SSukumar Swaminathan 1362*82527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_ELS_HBQ_ID)) { 1363*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1364*82527734SSukumar Swaminathan "Unable to setup ELS HBQ."); 1365*82527734SSukumar Swaminathan rval = ENOMEM; 1366*82527734SSukumar Swaminathan goto failed; 1367*82527734SSukumar Swaminathan } 1368*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1369*82527734SSukumar Swaminathan "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1370291a2b48SSukumar Swaminathan 1371*82527734SSukumar Swaminathan if (emlxs_hbq_setup(hba, EMLXS_CT_HBQ_ID)) { 1372*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1373*82527734SSukumar Swaminathan "Unable to setup CT HBQ."); 1374291a2b48SSukumar Swaminathan 1375*82527734SSukumar Swaminathan rval = ENOMEM; 1376*82527734SSukumar Swaminathan goto failed; 1377*82527734SSukumar Swaminathan } 1378*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1379*82527734SSukumar Swaminathan "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1380*82527734SSukumar Swaminathan } else { 1381*82527734SSukumar Swaminathan if (hba->tgt_mode) { 1382*82527734SSukumar Swaminathan /* Post the FCT unsol buffers */ 1383*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_FCT_RING]; 1384*82527734SSukumar Swaminathan for (j = 0; j < MEM_FCTBUF_COUNT; j += 2) { 1385*82527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 1386*82527734SSukumar Swaminathan } 1387*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1388*82527734SSukumar Swaminathan "FCP Ring: Posted %d buffers.", MEM_FCTBUF_COUNT); 1389*82527734SSukumar Swaminathan } 1390291a2b48SSukumar Swaminathan 1391*82527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 1392*82527734SSukumar Swaminathan /* Post the IP unsol buffers */ 1393*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_IP_RING]; 1394*82527734SSukumar Swaminathan for (j = 0; j < MEM_IPBUF_COUNT; j += 2) { 1395*82527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 1396*82527734SSukumar Swaminathan } 1397*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1398*82527734SSukumar Swaminathan "IP Ring: Posted %d buffers.", MEM_IPBUF_COUNT); 1399*82527734SSukumar Swaminathan } 1400291a2b48SSukumar Swaminathan 1401*82527734SSukumar Swaminathan /* Post the ELS unsol buffers */ 1402*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_ELS_RING]; 1403*82527734SSukumar Swaminathan for (j = 0; j < MEM_ELSBUF_COUNT; j += 2) { 1404*82527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 1405*82527734SSukumar Swaminathan } 1406*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1407*82527734SSukumar Swaminathan "ELS Ring: Posted %d buffers.", MEM_ELSBUF_COUNT); 1408291a2b48SSukumar Swaminathan 1409*82527734SSukumar Swaminathan 1410*82527734SSukumar Swaminathan /* Post the CT unsol buffers */ 1411*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[FC_CT_RING]; 1412*82527734SSukumar Swaminathan for (j = 0; j < MEM_CTBUF_COUNT; j += 2) { 1413*82527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 2); 1414*82527734SSukumar Swaminathan } 1415*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1416*82527734SSukumar Swaminathan "CT Ring: Posted %d buffers.", MEM_CTBUF_COUNT); 1417291a2b48SSukumar Swaminathan } 1418291a2b48SSukumar Swaminathan 1419291a2b48SSukumar Swaminathan 1420*82527734SSukumar Swaminathan /* Reuse mbq from previous mbox */ 1421*82527734SSukumar Swaminathan bzero(mbq, sizeof (MAILBOXQ)); 1422291a2b48SSukumar Swaminathan 1423*82527734SSukumar Swaminathan /* 1424*82527734SSukumar Swaminathan * Setup and issue mailbox INITIALIZE LINK command 1425*82527734SSukumar Swaminathan * At this point, the interrupt will be generated by the HW 1426*82527734SSukumar Swaminathan * Do this only if persist-linkdown is not set 1427*82527734SSukumar Swaminathan */ 1428*82527734SSukumar Swaminathan if (cfg[CFG_PERSIST_LINKDOWN].current == 0) { 1429*82527734SSukumar Swaminathan emlxs_mb_init_link(hba, mbq, cfg[CFG_TOPOLOGY].current, 1430*82527734SSukumar Swaminathan cfg[CFG_LINK_SPEED].current); 1431291a2b48SSukumar Swaminathan 1432*82527734SSukumar Swaminathan rval = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 1433*82527734SSukumar Swaminathan if ((rval != MBX_SUCCESS) && (rval != MBX_BUSY)) { 1434291a2b48SSukumar Swaminathan 1435*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 1436*82527734SSukumar Swaminathan "Unable to initialize link. " \ 1437*82527734SSukumar Swaminathan "Mailbox cmd=%x status=%x", 1438*82527734SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 1439291a2b48SSukumar Swaminathan 1440*82527734SSukumar Swaminathan rval = EIO; 1441*82527734SSukumar Swaminathan goto failed; 1442*82527734SSukumar Swaminathan } 1443291a2b48SSukumar Swaminathan 1444*82527734SSukumar Swaminathan /* 1445*82527734SSukumar Swaminathan * Enable link attention interrupt 1446*82527734SSukumar Swaminathan */ 1447*82527734SSukumar Swaminathan emlxs_enable_latt(hba); 1448291a2b48SSukumar Swaminathan 1449*82527734SSukumar Swaminathan /* Wait for link to come up */ 1450*82527734SSukumar Swaminathan i = cfg[CFG_LINKUP_DELAY].current; 1451*82527734SSukumar Swaminathan while (i && (hba->state < FC_LINK_UP)) { 1452*82527734SSukumar Swaminathan /* Check for hardware error */ 1453*82527734SSukumar Swaminathan if (hba->state == FC_ERROR) { 1454*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1455*82527734SSukumar Swaminathan &emlxs_init_failed_msg, 1456*82527734SSukumar Swaminathan "Adapter error.", mb->mbxCommand, 1457*82527734SSukumar Swaminathan mb->mbxStatus); 1458291a2b48SSukumar Swaminathan 1459*82527734SSukumar Swaminathan rval = EIO; 1460*82527734SSukumar Swaminathan goto failed; 1461*82527734SSukumar Swaminathan } 1462*82527734SSukumar Swaminathan 1463*82527734SSukumar Swaminathan DELAYMS(1000); 1464*82527734SSukumar Swaminathan i--; 1465*82527734SSukumar Swaminathan } 1466*82527734SSukumar Swaminathan } else { 1467*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_LINK_DOWN_PERSIST); 1468*82527734SSukumar Swaminathan } 1469*82527734SSukumar Swaminathan 1470*82527734SSukumar Swaminathan /* 1471*82527734SSukumar Swaminathan * The leadvile driver will now handle the FLOGI at the driver level 1472*82527734SSukumar Swaminathan */ 1473291a2b48SSukumar Swaminathan 1474291a2b48SSukumar Swaminathan return (0); 1475291a2b48SSukumar Swaminathan 1476*82527734SSukumar Swaminathan failed: 1477291a2b48SSukumar Swaminathan 1478*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 1479291a2b48SSukumar Swaminathan 1480*82527734SSukumar Swaminathan if (hba->intr_flags & EMLXS_MSI_ADDED) { 1481*82527734SSukumar Swaminathan (void) EMLXS_INTR_REMOVE(hba); 1482*82527734SSukumar Swaminathan } 1483291a2b48SSukumar Swaminathan 1484*82527734SSukumar Swaminathan if (mp) { 1485*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp); 1486*82527734SSukumar Swaminathan mp = NULL; 1487*82527734SSukumar Swaminathan } 1488291a2b48SSukumar Swaminathan 1489*82527734SSukumar Swaminathan if (mp1) { 1490*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp1); 1491*82527734SSukumar Swaminathan mp1 = NULL; 1492*82527734SSukumar Swaminathan } 1493291a2b48SSukumar Swaminathan 1494*82527734SSukumar Swaminathan (void) emlxs_mem_free_buffer(hba); 1495291a2b48SSukumar Swaminathan 1496*82527734SSukumar Swaminathan if (mbq) { 1497*82527734SSukumar Swaminathan (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ)); 1498*82527734SSukumar Swaminathan mbq = NULL; 1499*82527734SSukumar Swaminathan mb = NULL; 1500291a2b48SSukumar Swaminathan } 1501291a2b48SSukumar Swaminathan 1502*82527734SSukumar Swaminathan if (rval == 0) { 1503*82527734SSukumar Swaminathan rval = EIO; 1504*82527734SSukumar Swaminathan } 1505291a2b48SSukumar Swaminathan 1506*82527734SSukumar Swaminathan return (rval); 1507291a2b48SSukumar Swaminathan 1508*82527734SSukumar Swaminathan } /* emlxs_sli3_online() */ 1509291a2b48SSukumar Swaminathan 1510291a2b48SSukumar Swaminathan 1511*82527734SSukumar Swaminathan static void 1512*82527734SSukumar Swaminathan emlxs_sli3_offline(emlxs_hba_t *hba) 1513*82527734SSukumar Swaminathan { 1514*82527734SSukumar Swaminathan /* Reverse emlxs_sli3_online */ 1515291a2b48SSukumar Swaminathan 1516*82527734SSukumar Swaminathan /* Kill the adapter */ 1517*82527734SSukumar Swaminathan emlxs_sli3_hba_kill(hba); 1518291a2b48SSukumar Swaminathan 1519*82527734SSukumar Swaminathan /* Free driver shared memory */ 1520*82527734SSukumar Swaminathan (void) emlxs_mem_free_buffer(hba); 1521291a2b48SSukumar Swaminathan 1522*82527734SSukumar Swaminathan } /* emlxs_sli3_offline() */ 1523291a2b48SSukumar Swaminathan 1524291a2b48SSukumar Swaminathan 1525*82527734SSukumar Swaminathan static int 1526*82527734SSukumar Swaminathan emlxs_sli3_map_hdw(emlxs_hba_t *hba) 1527291a2b48SSukumar Swaminathan { 1528*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 1529*82527734SSukumar Swaminathan dev_info_t *dip; 1530*82527734SSukumar Swaminathan ddi_device_acc_attr_t dev_attr; 1531*82527734SSukumar Swaminathan int status; 1532291a2b48SSukumar Swaminathan 1533*82527734SSukumar Swaminathan dip = (dev_info_t *)hba->dip; 1534*82527734SSukumar Swaminathan dev_attr = emlxs_dev_acc_attr; 1535291a2b48SSukumar Swaminathan 1536*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 1537291a2b48SSukumar Swaminathan 1538*82527734SSukumar Swaminathan if (hba->sli.sli3.slim_acc_handle == 0) { 1539*82527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, 1540*82527734SSukumar Swaminathan SBUS_DFLY_SLIM_RINDEX, 1541*82527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.slim_addr, 1542*82527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle); 1543*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1544*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1545*82527734SSukumar Swaminathan &emlxs_attach_failed_msg, 1546*82527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup SLIM failed. " 1547*82527734SSukumar Swaminathan "status=%x", status); 1548*82527734SSukumar Swaminathan goto failed; 1549*82527734SSukumar Swaminathan } 1550*82527734SSukumar Swaminathan } 1551*82527734SSukumar Swaminathan if (hba->sli.sli3.csr_acc_handle == 0) { 1552*82527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, 1553*82527734SSukumar Swaminathan SBUS_DFLY_CSR_RINDEX, 1554*82527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.csr_addr, 1555*82527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle); 1556*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1557*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1558*82527734SSukumar Swaminathan &emlxs_attach_failed_msg, 1559*82527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup DFLY CSR " 1560*82527734SSukumar Swaminathan "failed. status=%x", status); 1561*82527734SSukumar Swaminathan goto failed; 1562*82527734SSukumar Swaminathan } 1563*82527734SSukumar Swaminathan } 1564*82527734SSukumar Swaminathan if (hba->sli.sli3.sbus_flash_acc_handle == 0) { 1565*82527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, SBUS_FLASH_RDWR, 1566*82527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.sbus_flash_addr, 0, 0, 1567*82527734SSukumar Swaminathan &dev_attr, &hba->sli.sli3.sbus_flash_acc_handle); 1568*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1569*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1570*82527734SSukumar Swaminathan &emlxs_attach_failed_msg, 1571*82527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup Fcode Flash " 1572*82527734SSukumar Swaminathan "failed. status=%x", status); 1573*82527734SSukumar Swaminathan goto failed; 1574*82527734SSukumar Swaminathan } 1575*82527734SSukumar Swaminathan } 1576*82527734SSukumar Swaminathan if (hba->sli.sli3.sbus_core_acc_handle == 0) { 1577*82527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, SBUS_TITAN_CORE_RINDEX, 1578*82527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.sbus_core_addr, 0, 0, 1579*82527734SSukumar Swaminathan &dev_attr, &hba->sli.sli3.sbus_core_acc_handle); 1580*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1581*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1582*82527734SSukumar Swaminathan &emlxs_attach_failed_msg, 1583*82527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup TITAN CORE " 1584*82527734SSukumar Swaminathan "failed. status=%x", status); 1585*82527734SSukumar Swaminathan goto failed; 1586*82527734SSukumar Swaminathan } 1587291a2b48SSukumar Swaminathan } 1588291a2b48SSukumar Swaminathan 1589*82527734SSukumar Swaminathan if (hba->sli.sli3.sbus_csr_handle == 0) { 1590*82527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, SBUS_TITAN_CSR_RINDEX, 1591*82527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.sbus_csr_addr, 1592*82527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.sbus_csr_handle); 1593*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1594*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1595*82527734SSukumar Swaminathan &emlxs_attach_failed_msg, 1596*82527734SSukumar Swaminathan "(SBUS) ddi_regs_map_setup TITAN CSR " 1597*82527734SSukumar Swaminathan "failed. status=%x", status); 1598*82527734SSukumar Swaminathan goto failed; 1599291a2b48SSukumar Swaminathan } 1600291a2b48SSukumar Swaminathan } 1601*82527734SSukumar Swaminathan } else { /* ****** PCI ****** */ 1602291a2b48SSukumar Swaminathan 1603*82527734SSukumar Swaminathan if (hba->sli.sli3.slim_acc_handle == 0) { 1604*82527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, PCI_SLIM_RINDEX, 1605*82527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.slim_addr, 1606*82527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.slim_acc_handle); 1607*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1608*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1609*82527734SSukumar Swaminathan &emlxs_attach_failed_msg, 1610*82527734SSukumar Swaminathan "(PCI) ddi_regs_map_setup SLIM failed. " 1611*82527734SSukumar Swaminathan "stat=%d mem=%p attr=%p hdl=%p", 1612*82527734SSukumar Swaminathan status, &hba->sli.sli3.slim_addr, &dev_attr, 1613*82527734SSukumar Swaminathan &hba->sli.sli3.slim_acc_handle); 1614*82527734SSukumar Swaminathan goto failed; 1615*82527734SSukumar Swaminathan } 1616291a2b48SSukumar Swaminathan } 1617291a2b48SSukumar Swaminathan 1618*82527734SSukumar Swaminathan /* 1619*82527734SSukumar Swaminathan * Map in control registers, using memory-mapped version of 1620*82527734SSukumar Swaminathan * the registers rather than the I/O space-mapped registers. 1621*82527734SSukumar Swaminathan */ 1622*82527734SSukumar Swaminathan if (hba->sli.sli3.csr_acc_handle == 0) { 1623*82527734SSukumar Swaminathan status = ddi_regs_map_setup(dip, PCI_CSR_RINDEX, 1624*82527734SSukumar Swaminathan (caddr_t *)&hba->sli.sli3.csr_addr, 1625*82527734SSukumar Swaminathan 0, 0, &dev_attr, &hba->sli.sli3.csr_acc_handle); 1626*82527734SSukumar Swaminathan if (status != DDI_SUCCESS) { 1627*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 1628*82527734SSukumar Swaminathan &emlxs_attach_failed_msg, 1629*82527734SSukumar Swaminathan "ddi_regs_map_setup CSR failed. status=%x", 1630*82527734SSukumar Swaminathan status); 1631*82527734SSukumar Swaminathan goto failed; 1632*82527734SSukumar Swaminathan } 1633*82527734SSukumar Swaminathan } 1634291a2b48SSukumar Swaminathan } 1635291a2b48SSukumar Swaminathan 1636*82527734SSukumar Swaminathan if (hba->sli.sli3.slim2.virt == 0) { 1637*82527734SSukumar Swaminathan MBUF_INFO *buf_info; 1638*82527734SSukumar Swaminathan MBUF_INFO bufinfo; 1639291a2b48SSukumar Swaminathan 1640*82527734SSukumar Swaminathan buf_info = &bufinfo; 1641291a2b48SSukumar Swaminathan 1642*82527734SSukumar Swaminathan bzero(buf_info, sizeof (MBUF_INFO)); 1643*82527734SSukumar Swaminathan buf_info->size = SLI_SLIM2_SIZE; 1644*82527734SSukumar Swaminathan buf_info->flags = 1645*82527734SSukumar Swaminathan FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32; 1646*82527734SSukumar Swaminathan buf_info->align = ddi_ptob(dip, 1L); 1647291a2b48SSukumar Swaminathan 1648*82527734SSukumar Swaminathan (void) emlxs_mem_alloc(hba, buf_info); 1649291a2b48SSukumar Swaminathan 1650*82527734SSukumar Swaminathan if (buf_info->virt == NULL) { 1651*82527734SSukumar Swaminathan goto failed; 1652291a2b48SSukumar Swaminathan } 1653*82527734SSukumar Swaminathan 1654*82527734SSukumar Swaminathan hba->sli.sli3.slim2.virt = (uint8_t *)buf_info->virt; 1655*82527734SSukumar Swaminathan hba->sli.sli3.slim2.phys = buf_info->phys; 1656*82527734SSukumar Swaminathan hba->sli.sli3.slim2.size = SLI_SLIM2_SIZE; 1657*82527734SSukumar Swaminathan hba->sli.sli3.slim2.data_handle = buf_info->data_handle; 1658*82527734SSukumar Swaminathan hba->sli.sli3.slim2.dma_handle = buf_info->dma_handle; 1659*82527734SSukumar Swaminathan bzero((char *)hba->sli.sli3.slim2.virt, SLI_SLIM2_SIZE); 1660291a2b48SSukumar Swaminathan } 1661291a2b48SSukumar Swaminathan 1662*82527734SSukumar Swaminathan /* offset from beginning of register space */ 1663*82527734SSukumar Swaminathan hba->sli.sli3.ha_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1664*82527734SSukumar Swaminathan (sizeof (uint32_t) * HA_REG_OFFSET)); 1665*82527734SSukumar Swaminathan hba->sli.sli3.ca_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1666*82527734SSukumar Swaminathan (sizeof (uint32_t) * CA_REG_OFFSET)); 1667*82527734SSukumar Swaminathan hba->sli.sli3.hs_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1668*82527734SSukumar Swaminathan (sizeof (uint32_t) * HS_REG_OFFSET)); 1669*82527734SSukumar Swaminathan hba->sli.sli3.hc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1670*82527734SSukumar Swaminathan (sizeof (uint32_t) * HC_REG_OFFSET)); 1671*82527734SSukumar Swaminathan hba->sli.sli3.bc_reg_addr = (uint32_t *)(hba->sli.sli3.csr_addr + 1672*82527734SSukumar Swaminathan (sizeof (uint32_t) * BC_REG_OFFSET)); 1673291a2b48SSukumar Swaminathan 1674*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 1675*82527734SSukumar Swaminathan /* offset from beginning of register space */ 1676*82527734SSukumar Swaminathan /* for TITAN registers */ 1677*82527734SSukumar Swaminathan hba->sli.sli3.shc_reg_addr = 1678*82527734SSukumar Swaminathan (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 1679*82527734SSukumar Swaminathan (sizeof (uint32_t) * SBUS_CTRL_REG_OFFSET)); 1680*82527734SSukumar Swaminathan hba->sli.sli3.shs_reg_addr = 1681*82527734SSukumar Swaminathan (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 1682*82527734SSukumar Swaminathan (sizeof (uint32_t) * SBUS_STAT_REG_OFFSET)); 1683*82527734SSukumar Swaminathan hba->sli.sli3.shu_reg_addr = 1684*82527734SSukumar Swaminathan (uint32_t *)(hba->sli.sli3.sbus_csr_addr + 1685*82527734SSukumar Swaminathan (sizeof (uint32_t) * SBUS_UPDATE_REG_OFFSET)); 1686*82527734SSukumar Swaminathan } 1687*82527734SSukumar Swaminathan hba->chan_count = MAX_RINGS; 1688291a2b48SSukumar Swaminathan 1689*82527734SSukumar Swaminathan return (0); 1690291a2b48SSukumar Swaminathan 1691*82527734SSukumar Swaminathan failed: 1692291a2b48SSukumar Swaminathan 1693*82527734SSukumar Swaminathan emlxs_sli3_unmap_hdw(hba); 1694*82527734SSukumar Swaminathan return (ENOMEM); 1695291a2b48SSukumar Swaminathan 1696*82527734SSukumar Swaminathan } /* emlxs_sli3_map_hdw() */ 1697291a2b48SSukumar Swaminathan 1698291a2b48SSukumar Swaminathan 1699*82527734SSukumar Swaminathan static void 1700*82527734SSukumar Swaminathan emlxs_sli3_unmap_hdw(emlxs_hba_t *hba) 1701*82527734SSukumar Swaminathan { 1702*82527734SSukumar Swaminathan MBUF_INFO bufinfo; 1703*82527734SSukumar Swaminathan MBUF_INFO *buf_info = &bufinfo; 1704291a2b48SSukumar Swaminathan 1705*82527734SSukumar Swaminathan if (hba->sli.sli3.csr_acc_handle) { 1706*82527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.csr_acc_handle); 1707*82527734SSukumar Swaminathan hba->sli.sli3.csr_acc_handle = 0; 1708*82527734SSukumar Swaminathan } 1709291a2b48SSukumar Swaminathan 1710*82527734SSukumar Swaminathan if (hba->sli.sli3.slim_acc_handle) { 1711*82527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.slim_acc_handle); 1712*82527734SSukumar Swaminathan hba->sli.sli3.slim_acc_handle = 0; 1713*82527734SSukumar Swaminathan } 1714291a2b48SSukumar Swaminathan 1715*82527734SSukumar Swaminathan if (hba->sli.sli3.sbus_flash_acc_handle) { 1716*82527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.sbus_flash_acc_handle); 1717*82527734SSukumar Swaminathan hba->sli.sli3.sbus_flash_acc_handle = 0; 1718*82527734SSukumar Swaminathan } 1719291a2b48SSukumar Swaminathan 1720*82527734SSukumar Swaminathan if (hba->sli.sli3.sbus_core_acc_handle) { 1721*82527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.sbus_core_acc_handle); 1722*82527734SSukumar Swaminathan hba->sli.sli3.sbus_core_acc_handle = 0; 1723*82527734SSukumar Swaminathan } 1724291a2b48SSukumar Swaminathan 1725*82527734SSukumar Swaminathan if (hba->sli.sli3.sbus_csr_handle) { 1726*82527734SSukumar Swaminathan ddi_regs_map_free(&hba->sli.sli3.sbus_csr_handle); 1727*82527734SSukumar Swaminathan hba->sli.sli3.sbus_csr_handle = 0; 1728*82527734SSukumar Swaminathan } 1729291a2b48SSukumar Swaminathan 1730*82527734SSukumar Swaminathan if (hba->sli.sli3.slim2.virt) { 1731*82527734SSukumar Swaminathan bzero(buf_info, sizeof (MBUF_INFO)); 1732291a2b48SSukumar Swaminathan 1733*82527734SSukumar Swaminathan if (hba->sli.sli3.slim2.phys) { 1734*82527734SSukumar Swaminathan buf_info->phys = hba->sli.sli3.slim2.phys; 1735*82527734SSukumar Swaminathan buf_info->data_handle = hba->sli.sli3.slim2.data_handle; 1736*82527734SSukumar Swaminathan buf_info->dma_handle = hba->sli.sli3.slim2.dma_handle; 1737*82527734SSukumar Swaminathan buf_info->flags = FC_MBUF_DMA; 1738*82527734SSukumar Swaminathan } 1739291a2b48SSukumar Swaminathan 1740*82527734SSukumar Swaminathan buf_info->virt = (uint32_t *)hba->sli.sli3.slim2.virt; 1741*82527734SSukumar Swaminathan buf_info->size = hba->sli.sli3.slim2.size; 1742*82527734SSukumar Swaminathan emlxs_mem_free(hba, buf_info); 1743291a2b48SSukumar Swaminathan 1744*82527734SSukumar Swaminathan hba->sli.sli3.slim2.virt = 0; 1745291a2b48SSukumar Swaminathan } 1746291a2b48SSukumar Swaminathan 1747291a2b48SSukumar Swaminathan 1748*82527734SSukumar Swaminathan return; 1749291a2b48SSukumar Swaminathan 1750*82527734SSukumar Swaminathan } /* emlxs_sli3_unmap_hdw() */ 1751291a2b48SSukumar Swaminathan 1752291a2b48SSukumar Swaminathan 1753*82527734SSukumar Swaminathan static uint32_t 1754*82527734SSukumar Swaminathan emlxs_sli3_hba_init(emlxs_hba_t *hba) 1755*82527734SSukumar Swaminathan { 1756*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 1757*82527734SSukumar Swaminathan emlxs_port_t *vport; 1758*82527734SSukumar Swaminathan emlxs_config_t *cfg; 1759*82527734SSukumar Swaminathan int32_t i; 17604baa2c25SSukumar Swaminathan 1761*82527734SSukumar Swaminathan cfg = &CFG; 1762*82527734SSukumar Swaminathan i = 0; 1763291a2b48SSukumar Swaminathan 1764*82527734SSukumar Swaminathan /* Restart the adapter */ 1765*82527734SSukumar Swaminathan if (emlxs_sli3_hba_reset(hba, 1, 0, 0)) { 1766*82527734SSukumar Swaminathan return (1); 1767*82527734SSukumar Swaminathan } 1768291a2b48SSukumar Swaminathan 1769*82527734SSukumar Swaminathan hba->channel_fcp = FC_FCP_RING; 1770*82527734SSukumar Swaminathan hba->channel_els = FC_ELS_RING; 1771*82527734SSukumar Swaminathan hba->channel_ip = FC_IP_RING; 1772*82527734SSukumar Swaminathan hba->channel_ct = FC_CT_RING; 1773*82527734SSukumar Swaminathan hba->chan_count = MAX_RINGS; 1774*82527734SSukumar Swaminathan hba->sli.sli3.ring_count = MAX_RINGS; 1775291a2b48SSukumar Swaminathan 1776291a2b48SSukumar Swaminathan /* 1777*82527734SSukumar Swaminathan * WARNING: There is a max of 6 ring masks allowed 1778291a2b48SSukumar Swaminathan */ 1779*82527734SSukumar Swaminathan /* RING 0 - FCP */ 1780*82527734SSukumar Swaminathan if (hba->tgt_mode) { 1781*82527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_FCP_RING] = 1; 1782*82527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_FCP_CMND; 1783*82527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0; 1784*82527734SSukumar Swaminathan hba->sli.sli3.ring_tval[i] = FC_FCP_DATA; 1785*82527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 1786*82527734SSukumar Swaminathan } else { 1787*82527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_FCP_RING] = 0; 1788291a2b48SSukumar Swaminathan } 1789291a2b48SSukumar Swaminathan 1790*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_FCP_RING].fc_numCiocb = SLIM_IOCB_CMD_R0_ENTRIES; 1791*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_FCP_RING].fc_numRiocb = SLIM_IOCB_RSP_R0_ENTRIES; 1792291a2b48SSukumar Swaminathan 1793*82527734SSukumar Swaminathan /* RING 1 - IP */ 1794*82527734SSukumar Swaminathan if (cfg[CFG_NETWORK_ON].current) { 1795*82527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_IP_RING] = 1; 1796*82527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_UNSOL_DATA; /* Unsol Data */ 1797*82527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0xFF; 1798*82527734SSukumar Swaminathan hba->sli.sli3.ring_tval[i] = FC_LLC_SNAP; /* LLC/SNAP */ 1799*82527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 1800291a2b48SSukumar Swaminathan } else { 1801*82527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_IP_RING] = 0; 1802291a2b48SSukumar Swaminathan } 1803291a2b48SSukumar Swaminathan 1804*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_IP_RING].fc_numCiocb = SLIM_IOCB_CMD_R1_ENTRIES; 1805*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_IP_RING].fc_numRiocb = SLIM_IOCB_RSP_R1_ENTRIES; 18064baa2c25SSukumar Swaminathan 1807*82527734SSukumar Swaminathan /* RING 2 - ELS */ 1808*82527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_ELS_RING] = 1; 1809*82527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_ELS_REQ; /* ELS request/rsp */ 1810*82527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0xFE; 1811*82527734SSukumar Swaminathan hba->sli.sli3.ring_tval[i] = FC_ELS_DATA; /* ELS */ 1812*82527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 1813291a2b48SSukumar Swaminathan 1814*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_ELS_RING].fc_numCiocb = SLIM_IOCB_CMD_R2_ENTRIES; 1815*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_ELS_RING].fc_numRiocb = SLIM_IOCB_RSP_R2_ENTRIES; 1816291a2b48SSukumar Swaminathan 1817*82527734SSukumar Swaminathan /* RING 3 - CT */ 1818*82527734SSukumar Swaminathan hba->sli.sli3.ring_masks[FC_CT_RING] = 1; 1819*82527734SSukumar Swaminathan hba->sli.sli3.ring_rval[i] = FC_UNSOL_CTL; /* CT request/rsp */ 1820*82527734SSukumar Swaminathan hba->sli.sli3.ring_rmask[i] = 0xFE; 1821*82527734SSukumar Swaminathan hba->sli.sli3.ring_tval[i] = FC_CT_TYPE; /* CT */ 1822*82527734SSukumar Swaminathan hba->sli.sli3.ring_tmask[i++] = 0xFF; 1823291a2b48SSukumar Swaminathan 1824*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_CT_RING].fc_numCiocb = SLIM_IOCB_CMD_R3_ENTRIES; 1825*82527734SSukumar Swaminathan hba->sli.sli3.ring[FC_CT_RING].fc_numRiocb = SLIM_IOCB_RSP_R3_ENTRIES; 1826291a2b48SSukumar Swaminathan 1827*82527734SSukumar Swaminathan if (i > 6) { 1828*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 1829*82527734SSukumar Swaminathan "emlxs_hba_init: Too many ring masks defined. cnt=%d", i); 1830*82527734SSukumar Swaminathan return (1); 1831*82527734SSukumar Swaminathan } 1832*82527734SSukumar Swaminathan 1833*82527734SSukumar Swaminathan /* Initialize all the port objects */ 1834*82527734SSukumar Swaminathan hba->vpi_base = 0; 1835*82527734SSukumar Swaminathan hba->vpi_max = 0; 1836*82527734SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 1837*82527734SSukumar Swaminathan vport = &VPORT(i); 1838*82527734SSukumar Swaminathan vport->hba = hba; 1839*82527734SSukumar Swaminathan vport->vpi = i; 1840*82527734SSukumar Swaminathan } 1841*82527734SSukumar Swaminathan 1842*82527734SSukumar Swaminathan /* 1843*82527734SSukumar Swaminathan * Initialize the max_node count to a default value if needed 1844*82527734SSukumar Swaminathan * This determines how many node objects we preallocate in the pool 1845*82527734SSukumar Swaminathan * The actual max_nodes will be set later based on adapter info 1846*82527734SSukumar Swaminathan */ 1847*82527734SSukumar Swaminathan if (hba->max_nodes == 0) { 1848*82527734SSukumar Swaminathan if (cfg[CFG_NUM_NODES].current > 0) { 1849*82527734SSukumar Swaminathan hba->max_nodes = cfg[CFG_NUM_NODES].current; 1850*82527734SSukumar Swaminathan } else if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 1851*82527734SSukumar Swaminathan hba->max_nodes = 4096; 1852*82527734SSukumar Swaminathan } else { 1853*82527734SSukumar Swaminathan hba->max_nodes = 512; 1854*82527734SSukumar Swaminathan } 1855*82527734SSukumar Swaminathan } 1856291a2b48SSukumar Swaminathan 1857*82527734SSukumar Swaminathan return (0); 1858291a2b48SSukumar Swaminathan 1859*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_init() */ 1860291a2b48SSukumar Swaminathan 1861291a2b48SSukumar Swaminathan 1862*82527734SSukumar Swaminathan /* 1863*82527734SSukumar Swaminathan * 0: quiesce indicates the call is not from quiesce routine. 1864*82527734SSukumar Swaminathan * 1: quiesce indicates the call is from quiesce routine. 1865*82527734SSukumar Swaminathan */ 1866*82527734SSukumar Swaminathan static uint32_t 1867*82527734SSukumar Swaminathan emlxs_sli3_hba_reset(emlxs_hba_t *hba, uint32_t restart, uint32_t skip_post, 1868*82527734SSukumar Swaminathan uint32_t quiesce) 1869291a2b48SSukumar Swaminathan { 1870*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 1871*82527734SSukumar Swaminathan MAILBOX *swpmb; 1872*82527734SSukumar Swaminathan MAILBOX *mb; 1873*82527734SSukumar Swaminathan uint32_t word0; 1874*82527734SSukumar Swaminathan uint16_t cfg_value; 1875*82527734SSukumar Swaminathan uint32_t status; 1876*82527734SSukumar Swaminathan uint32_t status1; 1877*82527734SSukumar Swaminathan uint32_t status2; 1878*82527734SSukumar Swaminathan uint32_t i; 1879*82527734SSukumar Swaminathan uint32_t ready; 1880*82527734SSukumar Swaminathan emlxs_port_t *vport; 1881*82527734SSukumar Swaminathan RING *rp; 1882*82527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 1883291a2b48SSukumar Swaminathan 1884*82527734SSukumar Swaminathan i = 0; 1885291a2b48SSukumar Swaminathan 1886*82527734SSukumar Swaminathan if (!cfg[CFG_RESET_ENABLE].current) { 1887*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 1888*82527734SSukumar Swaminathan "Adapter reset disabled."); 1889*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 1890291a2b48SSukumar Swaminathan 1891*82527734SSukumar Swaminathan return (1); 1892291a2b48SSukumar Swaminathan } 1893291a2b48SSukumar Swaminathan 1894*82527734SSukumar Swaminathan /* Kill the adapter first */ 1895*82527734SSukumar Swaminathan if (quiesce == 0) { 1896*82527734SSukumar Swaminathan emlxs_sli3_hba_kill(hba); 1897*82527734SSukumar Swaminathan } else { 1898*82527734SSukumar Swaminathan emlxs_sli3_hba_kill4quiesce(hba); 1899291a2b48SSukumar Swaminathan } 1900291a2b48SSukumar Swaminathan 1901*82527734SSukumar Swaminathan if (restart) { 1902*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1903*82527734SSukumar Swaminathan "Restarting."); 1904*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_START); 1905291a2b48SSukumar Swaminathan 1906*82527734SSukumar Swaminathan ready = (HS_FFRDY | HS_MBRDY); 1907*82527734SSukumar Swaminathan } else { 1908*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1909*82527734SSukumar Swaminathan "Resetting."); 1910*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_WARM_START); 1911291a2b48SSukumar Swaminathan 1912*82527734SSukumar Swaminathan ready = HS_MBRDY; 1913291a2b48SSukumar Swaminathan } 1914291a2b48SSukumar Swaminathan 1915*82527734SSukumar Swaminathan hba->flag &= ~(FC_SLIM2_MODE | FC_HARDWARE_ERROR); 1916291a2b48SSukumar Swaminathan 1917*82527734SSukumar Swaminathan mb = FC_SLIM1_MAILBOX(hba); 1918*82527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 1919291a2b48SSukumar Swaminathan 1920*82527734SSukumar Swaminathan reset: 1921291a2b48SSukumar Swaminathan 1922*82527734SSukumar Swaminathan /* Save reset time */ 1923*82527734SSukumar Swaminathan HBASTATS.ResetTime = hba->timer_tics; 1924291a2b48SSukumar Swaminathan 1925*82527734SSukumar Swaminathan if (restart) { 1926*82527734SSukumar Swaminathan /* First put restart command in mailbox */ 1927*82527734SSukumar Swaminathan word0 = 0; 1928*82527734SSukumar Swaminathan swpmb->mbxCommand = MBX_RESTART; 1929*82527734SSukumar Swaminathan swpmb->mbxHc = 1; 1930*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb), word0); 1931*82527734SSukumar Swaminathan 1932*82527734SSukumar Swaminathan /* Only skip post after emlxs_sli3_online is completed */ 1933*82527734SSukumar Swaminathan if (skip_post) { 1934*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1), 1935*82527734SSukumar Swaminathan 1); 1936*82527734SSukumar Swaminathan } else { 1937*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb) + 1), 1938*82527734SSukumar Swaminathan 0); 1939291a2b48SSukumar Swaminathan } 1940291a2b48SSukumar Swaminathan 1941*82527734SSukumar Swaminathan } 1942291a2b48SSukumar Swaminathan 1943*82527734SSukumar Swaminathan /* 1944*82527734SSukumar Swaminathan * Turn off SERR, PERR in PCI cmd register 1945*82527734SSukumar Swaminathan */ 1946*82527734SSukumar Swaminathan cfg_value = ddi_get16(hba->pci_acc_handle, 1947*82527734SSukumar Swaminathan (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER)); 1948291a2b48SSukumar Swaminathan 1949*82527734SSukumar Swaminathan ddi_put16(hba->pci_acc_handle, 1950*82527734SSukumar Swaminathan (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 1951*82527734SSukumar Swaminathan (uint16_t)(cfg_value & ~(CMD_PARITY_CHK | CMD_SERR_ENBL))); 1952291a2b48SSukumar Swaminathan 1953*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy = HC_INITFF; 1954*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 1955291a2b48SSukumar Swaminathan 1956*82527734SSukumar Swaminathan /* Wait 1 msec before restoring PCI config */ 1957*82527734SSukumar Swaminathan DELAYMS(1); 1958291a2b48SSukumar Swaminathan 1959*82527734SSukumar Swaminathan /* Restore PCI cmd register */ 1960*82527734SSukumar Swaminathan ddi_put16(hba->pci_acc_handle, 1961*82527734SSukumar Swaminathan (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 1962*82527734SSukumar Swaminathan (uint16_t)cfg_value); 1963291a2b48SSukumar Swaminathan 1964*82527734SSukumar Swaminathan /* Wait 3 seconds before checking */ 1965*82527734SSukumar Swaminathan DELAYMS(3000); 1966*82527734SSukumar Swaminathan i += 3; 1967291a2b48SSukumar Swaminathan 1968*82527734SSukumar Swaminathan /* Wait for reset completion */ 1969*82527734SSukumar Swaminathan while (i < 30) { 1970*82527734SSukumar Swaminathan /* Check status register to see what current state is */ 1971*82527734SSukumar Swaminathan status = READ_CSR_REG(hba, FC_HS_REG(hba)); 1972291a2b48SSukumar Swaminathan 1973*82527734SSukumar Swaminathan /* Check to see if any errors occurred during init */ 1974*82527734SSukumar Swaminathan if (status & HS_FFERM) { 1975*82527734SSukumar Swaminathan status1 = READ_SLIM_ADDR(hba, ((volatile uint8_t *) 1976*82527734SSukumar Swaminathan hba->sli.sli3.slim_addr + 0xa8)); 1977*82527734SSukumar Swaminathan status2 = READ_SLIM_ADDR(hba, ((volatile uint8_t *) 1978*82527734SSukumar Swaminathan hba->sli.sli3.slim_addr + 0xac)); 1979291a2b48SSukumar Swaminathan 1980*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 1981*82527734SSukumar Swaminathan "HS_FFERM: status=0x%x status1=0x%x status2=0x%x", 1982*82527734SSukumar Swaminathan status, status1, status2); 1983291a2b48SSukumar Swaminathan 1984*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 1985*82527734SSukumar Swaminathan return (1); 1986291a2b48SSukumar Swaminathan } 1987291a2b48SSukumar Swaminathan 1988*82527734SSukumar Swaminathan if ((status & ready) == ready) { 1989*82527734SSukumar Swaminathan /* Reset Done !! */ 1990*82527734SSukumar Swaminathan goto done; 1991*82527734SSukumar Swaminathan } 1992291a2b48SSukumar Swaminathan 1993*82527734SSukumar Swaminathan /* 1994*82527734SSukumar Swaminathan * Check every 1 second for 15 seconds, then reset board 1995*82527734SSukumar Swaminathan * again (w/post), then check every 1 second for 15 * seconds. 1996*82527734SSukumar Swaminathan */ 1997*82527734SSukumar Swaminathan DELAYMS(1000); 1998*82527734SSukumar Swaminathan i++; 1999291a2b48SSukumar Swaminathan 2000*82527734SSukumar Swaminathan /* Reset again (w/post) at 15 seconds */ 2001*82527734SSukumar Swaminathan if (i == 15) { 2002*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2003*82527734SSukumar Swaminathan "Reset failed. Retrying..."); 2004291a2b48SSukumar Swaminathan 2005*82527734SSukumar Swaminathan goto reset; 2006291a2b48SSukumar Swaminathan } 2007291a2b48SSukumar Swaminathan } 2008291a2b48SSukumar Swaminathan 2009*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 2010*82527734SSukumar Swaminathan reset_fail: 2011*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2012291a2b48SSukumar Swaminathan 2013*82527734SSukumar Swaminathan /* Timeout occurred */ 2014*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_reset_failed_msg, 2015*82527734SSukumar Swaminathan "Timeout: status=0x%x", status); 2016*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 2017291a2b48SSukumar Swaminathan 2018*82527734SSukumar Swaminathan /* Log a dump event */ 2019*82527734SSukumar Swaminathan emlxs_log_dump_event(port, NULL, 0); 2020291a2b48SSukumar Swaminathan 2021*82527734SSukumar Swaminathan return (1); 2022291a2b48SSukumar Swaminathan 2023*82527734SSukumar Swaminathan done: 2024291a2b48SSukumar Swaminathan 2025*82527734SSukumar Swaminathan /* Initialize hc_copy */ 2026*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy = READ_CSR_REG(hba, FC_HC_REG(hba)); 2027291a2b48SSukumar Swaminathan 20284baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 20294baa2c25SSukumar Swaminathan /* Access handle validation */ 2030*82527734SSukumar Swaminathan if ((emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 20314baa2c25SSukumar Swaminathan != DDI_FM_OK) || 2032*82527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 2033*82527734SSukumar Swaminathan != DDI_FM_OK) || 2034*82527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 20354baa2c25SSukumar Swaminathan != DDI_FM_OK)) { 20364baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 20374baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 2038*82527734SSukumar Swaminathan goto reset_fail; 20394baa2c25SSukumar Swaminathan } 20404baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 20414baa2c25SSukumar Swaminathan 2042*82527734SSukumar Swaminathan /* Reset the hba structure */ 2043*82527734SSukumar Swaminathan hba->flag &= FC_RESET_MASK; 2044*82527734SSukumar Swaminathan hba->channel_tx_count = 0; 2045*82527734SSukumar Swaminathan hba->io_count = 0; 2046*82527734SSukumar Swaminathan hba->iodone_count = 0; 2047*82527734SSukumar Swaminathan hba->topology = 0; 2048*82527734SSukumar Swaminathan hba->linkspeed = 0; 2049*82527734SSukumar Swaminathan hba->heartbeat_active = 0; 2050*82527734SSukumar Swaminathan hba->discovery_timer = 0; 2051*82527734SSukumar Swaminathan hba->linkup_timer = 0; 2052*82527734SSukumar Swaminathan hba->loopback_tics = 0; 2053291a2b48SSukumar Swaminathan 2054291a2b48SSukumar Swaminathan 2055*82527734SSukumar Swaminathan /* Reset the ring objects */ 2056*82527734SSukumar Swaminathan for (i = 0; i < MAX_RINGS; i++) { 2057*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[i]; 2058*82527734SSukumar Swaminathan rp->fc_mpon = 0; 2059*82527734SSukumar Swaminathan rp->fc_mpoff = 0; 2060*82527734SSukumar Swaminathan } 2061291a2b48SSukumar Swaminathan 2062*82527734SSukumar Swaminathan /* Reset the port objects */ 2063*82527734SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 2064*82527734SSukumar Swaminathan vport = &VPORT(i); 2065291a2b48SSukumar Swaminathan 2066*82527734SSukumar Swaminathan vport->flag &= EMLXS_PORT_RESET_MASK; 2067*82527734SSukumar Swaminathan vport->did = 0; 2068*82527734SSukumar Swaminathan vport->prev_did = 0; 2069*82527734SSukumar Swaminathan vport->lip_type = 0; 2070*82527734SSukumar Swaminathan bzero(&vport->fabric_sparam, sizeof (SERV_PARM)); 2071*82527734SSukumar Swaminathan 2072*82527734SSukumar Swaminathan bzero((caddr_t)&vport->node_base, sizeof (NODELIST)); 2073*82527734SSukumar Swaminathan vport->node_base.nlp_Rpi = 0; 2074*82527734SSukumar Swaminathan vport->node_base.nlp_DID = 0xffffff; 2075*82527734SSukumar Swaminathan vport->node_base.nlp_list_next = NULL; 2076*82527734SSukumar Swaminathan vport->node_base.nlp_list_prev = NULL; 2077*82527734SSukumar Swaminathan vport->node_base.nlp_active = 1; 2078*82527734SSukumar Swaminathan vport->node_count = 0; 2079*82527734SSukumar Swaminathan 2080*82527734SSukumar Swaminathan if (vport->ub_count < EMLXS_UB_TOKEN_OFFSET) { 2081*82527734SSukumar Swaminathan vport->ub_count = EMLXS_UB_TOKEN_OFFSET; 2082291a2b48SSukumar Swaminathan } 2083*82527734SSukumar Swaminathan } 2084291a2b48SSukumar Swaminathan 2085*82527734SSukumar Swaminathan return (0); 2086291a2b48SSukumar Swaminathan 2087*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_reset */ 2088291a2b48SSukumar Swaminathan 2089291a2b48SSukumar Swaminathan 2090*82527734SSukumar Swaminathan #define BPL_CMD 0 2091*82527734SSukumar Swaminathan #define BPL_RESP 1 2092*82527734SSukumar Swaminathan #define BPL_DATA 2 2093291a2b48SSukumar Swaminathan 2094*82527734SSukumar Swaminathan static ULP_BDE64 * 2095*82527734SSukumar Swaminathan emlxs_pkt_to_bpl(ULP_BDE64 *bpl, fc_packet_t *pkt, uint32_t bpl_type, 2096*82527734SSukumar Swaminathan uint8_t bdeFlags) 2097*82527734SSukumar Swaminathan { 2098*82527734SSukumar Swaminathan ddi_dma_cookie_t *cp; 2099*82527734SSukumar Swaminathan uint_t i; 2100*82527734SSukumar Swaminathan int32_t size; 2101*82527734SSukumar Swaminathan uint_t cookie_cnt; 2102291a2b48SSukumar Swaminathan 2103*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3) 2104*82527734SSukumar Swaminathan switch (bpl_type) { 2105*82527734SSukumar Swaminathan case BPL_CMD: 2106*82527734SSukumar Swaminathan cp = pkt->pkt_cmd_cookie; 2107*82527734SSukumar Swaminathan cookie_cnt = pkt->pkt_cmd_cookie_cnt; 2108*82527734SSukumar Swaminathan size = (int32_t)pkt->pkt_cmdlen; 2109*82527734SSukumar Swaminathan break; 2110291a2b48SSukumar Swaminathan 2111*82527734SSukumar Swaminathan case BPL_RESP: 2112*82527734SSukumar Swaminathan cp = pkt->pkt_resp_cookie; 2113*82527734SSukumar Swaminathan cookie_cnt = pkt->pkt_resp_cookie_cnt; 2114*82527734SSukumar Swaminathan size = (int32_t)pkt->pkt_rsplen; 2115*82527734SSukumar Swaminathan break; 2116291a2b48SSukumar Swaminathan 2117291a2b48SSukumar Swaminathan 2118*82527734SSukumar Swaminathan case BPL_DATA: 2119*82527734SSukumar Swaminathan cp = pkt->pkt_data_cookie; 2120*82527734SSukumar Swaminathan cookie_cnt = pkt->pkt_data_cookie_cnt; 2121*82527734SSukumar Swaminathan size = (int32_t)pkt->pkt_datalen; 2122*82527734SSukumar Swaminathan break; 2123*82527734SSukumar Swaminathan } 2124291a2b48SSukumar Swaminathan 2125*82527734SSukumar Swaminathan #else 2126*82527734SSukumar Swaminathan switch (bpl_type) { 2127*82527734SSukumar Swaminathan case BPL_CMD: 2128*82527734SSukumar Swaminathan cp = &pkt->pkt_cmd_cookie; 2129*82527734SSukumar Swaminathan cookie_cnt = 1; 2130*82527734SSukumar Swaminathan size = (int32_t)pkt->pkt_cmdlen; 2131*82527734SSukumar Swaminathan break; 2132291a2b48SSukumar Swaminathan 2133*82527734SSukumar Swaminathan case BPL_RESP: 2134*82527734SSukumar Swaminathan cp = &pkt->pkt_resp_cookie; 2135*82527734SSukumar Swaminathan cookie_cnt = 1; 2136*82527734SSukumar Swaminathan size = (int32_t)pkt->pkt_rsplen; 2137*82527734SSukumar Swaminathan break; 2138291a2b48SSukumar Swaminathan 2139291a2b48SSukumar Swaminathan 2140*82527734SSukumar Swaminathan case BPL_DATA: 2141*82527734SSukumar Swaminathan cp = &pkt->pkt_data_cookie; 2142*82527734SSukumar Swaminathan cookie_cnt = 1; 2143*82527734SSukumar Swaminathan size = (int32_t)pkt->pkt_datalen; 2144*82527734SSukumar Swaminathan break; 2145*82527734SSukumar Swaminathan } 2146*82527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */ 2147291a2b48SSukumar Swaminathan 2148*82527734SSukumar Swaminathan for (i = 0; i < cookie_cnt && size > 0; i++, cp++) { 2149*82527734SSukumar Swaminathan bpl->addrHigh = 2150*82527734SSukumar Swaminathan BE_SWAP32(PADDR_HI(cp->dmac_laddress)); 2151*82527734SSukumar Swaminathan bpl->addrLow = 2152*82527734SSukumar Swaminathan BE_SWAP32(PADDR_LO(cp->dmac_laddress)); 2153*82527734SSukumar Swaminathan bpl->tus.f.bdeSize = MIN(size, cp->dmac_size); 2154*82527734SSukumar Swaminathan bpl->tus.f.bdeFlags = bdeFlags; 2155*82527734SSukumar Swaminathan bpl->tus.w = BE_SWAP32(bpl->tus.w); 2156291a2b48SSukumar Swaminathan 2157*82527734SSukumar Swaminathan bpl++; 2158*82527734SSukumar Swaminathan size -= cp->dmac_size; 2159*82527734SSukumar Swaminathan } 2160291a2b48SSukumar Swaminathan 2161*82527734SSukumar Swaminathan return (bpl); 2162291a2b48SSukumar Swaminathan 2163*82527734SSukumar Swaminathan } /* emlxs_pkt_to_bpl */ 2164291a2b48SSukumar Swaminathan 2165291a2b48SSukumar Swaminathan 2166*82527734SSukumar Swaminathan static uint32_t 2167*82527734SSukumar Swaminathan emlxs_sli2_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2168*82527734SSukumar Swaminathan { 2169*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 2170*82527734SSukumar Swaminathan fc_packet_t *pkt; 2171*82527734SSukumar Swaminathan MATCHMAP *bmp; 2172*82527734SSukumar Swaminathan ULP_BDE64 *bpl; 2173*82527734SSukumar Swaminathan uint64_t bp; 2174*82527734SSukumar Swaminathan uint8_t bdeFlag; 2175*82527734SSukumar Swaminathan IOCB *iocb; 2176*82527734SSukumar Swaminathan IOCBQ *iocbq; 2177*82527734SSukumar Swaminathan CHANNEL *cp; 2178*82527734SSukumar Swaminathan uint32_t cmd_cookie_cnt; 2179*82527734SSukumar Swaminathan uint32_t resp_cookie_cnt; 2180*82527734SSukumar Swaminathan uint32_t data_cookie_cnt; 2181*82527734SSukumar Swaminathan uint32_t cookie_cnt; 2182291a2b48SSukumar Swaminathan 2183*82527734SSukumar Swaminathan cp = sbp->channel; 2184*82527734SSukumar Swaminathan iocb = (IOCB *) & sbp->iocbq; 2185*82527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 2186291a2b48SSukumar Swaminathan 2187*82527734SSukumar Swaminathan #ifdef EMLXS_SPARC 2188*82527734SSukumar Swaminathan /* Use FCP MEM_BPL table to get BPL buffer */ 2189*82527734SSukumar Swaminathan bmp = hba->sli.sli3.fcp_bpl_table[sbp->iotag]; 2190*82527734SSukumar Swaminathan #else 2191*82527734SSukumar Swaminathan /* Use MEM_BPL pool to get BPL buffer */ 2192*82527734SSukumar Swaminathan bmp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BPL, 0); 2193291a2b48SSukumar Swaminathan 2194*82527734SSukumar Swaminathan #endif 2195291a2b48SSukumar Swaminathan 2196*82527734SSukumar Swaminathan if (!bmp) { 2197*82527734SSukumar Swaminathan return (1); 2198*82527734SSukumar Swaminathan } 2199291a2b48SSukumar Swaminathan 2200*82527734SSukumar Swaminathan sbp->bmp = bmp; 2201*82527734SSukumar Swaminathan bpl = (ULP_BDE64 *)bmp->virt; 2202*82527734SSukumar Swaminathan bp = bmp->phys; 2203*82527734SSukumar Swaminathan cookie_cnt = 0; 2204291a2b48SSukumar Swaminathan 2205*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3) 2206*82527734SSukumar Swaminathan cmd_cookie_cnt = pkt->pkt_cmd_cookie_cnt; 2207*82527734SSukumar Swaminathan resp_cookie_cnt = pkt->pkt_resp_cookie_cnt; 2208*82527734SSukumar Swaminathan data_cookie_cnt = pkt->pkt_data_cookie_cnt; 2209*82527734SSukumar Swaminathan #else 2210*82527734SSukumar Swaminathan cmd_cookie_cnt = 1; 2211*82527734SSukumar Swaminathan resp_cookie_cnt = 1; 2212*82527734SSukumar Swaminathan data_cookie_cnt = 1; 2213*82527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */ 2214291a2b48SSukumar Swaminathan 2215*82527734SSukumar Swaminathan iocbq = &sbp->iocbq; 2216*82527734SSukumar Swaminathan if (iocbq->flag & IOCB_FCP_CMD) 2217*82527734SSukumar Swaminathan goto fcpcmd; 2218*82527734SSukumar Swaminathan 2219*82527734SSukumar Swaminathan switch (cp->channelno) { 2220*82527734SSukumar Swaminathan case FC_FCP_RING: 2221*82527734SSukumar Swaminathan fcpcmd: 2222*82527734SSukumar Swaminathan /* CMD payload */ 2223*82527734SSukumar Swaminathan bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2224*82527734SSukumar Swaminathan cookie_cnt = cmd_cookie_cnt; 2225*82527734SSukumar Swaminathan 2226*82527734SSukumar Swaminathan if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2227*82527734SSukumar Swaminathan /* RSP payload */ 2228*82527734SSukumar Swaminathan bpl = 2229*82527734SSukumar Swaminathan emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP, 2230*82527734SSukumar Swaminathan BUFF_USE_RCV); 2231*82527734SSukumar Swaminathan cookie_cnt += resp_cookie_cnt; 2232*82527734SSukumar Swaminathan 2233*82527734SSukumar Swaminathan /* DATA payload */ 2234*82527734SSukumar Swaminathan if (pkt->pkt_datalen != 0) { 2235*82527734SSukumar Swaminathan bdeFlag = 2236*82527734SSukumar Swaminathan (pkt->pkt_tran_type == 2237*82527734SSukumar Swaminathan FC_PKT_FCP_READ) ? BUFF_USE_RCV : 0; 2238*82527734SSukumar Swaminathan bpl = 2239*82527734SSukumar Swaminathan emlxs_pkt_to_bpl(bpl, pkt, BPL_DATA, 2240*82527734SSukumar Swaminathan bdeFlag); 2241*82527734SSukumar Swaminathan cookie_cnt += data_cookie_cnt; 2242*82527734SSukumar Swaminathan } 2243291a2b48SSukumar Swaminathan } 2244*82527734SSukumar Swaminathan /* 2245*82527734SSukumar Swaminathan * else 2246*82527734SSukumar Swaminathan * { 2247*82527734SSukumar Swaminathan * Target mode FCP status. Do nothing more. 2248*82527734SSukumar Swaminathan * } 2249*82527734SSukumar Swaminathan */ 2250291a2b48SSukumar Swaminathan 2251*82527734SSukumar Swaminathan break; 2252291a2b48SSukumar Swaminathan 2253*82527734SSukumar Swaminathan case FC_IP_RING: 2254*82527734SSukumar Swaminathan 2255*82527734SSukumar Swaminathan /* CMD payload */ 2256*82527734SSukumar Swaminathan bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2257*82527734SSukumar Swaminathan cookie_cnt = cmd_cookie_cnt; 2258291a2b48SSukumar Swaminathan 2259291a2b48SSukumar Swaminathan break; 2260291a2b48SSukumar Swaminathan 2261*82527734SSukumar Swaminathan case FC_ELS_RING: 2262291a2b48SSukumar Swaminathan 2263*82527734SSukumar Swaminathan /* CMD payload */ 2264*82527734SSukumar Swaminathan bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2265*82527734SSukumar Swaminathan cookie_cnt = cmd_cookie_cnt; 2266291a2b48SSukumar Swaminathan 2267*82527734SSukumar Swaminathan /* RSP payload */ 2268*82527734SSukumar Swaminathan if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2269*82527734SSukumar Swaminathan bpl = 2270*82527734SSukumar Swaminathan emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP, 2271*82527734SSukumar Swaminathan BUFF_USE_RCV); 2272*82527734SSukumar Swaminathan cookie_cnt += resp_cookie_cnt; 2273*82527734SSukumar Swaminathan } 2274291a2b48SSukumar Swaminathan 2275*82527734SSukumar Swaminathan break; 2276291a2b48SSukumar Swaminathan 2277291a2b48SSukumar Swaminathan 2278*82527734SSukumar Swaminathan case FC_CT_RING: 2279291a2b48SSukumar Swaminathan 2280*82527734SSukumar Swaminathan /* CMD payload */ 2281*82527734SSukumar Swaminathan bpl = emlxs_pkt_to_bpl(bpl, pkt, BPL_CMD, 0); 2282*82527734SSukumar Swaminathan cookie_cnt = cmd_cookie_cnt; 2283291a2b48SSukumar Swaminathan 2284*82527734SSukumar Swaminathan if ((pkt->pkt_tran_type != FC_PKT_OUTBOUND) || 2285*82527734SSukumar Swaminathan (pkt->pkt_cmd_fhdr.type == EMLXS_MENLO_TYPE)) { 2286*82527734SSukumar Swaminathan /* RSP payload */ 2287*82527734SSukumar Swaminathan bpl = 2288*82527734SSukumar Swaminathan emlxs_pkt_to_bpl(bpl, pkt, BPL_RESP, 2289*82527734SSukumar Swaminathan BUFF_USE_RCV); 2290*82527734SSukumar Swaminathan cookie_cnt += resp_cookie_cnt; 2291*82527734SSukumar Swaminathan } 2292291a2b48SSukumar Swaminathan 2293*82527734SSukumar Swaminathan break; 2294291a2b48SSukumar Swaminathan 2295291a2b48SSukumar Swaminathan } 2296291a2b48SSukumar Swaminathan 2297*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BDL; 2298*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrHigh = PADDR_HI(bp); 2299*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrLow = PADDR_LO(bp); 2300*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.bdeSize = cookie_cnt * sizeof (ULP_BDE64); 2301291a2b48SSukumar Swaminathan 2302*82527734SSukumar Swaminathan iocb->ULPBDECOUNT = 1; 2303*82527734SSukumar Swaminathan iocb->ULPLE = 1; 2304291a2b48SSukumar Swaminathan 2305*82527734SSukumar Swaminathan return (0); 2306291a2b48SSukumar Swaminathan 2307*82527734SSukumar Swaminathan } /* emlxs_sli2_bde_setup */ 2308291a2b48SSukumar Swaminathan 2309291a2b48SSukumar Swaminathan 2310*82527734SSukumar Swaminathan static uint32_t 2311*82527734SSukumar Swaminathan emlxs_sli3_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2312*82527734SSukumar Swaminathan { 2313*82527734SSukumar Swaminathan ddi_dma_cookie_t *cp_cmd; 2314*82527734SSukumar Swaminathan ddi_dma_cookie_t *cp_resp; 2315*82527734SSukumar Swaminathan ddi_dma_cookie_t *cp_data; 2316*82527734SSukumar Swaminathan fc_packet_t *pkt; 2317*82527734SSukumar Swaminathan ULP_BDE64 *bde; 2318*82527734SSukumar Swaminathan int data_cookie_cnt; 2319*82527734SSukumar Swaminathan uint32_t i; 2320*82527734SSukumar Swaminathan IOCB *iocb; 2321*82527734SSukumar Swaminathan IOCBQ *iocbq; 2322*82527734SSukumar Swaminathan CHANNEL *cp; 2323291a2b48SSukumar Swaminathan 2324*82527734SSukumar Swaminathan cp = sbp->channel; 2325*82527734SSukumar Swaminathan iocb = (IOCB *) & sbp->iocbq; 2326*82527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 2327*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3) 2328*82527734SSukumar Swaminathan if ((pkt->pkt_cmd_cookie_cnt > 1) || 2329*82527734SSukumar Swaminathan (pkt->pkt_resp_cookie_cnt > 1) || 2330*82527734SSukumar Swaminathan ((pkt->pkt_cmd_cookie_cnt + pkt->pkt_resp_cookie_cnt + 2331*82527734SSukumar Swaminathan pkt->pkt_data_cookie_cnt) > SLI3_MAX_BDE)) { 2332*82527734SSukumar Swaminathan i = emlxs_sli2_bde_setup(port, sbp); 2333*82527734SSukumar Swaminathan return (i); 2334*82527734SSukumar Swaminathan } 2335291a2b48SSukumar Swaminathan 2336*82527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */ 2337291a2b48SSukumar Swaminathan 2338*82527734SSukumar Swaminathan #if (EMLXS_MODREV >= EMLXS_MODREV3) 2339*82527734SSukumar Swaminathan cp_cmd = pkt->pkt_cmd_cookie; 2340*82527734SSukumar Swaminathan cp_resp = pkt->pkt_resp_cookie; 2341*82527734SSukumar Swaminathan cp_data = pkt->pkt_data_cookie; 2342*82527734SSukumar Swaminathan data_cookie_cnt = pkt->pkt_data_cookie_cnt; 2343*82527734SSukumar Swaminathan #else 2344*82527734SSukumar Swaminathan cp_cmd = &pkt->pkt_cmd_cookie; 2345*82527734SSukumar Swaminathan cp_resp = &pkt->pkt_resp_cookie; 2346*82527734SSukumar Swaminathan cp_data = &pkt->pkt_data_cookie; 2347*82527734SSukumar Swaminathan data_cookie_cnt = 1; 2348*82527734SSukumar Swaminathan #endif /* >= EMLXS_MODREV3 */ 2349291a2b48SSukumar Swaminathan 2350*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count = 0; 2351291a2b48SSukumar Swaminathan 2352*82527734SSukumar Swaminathan iocbq = &sbp->iocbq; 2353*82527734SSukumar Swaminathan if (iocbq->flag & IOCB_FCP_CMD) 2354*82527734SSukumar Swaminathan goto fcpcmd; 2355291a2b48SSukumar Swaminathan 2356*82527734SSukumar Swaminathan switch (cp->channelno) { 2357*82527734SSukumar Swaminathan case FC_FCP_RING: 2358*82527734SSukumar Swaminathan fcpcmd: 2359*82527734SSukumar Swaminathan /* CMD payload */ 2360*82527734SSukumar Swaminathan iocb->un.fcpi64.bdl.addrHigh = 2361*82527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 2362*82527734SSukumar Swaminathan iocb->un.fcpi64.bdl.addrLow = 2363*82527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 2364*82527734SSukumar Swaminathan iocb->un.fcpi64.bdl.bdeSize = pkt->pkt_cmdlen; 2365*82527734SSukumar Swaminathan iocb->un.fcpi64.bdl.bdeFlags = 0; 2366291a2b48SSukumar Swaminathan 2367*82527734SSukumar Swaminathan if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2368*82527734SSukumar Swaminathan /* RSP payload */ 2369*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.addrHigh = 2370*82527734SSukumar Swaminathan PADDR_HI(cp_resp->dmac_laddress); 2371*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.addrLow = 2372*82527734SSukumar Swaminathan PADDR_LO(cp_resp->dmac_laddress); 2373*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = 2374*82527734SSukumar Swaminathan pkt->pkt_rsplen; 2375*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 0; 2376*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count = 1; 2377291a2b48SSukumar Swaminathan 2378*82527734SSukumar Swaminathan /* DATA payload */ 2379*82527734SSukumar Swaminathan if (pkt->pkt_datalen != 0) { 2380*82527734SSukumar Swaminathan bde = 2381*82527734SSukumar Swaminathan (ULP_BDE64 *)&iocb->unsli3.ext_iocb. 2382*82527734SSukumar Swaminathan ebde2; 2383*82527734SSukumar Swaminathan for (i = 0; i < data_cookie_cnt; i++) { 2384*82527734SSukumar Swaminathan bde->addrHigh = 2385*82527734SSukumar Swaminathan PADDR_HI(cp_data-> 2386*82527734SSukumar Swaminathan dmac_laddress); 2387*82527734SSukumar Swaminathan bde->addrLow = 2388*82527734SSukumar Swaminathan PADDR_LO(cp_data-> 2389*82527734SSukumar Swaminathan dmac_laddress); 2390*82527734SSukumar Swaminathan bde->tus.f.bdeSize = 2391*82527734SSukumar Swaminathan cp_data->dmac_size; 2392*82527734SSukumar Swaminathan bde->tus.f.bdeFlags = 0; 2393*82527734SSukumar Swaminathan cp_data++; 2394*82527734SSukumar Swaminathan bde++; 2395*82527734SSukumar Swaminathan } 2396*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count += 2397*82527734SSukumar Swaminathan data_cookie_cnt; 2398*82527734SSukumar Swaminathan } 2399*82527734SSukumar Swaminathan } 2400*82527734SSukumar Swaminathan /* 2401*82527734SSukumar Swaminathan * else 2402*82527734SSukumar Swaminathan * { 2403*82527734SSukumar Swaminathan * Target mode FCP status. Do nothing more. 2404*82527734SSukumar Swaminathan * } 2405*82527734SSukumar Swaminathan */ 2406291a2b48SSukumar Swaminathan 2407*82527734SSukumar Swaminathan break; 2408291a2b48SSukumar Swaminathan 2409*82527734SSukumar Swaminathan case FC_IP_RING: 2410291a2b48SSukumar Swaminathan 2411*82527734SSukumar Swaminathan /* CMD payload */ 2412*82527734SSukumar Swaminathan iocb->un.xseq64.bdl.addrHigh = 2413*82527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 2414*82527734SSukumar Swaminathan iocb->un.xseq64.bdl.addrLow = 2415*82527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 2416*82527734SSukumar Swaminathan iocb->un.xseq64.bdl.bdeSize = pkt->pkt_cmdlen; 2417*82527734SSukumar Swaminathan iocb->un.xseq64.bdl.bdeFlags = 0; 2418291a2b48SSukumar Swaminathan 2419*82527734SSukumar Swaminathan break; 2420291a2b48SSukumar Swaminathan 2421*82527734SSukumar Swaminathan case FC_ELS_RING: 2422291a2b48SSukumar Swaminathan 2423*82527734SSukumar Swaminathan /* CMD payload */ 2424*82527734SSukumar Swaminathan iocb->un.elsreq64.bdl.addrHigh = 2425*82527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 2426*82527734SSukumar Swaminathan iocb->un.elsreq64.bdl.addrLow = 2427*82527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 2428*82527734SSukumar Swaminathan iocb->un.elsreq64.bdl.bdeSize = pkt->pkt_cmdlen; 2429*82527734SSukumar Swaminathan iocb->un.elsreq64.bdl.bdeFlags = 0; 2430291a2b48SSukumar Swaminathan 2431*82527734SSukumar Swaminathan /* RSP payload */ 2432*82527734SSukumar Swaminathan if (pkt->pkt_tran_type != FC_PKT_OUTBOUND) { 2433*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.addrHigh = 2434*82527734SSukumar Swaminathan PADDR_HI(cp_resp->dmac_laddress); 2435*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.addrLow = 2436*82527734SSukumar Swaminathan PADDR_LO(cp_resp->dmac_laddress); 2437*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = 2438*82527734SSukumar Swaminathan pkt->pkt_rsplen; 2439*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 2440*82527734SSukumar Swaminathan BUFF_USE_RCV; 2441*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count = 1; 2442*82527734SSukumar Swaminathan } 2443291a2b48SSukumar Swaminathan 2444*82527734SSukumar Swaminathan break; 2445291a2b48SSukumar Swaminathan 2446*82527734SSukumar Swaminathan case FC_CT_RING: 2447291a2b48SSukumar Swaminathan 2448*82527734SSukumar Swaminathan /* CMD payload */ 2449*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrHigh = 2450*82527734SSukumar Swaminathan PADDR_HI(cp_cmd->dmac_laddress); 2451*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.addrLow = 2452*82527734SSukumar Swaminathan PADDR_LO(cp_cmd->dmac_laddress); 2453*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.bdeSize = pkt->pkt_cmdlen; 2454*82527734SSukumar Swaminathan iocb->un.genreq64.bdl.bdeFlags = 0; 2455291a2b48SSukumar Swaminathan 2456*82527734SSukumar Swaminathan if ((pkt->pkt_tran_type != FC_PKT_OUTBOUND) || 2457*82527734SSukumar Swaminathan (pkt->pkt_cmd_fhdr.type == EMLXS_MENLO_TYPE)) { 2458*82527734SSukumar Swaminathan /* RSP payload */ 2459*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.addrHigh = 2460*82527734SSukumar Swaminathan PADDR_HI(cp_resp->dmac_laddress); 2461*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.addrLow = 2462*82527734SSukumar Swaminathan PADDR_LO(cp_resp->dmac_laddress); 2463*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.tus.f.bdeSize = 2464*82527734SSukumar Swaminathan pkt->pkt_rsplen; 2465*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde1.tus.f.bdeFlags = 2466*82527734SSukumar Swaminathan BUFF_USE_RCV; 2467*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count = 1; 2468*82527734SSukumar Swaminathan } 2469291a2b48SSukumar Swaminathan 2470*82527734SSukumar Swaminathan break; 2471291a2b48SSukumar Swaminathan } 2472291a2b48SSukumar Swaminathan 2473*82527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 2474*82527734SSukumar Swaminathan iocb->ULPLE = 0; 2475291a2b48SSukumar Swaminathan 2476*82527734SSukumar Swaminathan return (0); 2477291a2b48SSukumar Swaminathan 2478*82527734SSukumar Swaminathan } /* emlxs_sli3_bde_setup */ 2479291a2b48SSukumar Swaminathan 2480291a2b48SSukumar Swaminathan 2481*82527734SSukumar Swaminathan /* Only used for FCP Data xfers */ 2482*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 2483*82527734SSukumar Swaminathan /*ARGSUSED*/ 2484*82527734SSukumar Swaminathan static uint32_t 2485*82527734SSukumar Swaminathan emlxs_sli2_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2486*82527734SSukumar Swaminathan { 2487*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 2488*82527734SSukumar Swaminathan scsi_task_t *fct_task; 2489*82527734SSukumar Swaminathan MATCHMAP *bmp; 2490*82527734SSukumar Swaminathan ULP_BDE64 *bpl; 2491*82527734SSukumar Swaminathan uint64_t bp; 2492*82527734SSukumar Swaminathan uint8_t bdeFlags; 2493*82527734SSukumar Swaminathan IOCB *iocb; 2494*82527734SSukumar Swaminathan uint32_t resid; 2495*82527734SSukumar Swaminathan uint32_t count; 2496*82527734SSukumar Swaminathan uint32_t size; 2497*82527734SSukumar Swaminathan uint32_t sgllen; 2498*82527734SSukumar Swaminathan struct stmf_sglist_ent *sgl; 2499*82527734SSukumar Swaminathan emlxs_fct_dmem_bctl_t *bctl; 2500291a2b48SSukumar Swaminathan 2501291a2b48SSukumar Swaminathan 2502*82527734SSukumar Swaminathan iocb = (IOCB *)&sbp->iocbq; 2503*82527734SSukumar Swaminathan sbp->bmp = NULL; 2504291a2b48SSukumar Swaminathan 2505*82527734SSukumar Swaminathan if (!sbp->fct_buf) { 2506*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = 0; 2507*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = 0; 2508*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = 0; 2509*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = 0; 2510*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 2511*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 0; 2512*82527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 2513*82527734SSukumar Swaminathan iocb->ULPLE = 1; 2514*82527734SSukumar Swaminathan return (0); 2515291a2b48SSukumar Swaminathan } 2516*82527734SSukumar Swaminathan #ifdef EMLXS_SPARC 2517*82527734SSukumar Swaminathan /* Use FCP MEM_BPL table to get BPL buffer */ 2518*82527734SSukumar Swaminathan bmp = hba->sli.sli3.fcp_bpl_table[sbp->iotag]; 2519*82527734SSukumar Swaminathan #else 2520*82527734SSukumar Swaminathan /* Use MEM_BPL pool to get BPL buffer */ 2521*82527734SSukumar Swaminathan bmp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BPL, 0); 2522*82527734SSukumar Swaminathan #endif /* EMLXS_SPARC */ 2523291a2b48SSukumar Swaminathan 2524*82527734SSukumar Swaminathan if (!bmp) { 2525*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 2526*82527734SSukumar Swaminathan "emlxs_fct_sli2_bde_setup: Unable to BPL buffer. iotag=%x", 2527*82527734SSukumar Swaminathan sbp->iotag); 2528291a2b48SSukumar Swaminathan 2529*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = 0; 2530*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = 0; 2531*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = 0; 2532*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = 0; 2533*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 2534*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 0; 2535*82527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 2536*82527734SSukumar Swaminathan iocb->ULPLE = 1; 2537*82527734SSukumar Swaminathan return (1); 2538*82527734SSukumar Swaminathan } 2539291a2b48SSukumar Swaminathan 2540*82527734SSukumar Swaminathan bpl = (ULP_BDE64 *)bmp->virt; 2541*82527734SSukumar Swaminathan bp = bmp->phys; 2542291a2b48SSukumar Swaminathan 2543291a2b48SSukumar Swaminathan 2544*82527734SSukumar Swaminathan fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific; 2545291a2b48SSukumar Swaminathan 2546*82527734SSukumar Swaminathan size = sbp->fct_buf->db_data_size; 2547*82527734SSukumar Swaminathan count = sbp->fct_buf->db_sglist_length; 2548*82527734SSukumar Swaminathan bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private; 2549291a2b48SSukumar Swaminathan 2550*82527734SSukumar Swaminathan bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0; 2551*82527734SSukumar Swaminathan sgl = sbp->fct_buf->db_sglist; 2552*82527734SSukumar Swaminathan resid = size; 2553291a2b48SSukumar Swaminathan 2554*82527734SSukumar Swaminathan /* Init the buffer list */ 2555*82527734SSukumar Swaminathan for (sgllen = 0; sgllen < count && resid > 0; sgllen++) { 2556*82527734SSukumar Swaminathan bpl->addrHigh = 2557*82527734SSukumar Swaminathan BE_SWAP32(PADDR_HI(bctl->bctl_dev_addr)); 2558*82527734SSukumar Swaminathan bpl->addrLow = 2559*82527734SSukumar Swaminathan BE_SWAP32(PADDR_LO(bctl->bctl_dev_addr)); 2560*82527734SSukumar Swaminathan bpl->tus.f.bdeSize = MIN(resid, sgl->seg_length); 2561*82527734SSukumar Swaminathan bpl->tus.f.bdeFlags = bdeFlags; 2562*82527734SSukumar Swaminathan bpl->tus.w = BE_SWAP32(bpl->tus.w); 2563*82527734SSukumar Swaminathan bpl++; 2564291a2b48SSukumar Swaminathan 2565*82527734SSukumar Swaminathan resid -= MIN(resid, sgl->seg_length); 2566*82527734SSukumar Swaminathan sgl++; 2567*82527734SSukumar Swaminathan } 2568291a2b48SSukumar Swaminathan 2569*82527734SSukumar Swaminathan /* Init the IOCB */ 2570*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bp); 2571*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bp); 2572*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = sgllen * sizeof (ULP_BDE64); 2573*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = BUFF_TYPE_BDL; 2574291a2b48SSukumar Swaminathan 2575*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 2576*82527734SSukumar Swaminathan (fct_task->task_flags & TF_WRITE_DATA) ? size : 0; 2577*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 2578291a2b48SSukumar Swaminathan 2579*82527734SSukumar Swaminathan iocb->ULPBDECOUNT = 1; 2580*82527734SSukumar Swaminathan iocb->ULPLE = 1; 2581*82527734SSukumar Swaminathan sbp->bmp = bmp; 2582291a2b48SSukumar Swaminathan 2583*82527734SSukumar Swaminathan return (0); 2584291a2b48SSukumar Swaminathan 2585*82527734SSukumar Swaminathan } /* emlxs_sli2_fct_bde_setup */ 2586*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2587291a2b48SSukumar Swaminathan 2588291a2b48SSukumar Swaminathan 2589*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 2590*82527734SSukumar Swaminathan /*ARGSUSED*/ 2591*82527734SSukumar Swaminathan static uint32_t 2592*82527734SSukumar Swaminathan emlxs_sli3_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 2593*82527734SSukumar Swaminathan { 2594*82527734SSukumar Swaminathan scsi_task_t *fct_task; 2595*82527734SSukumar Swaminathan ULP_BDE64 *bde; 2596*82527734SSukumar Swaminathan IOCB *iocb; 2597*82527734SSukumar Swaminathan uint32_t size; 2598*82527734SSukumar Swaminathan uint32_t count; 2599*82527734SSukumar Swaminathan uint32_t sgllen; 2600*82527734SSukumar Swaminathan int32_t resid; 2601*82527734SSukumar Swaminathan struct stmf_sglist_ent *sgl; 2602*82527734SSukumar Swaminathan uint32_t bdeFlags; 2603*82527734SSukumar Swaminathan emlxs_fct_dmem_bctl_t *bctl; 2604291a2b48SSukumar Swaminathan 2605*82527734SSukumar Swaminathan iocb = (IOCB *)&sbp->iocbq; 2606291a2b48SSukumar Swaminathan 2607*82527734SSukumar Swaminathan if (!sbp->fct_buf) { 2608*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = 0; 2609*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = 0; 2610*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = 0; 2611*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = 0; 2612*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 2613*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 0; 2614*82527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 2615*82527734SSukumar Swaminathan iocb->ULPLE = 0; 2616*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count = 0; 2617*82527734SSukumar Swaminathan return (0); 2618291a2b48SSukumar Swaminathan } 2619291a2b48SSukumar Swaminathan 2620*82527734SSukumar Swaminathan fct_task = (scsi_task_t *)sbp->fct_cmd->cmd_specific; 2621291a2b48SSukumar Swaminathan 2622*82527734SSukumar Swaminathan size = sbp->fct_buf->db_data_size; 2623*82527734SSukumar Swaminathan count = sbp->fct_buf->db_sglist_length; 2624*82527734SSukumar Swaminathan bctl = (emlxs_fct_dmem_bctl_t *)sbp->fct_buf->db_port_private; 2625291a2b48SSukumar Swaminathan 2626*82527734SSukumar Swaminathan bdeFlags = (fct_task->task_flags & TF_WRITE_DATA) ? BUFF_USE_RCV : 0; 2627*82527734SSukumar Swaminathan sgl = sbp->fct_buf->db_sglist; 2628*82527734SSukumar Swaminathan resid = size; 2629291a2b48SSukumar Swaminathan 2630*82527734SSukumar Swaminathan /* Init first BDE */ 2631*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(bctl->bctl_dev_addr); 2632*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.addrLow = PADDR_LO(bctl->bctl_dev_addr); 2633*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeSize = MIN(resid, sgl->seg_length); 2634*82527734SSukumar Swaminathan iocb->un.fcpt64.bdl.bdeFlags = bdeFlags; 2635*82527734SSukumar Swaminathan resid -= MIN(resid, sgl->seg_length); 2636*82527734SSukumar Swaminathan sgl++; 2637291a2b48SSukumar Swaminathan 2638*82527734SSukumar Swaminathan /* Init remaining BDE's */ 2639*82527734SSukumar Swaminathan bde = (ULP_BDE64 *)&iocb->unsli3.ext_iocb.ebde1; 2640*82527734SSukumar Swaminathan for (sgllen = 1; sgllen < count && resid > 0; sgllen++) { 2641*82527734SSukumar Swaminathan bde->addrHigh = PADDR_HI(bctl->bctl_dev_addr); 2642*82527734SSukumar Swaminathan bde->addrLow = PADDR_LO(bctl->bctl_dev_addr); 2643*82527734SSukumar Swaminathan bde->tus.f.bdeSize = MIN(resid, sgl->seg_length); 2644*82527734SSukumar Swaminathan bde->tus.f.bdeFlags = bdeFlags; 2645*82527734SSukumar Swaminathan bde++; 2646291a2b48SSukumar Swaminathan 2647*82527734SSukumar Swaminathan resid -= MIN(resid, sgl->seg_length); 2648*82527734SSukumar Swaminathan sgl++; 2649291a2b48SSukumar Swaminathan } 2650291a2b48SSukumar Swaminathan 2651*82527734SSukumar Swaminathan iocb->unsli3.ext_iocb.ebde_count = sgllen - 1; 2652*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Length = 2653*82527734SSukumar Swaminathan (fct_task->task_flags & TF_WRITE_DATA) ? size : 0; 2654*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = 0; 2655291a2b48SSukumar Swaminathan 2656*82527734SSukumar Swaminathan iocb->ULPBDECOUNT = 0; 2657*82527734SSukumar Swaminathan iocb->ULPLE = 0; 2658291a2b48SSukumar Swaminathan 2659*82527734SSukumar Swaminathan return (0); 2660291a2b48SSukumar Swaminathan 2661*82527734SSukumar Swaminathan } /* emlxs_sli3_fct_bde_setup */ 2662*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2663291a2b48SSukumar Swaminathan 2664291a2b48SSukumar Swaminathan 2665*82527734SSukumar Swaminathan static void 2666*82527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2667291a2b48SSukumar Swaminathan { 2668*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 2669*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2670*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2671*82527734SSukumar Swaminathan PGP *pgp; 2672*82527734SSukumar Swaminathan emlxs_buf_t *sbp; 2673*82527734SSukumar Swaminathan SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 2674291a2b48SSukumar Swaminathan RING *rp; 2675*82527734SSukumar Swaminathan uint32_t nextIdx; 2676*82527734SSukumar Swaminathan uint32_t status; 2677*82527734SSukumar Swaminathan void *ioa2; 2678*82527734SSukumar Swaminathan off_t offset; 2679*82527734SSukumar Swaminathan uint32_t count = 0; 2680*82527734SSukumar Swaminathan uint32_t flag; 2681*82527734SSukumar Swaminathan uint32_t channelno; 2682*82527734SSukumar Swaminathan int32_t throttle; 2683291a2b48SSukumar Swaminathan 2684*82527734SSukumar Swaminathan channelno = cp->channelno; 2685*82527734SSukumar Swaminathan rp = (RING *)cp->iopath; 2686291a2b48SSukumar Swaminathan 2687*82527734SSukumar Swaminathan throttle = 0; 2688291a2b48SSukumar Swaminathan 2689*82527734SSukumar Swaminathan /* Check if FCP ring and adapter is not ready */ 2690*82527734SSukumar Swaminathan /* We may use any ring for FCP_CMD */ 2691*82527734SSukumar Swaminathan if (iocbq && (iocbq->flag & IOCB_FCP_CMD) && (hba->state != FC_READY)) { 2692*82527734SSukumar Swaminathan if (!(iocbq->flag & IOCB_SPECIAL) || !iocbq->port || 2693*82527734SSukumar Swaminathan !(((emlxs_port_t *)iocbq->port)->tgt_mode)) { 2694*82527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2695*82527734SSukumar Swaminathan return; 2696*82527734SSukumar Swaminathan } 2697291a2b48SSukumar Swaminathan } 2698291a2b48SSukumar Swaminathan 2699*82527734SSukumar Swaminathan /* Attempt to acquire CMD_RING lock */ 2700*82527734SSukumar Swaminathan if (mutex_tryenter(&EMLXS_CMD_RING_LOCK(channelno)) == 0) { 2701*82527734SSukumar Swaminathan /* Queue it for later */ 2702*82527734SSukumar Swaminathan if (iocbq) { 2703*82527734SSukumar Swaminathan if ((hba->io_count - 2704*82527734SSukumar Swaminathan hba->channel_tx_count) > 10) { 2705*82527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2706*82527734SSukumar Swaminathan return; 2707*82527734SSukumar Swaminathan } else { 2708291a2b48SSukumar Swaminathan 2709*82527734SSukumar Swaminathan /* 2710*82527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, 2711*82527734SSukumar Swaminathan * &emlxs_ring_watchdog_msg, 2712*82527734SSukumar Swaminathan * "%s host=%d port=%d cnt=%d,%d RACE 2713*82527734SSukumar Swaminathan * CONDITION3 DETECTED.", 2714*82527734SSukumar Swaminathan * emlxs_ring_xlate(channelno), 2715*82527734SSukumar Swaminathan * rp->fc_cmdidx, rp->fc_port_cmdidx, 2716*82527734SSukumar Swaminathan * hba->channel_tx_count, 2717*82527734SSukumar Swaminathan * hba->io_count); 2718*82527734SSukumar Swaminathan */ 2719*82527734SSukumar Swaminathan mutex_enter(&EMLXS_CMD_RING_LOCK(channelno)); 2720*82527734SSukumar Swaminathan } 2721*82527734SSukumar Swaminathan } else { 2722*82527734SSukumar Swaminathan return; 2723*82527734SSukumar Swaminathan } 2724291a2b48SSukumar Swaminathan } 2725*82527734SSukumar Swaminathan /* CMD_RING_LOCK acquired */ 2726291a2b48SSukumar Swaminathan 2727*82527734SSukumar Swaminathan /* Throttle check only applies to non special iocb */ 2728*82527734SSukumar Swaminathan if (iocbq && (!(iocbq->flag & IOCB_SPECIAL))) { 2729*82527734SSukumar Swaminathan /* Check if HBA is full */ 2730*82527734SSukumar Swaminathan throttle = hba->io_throttle - hba->io_active; 2731*82527734SSukumar Swaminathan if (throttle <= 0) { 2732*82527734SSukumar Swaminathan /* Hitting adapter throttle limit */ 2733*82527734SSukumar Swaminathan /* Queue it for later */ 2734*82527734SSukumar Swaminathan if (iocbq) { 2735*82527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2736291a2b48SSukumar Swaminathan } 2737*82527734SSukumar Swaminathan 2738*82527734SSukumar Swaminathan goto busy; 2739291a2b48SSukumar Swaminathan } 2740291a2b48SSukumar Swaminathan } 2741291a2b48SSukumar Swaminathan 2742*82527734SSukumar Swaminathan /* Read adapter's get index */ 2743*82527734SSukumar Swaminathan pgp = (PGP *) 2744*82527734SSukumar Swaminathan &((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[channelno]; 2745*82527734SSukumar Swaminathan offset = 2746*82527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) - 2747*82527734SSukumar Swaminathan (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 2748*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 2749*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 2750*82527734SSukumar Swaminathan rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2751291a2b48SSukumar Swaminathan 2752*82527734SSukumar Swaminathan /* Calculate the next put index */ 2753*82527734SSukumar Swaminathan nextIdx = 2754*82527734SSukumar Swaminathan (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 2755291a2b48SSukumar Swaminathan 2756*82527734SSukumar Swaminathan /* Check if ring is full */ 2757*82527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 2758*82527734SSukumar Swaminathan /* Try one more time */ 2759*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 2760*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 2761*82527734SSukumar Swaminathan rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2762291a2b48SSukumar Swaminathan 2763*82527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 2764*82527734SSukumar Swaminathan /* Queue it for later */ 2765*82527734SSukumar Swaminathan if (iocbq) { 2766*82527734SSukumar Swaminathan emlxs_tx_put(iocbq, 1); 2767*82527734SSukumar Swaminathan } 2768291a2b48SSukumar Swaminathan 2769*82527734SSukumar Swaminathan goto busy; 2770*82527734SSukumar Swaminathan } 2771291a2b48SSukumar Swaminathan } 2772291a2b48SSukumar Swaminathan 2773*82527734SSukumar Swaminathan /* 2774*82527734SSukumar Swaminathan * We have a command ring slot available 2775*82527734SSukumar Swaminathan * Make sure we have an iocb to send 2776*82527734SSukumar Swaminathan */ 2777*82527734SSukumar Swaminathan if (iocbq) { 2778*82527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 2779291a2b48SSukumar Swaminathan 2780*82527734SSukumar Swaminathan /* Check if the ring already has iocb's waiting */ 2781*82527734SSukumar Swaminathan if (cp->nodeq.q_first != NULL) { 2782*82527734SSukumar Swaminathan /* Put the current iocbq on the tx queue */ 2783*82527734SSukumar Swaminathan emlxs_tx_put(iocbq, 0); 2784291a2b48SSukumar Swaminathan 2785*82527734SSukumar Swaminathan /* 2786*82527734SSukumar Swaminathan * Attempt to replace it with the next iocbq 2787*82527734SSukumar Swaminathan * in the tx queue 2788*82527734SSukumar Swaminathan */ 2789*82527734SSukumar Swaminathan iocbq = emlxs_tx_get(cp, 0); 2790*82527734SSukumar Swaminathan } 2791291a2b48SSukumar Swaminathan 2792*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 2793291a2b48SSukumar Swaminathan } else { 2794*82527734SSukumar Swaminathan /* Try to get the next iocb on the tx queue */ 2795*82527734SSukumar Swaminathan iocbq = emlxs_tx_get(cp, 1); 2796291a2b48SSukumar Swaminathan } 2797291a2b48SSukumar Swaminathan 2798*82527734SSukumar Swaminathan sendit: 2799*82527734SSukumar Swaminathan count = 0; 2800291a2b48SSukumar Swaminathan 2801*82527734SSukumar Swaminathan /* Process each iocbq */ 2802*82527734SSukumar Swaminathan while (iocbq) { 2803291a2b48SSukumar Swaminathan 2804*82527734SSukumar Swaminathan sbp = iocbq->sbp; 2805*82527734SSukumar Swaminathan if (sbp && (sbp->pkt_flags & PACKET_DELAY_REQUIRED)) { 2806*82527734SSukumar Swaminathan /* 2807*82527734SSukumar Swaminathan * Update adapter if needed, since we are about to 2808*82527734SSukumar Swaminathan * delay here 2809*82527734SSukumar Swaminathan */ 2810*82527734SSukumar Swaminathan if (count) { 2811*82527734SSukumar Swaminathan count = 0; 2812291a2b48SSukumar Swaminathan 2813*82527734SSukumar Swaminathan /* Update the adapter's cmd put index */ 2814*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 2815*82527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channelno]. 2816*82527734SSukumar Swaminathan cmdPutInx = 2817*82527734SSukumar Swaminathan BE_SWAP32(rp->fc_cmdidx); 2818291a2b48SSukumar Swaminathan 2819*82527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 2820*82527734SSukumar Swaminathan offset = (off_t) 2821*82527734SSukumar Swaminathan ((uint64_t) 2822*82527734SSukumar Swaminathan ((unsigned long)&(slim2p->mbx.us. 2823*82527734SSukumar Swaminathan s2.host[channelno].cmdPutInx)) - 2824*82527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 2825*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2. 2826*82527734SSukumar Swaminathan dma_handle, offset, 4, 2827*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 2828*82527734SSukumar Swaminathan } else { 2829*82527734SSukumar Swaminathan ioa2 = (void *) 2830*82527734SSukumar Swaminathan ((char *)hba->sli.sli3.slim_addr + 2831*82527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + 2832*82527734SSukumar Swaminathan ((channelno * 2) * 2833*82527734SSukumar Swaminathan sizeof (uint32_t))); 2834*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, 2835*82527734SSukumar Swaminathan (volatile uint32_t *)ioa2, 2836*82527734SSukumar Swaminathan rp->fc_cmdidx); 2837*82527734SSukumar Swaminathan } 2838291a2b48SSukumar Swaminathan 2839*82527734SSukumar Swaminathan status = (CA_R0ATT << (channelno * 4)); 2840*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), 2841*82527734SSukumar Swaminathan (volatile uint32_t)status); 2842291a2b48SSukumar Swaminathan 2843*82527734SSukumar Swaminathan } 2844*82527734SSukumar Swaminathan /* Perform delay */ 2845*82527734SSukumar Swaminathan if ((channelno == FC_ELS_RING) && 2846*82527734SSukumar Swaminathan !(iocbq->flag & IOCB_FCP_CMD)) { 2847*82527734SSukumar Swaminathan drv_usecwait(100000); 2848*82527734SSukumar Swaminathan } else { 2849*82527734SSukumar Swaminathan drv_usecwait(20000); 2850*82527734SSukumar Swaminathan } 2851*82527734SSukumar Swaminathan } 2852*82527734SSukumar Swaminathan 2853*82527734SSukumar Swaminathan /* 2854*82527734SSukumar Swaminathan * At this point, we have a command ring slot available 2855*82527734SSukumar Swaminathan * and an iocb to send 2856*82527734SSukumar Swaminathan */ 2857*82527734SSukumar Swaminathan flag = iocbq->flag; 2858291a2b48SSukumar Swaminathan 2859*82527734SSukumar Swaminathan /* Send the iocb */ 2860*82527734SSukumar Swaminathan emlxs_sli3_issue_iocb(hba, rp, iocbq); 2861*82527734SSukumar Swaminathan /* 2862*82527734SSukumar Swaminathan * After this, the sbp / iocb should not be 2863*82527734SSukumar Swaminathan * accessed in the xmit path. 2864*82527734SSukumar Swaminathan */ 2865291a2b48SSukumar Swaminathan 2866*82527734SSukumar Swaminathan count++; 2867*82527734SSukumar Swaminathan if (iocbq && (!(flag & IOCB_SPECIAL))) { 2868*82527734SSukumar Swaminathan /* Check if HBA is full */ 2869*82527734SSukumar Swaminathan throttle = hba->io_throttle - hba->io_active; 2870*82527734SSukumar Swaminathan if (throttle <= 0) { 2871*82527734SSukumar Swaminathan goto busy; 2872*82527734SSukumar Swaminathan } 2873*82527734SSukumar Swaminathan } 2874291a2b48SSukumar Swaminathan 2875*82527734SSukumar Swaminathan /* Calculate the next put index */ 2876*82527734SSukumar Swaminathan nextIdx = 2877*82527734SSukumar Swaminathan (rp->fc_cmdidx + 1 >= 2878*82527734SSukumar Swaminathan rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 2879291a2b48SSukumar Swaminathan 2880*82527734SSukumar Swaminathan /* Check if ring is full */ 2881*82527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 2882*82527734SSukumar Swaminathan /* Try one more time */ 2883*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 2884*82527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORKERNEL); 2885*82527734SSukumar Swaminathan rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 2886291a2b48SSukumar Swaminathan 2887*82527734SSukumar Swaminathan if (nextIdx == rp->fc_port_cmdidx) { 2888*82527734SSukumar Swaminathan goto busy; 2889*82527734SSukumar Swaminathan } 2890*82527734SSukumar Swaminathan } 2891291a2b48SSukumar Swaminathan 2892*82527734SSukumar Swaminathan /* Get the next iocb from the tx queue if there is one */ 2893*82527734SSukumar Swaminathan iocbq = emlxs_tx_get(cp, 1); 2894291a2b48SSukumar Swaminathan } 2895291a2b48SSukumar Swaminathan 2896*82527734SSukumar Swaminathan if (count) { 2897*82527734SSukumar Swaminathan /* Update the adapter's cmd put index */ 2898*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 2899*82527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channelno]. 2900*82527734SSukumar Swaminathan cmdPutInx = BE_SWAP32(rp->fc_cmdidx); 2901291a2b48SSukumar Swaminathan 2902*82527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 2903*82527734SSukumar Swaminathan offset = (off_t) 2904*82527734SSukumar Swaminathan ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 2905*82527734SSukumar Swaminathan host[channelno].cmdPutInx)) - 2906*82527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 2907*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 2908*82527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORDEV); 2909*82527734SSukumar Swaminathan } else { 2910*82527734SSukumar Swaminathan ioa2 = 2911*82527734SSukumar Swaminathan (void *)((char *)hba->sli.sli3.slim_addr + 2912*82527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + 2913*82527734SSukumar Swaminathan ((channelno * 2) * sizeof (uint32_t))); 2914*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 2915*82527734SSukumar Swaminathan rp->fc_cmdidx); 2916*82527734SSukumar Swaminathan } 2917291a2b48SSukumar Swaminathan 2918*82527734SSukumar Swaminathan status = (CA_R0ATT << (channelno * 4)); 2919*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), 2920*82527734SSukumar Swaminathan (volatile uint32_t)status); 2921291a2b48SSukumar Swaminathan 2922*82527734SSukumar Swaminathan /* Check tx queue one more time before releasing */ 2923*82527734SSukumar Swaminathan if ((iocbq = emlxs_tx_get(cp, 1))) { 2924*82527734SSukumar Swaminathan /* 2925*82527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_watchdog_msg, 2926*82527734SSukumar Swaminathan * "%s host=%d port=%d RACE CONDITION1 2927*82527734SSukumar Swaminathan * DETECTED.", emlxs_ring_xlate(channelno), 2928*82527734SSukumar Swaminathan * rp->fc_cmdidx, rp->fc_port_cmdidx); 2929*82527734SSukumar Swaminathan */ 2930*82527734SSukumar Swaminathan goto sendit; 2931*82527734SSukumar Swaminathan } 2932291a2b48SSukumar Swaminathan } 2933291a2b48SSukumar Swaminathan 2934*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 2935*82527734SSukumar Swaminathan /* Access handle validation */ 2936*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 2937*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 2938*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2939291a2b48SSukumar Swaminathan 2940*82527734SSukumar Swaminathan mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); 2941291a2b48SSukumar Swaminathan 2942*82527734SSukumar Swaminathan return; 2943291a2b48SSukumar Swaminathan 2944*82527734SSukumar Swaminathan busy: 2945291a2b48SSukumar Swaminathan 2946291a2b48SSukumar Swaminathan /* 2947*82527734SSukumar Swaminathan * Set ring to SET R0CE_REQ in Chip Att register. 2948*82527734SSukumar Swaminathan * Chip will tell us when an entry is freed. 2949291a2b48SSukumar Swaminathan */ 2950*82527734SSukumar Swaminathan if (count) { 2951*82527734SSukumar Swaminathan /* Update the adapter's cmd put index */ 2952*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 2953*82527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channelno].cmdPutInx = 2954*82527734SSukumar Swaminathan BE_SWAP32(rp->fc_cmdidx); 2955291a2b48SSukumar Swaminathan 2956*82527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 2957*82527734SSukumar Swaminathan offset = (off_t) 2958*82527734SSukumar Swaminathan ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 2959*82527734SSukumar Swaminathan host[channelno].cmdPutInx)) - 2960*82527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 2961*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 2962*82527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORDEV); 2963*82527734SSukumar Swaminathan } else { 2964*82527734SSukumar Swaminathan ioa2 = 2965*82527734SSukumar Swaminathan (void *)((char *)hba->sli.sli3.slim_addr + 2966*82527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + 2967*82527734SSukumar Swaminathan ((channelno * 2) * sizeof (uint32_t))); 2968*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 2969*82527734SSukumar Swaminathan rp->fc_cmdidx); 2970291a2b48SSukumar Swaminathan } 2971*82527734SSukumar Swaminathan } 2972291a2b48SSukumar Swaminathan 2973*82527734SSukumar Swaminathan status = ((CA_R0ATT | CA_R0CE_REQ) << (channelno * 4)); 2974*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), (volatile uint32_t)status); 2975*82527734SSukumar Swaminathan 2976*82527734SSukumar Swaminathan if (throttle <= 0) { 2977*82527734SSukumar Swaminathan HBASTATS.IocbThrottled++; 2978*82527734SSukumar Swaminathan } else { 2979*82527734SSukumar Swaminathan HBASTATS.IocbRingFull[channelno]++; 2980291a2b48SSukumar Swaminathan } 2981291a2b48SSukumar Swaminathan 2982*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 2983*82527734SSukumar Swaminathan /* Access handle validation */ 2984*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 2985*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 2986*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 2987291a2b48SSukumar Swaminathan 2988*82527734SSukumar Swaminathan mutex_exit(&EMLXS_CMD_RING_LOCK(channelno)); 2989291a2b48SSukumar Swaminathan 2990291a2b48SSukumar Swaminathan return; 2991291a2b48SSukumar Swaminathan 2992*82527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb_cmd() */ 2993291a2b48SSukumar Swaminathan 2994291a2b48SSukumar Swaminathan 2995*82527734SSukumar Swaminathan /* MBX_NOWAIT - returns MBX_BUSY or MBX_SUCCESS or MBX_HARDWARE_ERROR */ 2996*82527734SSukumar Swaminathan /* MBX_WAIT - returns MBX_TIMEOUT or mailbox_status */ 2997*82527734SSukumar Swaminathan /* MBX_SLEEP - returns MBX_TIMEOUT or mailbox_status */ 2998*82527734SSukumar Swaminathan /* MBX_POLL - returns MBX_TIMEOUT or mailbox_status */ 2999291a2b48SSukumar Swaminathan 3000*82527734SSukumar Swaminathan static uint32_t 3001*82527734SSukumar Swaminathan emlxs_sli3_issue_mbox_cmd(emlxs_hba_t *hba, MAILBOXQ *mbq, int32_t flag, 3002*82527734SSukumar Swaminathan uint32_t tmo) 3003291a2b48SSukumar Swaminathan { 3004*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 3005*82527734SSukumar Swaminathan SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 3006*82527734SSukumar Swaminathan MAILBOX *mbox; 3007*82527734SSukumar Swaminathan MAILBOX *mb; 3008*82527734SSukumar Swaminathan volatile uint32_t word0; 3009*82527734SSukumar Swaminathan volatile uint32_t ldata; 3010*82527734SSukumar Swaminathan uint32_t ha_copy; 3011*82527734SSukumar Swaminathan off_t offset; 3012*82527734SSukumar Swaminathan MATCHMAP *mbox_bp; 3013*82527734SSukumar Swaminathan uint32_t tmo_local; 3014*82527734SSukumar Swaminathan MAILBOX *swpmb; 3015291a2b48SSukumar Swaminathan 3016*82527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 3017*82527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 3018291a2b48SSukumar Swaminathan 3019*82527734SSukumar Swaminathan mb->mbxStatus = MBX_SUCCESS; 3020291a2b48SSukumar Swaminathan 3021*82527734SSukumar Swaminathan /* Check for minimum timeouts */ 3022*82527734SSukumar Swaminathan switch (mb->mbxCommand) { 3023*82527734SSukumar Swaminathan /* Mailbox commands that erase/write flash */ 3024*82527734SSukumar Swaminathan case MBX_DOWN_LOAD: 3025*82527734SSukumar Swaminathan case MBX_UPDATE_CFG: 3026*82527734SSukumar Swaminathan case MBX_LOAD_AREA: 3027*82527734SSukumar Swaminathan case MBX_LOAD_EXP_ROM: 3028*82527734SSukumar Swaminathan case MBX_WRITE_NV: 3029*82527734SSukumar Swaminathan case MBX_FLASH_WR_ULA: 3030*82527734SSukumar Swaminathan case MBX_DEL_LD_ENTRY: 3031*82527734SSukumar Swaminathan case MBX_LOAD_SM: 3032*82527734SSukumar Swaminathan if (tmo < 300) { 3033*82527734SSukumar Swaminathan tmo = 300; 3034291a2b48SSukumar Swaminathan } 3035*82527734SSukumar Swaminathan break; 3036291a2b48SSukumar Swaminathan 3037*82527734SSukumar Swaminathan default: 3038*82527734SSukumar Swaminathan if (tmo < 30) { 3039*82527734SSukumar Swaminathan tmo = 30; 3040*82527734SSukumar Swaminathan } 3041*82527734SSukumar Swaminathan break; 3042*82527734SSukumar Swaminathan } 3043291a2b48SSukumar Swaminathan 3044*82527734SSukumar Swaminathan /* Convert tmo seconds to 10 millisecond tics */ 3045*82527734SSukumar Swaminathan tmo_local = tmo * 100; 3046291a2b48SSukumar Swaminathan 3047*82527734SSukumar Swaminathan /* Adjust wait flag */ 3048*82527734SSukumar Swaminathan if (flag != MBX_NOWAIT) { 3049*82527734SSukumar Swaminathan /* If interrupt is enabled, use sleep, otherwise poll */ 3050*82527734SSukumar Swaminathan if (hba->sli.sli3.hc_copy & HC_MBINT_ENA) { 3051*82527734SSukumar Swaminathan flag = MBX_SLEEP; 3052291a2b48SSukumar Swaminathan } else { 3053*82527734SSukumar Swaminathan flag = MBX_POLL; 3054291a2b48SSukumar Swaminathan } 3055*82527734SSukumar Swaminathan } 3056291a2b48SSukumar Swaminathan 3057*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 3058291a2b48SSukumar Swaminathan 3059*82527734SSukumar Swaminathan /* Check for hardware error */ 3060*82527734SSukumar Swaminathan if (hba->flag & FC_HARDWARE_ERROR) { 3061*82527734SSukumar Swaminathan mb->mbxStatus = (hba->flag & FC_OVERTEMP_EVENT) ? 3062*82527734SSukumar Swaminathan MBX_OVERTEMP_ERROR : MBX_HARDWARE_ERROR; 3063291a2b48SSukumar Swaminathan 3064*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3065291a2b48SSukumar Swaminathan 3066*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3067*82527734SSukumar Swaminathan "Hardware error reported. %s failed. status=%x mb=%p", 3068*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb->mbxStatus, mb); 3069291a2b48SSukumar Swaminathan 3070*82527734SSukumar Swaminathan return (MBX_HARDWARE_ERROR); 3071291a2b48SSukumar Swaminathan } 3072291a2b48SSukumar Swaminathan 3073*82527734SSukumar Swaminathan if (hba->mbox_queue_flag) { 3074*82527734SSukumar Swaminathan /* If we are not polling, then queue it for later */ 3075*82527734SSukumar Swaminathan if (flag == MBX_NOWAIT) { 3076*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3077*82527734SSukumar Swaminathan "Busy. %s: mb=%p NoWait.", 3078*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3079291a2b48SSukumar Swaminathan 3080*82527734SSukumar Swaminathan emlxs_mb_put(hba, mbq); 3081291a2b48SSukumar Swaminathan 3082*82527734SSukumar Swaminathan HBASTATS.MboxBusy++; 3083291a2b48SSukumar Swaminathan 3084*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3085291a2b48SSukumar Swaminathan 3086*82527734SSukumar Swaminathan return (MBX_BUSY); 3087*82527734SSukumar Swaminathan } 3088291a2b48SSukumar Swaminathan 3089*82527734SSukumar Swaminathan while (hba->mbox_queue_flag) { 3090*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3091291a2b48SSukumar Swaminathan 3092*82527734SSukumar Swaminathan if (tmo_local-- == 0) { 3093*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3094*82527734SSukumar Swaminathan &emlxs_mbox_event_msg, 3095*82527734SSukumar Swaminathan "Timeout. %s: mb=%p tmo=%d Waiting.", 3096*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3097*82527734SSukumar Swaminathan tmo); 3098291a2b48SSukumar Swaminathan 3099*82527734SSukumar Swaminathan /* Non-lethalStatus mailbox timeout */ 3100*82527734SSukumar Swaminathan /* Does not indicate a hardware error */ 3101*82527734SSukumar Swaminathan mb->mbxStatus = MBX_TIMEOUT; 3102*82527734SSukumar Swaminathan return (MBX_TIMEOUT); 3103*82527734SSukumar Swaminathan } 3104291a2b48SSukumar Swaminathan 3105*82527734SSukumar Swaminathan DELAYMS(10); 3106*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 31074baa2c25SSukumar Swaminathan } 3108291a2b48SSukumar Swaminathan } 3109291a2b48SSukumar Swaminathan 3110*82527734SSukumar Swaminathan /* Initialize mailbox area */ 3111*82527734SSukumar Swaminathan emlxs_mb_init(hba, mbq, flag, tmo); 3112291a2b48SSukumar Swaminathan 3113*82527734SSukumar Swaminathan switch (flag) { 3114*82527734SSukumar Swaminathan case MBX_NOWAIT: 3115291a2b48SSukumar Swaminathan 3116*82527734SSukumar Swaminathan if (mb->mbxCommand != MBX_HEARTBEAT) { 3117*82527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 3118*82527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 3119*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3120*82527734SSukumar Swaminathan &emlxs_mbox_detail_msg, 3121*82527734SSukumar Swaminathan "Sending. %s: mb=%p NoWait.", 3122*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3123*82527734SSukumar Swaminathan } 3124*82527734SSukumar Swaminathan } 3125291a2b48SSukumar Swaminathan 3126*82527734SSukumar Swaminathan break; 3127291a2b48SSukumar Swaminathan 3128*82527734SSukumar Swaminathan case MBX_SLEEP: 3129*82527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 3130*82527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 3131*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3132*82527734SSukumar Swaminathan "Sending. %s: mb=%p Sleep.", 3133*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3134*82527734SSukumar Swaminathan } 3135291a2b48SSukumar Swaminathan 3136*82527734SSukumar Swaminathan break; 3137291a2b48SSukumar Swaminathan 3138*82527734SSukumar Swaminathan case MBX_POLL: 3139*82527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 3140*82527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 3141*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3142*82527734SSukumar Swaminathan "Sending. %s: mb=%p Polled.", 3143*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3144*82527734SSukumar Swaminathan } 3145*82527734SSukumar Swaminathan break; 3146*82527734SSukumar Swaminathan } 3147291a2b48SSukumar Swaminathan 3148*82527734SSukumar Swaminathan mb->mbxOwner = OWN_CHIP; 3149291a2b48SSukumar Swaminathan 3150*82527734SSukumar Swaminathan /* Clear the attention bit */ 3151*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT); 3152291a2b48SSukumar Swaminathan 3153*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 3154*82527734SSukumar Swaminathan /* First copy command data */ 3155*82527734SSukumar Swaminathan mbox = FC_SLIM2_MAILBOX(hba); 3156*82527734SSukumar Swaminathan offset = 3157*82527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)mbox) 3158*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)slim2p)); 3159291a2b48SSukumar Swaminathan 3160*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 3161*82527734SSukumar Swaminathan if (mbq->extbuf) { 3162*82527734SSukumar Swaminathan uint32_t *mbox_ext = 3163*82527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + 3164*82527734SSukumar Swaminathan MBOX_EXTENSION_OFFSET); 3165*82527734SSukumar Swaminathan off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 3166291a2b48SSukumar Swaminathan 3167*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbq->extbuf, 3168*82527734SSukumar Swaminathan (uint8_t *)mbox_ext, mbq->extsize); 3169291a2b48SSukumar Swaminathan 3170*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 3171*82527734SSukumar Swaminathan offset_ext, mbq->extsize, 3172*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 3173291a2b48SSukumar Swaminathan } 3174*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 3175291a2b48SSukumar Swaminathan 3176*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox, 3177*82527734SSukumar Swaminathan MAILBOX_CMD_BSIZE); 3178291a2b48SSukumar Swaminathan 3179*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 3180*82527734SSukumar Swaminathan MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV); 3181*82527734SSukumar Swaminathan } 3182*82527734SSukumar Swaminathan /* Check for config port command */ 3183*82527734SSukumar Swaminathan else if (mb->mbxCommand == MBX_CONFIG_PORT) { 3184*82527734SSukumar Swaminathan /* copy command data into host mbox for cmpl */ 3185*82527734SSukumar Swaminathan mbox = FC_SLIM2_MAILBOX(hba); 3186*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mbox) 3187*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)slim2p)); 3188291a2b48SSukumar Swaminathan 3189*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mb, (uint8_t *)mbox, 3190*82527734SSukumar Swaminathan MAILBOX_CMD_BSIZE); 3191291a2b48SSukumar Swaminathan 3192*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 3193*82527734SSukumar Swaminathan MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORDEV); 3194291a2b48SSukumar Swaminathan 3195*82527734SSukumar Swaminathan /* First copy command data */ 3196*82527734SSukumar Swaminathan mbox = FC_SLIM1_MAILBOX(hba); 3197*82527734SSukumar Swaminathan WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords, 3198*82527734SSukumar Swaminathan (MAILBOX_CMD_WSIZE - 1)); 3199291a2b48SSukumar Swaminathan 3200*82527734SSukumar Swaminathan /* copy over last word, with mbxOwner set */ 3201*82527734SSukumar Swaminathan ldata = *((volatile uint32_t *)mb); 3202*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata); 3203291a2b48SSukumar Swaminathan 3204*82527734SSukumar Swaminathan /* switch over to host mailbox */ 3205*82527734SSukumar Swaminathan hba->flag |= FC_SLIM2_MODE; 3206*82527734SSukumar Swaminathan } else { /* SLIM 1 */ 3207291a2b48SSukumar Swaminathan 3208*82527734SSukumar Swaminathan mbox = FC_SLIM1_MAILBOX(hba); 3209291a2b48SSukumar Swaminathan 3210*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 3211*82527734SSukumar Swaminathan if (mbq->extbuf) { 3212*82527734SSukumar Swaminathan uint32_t *mbox_ext = 3213*82527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + 3214*82527734SSukumar Swaminathan MBOX_EXTENSION_OFFSET); 3215*82527734SSukumar Swaminathan WRITE_SLIM_COPY(hba, (uint32_t *)mbq->extbuf, 3216*82527734SSukumar Swaminathan mbox_ext, (mbq->extsize / 4)); 3217*82527734SSukumar Swaminathan } 3218*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 3219291a2b48SSukumar Swaminathan 3220*82527734SSukumar Swaminathan /* First copy command data */ 3221*82527734SSukumar Swaminathan WRITE_SLIM_COPY(hba, &mb->un.varWords, &mbox->un.varWords, 3222*82527734SSukumar Swaminathan (MAILBOX_CMD_WSIZE - 1)); 3223291a2b48SSukumar Swaminathan 3224*82527734SSukumar Swaminathan /* copy over last word, with mbxOwner set */ 3225*82527734SSukumar Swaminathan ldata = *((volatile uint32_t *)mb); 3226*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mbox), ldata); 3227291a2b48SSukumar Swaminathan } 3228291a2b48SSukumar Swaminathan 3229*82527734SSukumar Swaminathan /* Interrupt board to do it right away */ 3230*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 3231291a2b48SSukumar Swaminathan 3232*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 3233291a2b48SSukumar Swaminathan 32344baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 32354baa2c25SSukumar Swaminathan /* Access handle validation */ 3236*82527734SSukumar Swaminathan if ((emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 3237*82527734SSukumar Swaminathan != DDI_FM_OK) || 3238*82527734SSukumar Swaminathan (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle) 32394baa2c25SSukumar Swaminathan != DDI_FM_OK)) { 32404baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 32414baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 3242*82527734SSukumar Swaminathan return (MBX_HARDWARE_ERROR); 32434baa2c25SSukumar Swaminathan } 32444baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 32454baa2c25SSukumar Swaminathan 3246*82527734SSukumar Swaminathan switch (flag) { 3247*82527734SSukumar Swaminathan case MBX_NOWAIT: 3248*82527734SSukumar Swaminathan return (MBX_SUCCESS); 3249291a2b48SSukumar Swaminathan 3250*82527734SSukumar Swaminathan case MBX_SLEEP: 32514baa2c25SSukumar Swaminathan 3252*82527734SSukumar Swaminathan /* Wait for completion */ 3253*82527734SSukumar Swaminathan /* The driver clock is timing the mailbox. */ 3254*82527734SSukumar Swaminathan /* emlxs_mb_fini() will be called externally. */ 3255291a2b48SSukumar Swaminathan 3256*82527734SSukumar Swaminathan mutex_enter(&EMLXS_MBOX_LOCK); 3257*82527734SSukumar Swaminathan while (!(mbq->flag & MBQ_COMPLETED)) { 3258*82527734SSukumar Swaminathan cv_wait(&EMLXS_MBOX_CV, &EMLXS_MBOX_LOCK); 3259*82527734SSukumar Swaminathan } 3260*82527734SSukumar Swaminathan mutex_exit(&EMLXS_MBOX_LOCK); 3261291a2b48SSukumar Swaminathan 3262*82527734SSukumar Swaminathan if (mb->mbxStatus == MBX_TIMEOUT) { 3263*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg, 3264*82527734SSukumar Swaminathan "Timeout. %s: mb=%p tmo=%d. Sleep.", 3265*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo); 3266*82527734SSukumar Swaminathan } else { 3267*82527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 3268*82527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 3269*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3270*82527734SSukumar Swaminathan &emlxs_mbox_detail_msg, 3271*82527734SSukumar Swaminathan "Completed. %s: mb=%p status=%x Sleep.", 3272*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3273*82527734SSukumar Swaminathan mb->mbxStatus); 3274*82527734SSukumar Swaminathan } 3275*82527734SSukumar Swaminathan } 3276291a2b48SSukumar Swaminathan 3277*82527734SSukumar Swaminathan break; 3278291a2b48SSukumar Swaminathan 3279*82527734SSukumar Swaminathan case MBX_POLL: 3280291a2b48SSukumar Swaminathan 3281*82527734SSukumar Swaminathan /* Convert tmo seconds to 500 usec tics */ 3282*82527734SSukumar Swaminathan tmo_local = tmo * 2000; 3283291a2b48SSukumar Swaminathan 3284*82527734SSukumar Swaminathan if (hba->state >= FC_INIT_START) { 3285*82527734SSukumar Swaminathan ha_copy = 3286*82527734SSukumar Swaminathan READ_CSR_REG(hba, FC_HA_REG(hba)); 3287291a2b48SSukumar Swaminathan 3288*82527734SSukumar Swaminathan /* Wait for command to complete */ 3289*82527734SSukumar Swaminathan while (!(ha_copy & HA_MBATT) && 3290*82527734SSukumar Swaminathan !(mbq->flag & MBQ_COMPLETED)) { 3291*82527734SSukumar Swaminathan if (!hba->timer_id && (tmo_local-- == 0)) { 3292*82527734SSukumar Swaminathan /* self time */ 3293*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3294*82527734SSukumar Swaminathan &emlxs_mbox_timeout_msg, 3295*82527734SSukumar Swaminathan "%s: mb=%p Polled.", 3296*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb-> 3297*82527734SSukumar Swaminathan mbxCommand), mb); 3298291a2b48SSukumar Swaminathan 3299*82527734SSukumar Swaminathan hba->flag |= FC_MBOX_TIMEOUT; 3300*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 3301*82527734SSukumar Swaminathan emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 3302291a2b48SSukumar Swaminathan 3303*82527734SSukumar Swaminathan break; 3304*82527734SSukumar Swaminathan } 3305291a2b48SSukumar Swaminathan 3306*82527734SSukumar Swaminathan DELAYUS(500); 3307*82527734SSukumar Swaminathan ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 3308*82527734SSukumar Swaminathan } 3309291a2b48SSukumar Swaminathan 3310*82527734SSukumar Swaminathan if (mb->mbxStatus == MBX_TIMEOUT) { 3311*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3312*82527734SSukumar Swaminathan &emlxs_mbox_event_msg, 3313*82527734SSukumar Swaminathan "Timeout. %s: mb=%p tmo=%d. Polled.", 3314*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3315*82527734SSukumar Swaminathan tmo); 3316291a2b48SSukumar Swaminathan 3317*82527734SSukumar Swaminathan break; 3318*82527734SSukumar Swaminathan } 3319*82527734SSukumar Swaminathan } 3320291a2b48SSukumar Swaminathan 3321*82527734SSukumar Swaminathan /* Get first word of mailbox */ 3322*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 3323*82527734SSukumar Swaminathan mbox = FC_SLIM2_MAILBOX(hba); 3324*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mbox) - 3325*82527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 3326291a2b48SSukumar Swaminathan 3327*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 3328*82527734SSukumar Swaminathan offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 3329*82527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 3330*82527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 3331*82527734SSukumar Swaminathan } else { 3332*82527734SSukumar Swaminathan mbox = FC_SLIM1_MAILBOX(hba); 3333*82527734SSukumar Swaminathan word0 = 3334*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 33354baa2c25SSukumar Swaminathan } 33364baa2c25SSukumar Swaminathan 3337*82527734SSukumar Swaminathan /* Wait for command to complete */ 3338*82527734SSukumar Swaminathan while ((swpmb->mbxOwner == OWN_CHIP) && 3339*82527734SSukumar Swaminathan !(mbq->flag & MBQ_COMPLETED)) { 3340*82527734SSukumar Swaminathan if (!hba->timer_id && (tmo_local-- == 0)) { 3341*82527734SSukumar Swaminathan /* self time */ 3342*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 3343*82527734SSukumar Swaminathan &emlxs_mbox_timeout_msg, 3344*82527734SSukumar Swaminathan "%s: mb=%p Polled.", 3345*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb); 3346291a2b48SSukumar Swaminathan 3347*82527734SSukumar Swaminathan hba->flag |= FC_MBOX_TIMEOUT; 3348*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 3349*82527734SSukumar Swaminathan emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 3350291a2b48SSukumar Swaminathan 3351*82527734SSukumar Swaminathan break; 3352*82527734SSukumar Swaminathan } 3353291a2b48SSukumar Swaminathan 3354*82527734SSukumar Swaminathan DELAYUS(500); 3355291a2b48SSukumar Swaminathan 3356*82527734SSukumar Swaminathan /* Get first word of mailbox */ 3357*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 3358*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC( 3359*82527734SSukumar Swaminathan hba->sli.sli3.slim2.dma_handle, offset, 3360*82527734SSukumar Swaminathan sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 3361*82527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 3362*82527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 3363*82527734SSukumar Swaminathan } else { 3364*82527734SSukumar Swaminathan word0 = 3365*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 3366*82527734SSukumar Swaminathan ((volatile uint32_t *)mbox)); 3367*82527734SSukumar Swaminathan } 3368291a2b48SSukumar Swaminathan 3369*82527734SSukumar Swaminathan } /* while */ 3370291a2b48SSukumar Swaminathan 3371*82527734SSukumar Swaminathan if (mb->mbxStatus == MBX_TIMEOUT) { 3372*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_event_msg, 3373*82527734SSukumar Swaminathan "Timeout. %s: mb=%p tmo=%d. Polled.", 3374*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, tmo); 3375*82527734SSukumar Swaminathan 3376*82527734SSukumar Swaminathan break; 3377291a2b48SSukumar Swaminathan } 3378291a2b48SSukumar Swaminathan 3379*82527734SSukumar Swaminathan /* copy results back to user */ 3380*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 3381*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 3382*82527734SSukumar Swaminathan offset, MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); 3383291a2b48SSukumar Swaminathan 3384*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb, 3385*82527734SSukumar Swaminathan MAILBOX_CMD_BSIZE); 3386*82527734SSukumar Swaminathan } else { 3387*82527734SSukumar Swaminathan READ_SLIM_COPY(hba, (uint32_t *)mb, 3388*82527734SSukumar Swaminathan (uint32_t *)mbox, MAILBOX_CMD_WSIZE); 3389*82527734SSukumar Swaminathan } 3390291a2b48SSukumar Swaminathan 3391*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 3392*82527734SSukumar Swaminathan if (mbq->extbuf) { 3393*82527734SSukumar Swaminathan uint32_t *mbox_ext = 3394*82527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + 3395*82527734SSukumar Swaminathan MBOX_EXTENSION_OFFSET); 3396*82527734SSukumar Swaminathan off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 3397291a2b48SSukumar Swaminathan 3398*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 3399*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC( 3400*82527734SSukumar Swaminathan hba->sli.sli3.slim2.dma_handle, offset_ext, 3401*82527734SSukumar Swaminathan mbq->extsize, DDI_DMA_SYNC_FORKERNEL); 3402291a2b48SSukumar Swaminathan 3403*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox_ext, 3404*82527734SSukumar Swaminathan (uint8_t *)mbq->extbuf, mbq->extsize); 3405*82527734SSukumar Swaminathan } else { 3406*82527734SSukumar Swaminathan READ_SLIM_COPY(hba, 3407*82527734SSukumar Swaminathan (uint32_t *)mbq->extbuf, mbox_ext, 3408*82527734SSukumar Swaminathan (mbq->extsize / 4)); 3409*82527734SSukumar Swaminathan } 3410*82527734SSukumar Swaminathan } 3411*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 3412291a2b48SSukumar Swaminathan 3413*82527734SSukumar Swaminathan /* Sync the memory buffer */ 3414*82527734SSukumar Swaminathan if (mbq->bp) { 3415*82527734SSukumar Swaminathan mbox_bp = (MATCHMAP *)mbq->bp; 3416*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, 3417*82527734SSukumar Swaminathan mbox_bp->size, DDI_DMA_SYNC_FORKERNEL); 3418*82527734SSukumar Swaminathan } 3419291a2b48SSukumar Swaminathan 3420*82527734SSukumar Swaminathan if (mb->mbxCommand != MBX_DOWN_LOAD && 3421*82527734SSukumar Swaminathan mb->mbxCommand != MBX_DUMP_MEMORY) { 3422*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 3423*82527734SSukumar Swaminathan "Completed. %s: mb=%p status=%x Polled.", 3424*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), mb, 3425*82527734SSukumar Swaminathan mb->mbxStatus); 3426*82527734SSukumar Swaminathan } 3427291a2b48SSukumar Swaminathan 3428*82527734SSukumar Swaminathan /* Process the result */ 3429*82527734SSukumar Swaminathan if (!(mbq->flag & MBQ_PASSTHRU)) { 3430*82527734SSukumar Swaminathan if (mbq->mbox_cmpl) { 3431*82527734SSukumar Swaminathan (void) (mbq->mbox_cmpl)(hba, mbq); 3432*82527734SSukumar Swaminathan } 3433*82527734SSukumar Swaminathan } 3434291a2b48SSukumar Swaminathan 3435*82527734SSukumar Swaminathan /* Clear the attention bit */ 3436*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_MBATT); 34374baa2c25SSukumar Swaminathan 3438*82527734SSukumar Swaminathan /* Clean up the mailbox area */ 3439*82527734SSukumar Swaminathan emlxs_mb_fini(hba, NULL, mb->mbxStatus); 3440291a2b48SSukumar Swaminathan 3441*82527734SSukumar Swaminathan break; 3442291a2b48SSukumar Swaminathan 3443*82527734SSukumar Swaminathan } /* switch (flag) */ 3444*82527734SSukumar Swaminathan 3445*82527734SSukumar Swaminathan return (mb->mbxStatus); 3446*82527734SSukumar Swaminathan 3447*82527734SSukumar Swaminathan } /* emlxs_sli3_issue_mbox_cmd() */ 3448*82527734SSukumar Swaminathan 3449*82527734SSukumar Swaminathan 3450*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 3451*82527734SSukumar Swaminathan static uint32_t 3452*82527734SSukumar Swaminathan emlxs_sli3_prep_fct_iocb(emlxs_port_t *port, emlxs_buf_t *cmd_sbp, 3453*82527734SSukumar Swaminathan int channel) 3454291a2b48SSukumar Swaminathan { 3455*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 3456*82527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 3457*82527734SSukumar Swaminathan fct_cmd_t *fct_cmd; 3458*82527734SSukumar Swaminathan stmf_data_buf_t *dbuf; 3459*82527734SSukumar Swaminathan scsi_task_t *fct_task; 3460*82527734SSukumar Swaminathan uint32_t did; 3461*82527734SSukumar Swaminathan IOCBQ *iocbq; 3462*82527734SSukumar Swaminathan IOCB *iocb; 3463*82527734SSukumar Swaminathan uint32_t timeout; 3464*82527734SSukumar Swaminathan uint32_t iotag; 3465*82527734SSukumar Swaminathan emlxs_node_t *ndlp; 3466*82527734SSukumar Swaminathan CHANNEL *cp; 3467291a2b48SSukumar Swaminathan 3468*82527734SSukumar Swaminathan dbuf = cmd_sbp->fct_buf; 3469*82527734SSukumar Swaminathan fct_cmd = cmd_sbp->fct_cmd; 3470*82527734SSukumar Swaminathan fct_task = (scsi_task_t *)fct_cmd->cmd_specific; 3471*82527734SSukumar Swaminathan ndlp = *(emlxs_node_t **)fct_cmd->cmd_rp->rp_fca_private; 3472*82527734SSukumar Swaminathan did = fct_cmd->cmd_rportid; 3473291a2b48SSukumar Swaminathan 3474*82527734SSukumar Swaminathan cp = (CHANNEL *)cmd_sbp->channel; 3475291a2b48SSukumar Swaminathan 3476*82527734SSukumar Swaminathan channel = channel; 3477*82527734SSukumar Swaminathan iocbq = &cmd_sbp->iocbq; 3478*82527734SSukumar Swaminathan iocb = &iocbq->iocb; 3479291a2b48SSukumar Swaminathan 3480*82527734SSukumar Swaminathan if (cfg[CFG_TIMEOUT_ENABLE].current) { 3481*82527734SSukumar Swaminathan timeout = 3482*82527734SSukumar Swaminathan ((2 * hba->fc_ratov) < 60) ? 60 : (2 * hba->fc_ratov); 3483*82527734SSukumar Swaminathan } else { 3484*82527734SSukumar Swaminathan timeout = 0x80000000; 3485*82527734SSukumar Swaminathan } 3486291a2b48SSukumar Swaminathan 3487*82527734SSukumar Swaminathan #ifdef FCT_API_TRACE 3488*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_api_msg, 3489*82527734SSukumar Swaminathan "emlxs_fct_send_fcp_data %p: flgs=%x ioflags=%x dl=%d,%d,%d,%d,%d", 3490*82527734SSukumar Swaminathan fct_cmd, dbuf->db_flags, ioflags, fct_task->task_cmd_xfer_length, 3491*82527734SSukumar Swaminathan fct_task->task_nbytes_transferred, dbuf->db_data_size, 3492*82527734SSukumar Swaminathan fct_task->task_expected_xfer_length, channel); 3493*82527734SSukumar Swaminathan #endif /* FCT_API_TRACE */ 3494291a2b48SSukumar Swaminathan 3495291a2b48SSukumar Swaminathan 3496*82527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 3497*82527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, cmd_sbp); 3498291a2b48SSukumar Swaminathan 3499*82527734SSukumar Swaminathan if (!iotag) { 3500*82527734SSukumar Swaminathan /* No more command slots available, retry later */ 3501*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3502*82527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 35034baa2c25SSukumar Swaminathan 3504*82527734SSukumar Swaminathan return (IOERR_NO_RESOURCES); 3505291a2b48SSukumar Swaminathan } 3506291a2b48SSukumar Swaminathan 3507*82527734SSukumar Swaminathan cmd_sbp->ticks = 3508*82527734SSukumar Swaminathan hba->timer_tics + timeout + ((timeout > 0xff) ? 0 : 10); 3509291a2b48SSukumar Swaminathan 3510*82527734SSukumar Swaminathan /* Initalize iocbq */ 3511*82527734SSukumar Swaminathan iocbq->port = (void *)port; 3512*82527734SSukumar Swaminathan iocbq->node = (void *)ndlp; 3513291a2b48SSukumar Swaminathan 3514291a2b48SSukumar Swaminathan 3515*82527734SSukumar Swaminathan iocbq->channel = (void *)cmd_sbp->channel; 3516291a2b48SSukumar Swaminathan 3517*82527734SSukumar Swaminathan if (emlxs_fct_bde_setup(port, cmd_sbp)) { 3518*82527734SSukumar Swaminathan /* Unregister the packet */ 3519*82527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cmd_sbp->channel, iotag, 0); 3520291a2b48SSukumar Swaminathan 3521*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3522*82527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 3523291a2b48SSukumar Swaminathan 3524*82527734SSukumar Swaminathan return (IOERR_INTERNAL_ERROR); 3525*82527734SSukumar Swaminathan } 3526*82527734SSukumar Swaminathan /* Point of no return */ 3527291a2b48SSukumar Swaminathan 3528*82527734SSukumar Swaminathan /* Initalize iocb */ 3529*82527734SSukumar Swaminathan iocb->ULPCONTEXT = (uint16_t)fct_cmd->cmd_rxid; 3530*82527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 3531*82527734SSukumar Swaminathan iocb->ULPRSVDBYTE = ((timeout > 0xff) ? 0 : timeout); 3532*82527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3533*82527734SSukumar Swaminathan iocb->ULPCLASS = cmd_sbp->class; 3534291a2b48SSukumar Swaminathan 3535*82527734SSukumar Swaminathan iocb->ULPPU = 1; /* Wd4 is relative offset */ 3536*82527734SSukumar Swaminathan iocb->un.fcpt64.fcpt_Offset = dbuf->db_relative_offset; 3537291a2b48SSukumar Swaminathan 3538*82527734SSukumar Swaminathan if (fct_task->task_flags & TF_WRITE_DATA) { 3539*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_TRECEIVE64_CX; 3540*82527734SSukumar Swaminathan } else { /* TF_READ_DATA */ 3541291a2b48SSukumar Swaminathan 3542*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_TSEND64_CX; 3543291a2b48SSukumar Swaminathan 3544*82527734SSukumar Swaminathan if (dbuf->db_data_size == 3545*82527734SSukumar Swaminathan fct_task->task_expected_xfer_length) 3546*82527734SSukumar Swaminathan iocb->ULPCT = 0x1; 3547*82527734SSukumar Swaminathan /* enable auto-rsp AP feature */ 3548*82527734SSukumar Swaminathan } 3549291a2b48SSukumar Swaminathan 3550*82527734SSukumar Swaminathan return (IOERR_SUCCESS); 3551291a2b48SSukumar Swaminathan 3552*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_fct_iocb() */ 3553291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3554291a2b48SSukumar Swaminathan 3555*82527734SSukumar Swaminathan /* ARGSUSED */ 3556*82527734SSukumar Swaminathan static uint32_t 3557*82527734SSukumar Swaminathan emlxs_sli3_prep_fcp_iocb(emlxs_port_t *port, emlxs_buf_t *sbp, int channel) 3558*82527734SSukumar Swaminathan { 3559*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 3560*82527734SSukumar Swaminathan fc_packet_t *pkt; 3561*82527734SSukumar Swaminathan CHANNEL *cp; 3562*82527734SSukumar Swaminathan IOCBQ *iocbq; 3563*82527734SSukumar Swaminathan IOCB *iocb; 3564*82527734SSukumar Swaminathan NODELIST *ndlp; 3565*82527734SSukumar Swaminathan uint16_t iotag; 3566*82527734SSukumar Swaminathan uint32_t did; 3567*82527734SSukumar Swaminathan 3568*82527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 3569*82527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3570*82527734SSukumar Swaminathan cp = &hba->chan[FC_FCP_RING]; 3571*82527734SSukumar Swaminathan 3572*82527734SSukumar Swaminathan iocbq = &sbp->iocbq; 3573*82527734SSukumar Swaminathan iocb = &iocbq->iocb; 3574*82527734SSukumar Swaminathan 3575*82527734SSukumar Swaminathan /* Find target node object */ 3576*82527734SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 3577*82527734SSukumar Swaminathan 3578*82527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 3579*82527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 3580*82527734SSukumar Swaminathan 3581*82527734SSukumar Swaminathan if (!iotag) { 3582*82527734SSukumar Swaminathan /* 3583*82527734SSukumar Swaminathan * No more command slots available, retry later 3584*82527734SSukumar Swaminathan */ 3585*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3586*82527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag: did=0x%x", did); 3587*82527734SSukumar Swaminathan 3588*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3589*82527734SSukumar Swaminathan } 3590*82527734SSukumar Swaminathan 3591*82527734SSukumar Swaminathan /* Initalize iocbq */ 3592*82527734SSukumar Swaminathan iocbq->port = (void *) port; 3593*82527734SSukumar Swaminathan iocbq->channel = (void *) cp; 3594*82527734SSukumar Swaminathan 3595*82527734SSukumar Swaminathan /* Indicate this is a FCP cmd */ 3596*82527734SSukumar Swaminathan iocbq->flag |= IOCB_FCP_CMD; 3597*82527734SSukumar Swaminathan 3598*82527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 3599*82527734SSukumar Swaminathan /* Unregister the packet */ 3600*82527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 3601*82527734SSukumar Swaminathan 3602*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3603*82527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 3604*82527734SSukumar Swaminathan 3605*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3606*82527734SSukumar Swaminathan } 3607*82527734SSukumar Swaminathan /* Point of no return */ 3608*82527734SSukumar Swaminathan 3609*82527734SSukumar Swaminathan /* Initalize iocb */ 3610*82527734SSukumar Swaminathan iocb->ULPCONTEXT = ndlp->nlp_Rpi; 3611*82527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 3612*82527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 3613*82527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3614*82527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3615*82527734SSukumar Swaminathan 3616*82527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 3617*82527734SSukumar Swaminathan case FC_TRAN_CLASS1: 3618*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 3619*82527734SSukumar Swaminathan break; 3620*82527734SSukumar Swaminathan case FC_TRAN_CLASS2: 3621*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 3622*82527734SSukumar Swaminathan /* iocb->ULPCLASS = CLASS3; */ 3623*82527734SSukumar Swaminathan break; 3624*82527734SSukumar Swaminathan case FC_TRAN_CLASS3: 3625*82527734SSukumar Swaminathan default: 3626*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 3627*82527734SSukumar Swaminathan break; 3628*82527734SSukumar Swaminathan } 3629*82527734SSukumar Swaminathan 3630*82527734SSukumar Swaminathan /* if device is FCP-2 device, set the following bit */ 3631*82527734SSukumar Swaminathan /* that says to run the FC-TAPE protocol. */ 3632*82527734SSukumar Swaminathan if (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { 3633*82527734SSukumar Swaminathan iocb->ULPFCP2RCVY = 1; 3634*82527734SSukumar Swaminathan } 3635*82527734SSukumar Swaminathan 3636*82527734SSukumar Swaminathan if (pkt->pkt_datalen == 0) { 3637*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_ICMND64_CR; 3638*82527734SSukumar Swaminathan } else if (pkt->pkt_tran_type == FC_PKT_FCP_READ) { 3639*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_IREAD64_CR; 3640*82527734SSukumar Swaminathan iocb->ULPPU = PARM_READ_CHECK; 3641*82527734SSukumar Swaminathan iocb->un.fcpi64.fcpi_parm = pkt->pkt_datalen; 3642*82527734SSukumar Swaminathan } else { 3643*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_FCP_IWRITE64_CR; 3644*82527734SSukumar Swaminathan } 3645*82527734SSukumar Swaminathan 3646*82527734SSukumar Swaminathan return (FC_SUCCESS); 3647*82527734SSukumar Swaminathan 3648*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_fcp_iocb() */ 3649*82527734SSukumar Swaminathan 3650*82527734SSukumar Swaminathan 3651*82527734SSukumar Swaminathan static uint32_t 3652*82527734SSukumar Swaminathan emlxs_sli3_prep_ip_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 3653*82527734SSukumar Swaminathan { 3654*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 3655*82527734SSukumar Swaminathan fc_packet_t *pkt; 3656*82527734SSukumar Swaminathan IOCBQ *iocbq; 3657*82527734SSukumar Swaminathan IOCB *iocb; 3658*82527734SSukumar Swaminathan CHANNEL *cp; 3659*82527734SSukumar Swaminathan NODELIST *ndlp; 3660*82527734SSukumar Swaminathan uint16_t iotag; 3661*82527734SSukumar Swaminathan uint32_t did; 3662*82527734SSukumar Swaminathan 3663*82527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 3664*82527734SSukumar Swaminathan cp = &hba->chan[FC_IP_RING]; 3665*82527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3666*82527734SSukumar Swaminathan 3667*82527734SSukumar Swaminathan iocbq = &sbp->iocbq; 3668*82527734SSukumar Swaminathan iocb = &iocbq->iocb; 3669*82527734SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 3670*82527734SSukumar Swaminathan 3671*82527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 3672*82527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 3673*82527734SSukumar Swaminathan 3674*82527734SSukumar Swaminathan if (!iotag) { 3675*82527734SSukumar Swaminathan /* 3676*82527734SSukumar Swaminathan * No more command slots available, retry later 3677*82527734SSukumar Swaminathan */ 3678*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3679*82527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag: did=0x%x", did); 3680*82527734SSukumar Swaminathan 3681*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3682*82527734SSukumar Swaminathan } 3683*82527734SSukumar Swaminathan 3684*82527734SSukumar Swaminathan /* Initalize iocbq */ 3685*82527734SSukumar Swaminathan iocbq->port = (void *) port; 3686*82527734SSukumar Swaminathan iocbq->channel = (void *) cp; 3687*82527734SSukumar Swaminathan 3688*82527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 3689*82527734SSukumar Swaminathan /* Unregister the packet */ 3690*82527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 3691*82527734SSukumar Swaminathan 3692*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3693*82527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 3694*82527734SSukumar Swaminathan 3695*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3696*82527734SSukumar Swaminathan } 3697*82527734SSukumar Swaminathan /* Point of no return */ 3698*82527734SSukumar Swaminathan 3699*82527734SSukumar Swaminathan /* Initalize iocb */ 3700*82527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Fctl = 0; 3701*82527734SSukumar Swaminathan 3702*82527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_FIRST_SEQ) { 3703*82527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Fctl |= FSEQ; 3704*82527734SSukumar Swaminathan } 3705*82527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) { 3706*82527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Fctl |= SI; 3707*82527734SSukumar Swaminathan } 3708*82527734SSukumar Swaminathan 3709*82527734SSukumar Swaminathan /* network headers */ 3710*82527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; 3711*82527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 3712*82527734SSukumar Swaminathan iocb->un.xseq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type; 3713*82527734SSukumar Swaminathan 3714*82527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 3715*82527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 3716*82527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3717*82527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3718*82527734SSukumar Swaminathan 3719*82527734SSukumar Swaminathan if (pkt->pkt_tran_type == FC_PKT_BROADCAST) { 3720*82527734SSukumar Swaminathan HBASTATS.IpBcastIssued++; 3721*82527734SSukumar Swaminathan 3722*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_BCAST64_CN; 3723*82527734SSukumar Swaminathan iocb->ULPCONTEXT = 0; 3724*82527734SSukumar Swaminathan 3725*82527734SSukumar Swaminathan if (hba->sli_mode == 3) { 3726*82527734SSukumar Swaminathan if (hba->topology != TOPOLOGY_LOOP) { 3727*82527734SSukumar Swaminathan iocb->ULPCT = 0x1; 3728*82527734SSukumar Swaminathan } 3729*82527734SSukumar Swaminathan iocb->ULPCONTEXT = port->vpi; 3730*82527734SSukumar Swaminathan } 3731*82527734SSukumar Swaminathan 3732*82527734SSukumar Swaminathan } else { 3733*82527734SSukumar Swaminathan HBASTATS.IpSeqIssued++; 3734*82527734SSukumar Swaminathan 3735*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX; 3736*82527734SSukumar Swaminathan iocb->ULPCONTEXT = ndlp->nlp_Xri; 3737*82527734SSukumar Swaminathan } 3738*82527734SSukumar Swaminathan 3739*82527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 3740*82527734SSukumar Swaminathan case FC_TRAN_CLASS1: 3741*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 3742*82527734SSukumar Swaminathan break; 3743*82527734SSukumar Swaminathan case FC_TRAN_CLASS2: 3744*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 3745*82527734SSukumar Swaminathan break; 3746*82527734SSukumar Swaminathan case FC_TRAN_CLASS3: 3747*82527734SSukumar Swaminathan default: 3748*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 3749*82527734SSukumar Swaminathan break; 3750*82527734SSukumar Swaminathan } 3751*82527734SSukumar Swaminathan 3752*82527734SSukumar Swaminathan return (FC_SUCCESS); 3753*82527734SSukumar Swaminathan 3754*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_ip_iocb() */ 3755*82527734SSukumar Swaminathan 3756*82527734SSukumar Swaminathan 3757*82527734SSukumar Swaminathan static uint32_t 3758*82527734SSukumar Swaminathan emlxs_sli3_prep_els_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 3759*82527734SSukumar Swaminathan { 3760*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 3761*82527734SSukumar Swaminathan fc_packet_t *pkt; 3762*82527734SSukumar Swaminathan IOCBQ *iocbq; 3763*82527734SSukumar Swaminathan IOCB *iocb; 3764*82527734SSukumar Swaminathan CHANNEL *cp; 3765*82527734SSukumar Swaminathan uint16_t iotag; 3766*82527734SSukumar Swaminathan uint32_t did; 3767*82527734SSukumar Swaminathan uint32_t cmd; 3768*82527734SSukumar Swaminathan 3769*82527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 3770*82527734SSukumar Swaminathan cp = &hba->chan[FC_ELS_RING]; 3771*82527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3772*82527734SSukumar Swaminathan 3773*82527734SSukumar Swaminathan iocbq = &sbp->iocbq; 3774*82527734SSukumar Swaminathan iocb = &iocbq->iocb; 3775*82527734SSukumar Swaminathan 3776*82527734SSukumar Swaminathan 3777*82527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 3778*82527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 3779*82527734SSukumar Swaminathan 3780*82527734SSukumar Swaminathan if (!iotag) { 3781*82527734SSukumar Swaminathan /* 3782*82527734SSukumar Swaminathan * No more command slots available, retry later 3783*82527734SSukumar Swaminathan */ 3784*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3785*82527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 3786*82527734SSukumar Swaminathan 3787*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3788*82527734SSukumar Swaminathan } 3789*82527734SSukumar Swaminathan /* Initalize iocbq */ 3790*82527734SSukumar Swaminathan iocbq->port = (void *) port; 3791*82527734SSukumar Swaminathan iocbq->channel = (void *) cp; 3792*82527734SSukumar Swaminathan 3793*82527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 3794*82527734SSukumar Swaminathan /* Unregister the packet */ 3795*82527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 3796*82527734SSukumar Swaminathan 3797*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3798*82527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 3799*82527734SSukumar Swaminathan 3800*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3801*82527734SSukumar Swaminathan } 3802*82527734SSukumar Swaminathan /* Point of no return */ 3803*82527734SSukumar Swaminathan 3804*82527734SSukumar Swaminathan /* Initalize iocb */ 3805*82527734SSukumar Swaminathan if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 3806*82527734SSukumar Swaminathan /* ELS Response */ 3807*82527734SSukumar Swaminathan iocb->ULPCONTEXT = (volatile uint16_t) pkt->pkt_cmd_fhdr.rx_id; 3808*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_ELS_RSP64_CX; 3809*82527734SSukumar Swaminathan } else { 3810*82527734SSukumar Swaminathan /* ELS Request */ 3811*82527734SSukumar Swaminathan iocb->un.elsreq64.remoteID = (did == BCAST_DID) ? 0 : did; 3812*82527734SSukumar Swaminathan iocb->ULPCONTEXT = 3813*82527734SSukumar Swaminathan (did == BCAST_DID) ? pkt->pkt_cmd_fhdr.seq_id : 0; 3814*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_ELS_REQUEST64_CR; 3815*82527734SSukumar Swaminathan 3816*82527734SSukumar Swaminathan if (hba->topology != TOPOLOGY_LOOP) { 3817*82527734SSukumar Swaminathan cmd = *((uint32_t *)pkt->pkt_cmd); 3818*82527734SSukumar Swaminathan cmd &= ELS_CMD_MASK; 3819*82527734SSukumar Swaminathan 3820*82527734SSukumar Swaminathan if ((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) { 3821*82527734SSukumar Swaminathan iocb->ULPCT = 0x2; 3822*82527734SSukumar Swaminathan } else { 3823*82527734SSukumar Swaminathan iocb->ULPCT = 0x1; 3824*82527734SSukumar Swaminathan } 3825*82527734SSukumar Swaminathan } 3826*82527734SSukumar Swaminathan iocb->ULPCONTEXT = port->vpi; 3827*82527734SSukumar Swaminathan } 3828*82527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 3829*82527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 3830*82527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3831*82527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3832*82527734SSukumar Swaminathan 3833*82527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 3834*82527734SSukumar Swaminathan case FC_TRAN_CLASS1: 3835*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 3836*82527734SSukumar Swaminathan break; 3837*82527734SSukumar Swaminathan case FC_TRAN_CLASS2: 3838*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 3839*82527734SSukumar Swaminathan break; 3840*82527734SSukumar Swaminathan case FC_TRAN_CLASS3: 3841*82527734SSukumar Swaminathan default: 3842*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 3843*82527734SSukumar Swaminathan break; 3844*82527734SSukumar Swaminathan } 3845*82527734SSukumar Swaminathan sbp->class = iocb->ULPCLASS; 3846*82527734SSukumar Swaminathan 3847*82527734SSukumar Swaminathan return (FC_SUCCESS); 3848*82527734SSukumar Swaminathan 3849*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_els_iocb() */ 3850*82527734SSukumar Swaminathan 3851*82527734SSukumar Swaminathan 3852*82527734SSukumar Swaminathan static uint32_t 3853*82527734SSukumar Swaminathan emlxs_sli3_prep_ct_iocb(emlxs_port_t *port, emlxs_buf_t *sbp) 3854*82527734SSukumar Swaminathan { 3855*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 3856*82527734SSukumar Swaminathan fc_packet_t *pkt; 3857*82527734SSukumar Swaminathan IOCBQ *iocbq; 3858*82527734SSukumar Swaminathan IOCB *iocb; 3859*82527734SSukumar Swaminathan CHANNEL *cp; 3860*82527734SSukumar Swaminathan NODELIST *ndlp; 3861*82527734SSukumar Swaminathan uint16_t iotag; 3862*82527734SSukumar Swaminathan uint32_t did; 3863*82527734SSukumar Swaminathan 3864*82527734SSukumar Swaminathan pkt = PRIV2PKT(sbp); 3865*82527734SSukumar Swaminathan did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 3866*82527734SSukumar Swaminathan cp = &hba->chan[FC_CT_RING]; 3867*82527734SSukumar Swaminathan 3868*82527734SSukumar Swaminathan iocbq = &sbp->iocbq; 3869*82527734SSukumar Swaminathan iocb = &iocbq->iocb; 3870*82527734SSukumar Swaminathan ndlp = (NODELIST *)iocbq->node; 3871*82527734SSukumar Swaminathan 3872*82527734SSukumar Swaminathan /* Get the iotag by registering the packet */ 3873*82527734SSukumar Swaminathan iotag = emlxs_register_pkt(cp, sbp); 3874*82527734SSukumar Swaminathan 3875*82527734SSukumar Swaminathan if (!iotag) { 3876*82527734SSukumar Swaminathan /* 3877*82527734SSukumar Swaminathan * No more command slots available, retry later 3878*82527734SSukumar Swaminathan */ 3879*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3880*82527734SSukumar Swaminathan "Adapter Busy. Unable to allocate iotag. did=0x%x", did); 3881*82527734SSukumar Swaminathan 3882*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3883*82527734SSukumar Swaminathan } 3884*82527734SSukumar Swaminathan 3885*82527734SSukumar Swaminathan if (emlxs_bde_setup(port, sbp)) { 3886*82527734SSukumar Swaminathan /* Unregister the packet */ 3887*82527734SSukumar Swaminathan (void) emlxs_unregister_pkt(cp, iotag, 0); 3888*82527734SSukumar Swaminathan 3889*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 3890*82527734SSukumar Swaminathan "Adapter Busy. Unable to setup buffer list. did=%x", did); 3891*82527734SSukumar Swaminathan 3892*82527734SSukumar Swaminathan return (FC_TRAN_BUSY); 3893*82527734SSukumar Swaminathan } 3894*82527734SSukumar Swaminathan 3895*82527734SSukumar Swaminathan /* Point of no return */ 3896*82527734SSukumar Swaminathan 3897*82527734SSukumar Swaminathan /* Initalize iocbq */ 3898*82527734SSukumar Swaminathan iocbq->port = (void *) port; 3899*82527734SSukumar Swaminathan iocbq->channel = (void *) cp; 3900*82527734SSukumar Swaminathan 3901*82527734SSukumar Swaminathan /* Fill in rest of iocb */ 3902*82527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Fctl = LA; 3903*82527734SSukumar Swaminathan 3904*82527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_LAST_SEQ) { 3905*82527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Fctl |= LSEQ; 3906*82527734SSukumar Swaminathan } 3907*82527734SSukumar Swaminathan if (pkt->pkt_cmd_fhdr.f_ctl & F_CTL_SEQ_INITIATIVE) { 3908*82527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Fctl |= SI; 3909*82527734SSukumar Swaminathan } 3910*82527734SSukumar Swaminathan 3911*82527734SSukumar Swaminathan /* Initalize iocb */ 3912*82527734SSukumar Swaminathan if (pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 3913*82527734SSukumar Swaminathan /* CT Response */ 3914*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_XMIT_SEQUENCE64_CX; 3915*82527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Dfctl = pkt->pkt_cmd_fhdr.df_ctl; 3916*82527734SSukumar Swaminathan iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id; 3917*82527734SSukumar Swaminathan } else { 3918*82527734SSukumar Swaminathan /* CT Request */ 3919*82527734SSukumar Swaminathan iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CR; 3920*82527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Dfctl = 0; 3921*82527734SSukumar Swaminathan iocb->ULPCONTEXT = ndlp->nlp_Rpi; 3922*82527734SSukumar Swaminathan } 3923*82527734SSukumar Swaminathan 3924*82527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Rctl = pkt->pkt_cmd_fhdr.r_ctl; 3925*82527734SSukumar Swaminathan iocb->un.genreq64.w5.hcsw.Type = pkt->pkt_cmd_fhdr.type; 3926*82527734SSukumar Swaminathan 3927*82527734SSukumar Swaminathan iocb->ULPIOTAG = iotag; 3928*82527734SSukumar Swaminathan iocb->ULPRSVDBYTE = 3929*82527734SSukumar Swaminathan ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 3930*82527734SSukumar Swaminathan iocb->ULPOWNER = OWN_CHIP; 3931*82527734SSukumar Swaminathan 3932*82527734SSukumar Swaminathan switch (FC_TRAN_CLASS(pkt->pkt_tran_flags)) { 3933*82527734SSukumar Swaminathan case FC_TRAN_CLASS1: 3934*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS1; 3935*82527734SSukumar Swaminathan break; 3936*82527734SSukumar Swaminathan case FC_TRAN_CLASS2: 3937*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS2; 3938*82527734SSukumar Swaminathan break; 3939*82527734SSukumar Swaminathan case FC_TRAN_CLASS3: 3940*82527734SSukumar Swaminathan default: 3941*82527734SSukumar Swaminathan iocb->ULPCLASS = CLASS3; 3942*82527734SSukumar Swaminathan break; 3943*82527734SSukumar Swaminathan } 3944*82527734SSukumar Swaminathan 3945*82527734SSukumar Swaminathan return (FC_SUCCESS); 3946*82527734SSukumar Swaminathan 3947*82527734SSukumar Swaminathan } /* emlxs_sli3_prep_ct_iocb() */ 3948*82527734SSukumar Swaminathan 3949*82527734SSukumar Swaminathan 3950291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 3951*82527734SSukumar Swaminathan static uint32_t 3952*82527734SSukumar Swaminathan emlxs_fct_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 3953*82527734SSukumar Swaminathan { 3954*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 3955*82527734SSukumar Swaminathan uint32_t sgllen = 1; 3956*82527734SSukumar Swaminathan uint32_t rval; 3957*82527734SSukumar Swaminathan uint32_t size; 3958*82527734SSukumar Swaminathan uint32_t count; 3959*82527734SSukumar Swaminathan uint32_t resid; 3960*82527734SSukumar Swaminathan struct stmf_sglist_ent *sgl; 3961*82527734SSukumar Swaminathan 3962*82527734SSukumar Swaminathan size = sbp->fct_buf->db_data_size; 3963*82527734SSukumar Swaminathan count = sbp->fct_buf->db_sglist_length; 3964*82527734SSukumar Swaminathan sgl = sbp->fct_buf->db_sglist; 3965*82527734SSukumar Swaminathan resid = size; 3966*82527734SSukumar Swaminathan 3967*82527734SSukumar Swaminathan for (sgllen = 0; sgllen < count && resid > 0; sgllen++) { 3968*82527734SSukumar Swaminathan resid -= MIN(resid, sgl->seg_length); 3969*82527734SSukumar Swaminathan sgl++; 3970*82527734SSukumar Swaminathan } 3971*82527734SSukumar Swaminathan 3972*82527734SSukumar Swaminathan if (resid > 0) { 3973*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_error_msg, 3974*82527734SSukumar Swaminathan "emlxs_fct_bde_setup: Not enough scatter gather buffers " 3975*82527734SSukumar Swaminathan " size=%d resid=%d count=%d", 3976*82527734SSukumar Swaminathan size, resid, count); 3977*82527734SSukumar Swaminathan return (1); 3978*82527734SSukumar Swaminathan } 3979*82527734SSukumar Swaminathan 3980*82527734SSukumar Swaminathan if ((hba->sli_mode < 3) || (sgllen > SLI3_MAX_BDE)) { 3981*82527734SSukumar Swaminathan rval = emlxs_sli2_fct_bde_setup(port, sbp); 3982*82527734SSukumar Swaminathan } else { 3983*82527734SSukumar Swaminathan rval = emlxs_sli3_fct_bde_setup(port, sbp); 3984*82527734SSukumar Swaminathan } 3985*82527734SSukumar Swaminathan 3986*82527734SSukumar Swaminathan return (rval); 3987*82527734SSukumar Swaminathan 3988*82527734SSukumar Swaminathan } /* emlxs_fct_bde_setup() */ 3989291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 3990291a2b48SSukumar Swaminathan 3991*82527734SSukumar Swaminathan static uint32_t 3992*82527734SSukumar Swaminathan emlxs_bde_setup(emlxs_port_t *port, emlxs_buf_t *sbp) 3993*82527734SSukumar Swaminathan { 3994*82527734SSukumar Swaminathan uint32_t rval; 3995*82527734SSukumar Swaminathan emlxs_hba_t *hba = HBA; 3996*82527734SSukumar Swaminathan 3997*82527734SSukumar Swaminathan if (hba->sli_mode < 3) { 3998*82527734SSukumar Swaminathan rval = emlxs_sli2_bde_setup(port, sbp); 3999*82527734SSukumar Swaminathan } else { 4000*82527734SSukumar Swaminathan rval = emlxs_sli3_bde_setup(port, sbp); 4001*82527734SSukumar Swaminathan } 4002*82527734SSukumar Swaminathan 4003*82527734SSukumar Swaminathan return (rval); 4004*82527734SSukumar Swaminathan 4005*82527734SSukumar Swaminathan } /* emlxs_bde_setup() */ 4006*82527734SSukumar Swaminathan 4007*82527734SSukumar Swaminathan 4008*82527734SSukumar Swaminathan static void 4009*82527734SSukumar Swaminathan emlxs_sli3_poll_intr(emlxs_hba_t *hba, uint32_t att_bit) 4010*82527734SSukumar Swaminathan { 4011*82527734SSukumar Swaminathan uint32_t ha_copy; 4012*82527734SSukumar Swaminathan 4013*82527734SSukumar Swaminathan /* 4014*82527734SSukumar Swaminathan * Polling a specific attention bit. 4015*82527734SSukumar Swaminathan */ 4016*82527734SSukumar Swaminathan for (;;) { 4017*82527734SSukumar Swaminathan ha_copy = emlxs_check_attention(hba); 4018*82527734SSukumar Swaminathan 4019*82527734SSukumar Swaminathan if (ha_copy & att_bit) { 4020*82527734SSukumar Swaminathan break; 4021*82527734SSukumar Swaminathan } 4022*82527734SSukumar Swaminathan 4023*82527734SSukumar Swaminathan } 4024*82527734SSukumar Swaminathan 4025*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4026*82527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, -1); 4027*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4028*82527734SSukumar Swaminathan 4029*82527734SSukumar Swaminathan /* Process the attentions */ 4030*82527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 4031*82527734SSukumar Swaminathan 4032*82527734SSukumar Swaminathan return; 4033*82527734SSukumar Swaminathan 4034*82527734SSukumar Swaminathan } /* emlxs_sli3_poll_intr() */ 4035*82527734SSukumar Swaminathan 4036*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT 4037*82527734SSukumar Swaminathan static uint32_t 4038*82527734SSukumar Swaminathan emlxs_sli3_msi_intr(char *arg1, char *arg2) 4039*82527734SSukumar Swaminathan { 4040*82527734SSukumar Swaminathan emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 4041*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4042*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 4043*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4044*82527734SSukumar Swaminathan uint16_t msgid; 4045*82527734SSukumar Swaminathan uint32_t hc_copy; 4046*82527734SSukumar Swaminathan uint32_t ha_copy; 4047*82527734SSukumar Swaminathan uint32_t restore = 0; 4048291a2b48SSukumar Swaminathan 4049*82527734SSukumar Swaminathan /* 4050*82527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 4051*82527734SSukumar Swaminathan * "emlxs_sli3_msi_intr: arg1=%p arg2=%p", arg1, arg2); 4052*82527734SSukumar Swaminathan */ 4053291a2b48SSukumar Swaminathan 4054*82527734SSukumar Swaminathan /* Check for legacy interrupt handling */ 4055*82527734SSukumar Swaminathan if (hba->intr_type == DDI_INTR_TYPE_FIXED) { 4056*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4057291a2b48SSukumar Swaminathan 4058*82527734SSukumar Swaminathan if (hba->flag & FC_OFFLINE_MODE) { 4059*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4060291a2b48SSukumar Swaminathan 4061*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 4062*82527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 4063*82527734SSukumar Swaminathan } else { 4064*82527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 4065*82527734SSukumar Swaminathan } 4066291a2b48SSukumar Swaminathan } 4067291a2b48SSukumar Swaminathan 4068*82527734SSukumar Swaminathan /* Get host attention bits */ 4069*82527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, -1); 4070291a2b48SSukumar Swaminathan 4071*82527734SSukumar Swaminathan if (ha_copy == 0) { 4072*82527734SSukumar Swaminathan if (hba->intr_unclaimed) { 4073*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4074*82527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 4075*82527734SSukumar Swaminathan } 4076291a2b48SSukumar Swaminathan 4077*82527734SSukumar Swaminathan hba->intr_unclaimed = 1; 4078*82527734SSukumar Swaminathan } else { 4079*82527734SSukumar Swaminathan hba->intr_unclaimed = 0; 4080291a2b48SSukumar Swaminathan } 4081291a2b48SSukumar Swaminathan 4082*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4083291a2b48SSukumar Swaminathan 4084*82527734SSukumar Swaminathan /* Process the interrupt */ 4085*82527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 4086291a2b48SSukumar Swaminathan 4087*82527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 4088*82527734SSukumar Swaminathan } 4089291a2b48SSukumar Swaminathan 4090*82527734SSukumar Swaminathan /* DDI_INTR_TYPE_MSI */ 4091*82527734SSukumar Swaminathan /* DDI_INTR_TYPE_MSIX */ 4092291a2b48SSukumar Swaminathan 4093*82527734SSukumar Swaminathan /* Get MSI message id */ 4094*82527734SSukumar Swaminathan msgid = (uint16_t)((unsigned long)arg2); 4095291a2b48SSukumar Swaminathan 4096*82527734SSukumar Swaminathan /* Validate the message id */ 4097*82527734SSukumar Swaminathan if (msgid >= hba->intr_count) { 4098*82527734SSukumar Swaminathan msgid = 0; 4099*82527734SSukumar Swaminathan } 4100291a2b48SSukumar Swaminathan 4101*82527734SSukumar Swaminathan mutex_enter(&EMLXS_INTR_LOCK(msgid)); 4102291a2b48SSukumar Swaminathan 4103*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4104*82527734SSukumar Swaminathan 4105*82527734SSukumar Swaminathan /* Check if adapter is offline */ 4106*82527734SSukumar Swaminathan if (hba->flag & FC_OFFLINE_MODE) { 4107*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4108*82527734SSukumar Swaminathan mutex_exit(&EMLXS_INTR_LOCK(msgid)); 4109*82527734SSukumar Swaminathan 4110*82527734SSukumar Swaminathan /* Always claim an MSI interrupt */ 4111*82527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 4112*82527734SSukumar Swaminathan } 4113*82527734SSukumar Swaminathan 4114*82527734SSukumar Swaminathan /* Disable interrupts associated with this msgid */ 4115*82527734SSukumar Swaminathan if (msgid == 0 && (hba->model_info.chip == EMLXS_ZEPHYR_CHIP)) { 4116*82527734SSukumar Swaminathan hc_copy = hba->sli.sli3.hc_copy & ~hba->intr_mask; 4117*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hc_copy); 4118*82527734SSukumar Swaminathan restore = 1; 4119*82527734SSukumar Swaminathan } 4120*82527734SSukumar Swaminathan 4121*82527734SSukumar Swaminathan /* Get host attention bits */ 4122*82527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, msgid); 4123*82527734SSukumar Swaminathan 4124*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4125*82527734SSukumar Swaminathan 4126*82527734SSukumar Swaminathan /* Process the interrupt */ 4127*82527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 4128*82527734SSukumar Swaminathan 4129*82527734SSukumar Swaminathan /* Restore interrupts */ 4130*82527734SSukumar Swaminathan if (restore) { 4131*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4132*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 4133*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4134*82527734SSukumar Swaminathan /* Access handle validation */ 4135*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4136*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4137*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4138*82527734SSukumar Swaminathan } 4139*82527734SSukumar Swaminathan 4140*82527734SSukumar Swaminathan mutex_exit(&EMLXS_INTR_LOCK(msgid)); 4141*82527734SSukumar Swaminathan 4142*82527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 4143*82527734SSukumar Swaminathan 4144*82527734SSukumar Swaminathan } /* emlxs_sli3_msi_intr() */ 4145*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 4146*82527734SSukumar Swaminathan 4147*82527734SSukumar Swaminathan 4148*82527734SSukumar Swaminathan static int 4149*82527734SSukumar Swaminathan emlxs_sli3_intx_intr(char *arg) 4150*82527734SSukumar Swaminathan { 4151*82527734SSukumar Swaminathan emlxs_hba_t *hba = (emlxs_hba_t *)arg; 4152*82527734SSukumar Swaminathan uint32_t ha_copy = 0; 4153*82527734SSukumar Swaminathan 4154*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4155*82527734SSukumar Swaminathan 4156*82527734SSukumar Swaminathan if (hba->flag & FC_OFFLINE_MODE) { 4157*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4158*82527734SSukumar Swaminathan 4159*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 4160*82527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 4161*82527734SSukumar Swaminathan } else { 4162*82527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 4163291a2b48SSukumar Swaminathan } 4164*82527734SSukumar Swaminathan } 4165291a2b48SSukumar Swaminathan 4166*82527734SSukumar Swaminathan /* Get host attention bits */ 4167*82527734SSukumar Swaminathan ha_copy = emlxs_get_attention(hba, -1); 4168291a2b48SSukumar Swaminathan 4169*82527734SSukumar Swaminathan if (ha_copy == 0) { 4170*82527734SSukumar Swaminathan if (hba->intr_unclaimed) { 4171*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4172*82527734SSukumar Swaminathan return (DDI_INTR_UNCLAIMED); 4173291a2b48SSukumar Swaminathan } 4174291a2b48SSukumar Swaminathan 4175*82527734SSukumar Swaminathan hba->intr_unclaimed = 1; 4176*82527734SSukumar Swaminathan } else { 4177*82527734SSukumar Swaminathan hba->intr_unclaimed = 0; 4178*82527734SSukumar Swaminathan } 4179*82527734SSukumar Swaminathan 4180*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4181*82527734SSukumar Swaminathan 4182*82527734SSukumar Swaminathan /* Process the interrupt */ 4183*82527734SSukumar Swaminathan emlxs_proc_attention(hba, ha_copy); 4184*82527734SSukumar Swaminathan 4185*82527734SSukumar Swaminathan return (DDI_INTR_CLAIMED); 4186*82527734SSukumar Swaminathan 4187*82527734SSukumar Swaminathan } /* emlxs_sli3_intx_intr() */ 4188*82527734SSukumar Swaminathan 4189*82527734SSukumar Swaminathan 4190*82527734SSukumar Swaminathan /* EMLXS_PORT_LOCK must be held when call this routine */ 4191*82527734SSukumar Swaminathan static uint32_t 4192*82527734SSukumar Swaminathan emlxs_get_attention(emlxs_hba_t *hba, uint32_t msgid) 4193*82527734SSukumar Swaminathan { 4194*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4195*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 4196*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4197*82527734SSukumar Swaminathan uint32_t ha_copy = 0; 4198*82527734SSukumar Swaminathan uint32_t ha_copy2; 4199*82527734SSukumar Swaminathan uint32_t mask = hba->sli.sli3.hc_copy; 4200*82527734SSukumar Swaminathan 4201*82527734SSukumar Swaminathan #ifdef MSI_SUPPORT 4202*82527734SSukumar Swaminathan 4203*82527734SSukumar Swaminathan read_ha_register: 4204*82527734SSukumar Swaminathan 4205*82527734SSukumar Swaminathan /* Check for default MSI interrupt */ 4206*82527734SSukumar Swaminathan if (msgid == 0) { 4207*82527734SSukumar Swaminathan /* Read host attention register to determine interrupt source */ 4208*82527734SSukumar Swaminathan ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 4209*82527734SSukumar Swaminathan 4210*82527734SSukumar Swaminathan /* Filter out MSI non-default attention bits */ 4211*82527734SSukumar Swaminathan ha_copy2 &= ~(hba->intr_cond); 4212*82527734SSukumar Swaminathan } 4213*82527734SSukumar Swaminathan 4214*82527734SSukumar Swaminathan /* Check for polled or fixed type interrupt */ 4215*82527734SSukumar Swaminathan else if (msgid == -1) { 4216*82527734SSukumar Swaminathan /* Read host attention register to determine interrupt source */ 4217*82527734SSukumar Swaminathan ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 4218*82527734SSukumar Swaminathan } 4219*82527734SSukumar Swaminathan 4220*82527734SSukumar Swaminathan /* Otherwise, assume a mapped MSI interrupt */ 4221*82527734SSukumar Swaminathan else { 4222*82527734SSukumar Swaminathan /* Convert MSI msgid to mapped attention bits */ 4223*82527734SSukumar Swaminathan ha_copy2 = hba->intr_map[msgid]; 4224*82527734SSukumar Swaminathan } 4225*82527734SSukumar Swaminathan 4226*82527734SSukumar Swaminathan #else /* !MSI_SUPPORT */ 4227*82527734SSukumar Swaminathan 4228*82527734SSukumar Swaminathan /* Read host attention register to determine interrupt source */ 4229*82527734SSukumar Swaminathan ha_copy2 = READ_CSR_REG(hba, FC_HA_REG(hba)); 4230*82527734SSukumar Swaminathan 4231*82527734SSukumar Swaminathan #endif /* MSI_SUPPORT */ 4232*82527734SSukumar Swaminathan 4233*82527734SSukumar Swaminathan /* Check if Hardware error interrupt is enabled */ 4234*82527734SSukumar Swaminathan if ((ha_copy2 & HA_ERATT) && !(mask & HC_ERINT_ENA)) { 4235*82527734SSukumar Swaminathan ha_copy2 &= ~HA_ERATT; 4236*82527734SSukumar Swaminathan } 4237*82527734SSukumar Swaminathan 4238*82527734SSukumar Swaminathan /* Check if link interrupt is enabled */ 4239*82527734SSukumar Swaminathan if ((ha_copy2 & HA_LATT) && !(mask & HC_LAINT_ENA)) { 4240*82527734SSukumar Swaminathan ha_copy2 &= ~HA_LATT; 4241*82527734SSukumar Swaminathan } 4242*82527734SSukumar Swaminathan 4243*82527734SSukumar Swaminathan /* Check if Mailbox interrupt is enabled */ 4244*82527734SSukumar Swaminathan if ((ha_copy2 & HA_MBATT) && !(mask & HC_MBINT_ENA)) { 4245*82527734SSukumar Swaminathan ha_copy2 &= ~HA_MBATT; 4246*82527734SSukumar Swaminathan } 4247*82527734SSukumar Swaminathan 4248*82527734SSukumar Swaminathan /* Check if ring0 interrupt is enabled */ 4249*82527734SSukumar Swaminathan if ((ha_copy2 & HA_R0ATT) && !(mask & HC_R0INT_ENA)) { 4250*82527734SSukumar Swaminathan ha_copy2 &= ~HA_R0ATT; 4251*82527734SSukumar Swaminathan } 4252*82527734SSukumar Swaminathan 4253*82527734SSukumar Swaminathan /* Check if ring1 interrupt is enabled */ 4254*82527734SSukumar Swaminathan if ((ha_copy2 & HA_R1ATT) && !(mask & HC_R1INT_ENA)) { 4255*82527734SSukumar Swaminathan ha_copy2 &= ~HA_R1ATT; 4256*82527734SSukumar Swaminathan } 4257*82527734SSukumar Swaminathan 4258*82527734SSukumar Swaminathan /* Check if ring2 interrupt is enabled */ 4259*82527734SSukumar Swaminathan if ((ha_copy2 & HA_R2ATT) && !(mask & HC_R2INT_ENA)) { 4260*82527734SSukumar Swaminathan ha_copy2 &= ~HA_R2ATT; 4261*82527734SSukumar Swaminathan } 4262*82527734SSukumar Swaminathan 4263*82527734SSukumar Swaminathan /* Check if ring3 interrupt is enabled */ 4264*82527734SSukumar Swaminathan if ((ha_copy2 & HA_R3ATT) && !(mask & HC_R3INT_ENA)) { 4265*82527734SSukumar Swaminathan ha_copy2 &= ~HA_R3ATT; 4266*82527734SSukumar Swaminathan } 4267291a2b48SSukumar Swaminathan 4268*82527734SSukumar Swaminathan /* Accumulate attention bits */ 4269*82527734SSukumar Swaminathan ha_copy |= ha_copy2; 4270291a2b48SSukumar Swaminathan 4271*82527734SSukumar Swaminathan /* Clear attentions except for error, link, and autoclear(MSIX) */ 4272*82527734SSukumar Swaminathan ha_copy2 &= ~(HA_ERATT | HA_LATT); /* | hba->intr_autoClear */ 4273291a2b48SSukumar Swaminathan 4274*82527734SSukumar Swaminathan if (ha_copy2) { 4275*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), ha_copy2); 4276*82527734SSukumar Swaminathan } 4277291a2b48SSukumar Swaminathan 42784baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 4279*82527734SSukumar Swaminathan /* Access handle validation */ 4280*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 42814baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4282291a2b48SSukumar Swaminathan 4283*82527734SSukumar Swaminathan return (ha_copy); 4284291a2b48SSukumar Swaminathan 4285*82527734SSukumar Swaminathan } /* emlxs_get_attention() */ 4286291a2b48SSukumar Swaminathan 4287291a2b48SSukumar Swaminathan 4288*82527734SSukumar Swaminathan static void 4289*82527734SSukumar Swaminathan emlxs_proc_attention(emlxs_hba_t *hba, uint32_t ha_copy) 4290*82527734SSukumar Swaminathan { 42914baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 4292*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 42934baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 42944baa2c25SSukumar Swaminathan 4295*82527734SSukumar Swaminathan /* ha_copy should be pre-filtered */ 4296291a2b48SSukumar Swaminathan 4297*82527734SSukumar Swaminathan /* 4298*82527734SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 4299*82527734SSukumar Swaminathan * "emlxs_proc_attention: ha_copy=%x", ha_copy); 4300*82527734SSukumar Swaminathan */ 4301291a2b48SSukumar Swaminathan 4302*82527734SSukumar Swaminathan if (hba->state < FC_WARM_START) { 4303*82527734SSukumar Swaminathan return; 4304291a2b48SSukumar Swaminathan } 4305291a2b48SSukumar Swaminathan 4306*82527734SSukumar Swaminathan if (!ha_copy) { 4307*82527734SSukumar Swaminathan return; 4308*82527734SSukumar Swaminathan } 4309291a2b48SSukumar Swaminathan 4310*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 4311*82527734SSukumar Swaminathan (void) READ_SBUS_CSR_REG(hba, FC_SHS_REG(hba)); 4312*82527734SSukumar Swaminathan } 4313291a2b48SSukumar Swaminathan 4314*82527734SSukumar Swaminathan /* Adapter error */ 4315*82527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 4316*82527734SSukumar Swaminathan HBASTATS.IntrEvent[6]++; 4317*82527734SSukumar Swaminathan emlxs_handle_ff_error(hba); 4318*82527734SSukumar Swaminathan return; 4319*82527734SSukumar Swaminathan } 4320291a2b48SSukumar Swaminathan 4321*82527734SSukumar Swaminathan /* Mailbox interrupt */ 4322*82527734SSukumar Swaminathan if (ha_copy & HA_MBATT) { 4323*82527734SSukumar Swaminathan HBASTATS.IntrEvent[5]++; 4324*82527734SSukumar Swaminathan (void) emlxs_handle_mb_event(hba); 4325*82527734SSukumar Swaminathan } 4326291a2b48SSukumar Swaminathan 4327*82527734SSukumar Swaminathan /* Link Attention interrupt */ 4328*82527734SSukumar Swaminathan if (ha_copy & HA_LATT) { 4329*82527734SSukumar Swaminathan HBASTATS.IntrEvent[4]++; 4330*82527734SSukumar Swaminathan emlxs_sli3_handle_link_event(hba); 4331*82527734SSukumar Swaminathan } 4332291a2b48SSukumar Swaminathan 4333*82527734SSukumar Swaminathan /* event on ring 0 - FCP Ring */ 4334*82527734SSukumar Swaminathan if (ha_copy & HA_R0ATT) { 4335*82527734SSukumar Swaminathan HBASTATS.IntrEvent[0]++; 4336*82527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 0, ha_copy); 4337*82527734SSukumar Swaminathan } 4338291a2b48SSukumar Swaminathan 4339*82527734SSukumar Swaminathan /* event on ring 1 - IP Ring */ 4340*82527734SSukumar Swaminathan if (ha_copy & HA_R1ATT) { 4341*82527734SSukumar Swaminathan HBASTATS.IntrEvent[1]++; 4342*82527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 1, ha_copy); 4343*82527734SSukumar Swaminathan } 4344291a2b48SSukumar Swaminathan 4345*82527734SSukumar Swaminathan /* event on ring 2 - ELS Ring */ 4346*82527734SSukumar Swaminathan if (ha_copy & HA_R2ATT) { 4347*82527734SSukumar Swaminathan HBASTATS.IntrEvent[2]++; 4348*82527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 2, ha_copy); 4349*82527734SSukumar Swaminathan } 4350291a2b48SSukumar Swaminathan 4351*82527734SSukumar Swaminathan /* event on ring 3 - CT Ring */ 4352*82527734SSukumar Swaminathan if (ha_copy & HA_R3ATT) { 4353*82527734SSukumar Swaminathan HBASTATS.IntrEvent[3]++; 4354*82527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(hba, 3, ha_copy); 4355*82527734SSukumar Swaminathan } 4356291a2b48SSukumar Swaminathan 4357*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 4358*82527734SSukumar Swaminathan WRITE_SBUS_CSR_REG(hba, FC_SHS_REG(hba), SBUS_STAT_IP); 4359291a2b48SSukumar Swaminathan } 4360291a2b48SSukumar Swaminathan 4361*82527734SSukumar Swaminathan /* Set heartbeat flag to show activity */ 4362*82527734SSukumar Swaminathan hba->heartbeat_flag = 1; 4363291a2b48SSukumar Swaminathan 4364*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4365*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 4366*82527734SSukumar Swaminathan /* Access handle validation */ 4367*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.sbus_csr_handle); 4368291a2b48SSukumar Swaminathan } 4369*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4370291a2b48SSukumar Swaminathan 4371*82527734SSukumar Swaminathan return; 4372291a2b48SSukumar Swaminathan 4373*82527734SSukumar Swaminathan } /* emlxs_proc_attention() */ 4374291a2b48SSukumar Swaminathan 4375291a2b48SSukumar Swaminathan 4376*82527734SSukumar Swaminathan /* 4377*82527734SSukumar Swaminathan * emlxs_handle_ff_error() 4378*82527734SSukumar Swaminathan * 4379*82527734SSukumar Swaminathan * Description: Processes a FireFly error 4380*82527734SSukumar Swaminathan * Runs at Interrupt level 4381*82527734SSukumar Swaminathan */ 4382*82527734SSukumar Swaminathan static void 4383*82527734SSukumar Swaminathan emlxs_handle_ff_error(emlxs_hba_t *hba) 4384*82527734SSukumar Swaminathan { 4385*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 4386*82527734SSukumar Swaminathan uint32_t status; 4387*82527734SSukumar Swaminathan uint32_t status1; 4388*82527734SSukumar Swaminathan uint32_t status2; 4389*82527734SSukumar Swaminathan int i = 0; 4390291a2b48SSukumar Swaminathan 4391*82527734SSukumar Swaminathan /* do what needs to be done, get error from STATUS REGISTER */ 4392*82527734SSukumar Swaminathan status = READ_CSR_REG(hba, FC_HS_REG(hba)); 4393291a2b48SSukumar Swaminathan 4394*82527734SSukumar Swaminathan /* Clear Chip error bit */ 4395*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_ERATT); 4396291a2b48SSukumar Swaminathan 4397*82527734SSukumar Swaminathan /* If HS_FFER1 is set, then wait until the HS_FFER1 bit clears */ 4398*82527734SSukumar Swaminathan if (status & HS_FFER1) { 4399*82527734SSukumar Swaminathan 4400*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4401*82527734SSukumar Swaminathan "HS_FFER1 received"); 4402*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 4403*82527734SSukumar Swaminathan (void) emlxs_offline(hba); 4404*82527734SSukumar Swaminathan while ((status & HS_FFER1) && (i < 300)) { 4405*82527734SSukumar Swaminathan status = 4406*82527734SSukumar Swaminathan READ_CSR_REG(hba, FC_HS_REG(hba)); 4407*82527734SSukumar Swaminathan DELAYMS(1000); 4408*82527734SSukumar Swaminathan i++; 4409291a2b48SSukumar Swaminathan } 4410*82527734SSukumar Swaminathan } 4411291a2b48SSukumar Swaminathan 4412*82527734SSukumar Swaminathan if (i == 300) { 4413*82527734SSukumar Swaminathan /* 5 minutes is up, shutdown HBA */ 4414*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4415*82527734SSukumar Swaminathan "HS_FFER1 clear timeout"); 4416291a2b48SSukumar Swaminathan 4417*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 4418*82527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); 4419291a2b48SSukumar Swaminathan 4420*82527734SSukumar Swaminathan goto done; 4421291a2b48SSukumar Swaminathan } 4422291a2b48SSukumar Swaminathan 4423*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4424*82527734SSukumar Swaminathan "HS_FFER1 cleared"); 4425*82527734SSukumar Swaminathan 4426*82527734SSukumar Swaminathan if (status & HS_OVERTEMP) { 4427*82527734SSukumar Swaminathan status1 = 4428*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 4429*82527734SSukumar Swaminathan ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xb0)); 4430*82527734SSukumar Swaminathan 4431*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4432*82527734SSukumar Swaminathan "Maximum adapter temperature exceeded (%d �C).", status1); 4433*82527734SSukumar Swaminathan 4434*82527734SSukumar Swaminathan hba->temperature = status1; 4435*82527734SSukumar Swaminathan hba->flag |= FC_OVERTEMP_EVENT; 4436*82527734SSukumar Swaminathan 4437*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 4438*82527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, 4439*82527734SSukumar Swaminathan NULL, NULL); 4440*82527734SSukumar Swaminathan 4441*82527734SSukumar Swaminathan } else { 4442*82527734SSukumar Swaminathan status1 = 4443*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 4444*82527734SSukumar Swaminathan ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xa8)); 4445*82527734SSukumar Swaminathan status2 = 4446*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, 4447*82527734SSukumar Swaminathan ((volatile uint8_t *)hba->sli.sli3.slim_addr + 0xac)); 4448*82527734SSukumar Swaminathan 4449*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_hardware_error_msg, 4450*82527734SSukumar Swaminathan "Host Error Attention: " 4451*82527734SSukumar Swaminathan "status=0x%x status1=0x%x status2=0x%x", 4452*82527734SSukumar Swaminathan status, status1, status2); 4453*82527734SSukumar Swaminathan 4454*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 4455291a2b48SSukumar Swaminathan 4456*82527734SSukumar Swaminathan if (status & HS_FFER6) { 4457*82527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_restart_thread, 4458*82527734SSukumar Swaminathan NULL, NULL); 4459*82527734SSukumar Swaminathan } else { 4460*82527734SSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, 4461*82527734SSukumar Swaminathan NULL, NULL); 4462291a2b48SSukumar Swaminathan } 4463291a2b48SSukumar Swaminathan } 4464291a2b48SSukumar Swaminathan 4465*82527734SSukumar Swaminathan done: 4466*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4467*82527734SSukumar Swaminathan /* Access handle validation */ 4468*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 4469*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4470*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4471291a2b48SSukumar Swaminathan 4472*82527734SSukumar Swaminathan return; 4473291a2b48SSukumar Swaminathan 4474*82527734SSukumar Swaminathan } /* emlxs_handle_ff_error() */ 4475291a2b48SSukumar Swaminathan 4476291a2b48SSukumar Swaminathan 4477*82527734SSukumar Swaminathan /* 4478*82527734SSukumar Swaminathan * emlxs_sli3_handle_link_event() 4479*82527734SSukumar Swaminathan * 4480*82527734SSukumar Swaminathan * Description: Process a Link Attention. 4481*82527734SSukumar Swaminathan */ 4482*82527734SSukumar Swaminathan static void 4483*82527734SSukumar Swaminathan emlxs_sli3_handle_link_event(emlxs_hba_t *hba) 4484*82527734SSukumar Swaminathan { 4485*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 4486*82527734SSukumar Swaminathan MAILBOXQ *mbq; 4487*82527734SSukumar Swaminathan int rc; 4488291a2b48SSukumar Swaminathan 4489*82527734SSukumar Swaminathan HBASTATS.LinkEvent++; 4490291a2b48SSukumar Swaminathan 4491*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_event_msg, "event=%x", 4492*82527734SSukumar Swaminathan HBASTATS.LinkEvent); 4493291a2b48SSukumar Swaminathan 4494*82527734SSukumar Swaminathan /* Make sure link is declared down */ 4495*82527734SSukumar Swaminathan emlxs_linkdown(hba); 4496291a2b48SSukumar Swaminathan 4497291a2b48SSukumar Swaminathan 4498*82527734SSukumar Swaminathan /* Get a buffer which will be used for mailbox commands */ 4499*82527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 4500*82527734SSukumar Swaminathan /* Get link attention message */ 4501*82527734SSukumar Swaminathan if (emlxs_mb_read_la(hba, mbq) == 0) { 4502*82527734SSukumar Swaminathan rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, 4503*82527734SSukumar Swaminathan MBX_NOWAIT, 0); 4504*82527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 4505*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, 4506*82527734SSukumar Swaminathan (uint8_t *)mbq); 4507*82527734SSukumar Swaminathan } 4508291a2b48SSukumar Swaminathan 4509*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4510291a2b48SSukumar Swaminathan 4511291a2b48SSukumar Swaminathan 4512*82527734SSukumar Swaminathan /* 4513*82527734SSukumar Swaminathan * Clear Link Attention in HA REG 4514*82527734SSukumar Swaminathan */ 4515*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), HA_LATT); 4516291a2b48SSukumar Swaminathan 4517*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4518*82527734SSukumar Swaminathan /* Access handle validation */ 4519*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4520*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4521291a2b48SSukumar Swaminathan 4522*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4523*82527734SSukumar Swaminathan } else { 4524*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 4525291a2b48SSukumar Swaminathan } 4526291a2b48SSukumar Swaminathan } 4527291a2b48SSukumar Swaminathan 4528*82527734SSukumar Swaminathan } /* emlxs_sli3_handle_link_event() */ 4529291a2b48SSukumar Swaminathan 4530291a2b48SSukumar Swaminathan 4531*82527734SSukumar Swaminathan /* 4532*82527734SSukumar Swaminathan * emlxs_sli3_handle_ring_event() 4533*82527734SSukumar Swaminathan * 4534*82527734SSukumar Swaminathan * Description: Process a Ring Attention. 4535*82527734SSukumar Swaminathan */ 4536291a2b48SSukumar Swaminathan static void 4537*82527734SSukumar Swaminathan emlxs_sli3_handle_ring_event(emlxs_hba_t *hba, int32_t ring_no, 4538*82527734SSukumar Swaminathan uint32_t ha_copy) 4539291a2b48SSukumar Swaminathan { 4540*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 4541*82527734SSukumar Swaminathan SLIM2 *slim2p = (SLIM2 *)hba->sli.sli3.slim2.virt; 4542*82527734SSukumar Swaminathan CHANNEL *cp; 4543*82527734SSukumar Swaminathan RING *rp; 4544*82527734SSukumar Swaminathan IOCB *entry; 4545*82527734SSukumar Swaminathan IOCBQ *iocbq; 4546*82527734SSukumar Swaminathan IOCBQ local_iocbq; 4547*82527734SSukumar Swaminathan PGP *pgp; 4548*82527734SSukumar Swaminathan uint32_t count; 4549*82527734SSukumar Swaminathan volatile uint32_t chipatt; 4550*82527734SSukumar Swaminathan void *ioa2; 4551*82527734SSukumar Swaminathan uint32_t reg; 4552*82527734SSukumar Swaminathan uint32_t channel_no; 4553291a2b48SSukumar Swaminathan off_t offset; 4554*82527734SSukumar Swaminathan IOCBQ *rsp_head = NULL; 4555*82527734SSukumar Swaminathan IOCBQ *rsp_tail = NULL; 4556*82527734SSukumar Swaminathan emlxs_buf_t *sbp = NULL; 4557291a2b48SSukumar Swaminathan 4558*82527734SSukumar Swaminathan count = 0; 4559*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ring_no]; 4560*82527734SSukumar Swaminathan cp = rp->channelp; 4561*82527734SSukumar Swaminathan channel_no = cp->channelno; 4562291a2b48SSukumar Swaminathan 4563*82527734SSukumar Swaminathan /* 4564*82527734SSukumar Swaminathan * Isolate this ring's host attention bits 4565*82527734SSukumar Swaminathan * This makes all ring attention bits equal 4566*82527734SSukumar Swaminathan * to Ring0 attention bits 4567*82527734SSukumar Swaminathan */ 4568*82527734SSukumar Swaminathan reg = (ha_copy >> (ring_no * 4)) & 0x0f; 4569291a2b48SSukumar Swaminathan 4570*82527734SSukumar Swaminathan /* 4571*82527734SSukumar Swaminathan * Gather iocb entries off response ring. 4572*82527734SSukumar Swaminathan * Ensure entry is owned by the host. 4573*82527734SSukumar Swaminathan */ 4574*82527734SSukumar Swaminathan pgp = (PGP *)&slim2p->mbx.us.s2.port[ring_no]; 4575*82527734SSukumar Swaminathan offset = 4576*82527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) - 4577*82527734SSukumar Swaminathan (uint64_t)((unsigned long)slim2p)); 4578*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 4579*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 4580*82527734SSukumar Swaminathan rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx); 4581291a2b48SSukumar Swaminathan 4582*82527734SSukumar Swaminathan /* While ring is not empty */ 4583*82527734SSukumar Swaminathan while (rp->fc_rspidx != rp->fc_port_rspidx) { 4584*82527734SSukumar Swaminathan HBASTATS.IocbReceived[channel_no]++; 4585291a2b48SSukumar Swaminathan 4586*82527734SSukumar Swaminathan /* Get the next response ring iocb */ 4587*82527734SSukumar Swaminathan entry = 4588*82527734SSukumar Swaminathan (IOCB *)(((char *)rp->fc_rspringaddr + 4589*82527734SSukumar Swaminathan (rp->fc_rspidx * hba->sli.sli3.iocb_rsp_size))); 4590291a2b48SSukumar Swaminathan 4591*82527734SSukumar Swaminathan /* DMA sync the response ring iocb for the adapter */ 4592*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)entry) 4593*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)slim2p)); 4594*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4595*82527734SSukumar Swaminathan hba->sli.sli3.iocb_rsp_size, DDI_DMA_SYNC_FORKERNEL); 4596291a2b48SSukumar Swaminathan 4597*82527734SSukumar Swaminathan count++; 4598291a2b48SSukumar Swaminathan 4599*82527734SSukumar Swaminathan /* Copy word6 and word7 to local iocb for now */ 4600*82527734SSukumar Swaminathan iocbq = &local_iocbq; 4601291a2b48SSukumar Swaminathan 4602*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry + (sizeof (uint32_t) * 6), 4603*82527734SSukumar Swaminathan (uint8_t *)iocbq + (sizeof (uint32_t) * 6), 4604*82527734SSukumar Swaminathan (sizeof (uint32_t) * 2)); 4605291a2b48SSukumar Swaminathan 4606*82527734SSukumar Swaminathan /* when LE is not set, entire Command has not been received */ 4607*82527734SSukumar Swaminathan if (!iocbq->iocb.ULPLE) { 4608*82527734SSukumar Swaminathan /* This should never happen */ 4609*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_error_msg, 4610*82527734SSukumar Swaminathan "ulpLE is not set. " 4611*82527734SSukumar Swaminathan "ring=%d iotag=%x cmd=%x status=%x", 4612*82527734SSukumar Swaminathan channel_no, iocbq->iocb.ULPIOTAG, 4613*82527734SSukumar Swaminathan iocbq->iocb.ULPCOMMAND, iocbq->iocb.ULPSTATUS); 4614291a2b48SSukumar Swaminathan 4615*82527734SSukumar Swaminathan goto next; 4616291a2b48SSukumar Swaminathan } 4617291a2b48SSukumar Swaminathan 4618*82527734SSukumar Swaminathan switch (iocbq->iocb.ULPCOMMAND) { 4619*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 4620*82527734SSukumar Swaminathan case CMD_CLOSE_XRI_CX: 4621*82527734SSukumar Swaminathan case CMD_CLOSE_XRI_CN: 4622*82527734SSukumar Swaminathan case CMD_ABORT_XRI_CX: 4623*82527734SSukumar Swaminathan if (!port->tgt_mode) { 4624*82527734SSukumar Swaminathan sbp = NULL; 4625*82527734SSukumar Swaminathan break; 4626*82527734SSukumar Swaminathan } 4627291a2b48SSukumar Swaminathan 4628*82527734SSukumar Swaminathan sbp = 4629*82527734SSukumar Swaminathan emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0); 4630*82527734SSukumar Swaminathan break; 4631*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4632291a2b48SSukumar Swaminathan 4633*82527734SSukumar Swaminathan /* Ring 0 registered commands */ 4634*82527734SSukumar Swaminathan case CMD_FCP_ICMND_CR: 4635*82527734SSukumar Swaminathan case CMD_FCP_ICMND_CX: 4636*82527734SSukumar Swaminathan case CMD_FCP_IREAD_CR: 4637*82527734SSukumar Swaminathan case CMD_FCP_IREAD_CX: 4638*82527734SSukumar Swaminathan case CMD_FCP_IWRITE_CR: 4639*82527734SSukumar Swaminathan case CMD_FCP_IWRITE_CX: 4640*82527734SSukumar Swaminathan case CMD_FCP_ICMND64_CR: 4641*82527734SSukumar Swaminathan case CMD_FCP_ICMND64_CX: 4642*82527734SSukumar Swaminathan case CMD_FCP_IREAD64_CR: 4643*82527734SSukumar Swaminathan case CMD_FCP_IREAD64_CX: 4644*82527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CR: 4645*82527734SSukumar Swaminathan case CMD_FCP_IWRITE64_CX: 4646*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 4647*82527734SSukumar Swaminathan case CMD_FCP_TSEND_CX: 4648*82527734SSukumar Swaminathan case CMD_FCP_TSEND64_CX: 4649*82527734SSukumar Swaminathan case CMD_FCP_TRECEIVE_CX: 4650*82527734SSukumar Swaminathan case CMD_FCP_TRECEIVE64_CX: 4651*82527734SSukumar Swaminathan case CMD_FCP_TRSP_CX: 4652*82527734SSukumar Swaminathan case CMD_FCP_TRSP64_CX: 4653*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4654291a2b48SSukumar Swaminathan 4655*82527734SSukumar Swaminathan /* Ring 1 registered commands */ 4656*82527734SSukumar Swaminathan case CMD_XMIT_BCAST_CN: 4657*82527734SSukumar Swaminathan case CMD_XMIT_BCAST_CX: 4658*82527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE_CX: 4659*82527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE_CR: 4660*82527734SSukumar Swaminathan case CMD_XMIT_BCAST64_CN: 4661*82527734SSukumar Swaminathan case CMD_XMIT_BCAST64_CX: 4662*82527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE64_CX: 4663*82527734SSukumar Swaminathan case CMD_XMIT_SEQUENCE64_CR: 4664*82527734SSukumar Swaminathan case CMD_CREATE_XRI_CR: 4665*82527734SSukumar Swaminathan case CMD_CREATE_XRI_CX: 4666291a2b48SSukumar Swaminathan 4667*82527734SSukumar Swaminathan /* Ring 2 registered commands */ 4668*82527734SSukumar Swaminathan case CMD_ELS_REQUEST_CR: 4669*82527734SSukumar Swaminathan case CMD_ELS_REQUEST_CX: 4670*82527734SSukumar Swaminathan case CMD_XMIT_ELS_RSP_CX: 4671*82527734SSukumar Swaminathan case CMD_ELS_REQUEST64_CR: 4672*82527734SSukumar Swaminathan case CMD_ELS_REQUEST64_CX: 4673*82527734SSukumar Swaminathan case CMD_XMIT_ELS_RSP64_CX: 4674291a2b48SSukumar Swaminathan 4675*82527734SSukumar Swaminathan /* Ring 3 registered commands */ 4676*82527734SSukumar Swaminathan case CMD_GEN_REQUEST64_CR: 4677*82527734SSukumar Swaminathan case CMD_GEN_REQUEST64_CX: 4678291a2b48SSukumar Swaminathan 4679*82527734SSukumar Swaminathan sbp = 4680*82527734SSukumar Swaminathan emlxs_unregister_pkt(cp, iocbq->iocb.ULPIOTAG, 0); 4681*82527734SSukumar Swaminathan break; 4682291a2b48SSukumar Swaminathan 4683*82527734SSukumar Swaminathan default: 4684*82527734SSukumar Swaminathan sbp = NULL; 4685*82527734SSukumar Swaminathan } 4686291a2b48SSukumar Swaminathan 4687*82527734SSukumar Swaminathan /* If packet is stale, then drop it. */ 4688*82527734SSukumar Swaminathan if (sbp == STALE_PACKET) { 4689*82527734SSukumar Swaminathan cp->hbaCmplCmd_sbp++; 4690*82527734SSukumar Swaminathan /* Copy entry to the local iocbq */ 4691*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry, 4692*82527734SSukumar Swaminathan (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4693291a2b48SSukumar Swaminathan 4694*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg, 4695*82527734SSukumar Swaminathan "channelno=%d iocb=%p cmd=%x status=%x " 4696*82527734SSukumar Swaminathan "error=%x iotag=%x context=%x info=%x", 4697*82527734SSukumar Swaminathan channel_no, iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND, 4698*82527734SSukumar Swaminathan iocbq->iocb.ULPSTATUS, 4699*82527734SSukumar Swaminathan (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError, 4700*82527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPIOTAG, 4701*82527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPCONTEXT, 4702*82527734SSukumar Swaminathan (uint8_t)iocbq->iocb.ULPRSVDBYTE); 4703291a2b48SSukumar Swaminathan 4704*82527734SSukumar Swaminathan goto next; 4705291a2b48SSukumar Swaminathan } 4706291a2b48SSukumar Swaminathan 4707*82527734SSukumar Swaminathan /* 4708*82527734SSukumar Swaminathan * If a packet was found, then queue the packet's 4709*82527734SSukumar Swaminathan * iocb for deferred processing 4710*82527734SSukumar Swaminathan */ 4711*82527734SSukumar Swaminathan else if (sbp) { 4712*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 4713*82527734SSukumar Swaminathan fct_cmd_t *fct_cmd; 4714*82527734SSukumar Swaminathan emlxs_buf_t *cmd_sbp; 4715291a2b48SSukumar Swaminathan 4716*82527734SSukumar Swaminathan fct_cmd = sbp->fct_cmd; 4717*82527734SSukumar Swaminathan if (fct_cmd) { 4718*82527734SSukumar Swaminathan cmd_sbp = 4719*82527734SSukumar Swaminathan (emlxs_buf_t *)fct_cmd->cmd_fca_private; 4720*82527734SSukumar Swaminathan mutex_enter(&cmd_sbp->fct_mtx); 4721*82527734SSukumar Swaminathan EMLXS_FCT_STATE_CHG(fct_cmd, cmd_sbp, 4722*82527734SSukumar Swaminathan EMLXS_FCT_IOCB_COMPLETE); 4723*82527734SSukumar Swaminathan mutex_exit(&cmd_sbp->fct_mtx); 4724*82527734SSukumar Swaminathan } 4725*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4726*82527734SSukumar Swaminathan cp->hbaCmplCmd_sbp++; 4727*82527734SSukumar Swaminathan atomic_add_32(&hba->io_active, -1); 4728291a2b48SSukumar Swaminathan 4729*82527734SSukumar Swaminathan /* Copy entry to sbp's iocbq */ 4730*82527734SSukumar Swaminathan iocbq = &sbp->iocbq; 4731*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry, 4732*82527734SSukumar Swaminathan (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4733291a2b48SSukumar Swaminathan 4734*82527734SSukumar Swaminathan iocbq->next = NULL; 4735291a2b48SSukumar Swaminathan 4736*82527734SSukumar Swaminathan /* 4737*82527734SSukumar Swaminathan * If this is NOT a polled command completion 4738*82527734SSukumar Swaminathan * or a driver allocated pkt, then defer pkt 4739*82527734SSukumar Swaminathan * completion. 4740*82527734SSukumar Swaminathan */ 4741*82527734SSukumar Swaminathan if (!(sbp->pkt_flags & 4742*82527734SSukumar Swaminathan (PACKET_POLLED | PACKET_ALLOCATED))) { 4743*82527734SSukumar Swaminathan /* Add the IOCB to the local list */ 4744*82527734SSukumar Swaminathan if (!rsp_head) { 4745*82527734SSukumar Swaminathan rsp_head = iocbq; 4746*82527734SSukumar Swaminathan } else { 4747*82527734SSukumar Swaminathan rsp_tail->next = iocbq; 4748*82527734SSukumar Swaminathan } 4749291a2b48SSukumar Swaminathan 4750*82527734SSukumar Swaminathan rsp_tail = iocbq; 4751291a2b48SSukumar Swaminathan 4752*82527734SSukumar Swaminathan goto next; 4753*82527734SSukumar Swaminathan } 4754*82527734SSukumar Swaminathan } else { 4755*82527734SSukumar Swaminathan cp->hbaCmplCmd++; 4756*82527734SSukumar Swaminathan /* Copy entry to the local iocbq */ 4757*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)entry, 4758*82527734SSukumar Swaminathan (uint8_t *)iocbq, hba->sli.sli3.iocb_rsp_size); 4759291a2b48SSukumar Swaminathan 4760*82527734SSukumar Swaminathan iocbq->next = NULL; 4761*82527734SSukumar Swaminathan iocbq->bp = NULL; 4762*82527734SSukumar Swaminathan iocbq->port = &PPORT; 4763*82527734SSukumar Swaminathan iocbq->channel = cp; 4764*82527734SSukumar Swaminathan iocbq->node = NULL; 4765*82527734SSukumar Swaminathan iocbq->sbp = NULL; 4766*82527734SSukumar Swaminathan iocbq->flag = 0; 4767*82527734SSukumar Swaminathan } 4768291a2b48SSukumar Swaminathan 4769*82527734SSukumar Swaminathan /* process the channel event now */ 4770*82527734SSukumar Swaminathan emlxs_proc_channel_event(hba, cp, iocbq); 4771291a2b48SSukumar Swaminathan 4772*82527734SSukumar Swaminathan next: 4773*82527734SSukumar Swaminathan /* Increment the driver's local response get index */ 4774*82527734SSukumar Swaminathan if (++rp->fc_rspidx >= rp->fc_numRiocb) { 4775*82527734SSukumar Swaminathan rp->fc_rspidx = 0; 4776*82527734SSukumar Swaminathan } 4777291a2b48SSukumar Swaminathan 4778*82527734SSukumar Swaminathan } /* while (TRUE) */ 4779291a2b48SSukumar Swaminathan 4780*82527734SSukumar Swaminathan if (rsp_head) { 4781*82527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 4782*82527734SSukumar Swaminathan if (cp->rsp_head == NULL) { 4783*82527734SSukumar Swaminathan cp->rsp_head = rsp_head; 4784*82527734SSukumar Swaminathan cp->rsp_tail = rsp_tail; 4785*82527734SSukumar Swaminathan } else { 4786*82527734SSukumar Swaminathan cp->rsp_tail->next = rsp_head; 4787*82527734SSukumar Swaminathan cp->rsp_tail = rsp_tail; 4788*82527734SSukumar Swaminathan } 4789*82527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 4790291a2b48SSukumar Swaminathan 4791*82527734SSukumar Swaminathan emlxs_thread_trigger2(&cp->intr_thread, emlxs_proc_channel, cp); 4792*82527734SSukumar Swaminathan } 4793291a2b48SSukumar Swaminathan 4794*82527734SSukumar Swaminathan /* Check if at least one response entry was processed */ 4795*82527734SSukumar Swaminathan if (count) { 4796*82527734SSukumar Swaminathan /* Update response get index for the adapter */ 4797*82527734SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 4798*82527734SSukumar Swaminathan slim2p->mbx.us.s2.host[channel_no].rspGetInx 4799*82527734SSukumar Swaminathan = BE_SWAP32(rp->fc_rspidx); 4800291a2b48SSukumar Swaminathan 4801*82527734SSukumar Swaminathan /* DMA sync the index for the adapter */ 4802*82527734SSukumar Swaminathan offset = (off_t) 4803*82527734SSukumar Swaminathan ((uint64_t)((unsigned long)&(slim2p->mbx.us.s2. 4804*82527734SSukumar Swaminathan host[channel_no].rspGetInx)) 4805*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)slim2p)); 4806*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 4807*82527734SSukumar Swaminathan offset, 4, DDI_DMA_SYNC_FORDEV); 4808*82527734SSukumar Swaminathan } else { 4809*82527734SSukumar Swaminathan ioa2 = 4810*82527734SSukumar Swaminathan (void *)((char *)hba->sli.sli3.slim_addr + 4811*82527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset + (((channel_no * 2) + 4812*82527734SSukumar Swaminathan 1) * sizeof (uint32_t))); 4813*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, 4814*82527734SSukumar Swaminathan rp->fc_rspidx); 4815*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4816*82527734SSukumar Swaminathan /* Access handle validation */ 4817*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, 4818*82527734SSukumar Swaminathan hba->sli.sli3.slim_acc_handle); 4819*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4820291a2b48SSukumar Swaminathan } 4821291a2b48SSukumar Swaminathan 4822*82527734SSukumar Swaminathan if (reg & HA_R0RE_REQ) { 4823*82527734SSukumar Swaminathan /* HBASTATS.chipRingFree++; */ 4824291a2b48SSukumar Swaminathan 4825*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 4826291a2b48SSukumar Swaminathan 4827*82527734SSukumar Swaminathan /* Tell the adapter we serviced the ring */ 4828*82527734SSukumar Swaminathan chipatt = ((CA_R0ATT | CA_R0RE_RSP) << 4829*82527734SSukumar Swaminathan (channel_no * 4)); 4830*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), chipatt); 4831291a2b48SSukumar Swaminathan 4832*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 4833*82527734SSukumar Swaminathan /* Access handle validation */ 4834*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 4835*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 4836*82527734SSukumar Swaminathan 4837*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 4838291a2b48SSukumar Swaminathan } 4839*82527734SSukumar Swaminathan } 4840291a2b48SSukumar Swaminathan 4841*82527734SSukumar Swaminathan if ((reg & HA_R0CE_RSP) || hba->channel_tx_count) { 4842*82527734SSukumar Swaminathan /* HBASTATS.hostRingFree++; */ 4843291a2b48SSukumar Swaminathan 4844*82527734SSukumar Swaminathan /* Cmd ring may be available. Try sending more iocbs */ 4845*82527734SSukumar Swaminathan emlxs_sli3_issue_iocb_cmd(hba, cp, 0); 4846291a2b48SSukumar Swaminathan } 4847291a2b48SSukumar Swaminathan 4848*82527734SSukumar Swaminathan /* HBASTATS.ringEvent++; */ 4849291a2b48SSukumar Swaminathan 4850*82527734SSukumar Swaminathan return; 4851291a2b48SSukumar Swaminathan 4852*82527734SSukumar Swaminathan } /* emlxs_sli3_handle_ring_event() */ 4853291a2b48SSukumar Swaminathan 4854291a2b48SSukumar Swaminathan 4855*82527734SSukumar Swaminathan extern int 4856*82527734SSukumar Swaminathan emlxs_handle_rcv_seq(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 4857*82527734SSukumar Swaminathan { 4858*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 4859*82527734SSukumar Swaminathan IOCB *iocb; 4860*82527734SSukumar Swaminathan RING *rp; 4861*82527734SSukumar Swaminathan MATCHMAP *mp = NULL; 4862*82527734SSukumar Swaminathan uint64_t bdeAddr; 4863*82527734SSukumar Swaminathan uint32_t vpi = 0; 4864*82527734SSukumar Swaminathan uint32_t channelno; 4865*82527734SSukumar Swaminathan uint32_t size = 0; 4866*82527734SSukumar Swaminathan uint32_t *RcvError; 4867*82527734SSukumar Swaminathan uint32_t *RcvDropped; 4868*82527734SSukumar Swaminathan uint32_t *UbPosted; 4869*82527734SSukumar Swaminathan emlxs_msg_t *dropped_msg; 4870*82527734SSukumar Swaminathan char error_str[64]; 4871*82527734SSukumar Swaminathan uint32_t buf_type; 4872*82527734SSukumar Swaminathan uint32_t *word; 4873*82527734SSukumar Swaminathan uint32_t hbq_id; 4874291a2b48SSukumar Swaminathan 4875*82527734SSukumar Swaminathan channelno = cp->channelno; 4876*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[channelno]; 4877291a2b48SSukumar Swaminathan 4878*82527734SSukumar Swaminathan iocb = &iocbq->iocb; 4879*82527734SSukumar Swaminathan word = (uint32_t *)iocb; 4880291a2b48SSukumar Swaminathan 4881*82527734SSukumar Swaminathan switch (channelno) { 4882*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 4883*82527734SSukumar Swaminathan case FC_FCT_RING: 4884*82527734SSukumar Swaminathan HBASTATS.FctRingEvent++; 4885*82527734SSukumar Swaminathan RcvError = &HBASTATS.FctRingError; 4886*82527734SSukumar Swaminathan RcvDropped = &HBASTATS.FctRingDropped; 4887*82527734SSukumar Swaminathan UbPosted = &HBASTATS.FctUbPosted; 4888*82527734SSukumar Swaminathan dropped_msg = &emlxs_fct_detail_msg; 4889*82527734SSukumar Swaminathan buf_type = MEM_FCTBUF; 4890*82527734SSukumar Swaminathan break; 4891*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 4892291a2b48SSukumar Swaminathan 4893*82527734SSukumar Swaminathan case FC_IP_RING: 4894*82527734SSukumar Swaminathan HBASTATS.IpRcvEvent++; 4895*82527734SSukumar Swaminathan RcvError = &HBASTATS.IpDropped; 4896*82527734SSukumar Swaminathan RcvDropped = &HBASTATS.IpDropped; 4897*82527734SSukumar Swaminathan UbPosted = &HBASTATS.IpUbPosted; 4898*82527734SSukumar Swaminathan dropped_msg = &emlxs_unsol_ip_dropped_msg; 4899*82527734SSukumar Swaminathan buf_type = MEM_IPBUF; 4900*82527734SSukumar Swaminathan break; 4901291a2b48SSukumar Swaminathan 4902*82527734SSukumar Swaminathan case FC_ELS_RING: 4903*82527734SSukumar Swaminathan HBASTATS.ElsRcvEvent++; 4904*82527734SSukumar Swaminathan RcvError = &HBASTATS.ElsRcvError; 4905*82527734SSukumar Swaminathan RcvDropped = &HBASTATS.ElsRcvDropped; 4906*82527734SSukumar Swaminathan UbPosted = &HBASTATS.ElsUbPosted; 4907*82527734SSukumar Swaminathan dropped_msg = &emlxs_unsol_els_dropped_msg; 4908*82527734SSukumar Swaminathan buf_type = MEM_ELSBUF; 4909*82527734SSukumar Swaminathan break; 4910*82527734SSukumar Swaminathan 4911*82527734SSukumar Swaminathan case FC_CT_RING: 4912*82527734SSukumar Swaminathan HBASTATS.CtRcvEvent++; 4913*82527734SSukumar Swaminathan RcvError = &HBASTATS.CtRcvError; 4914*82527734SSukumar Swaminathan RcvDropped = &HBASTATS.CtRcvDropped; 4915*82527734SSukumar Swaminathan UbPosted = &HBASTATS.CtUbPosted; 4916*82527734SSukumar Swaminathan dropped_msg = &emlxs_unsol_ct_dropped_msg; 4917*82527734SSukumar Swaminathan buf_type = MEM_CTBUF; 4918*82527734SSukumar Swaminathan break; 4919*82527734SSukumar Swaminathan 4920*82527734SSukumar Swaminathan default: 4921*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 4922*82527734SSukumar Swaminathan "channel=%d cmd=%x %s %x %x %x %x", 4923*82527734SSukumar Swaminathan channelno, iocb->ULPCOMMAND, 4924*82527734SSukumar Swaminathan emlxs_state_xlate(iocb->ULPSTATUS), word[4], word[5], 4925*82527734SSukumar Swaminathan word[6], word[7]); 4926*82527734SSukumar Swaminathan return (1); 4927*82527734SSukumar Swaminathan } 4928*82527734SSukumar Swaminathan 4929*82527734SSukumar Swaminathan if (iocb->ULPSTATUS) { 4930*82527734SSukumar Swaminathan if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) && 4931*82527734SSukumar Swaminathan (iocb->un.grsp.perr.statLocalError == 4932*82527734SSukumar Swaminathan IOERR_RCV_BUFFER_TIMEOUT)) { 4933*82527734SSukumar Swaminathan (void) strcpy(error_str, "Out of posted buffers:"); 4934*82527734SSukumar Swaminathan } else if ((iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) && 4935*82527734SSukumar Swaminathan (iocb->un.grsp.perr.statLocalError == 4936*82527734SSukumar Swaminathan IOERR_RCV_BUFFER_WAITING)) { 4937*82527734SSukumar Swaminathan (void) strcpy(error_str, "Buffer waiting:"); 4938*82527734SSukumar Swaminathan goto done; 4939*82527734SSukumar Swaminathan } else if (iocb->ULPSTATUS == IOSTAT_NEED_BUFF_ENTRY) { 4940*82527734SSukumar Swaminathan (void) strcpy(error_str, "Need Buffer Entry:"); 4941*82527734SSukumar Swaminathan goto done; 4942*82527734SSukumar Swaminathan } else { 4943*82527734SSukumar Swaminathan (void) strcpy(error_str, "General error:"); 4944291a2b48SSukumar Swaminathan } 4945291a2b48SSukumar Swaminathan 4946*82527734SSukumar Swaminathan goto failed; 4947291a2b48SSukumar Swaminathan } 4948291a2b48SSukumar Swaminathan 4949*82527734SSukumar Swaminathan if (hba->flag & FC_HBQ_ENABLED) { 4950*82527734SSukumar Swaminathan HBQ_INIT_t *hbq; 4951*82527734SSukumar Swaminathan HBQE_t *hbqE; 4952*82527734SSukumar Swaminathan uint32_t hbqe_tag; 4953291a2b48SSukumar Swaminathan 4954*82527734SSukumar Swaminathan (*UbPosted)--; 4955291a2b48SSukumar Swaminathan 4956*82527734SSukumar Swaminathan hbqE = (HBQE_t *)iocb; 4957*82527734SSukumar Swaminathan hbq_id = hbqE->unt.ext.HBQ_tag; 4958*82527734SSukumar Swaminathan hbqe_tag = hbqE->unt.ext.HBQE_tag; 4959291a2b48SSukumar Swaminathan 4960*82527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 4961291a2b48SSukumar Swaminathan 4962*82527734SSukumar Swaminathan if (hbqe_tag >= hbq->HBQ_numEntries) { 4963*82527734SSukumar Swaminathan (void) sprintf(error_str, "Invalid HBQE tag=%x:", 4964*82527734SSukumar Swaminathan hbqe_tag); 4965*82527734SSukumar Swaminathan goto dropped; 4966*82527734SSukumar Swaminathan } 4967291a2b48SSukumar Swaminathan 4968*82527734SSukumar Swaminathan mp = hba->sli.sli3.hbq_table[hbq_id].HBQ_PostBufs[hbqe_tag]; 4969291a2b48SSukumar Swaminathan 4970*82527734SSukumar Swaminathan size = iocb->unsli3.ext_rcv.seq_len; 4971*82527734SSukumar Swaminathan } else { 4972*82527734SSukumar Swaminathan bdeAddr = 4973*82527734SSukumar Swaminathan PADDR(iocb->un.cont64[0].addrHigh, 4974*82527734SSukumar Swaminathan iocb->un.cont64[0].addrLow); 4975291a2b48SSukumar Swaminathan 4976*82527734SSukumar Swaminathan /* Check for invalid buffer */ 4977*82527734SSukumar Swaminathan if (iocb->un.cont64[0].tus.f.bdeFlags & BUFF_TYPE_INVALID) { 4978*82527734SSukumar Swaminathan (void) strcpy(error_str, "Invalid buffer:"); 4979*82527734SSukumar Swaminathan goto dropped; 4980291a2b48SSukumar Swaminathan } 4981291a2b48SSukumar Swaminathan 4982*82527734SSukumar Swaminathan mp = emlxs_mem_get_vaddr(hba, rp, bdeAddr); 4983291a2b48SSukumar Swaminathan 4984*82527734SSukumar Swaminathan size = iocb->un.rcvseq64.rcvBde.tus.f.bdeSize; 4985291a2b48SSukumar Swaminathan } 4986291a2b48SSukumar Swaminathan 4987*82527734SSukumar Swaminathan if (!mp) { 4988*82527734SSukumar Swaminathan (void) strcpy(error_str, "Buffer not mapped:"); 4989*82527734SSukumar Swaminathan goto dropped; 4990*82527734SSukumar Swaminathan } 4991291a2b48SSukumar Swaminathan 4992*82527734SSukumar Swaminathan if (!size) { 4993*82527734SSukumar Swaminathan (void) strcpy(error_str, "Buffer empty:"); 4994*82527734SSukumar Swaminathan goto dropped; 4995*82527734SSukumar Swaminathan } 4996291a2b48SSukumar Swaminathan 4997*82527734SSukumar Swaminathan /* To avoid we drop the broadcast packets */ 4998*82527734SSukumar Swaminathan if (channelno != FC_IP_RING) { 4999*82527734SSukumar Swaminathan /* Get virtual port */ 5000*82527734SSukumar Swaminathan if (hba->flag & FC_NPIV_ENABLED) { 5001*82527734SSukumar Swaminathan vpi = iocb->unsli3.ext_rcv.vpi; 5002*82527734SSukumar Swaminathan if (vpi >= hba->vpi_max) { 5003*82527734SSukumar Swaminathan (void) sprintf(error_str, 5004*82527734SSukumar Swaminathan "Invalid VPI=%d:", vpi); 5005*82527734SSukumar Swaminathan goto dropped; 5006*82527734SSukumar Swaminathan } 5007291a2b48SSukumar Swaminathan 5008*82527734SSukumar Swaminathan port = &VPORT(vpi); 5009*82527734SSukumar Swaminathan } 50104baa2c25SSukumar Swaminathan } 50114baa2c25SSukumar Swaminathan 5012*82527734SSukumar Swaminathan /* Process request */ 5013*82527734SSukumar Swaminathan switch (channelno) { 5014*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 5015*82527734SSukumar Swaminathan case FC_FCT_RING: 5016*82527734SSukumar Swaminathan (void) emlxs_fct_handle_unsol_req(port, cp, iocbq, mp, size); 5017*82527734SSukumar Swaminathan break; 5018*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 5019291a2b48SSukumar Swaminathan 5020*82527734SSukumar Swaminathan case FC_IP_RING: 5021*82527734SSukumar Swaminathan (void) emlxs_ip_handle_unsol_req(port, cp, iocbq, mp, size); 5022*82527734SSukumar Swaminathan break; 5023291a2b48SSukumar Swaminathan 5024*82527734SSukumar Swaminathan case FC_ELS_RING: 5025*82527734SSukumar Swaminathan /* If this is a target port, then let fct handle this */ 5026*82527734SSukumar Swaminathan if (port->ini_mode) { 5027*82527734SSukumar Swaminathan (void) emlxs_els_handle_unsol_req(port, cp, iocbq, mp, 5028*82527734SSukumar Swaminathan size); 5029*82527734SSukumar Swaminathan } 5030*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 5031*82527734SSukumar Swaminathan else if (port->tgt_mode) { 5032*82527734SSukumar Swaminathan (void) emlxs_fct_handle_unsol_els(port, cp, iocbq, mp, 5033*82527734SSukumar Swaminathan size); 5034*82527734SSukumar Swaminathan } 5035*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 5036*82527734SSukumar Swaminathan break; 5037291a2b48SSukumar Swaminathan 5038*82527734SSukumar Swaminathan case FC_CT_RING: 5039*82527734SSukumar Swaminathan (void) emlxs_ct_handle_unsol_req(port, cp, iocbq, mp, size); 5040*82527734SSukumar Swaminathan break; 5041*82527734SSukumar Swaminathan } 5042291a2b48SSukumar Swaminathan 5043*82527734SSukumar Swaminathan goto done; 5044291a2b48SSukumar Swaminathan 5045*82527734SSukumar Swaminathan dropped: 5046*82527734SSukumar Swaminathan (*RcvDropped)++; 5047291a2b48SSukumar Swaminathan 5048*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 5049*82527734SSukumar Swaminathan "%s: cmd=%x %s %x %x %x %x", 5050*82527734SSukumar Swaminathan error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS), 5051*82527734SSukumar Swaminathan word[4], word[5], word[6], word[7]); 5052291a2b48SSukumar Swaminathan 5053*82527734SSukumar Swaminathan if (channelno == FC_FCT_RING) { 5054*82527734SSukumar Swaminathan uint32_t sid; 5055291a2b48SSukumar Swaminathan 5056*82527734SSukumar Swaminathan if (hba->sli_mode >= EMLXS_HBA_SLI3_MODE) { 5057*82527734SSukumar Swaminathan emlxs_node_t *ndlp; 5058*82527734SSukumar Swaminathan ndlp = emlxs_node_find_rpi(port, iocb->ULPIOTAG); 5059*82527734SSukumar Swaminathan sid = ndlp->nlp_DID; 5060*82527734SSukumar Swaminathan } else { 5061*82527734SSukumar Swaminathan sid = iocb->un.ulpWord[4] & 0xFFFFFF; 5062*82527734SSukumar Swaminathan } 5063291a2b48SSukumar Swaminathan 5064*82527734SSukumar Swaminathan emlxs_send_logo(port, sid); 5065291a2b48SSukumar Swaminathan } 5066291a2b48SSukumar Swaminathan 5067*82527734SSukumar Swaminathan goto done; 5068291a2b48SSukumar Swaminathan 5069*82527734SSukumar Swaminathan failed: 5070*82527734SSukumar Swaminathan (*RcvError)++; 5071291a2b48SSukumar Swaminathan 5072*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, dropped_msg, 5073*82527734SSukumar Swaminathan "%s: cmd=%x %s %x %x %x %x hba:%x %x", 5074*82527734SSukumar Swaminathan error_str, iocb->ULPCOMMAND, emlxs_state_xlate(iocb->ULPSTATUS), 5075*82527734SSukumar Swaminathan word[4], word[5], word[6], word[7], hba->state, hba->flag); 5076291a2b48SSukumar Swaminathan 5077*82527734SSukumar Swaminathan done: 5078291a2b48SSukumar Swaminathan 5079*82527734SSukumar Swaminathan if (hba->flag & FC_HBQ_ENABLED) { 5080*82527734SSukumar Swaminathan emlxs_update_HBQ_index(hba, hbq_id); 5081*82527734SSukumar Swaminathan } else { 5082*82527734SSukumar Swaminathan if (mp) { 5083*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, buf_type, (uint8_t *)mp); 5084291a2b48SSukumar Swaminathan } 5085*82527734SSukumar Swaminathan (void) emlxs_post_buffer(hba, rp, 1); 5086291a2b48SSukumar Swaminathan } 5087291a2b48SSukumar Swaminathan 5088*82527734SSukumar Swaminathan return (0); 5089291a2b48SSukumar Swaminathan 5090*82527734SSukumar Swaminathan } /* emlxs_handle_rcv_seq() */ 5091291a2b48SSukumar Swaminathan 5092291a2b48SSukumar Swaminathan 5093*82527734SSukumar Swaminathan /* EMLXS_CMD_RING_LOCK must be held when calling this function */ 5094*82527734SSukumar Swaminathan static void 5095*82527734SSukumar Swaminathan emlxs_sli3_issue_iocb(emlxs_hba_t *hba, RING *rp, IOCBQ *iocbq) 5096291a2b48SSukumar Swaminathan { 5097*82527734SSukumar Swaminathan emlxs_port_t *port; 5098*82527734SSukumar Swaminathan IOCB *icmd; 5099*82527734SSukumar Swaminathan IOCB *iocb; 5100*82527734SSukumar Swaminathan emlxs_buf_t *sbp; 5101*82527734SSukumar Swaminathan off_t offset; 5102*82527734SSukumar Swaminathan uint32_t ringno; 5103291a2b48SSukumar Swaminathan 5104*82527734SSukumar Swaminathan ringno = rp->ringno; 5105*82527734SSukumar Swaminathan sbp = iocbq->sbp; 5106*82527734SSukumar Swaminathan icmd = &iocbq->iocb; 5107*82527734SSukumar Swaminathan port = iocbq->port; 5108291a2b48SSukumar Swaminathan 5109*82527734SSukumar Swaminathan HBASTATS.IocbIssued[ringno]++; 5110291a2b48SSukumar Swaminathan 5111*82527734SSukumar Swaminathan /* Check for ULP pkt request */ 5112*82527734SSukumar Swaminathan if (sbp) { 5113*82527734SSukumar Swaminathan mutex_enter(&sbp->mtx); 5114291a2b48SSukumar Swaminathan 5115*82527734SSukumar Swaminathan if (sbp->node == NULL) { 5116*82527734SSukumar Swaminathan /* Set node to base node by default */ 5117*82527734SSukumar Swaminathan iocbq->node = (void *)&port->node_base; 5118*82527734SSukumar Swaminathan sbp->node = (void *)&port->node_base; 5119*82527734SSukumar Swaminathan } 5120291a2b48SSukumar Swaminathan 5121*82527734SSukumar Swaminathan sbp->pkt_flags |= PACKET_IN_CHIPQ; 5122*82527734SSukumar Swaminathan mutex_exit(&sbp->mtx); 5123291a2b48SSukumar Swaminathan 5124*82527734SSukumar Swaminathan atomic_add_32(&hba->io_active, 1); 5125291a2b48SSukumar Swaminathan 5126*82527734SSukumar Swaminathan #ifdef SFCT_SUPPORT 5127*82527734SSukumar Swaminathan #ifdef FCT_IO_TRACE 5128*82527734SSukumar Swaminathan if (sbp->fct_cmd) { 5129*82527734SSukumar Swaminathan emlxs_fct_io_trace(port, sbp->fct_cmd, 5130*82527734SSukumar Swaminathan EMLXS_FCT_IOCB_ISSUED); 5131*82527734SSukumar Swaminathan emlxs_fct_io_trace(port, sbp->fct_cmd, 5132*82527734SSukumar Swaminathan icmd->ULPCOMMAND); 5133*82527734SSukumar Swaminathan } 5134*82527734SSukumar Swaminathan #endif /* FCT_IO_TRACE */ 5135*82527734SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 5136291a2b48SSukumar Swaminathan 5137*82527734SSukumar Swaminathan rp->channelp->hbaSendCmd_sbp++; 5138*82527734SSukumar Swaminathan iocbq->channel = rp->channelp; 5139291a2b48SSukumar Swaminathan } else { 5140*82527734SSukumar Swaminathan rp->channelp->hbaSendCmd++; 5141291a2b48SSukumar Swaminathan } 5142291a2b48SSukumar Swaminathan 5143*82527734SSukumar Swaminathan /* get the next available command ring iocb */ 5144*82527734SSukumar Swaminathan iocb = 5145*82527734SSukumar Swaminathan (IOCB *)(((char *)rp->fc_cmdringaddr + 5146*82527734SSukumar Swaminathan (rp->fc_cmdidx * hba->sli.sli3.iocb_cmd_size))); 5147291a2b48SSukumar Swaminathan 5148*82527734SSukumar Swaminathan /* Copy the local iocb to the command ring iocb */ 5149*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)icmd, (uint8_t *)iocb, 5150*82527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size); 5151291a2b48SSukumar Swaminathan 5152*82527734SSukumar Swaminathan /* DMA sync the command ring iocb for the adapter */ 5153*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)iocb) 5154*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5155*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 5156*82527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size, DDI_DMA_SYNC_FORDEV); 5157291a2b48SSukumar Swaminathan 5158*82527734SSukumar Swaminathan /* 5159*82527734SSukumar Swaminathan * After this, the sbp / iocb should not be 5160*82527734SSukumar Swaminathan * accessed in the xmit path. 5161*82527734SSukumar Swaminathan */ 5162*82527734SSukumar Swaminathan 5163*82527734SSukumar Swaminathan /* Free the local iocb if there is no sbp tracking it */ 5164*82527734SSukumar Swaminathan if (!sbp) { 5165*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_IOCB, (uint8_t *)iocbq); 5166291a2b48SSukumar Swaminathan } 5167291a2b48SSukumar Swaminathan 5168*82527734SSukumar Swaminathan /* update local ring index to next available ring index */ 5169*82527734SSukumar Swaminathan rp->fc_cmdidx = 5170*82527734SSukumar Swaminathan (rp->fc_cmdidx + 1 >= rp->fc_numCiocb) ? 0 : rp->fc_cmdidx + 1; 5171291a2b48SSukumar Swaminathan 5172291a2b48SSukumar Swaminathan 5173*82527734SSukumar Swaminathan return; 51744baa2c25SSukumar Swaminathan 5175*82527734SSukumar Swaminathan } /* emlxs_sli3_issue_iocb() */ 5176291a2b48SSukumar Swaminathan 5177291a2b48SSukumar Swaminathan 5178*82527734SSukumar Swaminathan static void 5179*82527734SSukumar Swaminathan emlxs_sli3_hba_kill(emlxs_hba_t *hba) 5180*82527734SSukumar Swaminathan { 5181*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 5182*82527734SSukumar Swaminathan MAILBOX *swpmb; 5183*82527734SSukumar Swaminathan MAILBOX *mb2; 5184*82527734SSukumar Swaminathan MAILBOX *mb1; 5185*82527734SSukumar Swaminathan uint32_t word0; 5186*82527734SSukumar Swaminathan uint32_t j; 5187*82527734SSukumar Swaminathan uint32_t interlock_failed; 5188*82527734SSukumar Swaminathan uint32_t ha_copy; 5189*82527734SSukumar Swaminathan uint32_t value; 5190*82527734SSukumar Swaminathan off_t offset; 5191*82527734SSukumar Swaminathan uint32_t size; 5192291a2b48SSukumar Swaminathan 5193*82527734SSukumar Swaminathan /* Perform adapter interlock to kill adapter */ 5194*82527734SSukumar Swaminathan interlock_failed = 0; 5195291a2b48SSukumar Swaminathan 5196*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 5197*82527734SSukumar Swaminathan if (hba->flag & FC_INTERLOCKED) { 5198*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5199291a2b48SSukumar Swaminathan 5200*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5201291a2b48SSukumar Swaminathan 5202*82527734SSukumar Swaminathan return; 5203*82527734SSukumar Swaminathan } 5204291a2b48SSukumar Swaminathan 5205*82527734SSukumar Swaminathan j = 0; 5206*82527734SSukumar Swaminathan while (j++ < 10000) { 5207*82527734SSukumar Swaminathan if (hba->mbox_queue_flag == 0) { 5208*82527734SSukumar Swaminathan break; 5209*82527734SSukumar Swaminathan } 5210291a2b48SSukumar Swaminathan 5211*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5212*82527734SSukumar Swaminathan DELAYUS(100); 5213*82527734SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 5214*82527734SSukumar Swaminathan } 5215291a2b48SSukumar Swaminathan 5216*82527734SSukumar Swaminathan if (hba->mbox_queue_flag != 0) { 5217*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5218*82527734SSukumar Swaminathan "Interlock failed. Mailbox busy."); 5219*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5220*82527734SSukumar Swaminathan return; 5221*82527734SSukumar Swaminathan } 5222291a2b48SSukumar Swaminathan 5223*82527734SSukumar Swaminathan hba->flag |= FC_INTERLOCKED; 5224*82527734SSukumar Swaminathan hba->mbox_queue_flag = 1; 5225291a2b48SSukumar Swaminathan 5226*82527734SSukumar Swaminathan /* Disable all host interrupts */ 5227*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy = 0; 5228*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 5229*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff); 5230291a2b48SSukumar Swaminathan 5231*82527734SSukumar Swaminathan mb2 = FC_SLIM2_MAILBOX(hba); 5232*82527734SSukumar Swaminathan mb1 = FC_SLIM1_MAILBOX(hba); 5233*82527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 5234291a2b48SSukumar Swaminathan 5235*82527734SSukumar Swaminathan if (!(hba->flag & FC_SLIM2_MODE)) { 5236*82527734SSukumar Swaminathan goto mode_B; 5237*82527734SSukumar Swaminathan } 5238291a2b48SSukumar Swaminathan 5239*82527734SSukumar Swaminathan mode_A: 5240291a2b48SSukumar Swaminathan 5241*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5242*82527734SSukumar Swaminathan "Attempting SLIM2 Interlock..."); 5243291a2b48SSukumar Swaminathan 5244*82527734SSukumar Swaminathan interlock_A: 5245291a2b48SSukumar Swaminathan 5246*82527734SSukumar Swaminathan value = 0xFFFFFFFF; 5247*82527734SSukumar Swaminathan word0 = 0; 5248*82527734SSukumar Swaminathan swpmb->mbxCommand = MBX_KILL_BOARD; 5249*82527734SSukumar Swaminathan swpmb->mbxOwner = OWN_CHIP; 5250291a2b48SSukumar Swaminathan 5251*82527734SSukumar Swaminathan /* Write value to SLIM */ 5252*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 5253*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0); 5254291a2b48SSukumar Swaminathan 5255*82527734SSukumar Swaminathan /* Send Kill board request */ 5256*82527734SSukumar Swaminathan mb2->un.varWords[0] = value; 5257*82527734SSukumar Swaminathan mb2->mbxCommand = MBX_KILL_BOARD; 5258*82527734SSukumar Swaminathan mb2->mbxOwner = OWN_CHIP; 5259291a2b48SSukumar Swaminathan 5260*82527734SSukumar Swaminathan /* Sync the memory */ 5261*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mb2) 5262*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5263*82527734SSukumar Swaminathan size = (sizeof (uint32_t) * 2); 5264291a2b48SSukumar Swaminathan 5265*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size); 5266291a2b48SSukumar Swaminathan 5267*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size, 5268*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 5269291a2b48SSukumar Swaminathan 5270*82527734SSukumar Swaminathan /* interrupt board to do it right away */ 5271*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5272291a2b48SSukumar Swaminathan 5273*82527734SSukumar Swaminathan /* First wait for command acceptence */ 5274*82527734SSukumar Swaminathan j = 0; 5275*82527734SSukumar Swaminathan while (j++ < 1000) { 5276*82527734SSukumar Swaminathan value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5277291a2b48SSukumar Swaminathan 5278*82527734SSukumar Swaminathan if (value == 0) { 5279*82527734SSukumar Swaminathan break; 5280291a2b48SSukumar Swaminathan } 5281291a2b48SSukumar Swaminathan 5282*82527734SSukumar Swaminathan DELAYUS(50); 5283*82527734SSukumar Swaminathan } 5284291a2b48SSukumar Swaminathan 5285*82527734SSukumar Swaminathan if (value == 0) { 5286*82527734SSukumar Swaminathan /* Now wait for mailbox ownership to clear */ 5287*82527734SSukumar Swaminathan while (j++ < 10000) { 5288*82527734SSukumar Swaminathan word0 = 5289*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5290291a2b48SSukumar Swaminathan 5291*82527734SSukumar Swaminathan if (swpmb->mbxOwner == 0) { 5292*82527734SSukumar Swaminathan break; 52934baa2c25SSukumar Swaminathan } 5294*82527734SSukumar Swaminathan 5295*82527734SSukumar Swaminathan DELAYUS(50); 5296291a2b48SSukumar Swaminathan } 5297291a2b48SSukumar Swaminathan 5298*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5299*82527734SSukumar Swaminathan "Interlock succeeded."); 5300291a2b48SSukumar Swaminathan 5301*82527734SSukumar Swaminathan goto done; 5302*82527734SSukumar Swaminathan } 5303291a2b48SSukumar Swaminathan 5304*82527734SSukumar Swaminathan /* Interlock failed !!! */ 5305*82527734SSukumar Swaminathan interlock_failed = 1; 5306291a2b48SSukumar Swaminathan 5307*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, "Interlock failed."); 5308291a2b48SSukumar Swaminathan 5309*82527734SSukumar Swaminathan mode_B: 5310291a2b48SSukumar Swaminathan 5311*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5312*82527734SSukumar Swaminathan "Attempting SLIM1 Interlock..."); 5313291a2b48SSukumar Swaminathan 5314*82527734SSukumar Swaminathan interlock_B: 53154baa2c25SSukumar Swaminathan 5316*82527734SSukumar Swaminathan value = 0xFFFFFFFF; 5317*82527734SSukumar Swaminathan word0 = 0; 5318*82527734SSukumar Swaminathan swpmb->mbxCommand = MBX_KILL_BOARD; 5319*82527734SSukumar Swaminathan swpmb->mbxOwner = OWN_CHIP; 53204baa2c25SSukumar Swaminathan 5321*82527734SSukumar Swaminathan /* Write KILL BOARD to mailbox */ 5322*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 5323*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, ((volatile uint32_t *)mb1), word0); 5324291a2b48SSukumar Swaminathan 5325*82527734SSukumar Swaminathan /* interrupt board to do it right away */ 5326*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5327291a2b48SSukumar Swaminathan 5328*82527734SSukumar Swaminathan /* First wait for command acceptence */ 5329*82527734SSukumar Swaminathan j = 0; 5330*82527734SSukumar Swaminathan while (j++ < 1000) { 5331*82527734SSukumar Swaminathan value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5332291a2b48SSukumar Swaminathan 5333*82527734SSukumar Swaminathan if (value == 0) { 5334*82527734SSukumar Swaminathan break; 5335291a2b48SSukumar Swaminathan } 5336*82527734SSukumar Swaminathan 5337*82527734SSukumar Swaminathan DELAYUS(50); 5338291a2b48SSukumar Swaminathan } 5339291a2b48SSukumar Swaminathan 5340*82527734SSukumar Swaminathan if (value == 0) { 5341*82527734SSukumar Swaminathan /* Now wait for mailbox ownership to clear */ 5342*82527734SSukumar Swaminathan while (j++ < 10000) { 5343*82527734SSukumar Swaminathan word0 = 5344*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5345291a2b48SSukumar Swaminathan 5346*82527734SSukumar Swaminathan if (swpmb->mbxOwner == 0) { 5347*82527734SSukumar Swaminathan break; 5348*82527734SSukumar Swaminathan } 5349291a2b48SSukumar Swaminathan 5350*82527734SSukumar Swaminathan DELAYUS(50); 5351291a2b48SSukumar Swaminathan } 5352291a2b48SSukumar Swaminathan 5353*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5354*82527734SSukumar Swaminathan "Interlock succeeded."); 5355291a2b48SSukumar Swaminathan 5356*82527734SSukumar Swaminathan goto done; 5357*82527734SSukumar Swaminathan } 5358291a2b48SSukumar Swaminathan 5359*82527734SSukumar Swaminathan /* Interlock failed !!! */ 5360291a2b48SSukumar Swaminathan 5361*82527734SSukumar Swaminathan /* If this is the first time then try again */ 5362*82527734SSukumar Swaminathan if (interlock_failed == 0) { 5363*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5364*82527734SSukumar Swaminathan "Interlock failed. Retrying..."); 5365291a2b48SSukumar Swaminathan 5366*82527734SSukumar Swaminathan /* Try again */ 5367*82527734SSukumar Swaminathan interlock_failed = 1; 5368*82527734SSukumar Swaminathan goto interlock_B; 5369291a2b48SSukumar Swaminathan } 5370291a2b48SSukumar Swaminathan 5371291a2b48SSukumar Swaminathan /* 5372*82527734SSukumar Swaminathan * Now check for error attention to indicate the board has 5373*82527734SSukumar Swaminathan * been kiilled 5374291a2b48SSukumar Swaminathan */ 5375*82527734SSukumar Swaminathan j = 0; 5376*82527734SSukumar Swaminathan while (j++ < 10000) { 5377*82527734SSukumar Swaminathan ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 5378bb63f56eSSukumar Swaminathan 5379*82527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 5380*82527734SSukumar Swaminathan break; 5381*82527734SSukumar Swaminathan } 53823be114edSSukumar Swaminathan 5383*82527734SSukumar Swaminathan DELAYUS(50); 5384*82527734SSukumar Swaminathan } 5385291a2b48SSukumar Swaminathan 5386*82527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 5387*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5388*82527734SSukumar Swaminathan "Interlock failed. Board killed."); 5389*82527734SSukumar Swaminathan } else { 5390*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 5391*82527734SSukumar Swaminathan "Interlock failed. Board not killed."); 5392*82527734SSukumar Swaminathan } 5393291a2b48SSukumar Swaminathan 5394*82527734SSukumar Swaminathan done: 5395291a2b48SSukumar Swaminathan 5396*82527734SSukumar Swaminathan hba->mbox_queue_flag = 0; 5397291a2b48SSukumar Swaminathan 5398*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5399291a2b48SSukumar Swaminathan 5400*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 5401*82527734SSukumar Swaminathan /* Access handle validation */ 5402*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 5403*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 5404*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5405291a2b48SSukumar Swaminathan 5406*82527734SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5407291a2b48SSukumar Swaminathan 5408*82527734SSukumar Swaminathan return; 5409291a2b48SSukumar Swaminathan 5410*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill() */ 5411291a2b48SSukumar Swaminathan 5412291a2b48SSukumar Swaminathan 5413*82527734SSukumar Swaminathan static void 5414*82527734SSukumar Swaminathan emlxs_sli3_hba_kill4quiesce(emlxs_hba_t *hba) 5415*82527734SSukumar Swaminathan { 5416*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 5417*82527734SSukumar Swaminathan MAILBOX *swpmb; 5418*82527734SSukumar Swaminathan MAILBOX *mb2; 5419*82527734SSukumar Swaminathan MAILBOX *mb1; 5420*82527734SSukumar Swaminathan uint32_t word0; 5421*82527734SSukumar Swaminathan off_t offset; 5422*82527734SSukumar Swaminathan uint32_t j; 5423*82527734SSukumar Swaminathan uint32_t value; 5424*82527734SSukumar Swaminathan uint32_t size; 5425291a2b48SSukumar Swaminathan 5426*82527734SSukumar Swaminathan /* Disable all host interrupts */ 5427*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy = 0; 5428*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 5429*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HA_REG(hba), 0xffffffff); 5430291a2b48SSukumar Swaminathan 5431*82527734SSukumar Swaminathan mb2 = FC_SLIM2_MAILBOX(hba); 5432*82527734SSukumar Swaminathan mb1 = FC_SLIM1_MAILBOX(hba); 5433*82527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 5434291a2b48SSukumar Swaminathan 5435*82527734SSukumar Swaminathan value = 0xFFFFFFFF; 5436*82527734SSukumar Swaminathan word0 = 0; 5437*82527734SSukumar Swaminathan swpmb->mbxCommand = MBX_KILL_BOARD; 5438*82527734SSukumar Swaminathan swpmb->mbxOwner = OWN_CHIP; 5439291a2b48SSukumar Swaminathan 5440*82527734SSukumar Swaminathan /* Write value to SLIM */ 5441*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1), value); 5442*82527734SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (((volatile uint32_t *)mb1)), word0); 5443291a2b48SSukumar Swaminathan 5444*82527734SSukumar Swaminathan /* Send Kill board request */ 5445*82527734SSukumar Swaminathan mb2->un.varWords[0] = value; 5446*82527734SSukumar Swaminathan mb2->mbxCommand = MBX_KILL_BOARD; 5447*82527734SSukumar Swaminathan mb2->mbxOwner = OWN_CHIP; 5448291a2b48SSukumar Swaminathan 5449*82527734SSukumar Swaminathan /* Sync the memory */ 5450*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mb2) 5451*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5452*82527734SSukumar Swaminathan size = (sizeof (uint32_t) * 2); 5453291a2b48SSukumar Swaminathan 5454*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mb2, (uint8_t *)mb2, size); 5455291a2b48SSukumar Swaminathan 5456*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, size, 5457*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORDEV); 5458291a2b48SSukumar Swaminathan 5459*82527734SSukumar Swaminathan /* interrupt board to do it right away */ 5460*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_CA_REG(hba), CA_MBATT); 5461291a2b48SSukumar Swaminathan 5462*82527734SSukumar Swaminathan /* First wait for command acceptence */ 5463*82527734SSukumar Swaminathan j = 0; 5464*82527734SSukumar Swaminathan while (j++ < 1000) { 5465*82527734SSukumar Swaminathan value = READ_SLIM_ADDR(hba, (((volatile uint32_t *)mb1) + 1)); 5466291a2b48SSukumar Swaminathan 5467*82527734SSukumar Swaminathan if (value == 0) { 5468*82527734SSukumar Swaminathan break; 5469*82527734SSukumar Swaminathan } 5470*82527734SSukumar Swaminathan DELAYUS(50); 5471*82527734SSukumar Swaminathan } 5472*82527734SSukumar Swaminathan if (value == 0) { 5473*82527734SSukumar Swaminathan /* Now wait for mailbox ownership to clear */ 5474*82527734SSukumar Swaminathan while (j++ < 10000) { 5475*82527734SSukumar Swaminathan word0 = 5476*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb1)); 5477*82527734SSukumar Swaminathan if (swpmb->mbxOwner == 0) { 5478*82527734SSukumar Swaminathan break; 5479291a2b48SSukumar Swaminathan } 5480*82527734SSukumar Swaminathan DELAYUS(50); 5481291a2b48SSukumar Swaminathan } 5482*82527734SSukumar Swaminathan goto done; 5483*82527734SSukumar Swaminathan } 5484291a2b48SSukumar Swaminathan 5485*82527734SSukumar Swaminathan done: 5486*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_KILLED); 5487291a2b48SSukumar Swaminathan 5488*82527734SSukumar Swaminathan #ifdef FMA_SUPPORT 5489*82527734SSukumar Swaminathan /* Access handle validation */ 5490*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 5491*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 5492*82527734SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5493*82527734SSukumar Swaminathan return; 5494291a2b48SSukumar Swaminathan 5495*82527734SSukumar Swaminathan } /* emlxs_sli3_hba_kill4quiesce */ 5496291a2b48SSukumar Swaminathan 5497291a2b48SSukumar Swaminathan 5498*82527734SSukumar Swaminathan static uint32_t 5499*82527734SSukumar Swaminathan emlxs_reset_ring(emlxs_hba_t *hba, uint32_t ringno) 5500*82527734SSukumar Swaminathan { 5501*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 5502*82527734SSukumar Swaminathan RING *rp; 5503*82527734SSukumar Swaminathan MAILBOXQ *mbq; 5504*82527734SSukumar Swaminathan MAILBOX *mb; 5505*82527734SSukumar Swaminathan PGP *pgp; 5506*82527734SSukumar Swaminathan off_t offset; 5507*82527734SSukumar Swaminathan NODELIST *ndlp; 5508*82527734SSukumar Swaminathan uint32_t i; 5509*82527734SSukumar Swaminathan emlxs_port_t *vport; 5510291a2b48SSukumar Swaminathan 5511*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[ringno]; 5512*82527734SSukumar Swaminathan pgp = 5513*82527734SSukumar Swaminathan (PGP *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port[ringno]; 5514291a2b48SSukumar Swaminathan 5515*82527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) { 5516*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, 5517*82527734SSukumar Swaminathan "%s: Unable to allocate mailbox buffer.", 5518*82527734SSukumar Swaminathan emlxs_ring_xlate(ringno)); 5519291a2b48SSukumar Swaminathan 5520*82527734SSukumar Swaminathan return ((uint32_t)FC_FAILURE); 5521*82527734SSukumar Swaminathan } 5522*82527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 5523291a2b48SSukumar Swaminathan 5524*82527734SSukumar Swaminathan emlxs_mb_reset_ring(hba, mbq, ringno); 5525*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 5526*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, 5527*82527734SSukumar Swaminathan "%s: Unable to reset ring. Mailbox cmd=%x status=%x", 5528*82527734SSukumar Swaminathan emlxs_ring_xlate(ringno), mb->mbxCommand, mb->mbxStatus); 5529291a2b48SSukumar Swaminathan 5530*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 5531*82527734SSukumar Swaminathan return ((uint32_t)FC_FAILURE); 5532*82527734SSukumar Swaminathan } 5533291a2b48SSukumar Swaminathan 5534*82527734SSukumar Swaminathan /* Free the mailbox */ 5535*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 5536291a2b48SSukumar Swaminathan 5537*82527734SSukumar Swaminathan /* Update the response ring indicies */ 5538*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)&(pgp->rspPutInx)) 5539*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5540*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 5541*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 5542*82527734SSukumar Swaminathan rp->fc_rspidx = rp->fc_port_rspidx = BE_SWAP32(pgp->rspPutInx); 5543291a2b48SSukumar Swaminathan 5544*82527734SSukumar Swaminathan /* Update the command ring indicies */ 5545*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)&(pgp->cmdGetInx)) - 5546*82527734SSukumar Swaminathan (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5547*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 4, 5548*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 5549*82527734SSukumar Swaminathan rp->fc_cmdidx = rp->fc_port_cmdidx = BE_SWAP32(pgp->cmdGetInx); 5550291a2b48SSukumar Swaminathan 5551*82527734SSukumar Swaminathan for (i = 0; i < MAX_VPORTS; i++) { 5552*82527734SSukumar Swaminathan vport = &VPORT(i); 5553*82527734SSukumar Swaminathan 5554*82527734SSukumar Swaminathan if (!(vport->flag & EMLXS_PORT_BOUND)) { 5555*82527734SSukumar Swaminathan continue; 5556*82527734SSukumar Swaminathan } 5557291a2b48SSukumar Swaminathan 5558*82527734SSukumar Swaminathan /* Clear all node XRI contexts */ 5559*82527734SSukumar Swaminathan rw_enter(&vport->node_rwlock, RW_WRITER); 5560*82527734SSukumar Swaminathan mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 5561*82527734SSukumar Swaminathan for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) { 5562*82527734SSukumar Swaminathan ndlp = vport->node_table[i]; 5563*82527734SSukumar Swaminathan while (ndlp != NULL) { 5564*82527734SSukumar Swaminathan ndlp->nlp_flag[FC_IP_RING] &= ~NLP_RPI_XRI; 5565*82527734SSukumar Swaminathan ndlp = ndlp->nlp_list_next; 5566291a2b48SSukumar Swaminathan } 5567291a2b48SSukumar Swaminathan } 5568*82527734SSukumar Swaminathan mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 5569*82527734SSukumar Swaminathan rw_exit(&vport->node_rwlock); 5570*82527734SSukumar Swaminathan } 5571*82527734SSukumar Swaminathan 5572*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ring_reset_msg, "%s", 5573*82527734SSukumar Swaminathan emlxs_ring_xlate(ringno)); 5574*82527734SSukumar Swaminathan 5575*82527734SSukumar Swaminathan return (FC_SUCCESS); 5576291a2b48SSukumar Swaminathan 5577*82527734SSukumar Swaminathan } /* emlxs_reset_ring() */ 5578291a2b48SSukumar Swaminathan 5579291a2b48SSukumar Swaminathan 5580*82527734SSukumar Swaminathan /* 5581*82527734SSukumar Swaminathan * emlxs_handle_mb_event 5582*82527734SSukumar Swaminathan * 5583*82527734SSukumar Swaminathan * Description: Process a Mailbox Attention. 5584*82527734SSukumar Swaminathan * Called from host_interrupt to process MBATT 5585*82527734SSukumar Swaminathan * 5586*82527734SSukumar Swaminathan * Returns: 5587*82527734SSukumar Swaminathan * 5588*82527734SSukumar Swaminathan */ 5589*82527734SSukumar Swaminathan static uint32_t 5590*82527734SSukumar Swaminathan emlxs_handle_mb_event(emlxs_hba_t *hba) 5591*82527734SSukumar Swaminathan { 5592*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 5593*82527734SSukumar Swaminathan MAILBOX *mb; 5594*82527734SSukumar Swaminathan MAILBOX *swpmb; 5595*82527734SSukumar Swaminathan MAILBOX *mbox; 5596*82527734SSukumar Swaminathan MAILBOXQ *mbq; 5597*82527734SSukumar Swaminathan volatile uint32_t word0; 5598*82527734SSukumar Swaminathan MATCHMAP *mbox_bp; 5599*82527734SSukumar Swaminathan off_t offset; 5600*82527734SSukumar Swaminathan uint32_t i; 5601*82527734SSukumar Swaminathan int rc; 5602*82527734SSukumar Swaminathan 5603*82527734SSukumar Swaminathan swpmb = (MAILBOX *)&word0; 5604291a2b48SSukumar Swaminathan 5605*82527734SSukumar Swaminathan switch (hba->mbox_queue_flag) { 5606*82527734SSukumar Swaminathan case 0: 5607*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, 5608*82527734SSukumar Swaminathan "No mailbox active."); 5609*82527734SSukumar Swaminathan return (0); 5610291a2b48SSukumar Swaminathan 5611*82527734SSukumar Swaminathan case MBX_POLL: 5612291a2b48SSukumar Swaminathan 5613*82527734SSukumar Swaminathan /* Mark mailbox complete, this should wake up any polling */ 5614*82527734SSukumar Swaminathan /* threads. This can happen if interrupts are enabled while */ 5615*82527734SSukumar Swaminathan /* a polled mailbox command is outstanding. If we don't set */ 5616*82527734SSukumar Swaminathan /* MBQ_COMPLETED here, the polling thread may wait until */ 5617*82527734SSukumar Swaminathan /* timeout error occurs */ 5618291a2b48SSukumar Swaminathan 5619*82527734SSukumar Swaminathan mutex_enter(&EMLXS_MBOX_LOCK); 5620*82527734SSukumar Swaminathan mbq = (MAILBOXQ *)hba->mbox_mbq; 5621*82527734SSukumar Swaminathan mutex_exit(&EMLXS_MBOX_LOCK); 5622*82527734SSukumar Swaminathan if (mbq) { 5623*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5624*82527734SSukumar Swaminathan "Mailbox event. Completing Polled command."); 5625*82527734SSukumar Swaminathan mbq->flag |= MBQ_COMPLETED; 5626*82527734SSukumar Swaminathan } 5627291a2b48SSukumar Swaminathan 5628*82527734SSukumar Swaminathan return (0); 5629291a2b48SSukumar Swaminathan 5630*82527734SSukumar Swaminathan case MBX_SLEEP: 5631*82527734SSukumar Swaminathan case MBX_NOWAIT: 5632*82527734SSukumar Swaminathan mutex_enter(&EMLXS_MBOX_LOCK); 5633*82527734SSukumar Swaminathan mbq = (MAILBOXQ *)hba->mbox_mbq; 5634*82527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 5635*82527734SSukumar Swaminathan mutex_exit(&EMLXS_MBOX_LOCK); 5636*82527734SSukumar Swaminathan break; 5637291a2b48SSukumar Swaminathan 5638*82527734SSukumar Swaminathan default: 5639*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_completion_error_msg, 5640*82527734SSukumar Swaminathan "Invalid Mailbox flag (%x)."); 5641*82527734SSukumar Swaminathan return (0); 5642*82527734SSukumar Swaminathan } 5643291a2b48SSukumar Swaminathan 5644*82527734SSukumar Swaminathan /* Get first word of mailbox */ 5645*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 5646*82527734SSukumar Swaminathan mbox = FC_SLIM2_MAILBOX(hba); 5647*82527734SSukumar Swaminathan offset = (off_t)((uint64_t)((unsigned long)mbox) 5648*82527734SSukumar Swaminathan - (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 5649291a2b48SSukumar Swaminathan 5650*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 5651*82527734SSukumar Swaminathan sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 5652*82527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 5653*82527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 5654*82527734SSukumar Swaminathan } else { 5655*82527734SSukumar Swaminathan mbox = FC_SLIM1_MAILBOX(hba); 5656*82527734SSukumar Swaminathan word0 = READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 5657*82527734SSukumar Swaminathan } 5658291a2b48SSukumar Swaminathan 5659*82527734SSukumar Swaminathan i = 0; 5660*82527734SSukumar Swaminathan while (swpmb->mbxOwner == OWN_CHIP) { 5661*82527734SSukumar Swaminathan if (i++ > 10000) { 5662*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_stray_mbox_intr_msg, 5663*82527734SSukumar Swaminathan "OWN_CHIP: %s: status=%x", 5664*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(swpmb->mbxCommand), 5665*82527734SSukumar Swaminathan swpmb->mbxStatus); 5666291a2b48SSukumar Swaminathan 5667*82527734SSukumar Swaminathan return (1); 5668*82527734SSukumar Swaminathan } 5669291a2b48SSukumar Swaminathan 5670*82527734SSukumar Swaminathan /* Get first word of mailbox */ 5671*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 5672*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 5673*82527734SSukumar Swaminathan offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 5674*82527734SSukumar Swaminathan word0 = *((volatile uint32_t *)mbox); 5675*82527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 5676*82527734SSukumar Swaminathan } else { 5677*82527734SSukumar Swaminathan word0 = 5678*82527734SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mbox)); 5679*82527734SSukumar Swaminathan } 5680*82527734SSukumar Swaminathan } 5681291a2b48SSukumar Swaminathan 5682*82527734SSukumar Swaminathan /* Now that we are the owner, DMA Sync entire mailbox if needed */ 5683*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 5684*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, offset, 5685*82527734SSukumar Swaminathan MAILBOX_CMD_BSIZE, DDI_DMA_SYNC_FORKERNEL); 5686291a2b48SSukumar Swaminathan 5687*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox, (uint8_t *)mb, 5688*82527734SSukumar Swaminathan MAILBOX_CMD_BSIZE); 5689*82527734SSukumar Swaminathan } else { 5690*82527734SSukumar Swaminathan READ_SLIM_COPY(hba, (uint32_t *)mb, (uint32_t *)mbox, 5691*82527734SSukumar Swaminathan MAILBOX_CMD_WSIZE); 5692*82527734SSukumar Swaminathan } 5693291a2b48SSukumar Swaminathan 5694*82527734SSukumar Swaminathan #ifdef MBOX_EXT_SUPPORT 5695*82527734SSukumar Swaminathan if (mbq->extbuf) { 5696*82527734SSukumar Swaminathan uint32_t *mbox_ext = 5697*82527734SSukumar Swaminathan (uint32_t *)((uint8_t *)mbox + MBOX_EXTENSION_OFFSET); 5698*82527734SSukumar Swaminathan off_t offset_ext = offset + MBOX_EXTENSION_OFFSET; 5699291a2b48SSukumar Swaminathan 5700*82527734SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 5701*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 5702*82527734SSukumar Swaminathan offset_ext, mbq->extsize, 5703*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 5704*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *)mbox_ext, 5705*82527734SSukumar Swaminathan (uint8_t *)mbq->extbuf, mbq->extsize); 5706*82527734SSukumar Swaminathan } else { 5707*82527734SSukumar Swaminathan READ_SLIM_COPY(hba, (uint32_t *)mbq->extbuf, 5708*82527734SSukumar Swaminathan mbox_ext, (mbq->extsize / 4)); 5709291a2b48SSukumar Swaminathan } 5710*82527734SSukumar Swaminathan } 5711*82527734SSukumar Swaminathan #endif /* MBOX_EXT_SUPPORT */ 5712291a2b48SSukumar Swaminathan 57134baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 5714*82527734SSukumar Swaminathan if (!(hba->flag & FC_SLIM2_MODE)) { 5715*82527734SSukumar Swaminathan /* Access handle validation */ 5716*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 5717*82527734SSukumar Swaminathan } 57184baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5719291a2b48SSukumar Swaminathan 5720*82527734SSukumar Swaminathan /* Now sync the memory buffer if one was used */ 5721*82527734SSukumar Swaminathan if (mbq->bp) { 5722*82527734SSukumar Swaminathan mbox_bp = (MATCHMAP *)mbq->bp; 5723*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(mbox_bp->dma_handle, 0, mbox_bp->size, 5724*82527734SSukumar Swaminathan DDI_DMA_SYNC_FORKERNEL); 5725*82527734SSukumar Swaminathan } 5726291a2b48SSukumar Swaminathan 5727*82527734SSukumar Swaminathan /* Mailbox has been completely received at this point */ 5728291a2b48SSukumar Swaminathan 5729*82527734SSukumar Swaminathan if (mb->mbxCommand == MBX_HEARTBEAT) { 5730*82527734SSukumar Swaminathan hba->heartbeat_active = 0; 5731*82527734SSukumar Swaminathan goto done; 5732291a2b48SSukumar Swaminathan } 5733291a2b48SSukumar Swaminathan 5734*82527734SSukumar Swaminathan if (hba->mbox_queue_flag == MBX_SLEEP) { 5735*82527734SSukumar Swaminathan if (swpmb->mbxCommand != MBX_DOWN_LOAD && 5736*82527734SSukumar Swaminathan swpmb->mbxCommand != MBX_DUMP_MEMORY) { 5737*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5738*82527734SSukumar Swaminathan "Received. %s: status=%x Sleep.", 5739*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(swpmb->mbxCommand), 5740*82527734SSukumar Swaminathan swpmb->mbxStatus); 5741291a2b48SSukumar Swaminathan } 5742*82527734SSukumar Swaminathan } else { 5743*82527734SSukumar Swaminathan if (swpmb->mbxCommand != MBX_DOWN_LOAD && 5744*82527734SSukumar Swaminathan swpmb->mbxCommand != MBX_DUMP_MEMORY) { 5745*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5746*82527734SSukumar Swaminathan "Completed. %s: status=%x", 5747*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(swpmb->mbxCommand), 5748*82527734SSukumar Swaminathan swpmb->mbxStatus); 5749291a2b48SSukumar Swaminathan } 5750*82527734SSukumar Swaminathan } 5751291a2b48SSukumar Swaminathan 5752*82527734SSukumar Swaminathan /* Filter out passthru mailbox */ 5753*82527734SSukumar Swaminathan if (mbq->flag & MBQ_PASSTHRU) { 5754*82527734SSukumar Swaminathan goto done; 5755*82527734SSukumar Swaminathan } 5756291a2b48SSukumar Swaminathan 5757*82527734SSukumar Swaminathan if (mb->mbxStatus) { 5758*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5759*82527734SSukumar Swaminathan "%s: status=0x%x", emlxs_mb_cmd_xlate(mb->mbxCommand), 5760*82527734SSukumar Swaminathan (uint32_t)mb->mbxStatus); 5761*82527734SSukumar Swaminathan } 5762291a2b48SSukumar Swaminathan 5763*82527734SSukumar Swaminathan if (mbq->mbox_cmpl) { 5764*82527734SSukumar Swaminathan rc = (mbq->mbox_cmpl)(hba, mbq); 5765*82527734SSukumar Swaminathan /* If mbox was retried, return immediately */ 5766*82527734SSukumar Swaminathan if (rc) { 5767*82527734SSukumar Swaminathan return (0); 5768*82527734SSukumar Swaminathan } 5769*82527734SSukumar Swaminathan } 5770291a2b48SSukumar Swaminathan 5771*82527734SSukumar Swaminathan done: 5772291a2b48SSukumar Swaminathan 5773*82527734SSukumar Swaminathan /* Clean up the mailbox area */ 5774*82527734SSukumar Swaminathan emlxs_mb_fini(hba, mb, mb->mbxStatus); 5775*82527734SSukumar Swaminathan 5776*82527734SSukumar Swaminathan mbq = (MAILBOXQ *)emlxs_mb_get(hba); 5777*82527734SSukumar Swaminathan if (mbq) { 5778*82527734SSukumar Swaminathan /* Attempt to send pending mailboxes */ 5779*82527734SSukumar Swaminathan rc = emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_NOWAIT, 0); 5780*82527734SSukumar Swaminathan if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 5781*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 5782291a2b48SSukumar Swaminathan } 5783*82527734SSukumar Swaminathan } 5784*82527734SSukumar Swaminathan return (0); 5785291a2b48SSukumar Swaminathan 5786*82527734SSukumar Swaminathan } /* emlxs_handle_mb_event() */ 5787291a2b48SSukumar Swaminathan 5788291a2b48SSukumar Swaminathan 5789*82527734SSukumar Swaminathan extern void 5790*82527734SSukumar Swaminathan emlxs_sli3_timer(emlxs_hba_t *hba) 5791*82527734SSukumar Swaminathan { 5792*82527734SSukumar Swaminathan /* Perform SLI3 level timer checks */ 5793291a2b48SSukumar Swaminathan 5794*82527734SSukumar Swaminathan emlxs_sli3_timer_check_mbox(hba); 5795291a2b48SSukumar Swaminathan 5796*82527734SSukumar Swaminathan } /* emlxs_sli3_timer() */ 5797291a2b48SSukumar Swaminathan 5798*82527734SSukumar Swaminathan 5799*82527734SSukumar Swaminathan static void 5800*82527734SSukumar Swaminathan emlxs_sli3_timer_check_mbox(emlxs_hba_t *hba) 5801291a2b48SSukumar Swaminathan { 5802291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 5803291a2b48SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 5804*82527734SSukumar Swaminathan MAILBOX *mb = NULL; 5805291a2b48SSukumar Swaminathan uint32_t word0; 5806291a2b48SSukumar Swaminathan uint32_t offset; 5807291a2b48SSukumar Swaminathan uint32_t ha_copy = 0; 5808291a2b48SSukumar Swaminathan 5809291a2b48SSukumar Swaminathan if (!cfg[CFG_TIMEOUT_ENABLE].current) { 5810291a2b48SSukumar Swaminathan return; 5811291a2b48SSukumar Swaminathan } 5812291a2b48SSukumar Swaminathan 5813291a2b48SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 5814291a2b48SSukumar Swaminathan 5815291a2b48SSukumar Swaminathan /* Return if timer hasn't expired */ 5816291a2b48SSukumar Swaminathan if (!hba->mbox_timer || (hba->timer_tics < hba->mbox_timer)) { 5817291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5818291a2b48SSukumar Swaminathan return; 5819291a2b48SSukumar Swaminathan } 5820291a2b48SSukumar Swaminathan hba->mbox_timer = 0; 5821291a2b48SSukumar Swaminathan 5822291a2b48SSukumar Swaminathan /* Mailbox timed out, first check for error attention */ 5823291a2b48SSukumar Swaminathan ha_copy = emlxs_check_attention(hba); 5824291a2b48SSukumar Swaminathan 5825291a2b48SSukumar Swaminathan if (ha_copy & HA_ERATT) { 5826291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5827291a2b48SSukumar Swaminathan emlxs_handle_ff_error(hba); 5828291a2b48SSukumar Swaminathan return; 5829291a2b48SSukumar Swaminathan } 5830291a2b48SSukumar Swaminathan 5831291a2b48SSukumar Swaminathan if (hba->mbox_queue_flag) { 5832291a2b48SSukumar Swaminathan /* Get first word of mailbox */ 5833291a2b48SSukumar Swaminathan if (hba->flag & FC_SLIM2_MODE) { 5834291a2b48SSukumar Swaminathan mb = FC_SLIM2_MAILBOX(hba); 5835*82527734SSukumar Swaminathan offset = 5836*82527734SSukumar Swaminathan (off_t)((uint64_t)((unsigned long)mb) - (uint64_t) 5837*82527734SSukumar Swaminathan ((unsigned long)hba->sli.sli3.slim2.virt)); 5838291a2b48SSukumar Swaminathan 5839*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, 5840*82527734SSukumar Swaminathan offset, sizeof (uint32_t), DDI_DMA_SYNC_FORKERNEL); 5841291a2b48SSukumar Swaminathan word0 = *((volatile uint32_t *)mb); 5842*82527734SSukumar Swaminathan word0 = BE_SWAP32(word0); 5843291a2b48SSukumar Swaminathan } else { 5844291a2b48SSukumar Swaminathan mb = FC_SLIM1_MAILBOX(hba); 5845291a2b48SSukumar Swaminathan word0 = 5846291a2b48SSukumar Swaminathan READ_SLIM_ADDR(hba, ((volatile uint32_t *)mb)); 58474baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 58484baa2c25SSukumar Swaminathan /* Access handle validation */ 5849*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, 5850*82527734SSukumar Swaminathan hba->sli.sli3.slim_acc_handle); 58514baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 5852291a2b48SSukumar Swaminathan } 5853291a2b48SSukumar Swaminathan 5854291a2b48SSukumar Swaminathan mb = (MAILBOX *)&word0; 5855291a2b48SSukumar Swaminathan 5856291a2b48SSukumar Swaminathan /* Check if mailbox has actually completed */ 5857291a2b48SSukumar Swaminathan if (mb->mbxOwner == OWN_HOST) { 5858291a2b48SSukumar Swaminathan /* Read host attention register to determine */ 5859291a2b48SSukumar Swaminathan /* interrupt source */ 5860291a2b48SSukumar Swaminathan uint32_t ha_copy = emlxs_check_attention(hba); 5861291a2b48SSukumar Swaminathan 5862291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_detail_msg, 5863291a2b48SSukumar Swaminathan "Mailbox attention missed: %s. Forcing event. " 5864291a2b48SSukumar Swaminathan "hc=%x ha=%x", emlxs_mb_cmd_xlate(mb->mbxCommand), 5865*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy, ha_copy); 5866291a2b48SSukumar Swaminathan 5867291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5868291a2b48SSukumar Swaminathan 5869291a2b48SSukumar Swaminathan (void) emlxs_handle_mb_event(hba); 5870291a2b48SSukumar Swaminathan 5871291a2b48SSukumar Swaminathan return; 5872291a2b48SSukumar Swaminathan } 5873291a2b48SSukumar Swaminathan 5874291a2b48SSukumar Swaminathan if (hba->mbox_mbq) { 5875291a2b48SSukumar Swaminathan mb = (MAILBOX *)hba->mbox_mbq; 5876291a2b48SSukumar Swaminathan } 5877291a2b48SSukumar Swaminathan } 5878291a2b48SSukumar Swaminathan 5879*82527734SSukumar Swaminathan if (mb) { 5880*82527734SSukumar Swaminathan switch (hba->mbox_queue_flag) { 5881*82527734SSukumar Swaminathan case MBX_NOWAIT: 5882*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5883*82527734SSukumar Swaminathan "%s: Nowait.", 5884*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand)); 5885*82527734SSukumar Swaminathan break; 5886291a2b48SSukumar Swaminathan 5887*82527734SSukumar Swaminathan case MBX_SLEEP: 5888*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5889*82527734SSukumar Swaminathan "%s: mb=%p Sleep.", 5890*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), 5891*82527734SSukumar Swaminathan mb); 5892*82527734SSukumar Swaminathan break; 5893291a2b48SSukumar Swaminathan 5894*82527734SSukumar Swaminathan case MBX_POLL: 5895*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5896*82527734SSukumar Swaminathan "%s: mb=%p Polled.", 5897*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), 5898*82527734SSukumar Swaminathan mb); 5899*82527734SSukumar Swaminathan break; 5900291a2b48SSukumar Swaminathan 5901*82527734SSukumar Swaminathan default: 5902*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, 5903*82527734SSukumar Swaminathan "%s: mb=%p (%d).", 5904*82527734SSukumar Swaminathan emlxs_mb_cmd_xlate(mb->mbxCommand), 5905*82527734SSukumar Swaminathan mb, hba->mbox_queue_flag); 5906*82527734SSukumar Swaminathan break; 5907*82527734SSukumar Swaminathan } 5908*82527734SSukumar Swaminathan } else { 5909291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mbox_timeout_msg, NULL); 5910291a2b48SSukumar Swaminathan } 5911291a2b48SSukumar Swaminathan 5912291a2b48SSukumar Swaminathan hba->flag |= FC_MBOX_TIMEOUT; 5913*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE_LOCKED(hba, FC_ERROR); 5914291a2b48SSukumar Swaminathan 5915291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 5916291a2b48SSukumar Swaminathan 5917291a2b48SSukumar Swaminathan /* Perform mailbox cleanup */ 5918291a2b48SSukumar Swaminathan /* This will wake any sleeping or polling threads */ 5919291a2b48SSukumar Swaminathan emlxs_mb_fini(hba, NULL, MBX_TIMEOUT); 5920291a2b48SSukumar Swaminathan 5921291a2b48SSukumar Swaminathan /* Trigger adapter shutdown */ 5922bb63f56eSSukumar Swaminathan emlxs_thread_spawn(hba, emlxs_shutdown_thread, NULL, NULL); 5923291a2b48SSukumar Swaminathan 5924291a2b48SSukumar Swaminathan return; 5925291a2b48SSukumar Swaminathan 5926*82527734SSukumar Swaminathan } /* emlxs_sli3_timer_check_mbox() */ 5927291a2b48SSukumar Swaminathan 5928291a2b48SSukumar Swaminathan 5929291a2b48SSukumar Swaminathan /* 5930291a2b48SSukumar Swaminathan * emlxs_mb_config_port Issue a CONFIG_PORT mailbox command 5931291a2b48SSukumar Swaminathan */ 5932*82527734SSukumar Swaminathan static uint32_t 5933*82527734SSukumar Swaminathan emlxs_mb_config_port(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t sli_mode, 5934291a2b48SSukumar Swaminathan uint32_t hbainit) 5935291a2b48SSukumar Swaminathan { 5936*82527734SSukumar Swaminathan MAILBOX *mb = (MAILBOX *)mbq; 5937291a2b48SSukumar Swaminathan emlxs_vpd_t *vpd = &VPD; 5938291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 5939291a2b48SSukumar Swaminathan emlxs_config_t *cfg; 5940291a2b48SSukumar Swaminathan RING *rp; 5941291a2b48SSukumar Swaminathan uint64_t pcb; 5942291a2b48SSukumar Swaminathan uint64_t mbx; 5943291a2b48SSukumar Swaminathan uint64_t hgp; 5944291a2b48SSukumar Swaminathan uint64_t pgp; 5945291a2b48SSukumar Swaminathan uint64_t rgp; 5946291a2b48SSukumar Swaminathan MAILBOX *mbox; 5947291a2b48SSukumar Swaminathan SLIM2 *slim; 5948291a2b48SSukumar Swaminathan SLI2_RDSC *rdsc; 5949291a2b48SSukumar Swaminathan uint64_t offset; 5950291a2b48SSukumar Swaminathan uint32_t Laddr; 5951291a2b48SSukumar Swaminathan uint32_t i; 5952291a2b48SSukumar Swaminathan 5953291a2b48SSukumar Swaminathan cfg = &CFG; 5954291a2b48SSukumar Swaminathan bzero((void *)mb, MAILBOX_CMD_BSIZE); 5955291a2b48SSukumar Swaminathan mbox = NULL; 5956291a2b48SSukumar Swaminathan slim = NULL; 5957291a2b48SSukumar Swaminathan 5958291a2b48SSukumar Swaminathan mb->mbxCommand = MBX_CONFIG_PORT; 5959291a2b48SSukumar Swaminathan mb->mbxOwner = OWN_HOST; 5960*82527734SSukumar Swaminathan mbq->mbox_cmpl = NULL; 5961291a2b48SSukumar Swaminathan 5962291a2b48SSukumar Swaminathan mb->un.varCfgPort.pcbLen = sizeof (PCB); 5963291a2b48SSukumar Swaminathan mb->un.varCfgPort.hbainit[0] = hbainit; 5964291a2b48SSukumar Swaminathan 5965*82527734SSukumar Swaminathan pcb = hba->sli.sli3.slim2.phys + 5966*82527734SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->pcb)); 5967*82527734SSukumar Swaminathan mb->un.varCfgPort.pcbLow = PADDR_LO(pcb); 5968*82527734SSukumar Swaminathan mb->un.varCfgPort.pcbHigh = PADDR_HI(pcb); 5969291a2b48SSukumar Swaminathan 5970291a2b48SSukumar Swaminathan /* Set Host pointers in SLIM flag */ 5971291a2b48SSukumar Swaminathan mb->un.varCfgPort.hps = 1; 5972291a2b48SSukumar Swaminathan 5973291a2b48SSukumar Swaminathan /* Initialize hba structure for assumed default SLI2 mode */ 5974291a2b48SSukumar Swaminathan /* If config port succeeds, then we will update it then */ 5975291a2b48SSukumar Swaminathan hba->sli_mode = sli_mode; 5976*82527734SSukumar Swaminathan hba->vpi_max = 0; 5977291a2b48SSukumar Swaminathan hba->flag &= ~FC_NPIV_ENABLED; 5978291a2b48SSukumar Swaminathan 5979*82527734SSukumar Swaminathan if (sli_mode == EMLXS_HBA_SLI3_MODE) { 5980291a2b48SSukumar Swaminathan mb->un.varCfgPort.sli_mode = EMLXS_HBA_SLI3_MODE; 5981291a2b48SSukumar Swaminathan mb->un.varCfgPort.cerbm = 1; 5982291a2b48SSukumar Swaminathan mb->un.varCfgPort.max_hbq = EMLXS_NUM_HBQ; 5983291a2b48SSukumar Swaminathan 5984291a2b48SSukumar Swaminathan if (cfg[CFG_NPIV_ENABLE].current) { 5985291a2b48SSukumar Swaminathan if (vpd->feaLevelHigh >= 0x09) { 5986291a2b48SSukumar Swaminathan if (hba->model_info.chip >= EMLXS_SATURN_CHIP) { 5987291a2b48SSukumar Swaminathan mb->un.varCfgPort.vpi_max = 5988291a2b48SSukumar Swaminathan MAX_VPORTS - 1; 5989291a2b48SSukumar Swaminathan } else { 5990291a2b48SSukumar Swaminathan mb->un.varCfgPort.vpi_max = 5991291a2b48SSukumar Swaminathan MAX_VPORTS_LIMITED - 1; 5992291a2b48SSukumar Swaminathan } 5993291a2b48SSukumar Swaminathan 5994291a2b48SSukumar Swaminathan mb->un.varCfgPort.cmv = 1; 5995291a2b48SSukumar Swaminathan } else { 5996291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 5997291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 5998291a2b48SSukumar Swaminathan "CFGPORT: Firmware does not support NPIV. " 5999291a2b48SSukumar Swaminathan "level=%d", vpd->feaLevelHigh); 6000291a2b48SSukumar Swaminathan } 6001291a2b48SSukumar Swaminathan 6002291a2b48SSukumar Swaminathan } 6003291a2b48SSukumar Swaminathan } 6004291a2b48SSukumar Swaminathan 6005291a2b48SSukumar Swaminathan /* 6006291a2b48SSukumar Swaminathan * Now setup pcb 6007291a2b48SSukumar Swaminathan */ 6008*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.type = TYPE_NATIVE_SLI2; 6009*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.feature = FEATURE_INITIAL_SLI2; 6010*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.maxRing = 6011*82527734SSukumar Swaminathan (hba->sli.sli3.ring_count - 1); 6012*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mailBoxSize = 6013291a2b48SSukumar Swaminathan sizeof (MAILBOX) + MBOX_EXTENSION_SIZE; 6014291a2b48SSukumar Swaminathan 6015*82527734SSukumar Swaminathan mbx = hba->sli.sli3.slim2.phys + 6016*82527734SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->mbx)); 6017*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrHigh = PADDR_HI(mbx); 6018*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.mbAddrLow = PADDR_LO(mbx); 6019291a2b48SSukumar Swaminathan 6020291a2b48SSukumar Swaminathan 6021291a2b48SSukumar Swaminathan /* 6022291a2b48SSukumar Swaminathan * Set up HGP - Port Memory 6023291a2b48SSukumar Swaminathan * 6024291a2b48SSukumar Swaminathan * CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80 6025291a2b48SSukumar Swaminathan * RR0Get 0xc4 0x84 6026291a2b48SSukumar Swaminathan * CR1Put 0xc8 0x88 6027291a2b48SSukumar Swaminathan * RR1Get 0xcc 0x8c 6028291a2b48SSukumar Swaminathan * CR2Put 0xd0 0x90 6029291a2b48SSukumar Swaminathan * RR2Get 0xd4 0x94 6030291a2b48SSukumar Swaminathan * CR3Put 0xd8 0x98 6031291a2b48SSukumar Swaminathan * RR3Get 0xdc 0x9c 6032291a2b48SSukumar Swaminathan * 6033291a2b48SSukumar Swaminathan * Reserved 0xa0-0xbf 6034291a2b48SSukumar Swaminathan * 6035291a2b48SSukumar Swaminathan * If HBQs configured: 6036291a2b48SSukumar Swaminathan * HBQ 0 Put ptr 0xc0 6037291a2b48SSukumar Swaminathan * HBQ 1 Put ptr 0xc4 6038291a2b48SSukumar Swaminathan * HBQ 2 Put ptr 0xc8 6039291a2b48SSukumar Swaminathan * ... 6040291a2b48SSukumar Swaminathan * HBQ(M-1)Put Pointer 0xc0+(M-1)*4 6041291a2b48SSukumar Swaminathan */ 6042291a2b48SSukumar Swaminathan 6043291a2b48SSukumar Swaminathan if (sli_mode >= EMLXS_HBA_SLI3_MODE) { 6044291a2b48SSukumar Swaminathan /* ERBM is enabled */ 6045*82527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset = 0x80; 6046*82527734SSukumar Swaminathan hba->sli.sli3.hgp_hbq_offset = 0xC0; 6047291a2b48SSukumar Swaminathan 6048*82527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size = SLI3_IOCB_CMD_SIZE; 6049*82527734SSukumar Swaminathan hba->sli.sli3.iocb_rsp_size = SLI3_IOCB_RSP_SIZE; 6050291a2b48SSukumar Swaminathan 6051*82527734SSukumar Swaminathan } else { /* SLI2 */ 6052291a2b48SSukumar Swaminathan /* ERBM is disabled */ 6053*82527734SSukumar Swaminathan hba->sli.sli3.hgp_ring_offset = 0xC0; 6054*82527734SSukumar Swaminathan hba->sli.sli3.hgp_hbq_offset = 0; 6055291a2b48SSukumar Swaminathan 6056*82527734SSukumar Swaminathan hba->sli.sli3.iocb_cmd_size = SLI2_IOCB_CMD_SIZE; 6057*82527734SSukumar Swaminathan hba->sli.sli3.iocb_rsp_size = SLI2_IOCB_RSP_SIZE; 6058291a2b48SSukumar Swaminathan } 6059291a2b48SSukumar Swaminathan 6060291a2b48SSukumar Swaminathan /* The Sbus card uses Host Memory. The PCI card uses SLIM POINTER */ 6061291a2b48SSukumar Swaminathan if (hba->bus_type == SBUS_FC) { 6062*82527734SSukumar Swaminathan hgp = hba->sli.sli3.slim2.phys + 6063291a2b48SSukumar Swaminathan (uint64_t)((unsigned long)&(mbox->us.s2.host)); 6064*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh = 6065*82527734SSukumar Swaminathan PADDR_HI(hgp); 6066*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow = 6067*82527734SSukumar Swaminathan PADDR_LO(hgp); 6068291a2b48SSukumar Swaminathan } else { 6069*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrHigh = 6070291a2b48SSukumar Swaminathan (uint32_t)ddi_get32(hba->pci_acc_handle, 6071291a2b48SSukumar Swaminathan (uint32_t *)(hba->pci_addr + PCI_BAR_1_REGISTER)); 6072291a2b48SSukumar Swaminathan 6073291a2b48SSukumar Swaminathan Laddr = 6074291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 6075291a2b48SSukumar Swaminathan (uint32_t *)(hba->pci_addr + PCI_BAR_0_REGISTER)); 6076291a2b48SSukumar Swaminathan Laddr &= ~0x4; 6077*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.hgpAddrLow = 6078*82527734SSukumar Swaminathan (uint32_t)(Laddr + hba->sli.sli3.hgp_ring_offset); 6079291a2b48SSukumar Swaminathan 60804baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 60814baa2c25SSukumar Swaminathan /* Access handle validation */ 6082*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle); 60834baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6084*82527734SSukumar Swaminathan 6085291a2b48SSukumar Swaminathan } 6086291a2b48SSukumar Swaminathan 6087*82527734SSukumar Swaminathan pgp = hba->sli.sli3.slim2.phys + 6088*82527734SSukumar Swaminathan (uint64_t)((unsigned long)&(mbox->us.s2.port)); 6089*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrHigh = 6090*82527734SSukumar Swaminathan PADDR_HI(pgp); 6091*82527734SSukumar Swaminathan ((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.pgpAddrLow = 6092*82527734SSukumar Swaminathan PADDR_LO(pgp); 6093291a2b48SSukumar Swaminathan 6094291a2b48SSukumar Swaminathan offset = 0; 6095291a2b48SSukumar Swaminathan for (i = 0; i < 4; i++) { 6096*82527734SSukumar Swaminathan rp = &hba->sli.sli3.ring[i]; 6097*82527734SSukumar Swaminathan rdsc = &((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb.rdsc[i]; 6098291a2b48SSukumar Swaminathan 6099291a2b48SSukumar Swaminathan /* Setup command ring */ 6100*82527734SSukumar Swaminathan rgp = hba->sli.sli3.slim2.phys + 6101291a2b48SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->IOCBs[offset])); 6102*82527734SSukumar Swaminathan rdsc->cmdAddrHigh = PADDR_HI(rgp); 6103*82527734SSukumar Swaminathan rdsc->cmdAddrLow = PADDR_LO(rgp); 6104291a2b48SSukumar Swaminathan rdsc->cmdEntries = rp->fc_numCiocb; 6105291a2b48SSukumar Swaminathan 6106291a2b48SSukumar Swaminathan rp->fc_cmdringaddr = 6107*82527734SSukumar Swaminathan (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset]; 6108*82527734SSukumar Swaminathan offset += rdsc->cmdEntries * hba->sli.sli3.iocb_cmd_size; 6109291a2b48SSukumar Swaminathan 6110291a2b48SSukumar Swaminathan /* Setup response ring */ 6111*82527734SSukumar Swaminathan rgp = hba->sli.sli3.slim2.phys + 6112291a2b48SSukumar Swaminathan (uint64_t)((unsigned long)&(slim->IOCBs[offset])); 6113*82527734SSukumar Swaminathan rdsc->rspAddrHigh = PADDR_HI(rgp); 6114*82527734SSukumar Swaminathan rdsc->rspAddrLow = PADDR_LO(rgp); 6115291a2b48SSukumar Swaminathan rdsc->rspEntries = rp->fc_numRiocb; 6116291a2b48SSukumar Swaminathan 6117291a2b48SSukumar Swaminathan rp->fc_rspringaddr = 6118*82527734SSukumar Swaminathan (void *)&((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs[offset]; 6119*82527734SSukumar Swaminathan offset += rdsc->rspEntries * hba->sli.sli3.iocb_rsp_size; 6120291a2b48SSukumar Swaminathan } 6121291a2b48SSukumar Swaminathan 6122*82527734SSukumar Swaminathan BE_SWAP32_BCOPY((uint8_t *) 6123*82527734SSukumar Swaminathan (&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb), 6124*82527734SSukumar Swaminathan (uint8_t *)(&((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb), 6125*82527734SSukumar Swaminathan sizeof (PCB)); 6126291a2b48SSukumar Swaminathan 6127*82527734SSukumar Swaminathan offset = ((uint64_t)((unsigned long) 6128*82527734SSukumar Swaminathan &(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb)) - 6129*82527734SSukumar Swaminathan (uint64_t)((unsigned long)hba->sli.sli3.slim2.virt)); 6130*82527734SSukumar Swaminathan EMLXS_MPDATA_SYNC(hba->sli.sli3.slim2.dma_handle, (off_t)offset, 6131*82527734SSukumar Swaminathan sizeof (PCB), DDI_DMA_SYNC_FORDEV); 6132291a2b48SSukumar Swaminathan 6133291a2b48SSukumar Swaminathan return (0); 6134291a2b48SSukumar Swaminathan 6135291a2b48SSukumar Swaminathan } /* emlxs_mb_config_port() */ 6136291a2b48SSukumar Swaminathan 6137291a2b48SSukumar Swaminathan 6138*82527734SSukumar Swaminathan static uint32_t 6139291a2b48SSukumar Swaminathan emlxs_hbq_setup(emlxs_hba_t *hba, uint32_t hbq_id) 6140291a2b48SSukumar Swaminathan { 6141291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 6142291a2b48SSukumar Swaminathan HBQ_INIT_t *hbq; 6143291a2b48SSukumar Swaminathan MATCHMAP *mp; 6144291a2b48SSukumar Swaminathan HBQE_t *hbqE; 6145291a2b48SSukumar Swaminathan MAILBOX *mb; 6146*82527734SSukumar Swaminathan MAILBOXQ *mbq; 6147291a2b48SSukumar Swaminathan void *ioa2; 6148291a2b48SSukumar Swaminathan uint32_t j; 6149291a2b48SSukumar Swaminathan uint32_t count; 6150291a2b48SSukumar Swaminathan uint32_t size; 6151291a2b48SSukumar Swaminathan uint32_t ringno; 6152291a2b48SSukumar Swaminathan uint32_t seg; 6153291a2b48SSukumar Swaminathan 6154291a2b48SSukumar Swaminathan switch (hbq_id) { 6155291a2b48SSukumar Swaminathan case EMLXS_ELS_HBQ_ID: 6156291a2b48SSukumar Swaminathan count = MEM_ELSBUF_COUNT; 6157291a2b48SSukumar Swaminathan size = MEM_ELSBUF_SIZE; 6158291a2b48SSukumar Swaminathan ringno = FC_ELS_RING; 6159291a2b48SSukumar Swaminathan seg = MEM_ELSBUF; 6160291a2b48SSukumar Swaminathan HBASTATS.ElsUbPosted = count; 6161291a2b48SSukumar Swaminathan break; 6162291a2b48SSukumar Swaminathan 6163291a2b48SSukumar Swaminathan case EMLXS_IP_HBQ_ID: 6164291a2b48SSukumar Swaminathan count = MEM_IPBUF_COUNT; 6165291a2b48SSukumar Swaminathan size = MEM_IPBUF_SIZE; 6166291a2b48SSukumar Swaminathan ringno = FC_IP_RING; 6167291a2b48SSukumar Swaminathan seg = MEM_IPBUF; 6168291a2b48SSukumar Swaminathan HBASTATS.IpUbPosted = count; 6169291a2b48SSukumar Swaminathan break; 6170291a2b48SSukumar Swaminathan 6171291a2b48SSukumar Swaminathan case EMLXS_CT_HBQ_ID: 6172291a2b48SSukumar Swaminathan count = MEM_CTBUF_COUNT; 6173291a2b48SSukumar Swaminathan size = MEM_CTBUF_SIZE; 6174291a2b48SSukumar Swaminathan ringno = FC_CT_RING; 6175291a2b48SSukumar Swaminathan seg = MEM_CTBUF; 6176291a2b48SSukumar Swaminathan HBASTATS.CtUbPosted = count; 6177291a2b48SSukumar Swaminathan break; 6178291a2b48SSukumar Swaminathan 6179291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 6180291a2b48SSukumar Swaminathan case EMLXS_FCT_HBQ_ID: 6181291a2b48SSukumar Swaminathan count = MEM_FCTBUF_COUNT; 6182291a2b48SSukumar Swaminathan size = MEM_FCTBUF_SIZE; 6183291a2b48SSukumar Swaminathan ringno = FC_FCT_RING; 6184291a2b48SSukumar Swaminathan seg = MEM_FCTBUF; 6185291a2b48SSukumar Swaminathan HBASTATS.FctUbPosted = count; 6186291a2b48SSukumar Swaminathan break; 6187291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 6188291a2b48SSukumar Swaminathan 6189291a2b48SSukumar Swaminathan default: 6190291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6191291a2b48SSukumar Swaminathan "emlxs_hbq_setup: Invalid HBQ id. (%x)", hbq_id); 6192291a2b48SSukumar Swaminathan return (1); 6193291a2b48SSukumar Swaminathan } 6194291a2b48SSukumar Swaminathan 6195291a2b48SSukumar Swaminathan /* Configure HBQ */ 6196*82527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6197291a2b48SSukumar Swaminathan hbq->HBQ_numEntries = count; 6198291a2b48SSukumar Swaminathan 6199291a2b48SSukumar Swaminathan /* Get a Mailbox buffer to setup mailbox commands for CONFIG_HBQ */ 6200*82527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) { 6201291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6202291a2b48SSukumar Swaminathan "emlxs_hbq_setup: Unable to get mailbox."); 6203291a2b48SSukumar Swaminathan return (1); 6204291a2b48SSukumar Swaminathan } 6205*82527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 6206291a2b48SSukumar Swaminathan 6207291a2b48SSukumar Swaminathan /* Allocate HBQ Host buffer and Initialize the HBQEs */ 6208291a2b48SSukumar Swaminathan if (emlxs_hbq_alloc(hba, hbq_id)) { 6209291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6210291a2b48SSukumar Swaminathan "emlxs_hbq_setup: Unable to allocate HBQ."); 6211*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 6212291a2b48SSukumar Swaminathan return (1); 6213291a2b48SSukumar Swaminathan } 6214291a2b48SSukumar Swaminathan 6215291a2b48SSukumar Swaminathan hbq->HBQ_recvNotify = 1; 6216291a2b48SSukumar Swaminathan hbq->HBQ_num_mask = 0; /* Bind to ring */ 6217291a2b48SSukumar Swaminathan hbq->HBQ_profile = 0; /* Selection profile */ 6218291a2b48SSukumar Swaminathan /* 0=all, 7=logentry */ 6219291a2b48SSukumar Swaminathan hbq->HBQ_ringMask = 1 << ringno; /* b0100 * ringno - Binds */ 6220291a2b48SSukumar Swaminathan /* HBQ to a ring */ 6221291a2b48SSukumar Swaminathan /* Ring0=b0001, Ring1=b0010, */ 6222291a2b48SSukumar Swaminathan /* Ring2=b0100 */ 6223291a2b48SSukumar Swaminathan hbq->HBQ_headerLen = 0; /* 0 if not profile 4 or 5 */ 6224291a2b48SSukumar Swaminathan hbq->HBQ_logEntry = 0; /* Set to 1 if this HBQ will */ 6225291a2b48SSukumar Swaminathan /* be used for */ 6226291a2b48SSukumar Swaminathan hbq->HBQ_id = hbq_id; 6227291a2b48SSukumar Swaminathan hbq->HBQ_PutIdx_next = 0; 6228291a2b48SSukumar Swaminathan hbq->HBQ_PutIdx = hbq->HBQ_numEntries - 1; 6229291a2b48SSukumar Swaminathan hbq->HBQ_GetIdx = 0; 6230291a2b48SSukumar Swaminathan hbq->HBQ_PostBufCnt = hbq->HBQ_numEntries; 6231291a2b48SSukumar Swaminathan bzero(hbq->HBQ_PostBufs, sizeof (hbq->HBQ_PostBufs)); 6232291a2b48SSukumar Swaminathan 6233291a2b48SSukumar Swaminathan /* Fill in POST BUFFERs in HBQE */ 6234291a2b48SSukumar Swaminathan hbqE = (HBQE_t *)hbq->HBQ_host_buf.virt; 6235291a2b48SSukumar Swaminathan for (j = 0; j < hbq->HBQ_numEntries; j++, hbqE++) { 6236291a2b48SSukumar Swaminathan /* Allocate buffer to post */ 6237291a2b48SSukumar Swaminathan if ((mp = (MATCHMAP *)emlxs_mem_get(hba, 6238*82527734SSukumar Swaminathan seg, 1)) == 0) { 6239291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_msg, 6240291a2b48SSukumar Swaminathan "emlxs_hbq_setup: Unable to allocate HBQ buffer. " 6241291a2b48SSukumar Swaminathan "cnt=%d", j); 6242291a2b48SSukumar Swaminathan emlxs_hbq_free_all(hba, hbq_id); 6243291a2b48SSukumar Swaminathan return (1); 6244291a2b48SSukumar Swaminathan } 6245291a2b48SSukumar Swaminathan 6246291a2b48SSukumar Swaminathan hbq->HBQ_PostBufs[j] = mp; 6247291a2b48SSukumar Swaminathan 6248291a2b48SSukumar Swaminathan hbqE->unt.ext.HBQ_tag = hbq_id; 6249291a2b48SSukumar Swaminathan hbqE->unt.ext.HBQE_tag = j; 6250291a2b48SSukumar Swaminathan hbqE->bde.tus.f.bdeSize = size; 6251291a2b48SSukumar Swaminathan hbqE->bde.tus.f.bdeFlags = 0; 6252*82527734SSukumar Swaminathan hbqE->unt.w = BE_SWAP32(hbqE->unt.w); 6253*82527734SSukumar Swaminathan hbqE->bde.tus.w = BE_SWAP32(hbqE->bde.tus.w); 6254291a2b48SSukumar Swaminathan hbqE->bde.addrLow = 6255*82527734SSukumar Swaminathan BE_SWAP32(PADDR_LO(mp->phys)); 6256291a2b48SSukumar Swaminathan hbqE->bde.addrHigh = 6257*82527734SSukumar Swaminathan BE_SWAP32(PADDR_HI(mp->phys)); 6258291a2b48SSukumar Swaminathan } 6259291a2b48SSukumar Swaminathan 6260291a2b48SSukumar Swaminathan /* Issue CONFIG_HBQ */ 6261*82527734SSukumar Swaminathan emlxs_mb_config_hbq(hba, mbq, hbq_id); 6262*82527734SSukumar Swaminathan if (emlxs_sli3_issue_mbox_cmd(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 6263291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 6264291a2b48SSukumar Swaminathan "emlxs_hbq_setup: Unable to config HBQ. cmd=%x status=%x", 6265291a2b48SSukumar Swaminathan mb->mbxCommand, mb->mbxStatus); 6266291a2b48SSukumar Swaminathan 6267*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 6268291a2b48SSukumar Swaminathan emlxs_hbq_free_all(hba, hbq_id); 6269291a2b48SSukumar Swaminathan return (1); 6270291a2b48SSukumar Swaminathan } 6271291a2b48SSukumar Swaminathan 6272291a2b48SSukumar Swaminathan /* Setup HBQ Get/Put indexes */ 6273*82527734SSukumar Swaminathan ioa2 = (void *)((char *)hba->sli.sli3.slim_addr + 6274*82527734SSukumar Swaminathan (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t)))); 6275291a2b48SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, hbq->HBQ_PutIdx); 6276291a2b48SSukumar Swaminathan 6277*82527734SSukumar Swaminathan hba->sli.sli3.hbq_count++; 6278291a2b48SSukumar Swaminathan 6279*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 6280291a2b48SSukumar Swaminathan 62814baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 62824baa2c25SSukumar Swaminathan /* Access handle validation */ 6283*82527734SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 62844baa2c25SSukumar Swaminathan != DDI_FM_OK) { 62854baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 62864baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 62874baa2c25SSukumar Swaminathan emlxs_hbq_free_all(hba, hbq_id); 62884baa2c25SSukumar Swaminathan return (1); 62894baa2c25SSukumar Swaminathan } 62904baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 62914baa2c25SSukumar Swaminathan 6292291a2b48SSukumar Swaminathan return (0); 6293291a2b48SSukumar Swaminathan 6294*82527734SSukumar Swaminathan } /* emlxs_hbq_setup() */ 6295291a2b48SSukumar Swaminathan 6296291a2b48SSukumar Swaminathan 6297*82527734SSukumar Swaminathan extern void 6298291a2b48SSukumar Swaminathan emlxs_hbq_free_all(emlxs_hba_t *hba, uint32_t hbq_id) 6299291a2b48SSukumar Swaminathan { 6300291a2b48SSukumar Swaminathan HBQ_INIT_t *hbq; 6301291a2b48SSukumar Swaminathan MBUF_INFO *buf_info; 6302291a2b48SSukumar Swaminathan MBUF_INFO bufinfo; 6303291a2b48SSukumar Swaminathan uint32_t seg; 6304291a2b48SSukumar Swaminathan uint32_t j; 6305291a2b48SSukumar Swaminathan 6306291a2b48SSukumar Swaminathan switch (hbq_id) { 6307291a2b48SSukumar Swaminathan case EMLXS_ELS_HBQ_ID: 6308291a2b48SSukumar Swaminathan seg = MEM_ELSBUF; 6309291a2b48SSukumar Swaminathan HBASTATS.ElsUbPosted = 0; 6310291a2b48SSukumar Swaminathan break; 6311291a2b48SSukumar Swaminathan 6312291a2b48SSukumar Swaminathan case EMLXS_IP_HBQ_ID: 6313291a2b48SSukumar Swaminathan seg = MEM_IPBUF; 6314291a2b48SSukumar Swaminathan HBASTATS.IpUbPosted = 0; 6315291a2b48SSukumar Swaminathan break; 6316291a2b48SSukumar Swaminathan 6317291a2b48SSukumar Swaminathan case EMLXS_CT_HBQ_ID: 6318291a2b48SSukumar Swaminathan seg = MEM_CTBUF; 6319291a2b48SSukumar Swaminathan HBASTATS.CtUbPosted = 0; 6320291a2b48SSukumar Swaminathan break; 6321291a2b48SSukumar Swaminathan 6322291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 6323291a2b48SSukumar Swaminathan case EMLXS_FCT_HBQ_ID: 6324291a2b48SSukumar Swaminathan seg = MEM_FCTBUF; 6325291a2b48SSukumar Swaminathan HBASTATS.FctUbPosted = 0; 6326291a2b48SSukumar Swaminathan break; 6327291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 6328291a2b48SSukumar Swaminathan 6329291a2b48SSukumar Swaminathan default: 6330291a2b48SSukumar Swaminathan return; 6331291a2b48SSukumar Swaminathan } 6332291a2b48SSukumar Swaminathan 6333291a2b48SSukumar Swaminathan 6334*82527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6335291a2b48SSukumar Swaminathan 6336291a2b48SSukumar Swaminathan if (hbq->HBQ_host_buf.virt != 0) { 6337291a2b48SSukumar Swaminathan for (j = 0; j < hbq->HBQ_PostBufCnt; j++) { 6338291a2b48SSukumar Swaminathan (void) emlxs_mem_put(hba, seg, 6339291a2b48SSukumar Swaminathan (uint8_t *)hbq->HBQ_PostBufs[j]); 6340291a2b48SSukumar Swaminathan hbq->HBQ_PostBufs[j] = NULL; 6341291a2b48SSukumar Swaminathan } 6342291a2b48SSukumar Swaminathan hbq->HBQ_PostBufCnt = 0; 6343291a2b48SSukumar Swaminathan 6344291a2b48SSukumar Swaminathan buf_info = &bufinfo; 6345291a2b48SSukumar Swaminathan bzero(buf_info, sizeof (MBUF_INFO)); 6346291a2b48SSukumar Swaminathan 6347291a2b48SSukumar Swaminathan buf_info->size = hbq->HBQ_host_buf.size; 6348291a2b48SSukumar Swaminathan buf_info->virt = hbq->HBQ_host_buf.virt; 6349291a2b48SSukumar Swaminathan buf_info->phys = hbq->HBQ_host_buf.phys; 6350291a2b48SSukumar Swaminathan buf_info->dma_handle = hbq->HBQ_host_buf.dma_handle; 6351291a2b48SSukumar Swaminathan buf_info->data_handle = hbq->HBQ_host_buf.data_handle; 6352291a2b48SSukumar Swaminathan buf_info->flags = FC_MBUF_DMA; 6353291a2b48SSukumar Swaminathan 6354291a2b48SSukumar Swaminathan emlxs_mem_free(hba, buf_info); 6355291a2b48SSukumar Swaminathan 6356291a2b48SSukumar Swaminathan hbq->HBQ_host_buf.virt = NULL; 6357291a2b48SSukumar Swaminathan } 6358291a2b48SSukumar Swaminathan 6359291a2b48SSukumar Swaminathan return; 6360291a2b48SSukumar Swaminathan 6361*82527734SSukumar Swaminathan } /* emlxs_hbq_free_all() */ 6362291a2b48SSukumar Swaminathan 6363291a2b48SSukumar Swaminathan 6364*82527734SSukumar Swaminathan extern void 6365291a2b48SSukumar Swaminathan emlxs_update_HBQ_index(emlxs_hba_t *hba, uint32_t hbq_id) 6366291a2b48SSukumar Swaminathan { 63674baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 63684baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 63694baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6370291a2b48SSukumar Swaminathan void *ioa2; 6371291a2b48SSukumar Swaminathan uint32_t status; 6372291a2b48SSukumar Swaminathan uint32_t HBQ_PortGetIdx; 6373291a2b48SSukumar Swaminathan HBQ_INIT_t *hbq; 6374291a2b48SSukumar Swaminathan 6375291a2b48SSukumar Swaminathan switch (hbq_id) { 6376291a2b48SSukumar Swaminathan case EMLXS_ELS_HBQ_ID: 6377291a2b48SSukumar Swaminathan HBASTATS.ElsUbPosted++; 6378291a2b48SSukumar Swaminathan break; 6379291a2b48SSukumar Swaminathan 6380291a2b48SSukumar Swaminathan case EMLXS_IP_HBQ_ID: 6381291a2b48SSukumar Swaminathan HBASTATS.IpUbPosted++; 6382291a2b48SSukumar Swaminathan break; 6383291a2b48SSukumar Swaminathan 6384291a2b48SSukumar Swaminathan case EMLXS_CT_HBQ_ID: 6385291a2b48SSukumar Swaminathan HBASTATS.CtUbPosted++; 6386291a2b48SSukumar Swaminathan break; 6387291a2b48SSukumar Swaminathan 6388291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 6389291a2b48SSukumar Swaminathan case EMLXS_FCT_HBQ_ID: 6390291a2b48SSukumar Swaminathan HBASTATS.FctUbPosted++; 6391291a2b48SSukumar Swaminathan break; 6392291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 6393291a2b48SSukumar Swaminathan 6394291a2b48SSukumar Swaminathan default: 6395291a2b48SSukumar Swaminathan return; 6396291a2b48SSukumar Swaminathan } 6397291a2b48SSukumar Swaminathan 6398*82527734SSukumar Swaminathan hbq = &hba->sli.sli3.hbq_table[hbq_id]; 6399291a2b48SSukumar Swaminathan 6400291a2b48SSukumar Swaminathan hbq->HBQ_PutIdx = 6401291a2b48SSukumar Swaminathan (hbq->HBQ_PutIdx + 1 >= 6402291a2b48SSukumar Swaminathan hbq->HBQ_numEntries) ? 0 : hbq->HBQ_PutIdx + 1; 6403291a2b48SSukumar Swaminathan 6404291a2b48SSukumar Swaminathan if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) { 6405291a2b48SSukumar Swaminathan HBQ_PortGetIdx = 6406*82527734SSukumar Swaminathan BE_SWAP32(((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2. 6407291a2b48SSukumar Swaminathan HBQ_PortGetIdx[hbq_id]); 6408291a2b48SSukumar Swaminathan 6409291a2b48SSukumar Swaminathan hbq->HBQ_GetIdx = HBQ_PortGetIdx; 6410291a2b48SSukumar Swaminathan 6411291a2b48SSukumar Swaminathan if (hbq->HBQ_PutIdx == hbq->HBQ_GetIdx) { 6412291a2b48SSukumar Swaminathan return; 6413291a2b48SSukumar Swaminathan } 6414291a2b48SSukumar Swaminathan } 6415291a2b48SSukumar Swaminathan 6416*82527734SSukumar Swaminathan ioa2 = (void *)((char *)hba->sli.sli3.slim_addr + 6417*82527734SSukumar Swaminathan (hba->sli.sli3.hgp_hbq_offset + (hbq_id * sizeof (uint32_t)))); 6418291a2b48SSukumar Swaminathan status = hbq->HBQ_PutIdx; 6419291a2b48SSukumar Swaminathan WRITE_SLIM_ADDR(hba, (volatile uint32_t *)ioa2, status); 6420291a2b48SSukumar Swaminathan 64214baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64224baa2c25SSukumar Swaminathan /* Access handle validation */ 6423*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.slim_acc_handle); 64244baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 64254baa2c25SSukumar Swaminathan 6426291a2b48SSukumar Swaminathan return; 6427291a2b48SSukumar Swaminathan 6428*82527734SSukumar Swaminathan } /* emlxs_update_HBQ_index() */ 6429291a2b48SSukumar Swaminathan 6430291a2b48SSukumar Swaminathan 6431*82527734SSukumar Swaminathan static void 6432*82527734SSukumar Swaminathan emlxs_sli3_enable_intr(emlxs_hba_t *hba) 6433291a2b48SSukumar Swaminathan { 64344baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64354baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 64364baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6437291a2b48SSukumar Swaminathan uint32_t status; 6438291a2b48SSukumar Swaminathan 6439291a2b48SSukumar Swaminathan /* Enable mailbox, error attention interrupts */ 6440*82527734SSukumar Swaminathan status = (uint32_t)(HC_MBINT_ENA); 6441291a2b48SSukumar Swaminathan 6442291a2b48SSukumar Swaminathan /* Enable ring interrupts */ 6443*82527734SSukumar Swaminathan if (hba->sli.sli3.ring_count >= 4) { 6444291a2b48SSukumar Swaminathan status |= 6445291a2b48SSukumar Swaminathan (HC_R3INT_ENA | HC_R2INT_ENA | HC_R1INT_ENA | 6446291a2b48SSukumar Swaminathan HC_R0INT_ENA); 6447*82527734SSukumar Swaminathan } else if (hba->sli.sli3.ring_count == 3) { 6448291a2b48SSukumar Swaminathan status |= (HC_R2INT_ENA | HC_R1INT_ENA | HC_R0INT_ENA); 6449*82527734SSukumar Swaminathan } else if (hba->sli.sli3.ring_count == 2) { 6450291a2b48SSukumar Swaminathan status |= (HC_R1INT_ENA | HC_R0INT_ENA); 6451*82527734SSukumar Swaminathan } else if (hba->sli.sli3.ring_count == 1) { 6452291a2b48SSukumar Swaminathan status |= (HC_R0INT_ENA); 6453291a2b48SSukumar Swaminathan } 6454291a2b48SSukumar Swaminathan 6455*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy = status; 6456*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 64574baa2c25SSukumar Swaminathan 64584baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64594baa2c25SSukumar Swaminathan /* Access handle validation */ 6460*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 64614baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6462291a2b48SSukumar Swaminathan 6463*82527734SSukumar Swaminathan } /* emlxs_sli3_enable_intr() */ 6464*82527734SSukumar Swaminathan 6465*82527734SSukumar Swaminathan 6466*82527734SSukumar Swaminathan static void 6467291a2b48SSukumar Swaminathan emlxs_enable_latt(emlxs_hba_t *hba) 6468291a2b48SSukumar Swaminathan { 64694baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64704baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 64714baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 64724baa2c25SSukumar Swaminathan 6473291a2b48SSukumar Swaminathan mutex_enter(&EMLXS_PORT_LOCK); 6474*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy |= HC_LAINT_ENA; 6475*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 64764baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64774baa2c25SSukumar Swaminathan /* Access handle validation */ 6478*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 64794baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6480291a2b48SSukumar Swaminathan mutex_exit(&EMLXS_PORT_LOCK); 6481291a2b48SSukumar Swaminathan 6482*82527734SSukumar Swaminathan } /* emlxs_enable_latt() */ 6483*82527734SSukumar Swaminathan 6484*82527734SSukumar Swaminathan 6485*82527734SSukumar Swaminathan static void 6486*82527734SSukumar Swaminathan emlxs_sli3_disable_intr(emlxs_hba_t *hba, uint32_t att) 6487291a2b48SSukumar Swaminathan { 64884baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64894baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 64904baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 64914baa2c25SSukumar Swaminathan 6492291a2b48SSukumar Swaminathan /* Disable all adapter interrupts */ 6493*82527734SSukumar Swaminathan hba->sli.sli3.hc_copy = att; 6494*82527734SSukumar Swaminathan WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy); 64954baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 64964baa2c25SSukumar Swaminathan /* Access handle validation */ 6497*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 64984baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6499291a2b48SSukumar Swaminathan 6500*82527734SSukumar Swaminathan } /* emlxs_sli3_disable_intr() */ 6501*82527734SSukumar Swaminathan 6502*82527734SSukumar Swaminathan 6503*82527734SSukumar Swaminathan static uint32_t 6504291a2b48SSukumar Swaminathan emlxs_check_attention(emlxs_hba_t *hba) 6505291a2b48SSukumar Swaminathan { 65064baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 65074baa2c25SSukumar Swaminathan emlxs_port_t *port = &PPORT; 65084baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6509291a2b48SSukumar Swaminathan uint32_t ha_copy; 6510291a2b48SSukumar Swaminathan 6511*82527734SSukumar Swaminathan ha_copy = READ_CSR_REG(hba, FC_HA_REG(hba)); 65124baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 65134baa2c25SSukumar Swaminathan /* Access handle validation */ 6514*82527734SSukumar Swaminathan EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle); 65154baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 6516291a2b48SSukumar Swaminathan return (ha_copy); 6517*82527734SSukumar Swaminathan 6518*82527734SSukumar Swaminathan } /* emlxs_check_attention() */ 6519*82527734SSukumar Swaminathan 6520*82527734SSukumar Swaminathan void 6521*82527734SSukumar Swaminathan emlxs_sli3_poll_erratt(emlxs_hba_t *hba) 6522*82527734SSukumar Swaminathan { 6523*82527734SSukumar Swaminathan uint32_t ha_copy; 6524*82527734SSukumar Swaminathan 6525*82527734SSukumar Swaminathan ha_copy = emlxs_check_attention(hba); 6526*82527734SSukumar Swaminathan 6527*82527734SSukumar Swaminathan /* Adapter error */ 6528*82527734SSukumar Swaminathan if (ha_copy & HA_ERATT) { 6529*82527734SSukumar Swaminathan HBASTATS.IntrEvent[6]++; 6530*82527734SSukumar Swaminathan emlxs_handle_ff_error(hba); 6531*82527734SSukumar Swaminathan } 6532291a2b48SSukumar Swaminathan } 6533