summaryrefslogblamecommitdiff
path: root/drivers/scsi/bfa/bfad_bsg.c
blob: 26def664cb831dc35deae575001e17da70dd92f4 (plain) (tree)
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722























                                                                          

































                                                                  
                              













                                                        


















                                                                            
                                        














































                                                                            








































                                                                              































                                                                              

































































                                                                                



























                                                                              

































                                                                                










































































                                                                               






















                                                                                
























                                                                

































                                                                        


































                                                                 
                               




























































                                                                                
















































                                                                 






































                                                                       

















































































































































                                                                                









































                                                                     
   



























































                                                                               





















                                                                                





















                                                                          















                                                                       


















                                                                                






























                                                                         




























                                                                               





















































                                                                       



































































































































































                                                                              


































































                                                                            






















































































                                                                                










































                                                                              








































































































                                                                                


















































































































































































                                                                                










































































                                                                               


















                                                                         




























                                                                               


















                                                                                


































































                                                                                













































                                                                                



                                                                      
                         

                      





                                                         





                                                          





                                                                          







                                                                  











                                                            


                                                           


                                                                         















                                                                


                                                            


                                                             


                                                               








                                                                           


                                                            


                                                             














                                                             


                                                                            









                                                                


                                                                


                                                                


                                                                     


                                                            


                                                               


                                                               








                                                                





















                                                               








                                                         








                                                                        





                                                       











                                                                            


























                                                               











                                                                     





                                                         











                                                                        






                                                                    
                
                             

                      
                  







































































































































































































































































































































































































































                                                                                

















                                                      











                                                              
/*
 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
 * All rights reserved
 * www.brocade.com
 *
 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License (GPL) Version 2 as
 * published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#include <linux/uaccess.h>
#include "bfad_drv.h"
#include "bfad_im.h"
#include "bfad_bsg.h"

BFA_TRC_FILE(LDRV, BSG);

int
bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	int	rc = 0;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	/* If IOC is not in disabled state - return */
	if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_IOC_FAILURE;
		return rc;
	}

	init_completion(&bfad->enable_comp);
	bfa_iocfc_enable(&bfad->bfa);
	iocmd->status = BFA_STATUS_OK;
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	wait_for_completion(&bfad->enable_comp);

	return rc;
}

int
bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	int	rc = 0;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	if (bfad->disable_active) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		return -EBUSY;
	}

	bfad->disable_active = BFA_TRUE;
	init_completion(&bfad->disable_comp);
	bfa_iocfc_disable(&bfad->bfa);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	wait_for_completion(&bfad->disable_comp);
	bfad->disable_active = BFA_FALSE;
	iocmd->status = BFA_STATUS_OK;

	return rc;
}

static int
bfad_iocmd_ioc_get_info(struct bfad_s *bfad, void *cmd)
{
	int	i;
	struct bfa_bsg_ioc_info_s *iocmd = (struct bfa_bsg_ioc_info_s *)cmd;
	struct bfad_im_port_s	*im_port;
	struct bfa_port_attr_s	pattr;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	bfa_fcport_get_attr(&bfad->bfa, &pattr);
	iocmd->nwwn = pattr.nwwn;
	iocmd->pwwn = pattr.pwwn;
	iocmd->ioc_type = bfa_get_type(&bfad->bfa);
	iocmd->mac = bfa_get_mac(&bfad->bfa);
	iocmd->factory_mac = bfa_get_mfg_mac(&bfad->bfa);
	bfa_get_adapter_serial_num(&bfad->bfa, iocmd->serialnum);
	iocmd->factorynwwn = pattr.factorynwwn;
	iocmd->factorypwwn = pattr.factorypwwn;
	iocmd->bfad_num = bfad->inst_no;
	im_port = bfad->pport.im_port;
	iocmd->host = im_port->shost->host_no;
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	strcpy(iocmd->name, bfad->adapter_name);
	strcpy(iocmd->port_name, bfad->port_name);
	strcpy(iocmd->hwpath, bfad->pci_name);

	/* set adapter hw path */
	strcpy(iocmd->adapter_hwpath, bfad->pci_name);
	i = strlen(iocmd->adapter_hwpath) - 1;
	while (iocmd->adapter_hwpath[i] != '.')
		i--;
	iocmd->adapter_hwpath[i] = '\0';
	iocmd->status = BFA_STATUS_OK;
	return 0;
}

static int
bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_ioc_attr_s *iocmd = (struct bfa_bsg_ioc_attr_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	bfa_ioc_get_attr(&bfad->bfa.ioc, &iocmd->ioc_attr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	/* fill in driver attr info */
	strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME);
	strncpy(iocmd->ioc_attr.driver_attr.driver_ver,
		BFAD_DRIVER_VERSION, BFA_VERSION_LEN);
	strcpy(iocmd->ioc_attr.driver_attr.fw_ver,
		iocmd->ioc_attr.adapter_attr.fw_ver);
	strcpy(iocmd->ioc_attr.driver_attr.bios_ver,
		iocmd->ioc_attr.adapter_attr.optrom_ver);

	/* copy chip rev info first otherwise it will be overwritten */
	memcpy(bfad->pci_attr.chip_rev, iocmd->ioc_attr.pci_attr.chip_rev,
		sizeof(bfad->pci_attr.chip_rev));
	memcpy(&iocmd->ioc_attr.pci_attr, &bfad->pci_attr,
		sizeof(struct bfa_ioc_pci_attr_s));

	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_ioc_get_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_ioc_stats_s *iocmd = (struct bfa_bsg_ioc_stats_s *)cmd;

	bfa_ioc_get_stats(&bfad->bfa, &iocmd->ioc_stats);
	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_ioc_get_fwstats(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_ioc_fwstats_s *iocmd =
			(struct bfa_bsg_ioc_fwstats_s *)cmd;
	void	*iocmd_bufptr;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_ioc_fwstats_s),
			sizeof(struct bfa_fw_stats_s)) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		goto out;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_ioc_fwstats_s);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ioc_fw_stats_get(&bfad->bfa.ioc, iocmd_bufptr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (iocmd->status != BFA_STATUS_OK) {
		bfa_trc(bfad, iocmd->status);
		goto out;
	}
out:
	bfa_trc(bfad, 0x6666);
	return 0;
}

int
bfad_iocmd_ioc_reset_stats(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	unsigned long	flags;

	if (v_cmd == IOCMD_IOC_RESET_STATS) {
		bfa_ioc_clear_stats(&bfad->bfa);
		iocmd->status = BFA_STATUS_OK;
	} else if (v_cmd == IOCMD_IOC_RESET_FWSTATS) {
		spin_lock_irqsave(&bfad->bfad_lock, flags);
		iocmd->status = bfa_ioc_fw_stats_clear(&bfad->bfa.ioc);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	}

	return 0;
}

int
bfad_iocmd_ioc_set_name(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
	struct bfa_bsg_ioc_name_s *iocmd = (struct bfa_bsg_ioc_name_s *) cmd;

	if (v_cmd == IOCMD_IOC_SET_ADAPTER_NAME)
		strcpy(bfad->adapter_name, iocmd->name);
	else if (v_cmd == IOCMD_IOC_SET_PORT_NAME)
		strcpy(bfad->port_name, iocmd->name);

	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_iocfc_attr_s *iocmd = (struct bfa_bsg_iocfc_attr_s *)cmd;

	iocmd->status = BFA_STATUS_OK;
	bfa_iocfc_get_attr(&bfad->bfa, &iocmd->iocfc_attr);

	return 0;
}

int
bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_iocfc_israttr_set(&bfad->bfa, &iocmd->attr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

int
bfad_iocmd_port_enable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_port_enable(&bfad->bfa.modules.port,
					bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK) {
		bfa_trc(bfad, iocmd->status);
		return 0;
	}
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
	return 0;
}

int
bfad_iocmd_port_disable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_port_disable(&bfad->bfa.modules.port,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (iocmd->status != BFA_STATUS_OK) {
		bfa_trc(bfad, iocmd->status);
		return 0;
	}
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
	return 0;
}

static int
bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_port_attr_s *iocmd = (struct bfa_bsg_port_attr_s *)cmd;
	struct bfa_lport_attr_s	port_attr;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	bfa_fcport_get_attr(&bfad->bfa, &iocmd->attr);
	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (iocmd->attr.topology != BFA_PORT_TOPOLOGY_NONE)
		iocmd->attr.pid = port_attr.pid;
	else
		iocmd->attr.pid = 0;

	iocmd->attr.port_type = port_attr.port_type;
	iocmd->attr.loopback = port_attr.loopback;
	iocmd->attr.authfail = port_attr.authfail;
	strncpy(iocmd->attr.port_symname.symname,
		port_attr.port_cfg.sym_name.symname,
		sizeof(port_attr.port_cfg.sym_name.symname));

	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_port_get_stats(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_port_stats_s *iocmd = (struct bfa_bsg_port_stats_s *)cmd;
	struct bfad_hal_comp fcomp;
	void	*iocmd_bufptr;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_port_stats_s),
			sizeof(union bfa_port_stats_u)) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_port_stats_s);

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_port_get_stats(&bfad->bfa.modules.port,
				iocmd_bufptr, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK) {
		bfa_trc(bfad, iocmd->status);
		goto out;
	}

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_port_reset_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_port_clear_stats(&bfad->bfa.modules.port,
					bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK) {
		bfa_trc(bfad, iocmd->status);
		return 0;
	}
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
	return 0;
}

int
bfad_iocmd_set_port_cfg(struct bfad_s *bfad, void *iocmd, unsigned int v_cmd)
{
	struct bfa_bsg_port_cfg_s *cmd = (struct bfa_bsg_port_cfg_s *)iocmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	if (v_cmd == IOCMD_PORT_CFG_TOPO)
		cmd->status = bfa_fcport_cfg_topology(&bfad->bfa, cmd->param);
	else if (v_cmd == IOCMD_PORT_CFG_SPEED)
		cmd->status = bfa_fcport_cfg_speed(&bfad->bfa, cmd->param);
	else if (v_cmd == IOCMD_PORT_CFG_ALPA)
		cmd->status = bfa_fcport_cfg_hardalpa(&bfad->bfa, cmd->param);
	else if (v_cmd == IOCMD_PORT_CLR_ALPA)
		cmd->status = bfa_fcport_clr_hardalpa(&bfad->bfa);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

int
bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_port_cfg_maxfrsize_s *iocmd =
				(struct bfa_bsg_port_cfg_maxfrsize_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcport_cfg_maxfrsize(&bfad->bfa, iocmd->maxfrsize);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

int
bfad_iocmd_port_cfg_bbsc(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	if (bfa_ioc_get_type(&bfad->bfa.ioc) == BFA_IOC_TYPE_FC) {
		if (v_cmd == IOCMD_PORT_BBSC_ENABLE)
			fcport->cfg.bb_scn_state = BFA_TRUE;
		else if (v_cmd == IOCMD_PORT_BBSC_DISABLE)
			fcport->cfg.bb_scn_state = BFA_FALSE;
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	iocmd->status = BFA_STATUS_OK;
	return 0;
}

static int
bfad_iocmd_lport_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_fcs_lport_s	*fcs_port;
	struct bfa_bsg_lport_attr_s *iocmd = (struct bfa_bsg_lport_attr_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	bfa_fcs_lport_get_attr(fcs_port, &iocmd->port_attr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_lport_get_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_bsg_lport_stats_s *iocmd =
			(struct bfa_bsg_lport_stats_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	bfa_fcs_lport_get_stats(fcs_port, &iocmd->port_stats);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_lport_reset_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_bsg_reset_stats_s *iocmd =
			(struct bfa_bsg_reset_stats_s *)cmd;
	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
	struct list_head *qe, *qen;
	struct bfa_itnim_s *itnim;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->vpwwn);
	if (fcs_port == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	bfa_fcs_lport_clear_stats(fcs_port);
	/* clear IO stats from all active itnims */
	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
		itnim = (struct bfa_itnim_s *) qe;
		if (itnim->rport->rport_info.lp_tag != fcs_port->lp_tag)
			continue;
		bfa_itnim_clear_stats(itnim);
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_lport_get_iostats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_bsg_lport_iostats_s *iocmd =
			(struct bfa_bsg_lport_iostats_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	bfa_fcpim_port_iostats(&bfad->bfa, &iocmd->iostats,
			fcs_port->lp_tag);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_lport_get_rports_s *iocmd =
			(struct bfa_bsg_lport_get_rports_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	unsigned long	flags;
	void	*iocmd_bufptr;

	if (iocmd->nrports == 0)
		return -EINVAL;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_lport_get_rports_s),
			sizeof(wwn_t) * iocmd->nrports) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd +
			sizeof(struct bfa_bsg_lport_get_rports_s);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		bfa_trc(bfad, 0);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	bfa_fcs_lport_get_rports(fcs_port, (wwn_t *)iocmd_bufptr,
				&iocmd->nrports);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_rport_attr_s *iocmd = (struct bfa_bsg_rport_attr_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_rport_s *fcs_rport;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
	if (fcs_rport == NULL) {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		goto out;
	}

	bfa_fcs_rport_get_attr(fcs_rport, &iocmd->attr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

static int
bfad_iocmd_rport_get_addr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_rport_scsi_addr_s *iocmd =
			(struct bfa_bsg_rport_scsi_addr_s *)cmd;
	struct bfa_fcs_lport_s	*fcs_port;
	struct bfa_fcs_itnim_s	*fcs_itnim;
	struct bfad_itnim_s	*drv_itnim;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	fcs_itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
	if (fcs_itnim == NULL) {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		goto out;
	}

	drv_itnim = fcs_itnim->itnim_drv;

	if (drv_itnim && drv_itnim->im_port)
		iocmd->host = drv_itnim->im_port->shost->host_no;
	else {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		goto out;
	}

	iocmd->target = drv_itnim->scsi_tgt_id;
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	iocmd->bus = 0;
	iocmd->lun = 0;
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_rport_stats_s *iocmd =
			(struct bfa_bsg_rport_stats_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_rport_s *fcs_rport;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
	if (fcs_rport == NULL) {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		goto out;
	}

	memcpy((void *)&iocmd->stats, (void *)&fcs_rport->stats,
		sizeof(struct bfa_rport_stats_s));
	memcpy((void *)&iocmd->stats.hal_stats,
	       (void *)&(bfa_fcs_rport_get_halrport(fcs_rport)->stats),
	       sizeof(struct bfa_rport_hal_stats_s));

	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_rport_clr_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_rport_reset_stats_s *iocmd =
				(struct bfa_bsg_rport_reset_stats_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_rport_s *fcs_rport;
	struct bfa_rport_s *rport;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
	if (fcs_rport == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		goto out;
	}

	memset((char *)&fcs_rport->stats, 0, sizeof(struct bfa_rport_stats_s));
	rport = bfa_fcs_rport_get_halrport(fcs_rport);
	memset(&rport->stats, 0, sizeof(rport->stats));
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_rport_set_speed(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_rport_set_speed_s *iocmd =
				(struct bfa_bsg_rport_set_speed_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_rport_s *fcs_rport;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (fcs_port == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		goto out;
	}

	fcs_rport = bfa_fcs_rport_lookup(fcs_port, iocmd->rpwwn);
	if (fcs_rport == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		goto out;
	}

	fcs_rport->rpf.assigned_speed  = iocmd->speed;
	/* Set this speed in f/w only if the RPSC speed is not available */
	if (fcs_rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
		bfa_rport_speed(fcs_rport->bfa_rport, iocmd->speed);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_vport_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_fcs_vport_s *fcs_vport;
	struct bfa_bsg_vport_attr_s *iocmd = (struct bfa_bsg_vport_attr_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->vpwwn);
	if (fcs_vport == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_VWWN;
		goto out;
	}

	bfa_fcs_vport_get_attr(fcs_vport, &iocmd->vport_attr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_vport_get_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_fcs_vport_s *fcs_vport;
	struct bfa_bsg_vport_stats_s *iocmd =
				(struct bfa_bsg_vport_stats_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->vpwwn);
	if (fcs_vport == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_VWWN;
		goto out;
	}

	memcpy((void *)&iocmd->vport_stats, (void *)&fcs_vport->vport_stats,
		sizeof(struct bfa_vport_stats_s));
	memcpy((void *)&iocmd->vport_stats.port_stats,
	       (void *)&fcs_vport->lport.stats,
		sizeof(struct bfa_lport_stats_s));
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_vport_clr_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_fcs_vport_s *fcs_vport;
	struct bfa_bsg_reset_stats_s *iocmd =
				(struct bfa_bsg_reset_stats_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->vpwwn);
	if (fcs_vport == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_VWWN;
		goto out;
	}

	memset(&fcs_vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
	memset(&fcs_vport->lport.stats, 0, sizeof(struct bfa_lport_stats_s));
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

static int
bfad_iocmd_fabric_get_lports(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_fabric_get_lports_s *iocmd =
			(struct bfa_bsg_fabric_get_lports_s *)cmd;
	bfa_fcs_vf_t	*fcs_vf;
	uint32_t	nports = iocmd->nports;
	unsigned long	flags;
	void	*iocmd_bufptr;

	if (nports == 0) {
		iocmd->status = BFA_STATUS_EINVAL;
		goto out;
	}

	if (bfad_chk_iocmd_sz(payload_len,
		sizeof(struct bfa_bsg_fabric_get_lports_s),
		sizeof(wwn_t[iocmd->nports])) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		goto out;
	}

	iocmd_bufptr = (char *)iocmd +
			sizeof(struct bfa_bsg_fabric_get_lports_s);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_vf = bfa_fcs_vf_lookup(&bfad->bfa_fcs, iocmd->vf_id);
	if (fcs_vf == NULL) {
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		iocmd->status = BFA_STATUS_UNKNOWN_VFID;
		goto out;
	}
	bfa_fcs_vf_get_ports(fcs_vf, (wwn_t *)iocmd_bufptr, &nports);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	iocmd->nports = nports;
	iocmd->status = BFA_STATUS_OK;
out:
	return 0;
}

int
bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);

	if (cmd == IOCMD_RATELIM_ENABLE)
		fcport->cfg.ratelimit = BFA_TRUE;
	else if (cmd == IOCMD_RATELIM_DISABLE)
		fcport->cfg.ratelimit = BFA_FALSE;

	if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
		fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;

	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;

	return 0;
}

int
bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
	struct bfa_bsg_trl_speed_s *iocmd = (struct bfa_bsg_trl_speed_s *)pcmd;
	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);

	/* Auto and speeds greater than the supported speed, are invalid */
	if ((iocmd->speed == BFA_PORT_SPEED_AUTO) ||
	    (iocmd->speed > fcport->speed_sup)) {
		iocmd->status = BFA_STATUS_UNSUPP_SPEED;
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		return 0;
	}

	fcport->cfg.trl_def_speed = iocmd->speed;
	iocmd->status = BFA_STATUS_OK;
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

int
bfad_iocmd_cfg_fcpim(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_fcpim_s *iocmd = (struct bfa_bsg_fcpim_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	bfa_fcpim_path_tov_set(&bfad->bfa, iocmd->param);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_fcpim_modstats_s *iocmd =
			(struct bfa_bsg_fcpim_modstats_s *)cmd;
	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
	struct list_head *qe, *qen;
	struct bfa_itnim_s *itnim;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	/* accumulate IO stats from itnim */
	memset((void *)&iocmd->modstats, 0, sizeof(struct bfa_itnim_iostats_s));
	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
		itnim = (struct bfa_itnim_s *) qe;
		bfa_fcpim_add_stats(&iocmd->modstats, &(itnim->stats));
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_fcpim_clr_modstats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_fcpim_modstatsclr_s *iocmd =
				(struct bfa_bsg_fcpim_modstatsclr_s *)cmd;
	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
	struct list_head *qe, *qen;
	struct bfa_itnim_s *itnim;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
		itnim = (struct bfa_itnim_s *) qe;
		bfa_itnim_clear_stats(itnim);
	}
	memset(&fcpim->del_itn_stats, 0,
		sizeof(struct bfa_fcpim_del_itn_stats_s));
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_fcpim_get_del_itn_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_fcpim_del_itn_stats_s *iocmd =
			(struct bfa_bsg_fcpim_del_itn_stats_s *)cmd;
	struct bfa_fcpim_s *fcpim = BFA_FCPIM(&bfad->bfa);
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	memcpy((void *)&iocmd->modstats, (void *)&fcpim->del_itn_stats,
		sizeof(struct bfa_fcpim_del_itn_stats_s));
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	iocmd->status = BFA_STATUS_OK;
	return 0;
}

static int
bfad_iocmd_itnim_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_itnim_attr_s *iocmd = (struct bfa_bsg_itnim_attr_s *)cmd;
	struct bfa_fcs_lport_s	*fcs_port;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->lpwwn);
	if (!fcs_port)
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
	else
		iocmd->status = bfa_fcs_itnim_attr_get(fcs_port,
					iocmd->rpwwn, &iocmd->attr);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	return 0;
}

static int
bfad_iocmd_itnim_get_iostats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_itnim_iostats_s *iocmd =
			(struct bfa_bsg_itnim_iostats_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_itnim_s *itnim;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->lpwwn);
	if (!fcs_port) {
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		bfa_trc(bfad, 0);
	} else {
		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
		if (itnim == NULL)
			iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		else {
			iocmd->status = BFA_STATUS_OK;
			memcpy((void *)&iocmd->iostats, (void *)
			       &(bfa_fcs_itnim_get_halitn(itnim)->stats),
			       sizeof(struct bfa_itnim_iostats_s));
		}
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	return 0;
}

static int
bfad_iocmd_itnim_reset_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_rport_reset_stats_s *iocmd =
			(struct bfa_bsg_rport_reset_stats_s *)cmd;
	struct bfa_fcs_lport_s	*fcs_port;
	struct bfa_fcs_itnim_s	*itnim;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->pwwn);
	if (!fcs_port)
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
	else {
		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
		if (itnim == NULL)
			iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		else {
			iocmd->status = BFA_STATUS_OK;
			bfa_fcs_itnim_stats_clear(fcs_port, iocmd->rpwwn);
			bfa_itnim_clear_stats(bfa_fcs_itnim_get_halitn(itnim));
		}
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

static int
bfad_iocmd_itnim_get_itnstats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_itnim_itnstats_s *iocmd =
			(struct bfa_bsg_itnim_itnstats_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_itnim_s *itnim;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->lpwwn);
	if (!fcs_port) {
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
		bfa_trc(bfad, 0);
	} else {
		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
		if (itnim == NULL)
			iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		else {
			iocmd->status = BFA_STATUS_OK;
			bfa_fcs_itnim_stats_get(fcs_port, iocmd->rpwwn,
					&iocmd->itnstats);
		}
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	return 0;
}

int
bfad_iocmd_fcport_enable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	unsigned long flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcport_enable(&bfad->bfa);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

int
bfad_iocmd_fcport_disable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	unsigned long flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcport_disable(&bfad->bfa);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

int
bfad_iocmd_ioc_get_pcifn_cfg(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_pcifn_cfg_s *iocmd = (struct bfa_bsg_pcifn_cfg_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ablk_query(&bfad->bfa.modules.ablk,
				&iocmd->pcifn_cfg,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ablk_pf_create(&bfad->bfa.modules.ablk,
				&iocmd->pcifn_id, iocmd->port,
				iocmd->pcifn_class, iocmd->bandwidth,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_pcifn_delete(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ablk_pf_delete(&bfad->bfa.modules.ablk,
				iocmd->pcifn_id,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ablk_pf_update(&bfad->bfa.modules.ablk,
				iocmd->pcifn_id, iocmd->bandwidth,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
	bfa_trc(bfad, iocmd->status);
out:
	return 0;
}

int
bfad_iocmd_adapter_cfg_mode(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_adapter_cfg_mode_s *iocmd =
			(struct bfa_bsg_adapter_cfg_mode_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags = 0;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ablk_adapter_config(&bfad->bfa.modules.ablk,
				iocmd->cfg.mode, iocmd->cfg.max_pf,
				iocmd->cfg.max_vf, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_port_cfg_mode(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_port_cfg_mode_s *iocmd =
			(struct bfa_bsg_port_cfg_mode_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long flags = 0;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ablk_port_config(&bfad->bfa.modules.ablk,
				iocmd->instance, iocmd->cfg.mode,
				iocmd->cfg.max_pf, iocmd->cfg.max_vf,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_ablk_optrom(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
	struct bfad_hal_comp fcomp;
	unsigned long   flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	if (cmd == IOCMD_FLASH_ENABLE_OPTROM)
		iocmd->status = bfa_ablk_optrom_en(&bfad->bfa.modules.ablk,
					bfad_hcb_comp, &fcomp);
	else
		iocmd->status = bfa_ablk_optrom_dis(&bfad->bfa.modules.ablk,
					bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_faa_enable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	unsigned long   flags;
	struct bfad_hal_comp    fcomp;

	init_completion(&fcomp.comp);
	iocmd->status = BFA_STATUS_OK;
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_faa_enable(&bfad->bfa, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_faa_disable(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	unsigned long   flags;
	struct bfad_hal_comp    fcomp;

	init_completion(&fcomp.comp);
	iocmd->status = BFA_STATUS_OK;
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_faa_disable(&bfad->bfa, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_faa_query(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_faa_attr_s *iocmd = (struct bfa_bsg_faa_attr_s *)cmd;
	struct bfad_hal_comp    fcomp;
	unsigned long   flags;

	init_completion(&fcomp.comp);
	iocmd->status = BFA_STATUS_OK;
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_faa_query(&bfad->bfa, &iocmd->faa_attr,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	if (iocmd->status != BFA_STATUS_OK)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_cee_attr(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
{
	struct bfa_bsg_cee_attr_s *iocmd =
				(struct bfa_bsg_cee_attr_s *)cmd;
	void	*iocmd_bufptr;
	struct bfad_hal_comp	cee_comp;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_cee_attr_s),
			sizeof(struct bfa_cee_attr_s)) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_attr_s);

	cee_comp.status = 0;
	init_completion(&cee_comp.comp);
	mutex_lock(&bfad_mutex);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_cee_get_attr(&bfad->bfa.modules.cee, iocmd_bufptr,
					 bfad_hcb_comp, &cee_comp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK) {
		mutex_unlock(&bfad_mutex);
		bfa_trc(bfad, 0x5555);
		goto out;
	}
	wait_for_completion(&cee_comp.comp);
	mutex_unlock(&bfad_mutex);
out:
	return 0;
}

int
bfad_iocmd_cee_get_stats(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_cee_stats_s *iocmd =
				(struct bfa_bsg_cee_stats_s *)cmd;
	void	*iocmd_bufptr;
	struct bfad_hal_comp	cee_comp;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_cee_stats_s),
			sizeof(struct bfa_cee_stats_s)) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_cee_stats_s);

	cee_comp.status = 0;
	init_completion(&cee_comp.comp);
	mutex_lock(&bfad_mutex);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_cee_get_stats(&bfad->bfa.modules.cee, iocmd_bufptr,
					bfad_hcb_comp, &cee_comp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK) {
		mutex_unlock(&bfad_mutex);
		bfa_trc(bfad, 0x5555);
		goto out;
	}
	wait_for_completion(&cee_comp.comp);
	mutex_unlock(&bfad_mutex);
out:
	return 0;
}

int
bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_cee_reset_stats(&bfad->bfa.modules.cee, NULL, NULL);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		bfa_trc(bfad, 0x5555);
	return 0;
}

int
bfad_iocmd_sfp_media(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_sfp_media_s *iocmd = (struct bfa_bsg_sfp_media_s *)cmd;
	struct bfad_hal_comp	fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_sfp_media(BFA_SFP_MOD(&bfad->bfa), &iocmd->media,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_SFP_NOT_READY)
		goto out;

	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_sfp_speed(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_sfp_speed_s *iocmd = (struct bfa_bsg_sfp_speed_s *)cmd;
	struct bfad_hal_comp	fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_sfp_speed(BFA_SFP_MOD(&bfad->bfa), iocmd->speed,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_SFP_NOT_READY)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_flash_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_flash_attr_s *iocmd =
			(struct bfa_bsg_flash_attr_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_flash_get_attr(BFA_FLASH(&bfad->bfa), &iocmd->attr,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_flash_erase_part(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_flash_erase_part(BFA_FLASH(&bfad->bfa), iocmd->type,
				iocmd->instance, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_flash_update_part(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
	void	*iocmd_bufptr;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_flash_s),
			iocmd->bufsz) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s);

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_flash_update_part(BFA_FLASH(&bfad->bfa),
				iocmd->type, iocmd->instance, iocmd_bufptr,
				iocmd->bufsz, 0, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_flash_read_part(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
	struct bfad_hal_comp fcomp;
	void	*iocmd_bufptr;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_flash_s),
			iocmd->bufsz) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_flash_s);

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_flash_read_part(BFA_FLASH(&bfad->bfa), iocmd->type,
				iocmd->instance, iocmd_bufptr, iocmd->bufsz, 0,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_diag_temp(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_get_temp_s *iocmd =
			(struct bfa_bsg_diag_get_temp_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_diag_tsensor_query(BFA_DIAG_MOD(&bfad->bfa),
				&iocmd->result, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_diag_memtest(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_memtest_s *iocmd =
			(struct bfa_bsg_diag_memtest_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long   flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_diag_memtest(BFA_DIAG_MOD(&bfad->bfa),
				&iocmd->memtest, iocmd->pat,
				&iocmd->result, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_diag_loopback(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_loopback_s *iocmd =
			(struct bfa_bsg_diag_loopback_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long   flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcdiag_loopback(&bfad->bfa, iocmd->opmode,
				iocmd->speed, iocmd->lpcnt, iocmd->pat,
				&iocmd->result, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_diag_fwping(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_fwping_s *iocmd =
			(struct bfa_bsg_diag_fwping_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long   flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_diag_fwping(BFA_DIAG_MOD(&bfad->bfa), iocmd->cnt,
				iocmd->pattern, &iocmd->result,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	bfa_trc(bfad, 0x77771);
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_diag_queuetest(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_qtest_s *iocmd = (struct bfa_bsg_diag_qtest_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long   flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcdiag_queuetest(&bfad->bfa, iocmd->force,
				iocmd->queue, &iocmd->result,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_diag_sfp(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_sfp_show_s *iocmd =
			(struct bfa_bsg_sfp_show_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long   flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_sfp_show(BFA_SFP_MOD(&bfad->bfa), &iocmd->sfp,
				bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
	bfa_trc(bfad, iocmd->status);
out:
	return 0;
}

int
bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_led_s *iocmd = (struct bfa_bsg_diag_led_s *)cmd;
	unsigned long   flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_diag_ledtest(BFA_DIAG_MOD(&bfad->bfa),
				&iocmd->ledtest);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	return 0;
}

int
bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_beacon_s *iocmd =
			(struct bfa_bsg_diag_beacon_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_diag_beacon_port(BFA_DIAG_MOD(&bfad->bfa),
				iocmd->beacon, iocmd->link_e2e_beacon,
				iocmd->second);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	return 0;
}

int
bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_diag_lb_stat_s *iocmd =
			(struct bfa_bsg_diag_lb_stat_s *)cmd;
	unsigned long	flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcdiag_lb_is_running(&bfad->bfa);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	bfa_trc(bfad, iocmd->status);

	return 0;
}

int
bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_phy_attr_s *iocmd =
			(struct bfa_bsg_phy_attr_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_phy_get_attr(BFA_PHY(&bfad->bfa), iocmd->instance,
				&iocmd->attr, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_phy_get_stats(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_phy_stats_s *iocmd =
			(struct bfa_bsg_phy_stats_s *)cmd;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_phy_get_stats(BFA_PHY(&bfad->bfa), iocmd->instance,
				&iocmd->stats, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_phy_read(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
{
	struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
	struct bfad_hal_comp fcomp;
	void	*iocmd_bufptr;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_phy_s),
			iocmd->bufsz) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s);
	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_phy_read(BFA_PHY(&bfad->bfa),
				iocmd->instance, iocmd_bufptr, iocmd->bufsz,
				0, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
out:
	return 0;
}

int
bfad_iocmd_vhba_query(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_vhba_attr_s *iocmd =
			(struct bfa_bsg_vhba_attr_s *)cmd;
	struct bfa_vhba_attr_s *attr = &iocmd->attr;
	unsigned long flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	attr->pwwn =  bfad->bfa.ioc.attr->pwwn;
	attr->nwwn =  bfad->bfa.ioc.attr->nwwn;
	attr->plog_enabled = (bfa_boolean_t)bfad->bfa.plog->plog_enabled;
	attr->io_profile = bfa_fcpim_get_io_profile(&bfad->bfa);
	attr->path_tov  = bfa_fcpim_path_tov_get(&bfad->bfa);
	iocmd->status = BFA_STATUS_OK;
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	return 0;
}

int
bfad_iocmd_phy_update(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
{
	struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
	void	*iocmd_bufptr;
	struct bfad_hal_comp fcomp;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len,
			sizeof(struct bfa_bsg_phy_s),
			iocmd->bufsz) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_phy_s);
	init_completion(&fcomp.comp);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_phy_update(BFA_PHY(&bfad->bfa),
				iocmd->instance, iocmd_bufptr, iocmd->bufsz,
				0, bfad_hcb_comp, &fcomp);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	if (iocmd->status != BFA_STATUS_OK)
		goto out;
	wait_for_completion(&fcomp.comp);
	iocmd->status = fcomp.status;
out:
	return 0;
}

int
bfad_iocmd_porglog_get(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd;
	void *iocmd_bufptr;

	if (iocmd->bufsz < sizeof(struct bfa_plog_s)) {
		bfa_trc(bfad, sizeof(struct bfa_plog_s));
		iocmd->status = BFA_STATUS_EINVAL;
		goto out;
	}

	iocmd->status = BFA_STATUS_OK;
	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_debug_s);
	memcpy(iocmd_bufptr, (u8 *) &bfad->plog_buf, sizeof(struct bfa_plog_s));
out:
	return 0;
}

#define BFA_DEBUG_FW_CORE_CHUNK_SZ	0x4000U /* 16K chunks for FW dump */
int
bfad_iocmd_debug_fw_core(struct bfad_s *bfad, void *cmd,
			unsigned int payload_len)
{
	struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd;
	void	*iocmd_bufptr;
	unsigned long	flags;

	if (bfad_chk_iocmd_sz(payload_len, sizeof(struct bfa_bsg_debug_s),
			BFA_DEBUG_FW_CORE_CHUNK_SZ) != BFA_STATUS_OK) {
		iocmd->status = BFA_STATUS_VERSION_FAIL;
		return 0;
	}

	if (iocmd->bufsz < BFA_DEBUG_FW_CORE_CHUNK_SZ ||
			!IS_ALIGNED(iocmd->bufsz, sizeof(u16)) ||
			!IS_ALIGNED(iocmd->offset, sizeof(u32))) {
		bfa_trc(bfad, BFA_DEBUG_FW_CORE_CHUNK_SZ);
		iocmd->status = BFA_STATUS_EINVAL;
		goto out;
	}

	iocmd_bufptr = (char *)iocmd + sizeof(struct bfa_bsg_debug_s);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_ioc_debug_fwcore(&bfad->bfa.ioc, iocmd_bufptr,
				(u32 *)&iocmd->offset, &iocmd->bufsz);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
out:
	return 0;
}

int
bfad_iocmd_debug_ctl(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
	struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
	unsigned long	flags;

	if (v_cmd == IOCMD_DEBUG_FW_STATE_CLR) {
		spin_lock_irqsave(&bfad->bfad_lock, flags);
		bfad->bfa.ioc.dbg_fwsave_once = BFA_TRUE;
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	} else if (v_cmd == IOCMD_DEBUG_PORTLOG_CLR)
		bfad->plog_buf.head = bfad->plog_buf.tail = 0;
	else if (v_cmd == IOCMD_DEBUG_START_DTRC)
		bfa_trc_init(bfad->trcmod);
	else if (v_cmd == IOCMD_DEBUG_STOP_DTRC)
		bfa_trc_stop(bfad->trcmod);

	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_porglog_ctl(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_portlogctl_s *iocmd = (struct bfa_bsg_portlogctl_s *)cmd;

	if (iocmd->ctl == BFA_TRUE)
		bfad->plog_buf.plog_enabled = 1;
	else
		bfad->plog_buf.plog_enabled = 0;

	iocmd->status = BFA_STATUS_OK;
	return 0;
}

int
bfad_iocmd_fcpim_cfg_profile(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
	struct bfa_bsg_fcpim_profile_s *iocmd =
				(struct bfa_bsg_fcpim_profile_s *)cmd;
	struct timeval  tv;
	unsigned long	flags;

	do_gettimeofday(&tv);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	if (v_cmd == IOCMD_FCPIM_PROFILE_ON)
		iocmd->status = bfa_fcpim_profile_on(&bfad->bfa, tv.tv_sec);
	else if (v_cmd == IOCMD_FCPIM_PROFILE_OFF)
		iocmd->status = bfa_fcpim_profile_off(&bfad->bfa);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return 0;
}

static int
bfad_iocmd_itnim_get_ioprofile(struct bfad_s *bfad, void *cmd)
{
	struct bfa_bsg_itnim_ioprofile_s *iocmd =
				(struct bfa_bsg_itnim_ioprofile_s *)cmd;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_itnim_s *itnim;
	unsigned long   flags;

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs,
				iocmd->vf_id, iocmd->lpwwn);
	if (!fcs_port)
		iocmd->status = BFA_STATUS_UNKNOWN_LWWN;
	else {
		itnim = bfa_fcs_itnim_lookup(fcs_port, iocmd->rpwwn);
		if (itnim == NULL)
			iocmd->status = BFA_STATUS_UNKNOWN_RWWN;
		else
			iocmd->status = bfa_itnim_get_ioprofile(
						bfa_fcs_itnim_get_halitn(itnim),
						&iocmd->ioprofile);
	}
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
	return 0;
}

static int
bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
		unsigned int payload_len)
{
	int rc = -EINVAL;

	switch (cmd) {
	case IOCMD_IOC_ENABLE:
		rc = bfad_iocmd_ioc_enable(bfad, iocmd);
		break;
	case IOCMD_IOC_DISABLE:
		rc = bfad_iocmd_ioc_disable(bfad, iocmd);
		break;
	case IOCMD_IOC_GET_INFO:
		rc = bfad_iocmd_ioc_get_info(bfad, iocmd);
		break;
	case IOCMD_IOC_GET_ATTR:
		rc = bfad_iocmd_ioc_get_attr(bfad, iocmd);
		break;
	case IOCMD_IOC_GET_STATS:
		rc = bfad_iocmd_ioc_get_stats(bfad, iocmd);
		break;
	case IOCMD_IOC_GET_FWSTATS:
		rc = bfad_iocmd_ioc_get_fwstats(bfad, iocmd, payload_len);
		break;
	case IOCMD_IOC_RESET_STATS:
	case IOCMD_IOC_RESET_FWSTATS:
		rc = bfad_iocmd_ioc_reset_stats(bfad, iocmd, cmd);
		break;
	case IOCMD_IOC_SET_ADAPTER_NAME:
	case IOCMD_IOC_SET_PORT_NAME:
		rc = bfad_iocmd_ioc_set_name(bfad, iocmd, cmd);
		break;
	case IOCMD_IOCFC_GET_ATTR:
		rc = bfad_iocmd_iocfc_get_attr(bfad, iocmd);
		break;
	case IOCMD_IOCFC_SET_INTR:
		rc = bfad_iocmd_iocfc_set_intr(bfad, iocmd);
		break;
	case IOCMD_PORT_ENABLE:
		rc = bfad_iocmd_port_enable(bfad, iocmd);
		break;
	case IOCMD_PORT_DISABLE:
		rc = bfad_iocmd_port_disable(bfad, iocmd);
		break;
	case IOCMD_PORT_GET_ATTR:
		rc = bfad_iocmd_port_get_attr(bfad, iocmd);
		break;
	case IOCMD_PORT_GET_STATS:
		rc = bfad_iocmd_port_get_stats(bfad, iocmd, payload_len);
		break;
	case IOCMD_PORT_RESET_STATS:
		rc = bfad_iocmd_port_reset_stats(bfad, iocmd);
		break;
	case IOCMD_PORT_CFG_TOPO:
	case IOCMD_PORT_CFG_SPEED:
	case IOCMD_PORT_CFG_ALPA:
	case IOCMD_PORT_CLR_ALPA:
		rc = bfad_iocmd_set_port_cfg(bfad, iocmd, cmd);
		break;
	case IOCMD_PORT_CFG_MAXFRSZ:
		rc = bfad_iocmd_port_cfg_maxfrsize(bfad, iocmd);
		break;
	case IOCMD_PORT_BBSC_ENABLE:
	case IOCMD_PORT_BBSC_DISABLE:
		rc = bfad_iocmd_port_cfg_bbsc(bfad, iocmd, cmd);
		break;
	case IOCMD_LPORT_GET_ATTR:
		rc = bfad_iocmd_lport_get_attr(bfad, iocmd);
		break;
	case IOCMD_LPORT_GET_STATS:
		rc = bfad_iocmd_lport_get_stats(bfad, iocmd);
		break;
	case IOCMD_LPORT_RESET_STATS:
		rc = bfad_iocmd_lport_reset_stats(bfad, iocmd);
		break;
	case IOCMD_LPORT_GET_IOSTATS:
		rc = bfad_iocmd_lport_get_iostats(bfad, iocmd);
		break;
	case IOCMD_LPORT_GET_RPORTS:
		rc = bfad_iocmd_lport_get_rports(bfad, iocmd, payload_len);
		break;
	case IOCMD_RPORT_GET_ATTR:
		rc = bfad_iocmd_rport_get_attr(bfad, iocmd);
		break;
	case IOCMD_RPORT_GET_ADDR:
		rc = bfad_iocmd_rport_get_addr(bfad, iocmd);
		break;
	case IOCMD_RPORT_GET_STATS:
		rc = bfad_iocmd_rport_get_stats(bfad, iocmd);
		break;
	case IOCMD_RPORT_RESET_STATS:
		rc = bfad_iocmd_rport_clr_stats(bfad, iocmd);
		break;
	case IOCMD_RPORT_SET_SPEED:
		rc = bfad_iocmd_rport_set_speed(bfad, iocmd);
		break;
	case IOCMD_VPORT_GET_ATTR:
		rc = bfad_iocmd_vport_get_attr(bfad, iocmd);
		break;
	case IOCMD_VPORT_GET_STATS:
		rc = bfad_iocmd_vport_get_stats(bfad, iocmd);
		break;
	case IOCMD_VPORT_RESET_STATS:
		rc = bfad_iocmd_vport_clr_stats(bfad, iocmd);
		break;
	case IOCMD_FABRIC_GET_LPORTS:
		rc = bfad_iocmd_fabric_get_lports(bfad, iocmd, payload_len);
		break;
	case IOCMD_RATELIM_ENABLE:
	case IOCMD_RATELIM_DISABLE:
		rc = bfad_iocmd_ratelim(bfad, cmd, iocmd);
		break;
	case IOCMD_RATELIM_DEF_SPEED:
		rc = bfad_iocmd_ratelim_speed(bfad, cmd, iocmd);
		break;
	case IOCMD_FCPIM_FAILOVER:
		rc = bfad_iocmd_cfg_fcpim(bfad, iocmd);
		break;
	case IOCMD_FCPIM_MODSTATS:
		rc = bfad_iocmd_fcpim_get_modstats(bfad, iocmd);
		break;
	case IOCMD_FCPIM_MODSTATSCLR:
		rc = bfad_iocmd_fcpim_clr_modstats(bfad, iocmd);
		break;
	case IOCMD_FCPIM_DEL_ITN_STATS:
		rc = bfad_iocmd_fcpim_get_del_itn_stats(bfad, iocmd);
		break;
	case IOCMD_ITNIM_GET_ATTR:
		rc = bfad_iocmd_itnim_get_attr(bfad, iocmd);
		break;
	case IOCMD_ITNIM_GET_IOSTATS:
		rc = bfad_iocmd_itnim_get_iostats(bfad, iocmd);
		break;
	case IOCMD_ITNIM_RESET_STATS:
		rc = bfad_iocmd_itnim_reset_stats(bfad, iocmd);
		break;
	case IOCMD_ITNIM_GET_ITNSTATS:
		rc = bfad_iocmd_itnim_get_itnstats(bfad, iocmd);
		break;
	case IOCMD_FCPORT_ENABLE:
		rc = bfad_iocmd_fcport_enable(bfad, iocmd);
		break;
	case IOCMD_FCPORT_DISABLE:
		rc = bfad_iocmd_fcport_disable(bfad, iocmd);
		break;
	case IOCMD_IOC_PCIFN_CFG:
		rc = bfad_iocmd_ioc_get_pcifn_cfg(bfad, iocmd);
		break;
	case IOCMD_PCIFN_CREATE:
		rc = bfad_iocmd_pcifn_create(bfad, iocmd);
		break;
	case IOCMD_PCIFN_DELETE:
		rc = bfad_iocmd_pcifn_delete(bfad, iocmd);
		break;
	case IOCMD_PCIFN_BW:
		rc = bfad_iocmd_pcifn_bw(bfad, iocmd);
		break;
	case IOCMD_ADAPTER_CFG_MODE:
		rc = bfad_iocmd_adapter_cfg_mode(bfad, iocmd);
		break;
	case IOCMD_PORT_CFG_MODE:
		rc = bfad_iocmd_port_cfg_mode(bfad, iocmd);
		break;
	case IOCMD_FLASH_ENABLE_OPTROM:
	case IOCMD_FLASH_DISABLE_OPTROM:
		rc = bfad_iocmd_ablk_optrom(bfad, cmd, iocmd);
		break;
	case IOCMD_FAA_ENABLE:
		rc = bfad_iocmd_faa_enable(bfad, iocmd);
		break;
	case IOCMD_FAA_DISABLE:
		rc = bfad_iocmd_faa_disable(bfad, iocmd);
		break;
	case IOCMD_FAA_QUERY:
		rc = bfad_iocmd_faa_query(bfad, iocmd);
		break;
	case IOCMD_CEE_GET_ATTR:
		rc = bfad_iocmd_cee_attr(bfad, iocmd, payload_len);
		break;
	case IOCMD_CEE_GET_STATS:
		rc = bfad_iocmd_cee_get_stats(bfad, iocmd, payload_len);
		break;
	case IOCMD_CEE_RESET_STATS:
		rc = bfad_iocmd_cee_reset_stats(bfad, iocmd);
		break;
	case IOCMD_SFP_MEDIA:
		rc = bfad_iocmd_sfp_media(bfad, iocmd);
		 break;
	case IOCMD_SFP_SPEED:
		rc = bfad_iocmd_sfp_speed(bfad, iocmd);
		break;
	case IOCMD_FLASH_GET_ATTR:
		rc = bfad_iocmd_flash_get_attr(bfad, iocmd);
		break;
	case IOCMD_FLASH_ERASE_PART:
		rc = bfad_iocmd_flash_erase_part(bfad, iocmd);
		break;
	case IOCMD_FLASH_UPDATE_PART:
		rc = bfad_iocmd_flash_update_part(bfad, iocmd, payload_len);
		break;
	case IOCMD_FLASH_READ_PART:
		rc = bfad_iocmd_flash_read_part(bfad, iocmd, payload_len);
		break;
	case IOCMD_DIAG_TEMP:
		rc = bfad_iocmd_diag_temp(bfad, iocmd);
		break;
	case IOCMD_DIAG_MEMTEST:
		rc = bfad_iocmd_diag_memtest(bfad, iocmd);
		break;
	case IOCMD_DIAG_LOOPBACK:
		rc = bfad_iocmd_diag_loopback(bfad, iocmd);
		break;
	case IOCMD_DIAG_FWPING:
		rc = bfad_iocmd_diag_fwping(bfad, iocmd);
		break;
	case IOCMD_DIAG_QUEUETEST:
		rc = bfad_iocmd_diag_queuetest(bfad, iocmd);
		break;
	case IOCMD_DIAG_SFP:
		rc = bfad_iocmd_diag_sfp(bfad, iocmd);
		break;
	case IOCMD_DIAG_LED:
		rc = bfad_iocmd_diag_led(bfad, iocmd);
		break;
	case IOCMD_DIAG_BEACON_LPORT:
		rc = bfad_iocmd_diag_beacon_lport(bfad, iocmd);
		break;
	case IOCMD_DIAG_LB_STAT:
		rc = bfad_iocmd_diag_lb_stat(bfad, iocmd);
		break;
	case IOCMD_PHY_GET_ATTR:
		rc = bfad_iocmd_phy_get_attr(bfad, iocmd);
		break;
	case IOCMD_PHY_GET_STATS:
		rc = bfad_iocmd_phy_get_stats(bfad, iocmd);
		break;
	case IOCMD_PHY_UPDATE_FW:
		rc = bfad_iocmd_phy_update(bfad, iocmd, payload_len);
		break;
	case IOCMD_PHY_READ_FW:
		rc = bfad_iocmd_phy_read(bfad, iocmd, payload_len);
		break;
	case IOCMD_VHBA_QUERY:
		rc = bfad_iocmd_vhba_query(bfad, iocmd);
		break;
	case IOCMD_DEBUG_PORTLOG:
		rc = bfad_iocmd_porglog_get(bfad, iocmd);
		break;
	case IOCMD_DEBUG_FW_CORE:
		rc = bfad_iocmd_debug_fw_core(bfad, iocmd, payload_len);
		break;
	case IOCMD_DEBUG_FW_STATE_CLR:
	case IOCMD_DEBUG_PORTLOG_CLR:
	case IOCMD_DEBUG_START_DTRC:
	case IOCMD_DEBUG_STOP_DTRC:
		rc = bfad_iocmd_debug_ctl(bfad, iocmd, cmd);
		break;
	case IOCMD_DEBUG_PORTLOG_CTL:
		rc = bfad_iocmd_porglog_ctl(bfad, iocmd);
		break;
	case IOCMD_FCPIM_PROFILE_ON:
	case IOCMD_FCPIM_PROFILE_OFF:
		rc = bfad_iocmd_fcpim_cfg_profile(bfad, iocmd, cmd);
		break;
	case IOCMD_ITNIM_GET_IOPROFILE:
		rc = bfad_iocmd_itnim_get_ioprofile(bfad, iocmd);
		break;
	default:
		rc = -EINVAL;
		break;
	}
	return rc;
}

static int
bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
{
	uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0];
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) job->shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	void *payload_kbuf;
	int rc = -EINVAL;

	/* Allocate a temp buffer to hold the passed in user space command */
	payload_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
	if (!payload_kbuf) {
		rc = -ENOMEM;
		goto out;
	}

	/* Copy the sg_list passed in to a linear buffer: holds the cmnd data */
	sg_copy_to_buffer(job->request_payload.sg_list,
			  job->request_payload.sg_cnt, payload_kbuf,
			  job->request_payload.payload_len);

	/* Invoke IOCMD handler - to handle all the vendor command requests */
	rc = bfad_iocmd_handler(bfad, vendor_cmd, payload_kbuf,
				job->request_payload.payload_len);
	if (rc != BFA_STATUS_OK)
		goto error;

	/* Copy the response data to the job->reply_payload sg_list */
	sg_copy_from_buffer(job->reply_payload.sg_list,
			    job->reply_payload.sg_cnt,
			    payload_kbuf,
			    job->reply_payload.payload_len);

	/* free the command buffer */
	kfree(payload_kbuf);

	/* Fill the BSG job reply data */
	job->reply_len = job->reply_payload.payload_len;
	job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
	job->reply->result = rc;

	job->job_done(job);
	return rc;
error:
	/* free the command buffer */
	kfree(payload_kbuf);
out:
	job->reply->result = rc;
	job->reply_len = sizeof(uint32_t);
	job->reply->reply_payload_rcv_len = 0;
	return rc;
}

/* FC passthru call backs */
u64
bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid)
{
	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
	struct bfa_sge_s  *sge;
	u64	addr;

	sge = drv_fcxp->req_sge + sgeid;
	addr = (u64)(size_t) sge->sg_addr;
	return addr;
}

u32
bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid)
{
	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
	struct bfa_sge_s	*sge;

	sge = drv_fcxp->req_sge + sgeid;
	return sge->sg_len;
}

u64
bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid)
{
	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
	struct bfa_sge_s	*sge;
	u64	addr;

	sge = drv_fcxp->rsp_sge + sgeid;
	addr = (u64)(size_t) sge->sg_addr;
	return addr;
}

u32
bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid)
{
	struct bfad_fcxp	*drv_fcxp = bfad_fcxp;
	struct bfa_sge_s	*sge;

	sge = drv_fcxp->rsp_sge + sgeid;
	return sge->sg_len;
}

void
bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
		bfa_status_t req_status, u32 rsp_len, u32 resid_len,
		struct fchs_s *rsp_fchs)
{
	struct bfad_fcxp *drv_fcxp = bfad_fcxp;

	drv_fcxp->req_status = req_status;
	drv_fcxp->rsp_len = rsp_len;

	/* bfa_fcxp will be automatically freed by BFA */
	drv_fcxp->bfa_fcxp = NULL;
	complete(&drv_fcxp->comp);
}

struct bfad_buf_info *
bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
		 uint32_t payload_len, uint32_t *num_sgles)
{
	struct bfad_buf_info	*buf_base, *buf_info;
	struct bfa_sge_s	*sg_table;
	int sge_num = 1;

	buf_base = kzalloc((sizeof(struct bfad_buf_info) +
			   sizeof(struct bfa_sge_s)) * sge_num, GFP_KERNEL);
	if (!buf_base)
		return NULL;

	sg_table = (struct bfa_sge_s *) (((uint8_t *)buf_base) +
			(sizeof(struct bfad_buf_info) * sge_num));

	/* Allocate dma coherent memory */
	buf_info = buf_base;
	buf_info->size = payload_len;
	buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size,
					&buf_info->phys, GFP_KERNEL);
	if (!buf_info->virt)
		goto out_free_mem;

	/* copy the linear bsg buffer to buf_info */
	memset(buf_info->virt, 0, buf_info->size);
	memcpy(buf_info->virt, payload_kbuf, buf_info->size);

	/*
	 * Setup SG table
	 */
	sg_table->sg_len = buf_info->size;
	sg_table->sg_addr = (void *)(size_t) buf_info->phys;

	*num_sgles = sge_num;

	return buf_base;

out_free_mem:
	kfree(buf_base);
	return NULL;
}

void
bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base,
		   uint32_t num_sgles)
{
	int i;
	struct bfad_buf_info *buf_info = buf_base;

	if (buf_base) {
		for (i = 0; i < num_sgles; buf_info++, i++) {
			if (buf_info->virt != NULL)
				dma_free_coherent(&bfad->pcidev->dev,
					buf_info->size, buf_info->virt,
					buf_info->phys);
		}
		kfree(buf_base);
	}
}

int
bfad_fcxp_bsg_send(struct fc_bsg_job *job, struct bfad_fcxp *drv_fcxp,
		   bfa_bsg_fcpt_t *bsg_fcpt)
{
	struct bfa_fcxp_s *hal_fcxp;
	struct bfad_s	*bfad = drv_fcxp->port->bfad;
	unsigned long	flags;
	uint8_t	lp_tag;

	spin_lock_irqsave(&bfad->bfad_lock, flags);

	/* Allocate bfa_fcxp structure */
	hal_fcxp = bfa_fcxp_alloc(drv_fcxp, &bfad->bfa,
				  drv_fcxp->num_req_sgles,
				  drv_fcxp->num_rsp_sgles,
				  bfad_fcxp_get_req_sgaddr_cb,
				  bfad_fcxp_get_req_sglen_cb,
				  bfad_fcxp_get_rsp_sgaddr_cb,
				  bfad_fcxp_get_rsp_sglen_cb);
	if (!hal_fcxp) {
		bfa_trc(bfad, 0);
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		return BFA_STATUS_ENOMEM;
	}

	drv_fcxp->bfa_fcxp = hal_fcxp;

	lp_tag = bfa_lps_get_tag_from_pid(&bfad->bfa, bsg_fcpt->fchs.s_id);

	bfa_fcxp_send(hal_fcxp, drv_fcxp->bfa_rport, bsg_fcpt->vf_id, lp_tag,
		      bsg_fcpt->cts, bsg_fcpt->cos,
		      job->request_payload.payload_len,
		      &bsg_fcpt->fchs, bfad_send_fcpt_cb, bfad,
		      job->reply_payload.payload_len, bsg_fcpt->tsecs);

	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	return BFA_STATUS_OK;
}

int
bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
{
	struct bfa_bsg_data *bsg_data;
	struct bfad_im_port_s *im_port =
			(struct bfad_im_port_s *) job->shost->hostdata[0];
	struct bfad_s *bfad = im_port->bfad;
	bfa_bsg_fcpt_t *bsg_fcpt;
	struct bfad_fcxp    *drv_fcxp;
	struct bfa_fcs_lport_s *fcs_port;
	struct bfa_fcs_rport_s *fcs_rport;
	uint32_t command_type = job->request->msgcode;
	unsigned long flags;
	struct bfad_buf_info *rsp_buf_info;
	void *req_kbuf = NULL, *rsp_kbuf = NULL;
	int rc = -EINVAL;

	job->reply_len  = sizeof(uint32_t);	/* Atleast uint32_t reply_len */
	job->reply->reply_payload_rcv_len = 0;

	/* Get the payload passed in from userspace */
	bsg_data = (struct bfa_bsg_data *) (((char *)job->request) +
					sizeof(struct fc_bsg_request));
	if (bsg_data == NULL)
		goto out;

	/*
	 * Allocate buffer for bsg_fcpt and do a copy_from_user op for payload
	 * buffer of size bsg_data->payload_len
	 */
	bsg_fcpt = (struct bfa_bsg_fcpt_s *)
		   kzalloc(bsg_data->payload_len, GFP_KERNEL);
	if (!bsg_fcpt)
		goto out;

	if (copy_from_user((uint8_t *)bsg_fcpt, bsg_data->payload,
				bsg_data->payload_len)) {
		kfree(bsg_fcpt);
		goto out;
	}

	drv_fcxp = kzalloc(sizeof(struct bfad_fcxp), GFP_KERNEL);
	if (drv_fcxp == NULL) {
		rc = -ENOMEM;
		goto out;
	}

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	fcs_port = bfa_fcs_lookup_port(&bfad->bfa_fcs, bsg_fcpt->vf_id,
					bsg_fcpt->lpwwn);
	if (fcs_port == NULL) {
		bsg_fcpt->status = BFA_STATUS_UNKNOWN_LWWN;
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		goto out_free_mem;
	}

	/* Check if the port is online before sending FC Passthru cmd */
	if (!bfa_fcs_lport_is_online(fcs_port)) {
		bsg_fcpt->status = BFA_STATUS_PORT_OFFLINE;
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		goto out_free_mem;
	}

	drv_fcxp->port = fcs_port->bfad_port;

	if (drv_fcxp->port->bfad == 0)
		drv_fcxp->port->bfad = bfad;

	/* Fetch the bfa_rport - if nexus needed */
	if (command_type == FC_BSG_HST_ELS_NOLOGIN ||
	    command_type == FC_BSG_HST_CT) {
		/* BSG HST commands: no nexus needed */
		drv_fcxp->bfa_rport = NULL;

	} else if (command_type == FC_BSG_RPT_ELS ||
		   command_type == FC_BSG_RPT_CT) {
		/* BSG RPT commands: nexus needed */
		fcs_rport = bfa_fcs_lport_get_rport_by_pwwn(fcs_port,
							    bsg_fcpt->dpwwn);
		if (fcs_rport == NULL) {
			bsg_fcpt->status = BFA_STATUS_UNKNOWN_RWWN;
			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
			goto out_free_mem;
		}

		drv_fcxp->bfa_rport = fcs_rport->bfa_rport;

	} else { /* Unknown BSG msgcode; return -EINVAL */
		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
		goto out_free_mem;
	}

	spin_unlock_irqrestore(&bfad->bfad_lock, flags);

	/* allocate memory for req / rsp buffers */
	req_kbuf = kzalloc(job->request_payload.payload_len, GFP_KERNEL);
	if (!req_kbuf) {
		printk(KERN_INFO "bfa %s: fcpt request buffer alloc failed\n",
				bfad->pci_name);
		rc = -ENOMEM;
		goto out_free_mem;
	}

	rsp_kbuf = kzalloc(job->reply_payload.payload_len, GFP_KERNEL);
	if (!rsp_kbuf) {
		printk(KERN_INFO "bfa %s: fcpt response buffer alloc failed\n",
				bfad->pci_name);
		rc = -ENOMEM;
		goto out_free_mem;
	}

	/* map req sg - copy the sg_list passed in to the linear buffer */
	sg_copy_to_buffer(job->request_payload.sg_list,
			  job->request_payload.sg_cnt, req_kbuf,
			  job->request_payload.payload_len);

	drv_fcxp->reqbuf_info = bfad_fcxp_map_sg(bfad, req_kbuf,
					job->request_payload.payload_len,
					&drv_fcxp->num_req_sgles);
	if (!drv_fcxp->reqbuf_info) {
		printk(KERN_INFO "bfa %s: fcpt request fcxp_map_sg failed\n",
				bfad->pci_name);
		rc = -ENOMEM;
		goto out_free_mem;
	}

	drv_fcxp->req_sge = (struct bfa_sge_s *)
			    (((uint8_t *)drv_fcxp->reqbuf_info) +
			    (sizeof(struct bfad_buf_info) *
					drv_fcxp->num_req_sgles));

	/* map rsp sg */
	drv_fcxp->rspbuf_info = bfad_fcxp_map_sg(bfad, rsp_kbuf,
					job->reply_payload.payload_len,
					&drv_fcxp->num_rsp_sgles);
	if (!drv_fcxp->rspbuf_info) {
		printk(KERN_INFO "bfa %s: fcpt response fcxp_map_sg failed\n",
				bfad->pci_name);
		rc = -ENOMEM;
		goto out_free_mem;
	}

	rsp_buf_info = (struct bfad_buf_info *)drv_fcxp->rspbuf_info;
	drv_fcxp->rsp_sge = (struct bfa_sge_s  *)
			    (((uint8_t *)drv_fcxp->rspbuf_info) +
			    (sizeof(struct bfad_buf_info) *
					drv_fcxp->num_rsp_sgles));

	/* fcxp send */
	init_completion(&drv_fcxp->comp);
	rc = bfad_fcxp_bsg_send(job, drv_fcxp, bsg_fcpt);
	if (rc == BFA_STATUS_OK) {
		wait_for_completion(&drv_fcxp->comp);
		bsg_fcpt->status = drv_fcxp->req_status;
	} else {
		bsg_fcpt->status = rc;
		goto out_free_mem;
	}

	/* fill the job->reply data */
	if (drv_fcxp->req_status == BFA_STATUS_OK) {
		job->reply_len = drv_fcxp->rsp_len;
		job->reply->reply_payload_rcv_len = drv_fcxp->rsp_len;
		job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
	} else {
		job->reply->reply_payload_rcv_len =
					sizeof(struct fc_bsg_ctels_reply);
		job->reply_len = sizeof(uint32_t);
		job->reply->reply_data.ctels_reply.status =
						FC_CTELS_STATUS_REJECT;
	}

	/* Copy the response data to the reply_payload sg list */
	sg_copy_from_buffer(job->reply_payload.sg_list,
			    job->reply_payload.sg_cnt,
			    (uint8_t *)rsp_buf_info->virt,
			    job->reply_payload.payload_len);

out_free_mem:
	bfad_fcxp_free_mem(bfad, drv_fcxp->rspbuf_info,
			   drv_fcxp->num_rsp_sgles);
	bfad_fcxp_free_mem(bfad, drv_fcxp->reqbuf_info,
			   drv_fcxp->num_req_sgles);
	kfree(req_kbuf);
	kfree(rsp_kbuf);

	/* Need a copy to user op */
	if (copy_to_user(bsg_data->payload, (void *) bsg_fcpt,
			 bsg_data->payload_len))
		rc = -EIO;

	kfree(bsg_fcpt);
	kfree(drv_fcxp);
out:
	job->reply->result = rc;

	if (rc == BFA_STATUS_OK)
		job->job_done(job);

	return rc;
}

int
bfad_im_bsg_request(struct fc_bsg_job *job)
{
	uint32_t rc = BFA_STATUS_OK;

	switch (job->request->msgcode) {
	case FC_BSG_HST_VENDOR:
		/* Process BSG HST Vendor requests */
		rc = bfad_im_bsg_vendor_request(job);
		break;
	case FC_BSG_HST_ELS_NOLOGIN:
	case FC_BSG_RPT_ELS:
	case FC_BSG_HST_CT:
	case FC_BSG_RPT_CT:
		/* Process BSG ELS/CT commands */
		rc = bfad_im_bsg_els_ct_request(job);
		break;
	default:
		job->reply->result = rc = -EINVAL;
		job->reply->reply_payload_rcv_len = 0;
		break;
	}

	return rc;
}

int
bfad_im_bsg_timeout(struct fc_bsg_job *job)
{
	/* Don't complete the BSG job request - return -EAGAIN
	 * to reset bsg job timeout : for ELS/CT pass thru we
	 * already have timer to track the request.
	 */
	return -EAGAIN;
}