2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
19 * bfa_uf.c BFA unsolicited frame receive implementation
24 #include <bfi/bfi_uf.h>
25 #include <cs/bfa_debug.h>
27 BFA_TRC_FILE(HAL
, UF
);
31 *****************************************************************************
33 *****************************************************************************
36 __bfa_cb_uf_recv(void *cbarg
, bfa_boolean_t complete
)
38 struct bfa_uf_s
*uf
= cbarg
;
39 struct bfa_uf_mod_s
*ufm
= BFA_UF_MOD(uf
->bfa
);
42 ufm
->ufrecv(ufm
->cbarg
, uf
);
46 claim_uf_pbs(struct bfa_uf_mod_s
*ufm
, struct bfa_meminfo_s
*mi
)
50 ufm
->uf_pbs_kva
= (struct bfa_uf_buf_s
*) bfa_meminfo_dma_virt(mi
);
51 ufm
->uf_pbs_pa
= bfa_meminfo_dma_phys(mi
);
52 uf_pb_tot_sz
= BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s
) * ufm
->num_ufs
),
55 bfa_meminfo_dma_virt(mi
) += uf_pb_tot_sz
;
56 bfa_meminfo_dma_phys(mi
) += uf_pb_tot_sz
;
58 bfa_os_memset((void *)ufm
->uf_pbs_kva
, 0, uf_pb_tot_sz
);
62 claim_uf_post_msgs(struct bfa_uf_mod_s
*ufm
, struct bfa_meminfo_s
*mi
)
64 struct bfi_uf_buf_post_s
*uf_bp_msg
;
65 struct bfi_sge_s
*sge
;
66 union bfi_addr_u sga_zero
= { {0} };
70 ufm
->uf_buf_posts
= (struct bfi_uf_buf_post_s
*) bfa_meminfo_kva(mi
);
71 uf_bp_msg
= ufm
->uf_buf_posts
;
73 for (i
= 0, uf_bp_msg
= ufm
->uf_buf_posts
; i
< ufm
->num_ufs
;
75 bfa_os_memset(uf_bp_msg
, 0, sizeof(struct bfi_uf_buf_post_s
));
77 uf_bp_msg
->buf_tag
= i
;
78 buf_len
= sizeof(struct bfa_uf_buf_s
);
79 uf_bp_msg
->buf_len
= bfa_os_htons(buf_len
);
80 bfi_h2i_set(uf_bp_msg
->mh
, BFI_MC_UF
, BFI_UF_H2I_BUF_POST
,
84 sge
[0].sg_len
= buf_len
;
85 sge
[0].flags
= BFI_SGE_DATA_LAST
;
86 bfa_dma_addr_set(sge
[0].sga
, ufm_pbs_pa(ufm
, i
));
89 sge
[1].sg_len
= buf_len
;
90 sge
[1].flags
= BFI_SGE_PGDLEN
;
91 sge
[1].sga
= sga_zero
;
92 bfa_sge_to_be(&sge
[1]);
96 * advance pointer beyond consumed memory
98 bfa_meminfo_kva(mi
) = (u8
*) uf_bp_msg
;
102 claim_ufs(struct bfa_uf_mod_s
*ufm
, struct bfa_meminfo_s
*mi
)
108 * Claim block of memory for UF list
110 ufm
->uf_list
= (struct bfa_uf_s
*) bfa_meminfo_kva(mi
);
113 * Initialize UFs and queue it in UF free queue
115 for (i
= 0, uf
= ufm
->uf_list
; i
< ufm
->num_ufs
; i
++, uf
++) {
116 bfa_os_memset(uf
, 0, sizeof(struct bfa_uf_s
));
119 uf
->pb_len
= sizeof(struct bfa_uf_buf_s
);
120 uf
->buf_kva
= (void *)&ufm
->uf_pbs_kva
[i
];
121 uf
->buf_pa
= ufm_pbs_pa(ufm
, i
);
122 list_add_tail(&uf
->qe
, &ufm
->uf_free_q
);
126 * advance memory pointer
128 bfa_meminfo_kva(mi
) = (u8
*) uf
;
132 uf_mem_claim(struct bfa_uf_mod_s
*ufm
, struct bfa_meminfo_s
*mi
)
134 claim_uf_pbs(ufm
, mi
);
136 claim_uf_post_msgs(ufm
, mi
);
140 bfa_uf_meminfo(struct bfa_iocfc_cfg_s
*cfg
, u32
*ndm_len
, u32
*dm_len
)
142 u32 num_ufs
= cfg
->fwcfg
.num_uf_bufs
;
145 * dma-able memory for UF posted bufs
147 *dm_len
+= BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s
) * num_ufs
),
151 * kernel Virtual memory for UFs and UF buf post msg copies
153 *ndm_len
+= sizeof(struct bfa_uf_s
) * num_ufs
;
154 *ndm_len
+= sizeof(struct bfi_uf_buf_post_s
) * num_ufs
;
158 bfa_uf_attach(struct bfa_s
*bfa
, void *bfad
, struct bfa_iocfc_cfg_s
*cfg
,
159 struct bfa_meminfo_s
*meminfo
, struct bfa_pcidev_s
*pcidev
)
161 struct bfa_uf_mod_s
*ufm
= BFA_UF_MOD(bfa
);
163 bfa_os_memset(ufm
, 0, sizeof(struct bfa_uf_mod_s
));
165 ufm
->num_ufs
= cfg
->fwcfg
.num_uf_bufs
;
166 INIT_LIST_HEAD(&ufm
->uf_free_q
);
167 INIT_LIST_HEAD(&ufm
->uf_posted_q
);
169 uf_mem_claim(ufm
, meminfo
);
173 bfa_uf_initdone(struct bfa_s
*bfa
)
178 bfa_uf_detach(struct bfa_s
*bfa
)
182 static struct bfa_uf_s
*
183 bfa_uf_get(struct bfa_uf_mod_s
*uf_mod
)
187 bfa_q_deq(&uf_mod
->uf_free_q
, &uf
);
192 bfa_uf_put(struct bfa_uf_mod_s
*uf_mod
, struct bfa_uf_s
*uf
)
194 list_add_tail(&uf
->qe
, &uf_mod
->uf_free_q
);
198 bfa_uf_post(struct bfa_uf_mod_s
*ufm
, struct bfa_uf_s
*uf
)
200 struct bfi_uf_buf_post_s
*uf_post_msg
;
202 uf_post_msg
= bfa_reqq_next(ufm
->bfa
, BFA_REQQ_FCXP
);
204 return BFA_STATUS_FAILED
;
206 bfa_os_memcpy(uf_post_msg
, &ufm
->uf_buf_posts
[uf
->uf_tag
],
207 sizeof(struct bfi_uf_buf_post_s
));
208 bfa_reqq_produce(ufm
->bfa
, BFA_REQQ_FCXP
);
210 bfa_trc(ufm
->bfa
, uf
->uf_tag
);
212 list_add_tail(&uf
->qe
, &ufm
->uf_posted_q
);
213 return BFA_STATUS_OK
;
217 bfa_uf_post_all(struct bfa_uf_mod_s
*uf_mod
)
221 while ((uf
= bfa_uf_get(uf_mod
)) != NULL
) {
222 if (bfa_uf_post(uf_mod
, uf
) != BFA_STATUS_OK
)
228 uf_recv(struct bfa_s
*bfa
, struct bfi_uf_frm_rcvd_s
*m
)
230 struct bfa_uf_mod_s
*ufm
= BFA_UF_MOD(bfa
);
231 u16 uf_tag
= m
->buf_tag
;
232 struct bfa_uf_buf_s
*uf_buf
= &ufm
->uf_pbs_kva
[uf_tag
];
233 struct bfa_uf_s
*uf
= &ufm
->uf_list
[uf_tag
];
234 u8
*buf
= &uf_buf
->d
[0];
237 m
->frm_len
= bfa_os_ntohs(m
->frm_len
);
238 m
->xfr_len
= bfa_os_ntohs(m
->xfr_len
);
240 fchs
= (struct fchs_s
*) uf_buf
;
242 list_del(&uf
->qe
); /* dequeue from posted queue */
245 uf
->data_len
= m
->xfr_len
;
247 bfa_assert(uf
->data_len
>= sizeof(struct fchs_s
));
249 if (uf
->data_len
== sizeof(struct fchs_s
)) {
250 bfa_plog_fchdr(bfa
->plog
, BFA_PL_MID_HAL_UF
, BFA_PL_EID_RX
,
251 uf
->data_len
, (struct fchs_s
*) buf
);
253 u32 pld_w0
= *((u32
*) (buf
+ sizeof(struct fchs_s
)));
254 bfa_plog_fchdr_and_pl(bfa
->plog
, BFA_PL_MID_HAL_UF
,
255 BFA_PL_EID_RX
, uf
->data_len
,
256 (struct fchs_s
*) buf
, pld_w0
);
259 bfa_cb_queue(bfa
, &uf
->hcb_qe
, __bfa_cb_uf_recv
, uf
);
263 bfa_uf_stop(struct bfa_s
*bfa
)
268 bfa_uf_iocdisable(struct bfa_s
*bfa
)
270 struct bfa_uf_mod_s
*ufm
= BFA_UF_MOD(bfa
);
272 struct list_head
*qe
, *qen
;
274 list_for_each_safe(qe
, qen
, &ufm
->uf_posted_q
) {
275 uf
= (struct bfa_uf_s
*) qe
;
282 bfa_uf_start(struct bfa_s
*bfa
)
284 bfa_uf_post_all(BFA_UF_MOD(bfa
));
294 * Register handler for all unsolicted recieve frames.
296 * @param[in] bfa BFA instance
297 * @param[in] ufrecv receive handler function
298 * @param[in] cbarg receive handler arg
301 bfa_uf_recv_register(struct bfa_s
*bfa
, bfa_cb_uf_recv_t ufrecv
, void *cbarg
)
303 struct bfa_uf_mod_s
*ufm
= BFA_UF_MOD(bfa
);
305 ufm
->ufrecv
= ufrecv
;
310 * Free an unsolicited frame back to BFA.
312 * @param[in] uf unsolicited frame to be freed
317 bfa_uf_free(struct bfa_uf_s
*uf
)
319 bfa_uf_put(BFA_UF_MOD(uf
->bfa
), uf
);
320 bfa_uf_post_all(BFA_UF_MOD(uf
->bfa
));
326 * uf_pub BFA uf module public functions
330 bfa_uf_isr(struct bfa_s
*bfa
, struct bfi_msg_s
*msg
)
332 bfa_trc(bfa
, msg
->mhdr
.msg_id
);
334 switch (msg
->mhdr
.msg_id
) {
335 case BFI_UF_I2H_FRM_RCVD
:
336 uf_recv(bfa
, (struct bfi_uf_frm_rcvd_s
*) msg
);
340 bfa_trc(bfa
, msg
->mhdr
.msg_id
);