[SCSI] bfa: Brocade BFA FC SCSI driver
[safe/jmp/linux-2.6] / drivers / scsi / bfa / bfa_uf.c
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
27 BFA_TRC_FILE(HAL, UF);
28 BFA_MODULE(uf);
29
30 /*
31  *****************************************************************************
32  * Internal functions
33  *****************************************************************************
34  */
35 static 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
45 static void
46 claim_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
61 static void
62 claim_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
101 static void
102 claim_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
131 static void
132 uf_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
139 static void
140 bfa_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
157 static void
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)
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
172 static void
173 bfa_uf_initdone(struct bfa_s *bfa)
174 {
175 }
176
177 static void
178 bfa_uf_detach(struct bfa_s *bfa)
179 {
180 }
181
182 static struct bfa_uf_s *
183 bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
184 {
185         struct bfa_uf_s   *uf;
186
187         bfa_q_deq(&uf_mod->uf_free_q, &uf);
188         return (uf);
189 }
190
191 static void
192 bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
193 {
194         list_add_tail(&uf->qe, &uf_mod->uf_free_q);
195 }
196
197 static bfa_status_t
198 bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
199 {
200         struct bfi_uf_buf_post_s *uf_post_msg;
201
202         uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
203         if (!uf_post_msg)
204                 return BFA_STATUS_FAILED;
205
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);
209
210         bfa_trc(ufm->bfa, uf->uf_tag);
211
212         list_add_tail(&uf->qe, &ufm->uf_posted_q);
213         return BFA_STATUS_OK;
214 }
215
216 static void
217 bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
218 {
219         struct bfa_uf_s   *uf;
220
221         while ((uf = bfa_uf_get(uf_mod)) != NULL) {
222                 if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
223                         break;
224         }
225 }
226
227 static void
228 uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
229 {
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];
235         struct fchs_s         *fchs;
236
237         m->frm_len = bfa_os_ntohs(m->frm_len);
238         m->xfr_len = bfa_os_ntohs(m->xfr_len);
239
240         fchs = (struct fchs_s *) uf_buf;
241
242         list_del(&uf->qe);      /* dequeue from posted queue */
243
244         uf->data_ptr = buf;
245         uf->data_len = m->xfr_len;
246
247         bfa_assert(uf->data_len >= sizeof(struct fchs_s));
248
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);
252         } else {
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);
257         }
258
259         bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
260 }
261
262 static void
263 bfa_uf_stop(struct bfa_s *bfa)
264 {
265 }
266
267 static void
268 bfa_uf_iocdisable(struct bfa_s *bfa)
269 {
270         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
271         struct bfa_uf_s   *uf;
272         struct list_head        *qe, *qen;
273
274         list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
275                 uf = (struct bfa_uf_s *) qe;
276                 list_del(&uf->qe);
277                 bfa_uf_put(ufm, uf);
278         }
279 }
280
281 static void
282 bfa_uf_start(struct bfa_s *bfa)
283 {
284         bfa_uf_post_all(BFA_UF_MOD(bfa));
285 }
286
287
288
289 /**
290  *  bfa_uf_api
291  */
292
293 /**
294  *              Register handler for all unsolicted recieve frames.
295  *
296  * @param[in]   bfa             BFA instance
297  * @param[in]   ufrecv  receive handler function
298  * @param[in]   cbarg   receive handler arg
299  */
300 void
301 bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
302 {
303         struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
304
305         ufm->ufrecv = ufrecv;
306         ufm->cbarg = cbarg;
307 }
308
309 /**
310  *              Free an unsolicited frame back to BFA.
311  *
312  * @param[in]           uf              unsolicited frame to be freed
313  *
314  * @return None
315  */
316 void
317 bfa_uf_free(struct bfa_uf_s *uf)
318 {
319         bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
320         bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
321 }
322
323
324
325 /**
326  *  uf_pub BFA uf module public functions
327  */
328
329 void
330 bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
331 {
332         bfa_trc(bfa, msg->mhdr.msg_id);
333
334         switch (msg->mhdr.msg_id) {
335         case BFI_UF_I2H_FRM_RCVD:
336                 uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
337                 break;
338
339         default:
340                 bfa_trc(bfa, msg->mhdr.msg_id);
341                 bfa_assert(0);
342         }
343 }
344
345