Print this page
8368 remove warlock leftovers from usr/src/uts


  58     uint16_t token, int *hwerr);
  59 static void hermon_mbox_sync(hermon_mbox_t *mbox, uint_t offset,
  60     uint_t length, uint_t flag);
  61 static void hermon_cmd_check_status(hermon_state_t *state, int status);
  62 
  63 /*
  64  * hermon_cmd_post()
  65  *    Context: Can be called from interrupt or base context.
  66  *
  67  *    The "cp_flags" field in cmdpost
  68  *    is used to determine whether to wait for an available
  69  *    outstanding command (if necessary) or to return error.
  70  */
  71 int
  72 hermon_cmd_post(hermon_state_t *state, hermon_cmd_post_t *cmdpost)
  73 {
  74         hermon_cmd_t    *cmdptr;
  75         int             status, retry_cnt, retry_cnt2, hw_err;
  76         uint16_t        token;
  77 
  78         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdpost))
  79 
  80         /* Determine if we are going to spin until completion */
  81         if (cmdpost->cp_flags == HERMON_CMD_NOSLEEP_SPIN) {
  82 
  83                 /* Write the command to the HCR */
  84                 retry_cnt = HCA_PIO_RETRY_CNT;
  85                 do {
  86                         status = hermon_write_hcr(state, cmdpost, 0, &hw_err);
  87                 } while (status == HERMON_CMD_INTERNAL_ERR && retry_cnt-- > 0);
  88 
  89                 /* Check if there is an error status in hermon_write_hcr() */
  90                 if (status != HERMON_CMD_SUCCESS) {
  91                         /*
  92                          * If there is a HW error, call hermon_cmd_retry_ok()
  93                          * to check the side-effect of the operation retry.
  94                          */
  95                         if ((retry_cnt == HCA_PIO_RETRY_CNT &&
  96                             hw_err == HCA_PIO_OK) ||
  97                             !hermon_cmd_retry_ok(cmdpost, status)) {
  98                                 hermon_cmd_check_status(state, status);
  99                                 return (status);
 100                         }
 101                 /* Check if there is a transient internal error */
 102                 } else if (retry_cnt != HCA_PIO_RETRY_CNT) {
 103                         hermon_fm_ereport(state, HCA_IBA_ERR,
 104                             HCA_ERR_TRANSIENT);
 105                 }
 106 
 107         } else {  /* "HERMON_CMD_SLEEP_NOSPIN" */
 108                 ASSERT(HERMON_SLEEPFLAG_FOR_CONTEXT() != HERMON_NOSLEEP);
 109 
 110                 /* NOTE: Expect threads to be waiting in here */
 111                 status = hermon_outstanding_cmd_alloc(state, &cmdptr,
 112                     cmdpost->cp_flags);
 113                 if (status != HERMON_CMD_SUCCESS) {
 114                         return (status);
 115                 }
 116                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdptr))
 117 
 118                 retry_cnt = HCA_PIO_RETRY_CNT;
 119 retry:
 120                 /*
 121                  * Set status to "HERMON_CMD_INVALID_STATUS".  It is
 122                  * appropriate to do this here without the "cmd_comp_lock"
 123                  * because this register is overloaded.  Later it will be
 124                  * used to indicate - through a change from this invalid
 125                  * value to some other value - that the condition variable
 126                  * has been signaled.  Once it has, status will then contain
 127                  * the _real_ completion status
 128                  */
 129                 cmdptr->cmd_status = HERMON_CMD_INVALID_STATUS;
 130 
 131                 /* Write the command to the HCR */
 132                 token = (uint16_t)cmdptr->cmd_indx;
 133                 retry_cnt2 = HCA_PIO_RETRY_CNT;
 134                 do {
 135                         status = hermon_write_hcr(state, cmdpost, token,
 136                             &hw_err);


 140                 if (status != HERMON_CMD_SUCCESS) {
 141                         /*
 142                          * If there is a HW error, call hermon_cmd_retry_ok()
 143                          * to check the side-effect of the operation retry.
 144                          */
 145                         if ((retry_cnt == HCA_PIO_RETRY_CNT &&
 146                             hw_err == HCA_PIO_OK) ||
 147                             !hermon_cmd_retry_ok(cmdpost, status)) {
 148                                 hermon_cmd_check_status(state, status);
 149                                 hermon_outstanding_cmd_free(state, &cmdptr);
 150                                 return (status);
 151                         }
 152                 /* Check if there is a transient internal error */
 153                 } else if (retry_cnt2 != HCA_PIO_RETRY_CNT) {
 154                         hermon_fm_ereport(state, HCA_IBA_ERR,
 155                             HCA_ERR_TRANSIENT);
 156                 }
 157 
 158                 /*
 159                  * cv_wait() on the "command_complete" condition variable.
 160                  * Note: We have the "__lock_lint" here to workaround warlock.
 161                  * Since warlock doesn't know that other parts of the Hermon
 162                  * may occasionally call this routine while holding their own
 163                  * locks, it complains about this cv_wait.  In reality,
 164                  * however, the rest of the driver never calls this routine
 165                  * with a lock held unless they pass HERMON_CMD_NOSLEEP.
 166                  */
 167                 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cmdptr))
 168                 mutex_enter(&cmdptr->cmd_comp_lock);
 169                 while (cmdptr->cmd_status == HERMON_CMD_INVALID_STATUS) {
 170 #ifndef __lock_lint
 171                         cv_wait(&cmdptr->cmd_comp_cv, &cmdptr->cmd_comp_lock);
 172                         /* NOTE: EXPECT SEVERAL THREADS TO BE WAITING HERE */
 173 #endif
 174                 }
 175                 mutex_exit(&cmdptr->cmd_comp_lock);
 176                 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdptr))
 177 
 178                 /*
 179                  * Wake up after command completes (cv_signal).  Read status
 180                  * from the command (success, fail, etc.).  It is appropriate
 181                  * here (as above) to read the status field without the
 182                  * "cmd_comp_lock" because it is no longer being used to
 183                  * indicate whether the condition variable has been signaled
 184                  * (i.e. at this point we are certain that it already has).
 185                  */
 186                 status = cmdptr->cmd_status;
 187 
 188                 /* retry the operation if an internal error occurs */
 189                 if (status == HERMON_CMD_INTERNAL_ERR && retry_cnt-- > 0)
 190                         goto retry;
 191 
 192                 /* Save the "outparam" values into the cmdpost struct */
 193                 cmdpost->cp_outparm = cmdptr->cmd_outparm;
 194 
 195                 /*
 196                  * Add the command back to the "outstanding commands list".


 324                         ASSERT(status == HERMON_CMD_SUCCESS);
 325                 } else {
 326                         /* NOTE: Expect threads to be waiting in here */
 327                         status = hermon_impl_mbox_alloc(state,
 328                             &state->hs_out_mblist, &mbox_info->mbi_out,
 329                             mbox_wait);
 330                         if (status != HERMON_CMD_SUCCESS) {
 331                                 /* If we allocated an "In" mailbox, free it */
 332                                 if (mbox_info->mbi_alloc_flags &
 333                                     HERMON_ALLOC_INMBOX) {
 334                                         hermon_impl_mbox_free(
 335                                             &state->hs_in_mblist,
 336                                             &mbox_info->mbi_in);
 337                                 }
 338                                 return (status);
 339                         }
 340                 }
 341         }
 342 
 343         /* Store appropriate context in mbox_info */
 344         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(mbox_info->mbi_sleep_context))
 345         mbox_info->mbi_sleep_context = sleep_context;
 346 
 347         return (HERMON_CMD_SUCCESS);
 348 }
 349 
 350 
 351 /*
 352  * hermon_mbox_free()
 353  *    Context: Can be called from interrupt or base context.
 354  */
 355 void
 356 hermon_mbox_free(hermon_state_t *state, hermon_mbox_info_t *mbox_info)
 357 {
 358         /*
 359          * The mailbox has to be freed in the same context from which it was
 360          * allocated.  The context is stored in the mbox_info at
 361          * hermon_mbox_alloc() time.  We check the stored context against the
 362          * current context here.
 363          */
 364         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(mbox_info->mbi_sleep_context))
 365         ASSERT(mbox_info->mbi_sleep_context == HERMON_SLEEPFLAG_FOR_CONTEXT());
 366 
 367         /* Determine correct mboxlist based on calling context */
 368         if (mbox_info->mbi_sleep_context == HERMON_NOSLEEP) {
 369                 /* Free the intr "In" mailbox */
 370                 if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_INMBOX) {
 371                         hermon_impl_mbox_free(&state->hs_in_intr_mblist,
 372                             &mbox_info->mbi_in);
 373                 }
 374 
 375                 /* Free the intr "Out" mailbox */
 376                 if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_OUTMBOX) {
 377                         hermon_impl_mbox_free(&state->hs_out_intr_mblist,
 378                             &mbox_info->mbi_out);
 379                 }
 380         } else {
 381                 /* Free the "In" mailbox */
 382                 if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_INMBOX) {
 383                         hermon_impl_mbox_free(&state->hs_in_mblist,
 384                             &mbox_info->mbi_in);


 586                         mutex_exit(&mblist->mbl_lock);
 587                         /* Delay loop polling for an available mbox */
 588                         if (++count > countmax) {
 589                                 return (HERMON_CMD_INSUFF_RSRC);
 590                         }
 591 
 592                         /* Delay before polling for mailbox again */
 593                         drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
 594                         mutex_enter(&mblist->mbl_lock);
 595                 }
 596                 mblist->mbl_pollers--;
 597 
 598         /* HERMON_SLEEP */
 599         } else {
 600                 /*
 601                  * Grab lock here as we prepare to cv_wait if needed.
 602                  */
 603                 mutex_enter(&mblist->mbl_lock);
 604                 while (mblist->mbl_entries_free == 0) {
 605                         /*
 606                          * Wait (on cv) for a mailbox to become free.  Note:
 607                          * Just as we do above in hermon_cmd_post(), we also
 608                          * have the "__lock_lint" here to workaround warlock.
 609                          * Warlock doesn't know that other parts of the Hermon
 610                          * may occasionally call this routine while holding
 611                          * their own locks, so it complains about this cv_wait.
 612                          * In reality, however, the rest of the driver never
 613                          * calls this routine with a lock held unless they pass
 614                          * HERMON_CMD_NOSLEEP.
 615                          */
 616                         mblist->mbl_waiters++;
 617 #ifndef __lock_lint
 618                         cv_wait(&mblist->mbl_cv, &mblist->mbl_lock);
 619 #endif
 620                 }
 621         }
 622 
 623         /* Grab the next available mailbox from list */
 624         mbox_ptr = mblist->mbl_mbox;
 625         index    = mblist->mbl_head_indx;
 626         next     = mbox_ptr[index].mb_next;
 627         prev     = mbox_ptr[index].mb_prev;
 628 
 629         /* Remove it from the mailbox list */
 630         mblist->mbl_mbox[next].mb_prev       = prev;
 631         mblist->mbl_mbox[prev].mb_next       = next;
 632         mblist->mbl_head_indx                = next;
 633 
 634         /* Update the "free" count and return the mailbox pointer */
 635         mblist->mbl_entries_free--;
 636         *mb = &mbox_ptr[index];
 637 
 638         mutex_exit(&mblist->mbl_lock);
 639 


 861 
 862         cmd_list = &state->hs_cmd_list;
 863         mutex_enter(&cmd_list->cml_lock);
 864 
 865         /* Ensure that outstanding commands are supported */
 866         ASSERT(cmd_list->cml_num_alloc != 0);
 867 
 868         /*
 869          * If the outstanding command list is empty, then wait (if
 870          * appropriate in the current context).  Otherwise, grab the
 871          * next available command.
 872          */
 873         while (cmd_list->cml_entries_free == 0) {
 874                 /* No free commands */
 875                 if (cmd_wait == HERMON_NOSLEEP) {
 876                         mutex_exit(&cmd_list->cml_lock);
 877                         return (HERMON_CMD_INSUFF_RSRC);
 878                 }
 879 
 880                 /*
 881                  * Wait (on cv) for a command to become free.  Note: Just
 882                  * as we do above in hermon_cmd_post(), we also have the
 883                  * "__lock_lint" here to workaround warlock.  Warlock doesn't
 884                  * know that other parts of the Hermon may occasionally call
 885                  * this routine while holding their own locks, so it complains
 886                  * about this cv_wait.  In reality, however, the rest of the
 887                  * driver never calls this routine with a lock held unless
 888                  * they pass HERMON_CMD_NOSLEEP.
 889                  */
 890                 cmd_list->cml_waiters++;
 891 #ifndef __lock_lint
 892                 cv_wait(&cmd_list->cml_cv, &cmd_list->cml_lock);
 893 #endif
 894         }
 895 
 896         /* Grab the next available command from the list */
 897         head = cmd_list->cml_head_indx;
 898         *cmd_ptr = &cmd_list->cml_cmd[head];
 899         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(**cmd_ptr))
 900         next = (*cmd_ptr)->cmd_next;
 901         prev = (*cmd_ptr)->cmd_prev;
 902         (*cmd_ptr)->cmd_status = HERMON_CMD_INVALID_STATUS;
 903 
 904         /* Remove it from the command list */
 905         cmd_list->cml_cmd[next].cmd_prev = prev;
 906         cmd_list->cml_cmd[prev].cmd_next = next;
 907         cmd_list->cml_head_indx               = next;
 908 
 909         /* Update the "free" count and return */
 910         cmd_list->cml_entries_free--;
 911 
 912         mutex_exit(&cmd_list->cml_lock);
 913 
 914         return (HERMON_CMD_SUCCESS);
 915 }
 916 
 917 
 918 /*
 919  * hermon_outstanding_cmd_free()


 978 static int
 979 hermon_write_hcr(hermon_state_t *state, hermon_cmd_post_t *cmdpost,
 980     uint16_t token, int *hw_err)
 981 {
 982         hermon_hw_hcr_t *hcr;
 983         uint_t          status, count, countmax;
 984         uint64_t        hcrreg;
 985         uint64_t        togmask;
 986         ddi_acc_handle_t cmdhdl = hermon_get_cmdhdl(state);
 987         boolean_t       hw_error = B_FALSE;
 988 
 989         /* initialize the FMA retry loop */
 990         hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
 991 
 992         /*
 993          * Grab the "HCR access" lock if the driver is not in
 994          * fastreboot. In fastreboot, this function is called
 995          * with the single thread but in high interrupt context
 996          * (so that this mutex lock cannot be used).
 997          */
 998 #ifdef __lock_lint
 999         mutex_enter(&state->hs_cmd_regs.hcr_lock);
1000 #else
1001         if (!HERMON_IN_FASTREBOOT(state)) {
1002                 mutex_enter(&state->hs_cmd_regs.hcr_lock);
1003         }
1004 #endif
1005         hcr = state->hs_cmd_regs.hcr;
1006 
1007         /*
1008          * First, check the "go" bit to see if any previous hcr usage is
1009          * complete.  As long as it is set then we must continue to poll.
1010          */
1011 
1012         countmax = state->hs_cfg_profile->cp_cmd_poll_max;
1013         togmask = (state->hs_cmd_toggle & 0x01) << HERMON_HCR_CMD_T_SHFT;
1014 
1015         /* the FMA retry loop starts. */
1016         hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
1017             fm_test);
1018 
1019         count    = 0;
1020         for (;;) {
1021                 hcrreg = ddi_get32(cmdhdl, &hcr->cmd);
1022 
1023                 /* If "go" bit is clear and toggle reset, then done */
1024                 if (((hcrreg & HERMON_HCR_CMD_GO_MASK) == 0) &&
1025                     ((hcrreg & HERMON_HCR_CMD_T_MASK)  == togmask)) {
1026                         break;
1027                 }
1028                 /* Delay before polling the "go" bit again */
1029                 drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
1030 
1031                 /*
1032                  * If we poll more than the maximum number of times, then
1033                  * return a "timeout" error.
1034                  */
1035                 if (++count > countmax) {
1036 #ifdef __lock_lint
1037                         mutex_exit(&state->hs_cmd_regs.hcr_lock);
1038 #else
1039                         if (!HERMON_IN_FASTREBOOT(state)) {
1040                                 mutex_exit(&state->hs_cmd_regs.hcr_lock);
1041                         }
1042 #endif
1043                         cmn_err(CE_NOTE, "write_hcr: cannot start cmd");
1044                         return (HERMON_CMD_TIMEOUT_GOBIT);
1045                 }
1046         }
1047 
1048         /* the FMA retry loop ends. */
1049         hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
1050             fm_test);
1051 
1052         /* check if there is a transient error */
1053         if (fm_loop_cnt != HCA_PIO_RETRY_CNT) {
1054                 hw_error = B_TRUE;
1055         }
1056 
1057         /* succeeded, so update the cmd counter for this cmd's completion */
1058         state->hs_cmd_toggle++;
1059         togmask = (state->hs_cmd_toggle & 0x01) << HERMON_HCR_CMD_T_SHFT;
1060 
1061         /* the FMA retry loop starts. */
1062         hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,


1113                 hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt,
1114                     fm_status, fm_test);
1115 
1116                 count    = 0;
1117                 for (;;) {
1118                         hcrreg = ddi_get32(cmdhdl, &hcr->cmd);
1119 
1120                         /* If "go" bit is clear and toggle reset, then done */
1121                         if (((hcrreg & HERMON_HCR_CMD_GO_MASK) == 0) &&
1122                             ((hcrreg & HERMON_HCR_CMD_T_MASK)  == togmask)) {
1123                                 break;
1124                         }
1125                         /* Delay before polling the "go" bit again */
1126                         drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
1127 
1128                         /*
1129                          * If we poll more than the maximum number of times,
1130                          * then return a "timeout" error.
1131                          */
1132                         if (++count > countmax) {
1133 #ifdef __lock_lint
1134                                 mutex_exit(&state-> hs_cmd_regs.hcr_lock);
1135 #else
1136                                 if (!HERMON_IN_FASTREBOOT(state)) {
1137                                         mutex_exit(&state->
1138                                             hs_cmd_regs.hcr_lock);
1139                                 }
1140 #endif
1141                                 cmn_err(CE_NOTE,
1142                                     "write_hcr: cannot complete cmd");
1143                                 return (HERMON_CMD_TIMEOUT_GOBIT);
1144                         }
1145                 }
1146 
1147                 /* Pull out the "status" bits from the HCR */
1148                 status = (hcrreg >> HERMON_HCR_CMD_STATUS_SHFT);
1149 
1150                 /*
1151                  * Read the "outparam" value.  Note: we have to read "outparam"
1152                  * as two separate 32-bit reads because the field in the HCR is
1153                  * not 64-bit aligned.
1154                  */
1155                 hcrreg = ddi_get32(cmdhdl, &hcr->out_param0);
1156                 cmdpost->cp_outparm = hcrreg << 32;
1157                 hcrreg = ddi_get32(cmdhdl, &hcr->out_param1);
1158                 cmdpost->cp_outparm |= hcrreg;
1159 
1160                 /* the FMA retry loop ends. */
1161                 hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
1162                     fm_test);
1163 
1164                 /* check if there is a transient error */
1165                 if (fm_loop_cnt != HCA_PIO_RETRY_CNT) {
1166                         hw_error = B_TRUE;
1167                 }
1168 
1169         /* END SPIN */
1170         } else {                /* NOSPIN */
1171                 status = HERMON_CMD_SUCCESS;
1172         }
1173 
1174         /* Drop the "HCR access" lock */
1175 #ifdef __lock_lint
1176         mutex_exit(&state->hs_cmd_regs.hcr_lock);
1177 #else
1178         if (!HERMON_IN_FASTREBOOT(state)) {
1179                 mutex_exit(&state->hs_cmd_regs.hcr_lock);
1180         }
1181 #endif
1182         if (hw_error == B_TRUE) {
1183                 *hw_err = HCA_PIO_TRANSIENT;
1184         } else {
1185                 *hw_err = HCA_PIO_OK;
1186         }
1187 #ifdef FMA_TEST
1188         if (hermon_test_num == -3) {
1189                 status = HERMON_CMD_INTERNAL_ERR;
1190         }
1191 #endif
1192         return (status);
1193 
1194 pio_error:
1195 #ifdef __lock_lint
1196         mutex_exit(&state->hs_cmd_regs.hcr_lock);
1197 #else
1198         if (!HERMON_IN_FASTREBOOT(state)) {
1199                 mutex_exit(&state->hs_cmd_regs.hcr_lock);
1200         }
1201 #endif
1202         hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_NON_FATAL);
1203         *hw_err = HCA_PIO_PERSISTENT;
1204         return (HERMON_CMD_INVALID_STATUS);
1205 }
1206 
1207 
1208 /*
1209  * hermon_outstanding_cmdlist_init()
1210  *    Context: Only called from attach() path context
1211  */
1212 int
1213 hermon_outstanding_cmdlist_init(hermon_state_t *state)
1214 {
1215         uint_t          num_outstanding_cmds, head, tail;
1216         int             i;
1217 
1218         /*
1219          * Determine the number of the outstanding commands supported
1220          * by the Hermon device (obtained from the QUERY_FW command).  Note:
1221          * Because we handle both SLEEP and NOSLEEP cases around the hermon HCR,


2014         cmd.cp_opcode   = MAD_IFC;
2015         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
2016         cmd.cp_flags    = HERMON_CMD_NOSLEEP_SPIN; /* NO SLEEP */
2017         status = hermon_cmd_post(state, &cmd);
2018         if (status != HERMON_CMD_SUCCESS) {
2019                 goto getportinfo_fail;
2020         }
2021 
2022         /* Sync the mailbox to read the results */
2023         size = sizeof (sm_portinfo_t);
2024         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
2025             size, DDI_DMA_SYNC_FORCPU);
2026 
2027         /*
2028          * Copy GetPortInfo response MAD into "portinfo".  Do any endian
2029          * swapping that may be necessary to flip any of the "portinfo"
2030          * fields
2031          */
2032         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2033             HERMON_CMD_MADDATA_OFFSET), portinfo, size);
2034         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*portinfo))
2035         HERMON_GETPORTINFO_SWAP(portinfo);
2036 
2037 getportinfo_fail:
2038         /* Free the mailbox */
2039         hermon_mbox_free(state, &mbox_info);
2040         return (status);
2041 }
2042 
2043 /*
2044  * hermon_is_ext_port_counters_supported()
2045  *
2046  * Determine weather extended port counters are supported or not by sending
2047  * ClassPortInfo perf mgmt class MAD.
2048  */
2049 int
2050 hermon_is_ext_port_counters_supported(hermon_state_t *state, uint_t port,
2051     uint_t sleepflag, int *ext_width_supported)
2052 {
2053         hermon_mbox_info_t      mbox_info;
2054         hermon_cmd_post_t       cmd;


2335         cmd.cp_opcode   = MAD_IFC;
2336         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
2337         cmd.cp_flags    = sleepflag;
2338         status = hermon_cmd_post(state, &cmd);
2339         if (status != HERMON_CMD_SUCCESS) {
2340                 goto getnodeinfo_fail;
2341         }
2342 
2343         /* Sync the mailbox to read the results */
2344         size = sizeof (sm_nodeinfo_t);
2345         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
2346             size, DDI_DMA_SYNC_FORCPU);
2347 
2348         /*
2349          * Copy GetNodeInfo response MAD into "nodeinfo".  Do any endian
2350          * swapping that may be necessary to flip any of the "nodeinfo"
2351          * fields
2352          */
2353         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2354             HERMON_CMD_MADDATA_OFFSET), nodeinfo, size);
2355         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*nodeinfo))
2356         HERMON_GETNODEINFO_SWAP(nodeinfo);
2357 
2358 getnodeinfo_fail:
2359         /* Free the mailbox */
2360         hermon_mbox_free(state, &mbox_info);
2361         return (status);
2362 }
2363 
2364 
2365 /*
2366  * hermon_getnodedesc_cmd_post()
2367  *    Context: Can be called from interrupt or base context.
2368  *    (Currently called only from attach() and detach() path contexts)
2369  */
2370 int
2371 hermon_getnodedesc_cmd_post(hermon_state_t *state, uint_t sleepflag,
2372     sm_nodedesc_t *nodedesc)
2373 {
2374         hermon_mbox_info_t      mbox_info;
2375         hermon_cmd_post_t       cmd;


2474         cmd.cp_inmod    = port;
2475         cmd.cp_opcode   = MAD_IFC;
2476         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
2477         cmd.cp_flags    = sleepflag;
2478         status = hermon_cmd_post(state, &cmd);
2479         if (status != HERMON_CMD_SUCCESS) {
2480                 goto getguidinfo_fail;
2481         }
2482 
2483         /* Sync the mailbox to read the results */
2484         size = sizeof (sm_guidinfo_t);
2485         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
2486             size, DDI_DMA_SYNC_FORCPU);
2487 
2488         /*
2489          * Copy GetGUIDInfo response MAD into "guidinfo".  Do any endian
2490          * swapping that may be necessary to flip the "guidinfo" fields
2491          */
2492         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2493             HERMON_CMD_MADDATA_OFFSET), guidinfo, size);
2494         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*guidinfo))
2495         HERMON_GETGUIDINFO_SWAP(guidinfo);
2496 
2497 getguidinfo_fail:
2498         /* Free the mailbox */
2499         hermon_mbox_free(state, &mbox_info);
2500         return (status);
2501 }
2502 
2503 
2504 /*
2505  * hermon_getpkeytable_cmd_post()
2506  *    Context: Can be called from interrupt or base context.
2507  */
2508 int
2509 hermon_getpkeytable_cmd_post(hermon_state_t *state, uint_t port,
2510     uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable)
2511 {
2512         hermon_mbox_info_t      mbox_info;
2513         hermon_cmd_post_t       cmd;
2514         uint32_t                *mbox;


2546         cmd.cp_inmod    = port;
2547         cmd.cp_opcode   = MAD_IFC;
2548         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
2549         cmd.cp_flags    = sleepflag;
2550         status = hermon_cmd_post(state, &cmd);
2551         if (status != HERMON_CMD_SUCCESS) {
2552                 goto getpkeytable_fail;
2553         }
2554 
2555         /* Sync the mailbox to read the results */
2556         size = sizeof (sm_pkey_table_t);
2557         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
2558             size, DDI_DMA_SYNC_FORCPU);
2559 
2560         /*
2561          * Copy GetPKeyTable response MAD into "pkeytable".  Do any endian
2562          * swapping that may be necessary to flip the "pkeytable" fields
2563          */
2564         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2565             HERMON_CMD_MADDATA_OFFSET), pkeytable, size);
2566         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pkeytable))
2567         HERMON_GETPKEYTABLE_SWAP(pkeytable);
2568 
2569 getpkeytable_fail:
2570         /* Free the mailbox */
2571         hermon_mbox_free(state, &mbox_info);
2572         return (status);
2573 }
2574 
2575 
2576 /*
2577  * hermon_write_mtt_cmd_post()
2578  *    Context: Can be called from interrupt or base context.
2579  */
2580 int
2581 hermon_write_mtt_cmd_post(hermon_state_t *state, hermon_rsrc_t *mtt,
2582     uint64_t start_addr, uint_t nummtt, uint_t sleepflag)
2583 {
2584         hermon_mbox_info_t      mbox_info;
2585         hermon_cmd_post_t       cmd;
2586         uint64_t                data;




  58     uint16_t token, int *hwerr);
  59 static void hermon_mbox_sync(hermon_mbox_t *mbox, uint_t offset,
  60     uint_t length, uint_t flag);
  61 static void hermon_cmd_check_status(hermon_state_t *state, int status);
  62 
  63 /*
  64  * hermon_cmd_post()
  65  *    Context: Can be called from interrupt or base context.
  66  *
  67  *    The "cp_flags" field in cmdpost
  68  *    is used to determine whether to wait for an available
  69  *    outstanding command (if necessary) or to return error.
  70  */
  71 int
  72 hermon_cmd_post(hermon_state_t *state, hermon_cmd_post_t *cmdpost)
  73 {
  74         hermon_cmd_t    *cmdptr;
  75         int             status, retry_cnt, retry_cnt2, hw_err;
  76         uint16_t        token;
  77 


  78         /* Determine if we are going to spin until completion */
  79         if (cmdpost->cp_flags == HERMON_CMD_NOSLEEP_SPIN) {
  80 
  81                 /* Write the command to the HCR */
  82                 retry_cnt = HCA_PIO_RETRY_CNT;
  83                 do {
  84                         status = hermon_write_hcr(state, cmdpost, 0, &hw_err);
  85                 } while (status == HERMON_CMD_INTERNAL_ERR && retry_cnt-- > 0);
  86 
  87                 /* Check if there is an error status in hermon_write_hcr() */
  88                 if (status != HERMON_CMD_SUCCESS) {
  89                         /*
  90                          * If there is a HW error, call hermon_cmd_retry_ok()
  91                          * to check the side-effect of the operation retry.
  92                          */
  93                         if ((retry_cnt == HCA_PIO_RETRY_CNT &&
  94                             hw_err == HCA_PIO_OK) ||
  95                             !hermon_cmd_retry_ok(cmdpost, status)) {
  96                                 hermon_cmd_check_status(state, status);
  97                                 return (status);
  98                         }
  99                 /* Check if there is a transient internal error */
 100                 } else if (retry_cnt != HCA_PIO_RETRY_CNT) {
 101                         hermon_fm_ereport(state, HCA_IBA_ERR,
 102                             HCA_ERR_TRANSIENT);
 103                 }
 104 
 105         } else {  /* "HERMON_CMD_SLEEP_NOSPIN" */
 106                 ASSERT(HERMON_SLEEPFLAG_FOR_CONTEXT() != HERMON_NOSLEEP);
 107 
 108                 /* NOTE: Expect threads to be waiting in here */
 109                 status = hermon_outstanding_cmd_alloc(state, &cmdptr,
 110                     cmdpost->cp_flags);
 111                 if (status != HERMON_CMD_SUCCESS) {
 112                         return (status);
 113                 }

 114 
 115                 retry_cnt = HCA_PIO_RETRY_CNT;
 116 retry:
 117                 /*
 118                  * Set status to "HERMON_CMD_INVALID_STATUS".  It is
 119                  * appropriate to do this here without the "cmd_comp_lock"
 120                  * because this register is overloaded.  Later it will be
 121                  * used to indicate - through a change from this invalid
 122                  * value to some other value - that the condition variable
 123                  * has been signaled.  Once it has, status will then contain
 124                  * the _real_ completion status
 125                  */
 126                 cmdptr->cmd_status = HERMON_CMD_INVALID_STATUS;
 127 
 128                 /* Write the command to the HCR */
 129                 token = (uint16_t)cmdptr->cmd_indx;
 130                 retry_cnt2 = HCA_PIO_RETRY_CNT;
 131                 do {
 132                         status = hermon_write_hcr(state, cmdpost, token,
 133                             &hw_err);


 137                 if (status != HERMON_CMD_SUCCESS) {
 138                         /*
 139                          * If there is a HW error, call hermon_cmd_retry_ok()
 140                          * to check the side-effect of the operation retry.
 141                          */
 142                         if ((retry_cnt == HCA_PIO_RETRY_CNT &&
 143                             hw_err == HCA_PIO_OK) ||
 144                             !hermon_cmd_retry_ok(cmdpost, status)) {
 145                                 hermon_cmd_check_status(state, status);
 146                                 hermon_outstanding_cmd_free(state, &cmdptr);
 147                                 return (status);
 148                         }
 149                 /* Check if there is a transient internal error */
 150                 } else if (retry_cnt2 != HCA_PIO_RETRY_CNT) {
 151                         hermon_fm_ereport(state, HCA_IBA_ERR,
 152                             HCA_ERR_TRANSIENT);
 153                 }
 154 
 155                 /*
 156                  * cv_wait() on the "command_complete" condition variable.






 157                  */

 158                 mutex_enter(&cmdptr->cmd_comp_lock);
 159                 while (cmdptr->cmd_status == HERMON_CMD_INVALID_STATUS) {


 160                         /* NOTE: EXPECT SEVERAL THREADS TO BE WAITING HERE */
 161                         cv_wait(&cmdptr->cmd_comp_cv, &cmdptr->cmd_comp_lock);
 162                 }
 163                 mutex_exit(&cmdptr->cmd_comp_lock);

 164 
 165                 /*
 166                  * Wake up after command completes (cv_signal).  Read status
 167                  * from the command (success, fail, etc.).  It is appropriate
 168                  * here (as above) to read the status field without the
 169                  * "cmd_comp_lock" because it is no longer being used to
 170                  * indicate whether the condition variable has been signaled
 171                  * (i.e. at this point we are certain that it already has).
 172                  */
 173                 status = cmdptr->cmd_status;
 174 
 175                 /* retry the operation if an internal error occurs */
 176                 if (status == HERMON_CMD_INTERNAL_ERR && retry_cnt-- > 0)
 177                         goto retry;
 178 
 179                 /* Save the "outparam" values into the cmdpost struct */
 180                 cmdpost->cp_outparm = cmdptr->cmd_outparm;
 181 
 182                 /*
 183                  * Add the command back to the "outstanding commands list".


 311                         ASSERT(status == HERMON_CMD_SUCCESS);
 312                 } else {
 313                         /* NOTE: Expect threads to be waiting in here */
 314                         status = hermon_impl_mbox_alloc(state,
 315                             &state->hs_out_mblist, &mbox_info->mbi_out,
 316                             mbox_wait);
 317                         if (status != HERMON_CMD_SUCCESS) {
 318                                 /* If we allocated an "In" mailbox, free it */
 319                                 if (mbox_info->mbi_alloc_flags &
 320                                     HERMON_ALLOC_INMBOX) {
 321                                         hermon_impl_mbox_free(
 322                                             &state->hs_in_mblist,
 323                                             &mbox_info->mbi_in);
 324                                 }
 325                                 return (status);
 326                         }
 327                 }
 328         }
 329 
 330         /* Store appropriate context in mbox_info */

 331         mbox_info->mbi_sleep_context = sleep_context;
 332 
 333         return (HERMON_CMD_SUCCESS);
 334 }
 335 
 336 
 337 /*
 338  * hermon_mbox_free()
 339  *    Context: Can be called from interrupt or base context.
 340  */
 341 void
 342 hermon_mbox_free(hermon_state_t *state, hermon_mbox_info_t *mbox_info)
 343 {
 344         /*
 345          * The mailbox has to be freed in the same context from which it was
 346          * allocated.  The context is stored in the mbox_info at
 347          * hermon_mbox_alloc() time.  We check the stored context against the
 348          * current context here.
 349          */

 350         ASSERT(mbox_info->mbi_sleep_context == HERMON_SLEEPFLAG_FOR_CONTEXT());
 351 
 352         /* Determine correct mboxlist based on calling context */
 353         if (mbox_info->mbi_sleep_context == HERMON_NOSLEEP) {
 354                 /* Free the intr "In" mailbox */
 355                 if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_INMBOX) {
 356                         hermon_impl_mbox_free(&state->hs_in_intr_mblist,
 357                             &mbox_info->mbi_in);
 358                 }
 359 
 360                 /* Free the intr "Out" mailbox */
 361                 if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_OUTMBOX) {
 362                         hermon_impl_mbox_free(&state->hs_out_intr_mblist,
 363                             &mbox_info->mbi_out);
 364                 }
 365         } else {
 366                 /* Free the "In" mailbox */
 367                 if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_INMBOX) {
 368                         hermon_impl_mbox_free(&state->hs_in_mblist,
 369                             &mbox_info->mbi_in);


 571                         mutex_exit(&mblist->mbl_lock);
 572                         /* Delay loop polling for an available mbox */
 573                         if (++count > countmax) {
 574                                 return (HERMON_CMD_INSUFF_RSRC);
 575                         }
 576 
 577                         /* Delay before polling for mailbox again */
 578                         drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
 579                         mutex_enter(&mblist->mbl_lock);
 580                 }
 581                 mblist->mbl_pollers--;
 582 
 583         /* HERMON_SLEEP */
 584         } else {
 585                 /*
 586                  * Grab lock here as we prepare to cv_wait if needed.
 587                  */
 588                 mutex_enter(&mblist->mbl_lock);
 589                 while (mblist->mbl_entries_free == 0) {
 590                         /*
 591                          * Wait (on cv) for a mailbox to become free.








 592                          */
 593                         mblist->mbl_waiters++;

 594                         cv_wait(&mblist->mbl_cv, &mblist->mbl_lock);

 595                 }
 596         }
 597 
 598         /* Grab the next available mailbox from list */
 599         mbox_ptr = mblist->mbl_mbox;
 600         index    = mblist->mbl_head_indx;
 601         next     = mbox_ptr[index].mb_next;
 602         prev     = mbox_ptr[index].mb_prev;
 603 
 604         /* Remove it from the mailbox list */
 605         mblist->mbl_mbox[next].mb_prev       = prev;
 606         mblist->mbl_mbox[prev].mb_next       = next;
 607         mblist->mbl_head_indx                = next;
 608 
 609         /* Update the "free" count and return the mailbox pointer */
 610         mblist->mbl_entries_free--;
 611         *mb = &mbox_ptr[index];
 612 
 613         mutex_exit(&mblist->mbl_lock);
 614 


 836 
 837         cmd_list = &state->hs_cmd_list;
 838         mutex_enter(&cmd_list->cml_lock);
 839 
 840         /* Ensure that outstanding commands are supported */
 841         ASSERT(cmd_list->cml_num_alloc != 0);
 842 
 843         /*
 844          * If the outstanding command list is empty, then wait (if
 845          * appropriate in the current context).  Otherwise, grab the
 846          * next available command.
 847          */
 848         while (cmd_list->cml_entries_free == 0) {
 849                 /* No free commands */
 850                 if (cmd_wait == HERMON_NOSLEEP) {
 851                         mutex_exit(&cmd_list->cml_lock);
 852                         return (HERMON_CMD_INSUFF_RSRC);
 853                 }
 854 
 855                 /*
 856                  * Wait (on cv) for a command to become free.







 857                  */
 858                 cmd_list->cml_waiters++;

 859                 cv_wait(&cmd_list->cml_cv, &cmd_list->cml_lock);

 860         }
 861 
 862         /* Grab the next available command from the list */
 863         head = cmd_list->cml_head_indx;
 864         *cmd_ptr = &cmd_list->cml_cmd[head];

 865         next = (*cmd_ptr)->cmd_next;
 866         prev = (*cmd_ptr)->cmd_prev;
 867         (*cmd_ptr)->cmd_status = HERMON_CMD_INVALID_STATUS;
 868 
 869         /* Remove it from the command list */
 870         cmd_list->cml_cmd[next].cmd_prev = prev;
 871         cmd_list->cml_cmd[prev].cmd_next = next;
 872         cmd_list->cml_head_indx               = next;
 873 
 874         /* Update the "free" count and return */
 875         cmd_list->cml_entries_free--;
 876 
 877         mutex_exit(&cmd_list->cml_lock);
 878 
 879         return (HERMON_CMD_SUCCESS);
 880 }
 881 
 882 
 883 /*
 884  * hermon_outstanding_cmd_free()


 943 static int
 944 hermon_write_hcr(hermon_state_t *state, hermon_cmd_post_t *cmdpost,
 945     uint16_t token, int *hw_err)
 946 {
 947         hermon_hw_hcr_t *hcr;
 948         uint_t          status, count, countmax;
 949         uint64_t        hcrreg;
 950         uint64_t        togmask;
 951         ddi_acc_handle_t cmdhdl = hermon_get_cmdhdl(state);
 952         boolean_t       hw_error = B_FALSE;
 953 
 954         /* initialize the FMA retry loop */
 955         hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
 956 
 957         /*
 958          * Grab the "HCR access" lock if the driver is not in
 959          * fastreboot. In fastreboot, this function is called
 960          * with the single thread but in high interrupt context
 961          * (so that this mutex lock cannot be used).
 962          */



 963         if (!HERMON_IN_FASTREBOOT(state)) {
 964                 mutex_enter(&state->hs_cmd_regs.hcr_lock);
 965         }

 966         hcr = state->hs_cmd_regs.hcr;
 967 
 968         /*
 969          * First, check the "go" bit to see if any previous hcr usage is
 970          * complete.  As long as it is set then we must continue to poll.
 971          */
 972 
 973         countmax = state->hs_cfg_profile->cp_cmd_poll_max;
 974         togmask = (state->hs_cmd_toggle & 0x01) << HERMON_HCR_CMD_T_SHFT;
 975 
 976         /* the FMA retry loop starts. */
 977         hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
 978             fm_test);
 979 
 980         count    = 0;
 981         for (;;) {
 982                 hcrreg = ddi_get32(cmdhdl, &hcr->cmd);
 983 
 984                 /* If "go" bit is clear and toggle reset, then done */
 985                 if (((hcrreg & HERMON_HCR_CMD_GO_MASK) == 0) &&
 986                     ((hcrreg & HERMON_HCR_CMD_T_MASK)  == togmask)) {
 987                         break;
 988                 }
 989                 /* Delay before polling the "go" bit again */
 990                 drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
 991 
 992                 /*
 993                  * If we poll more than the maximum number of times, then
 994                  * return a "timeout" error.
 995                  */
 996                 if (++count > countmax) {



 997                         if (!HERMON_IN_FASTREBOOT(state)) {
 998                                 mutex_exit(&state->hs_cmd_regs.hcr_lock);
 999                         }

1000                         cmn_err(CE_NOTE, "write_hcr: cannot start cmd");
1001                         return (HERMON_CMD_TIMEOUT_GOBIT);
1002                 }
1003         }
1004 
1005         /* the FMA retry loop ends. */
1006         hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
1007             fm_test);
1008 
1009         /* check if there is a transient error */
1010         if (fm_loop_cnt != HCA_PIO_RETRY_CNT) {
1011                 hw_error = B_TRUE;
1012         }
1013 
1014         /* succeeded, so update the cmd counter for this cmd's completion */
1015         state->hs_cmd_toggle++;
1016         togmask = (state->hs_cmd_toggle & 0x01) << HERMON_HCR_CMD_T_SHFT;
1017 
1018         /* the FMA retry loop starts. */
1019         hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,


1070                 hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt,
1071                     fm_status, fm_test);
1072 
1073                 count    = 0;
1074                 for (;;) {
1075                         hcrreg = ddi_get32(cmdhdl, &hcr->cmd);
1076 
1077                         /* If "go" bit is clear and toggle reset, then done */
1078                         if (((hcrreg & HERMON_HCR_CMD_GO_MASK) == 0) &&
1079                             ((hcrreg & HERMON_HCR_CMD_T_MASK)  == togmask)) {
1080                                 break;
1081                         }
1082                         /* Delay before polling the "go" bit again */
1083                         drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
1084 
1085                         /*
1086                          * If we poll more than the maximum number of times,
1087                          * then return a "timeout" error.
1088                          */
1089                         if (++count > countmax) {



1090                                 if (!HERMON_IN_FASTREBOOT(state)) {
1091                                         mutex_exit(&state->
1092                                             hs_cmd_regs.hcr_lock);
1093                                 }

1094                                 cmn_err(CE_NOTE,
1095                                     "write_hcr: cannot complete cmd");
1096                                 return (HERMON_CMD_TIMEOUT_GOBIT);
1097                         }
1098                 }
1099 
1100                 /* Pull out the "status" bits from the HCR */
1101                 status = (hcrreg >> HERMON_HCR_CMD_STATUS_SHFT);
1102 
1103                 /*
1104                  * Read the "outparam" value.  Note: we have to read "outparam"
1105                  * as two separate 32-bit reads because the field in the HCR is
1106                  * not 64-bit aligned.
1107                  */
1108                 hcrreg = ddi_get32(cmdhdl, &hcr->out_param0);
1109                 cmdpost->cp_outparm = hcrreg << 32;
1110                 hcrreg = ddi_get32(cmdhdl, &hcr->out_param1);
1111                 cmdpost->cp_outparm |= hcrreg;
1112 
1113                 /* the FMA retry loop ends. */
1114                 hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
1115                     fm_test);
1116 
1117                 /* check if there is a transient error */
1118                 if (fm_loop_cnt != HCA_PIO_RETRY_CNT) {
1119                         hw_error = B_TRUE;
1120                 }
1121 
1122         /* END SPIN */
1123         } else {                /* NOSPIN */
1124                 status = HERMON_CMD_SUCCESS;
1125         }
1126 
1127         /* Drop the "HCR access" lock */



1128         if (!HERMON_IN_FASTREBOOT(state)) {
1129                 mutex_exit(&state->hs_cmd_regs.hcr_lock);
1130         }

1131         if (hw_error == B_TRUE) {
1132                 *hw_err = HCA_PIO_TRANSIENT;
1133         } else {
1134                 *hw_err = HCA_PIO_OK;
1135         }
1136 #ifdef FMA_TEST
1137         if (hermon_test_num == -3) {
1138                 status = HERMON_CMD_INTERNAL_ERR;
1139         }
1140 #endif
1141         return (status);
1142 
1143 pio_error:



1144         if (!HERMON_IN_FASTREBOOT(state)) {
1145                 mutex_exit(&state->hs_cmd_regs.hcr_lock);
1146         }

1147         hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_NON_FATAL);
1148         *hw_err = HCA_PIO_PERSISTENT;
1149         return (HERMON_CMD_INVALID_STATUS);
1150 }
1151 
1152 
1153 /*
1154  * hermon_outstanding_cmdlist_init()
1155  *    Context: Only called from attach() path context
1156  */
1157 int
1158 hermon_outstanding_cmdlist_init(hermon_state_t *state)
1159 {
1160         uint_t          num_outstanding_cmds, head, tail;
1161         int             i;
1162 
1163         /*
1164          * Determine the number of the outstanding commands supported
1165          * by the Hermon device (obtained from the QUERY_FW command).  Note:
1166          * Because we handle both SLEEP and NOSLEEP cases around the hermon HCR,


1959         cmd.cp_opcode   = MAD_IFC;
1960         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
1961         cmd.cp_flags    = HERMON_CMD_NOSLEEP_SPIN; /* NO SLEEP */
1962         status = hermon_cmd_post(state, &cmd);
1963         if (status != HERMON_CMD_SUCCESS) {
1964                 goto getportinfo_fail;
1965         }
1966 
1967         /* Sync the mailbox to read the results */
1968         size = sizeof (sm_portinfo_t);
1969         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
1970             size, DDI_DMA_SYNC_FORCPU);
1971 
1972         /*
1973          * Copy GetPortInfo response MAD into "portinfo".  Do any endian
1974          * swapping that may be necessary to flip any of the "portinfo"
1975          * fields
1976          */
1977         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
1978             HERMON_CMD_MADDATA_OFFSET), portinfo, size);

1979         HERMON_GETPORTINFO_SWAP(portinfo);
1980 
1981 getportinfo_fail:
1982         /* Free the mailbox */
1983         hermon_mbox_free(state, &mbox_info);
1984         return (status);
1985 }
1986 
1987 /*
1988  * hermon_is_ext_port_counters_supported()
1989  *
1990  * Determine weather extended port counters are supported or not by sending
1991  * ClassPortInfo perf mgmt class MAD.
1992  */
1993 int
1994 hermon_is_ext_port_counters_supported(hermon_state_t *state, uint_t port,
1995     uint_t sleepflag, int *ext_width_supported)
1996 {
1997         hermon_mbox_info_t      mbox_info;
1998         hermon_cmd_post_t       cmd;


2279         cmd.cp_opcode   = MAD_IFC;
2280         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
2281         cmd.cp_flags    = sleepflag;
2282         status = hermon_cmd_post(state, &cmd);
2283         if (status != HERMON_CMD_SUCCESS) {
2284                 goto getnodeinfo_fail;
2285         }
2286 
2287         /* Sync the mailbox to read the results */
2288         size = sizeof (sm_nodeinfo_t);
2289         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
2290             size, DDI_DMA_SYNC_FORCPU);
2291 
2292         /*
2293          * Copy GetNodeInfo response MAD into "nodeinfo".  Do any endian
2294          * swapping that may be necessary to flip any of the "nodeinfo"
2295          * fields
2296          */
2297         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2298             HERMON_CMD_MADDATA_OFFSET), nodeinfo, size);

2299         HERMON_GETNODEINFO_SWAP(nodeinfo);
2300 
2301 getnodeinfo_fail:
2302         /* Free the mailbox */
2303         hermon_mbox_free(state, &mbox_info);
2304         return (status);
2305 }
2306 
2307 
2308 /*
2309  * hermon_getnodedesc_cmd_post()
2310  *    Context: Can be called from interrupt or base context.
2311  *    (Currently called only from attach() and detach() path contexts)
2312  */
2313 int
2314 hermon_getnodedesc_cmd_post(hermon_state_t *state, uint_t sleepflag,
2315     sm_nodedesc_t *nodedesc)
2316 {
2317         hermon_mbox_info_t      mbox_info;
2318         hermon_cmd_post_t       cmd;


2417         cmd.cp_inmod    = port;
2418         cmd.cp_opcode   = MAD_IFC;
2419         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
2420         cmd.cp_flags    = sleepflag;
2421         status = hermon_cmd_post(state, &cmd);
2422         if (status != HERMON_CMD_SUCCESS) {
2423                 goto getguidinfo_fail;
2424         }
2425 
2426         /* Sync the mailbox to read the results */
2427         size = sizeof (sm_guidinfo_t);
2428         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
2429             size, DDI_DMA_SYNC_FORCPU);
2430 
2431         /*
2432          * Copy GetGUIDInfo response MAD into "guidinfo".  Do any endian
2433          * swapping that may be necessary to flip the "guidinfo" fields
2434          */
2435         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2436             HERMON_CMD_MADDATA_OFFSET), guidinfo, size);

2437         HERMON_GETGUIDINFO_SWAP(guidinfo);
2438 
2439 getguidinfo_fail:
2440         /* Free the mailbox */
2441         hermon_mbox_free(state, &mbox_info);
2442         return (status);
2443 }
2444 
2445 
2446 /*
2447  * hermon_getpkeytable_cmd_post()
2448  *    Context: Can be called from interrupt or base context.
2449  */
2450 int
2451 hermon_getpkeytable_cmd_post(hermon_state_t *state, uint_t port,
2452     uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable)
2453 {
2454         hermon_mbox_info_t      mbox_info;
2455         hermon_cmd_post_t       cmd;
2456         uint32_t                *mbox;


2488         cmd.cp_inmod    = port;
2489         cmd.cp_opcode   = MAD_IFC;
2490         cmd.cp_opmod    = HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
2491         cmd.cp_flags    = sleepflag;
2492         status = hermon_cmd_post(state, &cmd);
2493         if (status != HERMON_CMD_SUCCESS) {
2494                 goto getpkeytable_fail;
2495         }
2496 
2497         /* Sync the mailbox to read the results */
2498         size = sizeof (sm_pkey_table_t);
2499         hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
2500             size, DDI_DMA_SYNC_FORCPU);
2501 
2502         /*
2503          * Copy GetPKeyTable response MAD into "pkeytable".  Do any endian
2504          * swapping that may be necessary to flip the "pkeytable" fields
2505          */
2506         bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
2507             HERMON_CMD_MADDATA_OFFSET), pkeytable, size);

2508         HERMON_GETPKEYTABLE_SWAP(pkeytable);
2509 
2510 getpkeytable_fail:
2511         /* Free the mailbox */
2512         hermon_mbox_free(state, &mbox_info);
2513         return (status);
2514 }
2515 
2516 
2517 /*
2518  * hermon_write_mtt_cmd_post()
2519  *    Context: Can be called from interrupt or base context.
2520  */
2521 int
2522 hermon_write_mtt_cmd_post(hermon_state_t *state, hermon_rsrc_t *mtt,
2523     uint64_t start_addr, uint_t nummtt, uint_t sleepflag)
2524 {
2525         hermon_mbox_info_t      mbox_info;
2526         hermon_cmd_post_t       cmd;
2527         uint64_t                data;