• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/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#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
28BFA_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
33static void     bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
34static void     bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
35					   *dcbcx_stats);
36static void     bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
37					  *lldp_stats);
38static void     bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
39static void     bfa_cee_format_cee_cfg(void *buffer);
40static void     bfa_cee_format_cee_stats(void *buffer);
41
42static void
43bfa_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
51static void
52bfa_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
58static void
59bfa_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
75static void
76bfa_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
90static void
91bfa_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
101static void
102bfa_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 */
117static          u32
118bfa_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 */
131static          u32
132bfa_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 */
146static void
147bfa_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 */
178static void
179bfa_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 */
211static void
212bfa_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 */
228u32
229bfa_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 */
244void
245bfa_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
266bfa_status_t
267bfa_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
306bfa_status_t
307bfa_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
345bfa_status_t
346bfa_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
380void
381bfa_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
414void
415bfa_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 */
460void
461bfa_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 */
484void
485bfa_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}
493