]>
Commit | Line | Data |
---|---|---|
7725ccfd | 1 | /* |
a36c61f9 | 2 | * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. |
7725ccfd JH |
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 | ||
a36c61f9 KG |
18 | #include "bfa_defs_svc.h" |
19 | #include "bfa_port.h" | |
20 | #include "bfi.h" | |
21 | #include "bfa_ioc.h" | |
22 | ||
7725ccfd JH |
23 | |
24 | BFA_TRC_FILE(CNA, PORT); | |
25 | ||
26 | #define bfa_ioc_portid(__ioc) ((__ioc)->port_id) | |
7725ccfd JH |
27 | |
28 | static void | |
a36c61f9 | 29 | bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats) |
7725ccfd | 30 | { |
a36c61f9 KG |
31 | u32 *dip = (u32 *) stats; |
32 | u32 t0, t1; | |
33 | int i; | |
7725ccfd | 34 | |
a36c61f9 KG |
35 | for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32); |
36 | i += 2) { | |
7725ccfd JH |
37 | t0 = dip[i]; |
38 | t1 = dip[i + 1]; | |
39 | #ifdef __BIGENDIAN | |
ba816ea8 JH |
40 | dip[i] = be32_to_cpu(t0); |
41 | dip[i + 1] = be32_to_cpu(t1); | |
7725ccfd | 42 | #else |
ba816ea8 JH |
43 | dip[i] = be32_to_cpu(t1); |
44 | dip[i + 1] = be32_to_cpu(t0); | |
7725ccfd JH |
45 | #endif |
46 | } | |
7725ccfd JH |
47 | } |
48 | ||
5fbe25c7 | 49 | /* |
7725ccfd JH |
50 | * bfa_port_enable_isr() |
51 | * | |
52 | * | |
53 | * @param[in] port - Pointer to the port module | |
54 | * status - Return status from the f/w | |
55 | * | |
56 | * @return void | |
57 | */ | |
58 | static void | |
59 | bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status) | |
60 | { | |
a36c61f9 KG |
61 | bfa_trc(port, status); |
62 | port->endis_pending = BFA_FALSE; | |
63 | port->endis_cbfn(port->endis_cbarg, status); | |
7725ccfd JH |
64 | } |
65 | ||
5fbe25c7 | 66 | /* |
7725ccfd JH |
67 | * bfa_port_disable_isr() |
68 | * | |
69 | * | |
70 | * @param[in] port - Pointer to the port module | |
71 | * status - Return status from the f/w | |
72 | * | |
73 | * @return void | |
74 | */ | |
75 | static void | |
76 | bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status) | |
77 | { | |
a36c61f9 KG |
78 | bfa_trc(port, status); |
79 | port->endis_pending = BFA_FALSE; | |
80 | port->endis_cbfn(port->endis_cbarg, status); | |
7725ccfd JH |
81 | } |
82 | ||
5fbe25c7 | 83 | /* |
7725ccfd JH |
84 | * bfa_port_get_stats_isr() |
85 | * | |
86 | * | |
87 | * @param[in] port - Pointer to the Port module | |
88 | * status - Return status from the f/w | |
89 | * | |
90 | * @return void | |
91 | */ | |
92 | static void | |
93 | bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status) | |
94 | { | |
95 | port->stats_status = status; | |
96 | port->stats_busy = BFA_FALSE; | |
97 | ||
98 | if (status == BFA_STATUS_OK) { | |
b85d045e JH |
99 | struct bfa_timeval_s tv; |
100 | ||
7725ccfd | 101 | memcpy(port->stats, port->stats_dma.kva, |
a36c61f9 | 102 | sizeof(union bfa_port_stats_u)); |
7725ccfd | 103 | bfa_port_stats_swap(port, port->stats); |
b85d045e JH |
104 | |
105 | bfa_os_gettimeofday(&tv); | |
106 | port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time; | |
7725ccfd JH |
107 | } |
108 | ||
109 | if (port->stats_cbfn) { | |
110 | port->stats_cbfn(port->stats_cbarg, status); | |
111 | port->stats_cbfn = NULL; | |
112 | } | |
113 | } | |
114 | ||
5fbe25c7 | 115 | /* |
7725ccfd JH |
116 | * bfa_port_clear_stats_isr() |
117 | * | |
118 | * | |
119 | * @param[in] port - Pointer to the Port module | |
120 | * status - Return status from the f/w | |
121 | * | |
122 | * @return void | |
123 | */ | |
124 | static void | |
125 | bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status) | |
126 | { | |
b85d045e JH |
127 | struct bfa_timeval_s tv; |
128 | ||
7725ccfd | 129 | port->stats_status = status; |
a36c61f9 | 130 | port->stats_busy = BFA_FALSE; |
7725ccfd | 131 | |
5fbe25c7 | 132 | /* |
a36c61f9 KG |
133 | * re-initialize time stamp for stats reset |
134 | */ | |
b85d045e JH |
135 | bfa_os_gettimeofday(&tv); |
136 | port->stats_reset_time = tv.tv_sec; | |
137 | ||
7725ccfd JH |
138 | if (port->stats_cbfn) { |
139 | port->stats_cbfn(port->stats_cbarg, status); | |
140 | port->stats_cbfn = NULL; | |
141 | } | |
142 | } | |
143 | ||
5fbe25c7 | 144 | /* |
7725ccfd JH |
145 | * bfa_port_isr() |
146 | * | |
147 | * | |
148 | * @param[in] Pointer to the Port module data structure. | |
149 | * | |
150 | * @return void | |
151 | */ | |
152 | static void | |
153 | bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m) | |
154 | { | |
a36c61f9 | 155 | struct bfa_port_s *port = (struct bfa_port_s *) cbarg; |
7725ccfd JH |
156 | union bfi_port_i2h_msg_u *i2hmsg; |
157 | ||
a36c61f9 | 158 | i2hmsg = (union bfi_port_i2h_msg_u *) m; |
7725ccfd JH |
159 | bfa_trc(port, m->mh.msg_id); |
160 | ||
161 | switch (m->mh.msg_id) { | |
162 | case BFI_PORT_I2H_ENABLE_RSP: | |
163 | if (port->endis_pending == BFA_FALSE) | |
164 | break; | |
165 | bfa_port_enable_isr(port, i2hmsg->enable_rsp.status); | |
166 | break; | |
167 | ||
168 | case BFI_PORT_I2H_DISABLE_RSP: | |
169 | if (port->endis_pending == BFA_FALSE) | |
170 | break; | |
171 | bfa_port_disable_isr(port, i2hmsg->disable_rsp.status); | |
172 | break; | |
173 | ||
174 | case BFI_PORT_I2H_GET_STATS_RSP: | |
a36c61f9 | 175 | /* Stats busy flag is still set? (may be cmd timed out) */ |
7725ccfd JH |
176 | if (port->stats_busy == BFA_FALSE) |
177 | break; | |
178 | bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status); | |
179 | break; | |
180 | ||
181 | case BFI_PORT_I2H_CLEAR_STATS_RSP: | |
182 | if (port->stats_busy == BFA_FALSE) | |
183 | break; | |
184 | bfa_port_clear_stats_isr(port, i2hmsg->clearstats_rsp.status); | |
185 | break; | |
186 | ||
187 | default: | |
188 | bfa_assert(0); | |
189 | } | |
190 | } | |
191 | ||
5fbe25c7 | 192 | /* |
7725ccfd JH |
193 | * bfa_port_meminfo() |
194 | * | |
195 | * | |
196 | * @param[in] void | |
197 | * | |
198 | * @return Size of DMA region | |
199 | */ | |
200 | u32 | |
201 | bfa_port_meminfo(void) | |
202 | { | |
a36c61f9 | 203 | return BFA_ROUNDUP(sizeof(union bfa_port_stats_u), BFA_DMA_ALIGN_SZ); |
7725ccfd JH |
204 | } |
205 | ||
5fbe25c7 | 206 | /* |
7725ccfd JH |
207 | * bfa_port_mem_claim() |
208 | * | |
209 | * | |
210 | * @param[in] port Port module pointer | |
a36c61f9 KG |
211 | * dma_kva Kernel Virtual Address of Port DMA Memory |
212 | * dma_pa Physical Address of Port DMA Memory | |
7725ccfd JH |
213 | * |
214 | * @return void | |
215 | */ | |
216 | void | |
217 | bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa) | |
218 | { | |
219 | port->stats_dma.kva = dma_kva; | |
a36c61f9 | 220 | port->stats_dma.pa = dma_pa; |
7725ccfd JH |
221 | } |
222 | ||
5fbe25c7 | 223 | /* |
7725ccfd JH |
224 | * bfa_port_enable() |
225 | * | |
226 | * Send the Port enable request to the f/w | |
227 | * | |
228 | * @param[in] Pointer to the Port module data structure. | |
229 | * | |
230 | * @return Status | |
231 | */ | |
232 | bfa_status_t | |
233 | bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn, | |
a36c61f9 | 234 | void *cbarg) |
7725ccfd JH |
235 | { |
236 | struct bfi_port_generic_req_s *m; | |
237 | ||
a36c61f9 KG |
238 | if (bfa_ioc_is_disabled(port->ioc)) { |
239 | bfa_trc(port, BFA_STATUS_IOC_DISABLED); | |
240 | return BFA_STATUS_IOC_DISABLED; | |
241 | } | |
7725ccfd JH |
242 | |
243 | if (!bfa_ioc_is_operational(port->ioc)) { | |
244 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | |
245 | return BFA_STATUS_IOC_FAILURE; | |
246 | } | |
247 | ||
248 | if (port->endis_pending) { | |
249 | bfa_trc(port, BFA_STATUS_DEVBUSY); | |
250 | return BFA_STATUS_DEVBUSY; | |
251 | } | |
252 | ||
a36c61f9 | 253 | m = (struct bfi_port_generic_req_s *) port->endis_mb.msg; |
7725ccfd JH |
254 | |
255 | port->msgtag++; | |
a36c61f9 KG |
256 | port->endis_cbfn = cbfn; |
257 | port->endis_cbarg = cbarg; | |
7725ccfd JH |
258 | port->endis_pending = BFA_TRUE; |
259 | ||
260 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ, | |
261 | bfa_ioc_portid(port->ioc)); | |
262 | bfa_ioc_mbox_queue(port->ioc, &port->endis_mb); | |
263 | ||
264 | return BFA_STATUS_OK; | |
265 | } | |
266 | ||
5fbe25c7 | 267 | /* |
7725ccfd JH |
268 | * bfa_port_disable() |
269 | * | |
270 | * Send the Port disable request to the f/w | |
271 | * | |
272 | * @param[in] Pointer to the Port module data structure. | |
273 | * | |
274 | * @return Status | |
275 | */ | |
276 | bfa_status_t | |
277 | bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn, | |
a36c61f9 | 278 | void *cbarg) |
7725ccfd JH |
279 | { |
280 | struct bfi_port_generic_req_s *m; | |
281 | ||
a36c61f9 KG |
282 | if (bfa_ioc_is_disabled(port->ioc)) { |
283 | bfa_trc(port, BFA_STATUS_IOC_DISABLED); | |
284 | return BFA_STATUS_IOC_DISABLED; | |
285 | } | |
7725ccfd JH |
286 | |
287 | if (!bfa_ioc_is_operational(port->ioc)) { | |
288 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | |
289 | return BFA_STATUS_IOC_FAILURE; | |
290 | } | |
291 | ||
292 | if (port->endis_pending) { | |
293 | bfa_trc(port, BFA_STATUS_DEVBUSY); | |
294 | return BFA_STATUS_DEVBUSY; | |
295 | } | |
296 | ||
a36c61f9 | 297 | m = (struct bfi_port_generic_req_s *) port->endis_mb.msg; |
7725ccfd JH |
298 | |
299 | port->msgtag++; | |
a36c61f9 KG |
300 | port->endis_cbfn = cbfn; |
301 | port->endis_cbarg = cbarg; | |
7725ccfd JH |
302 | port->endis_pending = BFA_TRUE; |
303 | ||
304 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ, | |
305 | bfa_ioc_portid(port->ioc)); | |
306 | bfa_ioc_mbox_queue(port->ioc, &port->endis_mb); | |
307 | ||
308 | return BFA_STATUS_OK; | |
309 | } | |
310 | ||
5fbe25c7 | 311 | /* |
7725ccfd JH |
312 | * bfa_port_get_stats() |
313 | * | |
314 | * Send the request to the f/w to fetch Port statistics. | |
315 | * | |
316 | * @param[in] Pointer to the Port module data structure. | |
317 | * | |
318 | * @return Status | |
319 | */ | |
320 | bfa_status_t | |
a36c61f9 KG |
321 | bfa_port_get_stats(struct bfa_port_s *port, union bfa_port_stats_u *stats, |
322 | bfa_port_stats_cbfn_t cbfn, void *cbarg) | |
7725ccfd JH |
323 | { |
324 | struct bfi_port_get_stats_req_s *m; | |
325 | ||
326 | if (!bfa_ioc_is_operational(port->ioc)) { | |
327 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | |
328 | return BFA_STATUS_IOC_FAILURE; | |
329 | } | |
330 | ||
331 | if (port->stats_busy) { | |
332 | bfa_trc(port, BFA_STATUS_DEVBUSY); | |
333 | return BFA_STATUS_DEVBUSY; | |
334 | } | |
335 | ||
a36c61f9 | 336 | m = (struct bfi_port_get_stats_req_s *) port->stats_mb.msg; |
7725ccfd | 337 | |
a36c61f9 KG |
338 | port->stats = stats; |
339 | port->stats_cbfn = cbfn; | |
7725ccfd | 340 | port->stats_cbarg = cbarg; |
a36c61f9 | 341 | port->stats_busy = BFA_TRUE; |
7725ccfd JH |
342 | bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa); |
343 | ||
344 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ, | |
345 | bfa_ioc_portid(port->ioc)); | |
346 | bfa_ioc_mbox_queue(port->ioc, &port->stats_mb); | |
347 | ||
348 | return BFA_STATUS_OK; | |
349 | } | |
350 | ||
5fbe25c7 | 351 | /* |
7725ccfd JH |
352 | * bfa_port_clear_stats() |
353 | * | |
354 | * | |
355 | * @param[in] Pointer to the Port module data structure. | |
356 | * | |
357 | * @return Status | |
358 | */ | |
359 | bfa_status_t | |
360 | bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn, | |
a36c61f9 | 361 | void *cbarg) |
7725ccfd JH |
362 | { |
363 | struct bfi_port_generic_req_s *m; | |
364 | ||
365 | if (!bfa_ioc_is_operational(port->ioc)) { | |
366 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | |
367 | return BFA_STATUS_IOC_FAILURE; | |
368 | } | |
369 | ||
370 | if (port->stats_busy) { | |
371 | bfa_trc(port, BFA_STATUS_DEVBUSY); | |
372 | return BFA_STATUS_DEVBUSY; | |
373 | } | |
374 | ||
a36c61f9 | 375 | m = (struct bfi_port_generic_req_s *) port->stats_mb.msg; |
7725ccfd | 376 | |
a36c61f9 | 377 | port->stats_cbfn = cbfn; |
7725ccfd | 378 | port->stats_cbarg = cbarg; |
a36c61f9 | 379 | port->stats_busy = BFA_TRUE; |
7725ccfd JH |
380 | |
381 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ, | |
382 | bfa_ioc_portid(port->ioc)); | |
383 | bfa_ioc_mbox_queue(port->ioc, &port->stats_mb); | |
384 | ||
385 | return BFA_STATUS_OK; | |
386 | } | |
387 | ||
5fbe25c7 | 388 | /* |
7725ccfd JH |
389 | * bfa_port_hbfail() |
390 | * | |
391 | * | |
392 | * @param[in] Pointer to the Port module data structure. | |
393 | * | |
394 | * @return void | |
395 | */ | |
396 | void | |
397 | bfa_port_hbfail(void *arg) | |
398 | { | |
a36c61f9 | 399 | struct bfa_port_s *port = (struct bfa_port_s *) arg; |
7725ccfd | 400 | |
a36c61f9 | 401 | /* Fail any pending get_stats/clear_stats requests */ |
7725ccfd JH |
402 | if (port->stats_busy) { |
403 | if (port->stats_cbfn) | |
8a4adf1c | 404 | port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED); |
7725ccfd JH |
405 | port->stats_cbfn = NULL; |
406 | port->stats_busy = BFA_FALSE; | |
407 | } | |
408 | ||
a36c61f9 | 409 | /* Clear any enable/disable is pending */ |
7725ccfd JH |
410 | if (port->endis_pending) { |
411 | if (port->endis_cbfn) | |
8a4adf1c | 412 | port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED); |
7725ccfd JH |
413 | port->endis_cbfn = NULL; |
414 | port->endis_pending = BFA_FALSE; | |
415 | } | |
416 | } | |
417 | ||
5fbe25c7 | 418 | /* |
7725ccfd JH |
419 | * bfa_port_attach() |
420 | * | |
421 | * | |
422 | * @param[in] port - Pointer to the Port module data structure | |
423 | * ioc - Pointer to the ioc module data structure | |
424 | * dev - Pointer to the device driver module data structure | |
425 | * The device driver specific mbox ISR functions have | |
426 | * this pointer as one of the parameters. | |
427 | * trcmod - | |
7725ccfd JH |
428 | * |
429 | * @return void | |
430 | */ | |
431 | void | |
a36c61f9 KG |
432 | bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, |
433 | void *dev, struct bfa_trc_mod_s *trcmod) | |
7725ccfd | 434 | { |
b85d045e JH |
435 | struct bfa_timeval_s tv; |
436 | ||
7725ccfd JH |
437 | bfa_assert(port); |
438 | ||
a36c61f9 KG |
439 | port->dev = dev; |
440 | port->ioc = ioc; | |
7725ccfd | 441 | port->trcmod = trcmod; |
7725ccfd | 442 | |
b85d045e JH |
443 | port->stats_busy = BFA_FALSE; |
444 | port->endis_pending = BFA_FALSE; | |
445 | port->stats_cbfn = NULL; | |
446 | port->endis_cbfn = NULL; | |
7725ccfd JH |
447 | |
448 | bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port); | |
449 | bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port); | |
450 | bfa_ioc_hbfail_register(port->ioc, &port->hbfail); | |
451 | ||
5fbe25c7 | 452 | /* |
b85d045e JH |
453 | * initialize time stamp for stats reset |
454 | */ | |
455 | bfa_os_gettimeofday(&tv); | |
456 | port->stats_reset_time = tv.tv_sec; | |
457 | ||
7725ccfd JH |
458 | bfa_trc(port, 0); |
459 | } | |
460 | ||
5fbe25c7 | 461 | /* |
7725ccfd JH |
462 | * bfa_port_detach() |
463 | * | |
464 | * | |
465 | * @param[in] port - Pointer to the Port module data structure | |
466 | * | |
467 | * @return void | |
468 | */ | |
469 | void | |
470 | bfa_port_detach(struct bfa_port_s *port) | |
471 | { | |
472 | bfa_trc(port, 0); | |
473 | } |