at master 214 lines 5.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) Amazon.com, Inc. or its affiliates. 3 * All rights reserved. 4 */ 5 6#include "linux/pci.h" 7#include "ena_devlink.h" 8#include "ena_phc.h" 9 10static int ena_devlink_enable_phc_validate(struct devlink *devlink, u32 id, 11 union devlink_param_value val, 12 struct netlink_ext_ack *extack) 13{ 14 struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink); 15 16 if (!val.vbool) 17 return 0; 18 19 if (!ena_com_phc_supported(adapter->ena_dev)) { 20 NL_SET_ERR_MSG_MOD(extack, "Device doesn't support PHC"); 21 return -EOPNOTSUPP; 22 } 23 24 return 0; 25} 26 27static const struct devlink_param ena_devlink_params[] = { 28 DEVLINK_PARAM_GENERIC(ENABLE_PHC, 29 BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 30 NULL, 31 NULL, 32 ena_devlink_enable_phc_validate), 33}; 34 35void ena_devlink_params_get(struct devlink *devlink) 36{ 37 struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink); 38 union devlink_param_value val; 39 int err; 40 41 err = devl_param_driverinit_value_get(devlink, 42 DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC, 43 &val); 44 if (err) { 45 netdev_err(adapter->netdev, "Failed to query PHC param\n"); 46 return; 47 } 48 49 ena_phc_enable(adapter, val.vbool); 50} 51 52void ena_devlink_disable_phc_param(struct devlink *devlink) 53{ 54 union devlink_param_value value; 55 56 devl_lock(devlink); 57 value.vbool = false; 58 devl_param_driverinit_value_set(devlink, 59 DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC, 60 value); 61 devl_unlock(devlink); 62} 63 64static void ena_devlink_port_register(struct devlink *devlink) 65{ 66 struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink); 67 struct devlink_port_attrs attrs = {}; 68 69 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 70 devlink_port_attrs_set(&adapter->devlink_port, &attrs); 71 devl_port_register(devlink, &adapter->devlink_port, 0); 72} 73 74static void ena_devlink_port_unregister(struct devlink *devlink) 75{ 76 struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink); 77 78 devl_port_unregister(&adapter->devlink_port); 79} 80 81static int ena_devlink_reload_down(struct devlink *devlink, 82 bool netns_change, 83 enum devlink_reload_action action, 84 enum devlink_reload_limit limit, 85 struct netlink_ext_ack *extack) 86{ 87 struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink); 88 89 if (netns_change) { 90 NL_SET_ERR_MSG_MOD(extack, 91 "Namespace change is not supported"); 92 return -EOPNOTSUPP; 93 } 94 95 ena_devlink_port_unregister(devlink); 96 97 rtnl_lock(); 98 ena_destroy_device(adapter, false); 99 rtnl_unlock(); 100 101 return 0; 102} 103 104static int ena_devlink_reload_up(struct devlink *devlink, 105 enum devlink_reload_action action, 106 enum devlink_reload_limit limit, 107 u32 *actions_performed, 108 struct netlink_ext_ack *extack) 109{ 110 struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink); 111 int err = 0; 112 113 rtnl_lock(); 114 /* Check that no other routine initialized the device (e.g. 115 * ena_fw_reset_device()). Also we're under devlink_mutex here, 116 * so devlink isn't freed under our feet. 117 */ 118 if (!test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags)) 119 err = ena_restore_device(adapter); 120 121 rtnl_unlock(); 122 123 ena_devlink_port_register(devlink); 124 125 if (!err) 126 *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 127 128 return err; 129} 130 131static const struct devlink_ops ena_devlink_ops = { 132 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT), 133 .reload_down = ena_devlink_reload_down, 134 .reload_up = ena_devlink_reload_up, 135}; 136 137static int ena_devlink_configure_params(struct devlink *devlink) 138{ 139 struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink); 140 union devlink_param_value value; 141 int rc; 142 143 rc = devlink_params_register(devlink, ena_devlink_params, 144 ARRAY_SIZE(ena_devlink_params)); 145 if (rc) { 146 netdev_err(adapter->netdev, "Failed to register devlink params\n"); 147 return rc; 148 } 149 150 devl_lock(devlink); 151 value.vbool = ena_phc_is_enabled(adapter); 152 devl_param_driverinit_value_set(devlink, 153 DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC, 154 value); 155 devl_unlock(devlink); 156 157 return 0; 158} 159 160struct devlink *ena_devlink_alloc(struct ena_adapter *adapter) 161{ 162 struct device *dev = &adapter->pdev->dev; 163 struct devlink *devlink; 164 165 devlink = devlink_alloc(&ena_devlink_ops, 166 sizeof(struct ena_adapter *), 167 dev); 168 if (!devlink) { 169 netdev_err(adapter->netdev, 170 "Failed to allocate devlink struct\n"); 171 return NULL; 172 } 173 174 ENA_DEVLINK_PRIV(devlink) = adapter; 175 adapter->devlink = devlink; 176 177 if (ena_devlink_configure_params(devlink)) 178 goto free_devlink; 179 180 return devlink; 181 182free_devlink: 183 devlink_free(devlink); 184 return NULL; 185} 186 187static void ena_devlink_configure_params_clean(struct devlink *devlink) 188{ 189 devlink_params_unregister(devlink, ena_devlink_params, 190 ARRAY_SIZE(ena_devlink_params)); 191} 192 193void ena_devlink_free(struct devlink *devlink) 194{ 195 ena_devlink_configure_params_clean(devlink); 196 197 devlink_free(devlink); 198} 199 200void ena_devlink_register(struct devlink *devlink, struct device *dev) 201{ 202 devl_lock(devlink); 203 ena_devlink_port_register(devlink); 204 devl_register(devlink); 205 devl_unlock(devlink); 206} 207 208void ena_devlink_unregister(struct devlink *devlink) 209{ 210 devl_lock(devlink); 211 ena_devlink_port_unregister(devlink); 212 devl_unregister(devlink); 213 devl_unlock(devlink); 214}