1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Huawei HiNIC PCI Express Linux driver 4 * Copyright(c) 2017 Huawei Technologies Co., Ltd 5 */ 6 7 #include <linux/types.h> 8 #include <linux/netdevice.h> 9 #include <linux/etherdevice.h> 10 #include <linux/if_vlan.h> 11 #include <linux/pci.h> 12 #include <linux/device.h> 13 #include <linux/errno.h> 14 15 #include "hinic_hw_if.h" 16 #include "hinic_hw_dev.h" 17 #include "hinic_port.h" 18 #include "hinic_dev.h" 19 20 #define HINIC_MIN_MTU_SIZE 256 21 #define HINIC_MAX_JUMBO_FRAME_SIZE 15872 22 23 enum mac_op { 24 MAC_DEL, 25 MAC_SET, 26 }; 27 28 /** 29 * change_mac - change(add or delete) mac address 30 * @nic_dev: nic device 31 * @addr: mac address 32 * @vlan_id: vlan number to set with the mac 33 * @op: add or delete the mac 34 * 35 * Return 0 - Success, negative - Failure 36 **/ 37 static int change_mac(struct hinic_dev *nic_dev, const u8 *addr, 38 u16 vlan_id, enum mac_op op) 39 { 40 struct net_device *netdev = nic_dev->netdev; 41 struct hinic_hwdev *hwdev = nic_dev->hwdev; 42 struct hinic_port_mac_cmd port_mac_cmd; 43 struct hinic_hwif *hwif = hwdev->hwif; 44 struct pci_dev *pdev = hwif->pdev; 45 enum hinic_port_cmd cmd; 46 u16 out_size; 47 int err; 48 49 if (vlan_id >= VLAN_N_VID) { 50 netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n"); 51 return -EINVAL; 52 } 53 54 if (op == MAC_SET) 55 cmd = HINIC_PORT_CMD_SET_MAC; 56 else 57 cmd = HINIC_PORT_CMD_DEL_MAC; 58 59 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif); 60 port_mac_cmd.vlan_id = vlan_id; 61 memcpy(port_mac_cmd.mac, addr, ETH_ALEN); 62 63 err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd, 64 sizeof(port_mac_cmd), 65 &port_mac_cmd, &out_size); 66 if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) { 67 dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n", 68 port_mac_cmd.status); 69 return -EFAULT; 70 } 71 72 return 0; 73 } 74 75 /** 76 * hinic_port_add_mac - add mac address 77 * @nic_dev: nic device 78 * @addr: mac address 79 * @vlan_id: vlan number to set with the mac 80 * 81 * Return 0 - Success, negative - Failure 82 **/ 83 int hinic_port_add_mac(struct hinic_dev *nic_dev, 84 const u8 *addr, u16 vlan_id) 85 { 86 return change_mac(nic_dev, addr, vlan_id, MAC_SET); 87 } 88 89 /** 90 * hinic_port_del_mac - remove mac address 91 * @nic_dev: nic device 92 * @addr: mac address 93 * @vlan_id: vlan number that is connected to the mac 94 * 95 * Return 0 - Success, negative - Failure 96 **/ 97 int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr, 98 u16 vlan_id) 99 { 100 return change_mac(nic_dev, addr, vlan_id, MAC_DEL); 101 } 102 103 /** 104 * hinic_port_get_mac - get the mac address of the nic device 105 * @nic_dev: nic device 106 * @addr: returned mac address 107 * 108 * Return 0 - Success, negative - Failure 109 **/ 110 int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr) 111 { 112 struct hinic_hwdev *hwdev = nic_dev->hwdev; 113 struct hinic_port_mac_cmd port_mac_cmd; 114 struct hinic_hwif *hwif = hwdev->hwif; 115 struct pci_dev *pdev = hwif->pdev; 116 u16 out_size; 117 int err; 118 119 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif); 120 121 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC, 122 &port_mac_cmd, sizeof(port_mac_cmd), 123 &port_mac_cmd, &out_size); 124 if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) { 125 dev_err(&pdev->dev, "Failed to get mac, ret = %d\n", 126 port_mac_cmd.status); 127 return -EFAULT; 128 } 129 130 memcpy(addr, port_mac_cmd.mac, ETH_ALEN); 131 return 0; 132 } 133 134 /** 135 * hinic_port_set_mtu - set mtu 136 * @nic_dev: nic device 137 * @new_mtu: new mtu 138 * 139 * Return 0 - Success, negative - Failure 140 **/ 141 int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu) 142 { 143 struct net_device *netdev = nic_dev->netdev; 144 struct hinic_hwdev *hwdev = nic_dev->hwdev; 145 struct hinic_port_mtu_cmd port_mtu_cmd; 146 struct hinic_hwif *hwif = hwdev->hwif; 147 struct pci_dev *pdev = hwif->pdev; 148 int err, max_frame; 149 u16 out_size; 150 151 if (new_mtu < HINIC_MIN_MTU_SIZE) { 152 netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size"); 153 return -EINVAL; 154 } 155 156 max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; 157 if (max_frame > HINIC_MAX_JUMBO_FRAME_SIZE) { 158 netif_err(nic_dev, drv, netdev, "mtu > MAX MTU size"); 159 return -EINVAL; 160 } 161 162 port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif); 163 port_mtu_cmd.mtu = new_mtu; 164 165 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU, 166 &port_mtu_cmd, sizeof(port_mtu_cmd), 167 &port_mtu_cmd, &out_size); 168 if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) { 169 dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n", 170 port_mtu_cmd.status); 171 return -EFAULT; 172 } 173 174 return 0; 175 } 176 177 /** 178 * hinic_port_add_vlan - add vlan to the nic device 179 * @nic_dev: nic device 180 * @vlan_id: the vlan number to add 181 * 182 * Return 0 - Success, negative - Failure 183 **/ 184 int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id) 185 { 186 struct hinic_hwdev *hwdev = nic_dev->hwdev; 187 struct hinic_port_vlan_cmd port_vlan_cmd; 188 189 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif); 190 port_vlan_cmd.vlan_id = vlan_id; 191 192 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN, 193 &port_vlan_cmd, sizeof(port_vlan_cmd), 194 NULL, NULL); 195 } 196 197 /** 198 * hinic_port_del_vlan - delete vlan from the nic device 199 * @nic_dev: nic device 200 * @vlan_id: the vlan number to delete 201 * 202 * Return 0 - Success, negative - Failure 203 **/ 204 int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id) 205 { 206 struct hinic_hwdev *hwdev = nic_dev->hwdev; 207 struct hinic_port_vlan_cmd port_vlan_cmd; 208 209 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif); 210 port_vlan_cmd.vlan_id = vlan_id; 211 212 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN, 213 &port_vlan_cmd, sizeof(port_vlan_cmd), 214 NULL, NULL); 215 } 216 217 /** 218 * hinic_port_set_rx_mode - set rx mode in the nic device 219 * @nic_dev: nic device 220 * @rx_mode: the rx mode to set 221 * 222 * Return 0 - Success, negative - Failure 223 **/ 224 int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode) 225 { 226 struct hinic_hwdev *hwdev = nic_dev->hwdev; 227 struct hinic_port_rx_mode_cmd rx_mode_cmd; 228 229 rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif); 230 rx_mode_cmd.rx_mode = rx_mode; 231 232 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE, 233 &rx_mode_cmd, sizeof(rx_mode_cmd), 234 NULL, NULL); 235 } 236 237 /** 238 * hinic_port_link_state - get the link state 239 * @nic_dev: nic device 240 * @link_state: the returned link state 241 * 242 * Return 0 - Success, negative - Failure 243 **/ 244 int hinic_port_link_state(struct hinic_dev *nic_dev, 245 enum hinic_port_link_state *link_state) 246 { 247 struct hinic_hwdev *hwdev = nic_dev->hwdev; 248 struct hinic_hwif *hwif = hwdev->hwif; 249 struct hinic_port_link_cmd link_cmd; 250 struct pci_dev *pdev = hwif->pdev; 251 u16 out_size; 252 int err; 253 254 if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { 255 dev_err(&pdev->dev, "unsupported PCI Function type\n"); 256 return -EINVAL; 257 } 258 259 link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif); 260 261 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE, 262 &link_cmd, sizeof(link_cmd), 263 &link_cmd, &out_size); 264 if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) { 265 dev_err(&pdev->dev, "Failed to get link state, ret = %d\n", 266 link_cmd.status); 267 return -EINVAL; 268 } 269 270 *link_state = link_cmd.state; 271 return 0; 272 } 273 274 /** 275 * hinic_port_set_state - set port state 276 * @nic_dev: nic device 277 * @state: the state to set 278 * 279 * Return 0 - Success, negative - Failure 280 **/ 281 int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state) 282 { 283 struct hinic_hwdev *hwdev = nic_dev->hwdev; 284 struct hinic_port_state_cmd port_state; 285 struct hinic_hwif *hwif = hwdev->hwif; 286 struct pci_dev *pdev = hwif->pdev; 287 u16 out_size; 288 int err; 289 290 if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { 291 dev_err(&pdev->dev, "unsupported PCI Function type\n"); 292 return -EINVAL; 293 } 294 295 port_state.state = state; 296 297 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE, 298 &port_state, sizeof(port_state), 299 &port_state, &out_size); 300 if (err || (out_size != sizeof(port_state)) || port_state.status) { 301 dev_err(&pdev->dev, "Failed to set port state, ret = %d\n", 302 port_state.status); 303 return -EFAULT; 304 } 305 306 return 0; 307 } 308 309 /** 310 * hinic_port_set_func_state- set func device state 311 * @nic_dev: nic device 312 * @state: the state to set 313 * 314 * Return 0 - Success, negative - Failure 315 **/ 316 int hinic_port_set_func_state(struct hinic_dev *nic_dev, 317 enum hinic_func_port_state state) 318 { 319 struct hinic_port_func_state_cmd func_state; 320 struct hinic_hwdev *hwdev = nic_dev->hwdev; 321 struct hinic_hwif *hwif = hwdev->hwif; 322 struct pci_dev *pdev = hwif->pdev; 323 u16 out_size; 324 int err; 325 326 func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif); 327 func_state.state = state; 328 329 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE, 330 &func_state, sizeof(func_state), 331 &func_state, &out_size); 332 if (err || (out_size != sizeof(func_state)) || func_state.status) { 333 dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n", 334 func_state.status); 335 return -EFAULT; 336 } 337 338 return 0; 339 } 340 341 /** 342 * hinic_port_get_cap - get port capabilities 343 * @nic_dev: nic device 344 * @port_cap: returned port capabilities 345 * 346 * Return 0 - Success, negative - Failure 347 **/ 348 int hinic_port_get_cap(struct hinic_dev *nic_dev, 349 struct hinic_port_cap *port_cap) 350 { 351 struct hinic_hwdev *hwdev = nic_dev->hwdev; 352 struct hinic_hwif *hwif = hwdev->hwif; 353 struct pci_dev *pdev = hwif->pdev; 354 u16 out_size; 355 int err; 356 357 port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif); 358 359 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP, 360 port_cap, sizeof(*port_cap), 361 port_cap, &out_size); 362 if (err || (out_size != sizeof(*port_cap)) || port_cap->status) { 363 dev_err(&pdev->dev, 364 "Failed to get port capabilities, ret = %d\n", 365 port_cap->status); 366 return -EINVAL; 367 } 368 369 return 0; 370 } 371 372 /** 373 * hinic_port_set_tso - set port tso configuration 374 * @nic_dev: nic device 375 * @state: the tso state to set 376 * 377 * Return 0 - Success, negative - Failure 378 **/ 379 int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state) 380 { 381 struct hinic_hwdev *hwdev = nic_dev->hwdev; 382 struct hinic_hwif *hwif = hwdev->hwif; 383 struct hinic_tso_config tso_cfg = {0}; 384 struct pci_dev *pdev = hwif->pdev; 385 u16 out_size; 386 int err; 387 388 tso_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif); 389 tso_cfg.tso_en = state; 390 391 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_TSO, 392 &tso_cfg, sizeof(tso_cfg), 393 &tso_cfg, &out_size); 394 if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) { 395 dev_err(&pdev->dev, 396 "Failed to set port tso, ret = %d\n", 397 tso_cfg.status); 398 return -EINVAL; 399 } 400 401 return 0; 402 } 403 404 int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en) 405 { 406 struct hinic_checksum_offload rx_csum_cfg = {0}; 407 struct hinic_hwdev *hwdev = nic_dev->hwdev; 408 struct hinic_hwif *hwif; 409 struct pci_dev *pdev; 410 u16 out_size; 411 int err; 412 413 if (!hwdev) 414 return -EINVAL; 415 416 hwif = hwdev->hwif; 417 pdev = hwif->pdev; 418 rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif); 419 rx_csum_cfg.rx_csum_offload = en; 420 421 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM, 422 &rx_csum_cfg, sizeof(rx_csum_cfg), 423 &rx_csum_cfg, &out_size); 424 if (err || !out_size || rx_csum_cfg.status) { 425 dev_err(&pdev->dev, 426 "Failed to set rx csum offload, ret = %d\n", 427 rx_csum_cfg.status); 428 return -EINVAL; 429 } 430 431 return 0; 432 } 433