1*915cc7acSMustafa Ismail // SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB 2*915cc7acSMustafa Ismail /* Copyright (c) 2015 - 2021 Intel Corporation */ 3*915cc7acSMustafa Ismail #include "main.h" 4*915cc7acSMustafa Ismail 5*915cc7acSMustafa Ismail /** 6*915cc7acSMustafa Ismail * irdma_arp_table -manage arp table 7*915cc7acSMustafa Ismail * @rf: RDMA PCI function 8*915cc7acSMustafa Ismail * @ip_addr: ip address for device 9*915cc7acSMustafa Ismail * @ipv4: IPv4 flag 10*915cc7acSMustafa Ismail * @mac_addr: mac address ptr 11*915cc7acSMustafa Ismail * @action: modify, delete or add 12*915cc7acSMustafa Ismail */ 13*915cc7acSMustafa Ismail int irdma_arp_table(struct irdma_pci_f *rf, u32 *ip_addr, bool ipv4, 14*915cc7acSMustafa Ismail u8 *mac_addr, u32 action) 15*915cc7acSMustafa Ismail { 16*915cc7acSMustafa Ismail unsigned long flags; 17*915cc7acSMustafa Ismail int arp_index; 18*915cc7acSMustafa Ismail u32 ip[4] = {}; 19*915cc7acSMustafa Ismail 20*915cc7acSMustafa Ismail if (ipv4) 21*915cc7acSMustafa Ismail ip[0] = *ip_addr; 22*915cc7acSMustafa Ismail else 23*915cc7acSMustafa Ismail memcpy(ip, ip_addr, sizeof(ip)); 24*915cc7acSMustafa Ismail 25*915cc7acSMustafa Ismail spin_lock_irqsave(&rf->arp_lock, flags); 26*915cc7acSMustafa Ismail for (arp_index = 0; (u32)arp_index < rf->arp_table_size; arp_index++) { 27*915cc7acSMustafa Ismail if (!memcmp(rf->arp_table[arp_index].ip_addr, ip, sizeof(ip))) 28*915cc7acSMustafa Ismail break; 29*915cc7acSMustafa Ismail } 30*915cc7acSMustafa Ismail 31*915cc7acSMustafa Ismail switch (action) { 32*915cc7acSMustafa Ismail case IRDMA_ARP_ADD: 33*915cc7acSMustafa Ismail if (arp_index != rf->arp_table_size) { 34*915cc7acSMustafa Ismail arp_index = -1; 35*915cc7acSMustafa Ismail break; 36*915cc7acSMustafa Ismail } 37*915cc7acSMustafa Ismail 38*915cc7acSMustafa Ismail arp_index = 0; 39*915cc7acSMustafa Ismail if (irdma_alloc_rsrc(rf, rf->allocated_arps, rf->arp_table_size, 40*915cc7acSMustafa Ismail (u32 *)&arp_index, &rf->next_arp_index)) { 41*915cc7acSMustafa Ismail arp_index = -1; 42*915cc7acSMustafa Ismail break; 43*915cc7acSMustafa Ismail } 44*915cc7acSMustafa Ismail 45*915cc7acSMustafa Ismail memcpy(rf->arp_table[arp_index].ip_addr, ip, 46*915cc7acSMustafa Ismail sizeof(rf->arp_table[arp_index].ip_addr)); 47*915cc7acSMustafa Ismail ether_addr_copy(rf->arp_table[arp_index].mac_addr, mac_addr); 48*915cc7acSMustafa Ismail break; 49*915cc7acSMustafa Ismail case IRDMA_ARP_RESOLVE: 50*915cc7acSMustafa Ismail if (arp_index == rf->arp_table_size) 51*915cc7acSMustafa Ismail arp_index = -1; 52*915cc7acSMustafa Ismail break; 53*915cc7acSMustafa Ismail case IRDMA_ARP_DELETE: 54*915cc7acSMustafa Ismail if (arp_index == rf->arp_table_size) { 55*915cc7acSMustafa Ismail arp_index = -1; 56*915cc7acSMustafa Ismail break; 57*915cc7acSMustafa Ismail } 58*915cc7acSMustafa Ismail 59*915cc7acSMustafa Ismail memset(rf->arp_table[arp_index].ip_addr, 0, 60*915cc7acSMustafa Ismail sizeof(rf->arp_table[arp_index].ip_addr)); 61*915cc7acSMustafa Ismail eth_zero_addr(rf->arp_table[arp_index].mac_addr); 62*915cc7acSMustafa Ismail irdma_free_rsrc(rf, rf->allocated_arps, arp_index); 63*915cc7acSMustafa Ismail break; 64*915cc7acSMustafa Ismail default: 65*915cc7acSMustafa Ismail arp_index = -1; 66*915cc7acSMustafa Ismail break; 67*915cc7acSMustafa Ismail } 68*915cc7acSMustafa Ismail 69*915cc7acSMustafa Ismail spin_unlock_irqrestore(&rf->arp_lock, flags); 70*915cc7acSMustafa Ismail return arp_index; 71*915cc7acSMustafa Ismail } 72*915cc7acSMustafa Ismail 73*915cc7acSMustafa Ismail /** 74*915cc7acSMustafa Ismail * irdma_add_arp - add a new arp entry if needed 75*915cc7acSMustafa Ismail * @rf: RDMA function 76*915cc7acSMustafa Ismail * @ip: IP address 77*915cc7acSMustafa Ismail * @ipv4: IPv4 flag 78*915cc7acSMustafa Ismail * @mac: MAC address 79*915cc7acSMustafa Ismail */ 80*915cc7acSMustafa Ismail int irdma_add_arp(struct irdma_pci_f *rf, u32 *ip, bool ipv4, u8 *mac) 81*915cc7acSMustafa Ismail { 82*915cc7acSMustafa Ismail int arpidx; 83*915cc7acSMustafa Ismail 84*915cc7acSMustafa Ismail arpidx = irdma_arp_table(rf, &ip[0], ipv4, NULL, IRDMA_ARP_RESOLVE); 85*915cc7acSMustafa Ismail if (arpidx >= 0) { 86*915cc7acSMustafa Ismail if (ether_addr_equal(rf->arp_table[arpidx].mac_addr, mac)) 87*915cc7acSMustafa Ismail return arpidx; 88*915cc7acSMustafa Ismail 89*915cc7acSMustafa Ismail irdma_manage_arp_cache(rf, rf->arp_table[arpidx].mac_addr, ip, 90*915cc7acSMustafa Ismail ipv4, IRDMA_ARP_DELETE); 91*915cc7acSMustafa Ismail } 92*915cc7acSMustafa Ismail 93*915cc7acSMustafa Ismail irdma_manage_arp_cache(rf, mac, ip, ipv4, IRDMA_ARP_ADD); 94*915cc7acSMustafa Ismail 95*915cc7acSMustafa Ismail return irdma_arp_table(rf, ip, ipv4, NULL, IRDMA_ARP_RESOLVE); 96*915cc7acSMustafa Ismail } 97*915cc7acSMustafa Ismail 98*915cc7acSMustafa Ismail /** 99*915cc7acSMustafa Ismail * wr32 - write 32 bits to hw register 100*915cc7acSMustafa Ismail * @hw: hardware information including registers 101*915cc7acSMustafa Ismail * @reg: register offset 102*915cc7acSMustafa Ismail * @val: value to write to register 103*915cc7acSMustafa Ismail */ 104*915cc7acSMustafa Ismail inline void wr32(struct irdma_hw *hw, u32 reg, u32 val) 105*915cc7acSMustafa Ismail { 106*915cc7acSMustafa Ismail writel(val, hw->hw_addr + reg); 107*915cc7acSMustafa Ismail } 108*915cc7acSMustafa Ismail 109*915cc7acSMustafa Ismail /** 110*915cc7acSMustafa Ismail * rd32 - read a 32 bit hw register 111*915cc7acSMustafa Ismail * @hw: hardware information including registers 112*915cc7acSMustafa Ismail * @reg: register offset 113*915cc7acSMustafa Ismail * 114*915cc7acSMustafa Ismail * Return value of register content 115*915cc7acSMustafa Ismail */ 116*915cc7acSMustafa Ismail inline u32 rd32(struct irdma_hw *hw, u32 reg) 117*915cc7acSMustafa Ismail { 118*915cc7acSMustafa Ismail return readl(hw->hw_addr + reg); 119*915cc7acSMustafa Ismail } 120*915cc7acSMustafa Ismail 121*915cc7acSMustafa Ismail /** 122*915cc7acSMustafa Ismail * rd64 - read a 64 bit hw register 123*915cc7acSMustafa Ismail * @hw: hardware information including registers 124*915cc7acSMustafa Ismail * @reg: register offset 125*915cc7acSMustafa Ismail * 126*915cc7acSMustafa Ismail * Return value of register content 127*915cc7acSMustafa Ismail */ 128*915cc7acSMustafa Ismail inline u64 rd64(struct irdma_hw *hw, u32 reg) 129*915cc7acSMustafa Ismail { 130*915cc7acSMustafa Ismail return readq(hw->hw_addr + reg); 131*915cc7acSMustafa Ismail } 132*915cc7acSMustafa Ismail 133*915cc7acSMustafa Ismail static void irdma_gid_change_event(struct ib_device *ibdev) 134*915cc7acSMustafa Ismail { 135*915cc7acSMustafa Ismail struct ib_event ib_event; 136*915cc7acSMustafa Ismail 137*915cc7acSMustafa Ismail ib_event.event = IB_EVENT_GID_CHANGE; 138*915cc7acSMustafa Ismail ib_event.device = ibdev; 139*915cc7acSMustafa Ismail ib_event.element.port_num = 1; 140*915cc7acSMustafa Ismail ib_dispatch_event(&ib_event); 141*915cc7acSMustafa Ismail } 142*915cc7acSMustafa Ismail 143*915cc7acSMustafa Ismail /** 144*915cc7acSMustafa Ismail * irdma_inetaddr_event - system notifier for ipv4 addr events 145*915cc7acSMustafa Ismail * @notifier: not used 146*915cc7acSMustafa Ismail * @event: event for notifier 147*915cc7acSMustafa Ismail * @ptr: if address 148*915cc7acSMustafa Ismail */ 149*915cc7acSMustafa Ismail int irdma_inetaddr_event(struct notifier_block *notifier, unsigned long event, 150*915cc7acSMustafa Ismail void *ptr) 151*915cc7acSMustafa Ismail { 152*915cc7acSMustafa Ismail struct in_ifaddr *ifa = ptr; 153*915cc7acSMustafa Ismail struct net_device *netdev = ifa->ifa_dev->dev; 154*915cc7acSMustafa Ismail struct irdma_device *iwdev; 155*915cc7acSMustafa Ismail struct ib_device *ibdev; 156*915cc7acSMustafa Ismail u32 local_ipaddr; 157*915cc7acSMustafa Ismail 158*915cc7acSMustafa Ismail ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_IRDMA); 159*915cc7acSMustafa Ismail if (!ibdev) 160*915cc7acSMustafa Ismail return NOTIFY_DONE; 161*915cc7acSMustafa Ismail 162*915cc7acSMustafa Ismail iwdev = to_iwdev(ibdev); 163*915cc7acSMustafa Ismail local_ipaddr = ntohl(ifa->ifa_address); 164*915cc7acSMustafa Ismail ibdev_dbg(&iwdev->ibdev, 165*915cc7acSMustafa Ismail "DEV: netdev %p event %lu local_ip=%pI4 MAC=%pM\n", netdev, 166*915cc7acSMustafa Ismail event, &local_ipaddr, netdev->dev_addr); 167*915cc7acSMustafa Ismail switch (event) { 168*915cc7acSMustafa Ismail case NETDEV_DOWN: 169*915cc7acSMustafa Ismail irdma_manage_arp_cache(iwdev->rf, netdev->dev_addr, 170*915cc7acSMustafa Ismail &local_ipaddr, true, IRDMA_ARP_DELETE); 171*915cc7acSMustafa Ismail irdma_if_notify(iwdev, netdev, &local_ipaddr, true, false); 172*915cc7acSMustafa Ismail irdma_gid_change_event(&iwdev->ibdev); 173*915cc7acSMustafa Ismail break; 174*915cc7acSMustafa Ismail case NETDEV_UP: 175*915cc7acSMustafa Ismail case NETDEV_CHANGEADDR: 176*915cc7acSMustafa Ismail irdma_add_arp(iwdev->rf, &local_ipaddr, true, netdev->dev_addr); 177*915cc7acSMustafa Ismail irdma_if_notify(iwdev, netdev, &local_ipaddr, true, true); 178*915cc7acSMustafa Ismail irdma_gid_change_event(&iwdev->ibdev); 179*915cc7acSMustafa Ismail break; 180*915cc7acSMustafa Ismail default: 181*915cc7acSMustafa Ismail break; 182*915cc7acSMustafa Ismail } 183*915cc7acSMustafa Ismail 184*915cc7acSMustafa Ismail ib_device_put(ibdev); 185*915cc7acSMustafa Ismail 186*915cc7acSMustafa Ismail return NOTIFY_DONE; 187*915cc7acSMustafa Ismail } 188*915cc7acSMustafa Ismail 189*915cc7acSMustafa Ismail /** 190*915cc7acSMustafa Ismail * irdma_inet6addr_event - system notifier for ipv6 addr events 191*915cc7acSMustafa Ismail * @notifier: not used 192*915cc7acSMustafa Ismail * @event: event for notifier 193*915cc7acSMustafa Ismail * @ptr: if address 194*915cc7acSMustafa Ismail */ 195*915cc7acSMustafa Ismail int irdma_inet6addr_event(struct notifier_block *notifier, unsigned long event, 196*915cc7acSMustafa Ismail void *ptr) 197*915cc7acSMustafa Ismail { 198*915cc7acSMustafa Ismail struct inet6_ifaddr *ifa = ptr; 199*915cc7acSMustafa Ismail struct net_device *netdev = ifa->idev->dev; 200*915cc7acSMustafa Ismail struct irdma_device *iwdev; 201*915cc7acSMustafa Ismail struct ib_device *ibdev; 202*915cc7acSMustafa Ismail u32 local_ipaddr6[4]; 203*915cc7acSMustafa Ismail 204*915cc7acSMustafa Ismail ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_IRDMA); 205*915cc7acSMustafa Ismail if (!ibdev) 206*915cc7acSMustafa Ismail return NOTIFY_DONE; 207*915cc7acSMustafa Ismail 208*915cc7acSMustafa Ismail iwdev = to_iwdev(ibdev); 209*915cc7acSMustafa Ismail irdma_copy_ip_ntohl(local_ipaddr6, ifa->addr.in6_u.u6_addr32); 210*915cc7acSMustafa Ismail ibdev_dbg(&iwdev->ibdev, 211*915cc7acSMustafa Ismail "DEV: netdev %p event %lu local_ip=%pI6 MAC=%pM\n", netdev, 212*915cc7acSMustafa Ismail event, local_ipaddr6, netdev->dev_addr); 213*915cc7acSMustafa Ismail switch (event) { 214*915cc7acSMustafa Ismail case NETDEV_DOWN: 215*915cc7acSMustafa Ismail irdma_manage_arp_cache(iwdev->rf, netdev->dev_addr, 216*915cc7acSMustafa Ismail local_ipaddr6, false, IRDMA_ARP_DELETE); 217*915cc7acSMustafa Ismail irdma_if_notify(iwdev, netdev, local_ipaddr6, false, false); 218*915cc7acSMustafa Ismail irdma_gid_change_event(&iwdev->ibdev); 219*915cc7acSMustafa Ismail break; 220*915cc7acSMustafa Ismail case NETDEV_UP: 221*915cc7acSMustafa Ismail case NETDEV_CHANGEADDR: 222*915cc7acSMustafa Ismail irdma_add_arp(iwdev->rf, local_ipaddr6, false, 223*915cc7acSMustafa Ismail netdev->dev_addr); 224*915cc7acSMustafa Ismail irdma_if_notify(iwdev, netdev, local_ipaddr6, false, true); 225*915cc7acSMustafa Ismail irdma_gid_change_event(&iwdev->ibdev); 226*915cc7acSMustafa Ismail break; 227*915cc7acSMustafa Ismail default: 228*915cc7acSMustafa Ismail break; 229*915cc7acSMustafa Ismail } 230*915cc7acSMustafa Ismail 231*915cc7acSMustafa Ismail ib_device_put(ibdev); 232*915cc7acSMustafa Ismail 233*915cc7acSMustafa Ismail return NOTIFY_DONE; 234*915cc7acSMustafa Ismail } 235*915cc7acSMustafa Ismail 236*915cc7acSMustafa Ismail /** 237*915cc7acSMustafa Ismail * irdma_net_event - system notifier for net events 238*915cc7acSMustafa Ismail * @notifier: not used 239*915cc7acSMustafa Ismail * @event: event for notifier 240*915cc7acSMustafa Ismail * @ptr: neighbor 241*915cc7acSMustafa Ismail */ 242*915cc7acSMustafa Ismail int irdma_net_event(struct notifier_block *notifier, unsigned long event, 243*915cc7acSMustafa Ismail void *ptr) 244*915cc7acSMustafa Ismail { 245*915cc7acSMustafa Ismail struct neighbour *neigh = ptr; 246*915cc7acSMustafa Ismail struct irdma_device *iwdev; 247*915cc7acSMustafa Ismail struct ib_device *ibdev; 248*915cc7acSMustafa Ismail __be32 *p; 249*915cc7acSMustafa Ismail u32 local_ipaddr[4] = {}; 250*915cc7acSMustafa Ismail bool ipv4 = true; 251*915cc7acSMustafa Ismail 252*915cc7acSMustafa Ismail ibdev = ib_device_get_by_netdev((struct net_device *)neigh->dev, 253*915cc7acSMustafa Ismail RDMA_DRIVER_IRDMA); 254*915cc7acSMustafa Ismail if (!ibdev) 255*915cc7acSMustafa Ismail return NOTIFY_DONE; 256*915cc7acSMustafa Ismail 257*915cc7acSMustafa Ismail iwdev = to_iwdev(ibdev); 258*915cc7acSMustafa Ismail 259*915cc7acSMustafa Ismail switch (event) { 260*915cc7acSMustafa Ismail case NETEVENT_NEIGH_UPDATE: 261*915cc7acSMustafa Ismail p = (__be32 *)neigh->primary_key; 262*915cc7acSMustafa Ismail if (neigh->tbl->family == AF_INET6) { 263*915cc7acSMustafa Ismail ipv4 = false; 264*915cc7acSMustafa Ismail irdma_copy_ip_ntohl(local_ipaddr, p); 265*915cc7acSMustafa Ismail } else { 266*915cc7acSMustafa Ismail local_ipaddr[0] = ntohl(*p); 267*915cc7acSMustafa Ismail } 268*915cc7acSMustafa Ismail 269*915cc7acSMustafa Ismail ibdev_dbg(&iwdev->ibdev, 270*915cc7acSMustafa Ismail "DEV: netdev %p state %d local_ip=%pI4 MAC=%pM\n", 271*915cc7acSMustafa Ismail iwdev->netdev, neigh->nud_state, local_ipaddr, 272*915cc7acSMustafa Ismail neigh->ha); 273*915cc7acSMustafa Ismail 274*915cc7acSMustafa Ismail if (neigh->nud_state & NUD_VALID) 275*915cc7acSMustafa Ismail irdma_add_arp(iwdev->rf, local_ipaddr, ipv4, neigh->ha); 276*915cc7acSMustafa Ismail 277*915cc7acSMustafa Ismail else 278*915cc7acSMustafa Ismail irdma_manage_arp_cache(iwdev->rf, neigh->ha, 279*915cc7acSMustafa Ismail local_ipaddr, ipv4, 280*915cc7acSMustafa Ismail IRDMA_ARP_DELETE); 281*915cc7acSMustafa Ismail break; 282*915cc7acSMustafa Ismail default: 283*915cc7acSMustafa Ismail break; 284*915cc7acSMustafa Ismail } 285*915cc7acSMustafa Ismail 286*915cc7acSMustafa Ismail ib_device_put(ibdev); 287*915cc7acSMustafa Ismail 288*915cc7acSMustafa Ismail return NOTIFY_DONE; 289*915cc7acSMustafa Ismail } 290*915cc7acSMustafa Ismail 291*915cc7acSMustafa Ismail /** 292*915cc7acSMustafa Ismail * irdma_netdevice_event - system notifier for netdev events 293*915cc7acSMustafa Ismail * @notifier: not used 294*915cc7acSMustafa Ismail * @event: event for notifier 295*915cc7acSMustafa Ismail * @ptr: netdev 296*915cc7acSMustafa Ismail */ 297*915cc7acSMustafa Ismail int irdma_netdevice_event(struct notifier_block *notifier, unsigned long event, 298*915cc7acSMustafa Ismail void *ptr) 299*915cc7acSMustafa Ismail { 300*915cc7acSMustafa Ismail struct irdma_device *iwdev; 301*915cc7acSMustafa Ismail struct ib_device *ibdev; 302*915cc7acSMustafa Ismail struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 303*915cc7acSMustafa Ismail 304*915cc7acSMustafa Ismail ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_IRDMA); 305*915cc7acSMustafa Ismail if (!ibdev) 306*915cc7acSMustafa Ismail return NOTIFY_DONE; 307*915cc7acSMustafa Ismail 308*915cc7acSMustafa Ismail iwdev = to_iwdev(ibdev); 309*915cc7acSMustafa Ismail iwdev->iw_status = 1; 310*915cc7acSMustafa Ismail switch (event) { 311*915cc7acSMustafa Ismail case NETDEV_DOWN: 312*915cc7acSMustafa Ismail iwdev->iw_status = 0; 313*915cc7acSMustafa Ismail fallthrough; 314*915cc7acSMustafa Ismail case NETDEV_UP: 315*915cc7acSMustafa Ismail irdma_port_ibevent(iwdev); 316*915cc7acSMustafa Ismail break; 317*915cc7acSMustafa Ismail default: 318*915cc7acSMustafa Ismail break; 319*915cc7acSMustafa Ismail } 320*915cc7acSMustafa Ismail ib_device_put(ibdev); 321*915cc7acSMustafa Ismail 322*915cc7acSMustafa Ismail return NOTIFY_DONE; 323*915cc7acSMustafa Ismail } 324*915cc7acSMustafa Ismail 325*915cc7acSMustafa Ismail /** 326*915cc7acSMustafa Ismail * irdma_add_ipv6_addr - add ipv6 address to the hw arp table 327*915cc7acSMustafa Ismail * @iwdev: irdma device 328*915cc7acSMustafa Ismail */ 329*915cc7acSMustafa Ismail static void irdma_add_ipv6_addr(struct irdma_device *iwdev) 330*915cc7acSMustafa Ismail { 331*915cc7acSMustafa Ismail struct net_device *ip_dev; 332*915cc7acSMustafa Ismail struct inet6_dev *idev; 333*915cc7acSMustafa Ismail struct inet6_ifaddr *ifp, *tmp; 334*915cc7acSMustafa Ismail u32 local_ipaddr6[4]; 335*915cc7acSMustafa Ismail 336*915cc7acSMustafa Ismail rcu_read_lock(); 337*915cc7acSMustafa Ismail for_each_netdev_rcu (&init_net, ip_dev) { 338*915cc7acSMustafa Ismail if (((rdma_vlan_dev_vlan_id(ip_dev) < 0xFFFF && 339*915cc7acSMustafa Ismail rdma_vlan_dev_real_dev(ip_dev) == iwdev->netdev) || 340*915cc7acSMustafa Ismail ip_dev == iwdev->netdev) && 341*915cc7acSMustafa Ismail (READ_ONCE(ip_dev->flags) & IFF_UP)) { 342*915cc7acSMustafa Ismail idev = __in6_dev_get(ip_dev); 343*915cc7acSMustafa Ismail if (!idev) { 344*915cc7acSMustafa Ismail ibdev_err(&iwdev->ibdev, "ipv6 inet device not found\n"); 345*915cc7acSMustafa Ismail break; 346*915cc7acSMustafa Ismail } 347*915cc7acSMustafa Ismail list_for_each_entry_safe (ifp, tmp, &idev->addr_list, 348*915cc7acSMustafa Ismail if_list) { 349*915cc7acSMustafa Ismail ibdev_dbg(&iwdev->ibdev, 350*915cc7acSMustafa Ismail "INIT: IP=%pI6, vlan_id=%d, MAC=%pM\n", 351*915cc7acSMustafa Ismail &ifp->addr, 352*915cc7acSMustafa Ismail rdma_vlan_dev_vlan_id(ip_dev), 353*915cc7acSMustafa Ismail ip_dev->dev_addr); 354*915cc7acSMustafa Ismail 355*915cc7acSMustafa Ismail irdma_copy_ip_ntohl(local_ipaddr6, 356*915cc7acSMustafa Ismail ifp->addr.in6_u.u6_addr32); 357*915cc7acSMustafa Ismail irdma_manage_arp_cache(iwdev->rf, 358*915cc7acSMustafa Ismail ip_dev->dev_addr, 359*915cc7acSMustafa Ismail local_ipaddr6, false, 360*915cc7acSMustafa Ismail IRDMA_ARP_ADD); 361*915cc7acSMustafa Ismail } 362*915cc7acSMustafa Ismail } 363*915cc7acSMustafa Ismail } 364*915cc7acSMustafa Ismail rcu_read_unlock(); 365*915cc7acSMustafa Ismail } 366*915cc7acSMustafa Ismail 367*915cc7acSMustafa Ismail /** 368*915cc7acSMustafa Ismail * irdma_add_ipv4_addr - add ipv4 address to the hw arp table 369*915cc7acSMustafa Ismail * @iwdev: irdma device 370*915cc7acSMustafa Ismail */ 371*915cc7acSMustafa Ismail static void irdma_add_ipv4_addr(struct irdma_device *iwdev) 372*915cc7acSMustafa Ismail { 373*915cc7acSMustafa Ismail struct net_device *dev; 374*915cc7acSMustafa Ismail struct in_device *idev; 375*915cc7acSMustafa Ismail u32 ip_addr; 376*915cc7acSMustafa Ismail 377*915cc7acSMustafa Ismail rcu_read_lock(); 378*915cc7acSMustafa Ismail for_each_netdev_rcu (&init_net, dev) { 379*915cc7acSMustafa Ismail if (((rdma_vlan_dev_vlan_id(dev) < 0xFFFF && 380*915cc7acSMustafa Ismail rdma_vlan_dev_real_dev(dev) == iwdev->netdev) || 381*915cc7acSMustafa Ismail dev == iwdev->netdev) && (READ_ONCE(dev->flags) & IFF_UP)) { 382*915cc7acSMustafa Ismail const struct in_ifaddr *ifa; 383*915cc7acSMustafa Ismail 384*915cc7acSMustafa Ismail idev = __in_dev_get_rcu(dev); 385*915cc7acSMustafa Ismail if (!idev) 386*915cc7acSMustafa Ismail continue; 387*915cc7acSMustafa Ismail 388*915cc7acSMustafa Ismail in_dev_for_each_ifa_rcu(ifa, idev) { 389*915cc7acSMustafa Ismail ibdev_dbg(&iwdev->ibdev, "CM: IP=%pI4, vlan_id=%d, MAC=%pM\n", 390*915cc7acSMustafa Ismail &ifa->ifa_address, rdma_vlan_dev_vlan_id(dev), 391*915cc7acSMustafa Ismail dev->dev_addr); 392*915cc7acSMustafa Ismail 393*915cc7acSMustafa Ismail ip_addr = ntohl(ifa->ifa_address); 394*915cc7acSMustafa Ismail irdma_manage_arp_cache(iwdev->rf, dev->dev_addr, 395*915cc7acSMustafa Ismail &ip_addr, true, 396*915cc7acSMustafa Ismail IRDMA_ARP_ADD); 397*915cc7acSMustafa Ismail } 398*915cc7acSMustafa Ismail } 399*915cc7acSMustafa Ismail } 400*915cc7acSMustafa Ismail rcu_read_unlock(); 401*915cc7acSMustafa Ismail } 402*915cc7acSMustafa Ismail 403*915cc7acSMustafa Ismail /** 404*915cc7acSMustafa Ismail * irdma_add_ip - add ip addresses 405*915cc7acSMustafa Ismail * @iwdev: irdma device 406*915cc7acSMustafa Ismail * 407*915cc7acSMustafa Ismail * Add ipv4/ipv6 addresses to the arp cache 408*915cc7acSMustafa Ismail */ 409*915cc7acSMustafa Ismail void irdma_add_ip(struct irdma_device *iwdev) 410*915cc7acSMustafa Ismail { 411*915cc7acSMustafa Ismail irdma_add_ipv4_addr(iwdev); 412*915cc7acSMustafa Ismail irdma_add_ipv6_addr(iwdev); 413*915cc7acSMustafa Ismail } 414*915cc7acSMustafa Ismail 415*915cc7acSMustafa Ismail /** 416*915cc7acSMustafa Ismail * irdma_alloc_and_get_cqp_request - get cqp struct 417*915cc7acSMustafa Ismail * @cqp: device cqp ptr 418*915cc7acSMustafa Ismail * @wait: cqp to be used in wait mode 419*915cc7acSMustafa Ismail */ 420*915cc7acSMustafa Ismail struct irdma_cqp_request *irdma_alloc_and_get_cqp_request(struct irdma_cqp *cqp, 421*915cc7acSMustafa Ismail bool wait) 422*915cc7acSMustafa Ismail { 423*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request = NULL; 424*915cc7acSMustafa Ismail unsigned long flags; 425*915cc7acSMustafa Ismail 426*915cc7acSMustafa Ismail spin_lock_irqsave(&cqp->req_lock, flags); 427*915cc7acSMustafa Ismail if (!list_empty(&cqp->cqp_avail_reqs)) { 428*915cc7acSMustafa Ismail cqp_request = list_entry(cqp->cqp_avail_reqs.next, 429*915cc7acSMustafa Ismail struct irdma_cqp_request, list); 430*915cc7acSMustafa Ismail list_del_init(&cqp_request->list); 431*915cc7acSMustafa Ismail } 432*915cc7acSMustafa Ismail spin_unlock_irqrestore(&cqp->req_lock, flags); 433*915cc7acSMustafa Ismail if (!cqp_request) { 434*915cc7acSMustafa Ismail cqp_request = kzalloc(sizeof(*cqp_request), GFP_ATOMIC); 435*915cc7acSMustafa Ismail if (cqp_request) { 436*915cc7acSMustafa Ismail cqp_request->dynamic = true; 437*915cc7acSMustafa Ismail if (wait) 438*915cc7acSMustafa Ismail init_waitqueue_head(&cqp_request->waitq); 439*915cc7acSMustafa Ismail } 440*915cc7acSMustafa Ismail } 441*915cc7acSMustafa Ismail if (!cqp_request) { 442*915cc7acSMustafa Ismail ibdev_dbg(to_ibdev(cqp->sc_cqp.dev), "ERR: CQP Request Fail: No Memory"); 443*915cc7acSMustafa Ismail return NULL; 444*915cc7acSMustafa Ismail } 445*915cc7acSMustafa Ismail 446*915cc7acSMustafa Ismail cqp_request->waiting = wait; 447*915cc7acSMustafa Ismail refcount_set(&cqp_request->refcnt, 1); 448*915cc7acSMustafa Ismail memset(&cqp_request->compl_info, 0, sizeof(cqp_request->compl_info)); 449*915cc7acSMustafa Ismail 450*915cc7acSMustafa Ismail return cqp_request; 451*915cc7acSMustafa Ismail } 452*915cc7acSMustafa Ismail 453*915cc7acSMustafa Ismail /** 454*915cc7acSMustafa Ismail * irdma_get_cqp_request - increase refcount for cqp_request 455*915cc7acSMustafa Ismail * @cqp_request: pointer to cqp_request instance 456*915cc7acSMustafa Ismail */ 457*915cc7acSMustafa Ismail static inline void irdma_get_cqp_request(struct irdma_cqp_request *cqp_request) 458*915cc7acSMustafa Ismail { 459*915cc7acSMustafa Ismail refcount_inc(&cqp_request->refcnt); 460*915cc7acSMustafa Ismail } 461*915cc7acSMustafa Ismail 462*915cc7acSMustafa Ismail /** 463*915cc7acSMustafa Ismail * irdma_free_cqp_request - free cqp request 464*915cc7acSMustafa Ismail * @cqp: cqp ptr 465*915cc7acSMustafa Ismail * @cqp_request: to be put back in cqp list 466*915cc7acSMustafa Ismail */ 467*915cc7acSMustafa Ismail void irdma_free_cqp_request(struct irdma_cqp *cqp, 468*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request) 469*915cc7acSMustafa Ismail { 470*915cc7acSMustafa Ismail unsigned long flags; 471*915cc7acSMustafa Ismail 472*915cc7acSMustafa Ismail if (cqp_request->dynamic) { 473*915cc7acSMustafa Ismail kfree(cqp_request); 474*915cc7acSMustafa Ismail } else { 475*915cc7acSMustafa Ismail cqp_request->request_done = false; 476*915cc7acSMustafa Ismail cqp_request->callback_fcn = NULL; 477*915cc7acSMustafa Ismail cqp_request->waiting = false; 478*915cc7acSMustafa Ismail 479*915cc7acSMustafa Ismail spin_lock_irqsave(&cqp->req_lock, flags); 480*915cc7acSMustafa Ismail list_add_tail(&cqp_request->list, &cqp->cqp_avail_reqs); 481*915cc7acSMustafa Ismail spin_unlock_irqrestore(&cqp->req_lock, flags); 482*915cc7acSMustafa Ismail } 483*915cc7acSMustafa Ismail wake_up(&cqp->remove_wq); 484*915cc7acSMustafa Ismail } 485*915cc7acSMustafa Ismail 486*915cc7acSMustafa Ismail /** 487*915cc7acSMustafa Ismail * irdma_put_cqp_request - dec ref count and free if 0 488*915cc7acSMustafa Ismail * @cqp: cqp ptr 489*915cc7acSMustafa Ismail * @cqp_request: to be put back in cqp list 490*915cc7acSMustafa Ismail */ 491*915cc7acSMustafa Ismail void irdma_put_cqp_request(struct irdma_cqp *cqp, 492*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request) 493*915cc7acSMustafa Ismail { 494*915cc7acSMustafa Ismail if (refcount_dec_and_test(&cqp_request->refcnt)) 495*915cc7acSMustafa Ismail irdma_free_cqp_request(cqp, cqp_request); 496*915cc7acSMustafa Ismail } 497*915cc7acSMustafa Ismail 498*915cc7acSMustafa Ismail /** 499*915cc7acSMustafa Ismail * irdma_free_pending_cqp_request -free pending cqp request objs 500*915cc7acSMustafa Ismail * @cqp: cqp ptr 501*915cc7acSMustafa Ismail * @cqp_request: to be put back in cqp list 502*915cc7acSMustafa Ismail */ 503*915cc7acSMustafa Ismail static void 504*915cc7acSMustafa Ismail irdma_free_pending_cqp_request(struct irdma_cqp *cqp, 505*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request) 506*915cc7acSMustafa Ismail { 507*915cc7acSMustafa Ismail if (cqp_request->waiting) { 508*915cc7acSMustafa Ismail cqp_request->compl_info.error = true; 509*915cc7acSMustafa Ismail cqp_request->request_done = true; 510*915cc7acSMustafa Ismail wake_up(&cqp_request->waitq); 511*915cc7acSMustafa Ismail } 512*915cc7acSMustafa Ismail wait_event_timeout(cqp->remove_wq, 513*915cc7acSMustafa Ismail refcount_read(&cqp_request->refcnt) == 1, 1000); 514*915cc7acSMustafa Ismail irdma_put_cqp_request(cqp, cqp_request); 515*915cc7acSMustafa Ismail } 516*915cc7acSMustafa Ismail 517*915cc7acSMustafa Ismail /** 518*915cc7acSMustafa Ismail * irdma_cleanup_pending_cqp_op - clean-up cqp with no 519*915cc7acSMustafa Ismail * completions 520*915cc7acSMustafa Ismail * @rf: RDMA PCI function 521*915cc7acSMustafa Ismail */ 522*915cc7acSMustafa Ismail void irdma_cleanup_pending_cqp_op(struct irdma_pci_f *rf) 523*915cc7acSMustafa Ismail { 524*915cc7acSMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 525*915cc7acSMustafa Ismail struct irdma_cqp *cqp = &rf->cqp; 526*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request = NULL; 527*915cc7acSMustafa Ismail struct cqp_cmds_info *pcmdinfo = NULL; 528*915cc7acSMustafa Ismail u32 i, pending_work, wqe_idx; 529*915cc7acSMustafa Ismail 530*915cc7acSMustafa Ismail pending_work = IRDMA_RING_USED_QUANTA(cqp->sc_cqp.sq_ring); 531*915cc7acSMustafa Ismail wqe_idx = IRDMA_RING_CURRENT_TAIL(cqp->sc_cqp.sq_ring); 532*915cc7acSMustafa Ismail for (i = 0; i < pending_work; i++) { 533*915cc7acSMustafa Ismail cqp_request = (struct irdma_cqp_request *)(unsigned long) 534*915cc7acSMustafa Ismail cqp->scratch_array[wqe_idx]; 535*915cc7acSMustafa Ismail if (cqp_request) 536*915cc7acSMustafa Ismail irdma_free_pending_cqp_request(cqp, cqp_request); 537*915cc7acSMustafa Ismail wqe_idx = (wqe_idx + 1) % IRDMA_RING_SIZE(cqp->sc_cqp.sq_ring); 538*915cc7acSMustafa Ismail } 539*915cc7acSMustafa Ismail 540*915cc7acSMustafa Ismail while (!list_empty(&dev->cqp_cmd_head)) { 541*915cc7acSMustafa Ismail pcmdinfo = irdma_remove_cqp_head(dev); 542*915cc7acSMustafa Ismail cqp_request = 543*915cc7acSMustafa Ismail container_of(pcmdinfo, struct irdma_cqp_request, info); 544*915cc7acSMustafa Ismail if (cqp_request) 545*915cc7acSMustafa Ismail irdma_free_pending_cqp_request(cqp, cqp_request); 546*915cc7acSMustafa Ismail } 547*915cc7acSMustafa Ismail } 548*915cc7acSMustafa Ismail 549*915cc7acSMustafa Ismail /** 550*915cc7acSMustafa Ismail * irdma_wait_event - wait for completion 551*915cc7acSMustafa Ismail * @rf: RDMA PCI function 552*915cc7acSMustafa Ismail * @cqp_request: cqp request to wait 553*915cc7acSMustafa Ismail */ 554*915cc7acSMustafa Ismail static enum irdma_status_code irdma_wait_event(struct irdma_pci_f *rf, 555*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request) 556*915cc7acSMustafa Ismail { 557*915cc7acSMustafa Ismail struct irdma_cqp_timeout cqp_timeout = {}; 558*915cc7acSMustafa Ismail bool cqp_error = false; 559*915cc7acSMustafa Ismail enum irdma_status_code err_code = 0; 560*915cc7acSMustafa Ismail 561*915cc7acSMustafa Ismail cqp_timeout.compl_cqp_cmds = rf->sc_dev.cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]; 562*915cc7acSMustafa Ismail do { 563*915cc7acSMustafa Ismail irdma_cqp_ce_handler(rf, &rf->ccq.sc_cq); 564*915cc7acSMustafa Ismail if (wait_event_timeout(cqp_request->waitq, 565*915cc7acSMustafa Ismail cqp_request->request_done, 566*915cc7acSMustafa Ismail msecs_to_jiffies(CQP_COMPL_WAIT_TIME_MS))) 567*915cc7acSMustafa Ismail break; 568*915cc7acSMustafa Ismail 569*915cc7acSMustafa Ismail irdma_check_cqp_progress(&cqp_timeout, &rf->sc_dev); 570*915cc7acSMustafa Ismail 571*915cc7acSMustafa Ismail if (cqp_timeout.count < CQP_TIMEOUT_THRESHOLD) 572*915cc7acSMustafa Ismail continue; 573*915cc7acSMustafa Ismail 574*915cc7acSMustafa Ismail if (!rf->reset) { 575*915cc7acSMustafa Ismail rf->reset = true; 576*915cc7acSMustafa Ismail rf->gen_ops.request_reset(rf); 577*915cc7acSMustafa Ismail } 578*915cc7acSMustafa Ismail return IRDMA_ERR_TIMEOUT; 579*915cc7acSMustafa Ismail } while (1); 580*915cc7acSMustafa Ismail 581*915cc7acSMustafa Ismail cqp_error = cqp_request->compl_info.error; 582*915cc7acSMustafa Ismail if (cqp_error) { 583*915cc7acSMustafa Ismail err_code = IRDMA_ERR_CQP_COMPL_ERROR; 584*915cc7acSMustafa Ismail if (cqp_request->compl_info.maj_err_code == 0xFFFF && 585*915cc7acSMustafa Ismail cqp_request->compl_info.min_err_code == 0x8029) { 586*915cc7acSMustafa Ismail if (!rf->reset) { 587*915cc7acSMustafa Ismail rf->reset = true; 588*915cc7acSMustafa Ismail rf->gen_ops.request_reset(rf); 589*915cc7acSMustafa Ismail } 590*915cc7acSMustafa Ismail } 591*915cc7acSMustafa Ismail } 592*915cc7acSMustafa Ismail 593*915cc7acSMustafa Ismail return err_code; 594*915cc7acSMustafa Ismail } 595*915cc7acSMustafa Ismail 596*915cc7acSMustafa Ismail static const char *const irdma_cqp_cmd_names[IRDMA_MAX_CQP_OPS] = { 597*915cc7acSMustafa Ismail [IRDMA_OP_CEQ_DESTROY] = "Destroy CEQ Cmd", 598*915cc7acSMustafa Ismail [IRDMA_OP_AEQ_DESTROY] = "Destroy AEQ Cmd", 599*915cc7acSMustafa Ismail [IRDMA_OP_DELETE_ARP_CACHE_ENTRY] = "Delete ARP Cache Cmd", 600*915cc7acSMustafa Ismail [IRDMA_OP_MANAGE_APBVT_ENTRY] = "Manage APBV Table Entry Cmd", 601*915cc7acSMustafa Ismail [IRDMA_OP_CEQ_CREATE] = "CEQ Create Cmd", 602*915cc7acSMustafa Ismail [IRDMA_OP_AEQ_CREATE] = "AEQ Destroy Cmd", 603*915cc7acSMustafa Ismail [IRDMA_OP_MANAGE_QHASH_TABLE_ENTRY] = "Manage Quad Hash Table Entry Cmd", 604*915cc7acSMustafa Ismail [IRDMA_OP_QP_MODIFY] = "Modify QP Cmd", 605*915cc7acSMustafa Ismail [IRDMA_OP_QP_UPLOAD_CONTEXT] = "Upload Context Cmd", 606*915cc7acSMustafa Ismail [IRDMA_OP_CQ_CREATE] = "Create CQ Cmd", 607*915cc7acSMustafa Ismail [IRDMA_OP_CQ_DESTROY] = "Destroy CQ Cmd", 608*915cc7acSMustafa Ismail [IRDMA_OP_QP_CREATE] = "Create QP Cmd", 609*915cc7acSMustafa Ismail [IRDMA_OP_QP_DESTROY] = "Destroy QP Cmd", 610*915cc7acSMustafa Ismail [IRDMA_OP_ALLOC_STAG] = "Allocate STag Cmd", 611*915cc7acSMustafa Ismail [IRDMA_OP_MR_REG_NON_SHARED] = "Register Non-Shared MR Cmd", 612*915cc7acSMustafa Ismail [IRDMA_OP_DEALLOC_STAG] = "Deallocate STag Cmd", 613*915cc7acSMustafa Ismail [IRDMA_OP_MW_ALLOC] = "Allocate Memory Window Cmd", 614*915cc7acSMustafa Ismail [IRDMA_OP_QP_FLUSH_WQES] = "Flush QP Cmd", 615*915cc7acSMustafa Ismail [IRDMA_OP_ADD_ARP_CACHE_ENTRY] = "Add ARP Cache Cmd", 616*915cc7acSMustafa Ismail [IRDMA_OP_MANAGE_PUSH_PAGE] = "Manage Push Page Cmd", 617*915cc7acSMustafa Ismail [IRDMA_OP_UPDATE_PE_SDS] = "Update PE SDs Cmd", 618*915cc7acSMustafa Ismail [IRDMA_OP_MANAGE_HMC_PM_FUNC_TABLE] = "Manage HMC PM Function Table Cmd", 619*915cc7acSMustafa Ismail [IRDMA_OP_SUSPEND] = "Suspend QP Cmd", 620*915cc7acSMustafa Ismail [IRDMA_OP_RESUME] = "Resume QP Cmd", 621*915cc7acSMustafa Ismail [IRDMA_OP_MANAGE_VF_PBLE_BP] = "Manage VF PBLE Backing Pages Cmd", 622*915cc7acSMustafa Ismail [IRDMA_OP_QUERY_FPM_VAL] = "Query FPM Values Cmd", 623*915cc7acSMustafa Ismail [IRDMA_OP_COMMIT_FPM_VAL] = "Commit FPM Values Cmd", 624*915cc7acSMustafa Ismail [IRDMA_OP_AH_CREATE] = "Create Address Handle Cmd", 625*915cc7acSMustafa Ismail [IRDMA_OP_AH_MODIFY] = "Modify Address Handle Cmd", 626*915cc7acSMustafa Ismail [IRDMA_OP_AH_DESTROY] = "Destroy Address Handle Cmd", 627*915cc7acSMustafa Ismail [IRDMA_OP_MC_CREATE] = "Create Multicast Group Cmd", 628*915cc7acSMustafa Ismail [IRDMA_OP_MC_DESTROY] = "Destroy Multicast Group Cmd", 629*915cc7acSMustafa Ismail [IRDMA_OP_MC_MODIFY] = "Modify Multicast Group Cmd", 630*915cc7acSMustafa Ismail [IRDMA_OP_STATS_ALLOCATE] = "Add Statistics Instance Cmd", 631*915cc7acSMustafa Ismail [IRDMA_OP_STATS_FREE] = "Free Statistics Instance Cmd", 632*915cc7acSMustafa Ismail [IRDMA_OP_STATS_GATHER] = "Gather Statistics Cmd", 633*915cc7acSMustafa Ismail [IRDMA_OP_WS_ADD_NODE] = "Add Work Scheduler Node Cmd", 634*915cc7acSMustafa Ismail [IRDMA_OP_WS_MODIFY_NODE] = "Modify Work Scheduler Node Cmd", 635*915cc7acSMustafa Ismail [IRDMA_OP_WS_DELETE_NODE] = "Delete Work Scheduler Node Cmd", 636*915cc7acSMustafa Ismail [IRDMA_OP_SET_UP_MAP] = "Set UP-UP Mapping Cmd", 637*915cc7acSMustafa Ismail [IRDMA_OP_GEN_AE] = "Generate AE Cmd", 638*915cc7acSMustafa Ismail [IRDMA_OP_QUERY_RDMA_FEATURES] = "RDMA Get Features Cmd", 639*915cc7acSMustafa Ismail [IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY] = "Allocal Local MAC Entry Cmd", 640*915cc7acSMustafa Ismail [IRDMA_OP_ADD_LOCAL_MAC_ENTRY] = "Add Local MAC Entry Cmd", 641*915cc7acSMustafa Ismail [IRDMA_OP_DELETE_LOCAL_MAC_ENTRY] = "Delete Local MAC Entry Cmd", 642*915cc7acSMustafa Ismail [IRDMA_OP_CQ_MODIFY] = "CQ Modify Cmd", 643*915cc7acSMustafa Ismail }; 644*915cc7acSMustafa Ismail 645*915cc7acSMustafa Ismail static const struct irdma_cqp_err_info irdma_noncrit_err_list[] = { 646*915cc7acSMustafa Ismail {0xffff, 0x8006, "Flush No Wqe Pending"}, 647*915cc7acSMustafa Ismail {0xffff, 0x8007, "Modify QP Bad Close"}, 648*915cc7acSMustafa Ismail {0xffff, 0x8009, "LLP Closed"}, 649*915cc7acSMustafa Ismail {0xffff, 0x800a, "Reset Not Sent"} 650*915cc7acSMustafa Ismail }; 651*915cc7acSMustafa Ismail 652*915cc7acSMustafa Ismail /** 653*915cc7acSMustafa Ismail * irdma_cqp_crit_err - check if CQP error is critical 654*915cc7acSMustafa Ismail * @dev: pointer to dev structure 655*915cc7acSMustafa Ismail * @cqp_cmd: code for last CQP operation 656*915cc7acSMustafa Ismail * @maj_err_code: major error code 657*915cc7acSMustafa Ismail * @min_err_code: minot error code 658*915cc7acSMustafa Ismail */ 659*915cc7acSMustafa Ismail bool irdma_cqp_crit_err(struct irdma_sc_dev *dev, u8 cqp_cmd, 660*915cc7acSMustafa Ismail u16 maj_err_code, u16 min_err_code) 661*915cc7acSMustafa Ismail { 662*915cc7acSMustafa Ismail int i; 663*915cc7acSMustafa Ismail 664*915cc7acSMustafa Ismail for (i = 0; i < ARRAY_SIZE(irdma_noncrit_err_list); ++i) { 665*915cc7acSMustafa Ismail if (maj_err_code == irdma_noncrit_err_list[i].maj && 666*915cc7acSMustafa Ismail min_err_code == irdma_noncrit_err_list[i].min) { 667*915cc7acSMustafa Ismail ibdev_dbg(to_ibdev(dev), 668*915cc7acSMustafa Ismail "CQP: [%s Error][%s] maj=0x%x min=0x%x\n", 669*915cc7acSMustafa Ismail irdma_noncrit_err_list[i].desc, 670*915cc7acSMustafa Ismail irdma_cqp_cmd_names[cqp_cmd], maj_err_code, 671*915cc7acSMustafa Ismail min_err_code); 672*915cc7acSMustafa Ismail return false; 673*915cc7acSMustafa Ismail } 674*915cc7acSMustafa Ismail } 675*915cc7acSMustafa Ismail return true; 676*915cc7acSMustafa Ismail } 677*915cc7acSMustafa Ismail 678*915cc7acSMustafa Ismail /** 679*915cc7acSMustafa Ismail * irdma_handle_cqp_op - process cqp command 680*915cc7acSMustafa Ismail * @rf: RDMA PCI function 681*915cc7acSMustafa Ismail * @cqp_request: cqp request to process 682*915cc7acSMustafa Ismail */ 683*915cc7acSMustafa Ismail enum irdma_status_code irdma_handle_cqp_op(struct irdma_pci_f *rf, 684*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request) 685*915cc7acSMustafa Ismail { 686*915cc7acSMustafa Ismail struct irdma_sc_dev *dev = &rf->sc_dev; 687*915cc7acSMustafa Ismail struct cqp_cmds_info *info = &cqp_request->info; 688*915cc7acSMustafa Ismail enum irdma_status_code status; 689*915cc7acSMustafa Ismail bool put_cqp_request = true; 690*915cc7acSMustafa Ismail 691*915cc7acSMustafa Ismail if (rf->reset) 692*915cc7acSMustafa Ismail return IRDMA_ERR_NOT_READY; 693*915cc7acSMustafa Ismail 694*915cc7acSMustafa Ismail irdma_get_cqp_request(cqp_request); 695*915cc7acSMustafa Ismail status = irdma_process_cqp_cmd(dev, info); 696*915cc7acSMustafa Ismail if (status) 697*915cc7acSMustafa Ismail goto err; 698*915cc7acSMustafa Ismail 699*915cc7acSMustafa Ismail if (cqp_request->waiting) { 700*915cc7acSMustafa Ismail put_cqp_request = false; 701*915cc7acSMustafa Ismail status = irdma_wait_event(rf, cqp_request); 702*915cc7acSMustafa Ismail if (status) 703*915cc7acSMustafa Ismail goto err; 704*915cc7acSMustafa Ismail } 705*915cc7acSMustafa Ismail 706*915cc7acSMustafa Ismail return 0; 707*915cc7acSMustafa Ismail 708*915cc7acSMustafa Ismail err: 709*915cc7acSMustafa Ismail if (irdma_cqp_crit_err(dev, info->cqp_cmd, 710*915cc7acSMustafa Ismail cqp_request->compl_info.maj_err_code, 711*915cc7acSMustafa Ismail cqp_request->compl_info.min_err_code)) 712*915cc7acSMustafa Ismail ibdev_err(&rf->iwdev->ibdev, 713*915cc7acSMustafa Ismail "[%s Error][op_code=%d] status=%d waiting=%d completion_err=%d maj=0x%x min=0x%x\n", 714*915cc7acSMustafa Ismail irdma_cqp_cmd_names[info->cqp_cmd], info->cqp_cmd, status, cqp_request->waiting, 715*915cc7acSMustafa Ismail cqp_request->compl_info.error, cqp_request->compl_info.maj_err_code, 716*915cc7acSMustafa Ismail cqp_request->compl_info.min_err_code); 717*915cc7acSMustafa Ismail 718*915cc7acSMustafa Ismail if (put_cqp_request) 719*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 720*915cc7acSMustafa Ismail 721*915cc7acSMustafa Ismail return status; 722*915cc7acSMustafa Ismail } 723*915cc7acSMustafa Ismail 724*915cc7acSMustafa Ismail void irdma_qp_add_ref(struct ib_qp *ibqp) 725*915cc7acSMustafa Ismail { 726*915cc7acSMustafa Ismail struct irdma_qp *iwqp = (struct irdma_qp *)ibqp; 727*915cc7acSMustafa Ismail 728*915cc7acSMustafa Ismail refcount_inc(&iwqp->refcnt); 729*915cc7acSMustafa Ismail } 730*915cc7acSMustafa Ismail 731*915cc7acSMustafa Ismail void irdma_qp_rem_ref(struct ib_qp *ibqp) 732*915cc7acSMustafa Ismail { 733*915cc7acSMustafa Ismail struct irdma_qp *iwqp = to_iwqp(ibqp); 734*915cc7acSMustafa Ismail struct irdma_device *iwdev = iwqp->iwdev; 735*915cc7acSMustafa Ismail u32 qp_num; 736*915cc7acSMustafa Ismail unsigned long flags; 737*915cc7acSMustafa Ismail 738*915cc7acSMustafa Ismail spin_lock_irqsave(&iwdev->rf->qptable_lock, flags); 739*915cc7acSMustafa Ismail if (!refcount_dec_and_test(&iwqp->refcnt)) { 740*915cc7acSMustafa Ismail spin_unlock_irqrestore(&iwdev->rf->qptable_lock, flags); 741*915cc7acSMustafa Ismail return; 742*915cc7acSMustafa Ismail } 743*915cc7acSMustafa Ismail 744*915cc7acSMustafa Ismail qp_num = iwqp->ibqp.qp_num; 745*915cc7acSMustafa Ismail iwdev->rf->qp_table[qp_num] = NULL; 746*915cc7acSMustafa Ismail spin_unlock_irqrestore(&iwdev->rf->qptable_lock, flags); 747*915cc7acSMustafa Ismail complete(&iwqp->free_qp); 748*915cc7acSMustafa Ismail } 749*915cc7acSMustafa Ismail 750*915cc7acSMustafa Ismail struct ib_device *to_ibdev(struct irdma_sc_dev *dev) 751*915cc7acSMustafa Ismail { 752*915cc7acSMustafa Ismail return &(container_of(dev, struct irdma_pci_f, sc_dev))->iwdev->ibdev; 753*915cc7acSMustafa Ismail } 754*915cc7acSMustafa Ismail 755*915cc7acSMustafa Ismail /** 756*915cc7acSMustafa Ismail * irdma_get_qp - get qp address 757*915cc7acSMustafa Ismail * @device: iwarp device 758*915cc7acSMustafa Ismail * @qpn: qp number 759*915cc7acSMustafa Ismail */ 760*915cc7acSMustafa Ismail struct ib_qp *irdma_get_qp(struct ib_device *device, int qpn) 761*915cc7acSMustafa Ismail { 762*915cc7acSMustafa Ismail struct irdma_device *iwdev = to_iwdev(device); 763*915cc7acSMustafa Ismail 764*915cc7acSMustafa Ismail if (qpn < IW_FIRST_QPN || qpn >= iwdev->rf->max_qp) 765*915cc7acSMustafa Ismail return NULL; 766*915cc7acSMustafa Ismail 767*915cc7acSMustafa Ismail return &iwdev->rf->qp_table[qpn]->ibqp; 768*915cc7acSMustafa Ismail } 769*915cc7acSMustafa Ismail 770*915cc7acSMustafa Ismail /** 771*915cc7acSMustafa Ismail * irdma_get_hw_addr - return hw addr 772*915cc7acSMustafa Ismail * @par: points to shared dev 773*915cc7acSMustafa Ismail */ 774*915cc7acSMustafa Ismail u8 __iomem *irdma_get_hw_addr(void *par) 775*915cc7acSMustafa Ismail { 776*915cc7acSMustafa Ismail struct irdma_sc_dev *dev = par; 777*915cc7acSMustafa Ismail 778*915cc7acSMustafa Ismail return dev->hw->hw_addr; 779*915cc7acSMustafa Ismail } 780*915cc7acSMustafa Ismail 781*915cc7acSMustafa Ismail /** 782*915cc7acSMustafa Ismail * irdma_remove_cqp_head - return head entry and remove 783*915cc7acSMustafa Ismail * @dev: device 784*915cc7acSMustafa Ismail */ 785*915cc7acSMustafa Ismail void *irdma_remove_cqp_head(struct irdma_sc_dev *dev) 786*915cc7acSMustafa Ismail { 787*915cc7acSMustafa Ismail struct list_head *entry; 788*915cc7acSMustafa Ismail struct list_head *list = &dev->cqp_cmd_head; 789*915cc7acSMustafa Ismail 790*915cc7acSMustafa Ismail if (list_empty(list)) 791*915cc7acSMustafa Ismail return NULL; 792*915cc7acSMustafa Ismail 793*915cc7acSMustafa Ismail entry = list->next; 794*915cc7acSMustafa Ismail list_del(entry); 795*915cc7acSMustafa Ismail 796*915cc7acSMustafa Ismail return entry; 797*915cc7acSMustafa Ismail } 798*915cc7acSMustafa Ismail 799*915cc7acSMustafa Ismail /** 800*915cc7acSMustafa Ismail * irdma_cqp_sds_cmd - create cqp command for sd 801*915cc7acSMustafa Ismail * @dev: hardware control device structure 802*915cc7acSMustafa Ismail * @sdinfo: information for sd cqp 803*915cc7acSMustafa Ismail * 804*915cc7acSMustafa Ismail */ 805*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_sds_cmd(struct irdma_sc_dev *dev, 806*915cc7acSMustafa Ismail struct irdma_update_sds_info *sdinfo) 807*915cc7acSMustafa Ismail { 808*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 809*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 810*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 811*915cc7acSMustafa Ismail enum irdma_status_code status; 812*915cc7acSMustafa Ismail 813*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); 814*915cc7acSMustafa Ismail if (!cqp_request) 815*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 816*915cc7acSMustafa Ismail 817*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 818*915cc7acSMustafa Ismail memcpy(&cqp_info->in.u.update_pe_sds.info, sdinfo, 819*915cc7acSMustafa Ismail sizeof(cqp_info->in.u.update_pe_sds.info)); 820*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_UPDATE_PE_SDS; 821*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 822*915cc7acSMustafa Ismail cqp_info->in.u.update_pe_sds.dev = dev; 823*915cc7acSMustafa Ismail cqp_info->in.u.update_pe_sds.scratch = (uintptr_t)cqp_request; 824*915cc7acSMustafa Ismail 825*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 826*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 827*915cc7acSMustafa Ismail 828*915cc7acSMustafa Ismail return status; 829*915cc7acSMustafa Ismail } 830*915cc7acSMustafa Ismail 831*915cc7acSMustafa Ismail /** 832*915cc7acSMustafa Ismail * irdma_cqp_qp_suspend_resume - cqp command for suspend/resume 833*915cc7acSMustafa Ismail * @qp: hardware control qp 834*915cc7acSMustafa Ismail * @op: suspend or resume 835*915cc7acSMustafa Ismail */ 836*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_qp_suspend_resume(struct irdma_sc_qp *qp, 837*915cc7acSMustafa Ismail u8 op) 838*915cc7acSMustafa Ismail { 839*915cc7acSMustafa Ismail struct irdma_sc_dev *dev = qp->dev; 840*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 841*915cc7acSMustafa Ismail struct irdma_sc_cqp *cqp = dev->cqp; 842*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 843*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 844*915cc7acSMustafa Ismail enum irdma_status_code status; 845*915cc7acSMustafa Ismail 846*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, false); 847*915cc7acSMustafa Ismail if (!cqp_request) 848*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 849*915cc7acSMustafa Ismail 850*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 851*915cc7acSMustafa Ismail cqp_info->cqp_cmd = op; 852*915cc7acSMustafa Ismail cqp_info->in.u.suspend_resume.cqp = cqp; 853*915cc7acSMustafa Ismail cqp_info->in.u.suspend_resume.qp = qp; 854*915cc7acSMustafa Ismail cqp_info->in.u.suspend_resume.scratch = (uintptr_t)cqp_request; 855*915cc7acSMustafa Ismail 856*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 857*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 858*915cc7acSMustafa Ismail 859*915cc7acSMustafa Ismail return status; 860*915cc7acSMustafa Ismail } 861*915cc7acSMustafa Ismail 862*915cc7acSMustafa Ismail /** 863*915cc7acSMustafa Ismail * irdma_term_modify_qp - modify qp for term message 864*915cc7acSMustafa Ismail * @qp: hardware control qp 865*915cc7acSMustafa Ismail * @next_state: qp's next state 866*915cc7acSMustafa Ismail * @term: terminate code 867*915cc7acSMustafa Ismail * @term_len: length 868*915cc7acSMustafa Ismail */ 869*915cc7acSMustafa Ismail void irdma_term_modify_qp(struct irdma_sc_qp *qp, u8 next_state, u8 term, 870*915cc7acSMustafa Ismail u8 term_len) 871*915cc7acSMustafa Ismail { 872*915cc7acSMustafa Ismail struct irdma_qp *iwqp; 873*915cc7acSMustafa Ismail 874*915cc7acSMustafa Ismail iwqp = qp->qp_uk.back_qp; 875*915cc7acSMustafa Ismail irdma_next_iw_state(iwqp, next_state, 0, term, term_len); 876*915cc7acSMustafa Ismail }; 877*915cc7acSMustafa Ismail 878*915cc7acSMustafa Ismail /** 879*915cc7acSMustafa Ismail * irdma_terminate_done - after terminate is completed 880*915cc7acSMustafa Ismail * @qp: hardware control qp 881*915cc7acSMustafa Ismail * @timeout_occurred: indicates if terminate timer expired 882*915cc7acSMustafa Ismail */ 883*915cc7acSMustafa Ismail void irdma_terminate_done(struct irdma_sc_qp *qp, int timeout_occurred) 884*915cc7acSMustafa Ismail { 885*915cc7acSMustafa Ismail struct irdma_qp *iwqp; 886*915cc7acSMustafa Ismail u8 hte = 0; 887*915cc7acSMustafa Ismail bool first_time; 888*915cc7acSMustafa Ismail unsigned long flags; 889*915cc7acSMustafa Ismail 890*915cc7acSMustafa Ismail iwqp = qp->qp_uk.back_qp; 891*915cc7acSMustafa Ismail spin_lock_irqsave(&iwqp->lock, flags); 892*915cc7acSMustafa Ismail if (iwqp->hte_added) { 893*915cc7acSMustafa Ismail iwqp->hte_added = 0; 894*915cc7acSMustafa Ismail hte = 1; 895*915cc7acSMustafa Ismail } 896*915cc7acSMustafa Ismail first_time = !(qp->term_flags & IRDMA_TERM_DONE); 897*915cc7acSMustafa Ismail qp->term_flags |= IRDMA_TERM_DONE; 898*915cc7acSMustafa Ismail spin_unlock_irqrestore(&iwqp->lock, flags); 899*915cc7acSMustafa Ismail if (first_time) { 900*915cc7acSMustafa Ismail if (!timeout_occurred) 901*915cc7acSMustafa Ismail irdma_terminate_del_timer(qp); 902*915cc7acSMustafa Ismail 903*915cc7acSMustafa Ismail irdma_next_iw_state(iwqp, IRDMA_QP_STATE_ERROR, hte, 0, 0); 904*915cc7acSMustafa Ismail irdma_cm_disconn(iwqp); 905*915cc7acSMustafa Ismail } 906*915cc7acSMustafa Ismail } 907*915cc7acSMustafa Ismail 908*915cc7acSMustafa Ismail static void irdma_terminate_timeout(struct timer_list *t) 909*915cc7acSMustafa Ismail { 910*915cc7acSMustafa Ismail struct irdma_qp *iwqp = from_timer(iwqp, t, terminate_timer); 911*915cc7acSMustafa Ismail struct irdma_sc_qp *qp = &iwqp->sc_qp; 912*915cc7acSMustafa Ismail 913*915cc7acSMustafa Ismail irdma_terminate_done(qp, 1); 914*915cc7acSMustafa Ismail irdma_qp_rem_ref(&iwqp->ibqp); 915*915cc7acSMustafa Ismail } 916*915cc7acSMustafa Ismail 917*915cc7acSMustafa Ismail /** 918*915cc7acSMustafa Ismail * irdma_terminate_start_timer - start terminate timeout 919*915cc7acSMustafa Ismail * @qp: hardware control qp 920*915cc7acSMustafa Ismail */ 921*915cc7acSMustafa Ismail void irdma_terminate_start_timer(struct irdma_sc_qp *qp) 922*915cc7acSMustafa Ismail { 923*915cc7acSMustafa Ismail struct irdma_qp *iwqp; 924*915cc7acSMustafa Ismail 925*915cc7acSMustafa Ismail iwqp = qp->qp_uk.back_qp; 926*915cc7acSMustafa Ismail irdma_qp_add_ref(&iwqp->ibqp); 927*915cc7acSMustafa Ismail timer_setup(&iwqp->terminate_timer, irdma_terminate_timeout, 0); 928*915cc7acSMustafa Ismail iwqp->terminate_timer.expires = jiffies + HZ; 929*915cc7acSMustafa Ismail 930*915cc7acSMustafa Ismail add_timer(&iwqp->terminate_timer); 931*915cc7acSMustafa Ismail } 932*915cc7acSMustafa Ismail 933*915cc7acSMustafa Ismail /** 934*915cc7acSMustafa Ismail * irdma_terminate_del_timer - delete terminate timeout 935*915cc7acSMustafa Ismail * @qp: hardware control qp 936*915cc7acSMustafa Ismail */ 937*915cc7acSMustafa Ismail void irdma_terminate_del_timer(struct irdma_sc_qp *qp) 938*915cc7acSMustafa Ismail { 939*915cc7acSMustafa Ismail struct irdma_qp *iwqp; 940*915cc7acSMustafa Ismail int ret; 941*915cc7acSMustafa Ismail 942*915cc7acSMustafa Ismail iwqp = qp->qp_uk.back_qp; 943*915cc7acSMustafa Ismail ret = del_timer(&iwqp->terminate_timer); 944*915cc7acSMustafa Ismail if (ret) 945*915cc7acSMustafa Ismail irdma_qp_rem_ref(&iwqp->ibqp); 946*915cc7acSMustafa Ismail } 947*915cc7acSMustafa Ismail 948*915cc7acSMustafa Ismail /** 949*915cc7acSMustafa Ismail * irdma_cqp_query_fpm_val_cmd - send cqp command for fpm 950*915cc7acSMustafa Ismail * @dev: function device struct 951*915cc7acSMustafa Ismail * @val_mem: buffer for fpm 952*915cc7acSMustafa Ismail * @hmc_fn_id: function id for fpm 953*915cc7acSMustafa Ismail */ 954*915cc7acSMustafa Ismail enum irdma_status_code 955*915cc7acSMustafa Ismail irdma_cqp_query_fpm_val_cmd(struct irdma_sc_dev *dev, 956*915cc7acSMustafa Ismail struct irdma_dma_mem *val_mem, u8 hmc_fn_id) 957*915cc7acSMustafa Ismail { 958*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 959*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 960*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 961*915cc7acSMustafa Ismail enum irdma_status_code status; 962*915cc7acSMustafa Ismail 963*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); 964*915cc7acSMustafa Ismail if (!cqp_request) 965*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 966*915cc7acSMustafa Ismail 967*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 968*915cc7acSMustafa Ismail cqp_request->param = NULL; 969*915cc7acSMustafa Ismail cqp_info->in.u.query_fpm_val.cqp = dev->cqp; 970*915cc7acSMustafa Ismail cqp_info->in.u.query_fpm_val.fpm_val_pa = val_mem->pa; 971*915cc7acSMustafa Ismail cqp_info->in.u.query_fpm_val.fpm_val_va = val_mem->va; 972*915cc7acSMustafa Ismail cqp_info->in.u.query_fpm_val.hmc_fn_id = hmc_fn_id; 973*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_QUERY_FPM_VAL; 974*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 975*915cc7acSMustafa Ismail cqp_info->in.u.query_fpm_val.scratch = (uintptr_t)cqp_request; 976*915cc7acSMustafa Ismail 977*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 978*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 979*915cc7acSMustafa Ismail 980*915cc7acSMustafa Ismail return status; 981*915cc7acSMustafa Ismail } 982*915cc7acSMustafa Ismail 983*915cc7acSMustafa Ismail /** 984*915cc7acSMustafa Ismail * irdma_cqp_commit_fpm_val_cmd - commit fpm values in hw 985*915cc7acSMustafa Ismail * @dev: hardware control device structure 986*915cc7acSMustafa Ismail * @val_mem: buffer with fpm values 987*915cc7acSMustafa Ismail * @hmc_fn_id: function id for fpm 988*915cc7acSMustafa Ismail */ 989*915cc7acSMustafa Ismail enum irdma_status_code 990*915cc7acSMustafa Ismail irdma_cqp_commit_fpm_val_cmd(struct irdma_sc_dev *dev, 991*915cc7acSMustafa Ismail struct irdma_dma_mem *val_mem, u8 hmc_fn_id) 992*915cc7acSMustafa Ismail { 993*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 994*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 995*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 996*915cc7acSMustafa Ismail enum irdma_status_code status; 997*915cc7acSMustafa Ismail 998*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); 999*915cc7acSMustafa Ismail if (!cqp_request) 1000*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1001*915cc7acSMustafa Ismail 1002*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1003*915cc7acSMustafa Ismail cqp_request->param = NULL; 1004*915cc7acSMustafa Ismail cqp_info->in.u.commit_fpm_val.cqp = dev->cqp; 1005*915cc7acSMustafa Ismail cqp_info->in.u.commit_fpm_val.fpm_val_pa = val_mem->pa; 1006*915cc7acSMustafa Ismail cqp_info->in.u.commit_fpm_val.fpm_val_va = val_mem->va; 1007*915cc7acSMustafa Ismail cqp_info->in.u.commit_fpm_val.hmc_fn_id = hmc_fn_id; 1008*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_COMMIT_FPM_VAL; 1009*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1010*915cc7acSMustafa Ismail cqp_info->in.u.commit_fpm_val.scratch = (uintptr_t)cqp_request; 1011*915cc7acSMustafa Ismail 1012*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1013*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1014*915cc7acSMustafa Ismail 1015*915cc7acSMustafa Ismail return status; 1016*915cc7acSMustafa Ismail } 1017*915cc7acSMustafa Ismail 1018*915cc7acSMustafa Ismail /** 1019*915cc7acSMustafa Ismail * irdma_cqp_cq_create_cmd - create a cq for the cqp 1020*915cc7acSMustafa Ismail * @dev: device pointer 1021*915cc7acSMustafa Ismail * @cq: pointer to created cq 1022*915cc7acSMustafa Ismail */ 1023*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_cq_create_cmd(struct irdma_sc_dev *dev, 1024*915cc7acSMustafa Ismail struct irdma_sc_cq *cq) 1025*915cc7acSMustafa Ismail { 1026*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1027*915cc7acSMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 1028*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1029*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1030*915cc7acSMustafa Ismail enum irdma_status_code status; 1031*915cc7acSMustafa Ismail 1032*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, true); 1033*915cc7acSMustafa Ismail if (!cqp_request) 1034*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1035*915cc7acSMustafa Ismail 1036*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1037*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_CQ_CREATE; 1038*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1039*915cc7acSMustafa Ismail cqp_info->in.u.cq_create.cq = cq; 1040*915cc7acSMustafa Ismail cqp_info->in.u.cq_create.scratch = (uintptr_t)cqp_request; 1041*915cc7acSMustafa Ismail 1042*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1043*915cc7acSMustafa Ismail irdma_put_cqp_request(iwcqp, cqp_request); 1044*915cc7acSMustafa Ismail 1045*915cc7acSMustafa Ismail return status; 1046*915cc7acSMustafa Ismail } 1047*915cc7acSMustafa Ismail 1048*915cc7acSMustafa Ismail /** 1049*915cc7acSMustafa Ismail * irdma_cqp_qp_create_cmd - create a qp for the cqp 1050*915cc7acSMustafa Ismail * @dev: device pointer 1051*915cc7acSMustafa Ismail * @qp: pointer to created qp 1052*915cc7acSMustafa Ismail */ 1053*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_qp_create_cmd(struct irdma_sc_dev *dev, 1054*915cc7acSMustafa Ismail struct irdma_sc_qp *qp) 1055*915cc7acSMustafa Ismail { 1056*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1057*915cc7acSMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 1058*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1059*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1060*915cc7acSMustafa Ismail struct irdma_create_qp_info *qp_info; 1061*915cc7acSMustafa Ismail enum irdma_status_code status; 1062*915cc7acSMustafa Ismail 1063*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, true); 1064*915cc7acSMustafa Ismail if (!cqp_request) 1065*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1066*915cc7acSMustafa Ismail 1067*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1068*915cc7acSMustafa Ismail qp_info = &cqp_request->info.in.u.qp_create.info; 1069*915cc7acSMustafa Ismail memset(qp_info, 0, sizeof(*qp_info)); 1070*915cc7acSMustafa Ismail qp_info->cq_num_valid = true; 1071*915cc7acSMustafa Ismail qp_info->next_iwarp_state = IRDMA_QP_STATE_RTS; 1072*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_QP_CREATE; 1073*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1074*915cc7acSMustafa Ismail cqp_info->in.u.qp_create.qp = qp; 1075*915cc7acSMustafa Ismail cqp_info->in.u.qp_create.scratch = (uintptr_t)cqp_request; 1076*915cc7acSMustafa Ismail 1077*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1078*915cc7acSMustafa Ismail irdma_put_cqp_request(iwcqp, cqp_request); 1079*915cc7acSMustafa Ismail 1080*915cc7acSMustafa Ismail return status; 1081*915cc7acSMustafa Ismail } 1082*915cc7acSMustafa Ismail 1083*915cc7acSMustafa Ismail /** 1084*915cc7acSMustafa Ismail * irdma_dealloc_push_page - free a push page for qp 1085*915cc7acSMustafa Ismail * @rf: RDMA PCI function 1086*915cc7acSMustafa Ismail * @qp: hardware control qp 1087*915cc7acSMustafa Ismail */ 1088*915cc7acSMustafa Ismail static void irdma_dealloc_push_page(struct irdma_pci_f *rf, 1089*915cc7acSMustafa Ismail struct irdma_sc_qp *qp) 1090*915cc7acSMustafa Ismail { 1091*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1092*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1093*915cc7acSMustafa Ismail enum irdma_status_code status; 1094*915cc7acSMustafa Ismail 1095*915cc7acSMustafa Ismail if (qp->push_idx == IRDMA_INVALID_PUSH_PAGE_INDEX) 1096*915cc7acSMustafa Ismail return; 1097*915cc7acSMustafa Ismail 1098*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, false); 1099*915cc7acSMustafa Ismail if (!cqp_request) 1100*915cc7acSMustafa Ismail return; 1101*915cc7acSMustafa Ismail 1102*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1103*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_MANAGE_PUSH_PAGE; 1104*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1105*915cc7acSMustafa Ismail cqp_info->in.u.manage_push_page.info.push_idx = qp->push_idx; 1106*915cc7acSMustafa Ismail cqp_info->in.u.manage_push_page.info.qs_handle = qp->qs_handle; 1107*915cc7acSMustafa Ismail cqp_info->in.u.manage_push_page.info.free_page = 1; 1108*915cc7acSMustafa Ismail cqp_info->in.u.manage_push_page.info.push_page_type = 0; 1109*915cc7acSMustafa Ismail cqp_info->in.u.manage_push_page.cqp = &rf->cqp.sc_cqp; 1110*915cc7acSMustafa Ismail cqp_info->in.u.manage_push_page.scratch = (uintptr_t)cqp_request; 1111*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1112*915cc7acSMustafa Ismail if (!status) 1113*915cc7acSMustafa Ismail qp->push_idx = IRDMA_INVALID_PUSH_PAGE_INDEX; 1114*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1115*915cc7acSMustafa Ismail } 1116*915cc7acSMustafa Ismail 1117*915cc7acSMustafa Ismail /** 1118*915cc7acSMustafa Ismail * irdma_free_qp_rsrc - free up memory resources for qp 1119*915cc7acSMustafa Ismail * @iwqp: qp ptr (user or kernel) 1120*915cc7acSMustafa Ismail */ 1121*915cc7acSMustafa Ismail void irdma_free_qp_rsrc(struct irdma_qp *iwqp) 1122*915cc7acSMustafa Ismail { 1123*915cc7acSMustafa Ismail struct irdma_device *iwdev = iwqp->iwdev; 1124*915cc7acSMustafa Ismail struct irdma_pci_f *rf = iwdev->rf; 1125*915cc7acSMustafa Ismail u32 qp_num = iwqp->ibqp.qp_num; 1126*915cc7acSMustafa Ismail 1127*915cc7acSMustafa Ismail irdma_ieq_cleanup_qp(iwdev->vsi.ieq, &iwqp->sc_qp); 1128*915cc7acSMustafa Ismail irdma_dealloc_push_page(rf, &iwqp->sc_qp); 1129*915cc7acSMustafa Ismail if (iwqp->sc_qp.vsi) { 1130*915cc7acSMustafa Ismail irdma_qp_rem_qos(&iwqp->sc_qp); 1131*915cc7acSMustafa Ismail iwqp->sc_qp.dev->ws_remove(iwqp->sc_qp.vsi, 1132*915cc7acSMustafa Ismail iwqp->sc_qp.user_pri); 1133*915cc7acSMustafa Ismail } 1134*915cc7acSMustafa Ismail 1135*915cc7acSMustafa Ismail if (qp_num > 2) 1136*915cc7acSMustafa Ismail irdma_free_rsrc(rf, rf->allocated_qps, qp_num); 1137*915cc7acSMustafa Ismail dma_free_coherent(rf->sc_dev.hw->device, iwqp->q2_ctx_mem.size, 1138*915cc7acSMustafa Ismail iwqp->q2_ctx_mem.va, iwqp->q2_ctx_mem.pa); 1139*915cc7acSMustafa Ismail iwqp->q2_ctx_mem.va = NULL; 1140*915cc7acSMustafa Ismail dma_free_coherent(rf->sc_dev.hw->device, iwqp->kqp.dma_mem.size, 1141*915cc7acSMustafa Ismail iwqp->kqp.dma_mem.va, iwqp->kqp.dma_mem.pa); 1142*915cc7acSMustafa Ismail iwqp->kqp.dma_mem.va = NULL; 1143*915cc7acSMustafa Ismail kfree(iwqp->kqp.sq_wrid_mem); 1144*915cc7acSMustafa Ismail iwqp->kqp.sq_wrid_mem = NULL; 1145*915cc7acSMustafa Ismail kfree(iwqp->kqp.rq_wrid_mem); 1146*915cc7acSMustafa Ismail iwqp->kqp.rq_wrid_mem = NULL; 1147*915cc7acSMustafa Ismail kfree(iwqp); 1148*915cc7acSMustafa Ismail } 1149*915cc7acSMustafa Ismail 1150*915cc7acSMustafa Ismail /** 1151*915cc7acSMustafa Ismail * irdma_cq_wq_destroy - send cq destroy cqp 1152*915cc7acSMustafa Ismail * @rf: RDMA PCI function 1153*915cc7acSMustafa Ismail * @cq: hardware control cq 1154*915cc7acSMustafa Ismail */ 1155*915cc7acSMustafa Ismail void irdma_cq_wq_destroy(struct irdma_pci_f *rf, struct irdma_sc_cq *cq) 1156*915cc7acSMustafa Ismail { 1157*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1158*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1159*915cc7acSMustafa Ismail 1160*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); 1161*915cc7acSMustafa Ismail if (!cqp_request) 1162*915cc7acSMustafa Ismail return; 1163*915cc7acSMustafa Ismail 1164*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1165*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_CQ_DESTROY; 1166*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1167*915cc7acSMustafa Ismail cqp_info->in.u.cq_destroy.cq = cq; 1168*915cc7acSMustafa Ismail cqp_info->in.u.cq_destroy.scratch = (uintptr_t)cqp_request; 1169*915cc7acSMustafa Ismail 1170*915cc7acSMustafa Ismail irdma_handle_cqp_op(rf, cqp_request); 1171*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1172*915cc7acSMustafa Ismail } 1173*915cc7acSMustafa Ismail 1174*915cc7acSMustafa Ismail /** 1175*915cc7acSMustafa Ismail * irdma_hw_modify_qp_callback - handle state for modifyQPs that don't wait 1176*915cc7acSMustafa Ismail * @cqp_request: modify QP completion 1177*915cc7acSMustafa Ismail */ 1178*915cc7acSMustafa Ismail static void irdma_hw_modify_qp_callback(struct irdma_cqp_request *cqp_request) 1179*915cc7acSMustafa Ismail { 1180*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1181*915cc7acSMustafa Ismail struct irdma_qp *iwqp; 1182*915cc7acSMustafa Ismail 1183*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1184*915cc7acSMustafa Ismail iwqp = cqp_info->in.u.qp_modify.qp->qp_uk.back_qp; 1185*915cc7acSMustafa Ismail atomic_dec(&iwqp->hw_mod_qp_pend); 1186*915cc7acSMustafa Ismail wake_up(&iwqp->mod_qp_waitq); 1187*915cc7acSMustafa Ismail } 1188*915cc7acSMustafa Ismail 1189*915cc7acSMustafa Ismail /** 1190*915cc7acSMustafa Ismail * irdma_hw_modify_qp - setup cqp for modify qp 1191*915cc7acSMustafa Ismail * @iwdev: RDMA device 1192*915cc7acSMustafa Ismail * @iwqp: qp ptr (user or kernel) 1193*915cc7acSMustafa Ismail * @info: info for modify qp 1194*915cc7acSMustafa Ismail * @wait: flag to wait or not for modify qp completion 1195*915cc7acSMustafa Ismail */ 1196*915cc7acSMustafa Ismail enum irdma_status_code irdma_hw_modify_qp(struct irdma_device *iwdev, 1197*915cc7acSMustafa Ismail struct irdma_qp *iwqp, 1198*915cc7acSMustafa Ismail struct irdma_modify_qp_info *info, 1199*915cc7acSMustafa Ismail bool wait) 1200*915cc7acSMustafa Ismail { 1201*915cc7acSMustafa Ismail enum irdma_status_code status; 1202*915cc7acSMustafa Ismail struct irdma_pci_f *rf = iwdev->rf; 1203*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1204*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1205*915cc7acSMustafa Ismail struct irdma_modify_qp_info *m_info; 1206*915cc7acSMustafa Ismail 1207*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, wait); 1208*915cc7acSMustafa Ismail if (!cqp_request) 1209*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1210*915cc7acSMustafa Ismail 1211*915cc7acSMustafa Ismail if (!wait) { 1212*915cc7acSMustafa Ismail cqp_request->callback_fcn = irdma_hw_modify_qp_callback; 1213*915cc7acSMustafa Ismail atomic_inc(&iwqp->hw_mod_qp_pend); 1214*915cc7acSMustafa Ismail } 1215*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1216*915cc7acSMustafa Ismail m_info = &cqp_info->in.u.qp_modify.info; 1217*915cc7acSMustafa Ismail memcpy(m_info, info, sizeof(*m_info)); 1218*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_QP_MODIFY; 1219*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1220*915cc7acSMustafa Ismail cqp_info->in.u.qp_modify.qp = &iwqp->sc_qp; 1221*915cc7acSMustafa Ismail cqp_info->in.u.qp_modify.scratch = (uintptr_t)cqp_request; 1222*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1223*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1224*915cc7acSMustafa Ismail if (status) { 1225*915cc7acSMustafa Ismail if (rdma_protocol_roce(&iwdev->ibdev, 1)) 1226*915cc7acSMustafa Ismail return status; 1227*915cc7acSMustafa Ismail 1228*915cc7acSMustafa Ismail switch (m_info->next_iwarp_state) { 1229*915cc7acSMustafa Ismail struct irdma_gen_ae_info ae_info; 1230*915cc7acSMustafa Ismail 1231*915cc7acSMustafa Ismail case IRDMA_QP_STATE_RTS: 1232*915cc7acSMustafa Ismail case IRDMA_QP_STATE_IDLE: 1233*915cc7acSMustafa Ismail case IRDMA_QP_STATE_TERMINATE: 1234*915cc7acSMustafa Ismail case IRDMA_QP_STATE_CLOSING: 1235*915cc7acSMustafa Ismail if (info->curr_iwarp_state == IRDMA_QP_STATE_IDLE) 1236*915cc7acSMustafa Ismail irdma_send_reset(iwqp->cm_node); 1237*915cc7acSMustafa Ismail else 1238*915cc7acSMustafa Ismail iwqp->sc_qp.term_flags = IRDMA_TERM_DONE; 1239*915cc7acSMustafa Ismail if (!wait) { 1240*915cc7acSMustafa Ismail ae_info.ae_code = IRDMA_AE_BAD_CLOSE; 1241*915cc7acSMustafa Ismail ae_info.ae_src = 0; 1242*915cc7acSMustafa Ismail irdma_gen_ae(rf, &iwqp->sc_qp, &ae_info, false); 1243*915cc7acSMustafa Ismail } else { 1244*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, 1245*915cc7acSMustafa Ismail wait); 1246*915cc7acSMustafa Ismail if (!cqp_request) 1247*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1248*915cc7acSMustafa Ismail 1249*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1250*915cc7acSMustafa Ismail m_info = &cqp_info->in.u.qp_modify.info; 1251*915cc7acSMustafa Ismail memcpy(m_info, info, sizeof(*m_info)); 1252*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_QP_MODIFY; 1253*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1254*915cc7acSMustafa Ismail cqp_info->in.u.qp_modify.qp = &iwqp->sc_qp; 1255*915cc7acSMustafa Ismail cqp_info->in.u.qp_modify.scratch = (uintptr_t)cqp_request; 1256*915cc7acSMustafa Ismail m_info->next_iwarp_state = IRDMA_QP_STATE_ERROR; 1257*915cc7acSMustafa Ismail m_info->reset_tcp_conn = true; 1258*915cc7acSMustafa Ismail irdma_handle_cqp_op(rf, cqp_request); 1259*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1260*915cc7acSMustafa Ismail } 1261*915cc7acSMustafa Ismail break; 1262*915cc7acSMustafa Ismail case IRDMA_QP_STATE_ERROR: 1263*915cc7acSMustafa Ismail default: 1264*915cc7acSMustafa Ismail break; 1265*915cc7acSMustafa Ismail } 1266*915cc7acSMustafa Ismail } 1267*915cc7acSMustafa Ismail 1268*915cc7acSMustafa Ismail return status; 1269*915cc7acSMustafa Ismail } 1270*915cc7acSMustafa Ismail 1271*915cc7acSMustafa Ismail /** 1272*915cc7acSMustafa Ismail * irdma_cqp_cq_destroy_cmd - destroy the cqp cq 1273*915cc7acSMustafa Ismail * @dev: device pointer 1274*915cc7acSMustafa Ismail * @cq: pointer to cq 1275*915cc7acSMustafa Ismail */ 1276*915cc7acSMustafa Ismail void irdma_cqp_cq_destroy_cmd(struct irdma_sc_dev *dev, struct irdma_sc_cq *cq) 1277*915cc7acSMustafa Ismail { 1278*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1279*915cc7acSMustafa Ismail 1280*915cc7acSMustafa Ismail irdma_cq_wq_destroy(rf, cq); 1281*915cc7acSMustafa Ismail } 1282*915cc7acSMustafa Ismail 1283*915cc7acSMustafa Ismail /** 1284*915cc7acSMustafa Ismail * irdma_cqp_qp_destroy_cmd - destroy the cqp 1285*915cc7acSMustafa Ismail * @dev: device pointer 1286*915cc7acSMustafa Ismail * @qp: pointer to qp 1287*915cc7acSMustafa Ismail */ 1288*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_qp_destroy_cmd(struct irdma_sc_dev *dev, struct irdma_sc_qp *qp) 1289*915cc7acSMustafa Ismail { 1290*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1291*915cc7acSMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 1292*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1293*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1294*915cc7acSMustafa Ismail enum irdma_status_code status; 1295*915cc7acSMustafa Ismail 1296*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, true); 1297*915cc7acSMustafa Ismail if (!cqp_request) 1298*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1299*915cc7acSMustafa Ismail 1300*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1301*915cc7acSMustafa Ismail memset(cqp_info, 0, sizeof(*cqp_info)); 1302*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_QP_DESTROY; 1303*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1304*915cc7acSMustafa Ismail cqp_info->in.u.qp_destroy.qp = qp; 1305*915cc7acSMustafa Ismail cqp_info->in.u.qp_destroy.scratch = (uintptr_t)cqp_request; 1306*915cc7acSMustafa Ismail cqp_info->in.u.qp_destroy.remove_hash_idx = true; 1307*915cc7acSMustafa Ismail 1308*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1309*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1310*915cc7acSMustafa Ismail 1311*915cc7acSMustafa Ismail return status; 1312*915cc7acSMustafa Ismail } 1313*915cc7acSMustafa Ismail 1314*915cc7acSMustafa Ismail /** 1315*915cc7acSMustafa Ismail * irdma_ieq_mpa_crc_ae - generate AE for crc error 1316*915cc7acSMustafa Ismail * @dev: hardware control device structure 1317*915cc7acSMustafa Ismail * @qp: hardware control qp 1318*915cc7acSMustafa Ismail */ 1319*915cc7acSMustafa Ismail void irdma_ieq_mpa_crc_ae(struct irdma_sc_dev *dev, struct irdma_sc_qp *qp) 1320*915cc7acSMustafa Ismail { 1321*915cc7acSMustafa Ismail struct irdma_gen_ae_info info = {}; 1322*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1323*915cc7acSMustafa Ismail 1324*915cc7acSMustafa Ismail ibdev_dbg(&rf->iwdev->ibdev, "AEQ: Generate MPA CRC AE\n"); 1325*915cc7acSMustafa Ismail info.ae_code = IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR; 1326*915cc7acSMustafa Ismail info.ae_src = IRDMA_AE_SOURCE_RQ; 1327*915cc7acSMustafa Ismail irdma_gen_ae(rf, qp, &info, false); 1328*915cc7acSMustafa Ismail } 1329*915cc7acSMustafa Ismail 1330*915cc7acSMustafa Ismail /** 1331*915cc7acSMustafa Ismail * irdma_init_hash_desc - initialize hash for crc calculation 1332*915cc7acSMustafa Ismail * @desc: cryption type 1333*915cc7acSMustafa Ismail */ 1334*915cc7acSMustafa Ismail enum irdma_status_code irdma_init_hash_desc(struct shash_desc **desc) 1335*915cc7acSMustafa Ismail { 1336*915cc7acSMustafa Ismail struct crypto_shash *tfm; 1337*915cc7acSMustafa Ismail struct shash_desc *tdesc; 1338*915cc7acSMustafa Ismail 1339*915cc7acSMustafa Ismail tfm = crypto_alloc_shash("crc32c", 0, 0); 1340*915cc7acSMustafa Ismail if (IS_ERR(tfm)) 1341*915cc7acSMustafa Ismail return IRDMA_ERR_MPA_CRC; 1342*915cc7acSMustafa Ismail 1343*915cc7acSMustafa Ismail tdesc = kzalloc(sizeof(*tdesc) + crypto_shash_descsize(tfm), 1344*915cc7acSMustafa Ismail GFP_KERNEL); 1345*915cc7acSMustafa Ismail if (!tdesc) { 1346*915cc7acSMustafa Ismail crypto_free_shash(tfm); 1347*915cc7acSMustafa Ismail return IRDMA_ERR_MPA_CRC; 1348*915cc7acSMustafa Ismail } 1349*915cc7acSMustafa Ismail 1350*915cc7acSMustafa Ismail tdesc->tfm = tfm; 1351*915cc7acSMustafa Ismail *desc = tdesc; 1352*915cc7acSMustafa Ismail 1353*915cc7acSMustafa Ismail return 0; 1354*915cc7acSMustafa Ismail } 1355*915cc7acSMustafa Ismail 1356*915cc7acSMustafa Ismail /** 1357*915cc7acSMustafa Ismail * irdma_free_hash_desc - free hash desc 1358*915cc7acSMustafa Ismail * @desc: to be freed 1359*915cc7acSMustafa Ismail */ 1360*915cc7acSMustafa Ismail void irdma_free_hash_desc(struct shash_desc *desc) 1361*915cc7acSMustafa Ismail { 1362*915cc7acSMustafa Ismail if (desc) { 1363*915cc7acSMustafa Ismail crypto_free_shash(desc->tfm); 1364*915cc7acSMustafa Ismail kfree(desc); 1365*915cc7acSMustafa Ismail } 1366*915cc7acSMustafa Ismail } 1367*915cc7acSMustafa Ismail 1368*915cc7acSMustafa Ismail /** 1369*915cc7acSMustafa Ismail * irdma_ieq_check_mpacrc - check if mpa crc is OK 1370*915cc7acSMustafa Ismail * @desc: desc for hash 1371*915cc7acSMustafa Ismail * @addr: address of buffer for crc 1372*915cc7acSMustafa Ismail * @len: length of buffer 1373*915cc7acSMustafa Ismail * @val: value to be compared 1374*915cc7acSMustafa Ismail */ 1375*915cc7acSMustafa Ismail enum irdma_status_code irdma_ieq_check_mpacrc(struct shash_desc *desc, 1376*915cc7acSMustafa Ismail void *addr, u32 len, u32 val) 1377*915cc7acSMustafa Ismail { 1378*915cc7acSMustafa Ismail u32 crc = 0; 1379*915cc7acSMustafa Ismail int ret; 1380*915cc7acSMustafa Ismail enum irdma_status_code ret_code = 0; 1381*915cc7acSMustafa Ismail 1382*915cc7acSMustafa Ismail crypto_shash_init(desc); 1383*915cc7acSMustafa Ismail ret = crypto_shash_update(desc, addr, len); 1384*915cc7acSMustafa Ismail if (!ret) 1385*915cc7acSMustafa Ismail crypto_shash_final(desc, (u8 *)&crc); 1386*915cc7acSMustafa Ismail if (crc != val) 1387*915cc7acSMustafa Ismail ret_code = IRDMA_ERR_MPA_CRC; 1388*915cc7acSMustafa Ismail 1389*915cc7acSMustafa Ismail return ret_code; 1390*915cc7acSMustafa Ismail } 1391*915cc7acSMustafa Ismail 1392*915cc7acSMustafa Ismail /** 1393*915cc7acSMustafa Ismail * irdma_ieq_get_qp - get qp based on quad in puda buffer 1394*915cc7acSMustafa Ismail * @dev: hardware control device structure 1395*915cc7acSMustafa Ismail * @buf: receive puda buffer on exception q 1396*915cc7acSMustafa Ismail */ 1397*915cc7acSMustafa Ismail struct irdma_sc_qp *irdma_ieq_get_qp(struct irdma_sc_dev *dev, 1398*915cc7acSMustafa Ismail struct irdma_puda_buf *buf) 1399*915cc7acSMustafa Ismail { 1400*915cc7acSMustafa Ismail struct irdma_qp *iwqp; 1401*915cc7acSMustafa Ismail struct irdma_cm_node *cm_node; 1402*915cc7acSMustafa Ismail struct irdma_device *iwdev = buf->vsi->back_vsi; 1403*915cc7acSMustafa Ismail u32 loc_addr[4] = {}; 1404*915cc7acSMustafa Ismail u32 rem_addr[4] = {}; 1405*915cc7acSMustafa Ismail u16 loc_port, rem_port; 1406*915cc7acSMustafa Ismail struct ipv6hdr *ip6h; 1407*915cc7acSMustafa Ismail struct iphdr *iph = (struct iphdr *)buf->iph; 1408*915cc7acSMustafa Ismail struct tcphdr *tcph = (struct tcphdr *)buf->tcph; 1409*915cc7acSMustafa Ismail 1410*915cc7acSMustafa Ismail if (iph->version == 4) { 1411*915cc7acSMustafa Ismail loc_addr[0] = ntohl(iph->daddr); 1412*915cc7acSMustafa Ismail rem_addr[0] = ntohl(iph->saddr); 1413*915cc7acSMustafa Ismail } else { 1414*915cc7acSMustafa Ismail ip6h = (struct ipv6hdr *)buf->iph; 1415*915cc7acSMustafa Ismail irdma_copy_ip_ntohl(loc_addr, ip6h->daddr.in6_u.u6_addr32); 1416*915cc7acSMustafa Ismail irdma_copy_ip_ntohl(rem_addr, ip6h->saddr.in6_u.u6_addr32); 1417*915cc7acSMustafa Ismail } 1418*915cc7acSMustafa Ismail loc_port = ntohs(tcph->dest); 1419*915cc7acSMustafa Ismail rem_port = ntohs(tcph->source); 1420*915cc7acSMustafa Ismail cm_node = irdma_find_node(&iwdev->cm_core, rem_port, rem_addr, loc_port, 1421*915cc7acSMustafa Ismail loc_addr, buf->vlan_valid ? buf->vlan_id : 0xFFFF); 1422*915cc7acSMustafa Ismail if (!cm_node) 1423*915cc7acSMustafa Ismail return NULL; 1424*915cc7acSMustafa Ismail 1425*915cc7acSMustafa Ismail iwqp = cm_node->iwqp; 1426*915cc7acSMustafa Ismail irdma_rem_ref_cm_node(cm_node); 1427*915cc7acSMustafa Ismail 1428*915cc7acSMustafa Ismail return &iwqp->sc_qp; 1429*915cc7acSMustafa Ismail } 1430*915cc7acSMustafa Ismail 1431*915cc7acSMustafa Ismail /** 1432*915cc7acSMustafa Ismail * irdma_send_ieq_ack - ACKs for duplicate or OOO partials FPDUs 1433*915cc7acSMustafa Ismail * @qp: qp ptr 1434*915cc7acSMustafa Ismail */ 1435*915cc7acSMustafa Ismail void irdma_send_ieq_ack(struct irdma_sc_qp *qp) 1436*915cc7acSMustafa Ismail { 1437*915cc7acSMustafa Ismail struct irdma_cm_node *cm_node = ((struct irdma_qp *)qp->qp_uk.back_qp)->cm_node; 1438*915cc7acSMustafa Ismail struct irdma_puda_buf *buf = qp->pfpdu.lastrcv_buf; 1439*915cc7acSMustafa Ismail struct tcphdr *tcph = (struct tcphdr *)buf->tcph; 1440*915cc7acSMustafa Ismail 1441*915cc7acSMustafa Ismail cm_node->tcp_cntxt.rcv_nxt = qp->pfpdu.nextseqnum; 1442*915cc7acSMustafa Ismail cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); 1443*915cc7acSMustafa Ismail 1444*915cc7acSMustafa Ismail irdma_send_ack(cm_node); 1445*915cc7acSMustafa Ismail } 1446*915cc7acSMustafa Ismail 1447*915cc7acSMustafa Ismail /** 1448*915cc7acSMustafa Ismail * irdma_puda_ieq_get_ah_info - get AH info from IEQ buffer 1449*915cc7acSMustafa Ismail * @qp: qp pointer 1450*915cc7acSMustafa Ismail * @ah_info: AH info pointer 1451*915cc7acSMustafa Ismail */ 1452*915cc7acSMustafa Ismail void irdma_puda_ieq_get_ah_info(struct irdma_sc_qp *qp, 1453*915cc7acSMustafa Ismail struct irdma_ah_info *ah_info) 1454*915cc7acSMustafa Ismail { 1455*915cc7acSMustafa Ismail struct irdma_puda_buf *buf = qp->pfpdu.ah_buf; 1456*915cc7acSMustafa Ismail struct iphdr *iph; 1457*915cc7acSMustafa Ismail struct ipv6hdr *ip6h; 1458*915cc7acSMustafa Ismail 1459*915cc7acSMustafa Ismail memset(ah_info, 0, sizeof(*ah_info)); 1460*915cc7acSMustafa Ismail ah_info->do_lpbk = true; 1461*915cc7acSMustafa Ismail ah_info->vlan_tag = buf->vlan_id; 1462*915cc7acSMustafa Ismail ah_info->insert_vlan_tag = buf->vlan_valid; 1463*915cc7acSMustafa Ismail ah_info->ipv4_valid = buf->ipv4; 1464*915cc7acSMustafa Ismail ah_info->vsi = qp->vsi; 1465*915cc7acSMustafa Ismail 1466*915cc7acSMustafa Ismail if (buf->smac_valid) 1467*915cc7acSMustafa Ismail ether_addr_copy(ah_info->mac_addr, buf->smac); 1468*915cc7acSMustafa Ismail 1469*915cc7acSMustafa Ismail if (buf->ipv4) { 1470*915cc7acSMustafa Ismail ah_info->ipv4_valid = true; 1471*915cc7acSMustafa Ismail iph = (struct iphdr *)buf->iph; 1472*915cc7acSMustafa Ismail ah_info->hop_ttl = iph->ttl; 1473*915cc7acSMustafa Ismail ah_info->tc_tos = iph->tos; 1474*915cc7acSMustafa Ismail ah_info->dest_ip_addr[0] = ntohl(iph->daddr); 1475*915cc7acSMustafa Ismail ah_info->src_ip_addr[0] = ntohl(iph->saddr); 1476*915cc7acSMustafa Ismail } else { 1477*915cc7acSMustafa Ismail ip6h = (struct ipv6hdr *)buf->iph; 1478*915cc7acSMustafa Ismail ah_info->hop_ttl = ip6h->hop_limit; 1479*915cc7acSMustafa Ismail ah_info->tc_tos = ip6h->priority; 1480*915cc7acSMustafa Ismail irdma_copy_ip_ntohl(ah_info->dest_ip_addr, 1481*915cc7acSMustafa Ismail ip6h->daddr.in6_u.u6_addr32); 1482*915cc7acSMustafa Ismail irdma_copy_ip_ntohl(ah_info->src_ip_addr, 1483*915cc7acSMustafa Ismail ip6h->saddr.in6_u.u6_addr32); 1484*915cc7acSMustafa Ismail } 1485*915cc7acSMustafa Ismail 1486*915cc7acSMustafa Ismail ah_info->dst_arpindex = irdma_arp_table(dev_to_rf(qp->dev), 1487*915cc7acSMustafa Ismail ah_info->dest_ip_addr, 1488*915cc7acSMustafa Ismail ah_info->ipv4_valid, 1489*915cc7acSMustafa Ismail NULL, IRDMA_ARP_RESOLVE); 1490*915cc7acSMustafa Ismail } 1491*915cc7acSMustafa Ismail 1492*915cc7acSMustafa Ismail /** 1493*915cc7acSMustafa Ismail * irdma_gen1_ieq_update_tcpip_info - update tcpip in the buffer 1494*915cc7acSMustafa Ismail * @buf: puda to update 1495*915cc7acSMustafa Ismail * @len: length of buffer 1496*915cc7acSMustafa Ismail * @seqnum: seq number for tcp 1497*915cc7acSMustafa Ismail */ 1498*915cc7acSMustafa Ismail static void irdma_gen1_ieq_update_tcpip_info(struct irdma_puda_buf *buf, 1499*915cc7acSMustafa Ismail u16 len, u32 seqnum) 1500*915cc7acSMustafa Ismail { 1501*915cc7acSMustafa Ismail struct tcphdr *tcph; 1502*915cc7acSMustafa Ismail struct iphdr *iph; 1503*915cc7acSMustafa Ismail u16 iphlen; 1504*915cc7acSMustafa Ismail u16 pktsize; 1505*915cc7acSMustafa Ismail u8 *addr = buf->mem.va; 1506*915cc7acSMustafa Ismail 1507*915cc7acSMustafa Ismail iphlen = (buf->ipv4) ? 20 : 40; 1508*915cc7acSMustafa Ismail iph = (struct iphdr *)(addr + buf->maclen); 1509*915cc7acSMustafa Ismail tcph = (struct tcphdr *)(addr + buf->maclen + iphlen); 1510*915cc7acSMustafa Ismail pktsize = len + buf->tcphlen + iphlen; 1511*915cc7acSMustafa Ismail iph->tot_len = htons(pktsize); 1512*915cc7acSMustafa Ismail tcph->seq = htonl(seqnum); 1513*915cc7acSMustafa Ismail } 1514*915cc7acSMustafa Ismail 1515*915cc7acSMustafa Ismail /** 1516*915cc7acSMustafa Ismail * irdma_ieq_update_tcpip_info - update tcpip in the buffer 1517*915cc7acSMustafa Ismail * @buf: puda to update 1518*915cc7acSMustafa Ismail * @len: length of buffer 1519*915cc7acSMustafa Ismail * @seqnum: seq number for tcp 1520*915cc7acSMustafa Ismail */ 1521*915cc7acSMustafa Ismail void irdma_ieq_update_tcpip_info(struct irdma_puda_buf *buf, u16 len, 1522*915cc7acSMustafa Ismail u32 seqnum) 1523*915cc7acSMustafa Ismail { 1524*915cc7acSMustafa Ismail struct tcphdr *tcph; 1525*915cc7acSMustafa Ismail u8 *addr; 1526*915cc7acSMustafa Ismail 1527*915cc7acSMustafa Ismail if (buf->vsi->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1) 1528*915cc7acSMustafa Ismail return irdma_gen1_ieq_update_tcpip_info(buf, len, seqnum); 1529*915cc7acSMustafa Ismail 1530*915cc7acSMustafa Ismail addr = buf->mem.va; 1531*915cc7acSMustafa Ismail tcph = (struct tcphdr *)addr; 1532*915cc7acSMustafa Ismail tcph->seq = htonl(seqnum); 1533*915cc7acSMustafa Ismail } 1534*915cc7acSMustafa Ismail 1535*915cc7acSMustafa Ismail /** 1536*915cc7acSMustafa Ismail * irdma_gen1_puda_get_tcpip_info - get tcpip info from puda 1537*915cc7acSMustafa Ismail * buffer 1538*915cc7acSMustafa Ismail * @info: to get information 1539*915cc7acSMustafa Ismail * @buf: puda buffer 1540*915cc7acSMustafa Ismail */ 1541*915cc7acSMustafa Ismail static enum irdma_status_code 1542*915cc7acSMustafa Ismail irdma_gen1_puda_get_tcpip_info(struct irdma_puda_cmpl_info *info, 1543*915cc7acSMustafa Ismail struct irdma_puda_buf *buf) 1544*915cc7acSMustafa Ismail { 1545*915cc7acSMustafa Ismail struct iphdr *iph; 1546*915cc7acSMustafa Ismail struct ipv6hdr *ip6h; 1547*915cc7acSMustafa Ismail struct tcphdr *tcph; 1548*915cc7acSMustafa Ismail u16 iphlen; 1549*915cc7acSMustafa Ismail u16 pkt_len; 1550*915cc7acSMustafa Ismail u8 *mem = buf->mem.va; 1551*915cc7acSMustafa Ismail struct ethhdr *ethh = buf->mem.va; 1552*915cc7acSMustafa Ismail 1553*915cc7acSMustafa Ismail if (ethh->h_proto == htons(0x8100)) { 1554*915cc7acSMustafa Ismail info->vlan_valid = true; 1555*915cc7acSMustafa Ismail buf->vlan_id = ntohs(((struct vlan_ethhdr *)ethh)->h_vlan_TCI) & 1556*915cc7acSMustafa Ismail VLAN_VID_MASK; 1557*915cc7acSMustafa Ismail } 1558*915cc7acSMustafa Ismail 1559*915cc7acSMustafa Ismail buf->maclen = (info->vlan_valid) ? 18 : 14; 1560*915cc7acSMustafa Ismail iphlen = (info->l3proto) ? 40 : 20; 1561*915cc7acSMustafa Ismail buf->ipv4 = (info->l3proto) ? false : true; 1562*915cc7acSMustafa Ismail buf->iph = mem + buf->maclen; 1563*915cc7acSMustafa Ismail iph = (struct iphdr *)buf->iph; 1564*915cc7acSMustafa Ismail buf->tcph = buf->iph + iphlen; 1565*915cc7acSMustafa Ismail tcph = (struct tcphdr *)buf->tcph; 1566*915cc7acSMustafa Ismail 1567*915cc7acSMustafa Ismail if (buf->ipv4) { 1568*915cc7acSMustafa Ismail pkt_len = ntohs(iph->tot_len); 1569*915cc7acSMustafa Ismail } else { 1570*915cc7acSMustafa Ismail ip6h = (struct ipv6hdr *)buf->iph; 1571*915cc7acSMustafa Ismail pkt_len = ntohs(ip6h->payload_len) + iphlen; 1572*915cc7acSMustafa Ismail } 1573*915cc7acSMustafa Ismail 1574*915cc7acSMustafa Ismail buf->totallen = pkt_len + buf->maclen; 1575*915cc7acSMustafa Ismail 1576*915cc7acSMustafa Ismail if (info->payload_len < buf->totallen) { 1577*915cc7acSMustafa Ismail ibdev_dbg(to_ibdev(buf->vsi->dev), 1578*915cc7acSMustafa Ismail "ERR: payload_len = 0x%x totallen expected0x%x\n", 1579*915cc7acSMustafa Ismail info->payload_len, buf->totallen); 1580*915cc7acSMustafa Ismail return IRDMA_ERR_INVALID_SIZE; 1581*915cc7acSMustafa Ismail } 1582*915cc7acSMustafa Ismail 1583*915cc7acSMustafa Ismail buf->tcphlen = tcph->doff << 2; 1584*915cc7acSMustafa Ismail buf->datalen = pkt_len - iphlen - buf->tcphlen; 1585*915cc7acSMustafa Ismail buf->data = buf->datalen ? buf->tcph + buf->tcphlen : NULL; 1586*915cc7acSMustafa Ismail buf->hdrlen = buf->maclen + iphlen + buf->tcphlen; 1587*915cc7acSMustafa Ismail buf->seqnum = ntohl(tcph->seq); 1588*915cc7acSMustafa Ismail 1589*915cc7acSMustafa Ismail return 0; 1590*915cc7acSMustafa Ismail } 1591*915cc7acSMustafa Ismail 1592*915cc7acSMustafa Ismail /** 1593*915cc7acSMustafa Ismail * irdma_puda_get_tcpip_info - get tcpip info from puda buffer 1594*915cc7acSMustafa Ismail * @info: to get information 1595*915cc7acSMustafa Ismail * @buf: puda buffer 1596*915cc7acSMustafa Ismail */ 1597*915cc7acSMustafa Ismail enum irdma_status_code 1598*915cc7acSMustafa Ismail irdma_puda_get_tcpip_info(struct irdma_puda_cmpl_info *info, 1599*915cc7acSMustafa Ismail struct irdma_puda_buf *buf) 1600*915cc7acSMustafa Ismail { 1601*915cc7acSMustafa Ismail struct tcphdr *tcph; 1602*915cc7acSMustafa Ismail u32 pkt_len; 1603*915cc7acSMustafa Ismail u8 *mem; 1604*915cc7acSMustafa Ismail 1605*915cc7acSMustafa Ismail if (buf->vsi->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1) 1606*915cc7acSMustafa Ismail return irdma_gen1_puda_get_tcpip_info(info, buf); 1607*915cc7acSMustafa Ismail 1608*915cc7acSMustafa Ismail mem = buf->mem.va; 1609*915cc7acSMustafa Ismail buf->vlan_valid = info->vlan_valid; 1610*915cc7acSMustafa Ismail if (info->vlan_valid) 1611*915cc7acSMustafa Ismail buf->vlan_id = info->vlan; 1612*915cc7acSMustafa Ismail 1613*915cc7acSMustafa Ismail buf->ipv4 = info->ipv4; 1614*915cc7acSMustafa Ismail if (buf->ipv4) 1615*915cc7acSMustafa Ismail buf->iph = mem + IRDMA_IPV4_PAD; 1616*915cc7acSMustafa Ismail else 1617*915cc7acSMustafa Ismail buf->iph = mem; 1618*915cc7acSMustafa Ismail 1619*915cc7acSMustafa Ismail buf->tcph = mem + IRDMA_TCP_OFFSET; 1620*915cc7acSMustafa Ismail tcph = (struct tcphdr *)buf->tcph; 1621*915cc7acSMustafa Ismail pkt_len = info->payload_len; 1622*915cc7acSMustafa Ismail buf->totallen = pkt_len; 1623*915cc7acSMustafa Ismail buf->tcphlen = tcph->doff << 2; 1624*915cc7acSMustafa Ismail buf->datalen = pkt_len - IRDMA_TCP_OFFSET - buf->tcphlen; 1625*915cc7acSMustafa Ismail buf->data = buf->datalen ? buf->tcph + buf->tcphlen : NULL; 1626*915cc7acSMustafa Ismail buf->hdrlen = IRDMA_TCP_OFFSET + buf->tcphlen; 1627*915cc7acSMustafa Ismail buf->seqnum = ntohl(tcph->seq); 1628*915cc7acSMustafa Ismail 1629*915cc7acSMustafa Ismail if (info->smac_valid) { 1630*915cc7acSMustafa Ismail ether_addr_copy(buf->smac, info->smac); 1631*915cc7acSMustafa Ismail buf->smac_valid = true; 1632*915cc7acSMustafa Ismail } 1633*915cc7acSMustafa Ismail 1634*915cc7acSMustafa Ismail return 0; 1635*915cc7acSMustafa Ismail } 1636*915cc7acSMustafa Ismail 1637*915cc7acSMustafa Ismail /** 1638*915cc7acSMustafa Ismail * irdma_hw_stats_timeout - Stats timer-handler which updates all HW stats 1639*915cc7acSMustafa Ismail * @t: timer_list pointer 1640*915cc7acSMustafa Ismail */ 1641*915cc7acSMustafa Ismail static void irdma_hw_stats_timeout(struct timer_list *t) 1642*915cc7acSMustafa Ismail { 1643*915cc7acSMustafa Ismail struct irdma_vsi_pestat *pf_devstat = 1644*915cc7acSMustafa Ismail from_timer(pf_devstat, t, stats_timer); 1645*915cc7acSMustafa Ismail struct irdma_sc_vsi *sc_vsi = pf_devstat->vsi; 1646*915cc7acSMustafa Ismail 1647*915cc7acSMustafa Ismail if (sc_vsi->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1) 1648*915cc7acSMustafa Ismail irdma_cqp_gather_stats_gen1(sc_vsi->dev, sc_vsi->pestat); 1649*915cc7acSMustafa Ismail else 1650*915cc7acSMustafa Ismail irdma_cqp_gather_stats_cmd(sc_vsi->dev, sc_vsi->pestat, false); 1651*915cc7acSMustafa Ismail 1652*915cc7acSMustafa Ismail mod_timer(&pf_devstat->stats_timer, 1653*915cc7acSMustafa Ismail jiffies + msecs_to_jiffies(STATS_TIMER_DELAY)); 1654*915cc7acSMustafa Ismail } 1655*915cc7acSMustafa Ismail 1656*915cc7acSMustafa Ismail /** 1657*915cc7acSMustafa Ismail * irdma_hw_stats_start_timer - Start periodic stats timer 1658*915cc7acSMustafa Ismail * @vsi: vsi structure pointer 1659*915cc7acSMustafa Ismail */ 1660*915cc7acSMustafa Ismail void irdma_hw_stats_start_timer(struct irdma_sc_vsi *vsi) 1661*915cc7acSMustafa Ismail { 1662*915cc7acSMustafa Ismail struct irdma_vsi_pestat *devstat = vsi->pestat; 1663*915cc7acSMustafa Ismail 1664*915cc7acSMustafa Ismail timer_setup(&devstat->stats_timer, irdma_hw_stats_timeout, 0); 1665*915cc7acSMustafa Ismail mod_timer(&devstat->stats_timer, 1666*915cc7acSMustafa Ismail jiffies + msecs_to_jiffies(STATS_TIMER_DELAY)); 1667*915cc7acSMustafa Ismail } 1668*915cc7acSMustafa Ismail 1669*915cc7acSMustafa Ismail /** 1670*915cc7acSMustafa Ismail * irdma_hw_stats_stop_timer - Delete periodic stats timer 1671*915cc7acSMustafa Ismail * @vsi: pointer to vsi structure 1672*915cc7acSMustafa Ismail */ 1673*915cc7acSMustafa Ismail void irdma_hw_stats_stop_timer(struct irdma_sc_vsi *vsi) 1674*915cc7acSMustafa Ismail { 1675*915cc7acSMustafa Ismail struct irdma_vsi_pestat *devstat = vsi->pestat; 1676*915cc7acSMustafa Ismail 1677*915cc7acSMustafa Ismail del_timer_sync(&devstat->stats_timer); 1678*915cc7acSMustafa Ismail } 1679*915cc7acSMustafa Ismail 1680*915cc7acSMustafa Ismail /** 1681*915cc7acSMustafa Ismail * irdma_process_stats - Checking for wrap and update stats 1682*915cc7acSMustafa Ismail * @pestat: stats structure pointer 1683*915cc7acSMustafa Ismail */ 1684*915cc7acSMustafa Ismail static inline void irdma_process_stats(struct irdma_vsi_pestat *pestat) 1685*915cc7acSMustafa Ismail { 1686*915cc7acSMustafa Ismail sc_vsi_update_stats(pestat->vsi); 1687*915cc7acSMustafa Ismail } 1688*915cc7acSMustafa Ismail 1689*915cc7acSMustafa Ismail /** 1690*915cc7acSMustafa Ismail * irdma_cqp_gather_stats_gen1 - Gather stats 1691*915cc7acSMustafa Ismail * @dev: pointer to device structure 1692*915cc7acSMustafa Ismail * @pestat: statistics structure 1693*915cc7acSMustafa Ismail */ 1694*915cc7acSMustafa Ismail void irdma_cqp_gather_stats_gen1(struct irdma_sc_dev *dev, 1695*915cc7acSMustafa Ismail struct irdma_vsi_pestat *pestat) 1696*915cc7acSMustafa Ismail { 1697*915cc7acSMustafa Ismail struct irdma_gather_stats *gather_stats = 1698*915cc7acSMustafa Ismail pestat->gather_info.gather_stats_va; 1699*915cc7acSMustafa Ismail u32 stats_inst_offset_32; 1700*915cc7acSMustafa Ismail u32 stats_inst_offset_64; 1701*915cc7acSMustafa Ismail 1702*915cc7acSMustafa Ismail stats_inst_offset_32 = (pestat->gather_info.use_stats_inst) ? 1703*915cc7acSMustafa Ismail pestat->gather_info.stats_inst_index : 1704*915cc7acSMustafa Ismail pestat->hw->hmc.hmc_fn_id; 1705*915cc7acSMustafa Ismail stats_inst_offset_32 *= 4; 1706*915cc7acSMustafa Ismail stats_inst_offset_64 = stats_inst_offset_32 * 2; 1707*915cc7acSMustafa Ismail 1708*915cc7acSMustafa Ismail gather_stats->rxvlanerr = 1709*915cc7acSMustafa Ismail rd32(dev->hw, 1710*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_RXVLANERR] 1711*915cc7acSMustafa Ismail + stats_inst_offset_32); 1712*915cc7acSMustafa Ismail gather_stats->ip4rxdiscard = 1713*915cc7acSMustafa Ismail rd32(dev->hw, 1714*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_IP4RXDISCARD] 1715*915cc7acSMustafa Ismail + stats_inst_offset_32); 1716*915cc7acSMustafa Ismail gather_stats->ip4rxtrunc = 1717*915cc7acSMustafa Ismail rd32(dev->hw, 1718*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_IP4RXTRUNC] 1719*915cc7acSMustafa Ismail + stats_inst_offset_32); 1720*915cc7acSMustafa Ismail gather_stats->ip4txnoroute = 1721*915cc7acSMustafa Ismail rd32(dev->hw, 1722*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_IP4TXNOROUTE] 1723*915cc7acSMustafa Ismail + stats_inst_offset_32); 1724*915cc7acSMustafa Ismail gather_stats->ip6rxdiscard = 1725*915cc7acSMustafa Ismail rd32(dev->hw, 1726*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_IP6RXDISCARD] 1727*915cc7acSMustafa Ismail + stats_inst_offset_32); 1728*915cc7acSMustafa Ismail gather_stats->ip6rxtrunc = 1729*915cc7acSMustafa Ismail rd32(dev->hw, 1730*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_IP6RXTRUNC] 1731*915cc7acSMustafa Ismail + stats_inst_offset_32); 1732*915cc7acSMustafa Ismail gather_stats->ip6txnoroute = 1733*915cc7acSMustafa Ismail rd32(dev->hw, 1734*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_IP6TXNOROUTE] 1735*915cc7acSMustafa Ismail + stats_inst_offset_32); 1736*915cc7acSMustafa Ismail gather_stats->tcprtxseg = 1737*915cc7acSMustafa Ismail rd32(dev->hw, 1738*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_TCPRTXSEG] 1739*915cc7acSMustafa Ismail + stats_inst_offset_32); 1740*915cc7acSMustafa Ismail gather_stats->tcprxopterr = 1741*915cc7acSMustafa Ismail rd32(dev->hw, 1742*915cc7acSMustafa Ismail dev->hw_stats_regs_32[IRDMA_HW_STAT_INDEX_TCPRXOPTERR] 1743*915cc7acSMustafa Ismail + stats_inst_offset_32); 1744*915cc7acSMustafa Ismail 1745*915cc7acSMustafa Ismail gather_stats->ip4rxocts = 1746*915cc7acSMustafa Ismail rd64(dev->hw, 1747*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4RXOCTS] 1748*915cc7acSMustafa Ismail + stats_inst_offset_64); 1749*915cc7acSMustafa Ismail gather_stats->ip4rxpkts = 1750*915cc7acSMustafa Ismail rd64(dev->hw, 1751*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4RXPKTS] 1752*915cc7acSMustafa Ismail + stats_inst_offset_64); 1753*915cc7acSMustafa Ismail gather_stats->ip4txfrag = 1754*915cc7acSMustafa Ismail rd64(dev->hw, 1755*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4RXFRAGS] 1756*915cc7acSMustafa Ismail + stats_inst_offset_64); 1757*915cc7acSMustafa Ismail gather_stats->ip4rxmcpkts = 1758*915cc7acSMustafa Ismail rd64(dev->hw, 1759*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4RXMCPKTS] 1760*915cc7acSMustafa Ismail + stats_inst_offset_64); 1761*915cc7acSMustafa Ismail gather_stats->ip4txocts = 1762*915cc7acSMustafa Ismail rd64(dev->hw, 1763*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4TXOCTS] 1764*915cc7acSMustafa Ismail + stats_inst_offset_64); 1765*915cc7acSMustafa Ismail gather_stats->ip4txpkts = 1766*915cc7acSMustafa Ismail rd64(dev->hw, 1767*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4TXPKTS] 1768*915cc7acSMustafa Ismail + stats_inst_offset_64); 1769*915cc7acSMustafa Ismail gather_stats->ip4txfrag = 1770*915cc7acSMustafa Ismail rd64(dev->hw, 1771*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4TXFRAGS] 1772*915cc7acSMustafa Ismail + stats_inst_offset_64); 1773*915cc7acSMustafa Ismail gather_stats->ip4txmcpkts = 1774*915cc7acSMustafa Ismail rd64(dev->hw, 1775*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP4TXMCPKTS] 1776*915cc7acSMustafa Ismail + stats_inst_offset_64); 1777*915cc7acSMustafa Ismail gather_stats->ip6rxocts = 1778*915cc7acSMustafa Ismail rd64(dev->hw, 1779*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6RXOCTS] 1780*915cc7acSMustafa Ismail + stats_inst_offset_64); 1781*915cc7acSMustafa Ismail gather_stats->ip6rxpkts = 1782*915cc7acSMustafa Ismail rd64(dev->hw, 1783*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6RXPKTS] 1784*915cc7acSMustafa Ismail + stats_inst_offset_64); 1785*915cc7acSMustafa Ismail gather_stats->ip6txfrags = 1786*915cc7acSMustafa Ismail rd64(dev->hw, 1787*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6RXFRAGS] 1788*915cc7acSMustafa Ismail + stats_inst_offset_64); 1789*915cc7acSMustafa Ismail gather_stats->ip6rxmcpkts = 1790*915cc7acSMustafa Ismail rd64(dev->hw, 1791*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6RXMCPKTS] 1792*915cc7acSMustafa Ismail + stats_inst_offset_64); 1793*915cc7acSMustafa Ismail gather_stats->ip6txocts = 1794*915cc7acSMustafa Ismail rd64(dev->hw, 1795*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6TXOCTS] 1796*915cc7acSMustafa Ismail + stats_inst_offset_64); 1797*915cc7acSMustafa Ismail gather_stats->ip6txpkts = 1798*915cc7acSMustafa Ismail rd64(dev->hw, 1799*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6TXPKTS] 1800*915cc7acSMustafa Ismail + stats_inst_offset_64); 1801*915cc7acSMustafa Ismail gather_stats->ip6txfrags = 1802*915cc7acSMustafa Ismail rd64(dev->hw, 1803*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6TXFRAGS] 1804*915cc7acSMustafa Ismail + stats_inst_offset_64); 1805*915cc7acSMustafa Ismail gather_stats->ip6txmcpkts = 1806*915cc7acSMustafa Ismail rd64(dev->hw, 1807*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_IP6TXMCPKTS] 1808*915cc7acSMustafa Ismail + stats_inst_offset_64); 1809*915cc7acSMustafa Ismail gather_stats->tcprxsegs = 1810*915cc7acSMustafa Ismail rd64(dev->hw, 1811*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_TCPRXSEGS] 1812*915cc7acSMustafa Ismail + stats_inst_offset_64); 1813*915cc7acSMustafa Ismail gather_stats->tcptxsegs = 1814*915cc7acSMustafa Ismail rd64(dev->hw, 1815*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_TCPTXSEG] 1816*915cc7acSMustafa Ismail + stats_inst_offset_64); 1817*915cc7acSMustafa Ismail gather_stats->rdmarxrds = 1818*915cc7acSMustafa Ismail rd64(dev->hw, 1819*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMARXRDS] 1820*915cc7acSMustafa Ismail + stats_inst_offset_64); 1821*915cc7acSMustafa Ismail gather_stats->rdmarxsnds = 1822*915cc7acSMustafa Ismail rd64(dev->hw, 1823*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMARXSNDS] 1824*915cc7acSMustafa Ismail + stats_inst_offset_64); 1825*915cc7acSMustafa Ismail gather_stats->rdmarxwrs = 1826*915cc7acSMustafa Ismail rd64(dev->hw, 1827*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMARXWRS] 1828*915cc7acSMustafa Ismail + stats_inst_offset_64); 1829*915cc7acSMustafa Ismail gather_stats->rdmatxrds = 1830*915cc7acSMustafa Ismail rd64(dev->hw, 1831*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMATXRDS] 1832*915cc7acSMustafa Ismail + stats_inst_offset_64); 1833*915cc7acSMustafa Ismail gather_stats->rdmatxsnds = 1834*915cc7acSMustafa Ismail rd64(dev->hw, 1835*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMATXSNDS] 1836*915cc7acSMustafa Ismail + stats_inst_offset_64); 1837*915cc7acSMustafa Ismail gather_stats->rdmatxwrs = 1838*915cc7acSMustafa Ismail rd64(dev->hw, 1839*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMATXWRS] 1840*915cc7acSMustafa Ismail + stats_inst_offset_64); 1841*915cc7acSMustafa Ismail gather_stats->rdmavbn = 1842*915cc7acSMustafa Ismail rd64(dev->hw, 1843*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMAVBND] 1844*915cc7acSMustafa Ismail + stats_inst_offset_64); 1845*915cc7acSMustafa Ismail gather_stats->rdmavinv = 1846*915cc7acSMustafa Ismail rd64(dev->hw, 1847*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_RDMAVINV] 1848*915cc7acSMustafa Ismail + stats_inst_offset_64); 1849*915cc7acSMustafa Ismail gather_stats->udprxpkts = 1850*915cc7acSMustafa Ismail rd64(dev->hw, 1851*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_UDPRXPKTS] 1852*915cc7acSMustafa Ismail + stats_inst_offset_64); 1853*915cc7acSMustafa Ismail gather_stats->udptxpkts = 1854*915cc7acSMustafa Ismail rd64(dev->hw, 1855*915cc7acSMustafa Ismail dev->hw_stats_regs_64[IRDMA_HW_STAT_INDEX_UDPTXPKTS] 1856*915cc7acSMustafa Ismail + stats_inst_offset_64); 1857*915cc7acSMustafa Ismail 1858*915cc7acSMustafa Ismail irdma_process_stats(pestat); 1859*915cc7acSMustafa Ismail } 1860*915cc7acSMustafa Ismail 1861*915cc7acSMustafa Ismail /** 1862*915cc7acSMustafa Ismail * irdma_process_cqp_stats - Checking for wrap and update stats 1863*915cc7acSMustafa Ismail * @cqp_request: cqp_request structure pointer 1864*915cc7acSMustafa Ismail */ 1865*915cc7acSMustafa Ismail static void irdma_process_cqp_stats(struct irdma_cqp_request *cqp_request) 1866*915cc7acSMustafa Ismail { 1867*915cc7acSMustafa Ismail struct irdma_vsi_pestat *pestat = cqp_request->param; 1868*915cc7acSMustafa Ismail 1869*915cc7acSMustafa Ismail irdma_process_stats(pestat); 1870*915cc7acSMustafa Ismail } 1871*915cc7acSMustafa Ismail 1872*915cc7acSMustafa Ismail /** 1873*915cc7acSMustafa Ismail * irdma_cqp_gather_stats_cmd - Gather stats 1874*915cc7acSMustafa Ismail * @dev: pointer to device structure 1875*915cc7acSMustafa Ismail * @pestat: pointer to stats info 1876*915cc7acSMustafa Ismail * @wait: flag to wait or not wait for stats 1877*915cc7acSMustafa Ismail */ 1878*915cc7acSMustafa Ismail enum irdma_status_code 1879*915cc7acSMustafa Ismail irdma_cqp_gather_stats_cmd(struct irdma_sc_dev *dev, 1880*915cc7acSMustafa Ismail struct irdma_vsi_pestat *pestat, bool wait) 1881*915cc7acSMustafa Ismail 1882*915cc7acSMustafa Ismail { 1883*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1884*915cc7acSMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 1885*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1886*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1887*915cc7acSMustafa Ismail enum irdma_status_code status; 1888*915cc7acSMustafa Ismail 1889*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, wait); 1890*915cc7acSMustafa Ismail if (!cqp_request) 1891*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1892*915cc7acSMustafa Ismail 1893*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1894*915cc7acSMustafa Ismail memset(cqp_info, 0, sizeof(*cqp_info)); 1895*915cc7acSMustafa Ismail cqp_info->cqp_cmd = IRDMA_OP_STATS_GATHER; 1896*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1897*915cc7acSMustafa Ismail cqp_info->in.u.stats_gather.info = pestat->gather_info; 1898*915cc7acSMustafa Ismail cqp_info->in.u.stats_gather.scratch = (uintptr_t)cqp_request; 1899*915cc7acSMustafa Ismail cqp_info->in.u.stats_gather.cqp = &rf->cqp.sc_cqp; 1900*915cc7acSMustafa Ismail cqp_request->param = pestat; 1901*915cc7acSMustafa Ismail if (!wait) 1902*915cc7acSMustafa Ismail cqp_request->callback_fcn = irdma_process_cqp_stats; 1903*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1904*915cc7acSMustafa Ismail if (wait) 1905*915cc7acSMustafa Ismail irdma_process_stats(pestat); 1906*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1907*915cc7acSMustafa Ismail 1908*915cc7acSMustafa Ismail return status; 1909*915cc7acSMustafa Ismail } 1910*915cc7acSMustafa Ismail 1911*915cc7acSMustafa Ismail /** 1912*915cc7acSMustafa Ismail * irdma_cqp_stats_inst_cmd - Allocate/free stats instance 1913*915cc7acSMustafa Ismail * @vsi: pointer to vsi structure 1914*915cc7acSMustafa Ismail * @cmd: command to allocate or free 1915*915cc7acSMustafa Ismail * @stats_info: pointer to allocate stats info 1916*915cc7acSMustafa Ismail */ 1917*915cc7acSMustafa Ismail enum irdma_status_code 1918*915cc7acSMustafa Ismail irdma_cqp_stats_inst_cmd(struct irdma_sc_vsi *vsi, u8 cmd, 1919*915cc7acSMustafa Ismail struct irdma_stats_inst_info *stats_info) 1920*915cc7acSMustafa Ismail { 1921*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(vsi->dev); 1922*915cc7acSMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 1923*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1924*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1925*915cc7acSMustafa Ismail enum irdma_status_code status; 1926*915cc7acSMustafa Ismail bool wait = false; 1927*915cc7acSMustafa Ismail 1928*915cc7acSMustafa Ismail if (cmd == IRDMA_OP_STATS_ALLOCATE) 1929*915cc7acSMustafa Ismail wait = true; 1930*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, wait); 1931*915cc7acSMustafa Ismail if (!cqp_request) 1932*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1933*915cc7acSMustafa Ismail 1934*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1935*915cc7acSMustafa Ismail memset(cqp_info, 0, sizeof(*cqp_info)); 1936*915cc7acSMustafa Ismail cqp_info->cqp_cmd = cmd; 1937*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1938*915cc7acSMustafa Ismail cqp_info->in.u.stats_manage.info = *stats_info; 1939*915cc7acSMustafa Ismail cqp_info->in.u.stats_manage.scratch = (uintptr_t)cqp_request; 1940*915cc7acSMustafa Ismail cqp_info->in.u.stats_manage.cqp = &rf->cqp.sc_cqp; 1941*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1942*915cc7acSMustafa Ismail if (wait) 1943*915cc7acSMustafa Ismail stats_info->stats_idx = cqp_request->compl_info.op_ret_val; 1944*915cc7acSMustafa Ismail irdma_put_cqp_request(iwcqp, cqp_request); 1945*915cc7acSMustafa Ismail 1946*915cc7acSMustafa Ismail return status; 1947*915cc7acSMustafa Ismail } 1948*915cc7acSMustafa Ismail 1949*915cc7acSMustafa Ismail /** 1950*915cc7acSMustafa Ismail * irdma_cqp_ceq_cmd - Create/Destroy CEQ's after CEQ 0 1951*915cc7acSMustafa Ismail * @dev: pointer to device info 1952*915cc7acSMustafa Ismail * @sc_ceq: pointer to ceq structure 1953*915cc7acSMustafa Ismail * @op: Create or Destroy 1954*915cc7acSMustafa Ismail */ 1955*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_ceq_cmd(struct irdma_sc_dev *dev, 1956*915cc7acSMustafa Ismail struct irdma_sc_ceq *sc_ceq, u8 op) 1957*915cc7acSMustafa Ismail { 1958*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1959*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1960*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1961*915cc7acSMustafa Ismail enum irdma_status_code status; 1962*915cc7acSMustafa Ismail 1963*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); 1964*915cc7acSMustafa Ismail if (!cqp_request) 1965*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1966*915cc7acSMustafa Ismail 1967*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1968*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1969*915cc7acSMustafa Ismail cqp_info->cqp_cmd = op; 1970*915cc7acSMustafa Ismail cqp_info->in.u.ceq_create.ceq = sc_ceq; 1971*915cc7acSMustafa Ismail cqp_info->in.u.ceq_create.scratch = (uintptr_t)cqp_request; 1972*915cc7acSMustafa Ismail 1973*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 1974*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 1975*915cc7acSMustafa Ismail 1976*915cc7acSMustafa Ismail return status; 1977*915cc7acSMustafa Ismail } 1978*915cc7acSMustafa Ismail 1979*915cc7acSMustafa Ismail /** 1980*915cc7acSMustafa Ismail * irdma_cqp_aeq_cmd - Create/Destroy AEQ 1981*915cc7acSMustafa Ismail * @dev: pointer to device info 1982*915cc7acSMustafa Ismail * @sc_aeq: pointer to aeq structure 1983*915cc7acSMustafa Ismail * @op: Create or Destroy 1984*915cc7acSMustafa Ismail */ 1985*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_aeq_cmd(struct irdma_sc_dev *dev, 1986*915cc7acSMustafa Ismail struct irdma_sc_aeq *sc_aeq, u8 op) 1987*915cc7acSMustafa Ismail { 1988*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 1989*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 1990*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 1991*915cc7acSMustafa Ismail enum irdma_status_code status; 1992*915cc7acSMustafa Ismail 1993*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); 1994*915cc7acSMustafa Ismail if (!cqp_request) 1995*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 1996*915cc7acSMustafa Ismail 1997*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 1998*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 1999*915cc7acSMustafa Ismail cqp_info->cqp_cmd = op; 2000*915cc7acSMustafa Ismail cqp_info->in.u.aeq_create.aeq = sc_aeq; 2001*915cc7acSMustafa Ismail cqp_info->in.u.aeq_create.scratch = (uintptr_t)cqp_request; 2002*915cc7acSMustafa Ismail 2003*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 2004*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 2005*915cc7acSMustafa Ismail 2006*915cc7acSMustafa Ismail return status; 2007*915cc7acSMustafa Ismail } 2008*915cc7acSMustafa Ismail 2009*915cc7acSMustafa Ismail /** 2010*915cc7acSMustafa Ismail * irdma_cqp_ws_node_cmd - Add/modify/delete ws node 2011*915cc7acSMustafa Ismail * @dev: pointer to device structure 2012*915cc7acSMustafa Ismail * @cmd: Add, modify or delete 2013*915cc7acSMustafa Ismail * @node_info: pointer to ws node info 2014*915cc7acSMustafa Ismail */ 2015*915cc7acSMustafa Ismail enum irdma_status_code 2016*915cc7acSMustafa Ismail irdma_cqp_ws_node_cmd(struct irdma_sc_dev *dev, u8 cmd, 2017*915cc7acSMustafa Ismail struct irdma_ws_node_info *node_info) 2018*915cc7acSMustafa Ismail { 2019*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 2020*915cc7acSMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 2021*915cc7acSMustafa Ismail struct irdma_sc_cqp *cqp = &iwcqp->sc_cqp; 2022*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 2023*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 2024*915cc7acSMustafa Ismail enum irdma_status_code status; 2025*915cc7acSMustafa Ismail bool poll; 2026*915cc7acSMustafa Ismail 2027*915cc7acSMustafa Ismail if (!rf->sc_dev.ceq_valid) 2028*915cc7acSMustafa Ismail poll = true; 2029*915cc7acSMustafa Ismail else 2030*915cc7acSMustafa Ismail poll = false; 2031*915cc7acSMustafa Ismail 2032*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, !poll); 2033*915cc7acSMustafa Ismail if (!cqp_request) 2034*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2035*915cc7acSMustafa Ismail 2036*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 2037*915cc7acSMustafa Ismail memset(cqp_info, 0, sizeof(*cqp_info)); 2038*915cc7acSMustafa Ismail cqp_info->cqp_cmd = cmd; 2039*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 2040*915cc7acSMustafa Ismail cqp_info->in.u.ws_node.info = *node_info; 2041*915cc7acSMustafa Ismail cqp_info->in.u.ws_node.cqp = cqp; 2042*915cc7acSMustafa Ismail cqp_info->in.u.ws_node.scratch = (uintptr_t)cqp_request; 2043*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 2044*915cc7acSMustafa Ismail if (status) 2045*915cc7acSMustafa Ismail goto exit; 2046*915cc7acSMustafa Ismail 2047*915cc7acSMustafa Ismail if (poll) { 2048*915cc7acSMustafa Ismail struct irdma_ccq_cqe_info compl_info; 2049*915cc7acSMustafa Ismail 2050*915cc7acSMustafa Ismail status = irdma_sc_poll_for_cqp_op_done(cqp, IRDMA_CQP_OP_WORK_SCHED_NODE, 2051*915cc7acSMustafa Ismail &compl_info); 2052*915cc7acSMustafa Ismail node_info->qs_handle = compl_info.op_ret_val; 2053*915cc7acSMustafa Ismail ibdev_dbg(&rf->iwdev->ibdev, "DCB: opcode=%d, compl_info.retval=%d\n", 2054*915cc7acSMustafa Ismail compl_info.op_code, compl_info.op_ret_val); 2055*915cc7acSMustafa Ismail } else { 2056*915cc7acSMustafa Ismail node_info->qs_handle = cqp_request->compl_info.op_ret_val; 2057*915cc7acSMustafa Ismail } 2058*915cc7acSMustafa Ismail 2059*915cc7acSMustafa Ismail exit: 2060*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 2061*915cc7acSMustafa Ismail 2062*915cc7acSMustafa Ismail return status; 2063*915cc7acSMustafa Ismail } 2064*915cc7acSMustafa Ismail 2065*915cc7acSMustafa Ismail /** 2066*915cc7acSMustafa Ismail * irdma_cqp_up_map_cmd - Set the up-up mapping 2067*915cc7acSMustafa Ismail * @dev: pointer to device structure 2068*915cc7acSMustafa Ismail * @cmd: map command 2069*915cc7acSMustafa Ismail * @map_info: pointer to up map info 2070*915cc7acSMustafa Ismail */ 2071*915cc7acSMustafa Ismail enum irdma_status_code irdma_cqp_up_map_cmd(struct irdma_sc_dev *dev, u8 cmd, 2072*915cc7acSMustafa Ismail struct irdma_up_info *map_info) 2073*915cc7acSMustafa Ismail { 2074*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 2075*915cc7acSMustafa Ismail struct irdma_cqp *iwcqp = &rf->cqp; 2076*915cc7acSMustafa Ismail struct irdma_sc_cqp *cqp = &iwcqp->sc_cqp; 2077*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 2078*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 2079*915cc7acSMustafa Ismail enum irdma_status_code status; 2080*915cc7acSMustafa Ismail 2081*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, false); 2082*915cc7acSMustafa Ismail if (!cqp_request) 2083*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2084*915cc7acSMustafa Ismail 2085*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 2086*915cc7acSMustafa Ismail memset(cqp_info, 0, sizeof(*cqp_info)); 2087*915cc7acSMustafa Ismail cqp_info->cqp_cmd = cmd; 2088*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 2089*915cc7acSMustafa Ismail cqp_info->in.u.up_map.info = *map_info; 2090*915cc7acSMustafa Ismail cqp_info->in.u.up_map.cqp = cqp; 2091*915cc7acSMustafa Ismail cqp_info->in.u.up_map.scratch = (uintptr_t)cqp_request; 2092*915cc7acSMustafa Ismail 2093*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 2094*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 2095*915cc7acSMustafa Ismail 2096*915cc7acSMustafa Ismail return status; 2097*915cc7acSMustafa Ismail } 2098*915cc7acSMustafa Ismail 2099*915cc7acSMustafa Ismail /** 2100*915cc7acSMustafa Ismail * irdma_ah_cqp_op - perform an AH cqp operation 2101*915cc7acSMustafa Ismail * @rf: RDMA PCI function 2102*915cc7acSMustafa Ismail * @sc_ah: address handle 2103*915cc7acSMustafa Ismail * @cmd: AH operation 2104*915cc7acSMustafa Ismail * @wait: wait if true 2105*915cc7acSMustafa Ismail * @callback_fcn: Callback function on CQP op completion 2106*915cc7acSMustafa Ismail * @cb_param: parameter for callback function 2107*915cc7acSMustafa Ismail * 2108*915cc7acSMustafa Ismail * returns errno 2109*915cc7acSMustafa Ismail */ 2110*915cc7acSMustafa Ismail int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, 2111*915cc7acSMustafa Ismail bool wait, 2112*915cc7acSMustafa Ismail void (*callback_fcn)(struct irdma_cqp_request *), 2113*915cc7acSMustafa Ismail void *cb_param) 2114*915cc7acSMustafa Ismail { 2115*915cc7acSMustafa Ismail struct irdma_cqp_request *cqp_request; 2116*915cc7acSMustafa Ismail struct cqp_cmds_info *cqp_info; 2117*915cc7acSMustafa Ismail enum irdma_status_code status; 2118*915cc7acSMustafa Ismail 2119*915cc7acSMustafa Ismail if (cmd != IRDMA_OP_AH_CREATE && cmd != IRDMA_OP_AH_DESTROY) 2120*915cc7acSMustafa Ismail return -EINVAL; 2121*915cc7acSMustafa Ismail 2122*915cc7acSMustafa Ismail cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, wait); 2123*915cc7acSMustafa Ismail if (!cqp_request) 2124*915cc7acSMustafa Ismail return -ENOMEM; 2125*915cc7acSMustafa Ismail 2126*915cc7acSMustafa Ismail cqp_info = &cqp_request->info; 2127*915cc7acSMustafa Ismail cqp_info->cqp_cmd = cmd; 2128*915cc7acSMustafa Ismail cqp_info->post_sq = 1; 2129*915cc7acSMustafa Ismail if (cmd == IRDMA_OP_AH_CREATE) { 2130*915cc7acSMustafa Ismail cqp_info->in.u.ah_create.info = sc_ah->ah_info; 2131*915cc7acSMustafa Ismail cqp_info->in.u.ah_create.scratch = (uintptr_t)cqp_request; 2132*915cc7acSMustafa Ismail cqp_info->in.u.ah_create.cqp = &rf->cqp.sc_cqp; 2133*915cc7acSMustafa Ismail } else if (cmd == IRDMA_OP_AH_DESTROY) { 2134*915cc7acSMustafa Ismail cqp_info->in.u.ah_destroy.info = sc_ah->ah_info; 2135*915cc7acSMustafa Ismail cqp_info->in.u.ah_destroy.scratch = (uintptr_t)cqp_request; 2136*915cc7acSMustafa Ismail cqp_info->in.u.ah_destroy.cqp = &rf->cqp.sc_cqp; 2137*915cc7acSMustafa Ismail } 2138*915cc7acSMustafa Ismail 2139*915cc7acSMustafa Ismail if (!wait) { 2140*915cc7acSMustafa Ismail cqp_request->callback_fcn = callback_fcn; 2141*915cc7acSMustafa Ismail cqp_request->param = cb_param; 2142*915cc7acSMustafa Ismail } 2143*915cc7acSMustafa Ismail status = irdma_handle_cqp_op(rf, cqp_request); 2144*915cc7acSMustafa Ismail irdma_put_cqp_request(&rf->cqp, cqp_request); 2145*915cc7acSMustafa Ismail 2146*915cc7acSMustafa Ismail if (status) 2147*915cc7acSMustafa Ismail return -ENOMEM; 2148*915cc7acSMustafa Ismail 2149*915cc7acSMustafa Ismail if (wait) 2150*915cc7acSMustafa Ismail sc_ah->ah_info.ah_valid = (cmd == IRDMA_OP_AH_CREATE); 2151*915cc7acSMustafa Ismail 2152*915cc7acSMustafa Ismail return 0; 2153*915cc7acSMustafa Ismail } 2154*915cc7acSMustafa Ismail 2155*915cc7acSMustafa Ismail /** 2156*915cc7acSMustafa Ismail * irdma_ieq_ah_cb - callback after creation of AH for IEQ 2157*915cc7acSMustafa Ismail * @cqp_request: pointer to cqp_request of create AH 2158*915cc7acSMustafa Ismail */ 2159*915cc7acSMustafa Ismail static void irdma_ieq_ah_cb(struct irdma_cqp_request *cqp_request) 2160*915cc7acSMustafa Ismail { 2161*915cc7acSMustafa Ismail struct irdma_sc_qp *qp = cqp_request->param; 2162*915cc7acSMustafa Ismail struct irdma_sc_ah *sc_ah = qp->pfpdu.ah; 2163*915cc7acSMustafa Ismail unsigned long flags; 2164*915cc7acSMustafa Ismail 2165*915cc7acSMustafa Ismail spin_lock_irqsave(&qp->pfpdu.lock, flags); 2166*915cc7acSMustafa Ismail if (!cqp_request->compl_info.op_ret_val) { 2167*915cc7acSMustafa Ismail sc_ah->ah_info.ah_valid = true; 2168*915cc7acSMustafa Ismail irdma_ieq_process_fpdus(qp, qp->vsi->ieq); 2169*915cc7acSMustafa Ismail } else { 2170*915cc7acSMustafa Ismail sc_ah->ah_info.ah_valid = false; 2171*915cc7acSMustafa Ismail irdma_ieq_cleanup_qp(qp->vsi->ieq, qp); 2172*915cc7acSMustafa Ismail } 2173*915cc7acSMustafa Ismail spin_unlock_irqrestore(&qp->pfpdu.lock, flags); 2174*915cc7acSMustafa Ismail } 2175*915cc7acSMustafa Ismail 2176*915cc7acSMustafa Ismail /** 2177*915cc7acSMustafa Ismail * irdma_ilq_ah_cb - callback after creation of AH for ILQ 2178*915cc7acSMustafa Ismail * @cqp_request: pointer to cqp_request of create AH 2179*915cc7acSMustafa Ismail */ 2180*915cc7acSMustafa Ismail static void irdma_ilq_ah_cb(struct irdma_cqp_request *cqp_request) 2181*915cc7acSMustafa Ismail { 2182*915cc7acSMustafa Ismail struct irdma_cm_node *cm_node = cqp_request->param; 2183*915cc7acSMustafa Ismail struct irdma_sc_ah *sc_ah = cm_node->ah; 2184*915cc7acSMustafa Ismail 2185*915cc7acSMustafa Ismail sc_ah->ah_info.ah_valid = !cqp_request->compl_info.op_ret_val; 2186*915cc7acSMustafa Ismail irdma_add_conn_est_qh(cm_node); 2187*915cc7acSMustafa Ismail } 2188*915cc7acSMustafa Ismail 2189*915cc7acSMustafa Ismail /** 2190*915cc7acSMustafa Ismail * irdma_puda_create_ah - create AH for ILQ/IEQ qp's 2191*915cc7acSMustafa Ismail * @dev: device pointer 2192*915cc7acSMustafa Ismail * @ah_info: Address handle info 2193*915cc7acSMustafa Ismail * @wait: When true will wait for operation to complete 2194*915cc7acSMustafa Ismail * @type: ILQ/IEQ 2195*915cc7acSMustafa Ismail * @cb_param: Callback param when not waiting 2196*915cc7acSMustafa Ismail * @ah_ret: Returned pointer to address handle if created 2197*915cc7acSMustafa Ismail * 2198*915cc7acSMustafa Ismail */ 2199*915cc7acSMustafa Ismail enum irdma_status_code irdma_puda_create_ah(struct irdma_sc_dev *dev, 2200*915cc7acSMustafa Ismail struct irdma_ah_info *ah_info, 2201*915cc7acSMustafa Ismail bool wait, enum puda_rsrc_type type, 2202*915cc7acSMustafa Ismail void *cb_param, 2203*915cc7acSMustafa Ismail struct irdma_sc_ah **ah_ret) 2204*915cc7acSMustafa Ismail { 2205*915cc7acSMustafa Ismail struct irdma_sc_ah *ah; 2206*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 2207*915cc7acSMustafa Ismail int err; 2208*915cc7acSMustafa Ismail 2209*915cc7acSMustafa Ismail ah = kzalloc(sizeof(*ah), GFP_ATOMIC); 2210*915cc7acSMustafa Ismail *ah_ret = ah; 2211*915cc7acSMustafa Ismail if (!ah) 2212*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2213*915cc7acSMustafa Ismail 2214*915cc7acSMustafa Ismail err = irdma_alloc_rsrc(rf, rf->allocated_ahs, rf->max_ah, 2215*915cc7acSMustafa Ismail &ah_info->ah_idx, &rf->next_ah); 2216*915cc7acSMustafa Ismail if (err) 2217*915cc7acSMustafa Ismail goto err_free; 2218*915cc7acSMustafa Ismail 2219*915cc7acSMustafa Ismail ah->dev = dev; 2220*915cc7acSMustafa Ismail ah->ah_info = *ah_info; 2221*915cc7acSMustafa Ismail 2222*915cc7acSMustafa Ismail if (type == IRDMA_PUDA_RSRC_TYPE_ILQ) 2223*915cc7acSMustafa Ismail err = irdma_ah_cqp_op(rf, ah, IRDMA_OP_AH_CREATE, wait, 2224*915cc7acSMustafa Ismail irdma_ilq_ah_cb, cb_param); 2225*915cc7acSMustafa Ismail else 2226*915cc7acSMustafa Ismail err = irdma_ah_cqp_op(rf, ah, IRDMA_OP_AH_CREATE, wait, 2227*915cc7acSMustafa Ismail irdma_ieq_ah_cb, cb_param); 2228*915cc7acSMustafa Ismail 2229*915cc7acSMustafa Ismail if (err) 2230*915cc7acSMustafa Ismail goto error; 2231*915cc7acSMustafa Ismail return 0; 2232*915cc7acSMustafa Ismail 2233*915cc7acSMustafa Ismail error: 2234*915cc7acSMustafa Ismail irdma_free_rsrc(rf, rf->allocated_ahs, ah->ah_info.ah_idx); 2235*915cc7acSMustafa Ismail err_free: 2236*915cc7acSMustafa Ismail kfree(ah); 2237*915cc7acSMustafa Ismail *ah_ret = NULL; 2238*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2239*915cc7acSMustafa Ismail } 2240*915cc7acSMustafa Ismail 2241*915cc7acSMustafa Ismail /** 2242*915cc7acSMustafa Ismail * irdma_puda_free_ah - free a puda address handle 2243*915cc7acSMustafa Ismail * @dev: device pointer 2244*915cc7acSMustafa Ismail * @ah: The address handle to free 2245*915cc7acSMustafa Ismail */ 2246*915cc7acSMustafa Ismail void irdma_puda_free_ah(struct irdma_sc_dev *dev, struct irdma_sc_ah *ah) 2247*915cc7acSMustafa Ismail { 2248*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 2249*915cc7acSMustafa Ismail 2250*915cc7acSMustafa Ismail if (!ah) 2251*915cc7acSMustafa Ismail return; 2252*915cc7acSMustafa Ismail 2253*915cc7acSMustafa Ismail if (ah->ah_info.ah_valid) { 2254*915cc7acSMustafa Ismail irdma_ah_cqp_op(rf, ah, IRDMA_OP_AH_DESTROY, false, NULL, NULL); 2255*915cc7acSMustafa Ismail irdma_free_rsrc(rf, rf->allocated_ahs, ah->ah_info.ah_idx); 2256*915cc7acSMustafa Ismail } 2257*915cc7acSMustafa Ismail 2258*915cc7acSMustafa Ismail kfree(ah); 2259*915cc7acSMustafa Ismail } 2260*915cc7acSMustafa Ismail 2261*915cc7acSMustafa Ismail /** 2262*915cc7acSMustafa Ismail * irdma_gsi_ud_qp_ah_cb - callback after creation of AH for GSI/ID QP 2263*915cc7acSMustafa Ismail * @cqp_request: pointer to cqp_request of create AH 2264*915cc7acSMustafa Ismail */ 2265*915cc7acSMustafa Ismail void irdma_gsi_ud_qp_ah_cb(struct irdma_cqp_request *cqp_request) 2266*915cc7acSMustafa Ismail { 2267*915cc7acSMustafa Ismail struct irdma_sc_ah *sc_ah = cqp_request->param; 2268*915cc7acSMustafa Ismail 2269*915cc7acSMustafa Ismail if (!cqp_request->compl_info.op_ret_val) 2270*915cc7acSMustafa Ismail sc_ah->ah_info.ah_valid = true; 2271*915cc7acSMustafa Ismail else 2272*915cc7acSMustafa Ismail sc_ah->ah_info.ah_valid = false; 2273*915cc7acSMustafa Ismail } 2274*915cc7acSMustafa Ismail 2275*915cc7acSMustafa Ismail /** 2276*915cc7acSMustafa Ismail * irdma_prm_add_pble_mem - add moemory to pble resources 2277*915cc7acSMustafa Ismail * @pprm: pble resource manager 2278*915cc7acSMustafa Ismail * @pchunk: chunk of memory to add 2279*915cc7acSMustafa Ismail */ 2280*915cc7acSMustafa Ismail enum irdma_status_code irdma_prm_add_pble_mem(struct irdma_pble_prm *pprm, 2281*915cc7acSMustafa Ismail struct irdma_chunk *pchunk) 2282*915cc7acSMustafa Ismail { 2283*915cc7acSMustafa Ismail u64 sizeofbitmap; 2284*915cc7acSMustafa Ismail 2285*915cc7acSMustafa Ismail if (pchunk->size & 0xfff) 2286*915cc7acSMustafa Ismail return IRDMA_ERR_PARAM; 2287*915cc7acSMustafa Ismail 2288*915cc7acSMustafa Ismail sizeofbitmap = (u64)pchunk->size >> pprm->pble_shift; 2289*915cc7acSMustafa Ismail 2290*915cc7acSMustafa Ismail pchunk->bitmapmem.size = sizeofbitmap >> 3; 2291*915cc7acSMustafa Ismail pchunk->bitmapmem.va = kzalloc(pchunk->bitmapmem.size, GFP_KERNEL); 2292*915cc7acSMustafa Ismail 2293*915cc7acSMustafa Ismail if (!pchunk->bitmapmem.va) 2294*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2295*915cc7acSMustafa Ismail 2296*915cc7acSMustafa Ismail pchunk->bitmapbuf = pchunk->bitmapmem.va; 2297*915cc7acSMustafa Ismail bitmap_zero(pchunk->bitmapbuf, sizeofbitmap); 2298*915cc7acSMustafa Ismail 2299*915cc7acSMustafa Ismail pchunk->sizeofbitmap = sizeofbitmap; 2300*915cc7acSMustafa Ismail /* each pble is 8 bytes hence shift by 3 */ 2301*915cc7acSMustafa Ismail pprm->total_pble_alloc += pchunk->size >> 3; 2302*915cc7acSMustafa Ismail pprm->free_pble_cnt += pchunk->size >> 3; 2303*915cc7acSMustafa Ismail 2304*915cc7acSMustafa Ismail return 0; 2305*915cc7acSMustafa Ismail } 2306*915cc7acSMustafa Ismail 2307*915cc7acSMustafa Ismail /** 2308*915cc7acSMustafa Ismail * irdma_prm_get_pbles - get pble's from prm 2309*915cc7acSMustafa Ismail * @pprm: pble resource manager 2310*915cc7acSMustafa Ismail * @chunkinfo: nformation about chunk where pble's were acquired 2311*915cc7acSMustafa Ismail * @mem_size: size of pble memory needed 2312*915cc7acSMustafa Ismail * @vaddr: returns virtual address of pble memory 2313*915cc7acSMustafa Ismail * @fpm_addr: returns fpm address of pble memory 2314*915cc7acSMustafa Ismail */ 2315*915cc7acSMustafa Ismail enum irdma_status_code 2316*915cc7acSMustafa Ismail irdma_prm_get_pbles(struct irdma_pble_prm *pprm, 2317*915cc7acSMustafa Ismail struct irdma_pble_chunkinfo *chunkinfo, u32 mem_size, 2318*915cc7acSMustafa Ismail u64 *vaddr, u64 *fpm_addr) 2319*915cc7acSMustafa Ismail { 2320*915cc7acSMustafa Ismail u64 bits_needed; 2321*915cc7acSMustafa Ismail u64 bit_idx = PBLE_INVALID_IDX; 2322*915cc7acSMustafa Ismail struct irdma_chunk *pchunk = NULL; 2323*915cc7acSMustafa Ismail struct list_head *chunk_entry = pprm->clist.next; 2324*915cc7acSMustafa Ismail u32 offset; 2325*915cc7acSMustafa Ismail unsigned long flags; 2326*915cc7acSMustafa Ismail *vaddr = 0; 2327*915cc7acSMustafa Ismail *fpm_addr = 0; 2328*915cc7acSMustafa Ismail 2329*915cc7acSMustafa Ismail bits_needed = (mem_size + (1 << pprm->pble_shift) - 1) >> pprm->pble_shift; 2330*915cc7acSMustafa Ismail 2331*915cc7acSMustafa Ismail spin_lock_irqsave(&pprm->prm_lock, flags); 2332*915cc7acSMustafa Ismail while (chunk_entry != &pprm->clist) { 2333*915cc7acSMustafa Ismail pchunk = (struct irdma_chunk *)chunk_entry; 2334*915cc7acSMustafa Ismail bit_idx = bitmap_find_next_zero_area(pchunk->bitmapbuf, 2335*915cc7acSMustafa Ismail pchunk->sizeofbitmap, 0, 2336*915cc7acSMustafa Ismail bits_needed, 0); 2337*915cc7acSMustafa Ismail if (bit_idx < pchunk->sizeofbitmap) 2338*915cc7acSMustafa Ismail break; 2339*915cc7acSMustafa Ismail 2340*915cc7acSMustafa Ismail /* list.next used macro */ 2341*915cc7acSMustafa Ismail chunk_entry = pchunk->list.next; 2342*915cc7acSMustafa Ismail } 2343*915cc7acSMustafa Ismail 2344*915cc7acSMustafa Ismail if (!pchunk || bit_idx >= pchunk->sizeofbitmap) { 2345*915cc7acSMustafa Ismail spin_unlock_irqrestore(&pprm->prm_lock, flags); 2346*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2347*915cc7acSMustafa Ismail } 2348*915cc7acSMustafa Ismail 2349*915cc7acSMustafa Ismail bitmap_set(pchunk->bitmapbuf, bit_idx, bits_needed); 2350*915cc7acSMustafa Ismail offset = bit_idx << pprm->pble_shift; 2351*915cc7acSMustafa Ismail *vaddr = pchunk->vaddr + offset; 2352*915cc7acSMustafa Ismail *fpm_addr = pchunk->fpm_addr + offset; 2353*915cc7acSMustafa Ismail 2354*915cc7acSMustafa Ismail chunkinfo->pchunk = pchunk; 2355*915cc7acSMustafa Ismail chunkinfo->bit_idx = bit_idx; 2356*915cc7acSMustafa Ismail chunkinfo->bits_used = bits_needed; 2357*915cc7acSMustafa Ismail /* 3 is sizeof pble divide */ 2358*915cc7acSMustafa Ismail pprm->free_pble_cnt -= chunkinfo->bits_used << (pprm->pble_shift - 3); 2359*915cc7acSMustafa Ismail spin_unlock_irqrestore(&pprm->prm_lock, flags); 2360*915cc7acSMustafa Ismail 2361*915cc7acSMustafa Ismail return 0; 2362*915cc7acSMustafa Ismail } 2363*915cc7acSMustafa Ismail 2364*915cc7acSMustafa Ismail /** 2365*915cc7acSMustafa Ismail * irdma_prm_return_pbles - return pbles back to prm 2366*915cc7acSMustafa Ismail * @pprm: pble resource manager 2367*915cc7acSMustafa Ismail * @chunkinfo: chunk where pble's were acquired and to be freed 2368*915cc7acSMustafa Ismail */ 2369*915cc7acSMustafa Ismail void irdma_prm_return_pbles(struct irdma_pble_prm *pprm, 2370*915cc7acSMustafa Ismail struct irdma_pble_chunkinfo *chunkinfo) 2371*915cc7acSMustafa Ismail { 2372*915cc7acSMustafa Ismail unsigned long flags; 2373*915cc7acSMustafa Ismail 2374*915cc7acSMustafa Ismail spin_lock_irqsave(&pprm->prm_lock, flags); 2375*915cc7acSMustafa Ismail pprm->free_pble_cnt += chunkinfo->bits_used << (pprm->pble_shift - 3); 2376*915cc7acSMustafa Ismail bitmap_clear(chunkinfo->pchunk->bitmapbuf, chunkinfo->bit_idx, 2377*915cc7acSMustafa Ismail chunkinfo->bits_used); 2378*915cc7acSMustafa Ismail spin_unlock_irqrestore(&pprm->prm_lock, flags); 2379*915cc7acSMustafa Ismail } 2380*915cc7acSMustafa Ismail 2381*915cc7acSMustafa Ismail enum irdma_status_code irdma_map_vm_page_list(struct irdma_hw *hw, void *va, 2382*915cc7acSMustafa Ismail dma_addr_t *pg_dma, u32 pg_cnt) 2383*915cc7acSMustafa Ismail { 2384*915cc7acSMustafa Ismail struct page *vm_page; 2385*915cc7acSMustafa Ismail int i; 2386*915cc7acSMustafa Ismail u8 *addr; 2387*915cc7acSMustafa Ismail 2388*915cc7acSMustafa Ismail addr = (u8 *)(uintptr_t)va; 2389*915cc7acSMustafa Ismail for (i = 0; i < pg_cnt; i++) { 2390*915cc7acSMustafa Ismail vm_page = vmalloc_to_page(addr); 2391*915cc7acSMustafa Ismail if (!vm_page) 2392*915cc7acSMustafa Ismail goto err; 2393*915cc7acSMustafa Ismail 2394*915cc7acSMustafa Ismail pg_dma[i] = dma_map_page(hw->device, vm_page, 0, PAGE_SIZE, 2395*915cc7acSMustafa Ismail DMA_BIDIRECTIONAL); 2396*915cc7acSMustafa Ismail if (dma_mapping_error(hw->device, pg_dma[i])) 2397*915cc7acSMustafa Ismail goto err; 2398*915cc7acSMustafa Ismail 2399*915cc7acSMustafa Ismail addr += PAGE_SIZE; 2400*915cc7acSMustafa Ismail } 2401*915cc7acSMustafa Ismail 2402*915cc7acSMustafa Ismail return 0; 2403*915cc7acSMustafa Ismail 2404*915cc7acSMustafa Ismail err: 2405*915cc7acSMustafa Ismail irdma_unmap_vm_page_list(hw, pg_dma, i); 2406*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2407*915cc7acSMustafa Ismail } 2408*915cc7acSMustafa Ismail 2409*915cc7acSMustafa Ismail void irdma_unmap_vm_page_list(struct irdma_hw *hw, dma_addr_t *pg_dma, u32 pg_cnt) 2410*915cc7acSMustafa Ismail { 2411*915cc7acSMustafa Ismail int i; 2412*915cc7acSMustafa Ismail 2413*915cc7acSMustafa Ismail for (i = 0; i < pg_cnt; i++) 2414*915cc7acSMustafa Ismail dma_unmap_page(hw->device, pg_dma[i], PAGE_SIZE, DMA_BIDIRECTIONAL); 2415*915cc7acSMustafa Ismail } 2416*915cc7acSMustafa Ismail 2417*915cc7acSMustafa Ismail /** 2418*915cc7acSMustafa Ismail * irdma_pble_free_paged_mem - free virtual paged memory 2419*915cc7acSMustafa Ismail * @chunk: chunk to free with paged memory 2420*915cc7acSMustafa Ismail */ 2421*915cc7acSMustafa Ismail void irdma_pble_free_paged_mem(struct irdma_chunk *chunk) 2422*915cc7acSMustafa Ismail { 2423*915cc7acSMustafa Ismail if (!chunk->pg_cnt) 2424*915cc7acSMustafa Ismail goto done; 2425*915cc7acSMustafa Ismail 2426*915cc7acSMustafa Ismail irdma_unmap_vm_page_list(chunk->dev->hw, chunk->dmainfo.dmaaddrs, 2427*915cc7acSMustafa Ismail chunk->pg_cnt); 2428*915cc7acSMustafa Ismail 2429*915cc7acSMustafa Ismail done: 2430*915cc7acSMustafa Ismail kfree(chunk->dmainfo.dmaaddrs); 2431*915cc7acSMustafa Ismail chunk->dmainfo.dmaaddrs = NULL; 2432*915cc7acSMustafa Ismail vfree((void *)(uintptr_t)chunk->vaddr); 2433*915cc7acSMustafa Ismail chunk->vaddr = 0; 2434*915cc7acSMustafa Ismail chunk->type = 0; 2435*915cc7acSMustafa Ismail } 2436*915cc7acSMustafa Ismail 2437*915cc7acSMustafa Ismail /** 2438*915cc7acSMustafa Ismail * irdma_pble_get_paged_mem -allocate paged memory for pbles 2439*915cc7acSMustafa Ismail * @chunk: chunk to add for paged memory 2440*915cc7acSMustafa Ismail * @pg_cnt: number of pages needed 2441*915cc7acSMustafa Ismail */ 2442*915cc7acSMustafa Ismail enum irdma_status_code irdma_pble_get_paged_mem(struct irdma_chunk *chunk, 2443*915cc7acSMustafa Ismail u32 pg_cnt) 2444*915cc7acSMustafa Ismail { 2445*915cc7acSMustafa Ismail u32 size; 2446*915cc7acSMustafa Ismail void *va; 2447*915cc7acSMustafa Ismail 2448*915cc7acSMustafa Ismail chunk->dmainfo.dmaaddrs = kzalloc(pg_cnt << 3, GFP_KERNEL); 2449*915cc7acSMustafa Ismail if (!chunk->dmainfo.dmaaddrs) 2450*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2451*915cc7acSMustafa Ismail 2452*915cc7acSMustafa Ismail size = PAGE_SIZE * pg_cnt; 2453*915cc7acSMustafa Ismail va = vmalloc(size); 2454*915cc7acSMustafa Ismail if (!va) 2455*915cc7acSMustafa Ismail goto err; 2456*915cc7acSMustafa Ismail 2457*915cc7acSMustafa Ismail if (irdma_map_vm_page_list(chunk->dev->hw, va, chunk->dmainfo.dmaaddrs, 2458*915cc7acSMustafa Ismail pg_cnt)) { 2459*915cc7acSMustafa Ismail vfree(va); 2460*915cc7acSMustafa Ismail goto err; 2461*915cc7acSMustafa Ismail } 2462*915cc7acSMustafa Ismail chunk->vaddr = (uintptr_t)va; 2463*915cc7acSMustafa Ismail chunk->size = size; 2464*915cc7acSMustafa Ismail chunk->pg_cnt = pg_cnt; 2465*915cc7acSMustafa Ismail chunk->type = PBLE_SD_PAGED; 2466*915cc7acSMustafa Ismail 2467*915cc7acSMustafa Ismail return 0; 2468*915cc7acSMustafa Ismail err: 2469*915cc7acSMustafa Ismail kfree(chunk->dmainfo.dmaaddrs); 2470*915cc7acSMustafa Ismail chunk->dmainfo.dmaaddrs = NULL; 2471*915cc7acSMustafa Ismail 2472*915cc7acSMustafa Ismail return IRDMA_ERR_NO_MEMORY; 2473*915cc7acSMustafa Ismail } 2474*915cc7acSMustafa Ismail 2475*915cc7acSMustafa Ismail /** 2476*915cc7acSMustafa Ismail * irdma_alloc_ws_node_id - Allocate a tx scheduler node ID 2477*915cc7acSMustafa Ismail * @dev: device pointer 2478*915cc7acSMustafa Ismail */ 2479*915cc7acSMustafa Ismail u16 irdma_alloc_ws_node_id(struct irdma_sc_dev *dev) 2480*915cc7acSMustafa Ismail { 2481*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 2482*915cc7acSMustafa Ismail u32 next = 1; 2483*915cc7acSMustafa Ismail u32 node_id; 2484*915cc7acSMustafa Ismail 2485*915cc7acSMustafa Ismail if (irdma_alloc_rsrc(rf, rf->allocated_ws_nodes, rf->max_ws_node_id, 2486*915cc7acSMustafa Ismail &node_id, &next)) 2487*915cc7acSMustafa Ismail return IRDMA_WS_NODE_INVALID; 2488*915cc7acSMustafa Ismail 2489*915cc7acSMustafa Ismail return (u16)node_id; 2490*915cc7acSMustafa Ismail } 2491*915cc7acSMustafa Ismail 2492*915cc7acSMustafa Ismail /** 2493*915cc7acSMustafa Ismail * irdma_free_ws_node_id - Free a tx scheduler node ID 2494*915cc7acSMustafa Ismail * @dev: device pointer 2495*915cc7acSMustafa Ismail * @node_id: Work scheduler node ID 2496*915cc7acSMustafa Ismail */ 2497*915cc7acSMustafa Ismail void irdma_free_ws_node_id(struct irdma_sc_dev *dev, u16 node_id) 2498*915cc7acSMustafa Ismail { 2499*915cc7acSMustafa Ismail struct irdma_pci_f *rf = dev_to_rf(dev); 2500*915cc7acSMustafa Ismail 2501*915cc7acSMustafa Ismail irdma_free_rsrc(rf, rf->allocated_ws_nodes, (u32)node_id); 2502*915cc7acSMustafa Ismail } 2503*915cc7acSMustafa Ismail 2504*915cc7acSMustafa Ismail /** 2505*915cc7acSMustafa Ismail * irdma_modify_qp_to_err - Modify a QP to error 2506*915cc7acSMustafa Ismail * @sc_qp: qp structure 2507*915cc7acSMustafa Ismail */ 2508*915cc7acSMustafa Ismail void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp) 2509*915cc7acSMustafa Ismail { 2510*915cc7acSMustafa Ismail struct irdma_qp *qp = sc_qp->qp_uk.back_qp; 2511*915cc7acSMustafa Ismail struct ib_qp_attr attr; 2512*915cc7acSMustafa Ismail 2513*915cc7acSMustafa Ismail if (qp->iwdev->reset) 2514*915cc7acSMustafa Ismail return; 2515*915cc7acSMustafa Ismail attr.qp_state = IB_QPS_ERR; 2516*915cc7acSMustafa Ismail 2517*915cc7acSMustafa Ismail if (rdma_protocol_roce(qp->ibqp.device, 1)) 2518*915cc7acSMustafa Ismail irdma_modify_qp_roce(&qp->ibqp, &attr, IB_QP_STATE, NULL); 2519*915cc7acSMustafa Ismail else 2520*915cc7acSMustafa Ismail irdma_modify_qp(&qp->ibqp, &attr, IB_QP_STATE, NULL); 2521*915cc7acSMustafa Ismail } 2522*915cc7acSMustafa Ismail 2523*915cc7acSMustafa Ismail void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event) 2524*915cc7acSMustafa Ismail { 2525*915cc7acSMustafa Ismail struct ib_event ibevent; 2526*915cc7acSMustafa Ismail 2527*915cc7acSMustafa Ismail if (!iwqp->ibqp.event_handler) 2528*915cc7acSMustafa Ismail return; 2529*915cc7acSMustafa Ismail 2530*915cc7acSMustafa Ismail switch (event) { 2531*915cc7acSMustafa Ismail case IRDMA_QP_EVENT_CATASTROPHIC: 2532*915cc7acSMustafa Ismail ibevent.event = IB_EVENT_QP_FATAL; 2533*915cc7acSMustafa Ismail break; 2534*915cc7acSMustafa Ismail case IRDMA_QP_EVENT_ACCESS_ERR: 2535*915cc7acSMustafa Ismail ibevent.event = IB_EVENT_QP_ACCESS_ERR; 2536*915cc7acSMustafa Ismail break; 2537*915cc7acSMustafa Ismail } 2538*915cc7acSMustafa Ismail ibevent.device = iwqp->ibqp.device; 2539*915cc7acSMustafa Ismail ibevent.element.qp = &iwqp->ibqp; 2540*915cc7acSMustafa Ismail iwqp->ibqp.event_handler(&ibevent, iwqp->ibqp.qp_context); 2541*915cc7acSMustafa Ismail } 2542