PageRenderTime 19ms CodeModel.GetById 4ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/scsi/bfa/bfa_port.c

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