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 10 static 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 27 static 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 35 void 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 52 void 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 64 static 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 74 static 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 81 static 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 104 static 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 131 static 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 137 static 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 160 struct 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 182 free_devlink: 183 devlink_free(devlink); 184 return NULL; 185 } 186 187 static 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 193 void ena_devlink_free(struct devlink *devlink) 194 { 195 ena_devlink_configure_params_clean(devlink); 196 197 devlink_free(devlink); 198 } 199 200 void 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 208 void 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 } 215