4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Emulex. All rights reserved.
24 * Use is subject to license terms.
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_PKT_C
);
33 #if (EMLXS_MODREV >= EMLXS_MODREV3)
34 typedef struct _emlxs_pkt_cookie_t
36 ddi_dma_cookie_t pkt_cmd_cookie
;
37 ddi_dma_cookie_t pkt_resp_cookie
;
38 ddi_dma_cookie_t pkt_data_cookie
;
41 #endif /* >= EMLXS_MODREV3 */
46 emlxs_pkt_thread(emlxs_hba_t
*hba
, void *arg1
, void *arg2
)
49 fc_packet_t
*pkt
= (fc_packet_t
*)arg1
;
56 /* Send the pkt now */
57 rval
= emlxs_pkt_send(pkt
, 1);
59 if (rval
!= FC_SUCCESS
) {
60 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_pkt_trans_msg
,
61 "Deferred emlxs_pkt_send failed: status=%x pkt=%p", rval
,
65 emlxs_set_pkt_state(sbp
, IOSTAT_LOCAL_REJECT
, 0, 1);
67 ((CHANNEL
*)sbp
->channel
)->ulpCmplCmd
++;
68 (*pkt
->pkt_comp
) (pkt
);
76 } /* emlxs_pkt_thread() */
80 emlxs_pkt_send(fc_packet_t
*pkt
, uint32_t now
)
82 emlxs_port_t
*port
= (emlxs_port_t
*)pkt
->pkt_ulp_private
;
83 emlxs_hba_t
*hba
= HBA
;
87 rval
= emlxs_fca_transport((opaque_t
)port
, pkt
);
89 /* Spawn a thread to send the pkt */
90 emlxs_thread_spawn(hba
, emlxs_pkt_thread
, (char *)pkt
, NULL
);
97 } /* emlxs_pkt_send() */
101 emlxs_pkt_free(fc_packet_t
*pkt
)
103 emlxs_port_t
*port
= (emlxs_port_t
*)pkt
->pkt_ulp_private
;
105 (void) emlxs_fca_pkt_uninit((opaque_t
)port
, pkt
);
107 if (pkt
->pkt_datalen
) {
108 (void) ddi_dma_unbind_handle(pkt
->pkt_data_dma
);
109 (void) ddi_dma_mem_free(&pkt
->pkt_data_acc
);
110 (void) ddi_dma_free_handle(&pkt
->pkt_data_dma
);
113 if (pkt
->pkt_rsplen
) {
114 (void) ddi_dma_unbind_handle(pkt
->pkt_resp_dma
);
115 (void) ddi_dma_mem_free(&pkt
->pkt_resp_acc
);
116 (void) ddi_dma_free_handle(&pkt
->pkt_resp_dma
);
119 if (pkt
->pkt_cmdlen
) {
120 (void) ddi_dma_unbind_handle(pkt
->pkt_cmd_dma
);
121 (void) ddi_dma_mem_free(&pkt
->pkt_cmd_acc
);
122 (void) ddi_dma_free_handle(&pkt
->pkt_cmd_dma
);
124 #if (EMLXS_MODREV >= EMLXS_MODREV3)
125 kmem_free(pkt
, (sizeof (fc_packet_t
) + sizeof (emlxs_buf_t
) +
126 sizeof (emlxs_pkt_cookie_t
)));
128 kmem_free(pkt
, (sizeof (fc_packet_t
) + sizeof (emlxs_buf_t
)));
129 #endif /* >= EMLXS_MODREV3 */
133 } /* emlxs_pkt_free() */
136 /* Default pkt callback routine */
138 emlxs_pkt_callback(fc_packet_t
*pkt
)
144 } /* emlxs_pkt_callback() */
149 emlxs_pkt_alloc(emlxs_port_t
*port
, uint32_t cmdlen
, uint32_t rsplen
,
150 uint32_t datalen
, int32_t sleep
)
152 emlxs_hba_t
*hba
= HBA
;
154 int32_t(*cb
) (caddr_t
);
155 unsigned long real_len
;
159 #if (EMLXS_MODREV >= EMLXS_MODREV3)
160 emlxs_pkt_cookie_t
*pkt_cookie
;
163 sizeof (fc_packet_t
) + sizeof (emlxs_buf_t
) +
164 sizeof (emlxs_pkt_cookie_t
);
168 pkt_size
= sizeof (fc_packet_t
) + sizeof (emlxs_buf_t
);
169 #endif /* >= EMLXS_MODREV3 */
172 /* Allocate some space */
173 if (!(pkt
= (fc_packet_t
*)kmem_alloc(pkt_size
, sleep
))) {
177 bzero(pkt
, pkt_size
);
179 cb
= (sleep
== KM_SLEEP
) ? DDI_DMA_SLEEP
: DDI_DMA_DONTWAIT
;
181 pkt
->pkt_ulp_private
= (opaque_t
)port
;
182 pkt
->pkt_fca_private
=
183 (opaque_t
)((uintptr_t)pkt
+ sizeof (fc_packet_t
));
184 pkt
->pkt_comp
= emlxs_pkt_callback
;
185 pkt
->pkt_tran_flags
= (FC_TRAN_CLASS3
| FC_TRAN_INTR
);
186 pkt
->pkt_cmdlen
= cmdlen
;
187 pkt
->pkt_rsplen
= rsplen
;
188 pkt
->pkt_datalen
= datalen
;
190 #if (EMLXS_MODREV >= EMLXS_MODREV3)
192 (emlxs_pkt_cookie_t
*)((uintptr_t)pkt
+ sizeof (fc_packet_t
) +
193 sizeof (emlxs_buf_t
));
194 pkt
->pkt_cmd_cookie
= &pkt_cookie
->pkt_cmd_cookie
;
195 pkt
->pkt_resp_cookie
= &pkt_cookie
->pkt_resp_cookie
;
196 pkt
->pkt_data_cookie
= &pkt_cookie
->pkt_data_cookie
;
197 #endif /* >= EMLXS_MODREV3 */
200 /* Allocate the cmd buf */
201 if (ddi_dma_alloc_handle(hba
->dip
, &hba
->dma_attr_1sg
, cb
,
202 NULL
, &pkt
->pkt_cmd_dma
) != DDI_SUCCESS
) {
209 if (ddi_dma_mem_alloc(pkt
->pkt_cmd_dma
, cmdlen
,
210 &emlxs_data_acc_attr
, DDI_DMA_CONSISTENT
, cb
, NULL
,
211 (caddr_t
*)&pkt
->pkt_cmd
, &real_len
,
212 &pkt
->pkt_cmd_acc
) != DDI_SUCCESS
) {
213 (void) ddi_dma_free_handle(&pkt
->pkt_cmd_dma
);
221 if (real_len
< cmdlen
) {
222 (void) ddi_dma_mem_free(&pkt
->pkt_cmd_acc
);
223 (void) ddi_dma_free_handle(&pkt
->pkt_cmd_dma
);
230 #if (EMLXS_MODREV >= EMLXS_MODREV3)
231 if (ddi_dma_addr_bind_handle(pkt
->pkt_cmd_dma
, NULL
,
232 pkt
->pkt_cmd
, real_len
,
233 DDI_DMA_WRITE
| DDI_DMA_CONSISTENT
, cb
, NULL
,
235 &pkt
->pkt_cmd_cookie_cnt
) != DDI_DMA_MAPPED
)
237 if (ddi_dma_addr_bind_handle(pkt
->pkt_cmd_dma
, NULL
,
238 pkt
->pkt_cmd
, real_len
,
239 DDI_DMA_WRITE
| DDI_DMA_CONSISTENT
, cb
, NULL
,
240 &pkt
->pkt_cmd_cookie
, &num_cookie
) != DDI_DMA_MAPPED
)
241 #endif /* >= EMLXS_MODREV3 */
243 (void) ddi_dma_mem_free(&pkt
->pkt_cmd_acc
);
244 (void) ddi_dma_free_handle(&pkt
->pkt_cmd_dma
);
251 #if (EMLXS_MODREV >= EMLXS_MODREV3)
252 if (pkt
->pkt_cmd_cookie_cnt
!= 1)
255 #endif /* >= EMLXS_MODREV3 */
262 bzero(pkt
->pkt_cmd
, cmdlen
);
267 /* Allocate the rsp buf */
268 if (ddi_dma_alloc_handle(hba
->dip
, &hba
->dma_attr_1sg
, cb
,
269 NULL
, &pkt
->pkt_resp_dma
) != DDI_SUCCESS
) {
276 if (ddi_dma_mem_alloc(pkt
->pkt_resp_dma
, rsplen
,
277 &emlxs_data_acc_attr
, DDI_DMA_CONSISTENT
, cb
, NULL
,
278 (caddr_t
*)&pkt
->pkt_resp
, &real_len
,
279 &pkt
->pkt_resp_acc
) != DDI_SUCCESS
) {
280 (void) ddi_dma_free_handle(&pkt
->pkt_resp_dma
);
287 if (real_len
< rsplen
) {
288 (void) ddi_dma_mem_free(&pkt
->pkt_resp_acc
);
289 (void) ddi_dma_free_handle(&pkt
->pkt_resp_dma
);
295 #if (EMLXS_MODREV >= EMLXS_MODREV3)
296 if (ddi_dma_addr_bind_handle(pkt
->pkt_resp_dma
, NULL
,
297 pkt
->pkt_resp
, real_len
,
298 DDI_DMA_READ
| DDI_DMA_CONSISTENT
, cb
, NULL
,
299 pkt
->pkt_resp_cookie
,
300 &pkt
->pkt_resp_cookie_cnt
) != DDI_DMA_MAPPED
)
302 if (ddi_dma_addr_bind_handle(pkt
->pkt_resp_dma
, NULL
,
303 pkt
->pkt_resp
, real_len
,
304 DDI_DMA_READ
| DDI_DMA_CONSISTENT
, cb
, NULL
,
305 &pkt
->pkt_resp_cookie
, &num_cookie
) != DDI_DMA_MAPPED
)
306 #endif /* >= EMLXS_MODREV3 */
308 (void) ddi_dma_mem_free(&pkt
->pkt_resp_acc
);
309 (void) ddi_dma_free_handle(&pkt
->pkt_resp_dma
);
315 #if (EMLXS_MODREV >= EMLXS_MODREV3)
316 if (pkt
->pkt_resp_cookie_cnt
!= 1)
319 #endif /* >= EMLXS_MODREV3 */
325 bzero(pkt
->pkt_resp
, rsplen
);
329 /* Allocate the data buf */
331 /* Allocate the rsp buf */
332 if (ddi_dma_alloc_handle(hba
->dip
, &hba
->dma_attr_1sg
, cb
,
333 NULL
, &pkt
->pkt_data_dma
) != DDI_SUCCESS
) {
338 if (ddi_dma_mem_alloc(pkt
->pkt_data_dma
, datalen
,
339 &emlxs_data_acc_attr
, DDI_DMA_CONSISTENT
, cb
, NULL
,
340 (caddr_t
*)&pkt
->pkt_data
, &real_len
,
341 &pkt
->pkt_data_acc
) != DDI_SUCCESS
) {
342 (void) ddi_dma_free_handle(&pkt
->pkt_data_dma
);
348 if (real_len
< datalen
) {
349 (void) ddi_dma_mem_free(&pkt
->pkt_data_acc
);
350 (void) ddi_dma_free_handle(&pkt
->pkt_data_dma
);
355 #if (EMLXS_MODREV >= EMLXS_MODREV3)
356 if (ddi_dma_addr_bind_handle(pkt
->pkt_data_dma
, NULL
,
357 pkt
->pkt_data
, real_len
,
358 DDI_DMA_READ
| DDI_DMA_WRITE
| DDI_DMA_CONSISTENT
, cb
,
359 NULL
, pkt
->pkt_data_cookie
,
360 &pkt
->pkt_data_cookie_cnt
) != DDI_DMA_MAPPED
)
362 if (ddi_dma_addr_bind_handle(pkt
->pkt_data_dma
, NULL
,
363 pkt
->pkt_data
, real_len
,
364 DDI_DMA_READ
| DDI_DMA_WRITE
| DDI_DMA_CONSISTENT
, cb
,
365 NULL
, &pkt
->pkt_data_cookie
,
366 &num_cookie
) != DDI_DMA_MAPPED
)
367 #endif /* >= EMLXS_MODREV3 */
369 (void) ddi_dma_mem_free(&pkt
->pkt_data_acc
);
370 (void) ddi_dma_free_handle(&pkt
->pkt_data_dma
);
375 #if (EMLXS_MODREV >= EMLXS_MODREV3)
376 if (pkt
->pkt_data_cookie_cnt
!= 1)
379 #endif /* >= EMLXS_MODREV3 */
384 bzero(pkt
->pkt_data
, datalen
);
388 bzero((void *)sbp
, sizeof (emlxs_buf_t
));
390 mutex_init(&sbp
->mtx
, NULL
, MUTEX_DRIVER
, DDI_INTR_PRI(hba
->intr_arg
));
391 sbp
->pkt_flags
= PACKET_VALID
| PACKET_ULP_OWNED
| PACKET_ALLOCATED
;
394 sbp
->iocbq
.sbp
= sbp
;
401 (void) ddi_dma_unbind_handle(pkt
->pkt_data_dma
);
402 (void) ddi_dma_mem_free(&pkt
->pkt_data_acc
);
403 (void) ddi_dma_free_handle(&pkt
->pkt_data_dma
);
407 (void) ddi_dma_unbind_handle(pkt
->pkt_resp_dma
);
408 (void) ddi_dma_mem_free(&pkt
->pkt_resp_acc
);
409 (void) ddi_dma_free_handle(&pkt
->pkt_resp_dma
);
413 (void) ddi_dma_unbind_handle(pkt
->pkt_cmd_dma
);
414 (void) ddi_dma_mem_free(&pkt
->pkt_cmd_acc
);
415 (void) ddi_dma_free_handle(&pkt
->pkt_cmd_dma
);
419 kmem_free(pkt
, pkt_size
);
424 } /* emlxs_pkt_alloc() */