aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c247
1 files changed, 243 insertions, 4 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index d833a2d418ea..9233117ea506 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -518,6 +518,16 @@ static void bnx2x_vf_set_bars(struct bnx2x *bp, struct bnx2x_virtf *vf)
518 } 518 }
519} 519}
520 520
521void bnx2x_iov_remove_one(struct bnx2x *bp)
522{
523 /* if SRIOV is not enabled there's nothing to do */
524 if (!IS_SRIOV(bp))
525 return;
526
527 /* free vf database */
528 __bnx2x_iov_free_vfdb(bp);
529}
530
521void bnx2x_iov_free_mem(struct bnx2x *bp) 531void bnx2x_iov_free_mem(struct bnx2x *bp)
522{ 532{
523 int i; 533 int i;
@@ -692,12 +702,241 @@ int bnx2x_iov_init_ilt(struct bnx2x *bp, u16 line)
692 return line + i; 702 return line + i;
693} 703}
694 704
695void bnx2x_iov_remove_one(struct bnx2x *bp) 705static u8 bnx2x_iov_is_vf_cid(struct bnx2x *bp, u16 cid)
696{ 706{
697 /* if SRIOV is not enabled there's nothing to do */ 707 return ((cid >= BNX2X_FIRST_VF_CID) &&
708 ((cid - BNX2X_FIRST_VF_CID) < BNX2X_VF_CIDS));
709}
710
711static
712void bnx2x_vf_handle_classification_eqe(struct bnx2x *bp,
713 struct bnx2x_vf_queue *vfq,
714 union event_ring_elem *elem)
715{
716 unsigned long ramrod_flags = 0;
717 int rc = 0;
718
719 /* Always push next commands out, don't wait here */
720 set_bit(RAMROD_CONT, &ramrod_flags);
721
722 switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
723 case BNX2X_FILTER_MAC_PENDING:
724 rc = vfq->mac_obj.complete(bp, &vfq->mac_obj, elem,
725 &ramrod_flags);
726 break;
727 case BNX2X_FILTER_VLAN_PENDING:
728 rc = vfq->vlan_obj.complete(bp, &vfq->vlan_obj, elem,
729 &ramrod_flags);
730 break;
731 default:
732 BNX2X_ERR("Unsupported classification command: %d\n",
733 elem->message.data.eth_event.echo);
734 return;
735 }
736 if (rc < 0)
737 BNX2X_ERR("Failed to schedule new commands: %d\n", rc);
738 else if (rc > 0)
739 DP(BNX2X_MSG_IOV, "Scheduled next pending commands...\n");
740}
741
742static
743void bnx2x_vf_handle_mcast_eqe(struct bnx2x *bp,
744 struct bnx2x_virtf *vf)
745{
746 struct bnx2x_mcast_ramrod_params rparam = {NULL};
747 int rc;
748
749 rparam.mcast_obj = &vf->mcast_obj;
750 vf->mcast_obj.raw.clear_pending(&vf->mcast_obj.raw);
751
752 /* If there are pending mcast commands - send them */
753 if (vf->mcast_obj.check_pending(&vf->mcast_obj)) {
754 rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT);
755 if (rc < 0)
756 BNX2X_ERR("Failed to send pending mcast commands: %d\n",
757 rc);
758 }
759}
760
761static
762void bnx2x_vf_handle_filters_eqe(struct bnx2x *bp,
763 struct bnx2x_virtf *vf)
764{
765 smp_mb__before_clear_bit();
766 clear_bit(BNX2X_FILTER_RX_MODE_PENDING, &vf->filter_state);
767 smp_mb__after_clear_bit();
768}
769
770int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem)
771{
772 struct bnx2x_virtf *vf;
773 int qidx = 0, abs_vfid;
774 u8 opcode;
775 u16 cid = 0xffff;
776
777 if (!IS_SRIOV(bp))
778 return 1;
779
780 /* first get the cid - the only events we handle here are cfc-delete
781 * and set-mac completion
782 */
783 opcode = elem->message.opcode;
784
785 switch (opcode) {
786 case EVENT_RING_OPCODE_CFC_DEL:
787 cid = SW_CID((__force __le32)
788 elem->message.data.cfc_del_event.cid);
789 DP(BNX2X_MSG_IOV, "checking cfc-del comp cid=%d\n", cid);
790 break;
791 case EVENT_RING_OPCODE_CLASSIFICATION_RULES:
792 case EVENT_RING_OPCODE_MULTICAST_RULES:
793 case EVENT_RING_OPCODE_FILTERS_RULES:
794 cid = (elem->message.data.eth_event.echo &
795 BNX2X_SWCID_MASK);
796 DP(BNX2X_MSG_IOV, "checking filtering comp cid=%d\n", cid);
797 break;
798 case EVENT_RING_OPCODE_VF_FLR:
799 abs_vfid = elem->message.data.vf_flr_event.vf_id;
800 DP(BNX2X_MSG_IOV, "Got VF FLR notification abs_vfid=%d\n",
801 abs_vfid);
802 goto get_vf;
803 case EVENT_RING_OPCODE_MALICIOUS_VF:
804 abs_vfid = elem->message.data.malicious_vf_event.vf_id;
805 DP(BNX2X_MSG_IOV, "Got VF MALICIOUS notification abs_vfid=%d\n",
806 abs_vfid);
807 goto get_vf;
808 default:
809 return 1;
810 }
811
812 /* check if the cid is the VF range */
813 if (!bnx2x_iov_is_vf_cid(bp, cid)) {
814 DP(BNX2X_MSG_IOV, "cid is outside vf range: %d\n", cid);
815 return 1;
816 }
817
818 /* extract vf and rxq index from vf_cid - relies on the following:
819 * 1. vfid on cid reflects the true abs_vfid
820 * 2. the max number of VFs (per path) is 64
821 */
822 qidx = cid & ((1 << BNX2X_VF_CID_WND)-1);
823 abs_vfid = (cid >> BNX2X_VF_CID_WND) & (BNX2X_MAX_NUM_OF_VFS-1);
824get_vf:
825 vf = bnx2x_vf_by_abs_fid(bp, abs_vfid);
826
827 if (!vf) {
828 BNX2X_ERR("EQ completion for unknown VF, cid %d, abs_vfid %d\n",
829 cid, abs_vfid);
830 return 0;
831 }
832
833 switch (opcode) {
834 case EVENT_RING_OPCODE_CFC_DEL:
835 DP(BNX2X_MSG_IOV, "got VF [%d:%d] cfc delete ramrod\n",
836 vf->abs_vfid, qidx);
837 vfq_get(vf, qidx)->sp_obj.complete_cmd(bp,
838 &vfq_get(vf,
839 qidx)->sp_obj,
840 BNX2X_Q_CMD_CFC_DEL);
841 break;
842 case EVENT_RING_OPCODE_CLASSIFICATION_RULES:
843 DP(BNX2X_MSG_IOV, "got VF [%d:%d] set mac/vlan ramrod\n",
844 vf->abs_vfid, qidx);
845 bnx2x_vf_handle_classification_eqe(bp, vfq_get(vf, qidx), elem);
846 break;
847 case EVENT_RING_OPCODE_MULTICAST_RULES:
848 DP(BNX2X_MSG_IOV, "got VF [%d:%d] set mcast ramrod\n",
849 vf->abs_vfid, qidx);
850 bnx2x_vf_handle_mcast_eqe(bp, vf);
851 break;
852 case EVENT_RING_OPCODE_FILTERS_RULES:
853 DP(BNX2X_MSG_IOV, "got VF [%d:%d] set rx-mode ramrod\n",
854 vf->abs_vfid, qidx);
855 bnx2x_vf_handle_filters_eqe(bp, vf);
856 break;
857 case EVENT_RING_OPCODE_VF_FLR:
858 DP(BNX2X_MSG_IOV, "got VF [%d] FLR notification\n",
859 vf->abs_vfid);
860 /* Do nothing for now */
861 break;
862 case EVENT_RING_OPCODE_MALICIOUS_VF:
863 DP(BNX2X_MSG_IOV, "got VF [%d] MALICIOUS notification\n",
864 vf->abs_vfid);
865 /* Do nothing for now */
866 break;
867 }
868 /* SRIOV: reschedule any 'in_progress' operations */
869 bnx2x_iov_sp_event(bp, cid, false);
870
871 return 0;
872}
873
874static struct bnx2x_virtf *bnx2x_vf_by_cid(struct bnx2x *bp, int vf_cid)
875{
876 /* extract the vf from vf_cid - relies on the following:
877 * 1. vfid on cid reflects the true abs_vfid
878 * 2. the max number of VFs (per path) is 64
879 */
880 int abs_vfid = (vf_cid >> BNX2X_VF_CID_WND) & (BNX2X_MAX_NUM_OF_VFS-1);
881 return bnx2x_vf_by_abs_fid(bp, abs_vfid);
882}
883
884void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid,
885 struct bnx2x_queue_sp_obj **q_obj)
886{
887 struct bnx2x_virtf *vf;
888
698 if (!IS_SRIOV(bp)) 889 if (!IS_SRIOV(bp))
699 return; 890 return;
700 891
701 /* free vf database */ 892 vf = bnx2x_vf_by_cid(bp, vf_cid);
702 __bnx2x_iov_free_vfdb(bp); 893
894 if (vf) {
895 /* extract queue index from vf_cid - relies on the following:
896 * 1. vfid on cid reflects the true abs_vfid
897 * 2. the max number of VFs (per path) is 64
898 */
899 int q_index = vf_cid & ((1 << BNX2X_VF_CID_WND)-1);
900 *q_obj = &bnx2x_vfq(vf, q_index, sp_obj);
901 } else {
902 BNX2X_ERR("No vf matching cid %d\n", vf_cid);
903 }
904}
905
906void bnx2x_iov_sp_event(struct bnx2x *bp, int vf_cid, bool queue_work)
907{
908 struct bnx2x_virtf *vf;
909
910 /* check if the cid is the VF range */
911 if (!IS_SRIOV(bp) || !bnx2x_iov_is_vf_cid(bp, vf_cid))
912 return;
913
914 vf = bnx2x_vf_by_cid(bp, vf_cid);
915 if (vf) {
916 /* set in_progress flag */
917 atomic_set(&vf->op_in_progress, 1);
918 if (queue_work)
919 queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
920 }
921}
922
923void bnx2x_iov_sp_task(struct bnx2x *bp)
924{
925 int i;
926
927 if (!IS_SRIOV(bp))
928 return;
929 /* Iterate over all VFs and invoke state transition for VFs with
930 * 'in-progress' slow-path operations
931 */
932 DP(BNX2X_MSG_IOV, "searching for pending vf operations\n");
933 for_each_vf(bp, i) {
934 struct bnx2x_virtf *vf = BP_VF(bp, i);
935
936 if (!list_empty(&vf->op_list_head) &&
937 atomic_read(&vf->op_in_progress)) {
938 DP(BNX2X_MSG_IOV, "running pending op for vf %d\n", i);
939 bnx2x_vfop_cur(bp, vf)->transition(bp, vf);
940 }
941 }
703} 942}