aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2013-01-01 00:22:33 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-02 04:45:06 -0500
commitfd1fc79dd6deb88ebf38ae9673190da999b3209f (patch)
tree0e9ff0dda51c3f200b7d40609532f16c8d0f2a90 /drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
parentb56e9670ffa4de1a3cf0ca2f89ff5e2e0c31a1f7 (diff)
bnx2x: Infrastructure for VF <-> PF request on PF side
Support interrupt from device which indicates VF has placed A request on the VF <-> PF channel. The PF driver issues a DMAE to retrieve the request from the VM memory (the Ghost Physical Address of the request is contained in the interrupt. The PF driver uses the GPA in the DMAE request, which is translated by the IOMMU to the correct physical address). The request which arrives is examined to recognize the sending VF. The PF driver allocates a workitem to handle the VF Operation (vfop). Signed-off-by: Ariel Elior <ariele@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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}