diff options
| -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__ */ |
