aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb4/cxgb4_main.c
diff options
context:
space:
mode:
authorCasey Leedom <leedom@chelsio.com>2010-06-25 08:11:46 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-29 02:59:35 -0400
commit7ee9ff94857dd27144521118173786a03d490efb (patch)
tree6b76131ed3b3c8d77328bfdda158ac3d44d01bf4 /drivers/net/cxgb4/cxgb4_main.c
parent17edf2594fef0c7ff186720915a9a73f77fee96b (diff)
cxgb4vf: Add code to provision T4 PCI-E SR-IOV Virtual Functions with hardware resources
Add code to provision T4 PCI-E SR-IOV Virtual Functions with hardware resources. Signed-off-by: Casey Leedom Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb4/cxgb4_main.c')
-rw-r--r--drivers/net/cxgb4/cxgb4_main.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 27f65b501a0a..65281674de91 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -77,6 +77,76 @@
77 */ 77 */
78#define MAX_SGE_TIMERVAL 200U 78#define MAX_SGE_TIMERVAL 200U
79 79
80#ifdef CONFIG_PCI_IOV
81/*
82 * Virtual Function provisioning constants. We need two extra Ingress Queues
83 * with Interrupt capability to serve as the VF's Firmware Event Queue and
84 * Forwarded Interrupt Queue (when using MSI mode) -- neither will have Free
85 * Lists associated with them). For each Ethernet/Control Egress Queue and
86 * for each Free List, we need an Egress Context.
87 */
88enum {
89 VFRES_NPORTS = 1, /* # of "ports" per VF */
90 VFRES_NQSETS = 2, /* # of "Queue Sets" per VF */
91
92 VFRES_NVI = VFRES_NPORTS, /* # of Virtual Interfaces */
93 VFRES_NETHCTRL = VFRES_NQSETS, /* # of EQs used for ETH or CTRL Qs */
94 VFRES_NIQFLINT = VFRES_NQSETS+2,/* # of ingress Qs/w Free List(s)/intr */
95 VFRES_NIQ = 0, /* # of non-fl/int ingress queues */
96 VFRES_NEQ = VFRES_NQSETS*2, /* # of egress queues */
97 VFRES_TC = 0, /* PCI-E traffic class */
98 VFRES_NEXACTF = 16, /* # of exact MPS filters */
99
100 VFRES_R_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF|FW_CMD_CAP_PORT,
101 VFRES_WX_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF,
102};
103
104/*
105 * Provide a Port Access Rights Mask for the specified PF/VF. This is very
106 * static and likely not to be useful in the long run. We really need to
107 * implement some form of persistent configuration which the firmware
108 * controls.
109 */
110static unsigned int pfvfres_pmask(struct adapter *adapter,
111 unsigned int pf, unsigned int vf)
112{
113 unsigned int portn, portvec;
114
115 /*
116 * Give PF's access to all of the ports.
117 */
118 if (vf == 0)
119 return FW_PFVF_CMD_PMASK_MASK;
120
121 /*
122 * For VFs, we'll assign them access to the ports based purely on the
123 * PF. We assign active ports in order, wrapping around if there are
124 * fewer active ports than PFs: e.g. active port[pf % nports].
125 * Unfortunately the adapter's port_info structs haven't been
126 * initialized yet so we have to compute this.
127 */
128 if (adapter->params.nports == 0)
129 return 0;
130
131 portn = pf % adapter->params.nports;
132 portvec = adapter->params.portvec;
133 for (;;) {
134 /*
135 * Isolate the lowest set bit in the port vector. If we're at
136 * the port number that we want, return that as the pmask.
137 * otherwise mask that bit out of the port vector and
138 * decrement our port number ...
139 */
140 unsigned int pmask = portvec ^ (portvec & (portvec-1));
141 if (portn == 0)
142 return pmask;
143 portn--;
144 portvec &= ~pmask;
145 }
146 /*NOTREACHED*/
147}
148#endif
149
80enum { 150enum {
81 MEMWIN0_APERTURE = 65536, 151 MEMWIN0_APERTURE = 65536,
82 MEMWIN0_BASE = 0x30000, 152 MEMWIN0_BASE = 0x30000,
@@ -2925,6 +2995,42 @@ static int adap_init0(struct adapter *adap)
2925 t4_read_mtu_tbl(adap, adap->params.mtus, NULL); 2995 t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
2926 t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd, 2996 t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
2927 adap->params.b_wnd); 2997 adap->params.b_wnd);
2998
2999#ifdef CONFIG_PCI_IOV
3000 /*
3001 * Provision resource limits for Virtual Functions. We currently
3002 * grant them all the same static resource limits except for the Port
3003 * Access Rights Mask which we're assigning based on the PF. All of
3004 * the static provisioning stuff for both the PF and VF really needs
3005 * to be managed in a persistent manner for each device which the
3006 * firmware controls.
3007 */
3008 {
3009 int pf, vf;
3010
3011 for (pf = 0; pf < ARRAY_SIZE(num_vf); pf++) {
3012 if (num_vf[pf] <= 0)
3013 continue;
3014
3015 /* VF numbering starts at 1! */
3016 for (vf = 1; vf <= num_vf[pf]; vf++) {
3017 ret = t4_cfg_pfvf(adap, 0, pf, vf,
3018 VFRES_NEQ, VFRES_NETHCTRL,
3019 VFRES_NIQFLINT, VFRES_NIQ,
3020 VFRES_TC, VFRES_NVI,
3021 FW_PFVF_CMD_CMASK_MASK,
3022 pfvfres_pmask(adap, pf, vf),
3023 VFRES_NEXACTF,
3024 VFRES_R_CAPS, VFRES_WX_CAPS);
3025 if (ret < 0)
3026 dev_warn(adap->pdev_dev, "failed to "
3027 "provision pf/vf=%d/%d; "
3028 "err=%d\n", pf, vf, ret);
3029 }
3030 }
3031 }
3032#endif
3033
2928 return 0; 3034 return 0;
2929 3035
2930 /* 3036 /*