Commit | Line | Data |
---|---|---|
7725ccfd JH |
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 | #include <bfa.h> | |
19 | #include <defs/bfa_defs_pci.h> | |
20 | #include <cs/bfa_debug.h> | |
21 | #include <bfa_iocfc.h> | |
22 | ||
23 | #define DEF_CFG_NUM_FABRICS 1 | |
24 | #define DEF_CFG_NUM_LPORTS 256 | |
25 | #define DEF_CFG_NUM_CQS 4 | |
26 | #define DEF_CFG_NUM_IOIM_REQS (BFA_IOIM_MAX) | |
27 | #define DEF_CFG_NUM_TSKIM_REQS 128 | |
28 | #define DEF_CFG_NUM_FCXP_REQS 64 | |
29 | #define DEF_CFG_NUM_UF_BUFS 64 | |
30 | #define DEF_CFG_NUM_RPORTS 1024 | |
31 | #define DEF_CFG_NUM_ITNIMS (DEF_CFG_NUM_RPORTS) | |
32 | #define DEF_CFG_NUM_TINS 256 | |
33 | ||
34 | #define DEF_CFG_NUM_SGPGS 2048 | |
35 | #define DEF_CFG_NUM_REQQ_ELEMS 256 | |
36 | #define DEF_CFG_NUM_RSPQ_ELEMS 64 | |
37 | #define DEF_CFG_NUM_SBOOT_TGTS 16 | |
38 | #define DEF_CFG_NUM_SBOOT_LUNS 16 | |
39 | ||
40 | /** | |
41 | * Use this function query the memory requirement of the BFA library. | |
42 | * This function needs to be called before bfa_attach() to get the | |
43 | * memory required of the BFA layer for a given driver configuration. | |
44 | * | |
45 | * This call will fail, if the cap is out of range compared to pre-defined | |
46 | * values within the BFA library | |
47 | * | |
48 | * @param[in] cfg - pointer to bfa_ioc_cfg_t. Driver layer should indicate | |
49 | * its configuration in this structure. | |
50 | * The default values for struct bfa_iocfc_cfg_s can be | |
51 | * fetched using bfa_cfg_get_default() API. | |
52 | * | |
53 | * If cap's boundary check fails, the library will use | |
54 | * the default bfa_cap_t values (and log a warning msg). | |
55 | * | |
56 | * @param[out] meminfo - pointer to bfa_meminfo_t. This content | |
57 | * indicates the memory type (see bfa_mem_type_t) and | |
58 | * amount of memory required. | |
59 | * | |
60 | * Driver should allocate the memory, populate the | |
61 | * starting address for each block and provide the same | |
62 | * structure as input parameter to bfa_attach() call. | |
63 | * | |
64 | * @return void | |
65 | * | |
66 | * Special Considerations: @note | |
67 | */ | |
68 | void | |
69 | bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo) | |
70 | { | |
71 | int i; | |
72 | u32 km_len = 0, dm_len = 0; | |
73 | ||
74 | bfa_assert((cfg != NULL) && (meminfo != NULL)); | |
75 | ||
76 | bfa_os_memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s)); | |
77 | meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type = | |
78 | BFA_MEM_TYPE_KVA; | |
79 | meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type = | |
80 | BFA_MEM_TYPE_DMA; | |
81 | ||
82 | bfa_iocfc_meminfo(cfg, &km_len, &dm_len); | |
83 | ||
84 | for (i = 0; hal_mods[i]; i++) | |
85 | hal_mods[i]->meminfo(cfg, &km_len, &dm_len); | |
86 | ||
7873ca4e | 87 | dm_len += bfa_port_meminfo(); |
7725ccfd JH |
88 | |
89 | meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len; | |
90 | meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len; | |
91 | } | |
92 | ||
7873ca4e KG |
93 | static void |
94 | bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi) | |
95 | { | |
96 | struct bfa_port_s *port = &bfa->modules.port; | |
97 | uint32_t dm_len; | |
98 | uint8_t *dm_kva; | |
99 | uint64_t dm_pa; | |
100 | ||
101 | dm_len = bfa_port_meminfo(); | |
102 | dm_kva = bfa_meminfo_dma_virt(mi); | |
103 | dm_pa = bfa_meminfo_dma_phys(mi); | |
104 | ||
105 | memset(port, 0, sizeof(struct bfa_port_s)); | |
106 | bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm); | |
107 | bfa_port_mem_claim(port, dm_kva, dm_pa); | |
108 | ||
109 | bfa_meminfo_dma_virt(mi) = dm_kva + dm_len; | |
110 | bfa_meminfo_dma_phys(mi) = dm_pa + dm_len; | |
111 | } | |
112 | ||
7725ccfd JH |
113 | /** |
114 | * Use this function to do attach the driver instance with the BFA | |
115 | * library. This function will not trigger any HW initialization | |
116 | * process (which will be done in bfa_init() call) | |
117 | * | |
118 | * This call will fail, if the cap is out of range compared to | |
119 | * pre-defined values within the BFA library | |
120 | * | |
121 | * @param[out] bfa Pointer to bfa_t. | |
122 | * @param[in] bfad Opaque handle back to the driver's IOC structure | |
123 | * @param[in] cfg Pointer to bfa_ioc_cfg_t. Should be same structure | |
124 | * that was used in bfa_cfg_get_meminfo(). | |
125 | * @param[in] meminfo Pointer to bfa_meminfo_t. The driver should | |
126 | * use the bfa_cfg_get_meminfo() call to | |
127 | * find the memory blocks required, allocate the | |
128 | * required memory and provide the starting addresses. | |
129 | * @param[in] pcidev pointer to struct bfa_pcidev_s | |
130 | * | |
131 | * @return | |
132 | * void | |
133 | * | |
134 | * Special Considerations: | |
135 | * | |
136 | * @note | |
137 | * | |
138 | */ | |
139 | void | |
140 | bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | |
141 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | |
142 | { | |
143 | int i; | |
144 | struct bfa_mem_elem_s *melem; | |
145 | ||
146 | bfa->fcs = BFA_FALSE; | |
147 | ||
148 | bfa_assert((cfg != NULL) && (meminfo != NULL)); | |
149 | ||
150 | /** | |
151 | * initialize all memory pointers for iterative allocation | |
152 | */ | |
153 | for (i = 0; i < BFA_MEM_TYPE_MAX; i++) { | |
154 | melem = meminfo->meminfo + i; | |
155 | melem->kva_curp = melem->kva; | |
156 | melem->dma_curp = melem->dma; | |
157 | } | |
158 | ||
159 | bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev); | |
160 | ||
161 | for (i = 0; hal_mods[i]; i++) | |
162 | hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev); | |
163 | ||
7873ca4e | 164 | bfa_com_port_attach(bfa, meminfo); |
7725ccfd JH |
165 | } |
166 | ||
167 | /** | |
168 | * Use this function to delete a BFA IOC. IOC should be stopped (by | |
169 | * calling bfa_stop()) before this function call. | |
170 | * | |
171 | * @param[in] bfa - pointer to bfa_t. | |
172 | * | |
173 | * @return | |
174 | * void | |
175 | * | |
176 | * Special Considerations: | |
177 | * | |
178 | * @note | |
179 | */ | |
180 | void | |
181 | bfa_detach(struct bfa_s *bfa) | |
182 | { | |
183 | int i; | |
184 | ||
185 | for (i = 0; hal_mods[i]; i++) | |
186 | hal_mods[i]->detach(bfa); | |
187 | ||
188 | bfa_iocfc_detach(bfa); | |
189 | } | |
190 | ||
191 | ||
192 | void | |
193 | bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod) | |
194 | { | |
195 | bfa->trcmod = trcmod; | |
196 | } | |
197 | ||
198 | ||
199 | void | |
200 | bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod) | |
201 | { | |
202 | bfa->logm = logmod; | |
203 | } | |
204 | ||
205 | ||
206 | void | |
207 | bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen) | |
208 | { | |
209 | bfa->aen = aen; | |
210 | } | |
211 | ||
212 | void | |
213 | bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog) | |
214 | { | |
215 | bfa->plog = plog; | |
216 | } | |
217 | ||
218 | /** | |
219 | * Initialize IOC. | |
220 | * | |
221 | * This function will return immediately, when the IOC initialization is | |
222 | * completed, the bfa_cb_init() will be called. | |
223 | * | |
224 | * @param[in] bfa instance | |
225 | * | |
226 | * @return void | |
227 | * | |
228 | * Special Considerations: | |
229 | * | |
230 | * @note | |
231 | * When this function returns, the driver should register the interrupt service | |
232 | * routine(s) and enable the device interrupts. If this is not done, | |
233 | * bfa_cb_init() will never get called | |
234 | */ | |
235 | void | |
236 | bfa_init(struct bfa_s *bfa) | |
237 | { | |
238 | bfa_iocfc_init(bfa); | |
239 | } | |
240 | ||
241 | /** | |
242 | * Use this function initiate the IOC configuration setup. This function | |
243 | * will return immediately. | |
244 | * | |
245 | * @param[in] bfa instance | |
246 | * | |
247 | * @return None | |
248 | */ | |
249 | void | |
250 | bfa_start(struct bfa_s *bfa) | |
251 | { | |
252 | bfa_iocfc_start(bfa); | |
253 | } | |
254 | ||
255 | /** | |
256 | * Use this function quiese the IOC. This function will return immediately, | |
257 | * when the IOC is actually stopped, the bfa_cb_stop() will be called. | |
258 | * | |
259 | * @param[in] bfa - pointer to bfa_t. | |
260 | * | |
261 | * @return None | |
262 | * | |
263 | * Special Considerations: | |
264 | * bfa_cb_stop() could be called before or after bfa_stop() returns. | |
265 | * | |
266 | * @note | |
267 | * In case of any failure, we could handle it automatically by doing a | |
268 | * reset and then succeed the bfa_stop() call. | |
269 | */ | |
270 | void | |
271 | bfa_stop(struct bfa_s *bfa) | |
272 | { | |
273 | bfa_iocfc_stop(bfa); | |
274 | } | |
275 | ||
276 | void | |
277 | bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q) | |
278 | { | |
279 | INIT_LIST_HEAD(comp_q); | |
280 | list_splice_tail_init(&bfa->comp_q, comp_q); | |
281 | } | |
282 | ||
283 | void | |
284 | bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q) | |
285 | { | |
286 | struct list_head *qe; | |
287 | struct list_head *qen; | |
288 | struct bfa_cb_qe_s *hcb_qe; | |
289 | ||
290 | list_for_each_safe(qe, qen, comp_q) { | |
291 | hcb_qe = (struct bfa_cb_qe_s *) qe; | |
292 | hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE); | |
293 | } | |
294 | } | |
295 | ||
296 | void | |
297 | bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q) | |
298 | { | |
299 | struct list_head *qe; | |
300 | struct bfa_cb_qe_s *hcb_qe; | |
301 | ||
302 | while (!list_empty(comp_q)) { | |
303 | bfa_q_deq(comp_q, &qe); | |
304 | hcb_qe = (struct bfa_cb_qe_s *) qe; | |
305 | hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE); | |
306 | } | |
307 | } | |
308 | ||
309 | void | |
310 | bfa_attach_fcs(struct bfa_s *bfa) | |
311 | { | |
312 | bfa->fcs = BFA_TRUE; | |
313 | } | |
314 | ||
315 | /** | |
316 | * Periodic timer heart beat from driver | |
317 | */ | |
318 | void | |
319 | bfa_timer_tick(struct bfa_s *bfa) | |
320 | { | |
321 | bfa_timer_beat(&bfa->timer_mod); | |
322 | } | |
323 | ||
324 | #ifndef BFA_BIOS_BUILD | |
325 | /** | |
326 | * Return the list of PCI vendor/device id lists supported by this | |
327 | * BFA instance. | |
328 | */ | |
329 | void | |
330 | bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids) | |
331 | { | |
332 | static struct bfa_pciid_s __pciids[] = { | |
333 | {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G2P}, | |
334 | {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G1P}, | |
335 | {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT}, | |
336 | }; | |
337 | ||
338 | *npciids = sizeof(__pciids) / sizeof(__pciids[0]); | |
339 | *pciids = __pciids; | |
340 | } | |
341 | ||
342 | /** | |
343 | * Use this function query the default struct bfa_iocfc_cfg_s value (compiled | |
344 | * into BFA layer). The OS driver can then turn back and overwrite entries that | |
345 | * have been configured by the user. | |
346 | * | |
347 | * @param[in] cfg - pointer to bfa_ioc_cfg_t | |
348 | * | |
349 | * @return | |
350 | * void | |
351 | * | |
352 | * Special Considerations: | |
353 | * note | |
354 | */ | |
355 | void | |
356 | bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg) | |
357 | { | |
358 | cfg->fwcfg.num_fabrics = DEF_CFG_NUM_FABRICS; | |
359 | cfg->fwcfg.num_lports = DEF_CFG_NUM_LPORTS; | |
360 | cfg->fwcfg.num_rports = DEF_CFG_NUM_RPORTS; | |
361 | cfg->fwcfg.num_ioim_reqs = DEF_CFG_NUM_IOIM_REQS; | |
362 | cfg->fwcfg.num_tskim_reqs = DEF_CFG_NUM_TSKIM_REQS; | |
363 | cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS; | |
364 | cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS; | |
365 | cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS; | |
366 | ||
367 | cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS; | |
368 | cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS; | |
369 | cfg->drvcfg.num_sgpgs = DEF_CFG_NUM_SGPGS; | |
370 | cfg->drvcfg.num_sboot_tgts = DEF_CFG_NUM_SBOOT_TGTS; | |
371 | cfg->drvcfg.num_sboot_luns = DEF_CFG_NUM_SBOOT_LUNS; | |
372 | cfg->drvcfg.path_tov = BFA_FCPIM_PATHTOV_DEF; | |
373 | cfg->drvcfg.ioc_recover = BFA_FALSE; | |
374 | cfg->drvcfg.delay_comp = BFA_FALSE; | |
375 | ||
376 | } | |
377 | ||
378 | void | |
379 | bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg) | |
380 | { | |
381 | bfa_cfg_get_default(cfg); | |
382 | cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN; | |
383 | cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN; | |
384 | cfg->fwcfg.num_fcxp_reqs = BFA_FCXP_MIN; | |
385 | cfg->fwcfg.num_uf_bufs = BFA_UF_MIN; | |
386 | cfg->fwcfg.num_rports = BFA_RPORT_MIN; | |
387 | ||
388 | cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN; | |
389 | cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN; | |
390 | cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN; | |
391 | cfg->drvcfg.min_cfg = BFA_TRUE; | |
392 | } | |
393 | ||
394 | void | |
395 | bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr) | |
396 | { | |
397 | bfa_ioc_get_attr(&bfa->ioc, ioc_attr); | |
398 | } | |
399 | ||
400 | /** | |
401 | * Retrieve firmware trace information on IOC failure. | |
402 | */ | |
403 | bfa_status_t | |
404 | bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen) | |
405 | { | |
406 | return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen); | |
407 | } | |
408 | ||
738c9e66 KG |
409 | /** |
410 | * Clear the saved firmware trace information of an IOC. | |
411 | */ | |
412 | void | |
413 | bfa_debug_fwsave_clear(struct bfa_s *bfa) | |
414 | { | |
415 | bfa_ioc_debug_fwsave_clear(&bfa->ioc); | |
416 | } | |
417 | ||
7725ccfd JH |
418 | /** |
419 | * Fetch firmware trace data. | |
420 | * | |
421 | * @param[in] bfa BFA instance | |
422 | * @param[out] trcdata Firmware trace buffer | |
423 | * @param[in,out] trclen Firmware trace buffer len | |
424 | * | |
425 | * @retval BFA_STATUS_OK Firmware trace is fetched. | |
426 | * @retval BFA_STATUS_INPROGRESS Firmware trace fetch is in progress. | |
427 | */ | |
428 | bfa_status_t | |
429 | bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen) | |
430 | { | |
431 | return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen); | |
432 | } | |
0a20de44 KG |
433 | |
434 | /** | |
435 | * Reset hw semaphore & usage cnt regs and initialize. | |
436 | */ | |
437 | void | |
438 | bfa_chip_reset(struct bfa_s *bfa) | |
439 | { | |
440 | bfa_ioc_ownership_reset(&bfa->ioc); | |
441 | bfa_ioc_pll_init(&bfa->ioc); | |
442 | } | |
7725ccfd | 443 | #endif |