diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2011-06-24 23:26:25 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-06-29 18:22:26 -0400 |
commit | 51e569aa1f0c10bd71af05e76e4ba0e42c51e4ab (patch) | |
tree | 65ab17fd7da7c3432c04c45269cbd62ee19198c5 /drivers/scsi/bfa | |
parent | 148d61039c625f3f7e2d0a6ad1efe17f83153e65 (diff) |
[SCSI] bfa: Added support to obtain SFP info.
- Added SFP sub-module to BFA.
- Added interface to collect sfp media info and sfp speed.
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa')
-rw-r--r-- | drivers/scsi/bfa/bfa_core.c | 13 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_defs.h | 266 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.c | 457 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.h | 52 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_modules.h | 1 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.c | 49 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.h | 16 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfi.h | 49 |
8 files changed, 903 insertions, 0 deletions
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index ec9872484711..3ba73faf3713 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c | |||
@@ -122,6 +122,16 @@ bfa_com_cee_attach(struct bfa_s *bfa) | |||
122 | bfa_cee_mem_claim(cee, cee_dma->kva_curp, cee_dma->dma_curp); | 122 | bfa_cee_mem_claim(cee, cee_dma->kva_curp, cee_dma->dma_curp); |
123 | } | 123 | } |
124 | 124 | ||
125 | static void | ||
126 | bfa_com_sfp_attach(struct bfa_s *bfa) | ||
127 | { | ||
128 | struct bfa_sfp_s *sfp = BFA_SFP_MOD(bfa); | ||
129 | struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa); | ||
130 | |||
131 | bfa_sfp_attach(sfp, &bfa->ioc, bfa, bfa->trcmod); | ||
132 | bfa_sfp_memclaim(sfp, sfp_dma->kva_curp, sfp_dma->dma_curp); | ||
133 | } | ||
134 | |||
125 | /* | 135 | /* |
126 | * BFA IOC FC related definitions | 136 | * BFA IOC FC related definitions |
127 | */ | 137 | */ |
@@ -1360,6 +1370,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, | |||
1360 | struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa); | 1370 | struct bfa_mem_dma_s *port_dma = BFA_MEM_PORT_DMA(bfa); |
1361 | struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa); | 1371 | struct bfa_mem_dma_s *ablk_dma = BFA_MEM_ABLK_DMA(bfa); |
1362 | struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa); | 1372 | struct bfa_mem_dma_s *cee_dma = BFA_MEM_CEE_DMA(bfa); |
1373 | struct bfa_mem_dma_s *sfp_dma = BFA_MEM_SFP_DMA(bfa); | ||
1363 | 1374 | ||
1364 | WARN_ON((cfg == NULL) || (meminfo == NULL)); | 1375 | WARN_ON((cfg == NULL) || (meminfo == NULL)); |
1365 | 1376 | ||
@@ -1378,6 +1389,7 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, | |||
1378 | bfa_mem_dma_setup(meminfo, port_dma, bfa_port_meminfo()); | 1389 | bfa_mem_dma_setup(meminfo, port_dma, bfa_port_meminfo()); |
1379 | bfa_mem_dma_setup(meminfo, ablk_dma, bfa_ablk_meminfo()); | 1390 | bfa_mem_dma_setup(meminfo, ablk_dma, bfa_ablk_meminfo()); |
1380 | bfa_mem_dma_setup(meminfo, cee_dma, bfa_cee_meminfo()); | 1391 | bfa_mem_dma_setup(meminfo, cee_dma, bfa_cee_meminfo()); |
1392 | bfa_mem_dma_setup(meminfo, sfp_dma, bfa_sfp_meminfo()); | ||
1381 | } | 1393 | } |
1382 | 1394 | ||
1383 | /* | 1395 | /* |
@@ -1446,6 +1458,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | |||
1446 | bfa_com_port_attach(bfa); | 1458 | bfa_com_port_attach(bfa); |
1447 | bfa_com_ablk_attach(bfa); | 1459 | bfa_com_ablk_attach(bfa); |
1448 | bfa_com_cee_attach(bfa); | 1460 | bfa_com_cee_attach(bfa); |
1461 | bfa_com_sfp_attach(bfa); | ||
1449 | } | 1462 | } |
1450 | 1463 | ||
1451 | /* | 1464 | /* |
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h index bb382656c8c9..715d9f9fe33d 100644 --- a/drivers/scsi/bfa/bfa_defs.h +++ b/drivers/scsi/bfa/bfa_defs.h | |||
@@ -130,6 +130,7 @@ enum bfa_status { | |||
130 | BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists, | 130 | BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists, |
131 | * contact support */ | 131 | * contact support */ |
132 | BFA_STATUS_EPROTOCOL = 6, /* Protocol error */ | 132 | BFA_STATUS_EPROTOCOL = 6, /* Protocol error */ |
133 | BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */ | ||
133 | BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */ | 134 | BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */ |
134 | BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */ | 135 | BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */ |
135 | BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */ | 136 | BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */ |
@@ -150,9 +151,11 @@ enum bfa_status { | |||
150 | BFA_STATUS_DIAG_BUSY = 71, /* diag busy */ | 151 | BFA_STATUS_DIAG_BUSY = 71, /* diag busy */ |
151 | BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */ | 152 | BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */ |
152 | BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */ | 153 | BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */ |
154 | BFA_STATUS_NO_SFP_DEV = 89, /* No SFP device check or replace SFP */ | ||
153 | BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */ | 155 | BFA_STATUS_INVALID_MAC = 134, /* Invalid MAC address */ |
154 | BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot | 156 | BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot |
155 | * configuration */ | 157 | * configuration */ |
158 | BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */ | ||
156 | BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on | 159 | BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on |
157 | * this adapter */ | 160 | * this adapter */ |
158 | BFA_STATUS_TRUNK_DISABLED = 165, /* Trunking is disabled on | 161 | BFA_STATUS_TRUNK_DISABLED = 165, /* Trunking is disabled on |
@@ -559,6 +562,269 @@ struct bfa_ablk_cfg_inst_s { | |||
559 | struct bfa_ablk_cfg_s { | 562 | struct bfa_ablk_cfg_s { |
560 | struct bfa_ablk_cfg_inst_s inst[BFA_ABLK_MAX]; | 563 | struct bfa_ablk_cfg_inst_s inst[BFA_ABLK_MAX]; |
561 | }; | 564 | }; |
565 | |||
566 | |||
567 | /* | ||
568 | * SFP module specific | ||
569 | */ | ||
570 | #define SFP_DIAGMON_SIZE 10 /* num bytes of diag monitor data */ | ||
571 | |||
572 | enum bfa_defs_sfp_media_e { | ||
573 | BFA_SFP_MEDIA_UNKNOWN = 0x00, | ||
574 | BFA_SFP_MEDIA_CU = 0x01, | ||
575 | BFA_SFP_MEDIA_LW = 0x02, | ||
576 | BFA_SFP_MEDIA_SW = 0x03, | ||
577 | BFA_SFP_MEDIA_EL = 0x04, | ||
578 | BFA_SFP_MEDIA_UNSUPPORT = 0x05, | ||
579 | }; | ||
580 | |||
581 | /* | ||
582 | * values for xmtr_tech above | ||
583 | */ | ||
584 | enum { | ||
585 | SFP_XMTR_TECH_CU = (1 << 0), /* copper FC-BaseT */ | ||
586 | SFP_XMTR_TECH_CP = (1 << 1), /* copper passive */ | ||
587 | SFP_XMTR_TECH_CA = (1 << 2), /* copper active */ | ||
588 | SFP_XMTR_TECH_LL = (1 << 3), /* longwave laser */ | ||
589 | SFP_XMTR_TECH_SL = (1 << 4), /* shortwave laser w/ OFC */ | ||
590 | SFP_XMTR_TECH_SN = (1 << 5), /* shortwave laser w/o OFC */ | ||
591 | SFP_XMTR_TECH_EL_INTRA = (1 << 6), /* elec intra-enclosure */ | ||
592 | SFP_XMTR_TECH_EL_INTER = (1 << 7), /* elec inter-enclosure */ | ||
593 | SFP_XMTR_TECH_LC = (1 << 8), /* longwave laser */ | ||
594 | SFP_XMTR_TECH_SA = (1 << 9) | ||
595 | }; | ||
596 | |||
597 | /* | ||
598 | * Serial ID: Data Fields -- Address A0h | ||
599 | * Basic ID field total 64 bytes | ||
600 | */ | ||
601 | struct sfp_srlid_base_s { | ||
602 | u8 id; /* 00: Identifier */ | ||
603 | u8 extid; /* 01: Extended Identifier */ | ||
604 | u8 connector; /* 02: Connector */ | ||
605 | u8 xcvr[8]; /* 03-10: Transceiver */ | ||
606 | u8 encoding; /* 11: Encoding */ | ||
607 | u8 br_norm; /* 12: BR, Nominal */ | ||
608 | u8 rate_id; /* 13: Rate Identifier */ | ||
609 | u8 len_km; /* 14: Length single mode km */ | ||
610 | u8 len_100m; /* 15: Length single mode 100m */ | ||
611 | u8 len_om2; /* 16: Length om2 fiber 10m */ | ||
612 | u8 len_om1; /* 17: Length om1 fiber 10m */ | ||
613 | u8 len_cu; /* 18: Length copper 1m */ | ||
614 | u8 len_om3; /* 19: Length om3 fiber 10m */ | ||
615 | u8 vendor_name[16];/* 20-35 */ | ||
616 | u8 unalloc1; | ||
617 | u8 vendor_oui[3]; /* 37-39 */ | ||
618 | u8 vendor_pn[16]; /* 40-55 */ | ||
619 | u8 vendor_rev[4]; /* 56-59 */ | ||
620 | u8 wavelen[2]; /* 60-61 */ | ||
621 | u8 unalloc2; | ||
622 | u8 cc_base; /* 63: check code for base id field */ | ||
623 | }; | ||
624 | |||
625 | /* | ||
626 | * Serial ID: Data Fields -- Address A0h | ||
627 | * Extended id field total 32 bytes | ||
628 | */ | ||
629 | struct sfp_srlid_ext_s { | ||
630 | u8 options[2]; | ||
631 | u8 br_max; | ||
632 | u8 br_min; | ||
633 | u8 vendor_sn[16]; | ||
634 | u8 date_code[8]; | ||
635 | u8 diag_mon_type; /* 92: Diagnostic Monitoring type */ | ||
636 | u8 en_options; | ||
637 | u8 sff_8472; | ||
638 | u8 cc_ext; | ||
639 | }; | ||
640 | |||
641 | /* | ||
642 | * Diagnostic: Data Fields -- Address A2h | ||
643 | * Diagnostic and control/status base field total 96 bytes | ||
644 | */ | ||
645 | struct sfp_diag_base_s { | ||
646 | /* | ||
647 | * Alarm and warning Thresholds 40 bytes | ||
648 | */ | ||
649 | u8 temp_high_alarm[2]; /* 00-01 */ | ||
650 | u8 temp_low_alarm[2]; /* 02-03 */ | ||
651 | u8 temp_high_warning[2]; /* 04-05 */ | ||
652 | u8 temp_low_warning[2]; /* 06-07 */ | ||
653 | |||
654 | u8 volt_high_alarm[2]; /* 08-09 */ | ||
655 | u8 volt_low_alarm[2]; /* 10-11 */ | ||
656 | u8 volt_high_warning[2]; /* 12-13 */ | ||
657 | u8 volt_low_warning[2]; /* 14-15 */ | ||
658 | |||
659 | u8 bias_high_alarm[2]; /* 16-17 */ | ||
660 | u8 bias_low_alarm[2]; /* 18-19 */ | ||
661 | u8 bias_high_warning[2]; /* 20-21 */ | ||
662 | u8 bias_low_warning[2]; /* 22-23 */ | ||
663 | |||
664 | u8 tx_pwr_high_alarm[2]; /* 24-25 */ | ||
665 | u8 tx_pwr_low_alarm[2]; /* 26-27 */ | ||
666 | u8 tx_pwr_high_warning[2]; /* 28-29 */ | ||
667 | u8 tx_pwr_low_warning[2]; /* 30-31 */ | ||
668 | |||
669 | u8 rx_pwr_high_alarm[2]; /* 32-33 */ | ||
670 | u8 rx_pwr_low_alarm[2]; /* 34-35 */ | ||
671 | u8 rx_pwr_high_warning[2]; /* 36-37 */ | ||
672 | u8 rx_pwr_low_warning[2]; /* 38-39 */ | ||
673 | |||
674 | u8 unallocate_1[16]; | ||
675 | |||
676 | /* | ||
677 | * ext_cal_const[36] | ||
678 | */ | ||
679 | u8 rx_pwr[20]; | ||
680 | u8 tx_i[4]; | ||
681 | u8 tx_pwr[4]; | ||
682 | u8 temp[4]; | ||
683 | u8 volt[4]; | ||
684 | u8 unallocate_2[3]; | ||
685 | u8 cc_dmi; | ||
686 | }; | ||
687 | |||
688 | /* | ||
689 | * Diagnostic: Data Fields -- Address A2h | ||
690 | * Diagnostic and control/status extended field total 24 bytes | ||
691 | */ | ||
692 | struct sfp_diag_ext_s { | ||
693 | u8 diag[SFP_DIAGMON_SIZE]; | ||
694 | u8 unalloc1[4]; | ||
695 | u8 status_ctl; | ||
696 | u8 rsvd; | ||
697 | u8 alarm_flags[2]; | ||
698 | u8 unalloc2[2]; | ||
699 | u8 warning_flags[2]; | ||
700 | u8 ext_status_ctl[2]; | ||
701 | }; | ||
702 | |||
703 | struct sfp_mem_s { | ||
704 | struct sfp_srlid_base_s srlid_base; | ||
705 | struct sfp_srlid_ext_s srlid_ext; | ||
706 | struct sfp_diag_base_s diag_base; | ||
707 | struct sfp_diag_ext_s diag_ext; | ||
708 | }; | ||
709 | |||
710 | /* | ||
711 | * transceiver codes (SFF-8472 Rev 10.2 Table 3.5) | ||
712 | */ | ||
713 | union sfp_xcvr_e10g_code_u { | ||
714 | u8 b; | ||
715 | struct { | ||
716 | #ifdef __BIGENDIAN | ||
717 | u8 e10g_unall:1; /* 10G Ethernet compliance */ | ||
718 | u8 e10g_lrm:1; | ||
719 | u8 e10g_lr:1; | ||
720 | u8 e10g_sr:1; | ||
721 | u8 ib_sx:1; /* Infiniband compliance */ | ||
722 | u8 ib_lx:1; | ||
723 | u8 ib_cu_a:1; | ||
724 | u8 ib_cu_p:1; | ||
725 | #else | ||
726 | u8 ib_cu_p:1; | ||
727 | u8 ib_cu_a:1; | ||
728 | u8 ib_lx:1; | ||
729 | u8 ib_sx:1; /* Infiniband compliance */ | ||
730 | u8 e10g_sr:1; | ||
731 | u8 e10g_lr:1; | ||
732 | u8 e10g_lrm:1; | ||
733 | u8 e10g_unall:1; /* 10G Ethernet compliance */ | ||
734 | #endif | ||
735 | } r; | ||
736 | }; | ||
737 | |||
738 | union sfp_xcvr_so1_code_u { | ||
739 | u8 b; | ||
740 | struct { | ||
741 | u8 escon:2; /* ESCON compliance code */ | ||
742 | u8 oc192_reach:1; /* SONET compliance code */ | ||
743 | u8 so_reach:2; | ||
744 | u8 oc48_reach:3; | ||
745 | } r; | ||
746 | }; | ||
747 | |||
748 | union sfp_xcvr_so2_code_u { | ||
749 | u8 b; | ||
750 | struct { | ||
751 | u8 reserved:1; | ||
752 | u8 oc12_reach:3; /* OC12 reach */ | ||
753 | u8 reserved1:1; | ||
754 | u8 oc3_reach:3; /* OC3 reach */ | ||
755 | } r; | ||
756 | }; | ||
757 | |||
758 | union sfp_xcvr_eth_code_u { | ||
759 | u8 b; | ||
760 | struct { | ||
761 | u8 base_px:1; | ||
762 | u8 base_bx10:1; | ||
763 | u8 e100base_fx:1; | ||
764 | u8 e100base_lx:1; | ||
765 | u8 e1000base_t:1; | ||
766 | u8 e1000base_cx:1; | ||
767 | u8 e1000base_lx:1; | ||
768 | u8 e1000base_sx:1; | ||
769 | } r; | ||
770 | }; | ||
771 | |||
772 | struct sfp_xcvr_fc1_code_s { | ||
773 | u8 link_len:5; /* FC link length */ | ||
774 | u8 xmtr_tech2:3; | ||
775 | u8 xmtr_tech1:7; /* FC transmitter technology */ | ||
776 | u8 reserved1:1; | ||
777 | }; | ||
778 | |||
779 | union sfp_xcvr_fc2_code_u { | ||
780 | u8 b; | ||
781 | struct { | ||
782 | u8 tw_media:1; /* twin axial pair (tw) */ | ||
783 | u8 tp_media:1; /* shielded twisted pair (sp) */ | ||
784 | u8 mi_media:1; /* miniature coax (mi) */ | ||
785 | u8 tv_media:1; /* video coax (tv) */ | ||
786 | u8 m6_media:1; /* multimode, 62.5m (m6) */ | ||
787 | u8 m5_media:1; /* multimode, 50m (m5) */ | ||
788 | u8 reserved:1; | ||
789 | u8 sm_media:1; /* single mode (sm) */ | ||
790 | } r; | ||
791 | }; | ||
792 | |||
793 | union sfp_xcvr_fc3_code_u { | ||
794 | u8 b; | ||
795 | struct { | ||
796 | #ifdef __BIGENDIAN | ||
797 | u8 rsv4:1; | ||
798 | u8 mb800:1; /* 800 Mbytes/sec */ | ||
799 | u8 mb1600:1; /* 1600 Mbytes/sec */ | ||
800 | u8 mb400:1; /* 400 Mbytes/sec */ | ||
801 | u8 rsv2:1; | ||
802 | u8 mb200:1; /* 200 Mbytes/sec */ | ||
803 | u8 rsv1:1; | ||
804 | u8 mb100:1; /* 100 Mbytes/sec */ | ||
805 | #else | ||
806 | u8 mb100:1; /* 100 Mbytes/sec */ | ||
807 | u8 rsv1:1; | ||
808 | u8 mb200:1; /* 200 Mbytes/sec */ | ||
809 | u8 rsv2:1; | ||
810 | u8 mb400:1; /* 400 Mbytes/sec */ | ||
811 | u8 mb1600:1; /* 1600 Mbytes/sec */ | ||
812 | u8 mb800:1; /* 800 Mbytes/sec */ | ||
813 | u8 rsv4:1; | ||
814 | #endif | ||
815 | } r; | ||
816 | }; | ||
817 | |||
818 | struct sfp_xcvr_s { | ||
819 | union sfp_xcvr_e10g_code_u e10g; | ||
820 | union sfp_xcvr_so1_code_u so1; | ||
821 | union sfp_xcvr_so2_code_u so2; | ||
822 | union sfp_xcvr_eth_code_u eth; | ||
823 | struct sfp_xcvr_fc1_code_s fc1; | ||
824 | union sfp_xcvr_fc2_code_u fc2; | ||
825 | union sfp_xcvr_fc3_code_u fc3; | ||
826 | }; | ||
827 | |||
562 | #pragma pack() | 828 | #pragma pack() |
563 | 829 | ||
564 | #endif /* __BFA_DEFS_H__ */ | 830 | #endif /* __BFA_DEFS_H__ */ |
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index bfe3a87c0b6f..d579036b08b7 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
@@ -3364,3 +3364,460 @@ bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg) | |||
3364 | 3364 | ||
3365 | return BFA_STATUS_OK; | 3365 | return BFA_STATUS_OK; |
3366 | } | 3366 | } |
3367 | |||
3368 | /* | ||
3369 | * SFP module specific | ||
3370 | */ | ||
3371 | |||
3372 | /* forward declarations */ | ||
3373 | static void bfa_sfp_getdata_send(struct bfa_sfp_s *sfp); | ||
3374 | static void bfa_sfp_media_get(struct bfa_sfp_s *sfp); | ||
3375 | static bfa_status_t bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, | ||
3376 | enum bfa_port_speed portspeed); | ||
3377 | |||
3378 | static void | ||
3379 | bfa_cb_sfp_show(struct bfa_sfp_s *sfp) | ||
3380 | { | ||
3381 | bfa_trc(sfp, sfp->lock); | ||
3382 | if (sfp->cbfn) | ||
3383 | sfp->cbfn(sfp->cbarg, sfp->status); | ||
3384 | sfp->lock = 0; | ||
3385 | sfp->cbfn = NULL; | ||
3386 | } | ||
3387 | |||
3388 | static void | ||
3389 | bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp) | ||
3390 | { | ||
3391 | bfa_trc(sfp, sfp->portspeed); | ||
3392 | if (sfp->media) { | ||
3393 | bfa_sfp_media_get(sfp); | ||
3394 | if (sfp->state_query_cbfn) | ||
3395 | sfp->state_query_cbfn(sfp->state_query_cbarg, | ||
3396 | sfp->status); | ||
3397 | sfp->media = NULL; | ||
3398 | } | ||
3399 | |||
3400 | if (sfp->portspeed) { | ||
3401 | sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed); | ||
3402 | if (sfp->state_query_cbfn) | ||
3403 | sfp->state_query_cbfn(sfp->state_query_cbarg, | ||
3404 | sfp->status); | ||
3405 | sfp->portspeed = BFA_PORT_SPEED_UNKNOWN; | ||
3406 | } | ||
3407 | |||
3408 | sfp->state_query_lock = 0; | ||
3409 | sfp->state_query_cbfn = NULL; | ||
3410 | } | ||
3411 | |||
3412 | /* | ||
3413 | * IOC event handler. | ||
3414 | */ | ||
3415 | static void | ||
3416 | bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event) | ||
3417 | { | ||
3418 | struct bfa_sfp_s *sfp = sfp_arg; | ||
3419 | |||
3420 | bfa_trc(sfp, event); | ||
3421 | bfa_trc(sfp, sfp->lock); | ||
3422 | bfa_trc(sfp, sfp->state_query_lock); | ||
3423 | |||
3424 | switch (event) { | ||
3425 | case BFA_IOC_E_DISABLED: | ||
3426 | case BFA_IOC_E_FAILED: | ||
3427 | if (sfp->lock) { | ||
3428 | sfp->status = BFA_STATUS_IOC_FAILURE; | ||
3429 | bfa_cb_sfp_show(sfp); | ||
3430 | } | ||
3431 | |||
3432 | if (sfp->state_query_lock) { | ||
3433 | sfp->status = BFA_STATUS_IOC_FAILURE; | ||
3434 | bfa_cb_sfp_state_query(sfp); | ||
3435 | } | ||
3436 | break; | ||
3437 | |||
3438 | default: | ||
3439 | break; | ||
3440 | } | ||
3441 | } | ||
3442 | |||
3443 | /* | ||
3444 | * SFP get data send | ||
3445 | */ | ||
3446 | static void | ||
3447 | bfa_sfp_getdata_send(struct bfa_sfp_s *sfp) | ||
3448 | { | ||
3449 | struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg; | ||
3450 | |||
3451 | bfa_trc(sfp, req->memtype); | ||
3452 | |||
3453 | /* build host command */ | ||
3454 | bfi_h2i_set(req->mh, BFI_MC_SFP, BFI_SFP_H2I_SHOW, | ||
3455 | bfa_ioc_portid(sfp->ioc)); | ||
3456 | |||
3457 | /* send mbox cmd */ | ||
3458 | bfa_ioc_mbox_queue(sfp->ioc, &sfp->mbcmd); | ||
3459 | } | ||
3460 | |||
3461 | /* | ||
3462 | * SFP is valid, read sfp data | ||
3463 | */ | ||
3464 | static void | ||
3465 | bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype) | ||
3466 | { | ||
3467 | struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg; | ||
3468 | |||
3469 | WARN_ON(sfp->lock != 0); | ||
3470 | bfa_trc(sfp, sfp->state); | ||
3471 | |||
3472 | sfp->lock = 1; | ||
3473 | sfp->memtype = memtype; | ||
3474 | req->memtype = memtype; | ||
3475 | |||
3476 | /* Setup SG list */ | ||
3477 | bfa_alen_set(&req->alen, sizeof(struct sfp_mem_s), sfp->dbuf_pa); | ||
3478 | |||
3479 | bfa_sfp_getdata_send(sfp); | ||
3480 | } | ||
3481 | |||
3482 | /* | ||
3483 | * SFP show complete | ||
3484 | */ | ||
3485 | static void | ||
3486 | bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg) | ||
3487 | { | ||
3488 | struct bfi_sfp_rsp_s *rsp = (struct bfi_sfp_rsp_s *) msg; | ||
3489 | |||
3490 | if (!sfp->lock) { | ||
3491 | /* | ||
3492 | * receiving response after ioc failure | ||
3493 | */ | ||
3494 | bfa_trc(sfp, sfp->lock); | ||
3495 | return; | ||
3496 | } | ||
3497 | |||
3498 | bfa_trc(sfp, rsp->status); | ||
3499 | if (rsp->status == BFA_STATUS_OK) { | ||
3500 | sfp->data_valid = 1; | ||
3501 | if (sfp->state == BFA_SFP_STATE_VALID) | ||
3502 | sfp->status = BFA_STATUS_OK; | ||
3503 | else if (sfp->state == BFA_SFP_STATE_UNSUPPORT) | ||
3504 | sfp->status = BFA_STATUS_SFP_UNSUPP; | ||
3505 | else | ||
3506 | bfa_trc(sfp, sfp->state); | ||
3507 | } else { | ||
3508 | sfp->data_valid = 0; | ||
3509 | sfp->status = rsp->status; | ||
3510 | /* sfpshow shouldn't change sfp state */ | ||
3511 | } | ||
3512 | |||
3513 | bfa_trc(sfp, sfp->memtype); | ||
3514 | if (sfp->memtype == BFI_SFP_MEM_DIAGEXT) { | ||
3515 | bfa_trc(sfp, sfp->data_valid); | ||
3516 | if (sfp->data_valid) { | ||
3517 | u32 size = sizeof(struct sfp_mem_s); | ||
3518 | u8 *des = (u8 *) &(sfp->sfpmem->srlid_base); | ||
3519 | memcpy(des, sfp->dbuf_kva, size); | ||
3520 | } | ||
3521 | /* | ||
3522 | * Queue completion callback. | ||
3523 | */ | ||
3524 | bfa_cb_sfp_show(sfp); | ||
3525 | } else | ||
3526 | sfp->lock = 0; | ||
3527 | |||
3528 | bfa_trc(sfp, sfp->state_query_lock); | ||
3529 | if (sfp->state_query_lock) { | ||
3530 | sfp->state = rsp->state; | ||
3531 | /* Complete callback */ | ||
3532 | bfa_cb_sfp_state_query(sfp); | ||
3533 | } | ||
3534 | } | ||
3535 | |||
3536 | /* | ||
3537 | * SFP query fw sfp state | ||
3538 | */ | ||
3539 | static void | ||
3540 | bfa_sfp_state_query(struct bfa_sfp_s *sfp) | ||
3541 | { | ||
3542 | struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg; | ||
3543 | |||
3544 | /* Should not be doing query if not in _INIT state */ | ||
3545 | WARN_ON(sfp->state != BFA_SFP_STATE_INIT); | ||
3546 | WARN_ON(sfp->state_query_lock != 0); | ||
3547 | bfa_trc(sfp, sfp->state); | ||
3548 | |||
3549 | sfp->state_query_lock = 1; | ||
3550 | req->memtype = 0; | ||
3551 | |||
3552 | if (!sfp->lock) | ||
3553 | bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL); | ||
3554 | } | ||
3555 | |||
3556 | static void | ||
3557 | bfa_sfp_media_get(struct bfa_sfp_s *sfp) | ||
3558 | { | ||
3559 | enum bfa_defs_sfp_media_e *media = sfp->media; | ||
3560 | |||
3561 | *media = BFA_SFP_MEDIA_UNKNOWN; | ||
3562 | |||
3563 | if (sfp->state == BFA_SFP_STATE_UNSUPPORT) | ||
3564 | *media = BFA_SFP_MEDIA_UNSUPPORT; | ||
3565 | else if (sfp->state == BFA_SFP_STATE_VALID) { | ||
3566 | union sfp_xcvr_e10g_code_u e10g; | ||
3567 | struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva; | ||
3568 | u16 xmtr_tech = (sfpmem->srlid_base.xcvr[4] & 0x3) << 7 | | ||
3569 | (sfpmem->srlid_base.xcvr[5] >> 1); | ||
3570 | |||
3571 | e10g.b = sfpmem->srlid_base.xcvr[0]; | ||
3572 | bfa_trc(sfp, e10g.b); | ||
3573 | bfa_trc(sfp, xmtr_tech); | ||
3574 | /* check fc transmitter tech */ | ||
3575 | if ((xmtr_tech & SFP_XMTR_TECH_CU) || | ||
3576 | (xmtr_tech & SFP_XMTR_TECH_CP) || | ||
3577 | (xmtr_tech & SFP_XMTR_TECH_CA)) | ||
3578 | *media = BFA_SFP_MEDIA_CU; | ||
3579 | else if ((xmtr_tech & SFP_XMTR_TECH_EL_INTRA) || | ||
3580 | (xmtr_tech & SFP_XMTR_TECH_EL_INTER)) | ||
3581 | *media = BFA_SFP_MEDIA_EL; | ||
3582 | else if ((xmtr_tech & SFP_XMTR_TECH_LL) || | ||
3583 | (xmtr_tech & SFP_XMTR_TECH_LC)) | ||
3584 | *media = BFA_SFP_MEDIA_LW; | ||
3585 | else if ((xmtr_tech & SFP_XMTR_TECH_SL) || | ||
3586 | (xmtr_tech & SFP_XMTR_TECH_SN) || | ||
3587 | (xmtr_tech & SFP_XMTR_TECH_SA)) | ||
3588 | *media = BFA_SFP_MEDIA_SW; | ||
3589 | /* Check 10G Ethernet Compilance code */ | ||
3590 | else if (e10g.b & 0x10) | ||
3591 | *media = BFA_SFP_MEDIA_SW; | ||
3592 | else if (e10g.b & 0x60) | ||
3593 | *media = BFA_SFP_MEDIA_LW; | ||
3594 | else if (e10g.r.e10g_unall & 0x80) | ||
3595 | *media = BFA_SFP_MEDIA_UNKNOWN; | ||
3596 | else | ||
3597 | bfa_trc(sfp, 0); | ||
3598 | } else | ||
3599 | bfa_trc(sfp, sfp->state); | ||
3600 | } | ||
3601 | |||
3602 | static bfa_status_t | ||
3603 | bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed) | ||
3604 | { | ||
3605 | struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva; | ||
3606 | struct sfp_xcvr_s *xcvr = (struct sfp_xcvr_s *) sfpmem->srlid_base.xcvr; | ||
3607 | union sfp_xcvr_fc3_code_u fc3 = xcvr->fc3; | ||
3608 | union sfp_xcvr_e10g_code_u e10g = xcvr->e10g; | ||
3609 | |||
3610 | if (portspeed == BFA_PORT_SPEED_10GBPS) { | ||
3611 | if (e10g.r.e10g_sr || e10g.r.e10g_lr) | ||
3612 | return BFA_STATUS_OK; | ||
3613 | else { | ||
3614 | bfa_trc(sfp, e10g.b); | ||
3615 | return BFA_STATUS_UNSUPP_SPEED; | ||
3616 | } | ||
3617 | } | ||
3618 | if (((portspeed & BFA_PORT_SPEED_16GBPS) && fc3.r.mb1600) || | ||
3619 | ((portspeed & BFA_PORT_SPEED_8GBPS) && fc3.r.mb800) || | ||
3620 | ((portspeed & BFA_PORT_SPEED_4GBPS) && fc3.r.mb400) || | ||
3621 | ((portspeed & BFA_PORT_SPEED_2GBPS) && fc3.r.mb200) || | ||
3622 | ((portspeed & BFA_PORT_SPEED_1GBPS) && fc3.r.mb100)) | ||
3623 | return BFA_STATUS_OK; | ||
3624 | else { | ||
3625 | bfa_trc(sfp, portspeed); | ||
3626 | bfa_trc(sfp, fc3.b); | ||
3627 | bfa_trc(sfp, e10g.b); | ||
3628 | return BFA_STATUS_UNSUPP_SPEED; | ||
3629 | } | ||
3630 | } | ||
3631 | |||
3632 | /* | ||
3633 | * SFP hmbox handler | ||
3634 | */ | ||
3635 | void | ||
3636 | bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg) | ||
3637 | { | ||
3638 | struct bfa_sfp_s *sfp = sfparg; | ||
3639 | |||
3640 | switch (msg->mh.msg_id) { | ||
3641 | case BFI_SFP_I2H_SHOW: | ||
3642 | bfa_sfp_show_comp(sfp, msg); | ||
3643 | break; | ||
3644 | |||
3645 | case BFI_SFP_I2H_SCN: | ||
3646 | bfa_trc(sfp, msg->mh.msg_id); | ||
3647 | break; | ||
3648 | |||
3649 | default: | ||
3650 | bfa_trc(sfp, msg->mh.msg_id); | ||
3651 | WARN_ON(1); | ||
3652 | } | ||
3653 | } | ||
3654 | |||
3655 | /* | ||
3656 | * Return DMA memory needed by sfp module. | ||
3657 | */ | ||
3658 | u32 | ||
3659 | bfa_sfp_meminfo(void) | ||
3660 | { | ||
3661 | return BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ); | ||
3662 | } | ||
3663 | |||
3664 | /* | ||
3665 | * Attach virtual and physical memory for SFP. | ||
3666 | */ | ||
3667 | void | ||
3668 | bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, void *dev, | ||
3669 | struct bfa_trc_mod_s *trcmod) | ||
3670 | { | ||
3671 | sfp->dev = dev; | ||
3672 | sfp->ioc = ioc; | ||
3673 | sfp->trcmod = trcmod; | ||
3674 | |||
3675 | sfp->cbfn = NULL; | ||
3676 | sfp->cbarg = NULL; | ||
3677 | sfp->sfpmem = NULL; | ||
3678 | sfp->lock = 0; | ||
3679 | sfp->data_valid = 0; | ||
3680 | sfp->state = BFA_SFP_STATE_INIT; | ||
3681 | sfp->state_query_lock = 0; | ||
3682 | sfp->state_query_cbfn = NULL; | ||
3683 | sfp->state_query_cbarg = NULL; | ||
3684 | sfp->media = NULL; | ||
3685 | sfp->portspeed = BFA_PORT_SPEED_UNKNOWN; | ||
3686 | sfp->is_elb = BFA_FALSE; | ||
3687 | |||
3688 | bfa_ioc_mbox_regisr(sfp->ioc, BFI_MC_SFP, bfa_sfp_intr, sfp); | ||
3689 | bfa_q_qe_init(&sfp->ioc_notify); | ||
3690 | bfa_ioc_notify_init(&sfp->ioc_notify, bfa_sfp_notify, sfp); | ||
3691 | list_add_tail(&sfp->ioc_notify.qe, &sfp->ioc->notify_q); | ||
3692 | } | ||
3693 | |||
3694 | /* | ||
3695 | * Claim Memory for SFP | ||
3696 | */ | ||
3697 | void | ||
3698 | bfa_sfp_memclaim(struct bfa_sfp_s *sfp, u8 *dm_kva, u64 dm_pa) | ||
3699 | { | ||
3700 | sfp->dbuf_kva = dm_kva; | ||
3701 | sfp->dbuf_pa = dm_pa; | ||
3702 | memset(sfp->dbuf_kva, 0, sizeof(struct sfp_mem_s)); | ||
3703 | |||
3704 | dm_kva += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ); | ||
3705 | dm_pa += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ); | ||
3706 | } | ||
3707 | |||
3708 | /* | ||
3709 | * Show SFP eeprom content | ||
3710 | * | ||
3711 | * @param[in] sfp - bfa sfp module | ||
3712 | * | ||
3713 | * @param[out] sfpmem - sfp eeprom data | ||
3714 | * | ||
3715 | */ | ||
3716 | bfa_status_t | ||
3717 | bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem, | ||
3718 | bfa_cb_sfp_t cbfn, void *cbarg) | ||
3719 | { | ||
3720 | |||
3721 | if (!bfa_ioc_is_operational(sfp->ioc)) { | ||
3722 | bfa_trc(sfp, 0); | ||
3723 | return BFA_STATUS_IOC_NON_OP; | ||
3724 | } | ||
3725 | |||
3726 | if (sfp->lock) { | ||
3727 | bfa_trc(sfp, 0); | ||
3728 | return BFA_STATUS_DEVBUSY; | ||
3729 | } | ||
3730 | |||
3731 | sfp->cbfn = cbfn; | ||
3732 | sfp->cbarg = cbarg; | ||
3733 | sfp->sfpmem = sfpmem; | ||
3734 | |||
3735 | bfa_sfp_getdata(sfp, BFI_SFP_MEM_DIAGEXT); | ||
3736 | return BFA_STATUS_OK; | ||
3737 | } | ||
3738 | |||
3739 | /* | ||
3740 | * Return SFP Media type | ||
3741 | * | ||
3742 | * @param[in] sfp - bfa sfp module | ||
3743 | * | ||
3744 | * @param[out] media - port speed from user | ||
3745 | * | ||
3746 | */ | ||
3747 | bfa_status_t | ||
3748 | bfa_sfp_media(struct bfa_sfp_s *sfp, enum bfa_defs_sfp_media_e *media, | ||
3749 | bfa_cb_sfp_t cbfn, void *cbarg) | ||
3750 | { | ||
3751 | if (!bfa_ioc_is_operational(sfp->ioc)) { | ||
3752 | bfa_trc(sfp, 0); | ||
3753 | return BFA_STATUS_IOC_NON_OP; | ||
3754 | } | ||
3755 | |||
3756 | sfp->media = media; | ||
3757 | if (sfp->state == BFA_SFP_STATE_INIT) { | ||
3758 | if (sfp->state_query_lock) { | ||
3759 | bfa_trc(sfp, 0); | ||
3760 | return BFA_STATUS_DEVBUSY; | ||
3761 | } else { | ||
3762 | sfp->state_query_cbfn = cbfn; | ||
3763 | sfp->state_query_cbarg = cbarg; | ||
3764 | bfa_sfp_state_query(sfp); | ||
3765 | return BFA_STATUS_SFP_NOT_READY; | ||
3766 | } | ||
3767 | } | ||
3768 | |||
3769 | bfa_sfp_media_get(sfp); | ||
3770 | return BFA_STATUS_OK; | ||
3771 | } | ||
3772 | |||
3773 | /* | ||
3774 | * Check if user set port speed is allowed by the SFP | ||
3775 | * | ||
3776 | * @param[in] sfp - bfa sfp module | ||
3777 | * @param[in] portspeed - port speed from user | ||
3778 | * | ||
3779 | */ | ||
3780 | bfa_status_t | ||
3781 | bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed, | ||
3782 | bfa_cb_sfp_t cbfn, void *cbarg) | ||
3783 | { | ||
3784 | WARN_ON(portspeed == BFA_PORT_SPEED_UNKNOWN); | ||
3785 | |||
3786 | if (!bfa_ioc_is_operational(sfp->ioc)) | ||
3787 | return BFA_STATUS_IOC_NON_OP; | ||
3788 | |||
3789 | /* For Mezz card, all speed is allowed */ | ||
3790 | if (bfa_mfg_is_mezz(sfp->ioc->attr->card_type)) | ||
3791 | return BFA_STATUS_OK; | ||
3792 | |||
3793 | /* Check SFP state */ | ||
3794 | sfp->portspeed = portspeed; | ||
3795 | if (sfp->state == BFA_SFP_STATE_INIT) { | ||
3796 | if (sfp->state_query_lock) { | ||
3797 | bfa_trc(sfp, 0); | ||
3798 | return BFA_STATUS_DEVBUSY; | ||
3799 | } else { | ||
3800 | sfp->state_query_cbfn = cbfn; | ||
3801 | sfp->state_query_cbarg = cbarg; | ||
3802 | bfa_sfp_state_query(sfp); | ||
3803 | return BFA_STATUS_SFP_NOT_READY; | ||
3804 | } | ||
3805 | } | ||
3806 | |||
3807 | if (sfp->state == BFA_SFP_STATE_REMOVED || | ||
3808 | sfp->state == BFA_SFP_STATE_FAILED) { | ||
3809 | bfa_trc(sfp, sfp->state); | ||
3810 | return BFA_STATUS_NO_SFP_DEV; | ||
3811 | } | ||
3812 | |||
3813 | if (sfp->state == BFA_SFP_STATE_INSERTED) { | ||
3814 | bfa_trc(sfp, sfp->state); | ||
3815 | return BFA_STATUS_DEVBUSY; /* sfp is reading data */ | ||
3816 | } | ||
3817 | |||
3818 | /* For eloopback, all speed is allowed */ | ||
3819 | if (sfp->is_elb) | ||
3820 | return BFA_STATUS_OK; | ||
3821 | |||
3822 | return bfa_sfp_speed_valid(sfp, portspeed); | ||
3823 | } | ||
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 83c3f2fc3411..1d51164faa81 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h | |||
@@ -367,6 +367,58 @@ struct bfa_ablk_s { | |||
367 | }; | 367 | }; |
368 | #define BFA_MEM_ABLK_DMA(__bfa) (&((__bfa)->modules.ablk.ablk_dma)) | 368 | #define BFA_MEM_ABLK_DMA(__bfa) (&((__bfa)->modules.ablk.ablk_dma)) |
369 | 369 | ||
370 | /* | ||
371 | * SFP module specific | ||
372 | */ | ||
373 | typedef void (*bfa_cb_sfp_t) (void *cbarg, bfa_status_t status); | ||
374 | |||
375 | struct bfa_sfp_s { | ||
376 | void *dev; | ||
377 | struct bfa_ioc_s *ioc; | ||
378 | struct bfa_trc_mod_s *trcmod; | ||
379 | struct sfp_mem_s *sfpmem; | ||
380 | bfa_cb_sfp_t cbfn; | ||
381 | void *cbarg; | ||
382 | enum bfi_sfp_mem_e memtype; /* mem access type */ | ||
383 | u32 status; | ||
384 | struct bfa_mbox_cmd_s mbcmd; | ||
385 | u8 *dbuf_kva; /* dma buf virtual address */ | ||
386 | u64 dbuf_pa; /* dma buf physical address */ | ||
387 | struct bfa_ioc_notify_s ioc_notify; | ||
388 | enum bfa_defs_sfp_media_e *media; | ||
389 | enum bfa_port_speed portspeed; | ||
390 | bfa_cb_sfp_t state_query_cbfn; | ||
391 | void *state_query_cbarg; | ||
392 | u8 lock; | ||
393 | u8 data_valid; /* data in dbuf is valid */ | ||
394 | u8 state; /* sfp state */ | ||
395 | u8 state_query_lock; | ||
396 | struct bfa_mem_dma_s sfp_dma; | ||
397 | u8 is_elb; /* eloopback */ | ||
398 | }; | ||
399 | |||
400 | #define BFA_SFP_MOD(__bfa) (&(__bfa)->modules.sfp) | ||
401 | #define BFA_MEM_SFP_DMA(__bfa) (&(BFA_SFP_MOD(__bfa)->sfp_dma)) | ||
402 | |||
403 | u32 bfa_sfp_meminfo(void); | ||
404 | |||
405 | void bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, | ||
406 | void *dev, struct bfa_trc_mod_s *trcmod); | ||
407 | |||
408 | void bfa_sfp_memclaim(struct bfa_sfp_s *diag, u8 *dm_kva, u64 dm_pa); | ||
409 | void bfa_sfp_intr(void *bfaarg, struct bfi_mbmsg_s *msg); | ||
410 | |||
411 | bfa_status_t bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem, | ||
412 | bfa_cb_sfp_t cbfn, void *cbarg); | ||
413 | |||
414 | bfa_status_t bfa_sfp_media(struct bfa_sfp_s *sfp, | ||
415 | enum bfa_defs_sfp_media_e *media, | ||
416 | bfa_cb_sfp_t cbfn, void *cbarg); | ||
417 | |||
418 | bfa_status_t bfa_sfp_speed(struct bfa_sfp_s *sfp, | ||
419 | enum bfa_port_speed portspeed, | ||
420 | bfa_cb_sfp_t cbfn, void *cbarg); | ||
421 | |||
370 | #define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func) | 422 | #define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func) |
371 | #define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id) | 423 | #define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id) |
372 | #define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva) | 424 | #define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva) |
diff --git a/drivers/scsi/bfa/bfa_modules.h b/drivers/scsi/bfa/bfa_modules.h index 239aba711226..d8ea708db9b7 100644 --- a/drivers/scsi/bfa/bfa_modules.h +++ b/drivers/scsi/bfa/bfa_modules.h | |||
@@ -39,6 +39,7 @@ struct bfa_modules_s { | |||
39 | struct bfa_port_s port; /* Physical port module */ | 39 | struct bfa_port_s port; /* Physical port module */ |
40 | struct bfa_ablk_s ablk; /* ASIC block config module */ | 40 | struct bfa_ablk_s ablk; /* ASIC block config module */ |
41 | struct bfa_cee_s cee; /* CEE Module */ | 41 | struct bfa_cee_s cee; /* CEE Module */ |
42 | struct bfa_sfp_s sfp; /* SFP module */ | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | /* | 45 | /* |
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index fcfe0ae7fd31..e4409e57e3a9 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c | |||
@@ -1066,6 +1066,49 @@ bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd) | |||
1066 | return 0; | 1066 | return 0; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | int | ||
1070 | bfad_iocmd_sfp_media(struct bfad_s *bfad, void *cmd) | ||
1071 | { | ||
1072 | struct bfa_bsg_sfp_media_s *iocmd = (struct bfa_bsg_sfp_media_s *)cmd; | ||
1073 | struct bfad_hal_comp fcomp; | ||
1074 | unsigned long flags; | ||
1075 | |||
1076 | init_completion(&fcomp.comp); | ||
1077 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1078 | iocmd->status = bfa_sfp_media(BFA_SFP_MOD(&bfad->bfa), &iocmd->media, | ||
1079 | bfad_hcb_comp, &fcomp); | ||
1080 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1081 | bfa_trc(bfad, iocmd->status); | ||
1082 | if (iocmd->status != BFA_STATUS_SFP_NOT_READY) | ||
1083 | goto out; | ||
1084 | |||
1085 | wait_for_completion(&fcomp.comp); | ||
1086 | iocmd->status = fcomp.status; | ||
1087 | out: | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | int | ||
1092 | bfad_iocmd_sfp_speed(struct bfad_s *bfad, void *cmd) | ||
1093 | { | ||
1094 | struct bfa_bsg_sfp_speed_s *iocmd = (struct bfa_bsg_sfp_speed_s *)cmd; | ||
1095 | struct bfad_hal_comp fcomp; | ||
1096 | unsigned long flags; | ||
1097 | |||
1098 | init_completion(&fcomp.comp); | ||
1099 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1100 | iocmd->status = bfa_sfp_speed(BFA_SFP_MOD(&bfad->bfa), iocmd->speed, | ||
1101 | bfad_hcb_comp, &fcomp); | ||
1102 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1103 | bfa_trc(bfad, iocmd->status); | ||
1104 | if (iocmd->status != BFA_STATUS_SFP_NOT_READY) | ||
1105 | goto out; | ||
1106 | wait_for_completion(&fcomp.comp); | ||
1107 | iocmd->status = fcomp.status; | ||
1108 | out: | ||
1109 | return 0; | ||
1110 | } | ||
1111 | |||
1069 | static int | 1112 | static int |
1070 | bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, | 1113 | bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, |
1071 | unsigned int payload_len) | 1114 | unsigned int payload_len) |
@@ -1194,6 +1237,12 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd, | |||
1194 | case IOCMD_CEE_RESET_STATS: | 1237 | case IOCMD_CEE_RESET_STATS: |
1195 | rc = bfad_iocmd_cee_reset_stats(bfad, iocmd); | 1238 | rc = bfad_iocmd_cee_reset_stats(bfad, iocmd); |
1196 | break; | 1239 | break; |
1240 | case IOCMD_SFP_MEDIA: | ||
1241 | rc = bfad_iocmd_sfp_media(bfad, iocmd); | ||
1242 | break; | ||
1243 | case IOCMD_SFP_SPEED: | ||
1244 | rc = bfad_iocmd_sfp_speed(bfad, iocmd); | ||
1245 | break; | ||
1197 | default: | 1246 | default: |
1198 | rc = EINVAL; | 1247 | rc = EINVAL; |
1199 | break; | 1248 | break; |
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h index 5b4599ad8fb9..faafd35f88ae 100644 --- a/drivers/scsi/bfa/bfad_bsg.h +++ b/drivers/scsi/bfa/bfad_bsg.h | |||
@@ -65,6 +65,8 @@ enum { | |||
65 | IOCMD_CEE_GET_ATTR, | 65 | IOCMD_CEE_GET_ATTR, |
66 | IOCMD_CEE_GET_STATS, | 66 | IOCMD_CEE_GET_STATS, |
67 | IOCMD_CEE_RESET_STATS, | 67 | IOCMD_CEE_RESET_STATS, |
68 | IOCMD_SFP_MEDIA, | ||
69 | IOCMD_SFP_SPEED, | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | struct bfa_bsg_gen_s { | 72 | struct bfa_bsg_gen_s { |
@@ -320,6 +322,20 @@ struct bfa_bsg_cee_stats_s { | |||
320 | u64 buf_ptr; | 322 | u64 buf_ptr; |
321 | }; | 323 | }; |
322 | 324 | ||
325 | struct bfa_bsg_sfp_media_s { | ||
326 | bfa_status_t status; | ||
327 | u16 bfad_num; | ||
328 | u16 rsvd; | ||
329 | enum bfa_defs_sfp_media_e media; | ||
330 | }; | ||
331 | |||
332 | struct bfa_bsg_sfp_speed_s { | ||
333 | bfa_status_t status; | ||
334 | u16 bfad_num; | ||
335 | u16 rsvd; | ||
336 | enum bfa_port_speed speed; | ||
337 | }; | ||
338 | |||
323 | struct bfa_bsg_fcpt_s { | 339 | struct bfa_bsg_fcpt_s { |
324 | bfa_status_t status; | 340 | bfa_status_t status; |
325 | u16 vf_id; | 341 | u16 vf_id; |
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h index 037b377668c2..0d249984fd08 100644 --- a/drivers/scsi/bfa/bfi.h +++ b/drivers/scsi/bfa/bfi.h | |||
@@ -206,6 +206,7 @@ enum bfi_mclass { | |||
206 | BFI_MC_IOIM_IOCOM = 17, /* good IO completion */ | 206 | BFI_MC_IOIM_IOCOM = 17, /* good IO completion */ |
207 | BFI_MC_TSKIM = 18, /* Initiator Task management */ | 207 | BFI_MC_TSKIM = 18, /* Initiator Task management */ |
208 | BFI_MC_PORT = 21, /* Physical port */ | 208 | BFI_MC_PORT = 21, /* Physical port */ |
209 | BFI_MC_SFP = 22, /* SFP module */ | ||
209 | BFI_MC_MAX = 32 | 210 | BFI_MC_MAX = 32 |
210 | }; | 211 | }; |
211 | 212 | ||
@@ -765,6 +766,54 @@ union bfi_cee_i2h_msg_u { | |||
765 | struct bfi_cee_stats_rsp_s stats_rsp; | 766 | struct bfi_cee_stats_rsp_s stats_rsp; |
766 | }; | 767 | }; |
767 | 768 | ||
769 | /* | ||
770 | * SFP related | ||
771 | */ | ||
772 | |||
773 | enum bfi_sfp_h2i_e { | ||
774 | BFI_SFP_H2I_SHOW = 1, | ||
775 | BFI_SFP_H2I_SCN = 2, | ||
776 | }; | ||
777 | |||
778 | enum bfi_sfp_i2h_e { | ||
779 | BFI_SFP_I2H_SHOW = BFA_I2HM(BFI_SFP_H2I_SHOW), | ||
780 | BFI_SFP_I2H_SCN = BFA_I2HM(BFI_SFP_H2I_SCN), | ||
781 | }; | ||
782 | |||
783 | /* | ||
784 | * SFP state | ||
785 | */ | ||
786 | enum bfa_sfp_stat_e { | ||
787 | BFA_SFP_STATE_INIT = 0, /* SFP state is uninit */ | ||
788 | BFA_SFP_STATE_REMOVED = 1, /* SFP is removed */ | ||
789 | BFA_SFP_STATE_INSERTED = 2, /* SFP is inserted */ | ||
790 | BFA_SFP_STATE_VALID = 3, /* SFP is valid */ | ||
791 | BFA_SFP_STATE_UNSUPPORT = 4, /* SFP is unsupport */ | ||
792 | BFA_SFP_STATE_FAILED = 5, /* SFP i2c read fail */ | ||
793 | }; | ||
794 | |||
795 | /* | ||
796 | * SFP memory access type | ||
797 | */ | ||
798 | enum bfi_sfp_mem_e { | ||
799 | BFI_SFP_MEM_ALL = 0x1, /* access all data field */ | ||
800 | BFI_SFP_MEM_DIAGEXT = 0x2, /* access diag ext data field only */ | ||
801 | }; | ||
802 | |||
803 | struct bfi_sfp_req_s { | ||
804 | struct bfi_mhdr_s mh; | ||
805 | u8 memtype; | ||
806 | u8 rsvd[3]; | ||
807 | struct bfi_alen_s alen; | ||
808 | }; | ||
809 | |||
810 | struct bfi_sfp_rsp_s { | ||
811 | struct bfi_mhdr_s mh; | ||
812 | u8 status; | ||
813 | u8 state; | ||
814 | u8 rsvd[2]; | ||
815 | }; | ||
816 | |||
768 | #pragma pack() | 817 | #pragma pack() |
769 | 818 | ||
770 | #endif /* __BFI_H__ */ | 819 | #endif /* __BFI_H__ */ |