FILE
ena_phc.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/amazon/ena/ena_phc.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* 3 * Copyright 2015-2022 Amazon.com, Inc. or its affiliates. All rights reserved. 4 */ 5 6#include <linux/pci.h> 7#include "ena_netdev.h" 8#include "ena_phc.h" 9#include "ena_devlink.h" 10 11static int ena_phc_adjtime(struct ptp_clock_info *clock_info, s64 delta) 12{ 13 return -EOPNOTSUPP; 14} 15 16static int ena_phc_adjfine(struct ptp_clock_info *clock_info, long scaled_ppm) 17{ 18 return -EOPNOTSUPP; 19} 20 21static int ena_phc_feature_enable(struct ptp_clock_info *clock_info, 22 struct ptp_clock_request *rq, 23 int on) 24{ 25 return -EOPNOTSUPP; 26} 27 28static int ena_phc_gettimex64(struct ptp_clock_info *clock_info, 29 struct timespec64 *ts, 30 struct ptp_system_timestamp *sts) 31{ 32 struct ena_phc_info *phc_info = 33 container_of(clock_info, struct ena_phc_info, clock_info); 34 unsigned long flags; 35 u64 timestamp_nsec; 36 int rc; 37 38 spin_lock_irqsave(&phc_info->lock, flags); 39 40 ptp_read_system_prets(sts); 41 42 rc = ena_com_phc_get_timestamp(phc_info->adapter->ena_dev, 43 ×tamp_nsec); 44 45 ptp_read_system_postts(sts); 46 47 spin_unlock_irqrestore(&phc_info->lock, flags); 48 49 *ts = ns_to_timespec64(timestamp_nsec); 50 51 return rc; 52} 53 54static int ena_phc_settime64(struct ptp_clock_info *clock_info, 55 const struct timespec64 *ts) 56{ 57 return -EOPNOTSUPP; 58} 59 60static struct ptp_clock_info ena_ptp_clock_info = { 61 .owner = THIS_MODULE, 62 .n_alarm = 0, 63 .n_ext_ts = 0, 64 .n_per_out = 0, 65 .pps = 0, 66 .adjtime = ena_phc_adjtime, 67 .adjfine = ena_phc_adjfine, 68 .gettimex64 = ena_phc_gettimex64, 69 .settime64 = ena_phc_settime64, 70 .enable = ena_phc_feature_enable, 71}; 72 73/* Enable/Disable PHC by the kernel, affects on the next init flow */ 74void ena_phc_enable(struct ena_adapter *adapter, bool enable) 75{ 76 struct ena_phc_info *phc_info = adapter->phc_info; 77 78 if (!phc_info) { 79 netdev_err(adapter->netdev, "phc_info is not allocated\n"); 80 return; 81 } 82 83 phc_info->enabled = enable; 84} 85 86/* Check if PHC is enabled by the kernel */ 87bool ena_phc_is_enabled(struct ena_adapter *adapter) 88{ 89 struct ena_phc_info *phc_info = adapter->phc_info; 90 91 return (phc_info && phc_info->enabled); 92} 93 94/* PHC is activated if ptp clock is registered in the kernel */ 95bool ena_phc_is_active(struct ena_adapter *adapter) 96{ 97 struct ena_phc_info *phc_info = adapter->phc_info; 98 99 return (phc_info && phc_info->clock); 100} 101 102static int ena_phc_register(struct ena_adapter *adapter) 103{ 104 struct pci_dev *pdev = adapter->pdev; 105 struct ptp_clock_info *clock_info; 106 struct ena_phc_info *phc_info; 107 int rc = 0; 108 109 phc_info = adapter->phc_info; 110 clock_info = &phc_info->clock_info; 111 112 /* PHC may already be registered in case of a reset */ 113 if (ena_phc_is_active(adapter)) 114 return 0; 115 116 phc_info->adapter = adapter; 117 118 spin_lock_init(&phc_info->lock); 119 120 /* Fill the ptp_clock_info struct and register PTP clock */ 121 *clock_info = ena_ptp_clock_info; 122 snprintf(clock_info->name, 123 sizeof(clock_info->name), 124 "ena-ptp-%02x", 125 PCI_SLOT(pdev->devfn)); 126 127 phc_info->clock = ptp_clock_register(clock_info, &pdev->dev); 128 if (IS_ERR(phc_info->clock)) { 129 rc = PTR_ERR(phc_info->clock); 130 netdev_err(adapter->netdev, "Failed registering ptp clock, error: %d\n", 131 rc); 132 phc_info->clock = NULL; 133 } 134 135 return rc; 136} 137 138static void ena_phc_unregister(struct ena_adapter *adapter) 139{ 140 struct ena_phc_info *phc_info = adapter->phc_info; 141 142 /* During reset flow, PHC must stay registered 143 * to keep kernel's PHC index 144 */ 145 if (ena_phc_is_active(adapter) && 146 !test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags)) { 147 ptp_clock_unregister(phc_info->clock); 148 phc_info->clock = NULL; 149 } 150} 151 152int ena_phc_alloc(struct ena_adapter *adapter) 153{ 154 /* Allocate driver specific PHC info */ 155 adapter->phc_info = vzalloc(sizeof(*adapter->phc_info)); 156 if (unlikely(!adapter->phc_info)) { 157 netdev_err(adapter->netdev, "Failed to alloc phc_info\n"); 158 return -ENOMEM; 159 } 160 161 return 0; 162} 163 164void ena_phc_free(struct ena_adapter *adapter) 165{ 166 if (adapter->phc_info) { 167 vfree(adapter->phc_info); 168 adapter->phc_info = NULL; 169 } 170} 171 172int ena_phc_init(struct ena_adapter *adapter) 173{ 174 struct ena_com_dev *ena_dev = adapter->ena_dev; 175 struct net_device *netdev = adapter->netdev; 176 int rc = -EOPNOTSUPP; 177 178 /* Validate PHC feature is supported in the device */ 179 if (!ena_com_phc_supported(ena_dev)) { 180 netdev_dbg(netdev, "PHC feature is not supported by the device\n"); 181 goto err_ena_com_phc_init; 182 } 183 184 /* Validate PHC feature is enabled by the kernel */ 185 if (!ena_phc_is_enabled(adapter)) { 186 netdev_dbg(netdev, "PHC feature is not enabled by the kernel\n"); 187 goto err_ena_com_phc_init; 188 } 189 190 /* Initialize device specific PHC info */ 191 rc = ena_com_phc_init(ena_dev); 192 if (unlikely(rc)) { 193 netdev_err(netdev, "Failed to init phc, error: %d\n", rc); 194 goto err_ena_com_phc_init; 195 } 196 197 /* Configure PHC feature in driver and device */ 198 rc = ena_com_phc_config(ena_dev); 199 if (unlikely(rc)) { 200 netdev_err(netdev, "Failed to config phc, error: %d\n", rc); 201 goto err_ena_com_phc_config; 202 } 203 204 /* Register to PTP class driver */ 205 rc = ena_phc_register(adapter); 206 if (unlikely(rc)) { 207 netdev_err(netdev, "Failed to register phc, error: %d\n", rc); 208 goto err_ena_com_phc_config; 209 } 210 211 return 0; 212 213err_ena_com_phc_config: 214 ena_com_phc_destroy(ena_dev); 215err_ena_com_phc_init: 216 ena_phc_enable(adapter, false); 217 ena_devlink_disable_phc_param(adapter->devlink); 218 return rc; 219} 220 221void ena_phc_destroy(struct ena_adapter *adapter) 222{ 223 ena_phc_unregister(adapter); 224 ena_com_phc_destroy(adapter->ena_dev); 225} 226 227int ena_phc_get_index(struct ena_adapter *adapter) 228{ 229 if (ena_phc_is_active(adapter)) 230 return ptp_clock_index(adapter->phc_info->clock); 231 232 return -1; 233}
~/
Read-only file preview.