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;
|