Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: fc: Parse FPIN packets and update statistics

Parse the incoming FPIN packets and update the host and rport FPIN
statistics based on the FPINs.

Link: https://lore.kernel.org/r/20201021092715.22669-4-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Reviewed-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Shyam Sundar <ssundar@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Shyam Sundar and committed by
Martin K. Petersen
3dcfe0de 547aab51

+294
+293
drivers/scsi/scsi_transport_fc.c
··· 34 34 static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *); 35 35 static void fc_bsg_remove(struct request_queue *); 36 36 static void fc_bsg_goose_queue(struct fc_rport *); 37 + static void fc_li_stats_update(struct fc_fn_li_desc *li_desc, 38 + struct fc_fpin_stats *stats); 39 + static void fc_delivery_stats_update(u32 reason_code, 40 + struct fc_fpin_stats *stats); 41 + static void fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats); 37 42 38 43 /* 39 44 * Module Parameters ··· 636 631 EXPORT_SYMBOL(fc_host_post_vendor_event); 637 632 638 633 /** 634 + * fc_find_rport_by_wwpn - find the fc_rport pointer for a given wwpn 635 + * @shost: host the fc_rport is associated with 636 + * @wwpn: wwpn of the fc_rport device 637 + * 638 + * Notes: 639 + * This routine assumes no locks are held on entry. 640 + */ 641 + struct fc_rport * 642 + fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn) 643 + { 644 + struct fc_rport *rport; 645 + unsigned long flags; 646 + 647 + spin_lock_irqsave(shost->host_lock, flags); 648 + 649 + list_for_each_entry(rport, &fc_host_rports(shost), peers) { 650 + if (rport->port_state != FC_PORTSTATE_ONLINE) 651 + continue; 652 + 653 + if (rport->port_name == wwpn) { 654 + spin_unlock_irqrestore(shost->host_lock, flags); 655 + return rport; 656 + } 657 + } 658 + 659 + spin_unlock_irqrestore(shost->host_lock, flags); 660 + return NULL; 661 + } 662 + EXPORT_SYMBOL(fc_find_rport_by_wwpn); 663 + 664 + static void 665 + fc_li_stats_update(struct fc_fn_li_desc *li_desc, 666 + struct fc_fpin_stats *stats) 667 + { 668 + stats->li += be32_to_cpu(li_desc->event_count); 669 + switch (be16_to_cpu(li_desc->event_type)) { 670 + case FPIN_LI_UNKNOWN: 671 + stats->li_failure_unknown += 672 + be32_to_cpu(li_desc->event_count); 673 + break; 674 + case FPIN_LI_LINK_FAILURE: 675 + stats->li_link_failure_count += 676 + be32_to_cpu(li_desc->event_count); 677 + break; 678 + case FPIN_LI_LOSS_OF_SYNC: 679 + stats->li_loss_of_sync_count += 680 + be32_to_cpu(li_desc->event_count); 681 + break; 682 + case FPIN_LI_LOSS_OF_SIG: 683 + stats->li_loss_of_signals_count += 684 + be32_to_cpu(li_desc->event_count); 685 + break; 686 + case FPIN_LI_PRIM_SEQ_ERR: 687 + stats->li_prim_seq_err_count += 688 + be32_to_cpu(li_desc->event_count); 689 + break; 690 + case FPIN_LI_INVALID_TX_WD: 691 + stats->li_invalid_tx_word_count += 692 + be32_to_cpu(li_desc->event_count); 693 + break; 694 + case FPIN_LI_INVALID_CRC: 695 + stats->li_invalid_crc_count += 696 + be32_to_cpu(li_desc->event_count); 697 + break; 698 + case FPIN_LI_DEVICE_SPEC: 699 + stats->li_device_specific += 700 + be32_to_cpu(li_desc->event_count); 701 + break; 702 + } 703 + } 704 + 705 + static void 706 + fc_delivery_stats_update(u32 reason_code, struct fc_fpin_stats *stats) 707 + { 708 + stats->dn++; 709 + switch (reason_code) { 710 + case FPIN_DELI_UNKNOWN: 711 + stats->dn_unknown++; 712 + break; 713 + case FPIN_DELI_TIMEOUT: 714 + stats->dn_timeout++; 715 + break; 716 + case FPIN_DELI_UNABLE_TO_ROUTE: 717 + stats->dn_unable_to_route++; 718 + break; 719 + case FPIN_DELI_DEVICE_SPEC: 720 + stats->dn_device_specific++; 721 + break; 722 + } 723 + } 724 + 725 + static void 726 + fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats) 727 + { 728 + stats->cn++; 729 + switch (event_type) { 730 + case FPIN_CONGN_CLEAR: 731 + stats->cn_clear++; 732 + break; 733 + case FPIN_CONGN_LOST_CREDIT: 734 + stats->cn_lost_credit++; 735 + break; 736 + case FPIN_CONGN_CREDIT_STALL: 737 + stats->cn_credit_stall++; 738 + break; 739 + case FPIN_CONGN_OVERSUBSCRIPTION: 740 + stats->cn_oversubscription++; 741 + break; 742 + case FPIN_CONGN_DEVICE_SPEC: 743 + stats->cn_device_specific++; 744 + } 745 + } 746 + 747 + /* 748 + * fc_fpin_li_stats_update - routine to update Link Integrity 749 + * event statistics. 750 + * @shost: host the FPIN was received on 751 + * @tlv: pointer to link integrity descriptor 752 + * 753 + */ 754 + static void 755 + fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv) 756 + { 757 + u8 i; 758 + struct fc_rport *rport = NULL; 759 + struct fc_rport *attach_rport = NULL; 760 + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); 761 + struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv; 762 + u64 wwpn; 763 + 764 + rport = fc_find_rport_by_wwpn(shost, 765 + be64_to_cpu(li_desc->attached_wwpn)); 766 + if (rport && 767 + (rport->roles & FC_PORT_ROLE_FCP_TARGET || 768 + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { 769 + attach_rport = rport; 770 + fc_li_stats_update(li_desc, &attach_rport->fpin_stats); 771 + } 772 + 773 + if (be32_to_cpu(li_desc->pname_count) > 0) { 774 + for (i = 0; 775 + i < be32_to_cpu(li_desc->pname_count); 776 + i++) { 777 + wwpn = be64_to_cpu(li_desc->pname_list[i]); 778 + rport = fc_find_rport_by_wwpn(shost, wwpn); 779 + if (rport && 780 + (rport->roles & FC_PORT_ROLE_FCP_TARGET || 781 + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { 782 + if (rport == attach_rport) 783 + continue; 784 + fc_li_stats_update(li_desc, 785 + &rport->fpin_stats); 786 + } 787 + } 788 + } 789 + 790 + if (fc_host->port_name == be64_to_cpu(li_desc->attached_wwpn)) 791 + fc_li_stats_update(li_desc, &fc_host->fpin_stats); 792 + } 793 + 794 + /* 795 + * fc_fpin_delivery_stats_update - routine to update Delivery Notification 796 + * event statistics. 797 + * @shost: host the FPIN was received on 798 + * @tlv: pointer to delivery descriptor 799 + * 800 + */ 801 + static void 802 + fc_fpin_delivery_stats_update(struct Scsi_Host *shost, 803 + struct fc_tlv_desc *tlv) 804 + { 805 + struct fc_rport *rport = NULL; 806 + struct fc_rport *attach_rport = NULL; 807 + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); 808 + struct fc_fn_deli_desc *dn_desc = (struct fc_fn_deli_desc *)tlv; 809 + u32 reason_code = be32_to_cpu(dn_desc->deli_reason_code); 810 + 811 + rport = fc_find_rport_by_wwpn(shost, 812 + be64_to_cpu(dn_desc->attached_wwpn)); 813 + if (rport && 814 + (rport->roles & FC_PORT_ROLE_FCP_TARGET || 815 + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { 816 + attach_rport = rport; 817 + fc_delivery_stats_update(reason_code, 818 + &attach_rport->fpin_stats); 819 + } 820 + 821 + if (fc_host->port_name == be64_to_cpu(dn_desc->attached_wwpn)) 822 + fc_delivery_stats_update(reason_code, &fc_host->fpin_stats); 823 + } 824 + 825 + /* 826 + * fc_fpin_peer_congn_stats_update - routine to update Peer Congestion 827 + * event statistics. 828 + * @shost: host the FPIN was received on 829 + * @tlv: pointer to peer congestion descriptor 830 + * 831 + */ 832 + static void 833 + fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost, 834 + struct fc_tlv_desc *tlv) 835 + { 836 + u8 i; 837 + struct fc_rport *rport = NULL; 838 + struct fc_rport *attach_rport = NULL; 839 + struct fc_fn_peer_congn_desc *pc_desc = 840 + (struct fc_fn_peer_congn_desc *)tlv; 841 + u16 event_type = be16_to_cpu(pc_desc->event_type); 842 + u64 wwpn; 843 + 844 + rport = fc_find_rport_by_wwpn(shost, 845 + be64_to_cpu(pc_desc->attached_wwpn)); 846 + if (rport && 847 + (rport->roles & FC_PORT_ROLE_FCP_TARGET || 848 + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { 849 + attach_rport = rport; 850 + fc_cn_stats_update(event_type, &attach_rport->fpin_stats); 851 + } 852 + 853 + if (be32_to_cpu(pc_desc->pname_count) > 0) { 854 + for (i = 0; 855 + i < be32_to_cpu(pc_desc->pname_count); 856 + i++) { 857 + wwpn = be64_to_cpu(pc_desc->pname_list[i]); 858 + rport = fc_find_rport_by_wwpn(shost, wwpn); 859 + if (rport && 860 + (rport->roles & FC_PORT_ROLE_FCP_TARGET || 861 + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { 862 + if (rport == attach_rport) 863 + continue; 864 + fc_cn_stats_update(event_type, 865 + &rport->fpin_stats); 866 + } 867 + } 868 + } 869 + } 870 + 871 + /* 872 + * fc_fpin_congn_stats_update - routine to update Congestion 873 + * event statistics. 874 + * @shost: host the FPIN was received on 875 + * @tlv: pointer to congestion descriptor 876 + * 877 + */ 878 + static void 879 + fc_fpin_congn_stats_update(struct Scsi_Host *shost, 880 + struct fc_tlv_desc *tlv) 881 + { 882 + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); 883 + struct fc_fn_congn_desc *congn = (struct fc_fn_congn_desc *)tlv; 884 + 885 + fc_cn_stats_update(be16_to_cpu(congn->event_type), 886 + &fc_host->fpin_stats); 887 + } 888 + 889 + /** 639 890 * fc_host_rcv_fpin - routine to process a received FPIN. 640 891 * @shost: host the FPIN was received on 641 892 * @fpin_len: length of FPIN payload, in bytes ··· 903 642 void 904 643 fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf) 905 644 { 645 + struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf; 646 + struct fc_tlv_desc *tlv; 647 + u32 desc_cnt = 0, bytes_remain; 648 + u32 dtag; 649 + 650 + /* Update Statistics */ 651 + tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0]; 652 + bytes_remain = fpin_len - offsetof(struct fc_els_fpin, fpin_desc); 653 + bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len)); 654 + 655 + while (bytes_remain >= FC_TLV_DESC_HDR_SZ && 656 + bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) { 657 + dtag = be32_to_cpu(tlv->desc_tag); 658 + switch (dtag) { 659 + case ELS_DTAG_LNK_INTEGRITY: 660 + fc_fpin_li_stats_update(shost, tlv); 661 + break; 662 + case ELS_DTAG_DELIVERY: 663 + fc_fpin_delivery_stats_update(shost, tlv); 664 + break; 665 + case ELS_DTAG_PEER_CONGEST: 666 + fc_fpin_peer_congn_stats_update(shost, tlv); 667 + break; 668 + case ELS_DTAG_CONGESTION: 669 + fc_fpin_congn_stats_update(shost, tlv); 670 + } 671 + 672 + desc_cnt++; 673 + bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv); 674 + tlv = fc_tlv_next_desc(tlv); 675 + } 676 + 906 677 fc_host_post_fc_event(shost, fc_get_event_number(), 907 678 FCH_EVT_LINK_FPIN, fpin_len, fpin_buf, 0); 908 679 }
+1
include/scsi/scsi_transport_fc.h
··· 819 819 enum fc_host_event_code event_code, u32 event_data); 820 820 void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, 821 821 u32 data_len, char *data_buf, u64 vendor_id); 822 + struct fc_rport *fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn); 822 823 void fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number, 823 824 enum fc_host_event_code event_code, 824 825 u32 data_len, char *data_buf, u64 vendor_id);