• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/scsi/bfa/
1/*
2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
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
11 *
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.
16 */
17
18/**
19 *  bfa_uf.c BFA unsolicited frame receive implementation
20 */
21
22#include <bfa.h>
23#include <bfa_svc.h>
24#include <bfi/bfi_uf.h>
25#include <cs/bfa_debug.h>
26
27BFA_TRC_FILE(HAL, UF);
28BFA_MODULE(uf);
29
30/*
31 *****************************************************************************
32 * Internal functions
33 *****************************************************************************
34 */
35static void
36__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
37{
38	struct bfa_uf_s   *uf = cbarg;
39	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
40
41	if (complete)
42		ufm->ufrecv(ufm->cbarg, uf);
43}
44
45static void
46claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
47{
48	u32        uf_pb_tot_sz;
49
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),
53							BFA_DMA_ALIGN_SZ);
54
55	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
56	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
57
58	bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
59}
60
61static void
62claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
63{
64	struct bfi_uf_buf_post_s *uf_bp_msg;
65	struct bfi_sge_s      *sge;
66	union bfi_addr_u      sga_zero = { {0} };
67	u16        i;
68	u16        buf_len;
69
70	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
71	uf_bp_msg = ufm->uf_buf_posts;
72
73	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
74	     i++, uf_bp_msg++) {
75		bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
76
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,
81			    bfa_lpuid(ufm->bfa));
82
83		sge = uf_bp_msg->sge;
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));
87		bfa_sge_to_be(sge);
88
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]);
93	}
94
95	/**
96	 * advance pointer beyond consumed memory
97	 */
98	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
99}
100
101static void
102claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
103{
104	u16        i;
105	struct bfa_uf_s   *uf;
106
107	/*
108	 * Claim block of memory for UF list
109	 */
110	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
111
112	/*
113	 * Initialize UFs and queue it in UF free queue
114	 */
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));
117		uf->bfa = ufm->bfa;
118		uf->uf_tag = i;
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);
123	}
124
125	/**
126	 * advance memory pointer
127	 */
128	bfa_meminfo_kva(mi) = (u8 *) uf;
129}
130
131static void
132uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
133{
134	claim_uf_pbs(ufm, mi);
135	claim_ufs(ufm, mi);
136	claim_uf_post_msgs(ufm, mi);
137}
138
139static void
140bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
141{
142	u32        num_ufs = cfg->fwcfg.num_uf_bufs;
143
144	/*
145	 * dma-able memory for UF posted bufs
146	 */
147	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
148							BFA_DMA_ALIGN_SZ);
149
150	/*
151	 * kernel Virtual memory for UFs and UF buf post msg copies
152	 */
153	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
154	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
155}
156
157static void
158bfa_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)
160{
161	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
162
163	bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
164	ufm->bfa = bfa;
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);
168
169	uf_mem_claim(ufm, meminfo);
170}
171
172static void
173bfa_uf_detach(struct bfa_s *bfa)
174{
175}
176
177static struct bfa_uf_s *
178bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
179{
180	struct bfa_uf_s   *uf;
181
182	bfa_q_deq(&uf_mod->uf_free_q, &uf);
183	return uf;
184}
185
186static void
187bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
188{
189	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
190}
191
192static bfa_status_t
193bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
194{
195	struct bfi_uf_buf_post_s *uf_post_msg;
196
197	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
198	if (!uf_post_msg)
199		return BFA_STATUS_FAILED;
200
201	bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
202		      sizeof(struct bfi_uf_buf_post_s));
203	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
204
205	bfa_trc(ufm->bfa, uf->uf_tag);
206
207	list_add_tail(&uf->qe, &ufm->uf_posted_q);
208	return BFA_STATUS_OK;
209}
210
211static void
212bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
213{
214	struct bfa_uf_s   *uf;
215
216	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
217		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
218			break;
219	}
220}
221
222static void
223uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
224{
225	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
226	u16        uf_tag = m->buf_tag;
227	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
228	struct bfa_uf_s   *uf = &ufm->uf_list[uf_tag];
229	u8        *buf = &uf_buf->d[0];
230	struct fchs_s         *fchs;
231
232	m->frm_len = bfa_os_ntohs(m->frm_len);
233	m->xfr_len = bfa_os_ntohs(m->xfr_len);
234
235	fchs = (struct fchs_s *) uf_buf;
236
237	list_del(&uf->qe);	/* dequeue from posted queue */
238
239	uf->data_ptr = buf;
240	uf->data_len = m->xfr_len;
241
242	bfa_assert(uf->data_len >= sizeof(struct fchs_s));
243
244	if (uf->data_len == sizeof(struct fchs_s)) {
245		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
246			       uf->data_len, (struct fchs_s *) buf);
247	} else {
248		u32        pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
249		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
250				      BFA_PL_EID_RX, uf->data_len,
251				      (struct fchs_s *) buf, pld_w0);
252	}
253
254	if (bfa->fcs)
255		__bfa_cb_uf_recv(uf, BFA_TRUE);
256	else
257		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
258}
259
260static void
261bfa_uf_stop(struct bfa_s *bfa)
262{
263}
264
265static void
266bfa_uf_iocdisable(struct bfa_s *bfa)
267{
268	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
269	struct bfa_uf_s   *uf;
270	struct list_head        *qe, *qen;
271
272	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
273		uf = (struct bfa_uf_s *) qe;
274		list_del(&uf->qe);
275		bfa_uf_put(ufm, uf);
276	}
277}
278
279static void
280bfa_uf_start(struct bfa_s *bfa)
281{
282	bfa_uf_post_all(BFA_UF_MOD(bfa));
283}
284
285
286
287/**
288 *  bfa_uf_api
289 */
290
291/**
292 * 		Register handler for all unsolicted recieve frames.
293 *
294 * @param[in]	bfa		BFA instance
295 * @param[in]	ufrecv	receive handler function
296 * @param[in]	cbarg	receive handler arg
297 */
298void
299bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
300{
301	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
302
303	ufm->ufrecv = ufrecv;
304	ufm->cbarg = cbarg;
305}
306
307/**
308 * 		Free an unsolicited frame back to BFA.
309 *
310 * @param[in]		uf		unsolicited frame to be freed
311 *
312 * @return None
313 */
314void
315bfa_uf_free(struct bfa_uf_s *uf)
316{
317	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
318	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
319}
320
321
322
323/**
324 *  uf_pub BFA uf module public functions
325 */
326
327void
328bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
329{
330	bfa_trc(bfa, msg->mhdr.msg_id);
331
332	switch (msg->mhdr.msg_id) {
333	case BFI_UF_I2H_FRM_RCVD:
334		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
335		break;
336
337	default:
338		bfa_trc(bfa, msg->mhdr.msg_id);
339		bfa_assert(0);
340	}
341}
342