1*e3cf00d0SUpinder Malhi /* 2*e3cf00d0SUpinder Malhi * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved. 3*e3cf00d0SUpinder Malhi * 4*e3cf00d0SUpinder Malhi * This program is free software; you may redistribute it and/or modify 5*e3cf00d0SUpinder Malhi * it under the terms of the GNU General Public License as published by 6*e3cf00d0SUpinder Malhi * the Free Software Foundation; version 2 of the License. 7*e3cf00d0SUpinder Malhi * 8*e3cf00d0SUpinder Malhi * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 9*e3cf00d0SUpinder Malhi * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 10*e3cf00d0SUpinder Malhi * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 11*e3cf00d0SUpinder Malhi * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 12*e3cf00d0SUpinder Malhi * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 13*e3cf00d0SUpinder Malhi * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14*e3cf00d0SUpinder Malhi * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 15*e3cf00d0SUpinder Malhi * SOFTWARE. 16*e3cf00d0SUpinder Malhi * 17*e3cf00d0SUpinder Malhi */ 18*e3cf00d0SUpinder Malhi #include <linux/netdevice.h> 19*e3cf00d0SUpinder Malhi #include <linux/pci.h> 20*e3cf00d0SUpinder Malhi 21*e3cf00d0SUpinder Malhi #include "enic_api.h" 22*e3cf00d0SUpinder Malhi #include "usnic_common_pkt_hdr.h" 23*e3cf00d0SUpinder Malhi #include "usnic_fwd.h" 24*e3cf00d0SUpinder Malhi #include "usnic_log.h" 25*e3cf00d0SUpinder Malhi 26*e3cf00d0SUpinder Malhi struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev) 27*e3cf00d0SUpinder Malhi { 28*e3cf00d0SUpinder Malhi struct usnic_fwd_dev *ufdev; 29*e3cf00d0SUpinder Malhi 30*e3cf00d0SUpinder Malhi ufdev = kzalloc(sizeof(*ufdev), GFP_KERNEL); 31*e3cf00d0SUpinder Malhi if (!ufdev) 32*e3cf00d0SUpinder Malhi return NULL; 33*e3cf00d0SUpinder Malhi 34*e3cf00d0SUpinder Malhi ufdev->pdev = pdev; 35*e3cf00d0SUpinder Malhi ufdev->netdev = pci_get_drvdata(pdev); 36*e3cf00d0SUpinder Malhi spin_lock_init(&ufdev->lock); 37*e3cf00d0SUpinder Malhi 38*e3cf00d0SUpinder Malhi return ufdev; 39*e3cf00d0SUpinder Malhi } 40*e3cf00d0SUpinder Malhi 41*e3cf00d0SUpinder Malhi void usnic_fwd_dev_free(struct usnic_fwd_dev *ufdev) 42*e3cf00d0SUpinder Malhi { 43*e3cf00d0SUpinder Malhi kfree(ufdev); 44*e3cf00d0SUpinder Malhi } 45*e3cf00d0SUpinder Malhi 46*e3cf00d0SUpinder Malhi static int usnic_fwd_devcmd(struct usnic_fwd_dev *ufdev, int vnic_idx, 47*e3cf00d0SUpinder Malhi enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1) 48*e3cf00d0SUpinder Malhi { 49*e3cf00d0SUpinder Malhi int status; 50*e3cf00d0SUpinder Malhi struct net_device *netdev = ufdev->netdev; 51*e3cf00d0SUpinder Malhi 52*e3cf00d0SUpinder Malhi spin_lock(&ufdev->lock); 53*e3cf00d0SUpinder Malhi status = enic_api_devcmd_proxy_by_index(netdev, 54*e3cf00d0SUpinder Malhi vnic_idx, 55*e3cf00d0SUpinder Malhi cmd, 56*e3cf00d0SUpinder Malhi a0, a1, 57*e3cf00d0SUpinder Malhi 1000); 58*e3cf00d0SUpinder Malhi spin_unlock(&ufdev->lock); 59*e3cf00d0SUpinder Malhi if (status) { 60*e3cf00d0SUpinder Malhi if (status == ERR_EINVAL && cmd == CMD_DEL_FILTER) { 61*e3cf00d0SUpinder Malhi usnic_dbg("Dev %s vnic idx %u cmd %u already deleted", 62*e3cf00d0SUpinder Malhi netdev_name(netdev), vnic_idx, cmd); 63*e3cf00d0SUpinder Malhi } else { 64*e3cf00d0SUpinder Malhi usnic_err("Dev %s vnic idx %u cmd %u failed with status %d\n", 65*e3cf00d0SUpinder Malhi netdev_name(netdev), vnic_idx, cmd, 66*e3cf00d0SUpinder Malhi status); 67*e3cf00d0SUpinder Malhi } 68*e3cf00d0SUpinder Malhi } else { 69*e3cf00d0SUpinder Malhi usnic_dbg("Dev %s vnic idx %u cmd %u success", 70*e3cf00d0SUpinder Malhi netdev_name(netdev), vnic_idx, 71*e3cf00d0SUpinder Malhi cmd); 72*e3cf00d0SUpinder Malhi } 73*e3cf00d0SUpinder Malhi 74*e3cf00d0SUpinder Malhi return status; 75*e3cf00d0SUpinder Malhi } 76*e3cf00d0SUpinder Malhi 77*e3cf00d0SUpinder Malhi int usnic_fwd_add_usnic_filter(struct usnic_fwd_dev *ufdev, int vnic_idx, 78*e3cf00d0SUpinder Malhi int rq_idx, struct usnic_fwd_filter *fwd_filter, 79*e3cf00d0SUpinder Malhi struct usnic_fwd_filter_hndl **filter_hndl) 80*e3cf00d0SUpinder Malhi { 81*e3cf00d0SUpinder Malhi struct filter_tlv *tlv, *tlv_va; 82*e3cf00d0SUpinder Malhi struct filter *filter; 83*e3cf00d0SUpinder Malhi struct filter_action *action; 84*e3cf00d0SUpinder Malhi struct pci_dev *pdev; 85*e3cf00d0SUpinder Malhi struct usnic_fwd_filter_hndl *usnic_filter_hndl; 86*e3cf00d0SUpinder Malhi int status; 87*e3cf00d0SUpinder Malhi u64 a0, a1; 88*e3cf00d0SUpinder Malhi u64 tlv_size; 89*e3cf00d0SUpinder Malhi dma_addr_t tlv_pa; 90*e3cf00d0SUpinder Malhi 91*e3cf00d0SUpinder Malhi pdev = ufdev->pdev; 92*e3cf00d0SUpinder Malhi tlv_size = (2*sizeof(struct filter_tlv) + 93*e3cf00d0SUpinder Malhi sizeof(struct filter) + 94*e3cf00d0SUpinder Malhi sizeof(struct filter_action)); 95*e3cf00d0SUpinder Malhi tlv = pci_alloc_consistent(pdev, tlv_size, &tlv_pa); 96*e3cf00d0SUpinder Malhi if (!tlv) { 97*e3cf00d0SUpinder Malhi usnic_err("Failed to allocate memory\n"); 98*e3cf00d0SUpinder Malhi return -ENOMEM; 99*e3cf00d0SUpinder Malhi } 100*e3cf00d0SUpinder Malhi 101*e3cf00d0SUpinder Malhi usnic_filter_hndl = kzalloc(sizeof(*usnic_filter_hndl), GFP_ATOMIC); 102*e3cf00d0SUpinder Malhi if (!usnic_filter_hndl) { 103*e3cf00d0SUpinder Malhi usnic_err("Failed to allocate memory for hndl\n"); 104*e3cf00d0SUpinder Malhi pci_free_consistent(pdev, tlv_size, tlv, tlv_pa); 105*e3cf00d0SUpinder Malhi return -ENOMEM; 106*e3cf00d0SUpinder Malhi } 107*e3cf00d0SUpinder Malhi 108*e3cf00d0SUpinder Malhi tlv_va = tlv; 109*e3cf00d0SUpinder Malhi a0 = tlv_pa; 110*e3cf00d0SUpinder Malhi a1 = tlv_size; 111*e3cf00d0SUpinder Malhi memset(tlv, 0, tlv_size); 112*e3cf00d0SUpinder Malhi tlv->type = CLSF_TLV_FILTER; 113*e3cf00d0SUpinder Malhi tlv->length = sizeof(struct filter); 114*e3cf00d0SUpinder Malhi filter = (struct filter *)&tlv->val; 115*e3cf00d0SUpinder Malhi filter->type = FILTER_USNIC_ID; 116*e3cf00d0SUpinder Malhi filter->u.usnic.ethtype = USNIC_ROCE_ETHERTYPE; 117*e3cf00d0SUpinder Malhi filter->u.usnic.flags = FILTER_FIELD_USNIC_ETHTYPE | 118*e3cf00d0SUpinder Malhi FILTER_FIELD_USNIC_ID | 119*e3cf00d0SUpinder Malhi FILTER_FIELD_USNIC_PROTO; 120*e3cf00d0SUpinder Malhi filter->u.usnic.proto_version = (USNIC_ROCE_GRH_VER << 121*e3cf00d0SUpinder Malhi USNIC_ROCE_GRH_VER_SHIFT) 122*e3cf00d0SUpinder Malhi | USNIC_PROTO_VER; 123*e3cf00d0SUpinder Malhi filter->u.usnic.usnic_id = fwd_filter->port_num; 124*e3cf00d0SUpinder Malhi tlv = (struct filter_tlv *)((char *)tlv + sizeof(struct filter_tlv) + 125*e3cf00d0SUpinder Malhi sizeof(struct filter)); 126*e3cf00d0SUpinder Malhi tlv->type = CLSF_TLV_ACTION; 127*e3cf00d0SUpinder Malhi tlv->length = sizeof(struct filter_action); 128*e3cf00d0SUpinder Malhi action = (struct filter_action *)&tlv->val; 129*e3cf00d0SUpinder Malhi action->type = FILTER_ACTION_RQ_STEERING; 130*e3cf00d0SUpinder Malhi action->u.rq_idx = rq_idx; 131*e3cf00d0SUpinder Malhi 132*e3cf00d0SUpinder Malhi status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_ADD_FILTER, &a0, &a1); 133*e3cf00d0SUpinder Malhi pci_free_consistent(pdev, tlv_size, tlv_va, tlv_pa); 134*e3cf00d0SUpinder Malhi if (status) { 135*e3cf00d0SUpinder Malhi usnic_err("VF %s Filter add failed with status:%d", 136*e3cf00d0SUpinder Malhi pci_name(pdev), 137*e3cf00d0SUpinder Malhi status); 138*e3cf00d0SUpinder Malhi kfree(usnic_filter_hndl); 139*e3cf00d0SUpinder Malhi return status; 140*e3cf00d0SUpinder Malhi } else { 141*e3cf00d0SUpinder Malhi usnic_dbg("VF %s FILTER ID:%u", 142*e3cf00d0SUpinder Malhi pci_name(pdev), 143*e3cf00d0SUpinder Malhi (u32)a0); 144*e3cf00d0SUpinder Malhi } 145*e3cf00d0SUpinder Malhi 146*e3cf00d0SUpinder Malhi usnic_filter_hndl->type = FILTER_USNIC_ID; 147*e3cf00d0SUpinder Malhi usnic_filter_hndl->id = (u32)a0; 148*e3cf00d0SUpinder Malhi usnic_filter_hndl->vnic_idx = vnic_idx; 149*e3cf00d0SUpinder Malhi usnic_filter_hndl->ufdev = ufdev; 150*e3cf00d0SUpinder Malhi usnic_filter_hndl->filter = fwd_filter; 151*e3cf00d0SUpinder Malhi *filter_hndl = usnic_filter_hndl; 152*e3cf00d0SUpinder Malhi 153*e3cf00d0SUpinder Malhi return status; 154*e3cf00d0SUpinder Malhi } 155*e3cf00d0SUpinder Malhi 156*e3cf00d0SUpinder Malhi int usnic_fwd_del_filter(struct usnic_fwd_filter_hndl *filter_hndl) 157*e3cf00d0SUpinder Malhi { 158*e3cf00d0SUpinder Malhi int status; 159*e3cf00d0SUpinder Malhi u64 a0, a1; 160*e3cf00d0SUpinder Malhi struct net_device *netdev; 161*e3cf00d0SUpinder Malhi 162*e3cf00d0SUpinder Malhi netdev = filter_hndl->ufdev->netdev; 163*e3cf00d0SUpinder Malhi a0 = filter_hndl->id; 164*e3cf00d0SUpinder Malhi 165*e3cf00d0SUpinder Malhi status = usnic_fwd_devcmd(filter_hndl->ufdev, filter_hndl->vnic_idx, 166*e3cf00d0SUpinder Malhi CMD_DEL_FILTER, &a0, &a1); 167*e3cf00d0SUpinder Malhi if (status) { 168*e3cf00d0SUpinder Malhi if (status == ERR_EINVAL) { 169*e3cf00d0SUpinder Malhi usnic_dbg("Filter %u already deleted for VF Idx %u pf: %s status: %d", 170*e3cf00d0SUpinder Malhi filter_hndl->id, filter_hndl->vnic_idx, 171*e3cf00d0SUpinder Malhi netdev_name(netdev), status); 172*e3cf00d0SUpinder Malhi status = 0; 173*e3cf00d0SUpinder Malhi kfree(filter_hndl); 174*e3cf00d0SUpinder Malhi } else { 175*e3cf00d0SUpinder Malhi usnic_err("PF %s VF Idx %u Filter: %u FILTER DELETE failed with status %d", 176*e3cf00d0SUpinder Malhi netdev_name(netdev), 177*e3cf00d0SUpinder Malhi filter_hndl->vnic_idx, filter_hndl->id, 178*e3cf00d0SUpinder Malhi status); 179*e3cf00d0SUpinder Malhi } 180*e3cf00d0SUpinder Malhi } else { 181*e3cf00d0SUpinder Malhi usnic_dbg("PF %s VF Idx %u Filter: %u FILTER DELETED", 182*e3cf00d0SUpinder Malhi netdev_name(netdev), filter_hndl->vnic_idx, 183*e3cf00d0SUpinder Malhi filter_hndl->id); 184*e3cf00d0SUpinder Malhi kfree(filter_hndl); 185*e3cf00d0SUpinder Malhi } 186*e3cf00d0SUpinder Malhi 187*e3cf00d0SUpinder Malhi return status; 188*e3cf00d0SUpinder Malhi } 189*e3cf00d0SUpinder Malhi 190*e3cf00d0SUpinder Malhi int usnic_fwd_enable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx) 191*e3cf00d0SUpinder Malhi { 192*e3cf00d0SUpinder Malhi int status; 193*e3cf00d0SUpinder Malhi struct net_device *pf_netdev; 194*e3cf00d0SUpinder Malhi u64 a0, a1; 195*e3cf00d0SUpinder Malhi 196*e3cf00d0SUpinder Malhi pf_netdev = ufdev->netdev; 197*e3cf00d0SUpinder Malhi a0 = rq_idx; 198*e3cf00d0SUpinder Malhi a1 = CMD_QP_RQWQ; 199*e3cf00d0SUpinder Malhi 200*e3cf00d0SUpinder Malhi status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_ENABLE, &a0, &a1); 201*e3cf00d0SUpinder Malhi 202*e3cf00d0SUpinder Malhi if (status) { 203*e3cf00d0SUpinder Malhi usnic_err("PF %s VNIC Index %u RQ Index: %u ENABLE Failed with status %d", 204*e3cf00d0SUpinder Malhi netdev_name(pf_netdev), 205*e3cf00d0SUpinder Malhi vnic_idx, 206*e3cf00d0SUpinder Malhi rq_idx, 207*e3cf00d0SUpinder Malhi status); 208*e3cf00d0SUpinder Malhi } else { 209*e3cf00d0SUpinder Malhi usnic_dbg("PF %s VNIC Index %u RQ Index: %u ENABLED", 210*e3cf00d0SUpinder Malhi netdev_name(pf_netdev), 211*e3cf00d0SUpinder Malhi vnic_idx, rq_idx); 212*e3cf00d0SUpinder Malhi } 213*e3cf00d0SUpinder Malhi 214*e3cf00d0SUpinder Malhi return status; 215*e3cf00d0SUpinder Malhi } 216*e3cf00d0SUpinder Malhi 217*e3cf00d0SUpinder Malhi int usnic_fwd_disable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx) 218*e3cf00d0SUpinder Malhi { 219*e3cf00d0SUpinder Malhi int status; 220*e3cf00d0SUpinder Malhi u64 a0, a1; 221*e3cf00d0SUpinder Malhi struct net_device *pf_netdev; 222*e3cf00d0SUpinder Malhi 223*e3cf00d0SUpinder Malhi pf_netdev = ufdev->netdev; 224*e3cf00d0SUpinder Malhi a0 = rq_idx; 225*e3cf00d0SUpinder Malhi a1 = CMD_QP_RQWQ; 226*e3cf00d0SUpinder Malhi 227*e3cf00d0SUpinder Malhi status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_DISABLE, &a0, &a1); 228*e3cf00d0SUpinder Malhi 229*e3cf00d0SUpinder Malhi if (status) { 230*e3cf00d0SUpinder Malhi usnic_err("PF %s VNIC Index %u RQ Index: %u DISABLE Failed with status %d", 231*e3cf00d0SUpinder Malhi netdev_name(pf_netdev), 232*e3cf00d0SUpinder Malhi vnic_idx, 233*e3cf00d0SUpinder Malhi rq_idx, 234*e3cf00d0SUpinder Malhi status); 235*e3cf00d0SUpinder Malhi } else { 236*e3cf00d0SUpinder Malhi usnic_dbg("PF %s VNIC Index %u RQ Index: %u DISABLED", 237*e3cf00d0SUpinder Malhi netdev_name(pf_netdev), 238*e3cf00d0SUpinder Malhi vnic_idx, 239*e3cf00d0SUpinder Malhi rq_idx); 240*e3cf00d0SUpinder Malhi } 241*e3cf00d0SUpinder Malhi 242*e3cf00d0SUpinder Malhi return status; 243*e3cf00d0SUpinder Malhi } 244