blob: 8da382ccf22bbd3f8b5c848dbe583df440b70f2d [file] [log] [blame]
Alexander Duyckb6fec182014-09-20 19:47:46 -04001/* Intel Ethernet Switch Host Interface Driver
2 * Copyright(c) 2013 - 2014 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * The full GNU General Public License is included in this distribution in
14 * the file called "COPYING".
15 *
16 * Contact Information:
17 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
18 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
19 */
20
21#include "fm10k_pf.h"
22
23/**
24 * fm10k_reset_hw_pf - PF hardware reset
25 * @hw: pointer to hardware structure
26 *
27 * This function should return the hardware to a state similar to the
28 * one it is in after being powered on.
29 **/
30static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw)
31{
32 s32 err;
33 u32 reg;
34 u16 i;
35
36 /* Disable interrupts */
37 fm10k_write_reg(hw, FM10K_EIMR, FM10K_EIMR_DISABLE(ALL));
38
39 /* Lock ITR2 reg 0 into itself and disable interrupt moderation */
40 fm10k_write_reg(hw, FM10K_ITR2(0), 0);
41 fm10k_write_reg(hw, FM10K_INT_CTRL, 0);
42
43 /* We assume here Tx and Rx queue 0 are owned by the PF */
44
45 /* Shut off VF access to their queues forcing them to queue 0 */
46 for (i = 0; i < FM10K_TQMAP_TABLE_SIZE; i++) {
47 fm10k_write_reg(hw, FM10K_TQMAP(i), 0);
48 fm10k_write_reg(hw, FM10K_RQMAP(i), 0);
49 }
50
51 /* shut down all rings */
52 err = fm10k_disable_queues_generic(hw, FM10K_MAX_QUEUES);
53 if (err)
54 return err;
55
56 /* Verify that DMA is no longer active */
57 reg = fm10k_read_reg(hw, FM10K_DMA_CTRL);
58 if (reg & (FM10K_DMA_CTRL_TX_ACTIVE | FM10K_DMA_CTRL_RX_ACTIVE))
59 return FM10K_ERR_DMA_PENDING;
60
61 /* Inititate data path reset */
62 reg |= FM10K_DMA_CTRL_DATAPATH_RESET;
63 fm10k_write_reg(hw, FM10K_DMA_CTRL, reg);
64
65 /* Flush write and allow 100us for reset to complete */
66 fm10k_write_flush(hw);
67 udelay(FM10K_RESET_TIMEOUT);
68
69 /* Verify we made it out of reset */
70 reg = fm10k_read_reg(hw, FM10K_IP);
71 if (!(reg & FM10K_IP_NOTINRESET))
72 err = FM10K_ERR_RESET_FAILED;
73
74 return err;
75}
76
77/**
78 * fm10k_init_hw_pf - PF hardware initialization
79 * @hw: pointer to hardware structure
80 *
81 **/
82static s32 fm10k_init_hw_pf(struct fm10k_hw *hw)
83{
84 u32 dma_ctrl, txqctl;
85 u16 i;
86
87 /* Establish default VSI as valid */
88 fm10k_write_reg(hw, FM10K_DGLORTDEC(fm10k_dglort_default), 0);
89 fm10k_write_reg(hw, FM10K_DGLORTMAP(fm10k_dglort_default),
90 FM10K_DGLORTMAP_ANY);
91
92 /* Invalidate all other GLORT entries */
93 for (i = 1; i < FM10K_DGLORT_COUNT; i++)
94 fm10k_write_reg(hw, FM10K_DGLORTMAP(i), FM10K_DGLORTMAP_NONE);
95
96 /* reset ITR2(0) to point to itself */
97 fm10k_write_reg(hw, FM10K_ITR2(0), 0);
98
99 /* reset VF ITR2(0) to point to 0 avoid PF registers */
100 fm10k_write_reg(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), 0);
101
102 /* loop through all PF ITR2 registers pointing them to the previous */
103 for (i = 1; i < FM10K_ITR_REG_COUNT_PF; i++)
104 fm10k_write_reg(hw, FM10K_ITR2(i), i - 1);
105
106 /* Enable interrupt moderator if not already enabled */
107 fm10k_write_reg(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR);
108
109 /* compute the default txqctl configuration */
110 txqctl = FM10K_TXQCTL_PF | FM10K_TXQCTL_UNLIMITED_BW |
111 (hw->mac.default_vid << FM10K_TXQCTL_VID_SHIFT);
112
113 for (i = 0; i < FM10K_MAX_QUEUES; i++) {
114 /* configure rings for 256 Queue / 32 Descriptor cache mode */
115 fm10k_write_reg(hw, FM10K_TQDLOC(i),
116 (i * FM10K_TQDLOC_BASE_32_DESC) |
117 FM10K_TQDLOC_SIZE_32_DESC);
118 fm10k_write_reg(hw, FM10K_TXQCTL(i), txqctl);
119
120 /* configure rings to provide TPH processing hints */
121 fm10k_write_reg(hw, FM10K_TPH_TXCTRL(i),
122 FM10K_TPH_TXCTRL_DESC_TPHEN |
123 FM10K_TPH_TXCTRL_DESC_RROEN |
124 FM10K_TPH_TXCTRL_DESC_WROEN |
125 FM10K_TPH_TXCTRL_DATA_RROEN);
126 fm10k_write_reg(hw, FM10K_TPH_RXCTRL(i),
127 FM10K_TPH_RXCTRL_DESC_TPHEN |
128 FM10K_TPH_RXCTRL_DESC_RROEN |
129 FM10K_TPH_RXCTRL_DATA_WROEN |
130 FM10K_TPH_RXCTRL_HDR_WROEN);
131 }
132
133 /* set max hold interval to align with 1.024 usec in all modes */
134 switch (hw->bus.speed) {
135 case fm10k_bus_speed_2500:
136 dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1;
137 break;
138 case fm10k_bus_speed_5000:
139 dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2;
140 break;
141 case fm10k_bus_speed_8000:
142 dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3;
143 break;
144 default:
145 dma_ctrl = 0;
146 break;
147 }
148
149 /* Configure TSO flags */
150 fm10k_write_reg(hw, FM10K_DTXTCPFLGL, FM10K_TSO_FLAGS_LOW);
151 fm10k_write_reg(hw, FM10K_DTXTCPFLGH, FM10K_TSO_FLAGS_HI);
152
153 /* Enable DMA engine
154 * Set Rx Descriptor size to 32
155 * Set Minimum MSS to 64
156 * Set Maximum number of Rx queues to 256 / 32 Descriptor
157 */
158 dma_ctrl |= FM10K_DMA_CTRL_TX_ENABLE | FM10K_DMA_CTRL_RX_ENABLE |
159 FM10K_DMA_CTRL_RX_DESC_SIZE | FM10K_DMA_CTRL_MINMSS_64 |
160 FM10K_DMA_CTRL_32_DESC;
161
162 fm10k_write_reg(hw, FM10K_DMA_CTRL, dma_ctrl);
163
164 /* record maximum queue count, we limit ourselves to 128 */
165 hw->mac.max_queues = FM10K_MAX_QUEUES_PF;
166
167 return 0;
168}
169
170/**
171 * fm10k_is_slot_appropriate_pf - Indicate appropriate slot for this SKU
172 * @hw: pointer to hardware structure
173 *
174 * Looks at the PCIe bus info to confirm whether or not this slot can support
175 * the necessary bandwidth for this device.
176 **/
177static bool fm10k_is_slot_appropriate_pf(struct fm10k_hw *hw)
178{
179 return (hw->bus.speed == hw->bus_caps.speed) &&
180 (hw->bus.width == hw->bus_caps.width);
181}
182
183/**
Alexander Duyck401b5382014-09-20 19:47:58 -0400184 * fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table
185 * @hw: pointer to hardware structure
186 * @vid: VLAN ID to add to table
187 * @vsi: Index indicating VF ID or PF ID in table
188 * @set: Indicates if this is a set or clear operation
189 *
190 * This function adds or removes the corresponding VLAN ID from the VLAN
191 * filter table for the corresponding function. In addition to the
192 * standard set/clear that supports one bit a multi-bit write is
193 * supported to set 64 bits at a time.
194 **/
195static s32 fm10k_update_vlan_pf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set)
196{
197 u32 vlan_table, reg, mask, bit, len;
198
199 /* verify the VSI index is valid */
200 if (vsi > FM10K_VLAN_TABLE_VSI_MAX)
201 return FM10K_ERR_PARAM;
202
203 /* VLAN multi-bit write:
204 * The multi-bit write has several parts to it.
205 * 3 2 1 0
206 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
207 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208 * | RSVD0 | Length |C|RSVD0| VLAN ID |
209 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210 *
211 * VLAN ID: Vlan Starting value
212 * RSVD0: Reserved section, must be 0
213 * C: Flag field, 0 is set, 1 is clear (Used in VF VLAN message)
214 * Length: Number of times to repeat the bit being set
215 */
216 len = vid >> 16;
217 vid = (vid << 17) >> 17;
218
219 /* verify the reserved 0 fields are 0 */
220 if (len >= FM10K_VLAN_TABLE_VID_MAX ||
221 vid >= FM10K_VLAN_TABLE_VID_MAX)
222 return FM10K_ERR_PARAM;
223
224 /* Loop through the table updating all required VLANs */
225 for (reg = FM10K_VLAN_TABLE(vsi, vid / 32), bit = vid % 32;
226 len < FM10K_VLAN_TABLE_VID_MAX;
227 len -= 32 - bit, reg++, bit = 0) {
228 /* record the initial state of the register */
229 vlan_table = fm10k_read_reg(hw, reg);
230
231 /* truncate mask if we are at the start or end of the run */
232 mask = (~(u32)0 >> ((len < 31) ? 31 - len : 0)) << bit;
233
234 /* make necessary modifications to the register */
235 mask &= set ? ~vlan_table : vlan_table;
236 if (mask)
237 fm10k_write_reg(hw, reg, vlan_table ^ mask);
238 }
239
240 return 0;
241}
242
243/**
Alexander Duyckb6fec182014-09-20 19:47:46 -0400244 * fm10k_read_mac_addr_pf - Read device MAC address
245 * @hw: pointer to the HW structure
246 *
247 * Reads the device MAC address from the SM_AREA and stores the value.
248 **/
249static s32 fm10k_read_mac_addr_pf(struct fm10k_hw *hw)
250{
251 u8 perm_addr[ETH_ALEN];
252 u32 serial_num;
253 int i;
254
255 serial_num = fm10k_read_reg(hw, FM10K_SM_AREA(1));
256
257 /* last byte should be all 1's */
258 if ((~serial_num) << 24)
259 return FM10K_ERR_INVALID_MAC_ADDR;
260
261 perm_addr[0] = (u8)(serial_num >> 24);
262 perm_addr[1] = (u8)(serial_num >> 16);
263 perm_addr[2] = (u8)(serial_num >> 8);
264
265 serial_num = fm10k_read_reg(hw, FM10K_SM_AREA(0));
266
267 /* first byte should be all 1's */
268 if ((~serial_num) >> 24)
269 return FM10K_ERR_INVALID_MAC_ADDR;
270
271 perm_addr[3] = (u8)(serial_num >> 16);
272 perm_addr[4] = (u8)(serial_num >> 8);
273 perm_addr[5] = (u8)(serial_num);
274
275 for (i = 0; i < ETH_ALEN; i++) {
276 hw->mac.perm_addr[i] = perm_addr[i];
277 hw->mac.addr[i] = perm_addr[i];
278 }
279
280 return 0;
281}
282
283/**
Alexander Duyck401b5382014-09-20 19:47:58 -0400284 * fm10k_glort_valid_pf - Validate that the provided glort is valid
285 * @hw: pointer to the HW structure
286 * @glort: base glort to be validated
287 *
288 * This function will return an error if the provided glort is invalid
289 **/
290bool fm10k_glort_valid_pf(struct fm10k_hw *hw, u16 glort)
291{
292 glort &= hw->mac.dglort_map >> FM10K_DGLORTMAP_MASK_SHIFT;
293
294 return glort == (hw->mac.dglort_map & FM10K_DGLORTMAP_NONE);
295}
296
297/**
298 * fm10k_update_uc_addr_pf - Update device unicast addresss
299 * @hw: pointer to the HW structure
300 * @glort: base resource tag for this request
301 * @mac: MAC address to add/remove from table
302 * @vid: VLAN ID to add/remove from table
303 * @add: Indicates if this is an add or remove operation
304 * @flags: flags field to indicate add and secure
305 *
306 * This function generates a message to the Switch API requesting
307 * that the given logical port add/remove the given L2 MAC/VLAN address.
308 **/
309static s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort,
310 const u8 *mac, u16 vid, bool add, u8 flags)
311{
312 struct fm10k_mbx_info *mbx = &hw->mbx;
313 struct fm10k_mac_update mac_update;
314 u32 msg[5];
315
316 /* if glort is not valid return error */
317 if (!fm10k_glort_valid_pf(hw, glort))
318 return FM10K_ERR_PARAM;
319
320 /* drop upper 4 bits of VLAN ID */
321 vid = (vid << 4) >> 4;
322
323 /* record fields */
324 mac_update.mac_lower = cpu_to_le32(((u32)mac[2] << 24) |
325 ((u32)mac[3] << 16) |
326 ((u32)mac[4] << 8) |
327 ((u32)mac[5]));
328 mac_update.mac_upper = cpu_to_le16(((u32)mac[0] << 8) |
329 ((u32)mac[1]));
330 mac_update.vlan = cpu_to_le16(vid);
331 mac_update.glort = cpu_to_le16(glort);
332 mac_update.action = add ? 0 : 1;
333 mac_update.flags = flags;
334
335 /* populate mac_update fields */
336 fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_UPDATE_MAC_FWD_RULE);
337 fm10k_tlv_attr_put_le_struct(msg, FM10K_PF_ATTR_ID_MAC_UPDATE,
338 &mac_update, sizeof(mac_update));
339
340 /* load onto outgoing mailbox */
341 return mbx->ops.enqueue_tx(hw, mbx, msg);
342}
343
344/**
345 * fm10k_update_uc_addr_pf - Update device unicast addresss
346 * @hw: pointer to the HW structure
347 * @glort: base resource tag for this request
348 * @mac: MAC address to add/remove from table
349 * @vid: VLAN ID to add/remove from table
350 * @add: Indicates if this is an add or remove operation
351 * @flags: flags field to indicate add and secure
352 *
353 * This function is used to add or remove unicast addresses for
354 * the PF.
355 **/
356static s32 fm10k_update_uc_addr_pf(struct fm10k_hw *hw, u16 glort,
357 const u8 *mac, u16 vid, bool add, u8 flags)
358{
359 /* verify MAC address is valid */
360 if (!is_valid_ether_addr(mac))
361 return FM10K_ERR_PARAM;
362
363 return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, flags);
364}
365
366/**
367 * fm10k_update_mc_addr_pf - Update device multicast addresses
368 * @hw: pointer to the HW structure
369 * @glort: base resource tag for this request
370 * @mac: MAC address to add/remove from table
371 * @vid: VLAN ID to add/remove from table
372 * @add: Indicates if this is an add or remove operation
373 *
374 * This function is used to add or remove multicast MAC addresses for
375 * the PF.
376 **/
377static s32 fm10k_update_mc_addr_pf(struct fm10k_hw *hw, u16 glort,
378 const u8 *mac, u16 vid, bool add)
379{
380 /* verify multicast address is valid */
381 if (!is_multicast_ether_addr(mac))
382 return FM10K_ERR_PARAM;
383
384 return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, 0);
385}
386
387/**
388 * fm10k_update_xcast_mode_pf - Request update of multicast mode
389 * @hw: pointer to hardware structure
390 * @glort: base resource tag for this request
391 * @mode: integer value indicating mode being requested
392 *
393 * This function will attempt to request a higher mode for the port
394 * so that it can enable either multicast, multicast promiscuous, or
395 * promiscuous mode of operation.
396 **/
397static s32 fm10k_update_xcast_mode_pf(struct fm10k_hw *hw, u16 glort, u8 mode)
398{
399 struct fm10k_mbx_info *mbx = &hw->mbx;
400 u32 msg[3], xcast_mode;
401
402 if (mode > FM10K_XCAST_MODE_NONE)
403 return FM10K_ERR_PARAM;
404 /* if glort is not valid return error */
405 if (!fm10k_glort_valid_pf(hw, glort))
406 return FM10K_ERR_PARAM;
407
408 /* write xcast mode as a single u32 value,
409 * lower 16 bits: glort
410 * upper 16 bits: mode
411 */
412 xcast_mode = ((u32)mode << 16) | glort;
413
414 /* generate message requesting to change xcast mode */
415 fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_XCAST_MODES);
416 fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_XCAST_MODE, xcast_mode);
417
418 /* load onto outgoing mailbox */
419 return mbx->ops.enqueue_tx(hw, mbx, msg);
420}
421
422/**
423 * fm10k_update_int_moderator_pf - Update interrupt moderator linked list
424 * @hw: pointer to hardware structure
425 *
426 * This function walks through the MSI-X vector table to determine the
427 * number of active interrupts and based on that information updates the
428 * interrupt moderator linked list.
429 **/
430static void fm10k_update_int_moderator_pf(struct fm10k_hw *hw)
431{
432 u32 i;
433
434 /* Disable interrupt moderator */
435 fm10k_write_reg(hw, FM10K_INT_CTRL, 0);
436
437 /* loop through PF from last to first looking enabled vectors */
438 for (i = FM10K_ITR_REG_COUNT_PF - 1; i; i--) {
439 if (!fm10k_read_reg(hw, FM10K_MSIX_VECTOR_MASK(i)))
440 break;
441 }
442
443 /* always reset VFITR2[0] to point to last enabled PF vector*/
444 fm10k_write_reg(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), i);
445
446 /* reset ITR2[0] to point to last enabled PF vector */
447 fm10k_write_reg(hw, FM10K_ITR2(0), i);
448
449 /* Enable interrupt moderator */
450 fm10k_write_reg(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR);
451}
452
453/**
454 * fm10k_update_lport_state_pf - Notify the switch of a change in port state
455 * @hw: pointer to the HW structure
456 * @glort: base resource tag for this request
457 * @count: number of logical ports being updated
458 * @enable: boolean value indicating enable or disable
459 *
460 * This function is used to add/remove a logical port from the switch.
461 **/
462static s32 fm10k_update_lport_state_pf(struct fm10k_hw *hw, u16 glort,
463 u16 count, bool enable)
464{
465 struct fm10k_mbx_info *mbx = &hw->mbx;
466 u32 msg[3], lport_msg;
467
468 /* do nothing if we are being asked to create or destroy 0 ports */
469 if (!count)
470 return 0;
471
472 /* if glort is not valid return error */
473 if (!fm10k_glort_valid_pf(hw, glort))
474 return FM10K_ERR_PARAM;
475
476 /* construct the lport message from the 2 pieces of data we have */
477 lport_msg = ((u32)count << 16) | glort;
478
479 /* generate lport create/delete message */
480 fm10k_tlv_msg_init(msg, enable ? FM10K_PF_MSG_ID_LPORT_CREATE :
481 FM10K_PF_MSG_ID_LPORT_DELETE);
482 fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_PORT, lport_msg);
483
484 /* load onto outgoing mailbox */
485 return mbx->ops.enqueue_tx(hw, mbx, msg);
486}
487
488/**
489 * fm10k_configure_dglort_map_pf - Configures GLORT entry and queues
490 * @hw: pointer to hardware structure
491 * @dglort: pointer to dglort configuration structure
492 *
493 * Reads the configuration structure contained in dglort_cfg and uses
494 * that information to then populate a DGLORTMAP/DEC entry and the queues
495 * to which it has been assigned.
496 **/
497static s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw,
498 struct fm10k_dglort_cfg *dglort)
499{
500 u16 glort, queue_count, vsi_count, pc_count;
501 u16 vsi, queue, pc, q_idx;
502 u32 txqctl, dglortdec, dglortmap;
503
504 /* verify the dglort pointer */
505 if (!dglort)
506 return FM10K_ERR_PARAM;
507
508 /* verify the dglort values */
509 if ((dglort->idx > 7) || (dglort->rss_l > 7) || (dglort->pc_l > 3) ||
510 (dglort->vsi_l > 6) || (dglort->vsi_b > 64) ||
511 (dglort->queue_l > 8) || (dglort->queue_b >= 256))
512 return FM10K_ERR_PARAM;
513
514 /* determine count of VSIs and queues */
515 queue_count = 1 << (dglort->rss_l + dglort->pc_l);
516 vsi_count = 1 << (dglort->vsi_l + dglort->queue_l);
517 glort = dglort->glort;
518 q_idx = dglort->queue_b;
519
520 /* configure SGLORT for queues */
521 for (vsi = 0; vsi < vsi_count; vsi++, glort++) {
522 for (queue = 0; queue < queue_count; queue++, q_idx++) {
523 if (q_idx >= FM10K_MAX_QUEUES)
524 break;
525
526 fm10k_write_reg(hw, FM10K_TX_SGLORT(q_idx), glort);
527 fm10k_write_reg(hw, FM10K_RX_SGLORT(q_idx), glort);
528 }
529 }
530
531 /* determine count of PCs and queues */
532 queue_count = 1 << (dglort->queue_l + dglort->rss_l + dglort->vsi_l);
533 pc_count = 1 << dglort->pc_l;
534
535 /* configure PC for Tx queues */
536 for (pc = 0; pc < pc_count; pc++) {
537 q_idx = pc + dglort->queue_b;
538 for (queue = 0; queue < queue_count; queue++) {
539 if (q_idx >= FM10K_MAX_QUEUES)
540 break;
541
542 txqctl = fm10k_read_reg(hw, FM10K_TXQCTL(q_idx));
543 txqctl &= ~FM10K_TXQCTL_PC_MASK;
544 txqctl |= pc << FM10K_TXQCTL_PC_SHIFT;
545 fm10k_write_reg(hw, FM10K_TXQCTL(q_idx), txqctl);
546
547 q_idx += pc_count;
548 }
549 }
550
551 /* configure DGLORTDEC */
552 dglortdec = ((u32)(dglort->rss_l) << FM10K_DGLORTDEC_RSSLENGTH_SHIFT) |
553 ((u32)(dglort->queue_b) << FM10K_DGLORTDEC_QBASE_SHIFT) |
554 ((u32)(dglort->pc_l) << FM10K_DGLORTDEC_PCLENGTH_SHIFT) |
555 ((u32)(dglort->vsi_b) << FM10K_DGLORTDEC_VSIBASE_SHIFT) |
556 ((u32)(dglort->vsi_l) << FM10K_DGLORTDEC_VSILENGTH_SHIFT) |
557 ((u32)(dglort->queue_l));
558 if (dglort->inner_rss)
559 dglortdec |= FM10K_DGLORTDEC_INNERRSS_ENABLE;
560
561 /* configure DGLORTMAP */
562 dglortmap = (dglort->idx == fm10k_dglort_default) ?
563 FM10K_DGLORTMAP_ANY : FM10K_DGLORTMAP_ZERO;
564 dglortmap <<= dglort->vsi_l + dglort->queue_l + dglort->shared_l;
565 dglortmap |= dglort->glort;
566
567 /* write values to hardware */
568 fm10k_write_reg(hw, FM10K_DGLORTDEC(dglort->idx), dglortdec);
569 fm10k_write_reg(hw, FM10K_DGLORTMAP(dglort->idx), dglortmap);
570
571 return 0;
572}
573
574/**
Alexander Duyckb6fec182014-09-20 19:47:46 -0400575 * fm10k_update_stats_hw_pf - Updates hardware related statistics of PF
576 * @hw: pointer to hardware structure
577 * @stats: pointer to the stats structure to update
578 *
579 * This function collects and aggregates global and per queue hardware
580 * statistics.
581 **/
582static void fm10k_update_hw_stats_pf(struct fm10k_hw *hw,
583 struct fm10k_hw_stats *stats)
584{
585 u32 timeout, ur, ca, um, xec, vlan_drop, loopback_drop, nodesc_drop;
586 u32 id, id_prev;
587
588 /* Use Tx queue 0 as a canary to detect a reset */
589 id = fm10k_read_reg(hw, FM10K_TXQCTL(0));
590
591 /* Read Global Statistics */
592 do {
593 timeout = fm10k_read_hw_stats_32b(hw, FM10K_STATS_TIMEOUT,
594 &stats->timeout);
595 ur = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UR, &stats->ur);
596 ca = fm10k_read_hw_stats_32b(hw, FM10K_STATS_CA, &stats->ca);
597 um = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UM, &stats->um);
598 xec = fm10k_read_hw_stats_32b(hw, FM10K_STATS_XEC, &stats->xec);
599 vlan_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_VLAN_DROP,
600 &stats->vlan_drop);
601 loopback_drop = fm10k_read_hw_stats_32b(hw,
602 FM10K_STATS_LOOPBACK_DROP,
603 &stats->loopback_drop);
604 nodesc_drop = fm10k_read_hw_stats_32b(hw,
605 FM10K_STATS_NODESC_DROP,
606 &stats->nodesc_drop);
607
608 /* if value has not changed then we have consistent data */
609 id_prev = id;
610 id = fm10k_read_reg(hw, FM10K_TXQCTL(0));
611 } while ((id ^ id_prev) & FM10K_TXQCTL_ID_MASK);
612
613 /* drop non-ID bits and set VALID ID bit */
614 id &= FM10K_TXQCTL_ID_MASK;
615 id |= FM10K_STAT_VALID;
616
617 /* Update Global Statistics */
618 if (stats->stats_idx == id) {
619 stats->timeout.count += timeout;
620 stats->ur.count += ur;
621 stats->ca.count += ca;
622 stats->um.count += um;
623 stats->xec.count += xec;
624 stats->vlan_drop.count += vlan_drop;
625 stats->loopback_drop.count += loopback_drop;
626 stats->nodesc_drop.count += nodesc_drop;
627 }
628
629 /* Update bases and record current PF id */
630 fm10k_update_hw_base_32b(&stats->timeout, timeout);
631 fm10k_update_hw_base_32b(&stats->ur, ur);
632 fm10k_update_hw_base_32b(&stats->ca, ca);
633 fm10k_update_hw_base_32b(&stats->um, um);
634 fm10k_update_hw_base_32b(&stats->xec, xec);
635 fm10k_update_hw_base_32b(&stats->vlan_drop, vlan_drop);
636 fm10k_update_hw_base_32b(&stats->loopback_drop, loopback_drop);
637 fm10k_update_hw_base_32b(&stats->nodesc_drop, nodesc_drop);
638 stats->stats_idx = id;
639
640 /* Update Queue Statistics */
641 fm10k_update_hw_stats_q(hw, stats->q, 0, hw->mac.max_queues);
642}
643
644/**
645 * fm10k_rebind_hw_stats_pf - Resets base for hardware statistics of PF
646 * @hw: pointer to hardware structure
647 * @stats: pointer to the stats structure to update
648 *
649 * This function resets the base for global and per queue hardware
650 * statistics.
651 **/
652static void fm10k_rebind_hw_stats_pf(struct fm10k_hw *hw,
653 struct fm10k_hw_stats *stats)
654{
655 /* Unbind Global Statistics */
656 fm10k_unbind_hw_stats_32b(&stats->timeout);
657 fm10k_unbind_hw_stats_32b(&stats->ur);
658 fm10k_unbind_hw_stats_32b(&stats->ca);
659 fm10k_unbind_hw_stats_32b(&stats->um);
660 fm10k_unbind_hw_stats_32b(&stats->xec);
661 fm10k_unbind_hw_stats_32b(&stats->vlan_drop);
662 fm10k_unbind_hw_stats_32b(&stats->loopback_drop);
663 fm10k_unbind_hw_stats_32b(&stats->nodesc_drop);
664
665 /* Unbind Queue Statistics */
666 fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues);
667
668 /* Reinitialize bases for all stats */
669 fm10k_update_hw_stats_pf(hw, stats);
670}
671
672/**
Alexander Duyck401b5382014-09-20 19:47:58 -0400673 * fm10k_set_dma_mask_pf - Configures PhyAddrSpace to limit DMA to system
674 * @hw: pointer to hardware structure
675 * @dma_mask: 64 bit DMA mask required for platform
676 *
677 * This function sets the PHYADDR.PhyAddrSpace bits for the endpoint in order
678 * to limit the access to memory beyond what is physically in the system.
679 **/
680static void fm10k_set_dma_mask_pf(struct fm10k_hw *hw, u64 dma_mask)
681{
682 /* we need to write the upper 32 bits of DMA mask to PhyAddrSpace */
683 u32 phyaddr = (u32)(dma_mask >> 32);
684
685 fm10k_write_reg(hw, FM10K_PHYADDR, phyaddr);
686}
687
688/**
Alexander Duyckb6fec182014-09-20 19:47:46 -0400689 * fm10k_get_fault_pf - Record a fault in one of the interface units
690 * @hw: pointer to hardware structure
691 * @type: pointer to fault type register offset
692 * @fault: pointer to memory location to record the fault
693 *
694 * Record the fault register contents to the fault data structure and
695 * clear the entry from the register.
696 *
697 * Returns ERR_PARAM if invalid register is specified or no error is present.
698 **/
699static s32 fm10k_get_fault_pf(struct fm10k_hw *hw, int type,
700 struct fm10k_fault *fault)
701{
702 u32 func;
703
704 /* verify the fault register is in range and is aligned */
705 switch (type) {
706 case FM10K_PCA_FAULT:
707 case FM10K_THI_FAULT:
708 case FM10K_FUM_FAULT:
709 break;
710 default:
711 return FM10K_ERR_PARAM;
712 }
713
714 /* only service faults that are valid */
715 func = fm10k_read_reg(hw, type + FM10K_FAULT_FUNC);
716 if (!(func & FM10K_FAULT_FUNC_VALID))
717 return FM10K_ERR_PARAM;
718
719 /* read remaining fields */
720 fault->address = fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_HI);
721 fault->address <<= 32;
722 fault->address = fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_LO);
723 fault->specinfo = fm10k_read_reg(hw, type + FM10K_FAULT_SPECINFO);
724
725 /* clear valid bit to allow for next error */
726 fm10k_write_reg(hw, type + FM10K_FAULT_FUNC, FM10K_FAULT_FUNC_VALID);
727
728 /* Record which function triggered the error */
729 if (func & FM10K_FAULT_FUNC_PF)
730 fault->func = 0;
731 else
732 fault->func = 1 + ((func & FM10K_FAULT_FUNC_VF_MASK) >>
733 FM10K_FAULT_FUNC_VF_SHIFT);
734
735 /* record fault type */
736 fault->type = func & FM10K_FAULT_FUNC_TYPE_MASK;
737
738 return 0;
739}
740
Alexander Duyck401b5382014-09-20 19:47:58 -0400741/**
742 * fm10k_request_lport_map_pf - Request LPORT map from the switch API
743 * @hw: pointer to hardware structure
744 *
745 **/
746static s32 fm10k_request_lport_map_pf(struct fm10k_hw *hw)
747{
748 struct fm10k_mbx_info *mbx = &hw->mbx;
749 u32 msg[1];
750
751 /* issue request asking for LPORT map */
752 fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_LPORT_MAP);
753
754 /* load onto outgoing mailbox */
755 return mbx->ops.enqueue_tx(hw, mbx, msg);
756}
757
758/**
759 * fm10k_get_host_state_pf - Returns the state of the switch and mailbox
760 * @hw: pointer to hardware structure
761 * @switch_ready: pointer to boolean value that will record switch state
762 *
763 * This funciton will check the DMA_CTRL2 register and mailbox in order
764 * to determine if the switch is ready for the PF to begin requesting
765 * addresses and mapping traffic to the local interface.
766 **/
767static s32 fm10k_get_host_state_pf(struct fm10k_hw *hw, bool *switch_ready)
768{
769 s32 ret_val = 0;
770 u32 dma_ctrl2;
771
772 /* verify the switch is ready for interraction */
773 dma_ctrl2 = fm10k_read_reg(hw, FM10K_DMA_CTRL2);
774 if (!(dma_ctrl2 & FM10K_DMA_CTRL2_SWITCH_READY))
775 goto out;
776
777 /* retrieve generic host state info */
778 ret_val = fm10k_get_host_state_generic(hw, switch_ready);
779 if (ret_val)
780 goto out;
781
782 /* interface cannot receive traffic without logical ports */
783 if (hw->mac.dglort_map == FM10K_DGLORTMAP_NONE)
784 ret_val = fm10k_request_lport_map_pf(hw);
785
786out:
787 return ret_val;
788}
789
790/* This structure defines the attibutes to be parsed below */
791const struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = {
792 FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_LPORT_MAP),
793 FM10K_TLV_ATTR_LAST
794};
795
796/**
797 * fm10k_msg_lport_map_pf - Message handler for lport_map message from SM
798 * @hw: Pointer to hardware structure
799 * @results: pointer array containing parsed data
800 * @mbx: Pointer to mailbox information structure
801 *
802 * This handler configures the lport mapping based on the reply from the
803 * switch API.
804 **/
805s32 fm10k_msg_lport_map_pf(struct fm10k_hw *hw, u32 **results,
806 struct fm10k_mbx_info *mbx)
807{
808 u16 glort, mask;
809 u32 dglort_map;
810 s32 err;
811
812 err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_LPORT_MAP],
813 &dglort_map);
814 if (err)
815 return err;
816
817 /* extract values out of the header */
818 glort = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_GLORT);
819 mask = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_MASK);
820
821 /* verify mask is set and none of the masked bits in glort are set */
822 if (!mask || (glort & ~mask))
823 return FM10K_ERR_PARAM;
824
825 /* verify the mask is contiguous, and that it is 1's followed by 0's */
826 if (((~(mask - 1) & mask) + mask) & FM10K_DGLORTMAP_NONE)
827 return FM10K_ERR_PARAM;
828
829 /* record the glort, mask, and port count */
830 hw->mac.dglort_map = dglort_map;
831
832 return 0;
833}
834
835const struct fm10k_tlv_attr fm10k_update_pvid_msg_attr[] = {
836 FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_UPDATE_PVID),
837 FM10K_TLV_ATTR_LAST
838};
839
840/**
841 * fm10k_msg_update_pvid_pf - Message handler for port VLAN message from SM
842 * @hw: Pointer to hardware structure
843 * @results: pointer array containing parsed data
844 * @mbx: Pointer to mailbox information structure
845 *
846 * This handler configures the default VLAN for the PF
847 **/
848s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results,
849 struct fm10k_mbx_info *mbx)
850{
851 u16 glort, pvid;
852 u32 pvid_update;
853 s32 err;
854
855 err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_UPDATE_PVID],
856 &pvid_update);
857 if (err)
858 return err;
859
860 /* extract values from the pvid update */
861 glort = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_GLORT);
862 pvid = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_PVID);
863
864 /* if glort is not valid return error */
865 if (!fm10k_glort_valid_pf(hw, glort))
866 return FM10K_ERR_PARAM;
867
868 /* verify VID is valid */
869 if (pvid >= FM10K_VLAN_TABLE_VID_MAX)
870 return FM10K_ERR_PARAM;
871
872 /* record the port VLAN ID value */
873 hw->mac.default_vid = pvid;
874
875 return 0;
876}
877
878/**
879 * fm10k_record_global_table_data - Move global table data to swapi table info
880 * @from: pointer to source table data structure
881 * @to: pointer to destination table info structure
882 *
883 * This function is will copy table_data to the table_info contained in
884 * the hw struct.
885 **/
886static void fm10k_record_global_table_data(struct fm10k_global_table_data *from,
887 struct fm10k_swapi_table_info *to)
888{
889 /* convert from le32 struct to CPU byte ordered values */
890 to->used = le32_to_cpu(from->used);
891 to->avail = le32_to_cpu(from->avail);
892}
893
894const struct fm10k_tlv_attr fm10k_err_msg_attr[] = {
895 FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR,
896 sizeof(struct fm10k_swapi_error)),
897 FM10K_TLV_ATTR_LAST
898};
899
900/**
901 * fm10k_msg_err_pf - Message handler for error reply
902 * @hw: Pointer to hardware structure
903 * @results: pointer array containing parsed data
904 * @mbx: Pointer to mailbox information structure
905 *
906 * This handler will capture the data for any error replies to previous
907 * messages that the PF has sent.
908 **/
909s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results,
910 struct fm10k_mbx_info *mbx)
911{
912 struct fm10k_swapi_error err_msg;
913 s32 err;
914
915 /* extract structure from message */
916 err = fm10k_tlv_attr_get_le_struct(results[FM10K_PF_ATTR_ID_ERR],
917 &err_msg, sizeof(err_msg));
918 if (err)
919 return err;
920
921 /* record table status */
922 fm10k_record_global_table_data(&err_msg.mac, &hw->swapi.mac);
923 fm10k_record_global_table_data(&err_msg.nexthop, &hw->swapi.nexthop);
924 fm10k_record_global_table_data(&err_msg.ffu, &hw->swapi.ffu);
925
926 /* record SW API status value */
927 hw->swapi.status = le32_to_cpu(err_msg.status);
928
929 return 0;
930}
931
932static const struct fm10k_msg_data fm10k_msg_data_pf[] = {
933 FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf),
934 FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf),
935 FM10K_PF_MSG_LPORT_MAP_HANDLER(fm10k_msg_lport_map_pf),
936 FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf),
937 FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf),
938 FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_msg_update_pvid_pf),
939 FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error),
940};
941
Alexander Duyckb6fec182014-09-20 19:47:46 -0400942static struct fm10k_mac_ops mac_ops_pf = {
943 .get_bus_info = &fm10k_get_bus_info_generic,
944 .reset_hw = &fm10k_reset_hw_pf,
945 .init_hw = &fm10k_init_hw_pf,
946 .start_hw = &fm10k_start_hw_generic,
947 .stop_hw = &fm10k_stop_hw_generic,
948 .is_slot_appropriate = &fm10k_is_slot_appropriate_pf,
Alexander Duyck401b5382014-09-20 19:47:58 -0400949 .update_vlan = &fm10k_update_vlan_pf,
Alexander Duyckb6fec182014-09-20 19:47:46 -0400950 .read_mac_addr = &fm10k_read_mac_addr_pf,
Alexander Duyck401b5382014-09-20 19:47:58 -0400951 .update_uc_addr = &fm10k_update_uc_addr_pf,
952 .update_mc_addr = &fm10k_update_mc_addr_pf,
953 .update_xcast_mode = &fm10k_update_xcast_mode_pf,
954 .update_int_moderator = &fm10k_update_int_moderator_pf,
955 .update_lport_state = &fm10k_update_lport_state_pf,
Alexander Duyckb6fec182014-09-20 19:47:46 -0400956 .update_hw_stats = &fm10k_update_hw_stats_pf,
957 .rebind_hw_stats = &fm10k_rebind_hw_stats_pf,
Alexander Duyck401b5382014-09-20 19:47:58 -0400958 .configure_dglort_map = &fm10k_configure_dglort_map_pf,
959 .set_dma_mask = &fm10k_set_dma_mask_pf,
Alexander Duyckb6fec182014-09-20 19:47:46 -0400960 .get_fault = &fm10k_get_fault_pf,
Alexander Duyck401b5382014-09-20 19:47:58 -0400961 .get_host_state = &fm10k_get_host_state_pf,
Alexander Duyckb6fec182014-09-20 19:47:46 -0400962};
963
Alexander Duyck401b5382014-09-20 19:47:58 -0400964static s32 fm10k_get_invariants_pf(struct fm10k_hw *hw)
965{
966 fm10k_get_invariants_generic(hw);
967
968 return fm10k_sm_mbx_init(hw, &hw->mbx, fm10k_msg_data_pf);
969}
970
Alexander Duyckb6fec182014-09-20 19:47:46 -0400971struct fm10k_info fm10k_pf_info = {
972 .mac = fm10k_mac_pf,
Alexander Duyck401b5382014-09-20 19:47:58 -0400973 .get_invariants = &fm10k_get_invariants_pf,
Alexander Duyckb6fec182014-09-20 19:47:46 -0400974 .mac_ops = &mac_ops_pf,
975};