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