upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / scsi / bfa / bfa_cee.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 #include <defs/bfa_defs_cee.h>
19 #include <cs/bfa_trc.h>
20 #include <cs/bfa_log.h>
21 #include <cs/bfa_debug.h>
22 #include <cee/bfa_cee.h>
23 #include <bfi/bfi_cee.h>
24 #include <bfi/bfi.h>
25 #include <bfa_ioc.h>
26 #include <cna/bfa_cna_trcmod.h>
27
28 BFA_TRC_FILE(CNA, CEE);
29
30 #define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
31 #define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
32
33 static void     bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
34 static void     bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
35                                            *dcbcx_stats);
36 static void     bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
37                                           *lldp_stats);
38 static void     bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
39 static void     bfa_cee_format_cee_cfg(void *buffer);
40 static void     bfa_cee_format_cee_stats(void *buffer);
41
42 static void
43 bfa_cee_format_cee_stats(void *buffer)
44 {
45         struct bfa_cee_stats_s *cee_stats = buffer;
46         bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats);
47         bfa_cee_format_lldp_stats(&cee_stats->lldp_stats);
48         bfa_cee_format_cfg_stats(&cee_stats->cfg_stats);
49 }
50
51 static void
52 bfa_cee_format_cee_cfg(void *buffer)
53 {
54         struct bfa_cee_attr_s *cee_cfg = buffer;
55         bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
56 }
57
58 static void
59 bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats)
60 {
61         dcbcx_stats->subtlvs_unrecognized =
62                 bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized);
63         dcbcx_stats->negotiation_failed =
64                 bfa_os_ntohl(dcbcx_stats->negotiation_failed);
65         dcbcx_stats->remote_cfg_changed =
66                 bfa_os_ntohl(dcbcx_stats->remote_cfg_changed);
67         dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received);
68         dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid);
69         dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno);
70         dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno);
71         dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno);
72         dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno);
73 }
74
75 static void
76 bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats)
77 {
78         lldp_stats->frames_transmitted =
79                 bfa_os_ntohl(lldp_stats->frames_transmitted);
80         lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out);
81         lldp_stats->frames_discarded =
82                 bfa_os_ntohl(lldp_stats->frames_discarded);
83         lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error);
84         lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd);
85         lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded);
86         lldp_stats->tlvs_unrecognized =
87                 bfa_os_ntohl(lldp_stats->tlvs_unrecognized);
88 }
89
90 static void
91 bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats)
92 {
93         cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down);
94         cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up);
95         cfg_stats->cee_hw_cfg_changed =
96                 bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed);
97         cfg_stats->recvd_invalid_cfg =
98                 bfa_os_ntohl(cfg_stats->recvd_invalid_cfg);
99 }
100
101 static void
102 bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg)
103 {
104         lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval);
105         lldp_cfg->enabled_system_cap =
106                 bfa_os_ntohs(lldp_cfg->enabled_system_cap);
107 }
108
109 /**
110  * bfa_cee_attr_meminfo()
111  *
112  *
113  * @param[in] void
114  *
115  * @return Size of DMA region
116  */
117 static          u32
118 bfa_cee_attr_meminfo(void)
119 {
120         return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
121 }
122
123 /**
124  * bfa_cee_stats_meminfo()
125  *
126  *
127  * @param[in] void
128  *
129  * @return Size of DMA region
130  */
131 static          u32
132 bfa_cee_stats_meminfo(void)
133 {
134         return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
135 }
136
137 /**
138  * bfa_cee_get_attr_isr()
139  *
140  *
141  * @param[in] cee - Pointer to the CEE module
142  *            status - Return status from the f/w
143  *
144  * @return void
145  */
146 static void
147 bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
148 {
149         cee->get_attr_status = status;
150         bfa_trc(cee, 0);
151         if (status == BFA_STATUS_OK) {
152                 bfa_trc(cee, 0);
153                 /*
154                  * The requested data has been copied to the DMA area, *process
155                  * it.
156                  */
157                 memcpy(cee->attr, cee->attr_dma.kva,
158                        sizeof(struct bfa_cee_attr_s));
159                 bfa_cee_format_cee_cfg(cee->attr);
160         }
161         cee->get_attr_pending = BFA_FALSE;
162         if (cee->cbfn.get_attr_cbfn) {
163                 bfa_trc(cee, 0);
164                 cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
165         }
166         bfa_trc(cee, 0);
167 }
168
169 /**
170  * bfa_cee_get_attr_isr()
171  *
172  *
173  * @param[in] cee - Pointer to the CEE module
174  *            status - Return status from the f/w
175  *
176  * @return void
177  */
178 static void
179 bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
180 {
181         cee->get_stats_status = status;
182         bfa_trc(cee, 0);
183         if (status == BFA_STATUS_OK) {
184                 bfa_trc(cee, 0);
185                 /*
186                  * The requested data has been copied to the DMA area, process
187                  * it.
188                  */
189                 memcpy(cee->stats, cee->stats_dma.kva,
190                        sizeof(struct bfa_cee_stats_s));
191                 bfa_cee_format_cee_stats(cee->stats);
192         }
193         cee->get_stats_pending = BFA_FALSE;
194         bfa_trc(cee, 0);
195         if (cee->cbfn.get_stats_cbfn) {
196                 bfa_trc(cee, 0);
197                 cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
198         }
199         bfa_trc(cee, 0);
200 }
201
202 /**
203  * bfa_cee_get_attr_isr()
204  *
205  *
206  * @param[in] cee - Pointer to the CEE module
207  *            status - Return status from the f/w
208  *
209  * @return void
210  */
211 static void
212 bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
213 {
214         cee->reset_stats_status = status;
215         cee->reset_stats_pending = BFA_FALSE;
216         if (cee->cbfn.reset_stats_cbfn)
217                 cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
218 }
219
220 /**
221  * bfa_cee_meminfo()
222  *
223  *
224  * @param[in] void
225  *
226  * @return Size of DMA region
227  */
228 u32
229 bfa_cee_meminfo(void)
230 {
231         return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
232 }
233
234 /**
235  * bfa_cee_mem_claim()
236  *
237  *
238  * @param[in] cee CEE module pointer
239  *            dma_kva Kernel Virtual Address of CEE DMA Memory
240  *            dma_pa  Physical Address of CEE DMA Memory
241  *
242  * @return void
243  */
244 void
245 bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
246 {
247         cee->attr_dma.kva = dma_kva;
248         cee->attr_dma.pa = dma_pa;
249         cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
250         cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
251         cee->attr = (struct bfa_cee_attr_s *)dma_kva;
252         cee->stats =
253                 (struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo());
254 }
255
256 /**
257  * bfa_cee_get_attr()
258  *
259  *   Send the request to the f/w to fetch CEE attributes.
260  *
261  * @param[in] Pointer to the CEE module data structure.
262  *
263  * @return Status
264  */
265
266 bfa_status_t
267 bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
268                  bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
269 {
270         struct bfi_cee_get_req_s *cmd;
271
272         bfa_assert((cee != NULL) && (cee->ioc != NULL));
273         bfa_trc(cee, 0);
274         if (!bfa_ioc_is_operational(cee->ioc)) {
275                 bfa_trc(cee, 0);
276                 return BFA_STATUS_IOC_FAILURE;
277         }
278         if (cee->get_attr_pending == BFA_TRUE) {
279                 bfa_trc(cee, 0);
280                 return BFA_STATUS_DEVBUSY;
281         }
282         cee->get_attr_pending = BFA_TRUE;
283         cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg;
284         cee->attr = attr;
285         cee->cbfn.get_attr_cbfn = cbfn;
286         cee->cbfn.get_attr_cbarg = cbarg;
287         bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
288                     bfa_ioc_portid(cee->ioc));
289         bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
290         bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
291         bfa_trc(cee, 0);
292
293         return BFA_STATUS_OK;
294 }
295
296 /**
297  * bfa_cee_get_stats()
298  *
299  *   Send the request to the f/w to fetch CEE statistics.
300  *
301  * @param[in] Pointer to the CEE module data structure.
302  *
303  * @return Status
304  */
305
306 bfa_status_t
307 bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
308                   bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
309 {
310         struct bfi_cee_get_req_s *cmd;
311
312         bfa_assert((cee != NULL) && (cee->ioc != NULL));
313
314         if (!bfa_ioc_is_operational(cee->ioc)) {
315                 bfa_trc(cee, 0);
316                 return BFA_STATUS_IOC_FAILURE;
317         }
318         if (cee->get_stats_pending == BFA_TRUE) {
319                 bfa_trc(cee, 0);
320                 return BFA_STATUS_DEVBUSY;
321         }
322         cee->get_stats_pending = BFA_TRUE;
323         cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg;
324         cee->stats = stats;
325         cee->cbfn.get_stats_cbfn = cbfn;
326         cee->cbfn.get_stats_cbarg = cbarg;
327         bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
328                     bfa_ioc_portid(cee->ioc));
329         bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
330         bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
331         bfa_trc(cee, 0);
332
333         return BFA_STATUS_OK;
334 }
335
336 /**
337  * bfa_cee_reset_stats()
338  *
339  *
340  * @param[in] Pointer to the CEE module data structure.
341  *
342  * @return Status
343  */
344
345 bfa_status_t
346 bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn,
347                     void *cbarg)
348 {
349         struct bfi_cee_reset_stats_s *cmd;
350
351         bfa_assert((cee != NULL) && (cee->ioc != NULL));
352         if (!bfa_ioc_is_operational(cee->ioc)) {
353                 bfa_trc(cee, 0);
354                 return BFA_STATUS_IOC_FAILURE;
355         }
356         if (cee->reset_stats_pending == BFA_TRUE) {
357                 bfa_trc(cee, 0);
358                 return BFA_STATUS_DEVBUSY;
359         }
360         cee->reset_stats_pending = BFA_TRUE;
361         cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg;
362         cee->cbfn.reset_stats_cbfn = cbfn;
363         cee->cbfn.reset_stats_cbarg = cbarg;
364         bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
365                     bfa_ioc_portid(cee->ioc));
366         bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
367         bfa_trc(cee, 0);
368         return BFA_STATUS_OK;
369 }
370
371 /**
372  * bfa_cee_isrs()
373  *
374  *
375  * @param[in] Pointer to the CEE module data structure.
376  *
377  * @return void
378  */
379
380 void
381 bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
382 {
383         union bfi_cee_i2h_msg_u *msg;
384         struct bfi_cee_get_rsp_s *get_rsp;
385         struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg;
386         msg = (union bfi_cee_i2h_msg_u *)m;
387         get_rsp = (struct bfi_cee_get_rsp_s *)m;
388         bfa_trc(cee, msg->mh.msg_id);
389         switch (msg->mh.msg_id) {
390         case BFI_CEE_I2H_GET_CFG_RSP:
391                 bfa_trc(cee, get_rsp->cmd_status);
392                 bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
393                 break;
394         case BFI_CEE_I2H_GET_STATS_RSP:
395                 bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
396                 break;
397         case BFI_CEE_I2H_RESET_STATS_RSP:
398                 bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
399                 break;
400         default:
401                 bfa_assert(0);
402         }
403 }
404
405 /**
406  * bfa_cee_hbfail()
407  *
408  *
409  * @param[in] Pointer to the CEE module data structure.
410  *
411  * @return void
412  */
413
414 void
415 bfa_cee_hbfail(void *arg)
416 {
417         struct bfa_cee_s *cee;
418         cee = (struct bfa_cee_s *)arg;
419
420         if (cee->get_attr_pending == BFA_TRUE) {
421                 cee->get_attr_status = BFA_STATUS_FAILED;
422                 cee->get_attr_pending = BFA_FALSE;
423                 if (cee->cbfn.get_attr_cbfn) {
424                         cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
425                                                 BFA_STATUS_FAILED);
426                 }
427         }
428         if (cee->get_stats_pending == BFA_TRUE) {
429                 cee->get_stats_status = BFA_STATUS_FAILED;
430                 cee->get_stats_pending = BFA_FALSE;
431                 if (cee->cbfn.get_stats_cbfn) {
432                         cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
433                                                  BFA_STATUS_FAILED);
434                 }
435         }
436         if (cee->reset_stats_pending == BFA_TRUE) {
437                 cee->reset_stats_status = BFA_STATUS_FAILED;
438                 cee->reset_stats_pending = BFA_FALSE;
439                 if (cee->cbfn.reset_stats_cbfn) {
440                         cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
441                                                    BFA_STATUS_FAILED);
442                 }
443         }
444 }
445
446 /**
447  * bfa_cee_attach()
448  *
449  *
450  * @param[in] cee - Pointer to the CEE module data structure
451  *            ioc - Pointer to the ioc module data structure
452  *            dev - Pointer to the device driver module data structure
453  *                  The device driver specific mbox ISR functions have
454  *                  this pointer as one of the parameters.
455  *            trcmod -
456  *            logmod -
457  *
458  * @return void
459  */
460 void
461 bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
462                struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
463 {
464         bfa_assert(cee != NULL);
465         cee->dev = dev;
466         cee->trcmod = trcmod;
467         cee->logmod = logmod;
468         cee->ioc = ioc;
469
470         bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
471         bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
472         bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail);
473         bfa_trc(cee, 0);
474 }
475
476 /**
477  * bfa_cee_detach()
478  *
479  *
480  * @param[in] cee - Pointer to the CEE module data structure
481  *
482  * @return void
483  */
484 void
485 bfa_cee_detach(struct bfa_cee_s *cee)
486 {
487         /*
488          * For now, just check if there is some ioctl pending and mark that as
489          * failed?
490          */
491         /* bfa_cee_hbfail(cee); */
492 }