aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2014-09-20 19:53:40 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-09-23 06:59:22 -0400
commit5f226ddb5b0c477bd512085b0b1d1052a24f0020 (patch)
tree75b962d536ceac983d15339c91516e487c523ff4 /drivers/net
parent7461fd913afe3a830b47cf133a6ad53e49a5db8b (diff)
fm10k: Add support for ptp to hw specific files
This change adds the messaging support needed to support PTP. In the case of Tx timestamps it is necessary for the Switch Management entity to return the frames via the mailbox as the host interface cannot know which port the timestamp will be delivered to. In addition there is only one clock on the entire switch, as such the entity that has BAR 4 access is the only one who can actually update the frequency as it is the only one with access. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_common.h8
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pf.c99
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_type.h14
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_vf.c55
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_vf.h10
5 files changed, 186 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_common.h b/drivers/net/ethernet/intel/fm10k/fm10k_common.h
index 8250e1432a27..45e4e5b1f20a 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_common.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_common.h
@@ -39,6 +39,14 @@ do { \
39 writel((val), &hw_addr[(reg)]); \ 39 writel((val), &hw_addr[(reg)]); \
40} while (0) 40} while (0)
41 41
42/* Switch register write operations, index using DWORDS */
43#define fm10k_write_sw_reg(hw, reg, val) \
44do { \
45 u32 __iomem *sw_addr = ACCESS_ONCE((hw)->sw_addr); \
46 if (!FM10K_REMOVED(sw_addr)) \
47 writel((val), &sw_addr[(reg)]); \
48} while (0)
49
42/* read ctrl register which has no clear on read fields as PCIe flush */ 50/* read ctrl register which has no clear on read fields as PCIe flush */
43#define fm10k_write_flush(hw) fm10k_read_reg((hw), FM10K_CTRL) 51#define fm10k_write_flush(hw) fm10k_read_reg((hw), FM10K_CTRL)
44s32 fm10k_get_bus_info_generic(struct fm10k_hw *hw); 52s32 fm10k_get_bus_info_generic(struct fm10k_hw *hw);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
index 0b6ce1082304..275423d4f777 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
@@ -1123,6 +1123,19 @@ static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw,
1123 fm10k_update_hw_stats_q(hw, q, idx, qpp); 1123 fm10k_update_hw_stats_q(hw, q, idx, qpp);
1124} 1124}
1125 1125
1126static s32 fm10k_iov_report_timestamp_pf(struct fm10k_hw *hw,
1127 struct fm10k_vf_info *vf_info,
1128 u64 timestamp)
1129{
1130 u32 msg[4];
1131
1132 /* generate port state response to notify VF it is not ready */
1133 fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_1588);
1134 fm10k_tlv_attr_put_u64(msg, FM10K_1588_MSG_TIMESTAMP, timestamp);
1135
1136 return vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg);
1137}
1138
1126/** 1139/**
1127 * fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF 1140 * fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF
1128 * @hw: Pointer to hardware structure 1141 * @hw: Pointer to hardware structure
@@ -1723,6 +1736,89 @@ s32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results,
1723 return 0; 1736 return 0;
1724} 1737}
1725 1738
1739const struct fm10k_tlv_attr fm10k_1588_timestamp_msg_attr[] = {
1740 FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_1588_TIMESTAMP,
1741 sizeof(struct fm10k_swapi_1588_timestamp)),
1742 FM10K_TLV_ATTR_LAST
1743};
1744
1745/* currently there is no shared 1588 timestamp handler */
1746
1747/**
1748 * fm10k_adjust_systime_pf - Adjust systime frequency
1749 * @hw: pointer to hardware structure
1750 * @ppb: adjustment rate in parts per billion
1751 *
1752 * This function will adjust the SYSTIME_CFG register contained in BAR 4
1753 * if this function is supported for BAR 4 access. The adjustment amount
1754 * is based on the parts per billion value provided and adjusted to a
1755 * value based on parts per 2^48 clock cycles.
1756 *
1757 * If adjustment is not supported or the requested value is too large
1758 * we will return an error.
1759 **/
1760static s32 fm10k_adjust_systime_pf(struct fm10k_hw *hw, s32 ppb)
1761{
1762 u64 systime_adjust;
1763
1764 /* if sw_addr is not set we don't have switch register access */
1765 if (!hw->sw_addr)
1766 return ppb ? FM10K_ERR_PARAM : 0;
1767
1768 /* we must convert the value from parts per billion to parts per
1769 * 2^48 cycles. In addition I have opted to only use the 30 most
1770 * significant bits of the adjustment value as the 8 least
1771 * significant bits are located in another register and represent
1772 * a value significantly less than a part per billion, the result
1773 * of dropping the 8 least significant bits is that the adjustment
1774 * value is effectively multiplied by 2^8 when we write it.
1775 *
1776 * As a result of all this the math for this breaks down as follows:
1777 * ppb / 10^9 == adjust * 2^8 / 2^48
1778 * If we solve this for adjust, and simplify it comes out as:
1779 * ppb * 2^31 / 5^9 == adjust
1780 */
1781 systime_adjust = (ppb < 0) ? -ppb : ppb;
1782 systime_adjust <<= 31;
1783 do_div(systime_adjust, 1953125);
1784
1785 /* verify the requested adjustment value is in range */
1786 if (systime_adjust > FM10K_SW_SYSTIME_ADJUST_MASK)
1787 return FM10K_ERR_PARAM;
1788
1789 if (ppb < 0)
1790 systime_adjust |= FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE;
1791
1792 fm10k_write_sw_reg(hw, FM10K_SW_SYSTIME_ADJUST, (u32)systime_adjust);
1793
1794 return 0;
1795}
1796
1797/**
1798 * fm10k_read_systime_pf - Reads value of systime registers
1799 * @hw: pointer to the hardware structure
1800 *
1801 * Function reads the content of 2 registers, combined to represent a 64 bit
1802 * value measured in nanosecods. In order to guarantee the value is accurate
1803 * we check the 32 most significant bits both before and after reading the
1804 * 32 least significant bits to verify they didn't change as we were reading
1805 * the registers.
1806 **/
1807static u64 fm10k_read_systime_pf(struct fm10k_hw *hw)
1808{
1809 u32 systime_l, systime_h, systime_tmp;
1810
1811 systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1);
1812
1813 do {
1814 systime_tmp = systime_h;
1815 systime_l = fm10k_read_reg(hw, FM10K_SYSTIME);
1816 systime_h = fm10k_read_reg(hw, FM10K_SYSTIME + 1);
1817 } while (systime_tmp != systime_h);
1818
1819 return ((u64)systime_h << 32) | systime_l;
1820}
1821
1726static const struct fm10k_msg_data fm10k_msg_data_pf[] = { 1822static const struct fm10k_msg_data fm10k_msg_data_pf[] = {
1727 FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), 1823 FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf),
1728 FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), 1824 FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf),
@@ -1753,6 +1849,8 @@ static struct fm10k_mac_ops mac_ops_pf = {
1753 .set_dma_mask = &fm10k_set_dma_mask_pf, 1849 .set_dma_mask = &fm10k_set_dma_mask_pf,
1754 .get_fault = &fm10k_get_fault_pf, 1850 .get_fault = &fm10k_get_fault_pf,
1755 .get_host_state = &fm10k_get_host_state_pf, 1851 .get_host_state = &fm10k_get_host_state_pf,
1852 .adjust_systime = &fm10k_adjust_systime_pf,
1853 .read_systime = &fm10k_read_systime_pf,
1756}; 1854};
1757 1855
1758static struct fm10k_iov_ops iov_ops_pf = { 1856static struct fm10k_iov_ops iov_ops_pf = {
@@ -1764,6 +1862,7 @@ static struct fm10k_iov_ops iov_ops_pf = {
1764 .set_lport = &fm10k_iov_set_lport_pf, 1862 .set_lport = &fm10k_iov_set_lport_pf,
1765 .reset_lport = &fm10k_iov_reset_lport_pf, 1863 .reset_lport = &fm10k_iov_reset_lport_pf,
1766 .update_stats = &fm10k_iov_update_stats_pf, 1864 .update_stats = &fm10k_iov_update_stats_pf,
1865 .report_timestamp = &fm10k_iov_report_timestamp_pf,
1767}; 1866};
1768 1867
1769static s32 fm10k_get_invariants_pf(struct fm10k_hw *hw) 1868static s32 fm10k_get_invariants_pf(struct fm10k_hw *hw)
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
index ecaf93a380cd..280296f29154 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h
@@ -224,6 +224,11 @@ struct fm10k_hw;
224#define FM10K_STATS_LOOPBACK_DROP 0x3806 224#define FM10K_STATS_LOOPBACK_DROP 0x3806
225#define FM10K_STATS_NODESC_DROP 0x3807 225#define FM10K_STATS_NODESC_DROP 0x3807
226 226
227/* Timesync registers */
228#define FM10K_SYSTIME 0x3814
229#define FM10K_SYSTIME_CFG 0x3818
230#define FM10K_SYSTIME_CFG_STEP_MASK 0x0000000F
231
227/* PCIe state registers */ 232/* PCIe state registers */
228#define FM10K_PHYADDR 0x381C 233#define FM10K_PHYADDR 0x381C
229 234
@@ -358,6 +363,12 @@ struct fm10k_hw;
358#define FM10K_VFSYSTIME 0x00040 363#define FM10K_VFSYSTIME 0x00040
359#define FM10K_VFITR(_n) ((_n) + 0x00060) 364#define FM10K_VFITR(_n) ((_n) + 0x00060)
360 365
366/* Registers contained in BAR 4 for Switch management */
367#define FM10K_SW_SYSTIME_ADJUST 0x0224D
368#define FM10K_SW_SYSTIME_ADJUST_MASK 0x3FFFFFFF
369#define FM10K_SW_SYSTIME_ADJUST_DIR_NEGATIVE 0x80000000
370#define FM10K_SW_SYSTIME_PULSE(_n) ((_n) + 0x02252)
371
361enum fm10k_int_source { 372enum fm10k_int_source {
362 fm10k_int_Mailbox = 0, 373 fm10k_int_Mailbox = 0,
363 fm10k_int_PCIeFault = 1, 374 fm10k_int_PCIeFault = 1,
@@ -524,6 +535,7 @@ struct fm10k_mac_ops {
524 s32 (*get_fault)(struct fm10k_hw *, int, struct fm10k_fault *); 535 s32 (*get_fault)(struct fm10k_hw *, int, struct fm10k_fault *);
525 void (*request_lport_map)(struct fm10k_hw *); 536 void (*request_lport_map)(struct fm10k_hw *);
526 s32 (*adjust_systime)(struct fm10k_hw *, s32 ppb); 537 s32 (*adjust_systime)(struct fm10k_hw *, s32 ppb);
538 u64 (*read_systime)(struct fm10k_hw *);
527}; 539};
528 540
529enum fm10k_mac_type { 541enum fm10k_mac_type {
@@ -614,6 +626,7 @@ struct fm10k_iov_ops {
614 s32 (*set_lport)(struct fm10k_hw *, struct fm10k_vf_info *, u16, u8); 626 s32 (*set_lport)(struct fm10k_hw *, struct fm10k_vf_info *, u16, u8);
615 void (*reset_lport)(struct fm10k_hw *, struct fm10k_vf_info *); 627 void (*reset_lport)(struct fm10k_hw *, struct fm10k_vf_info *);
616 void (*update_stats)(struct fm10k_hw *, struct fm10k_hw_stats_q *, u16); 628 void (*update_stats)(struct fm10k_hw *, struct fm10k_hw_stats_q *, u16);
629 s32 (*report_timestamp)(struct fm10k_hw *, struct fm10k_vf_info *, u64);
617}; 630};
618 631
619struct fm10k_iov_info { 632struct fm10k_iov_info {
@@ -637,6 +650,7 @@ struct fm10k_info {
637 650
638struct fm10k_hw { 651struct fm10k_hw {
639 u32 __iomem *hw_addr; 652 u32 __iomem *hw_addr;
653 u32 __iomem *sw_addr;
640 void *back; 654 void *back;
641 struct fm10k_mac_info mac; 655 struct fm10k_mac_info mac;
642 struct fm10k_bus_info bus; 656 struct fm10k_bus_info bus;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
index 25c23fce60f8..f0aa0f97b4a9 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c
@@ -431,6 +431,13 @@ static s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, u16 glort, u8 mode)
431 return mbx->ops.enqueue_tx(hw, mbx, msg); 431 return mbx->ops.enqueue_tx(hw, mbx, msg);
432} 432}
433 433
434const struct fm10k_tlv_attr fm10k_1588_msg_attr[] = {
435 FM10K_TLV_ATTR_U64(FM10K_1588_MSG_TIMESTAMP),
436 FM10K_TLV_ATTR_LAST
437};
438
439/* currently there is no shared 1588 timestamp handler */
440
434/** 441/**
435 * fm10k_update_hw_stats_vf - Updates hardware related statistics of VF 442 * fm10k_update_hw_stats_vf - Updates hardware related statistics of VF
436 * @hw: pointer to hardware structure 443 * @hw: pointer to hardware structure
@@ -482,6 +489,52 @@ static s32 fm10k_configure_dglort_map_vf(struct fm10k_hw *hw,
482 return 0; 489 return 0;
483} 490}
484 491
492/**
493 * fm10k_adjust_systime_vf - Adjust systime frequency
494 * @hw: pointer to hardware structure
495 * @ppb: adjustment rate in parts per billion
496 *
497 * This function takes an adjustment rate in parts per billion and will
498 * verify that this value is 0 as the VF cannot support adjusting the
499 * systime clock.
500 *
501 * If the ppb value is non-zero the return is ERR_PARAM else success
502 **/
503static s32 fm10k_adjust_systime_vf(struct fm10k_hw *hw, s32 ppb)
504{
505 /* The VF cannot adjust the clock frequency, however it should
506 * already have a syntonic clock with whichever host interface is
507 * running as the master for the host interface clock domain so
508 * there should be not frequency adjustment necessary.
509 */
510 return ppb ? FM10K_ERR_PARAM : 0;
511}
512
513/**
514 * fm10k_read_systime_vf - Reads value of systime registers
515 * @hw: pointer to the hardware structure
516 *
517 * Function reads the content of 2 registers, combined to represent a 64 bit
518 * value measured in nanosecods. In order to guarantee the value is accurate
519 * we check the 32 most significant bits both before and after reading the
520 * 32 least significant bits to verify they didn't change as we were reading
521 * the registers.
522 **/
523static u64 fm10k_read_systime_vf(struct fm10k_hw *hw)
524{
525 u32 systime_l, systime_h, systime_tmp;
526
527 systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
528
529 do {
530 systime_tmp = systime_h;
531 systime_l = fm10k_read_reg(hw, FM10K_VFSYSTIME);
532 systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
533 } while (systime_tmp != systime_h);
534
535 return ((u64)systime_h << 32) | systime_l;
536}
537
485static const struct fm10k_msg_data fm10k_msg_data_vf[] = { 538static const struct fm10k_msg_data fm10k_msg_data_vf[] = {
486 FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), 539 FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test),
487 FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf), 540 FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf),
@@ -507,6 +560,8 @@ static struct fm10k_mac_ops mac_ops_vf = {
507 .rebind_hw_stats = &fm10k_rebind_hw_stats_vf, 560 .rebind_hw_stats = &fm10k_rebind_hw_stats_vf,
508 .configure_dglort_map = &fm10k_configure_dglort_map_vf, 561 .configure_dglort_map = &fm10k_configure_dglort_map_vf,
509 .get_host_state = &fm10k_get_host_state_generic, 562 .get_host_state = &fm10k_get_host_state_generic,
563 .adjust_systime = &fm10k_adjust_systime_vf,
564 .read_systime = &fm10k_read_systime_vf,
510}; 565};
511 566
512static s32 fm10k_get_invariants_vf(struct fm10k_hw *hw) 567static s32 fm10k_get_invariants_vf(struct fm10k_hw *hw)
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.h b/drivers/net/ethernet/intel/fm10k/fm10k_vf.h
index 8e96ee53c147..06a99d794c99 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.h
@@ -29,6 +29,7 @@ enum fm10k_vf_tlv_msg_id {
29 FM10K_VF_MSG_ID_MSIX, 29 FM10K_VF_MSG_ID_MSIX,
30 FM10K_VF_MSG_ID_MAC_VLAN, 30 FM10K_VF_MSG_ID_MAC_VLAN,
31 FM10K_VF_MSG_ID_LPORT_STATE, 31 FM10K_VF_MSG_ID_LPORT_STATE,
32 FM10K_VF_MSG_ID_1588,
32 FM10K_VF_MSG_ID_MAX, 33 FM10K_VF_MSG_ID_MAX,
33}; 34};
34 35
@@ -48,6 +49,11 @@ enum fm10k_tlv_lport_state_attr_id {
48 FM10K_LPORT_STATE_MSG_MAX 49 FM10K_LPORT_STATE_MSG_MAX
49}; 50};
50 51
52enum fm10k_tlv_1588_attr_id {
53 FM10K_1588_MSG_TIMESTAMP,
54 FM10K_1588_MSG_MAX
55};
56
51#define FM10K_VF_MSG_MSIX_HANDLER(func) \ 57#define FM10K_VF_MSG_MSIX_HANDLER(func) \
52 FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_MSIX, NULL, func) 58 FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_MSIX, NULL, func)
53 59
@@ -64,5 +70,9 @@ extern const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[];
64 FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_LPORT_STATE, \ 70 FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_LPORT_STATE, \
65 fm10k_lport_state_msg_attr, func) 71 fm10k_lport_state_msg_attr, func)
66 72
73extern const struct fm10k_tlv_attr fm10k_1588_msg_attr[];
74#define FM10K_VF_MSG_1588_HANDLER(func) \
75 FM10K_MSG_HANDLER(FM10K_VF_MSG_ID_1588, fm10k_1588_msg_attr, func)
76
67extern struct fm10k_info fm10k_vf_info; 77extern struct fm10k_info fm10k_vf_info;
68#endif /* _FM10K_VF_H */ 78#endif /* _FM10K_VF_H */