1*cb6b8299SEric Joyner /****************************************************************************** 2*cb6b8299SEric Joyner 3*cb6b8299SEric Joyner Copyright (c) 2013-2015, Intel Corporation 4*cb6b8299SEric Joyner All rights reserved. 5*cb6b8299SEric Joyner 6*cb6b8299SEric Joyner Redistribution and use in source and binary forms, with or without 7*cb6b8299SEric Joyner modification, are permitted provided that the following conditions are met: 8*cb6b8299SEric Joyner 9*cb6b8299SEric Joyner 1. Redistributions of source code must retain the above copyright notice, 10*cb6b8299SEric Joyner this list of conditions and the following disclaimer. 11*cb6b8299SEric Joyner 12*cb6b8299SEric Joyner 2. Redistributions in binary form must reproduce the above copyright 13*cb6b8299SEric Joyner notice, this list of conditions and the following disclaimer in the 14*cb6b8299SEric Joyner documentation and/or other materials provided with the distribution. 15*cb6b8299SEric Joyner 16*cb6b8299SEric Joyner 3. Neither the name of the Intel Corporation nor the names of its 17*cb6b8299SEric Joyner contributors may be used to endorse or promote products derived from 18*cb6b8299SEric Joyner this software without specific prior written permission. 19*cb6b8299SEric Joyner 20*cb6b8299SEric Joyner THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21*cb6b8299SEric Joyner AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*cb6b8299SEric Joyner IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*cb6b8299SEric Joyner ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24*cb6b8299SEric Joyner LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25*cb6b8299SEric Joyner CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26*cb6b8299SEric Joyner SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27*cb6b8299SEric Joyner INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28*cb6b8299SEric Joyner CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29*cb6b8299SEric Joyner ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30*cb6b8299SEric Joyner POSSIBILITY OF SUCH DAMAGE. 31*cb6b8299SEric Joyner 32*cb6b8299SEric Joyner ******************************************************************************/ 33*cb6b8299SEric Joyner /*$FreeBSD$*/ 34*cb6b8299SEric Joyner 35*cb6b8299SEric Joyner #include "ixl.h" 36*cb6b8299SEric Joyner #include "ixl_pf.h" 37*cb6b8299SEric Joyner #include "ixl_iw.h" 38*cb6b8299SEric Joyner #include "ixl_iw_int.h" 39*cb6b8299SEric Joyner 40*cb6b8299SEric Joyner #ifdef IXL_IW 41*cb6b8299SEric Joyner 42*cb6b8299SEric Joyner #define IXL_IW_VEC_BASE(pf) ((pf)->msix - (pf)->iw_msix) 43*cb6b8299SEric Joyner #define IXL_IW_VEC_COUNT(pf) ((pf)->iw_msix) 44*cb6b8299SEric Joyner #define IXL_IW_VEC_LIMIT(pf) ((pf)->msix) 45*cb6b8299SEric Joyner 46*cb6b8299SEric Joyner extern int ixl_enable_iwarp; 47*cb6b8299SEric Joyner 48*cb6b8299SEric Joyner static struct ixl_iw_state ixl_iw; 49*cb6b8299SEric Joyner static int ixl_iw_ref_cnt; 50*cb6b8299SEric Joyner 51*cb6b8299SEric Joyner static void 52*cb6b8299SEric Joyner ixl_iw_pf_msix_reset(struct ixl_pf *pf) 53*cb6b8299SEric Joyner { 54*cb6b8299SEric Joyner struct i40e_hw *hw = &pf->hw; 55*cb6b8299SEric Joyner u32 reg; 56*cb6b8299SEric Joyner int vec; 57*cb6b8299SEric Joyner 58*cb6b8299SEric Joyner for (vec = IXL_IW_VEC_BASE(pf); vec < IXL_IW_VEC_LIMIT(pf); vec++) { 59*cb6b8299SEric Joyner reg = I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK; 60*cb6b8299SEric Joyner wr32(hw, I40E_PFINT_LNKLSTN(vec - 1), reg); 61*cb6b8299SEric Joyner } 62*cb6b8299SEric Joyner 63*cb6b8299SEric Joyner return; 64*cb6b8299SEric Joyner } 65*cb6b8299SEric Joyner 66*cb6b8299SEric Joyner static void 67*cb6b8299SEric Joyner ixl_iw_invoke_op(void *context, int pending) 68*cb6b8299SEric Joyner { 69*cb6b8299SEric Joyner struct ixl_iw_pf_entry *pf_entry = (struct ixl_iw_pf_entry *)context; 70*cb6b8299SEric Joyner struct ixl_iw_pf info; 71*cb6b8299SEric Joyner bool initialize; 72*cb6b8299SEric Joyner int err; 73*cb6b8299SEric Joyner 74*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 75*cb6b8299SEric Joyner 76*cb6b8299SEric Joyner mtx_lock(&ixl_iw.mtx); 77*cb6b8299SEric Joyner if ((pf_entry->state.iw_scheduled == IXL_IW_PF_STATE_ON) && 78*cb6b8299SEric Joyner (pf_entry->state.iw_current == IXL_IW_PF_STATE_OFF)) 79*cb6b8299SEric Joyner initialize = true; 80*cb6b8299SEric Joyner else if ((pf_entry->state.iw_scheduled == IXL_IW_PF_STATE_OFF) && 81*cb6b8299SEric Joyner (pf_entry->state.iw_current == IXL_IW_PF_STATE_ON)) 82*cb6b8299SEric Joyner initialize = false; 83*cb6b8299SEric Joyner else { 84*cb6b8299SEric Joyner /* nothing to be done, so finish here */ 85*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 86*cb6b8299SEric Joyner return; 87*cb6b8299SEric Joyner } 88*cb6b8299SEric Joyner info = pf_entry->pf_info; 89*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 90*cb6b8299SEric Joyner 91*cb6b8299SEric Joyner if (initialize) { 92*cb6b8299SEric Joyner err = ixl_iw.ops->init(&info); 93*cb6b8299SEric Joyner if (err) 94*cb6b8299SEric Joyner device_printf(pf_entry->pf->dev, 95*cb6b8299SEric Joyner "%s: failed to initialize iwarp (err %d)\n", 96*cb6b8299SEric Joyner __func__, err); 97*cb6b8299SEric Joyner else 98*cb6b8299SEric Joyner pf_entry->state.iw_current = IXL_IW_PF_STATE_ON; 99*cb6b8299SEric Joyner } else { 100*cb6b8299SEric Joyner err = ixl_iw.ops->stop(&info); 101*cb6b8299SEric Joyner if (err) 102*cb6b8299SEric Joyner device_printf(pf_entry->pf->dev, 103*cb6b8299SEric Joyner "%s: failed to stop iwarp (err %d)\n", 104*cb6b8299SEric Joyner __func__, err); 105*cb6b8299SEric Joyner else { 106*cb6b8299SEric Joyner ixl_iw_pf_msix_reset(pf_entry->pf); 107*cb6b8299SEric Joyner pf_entry->state.iw_current = IXL_IW_PF_STATE_OFF; 108*cb6b8299SEric Joyner } 109*cb6b8299SEric Joyner } 110*cb6b8299SEric Joyner return; 111*cb6b8299SEric Joyner } 112*cb6b8299SEric Joyner 113*cb6b8299SEric Joyner static void 114*cb6b8299SEric Joyner ixl_iw_uninit(void) 115*cb6b8299SEric Joyner { 116*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 117*cb6b8299SEric Joyner 118*cb6b8299SEric Joyner mtx_destroy(&ixl_iw.mtx); 119*cb6b8299SEric Joyner 120*cb6b8299SEric Joyner return; 121*cb6b8299SEric Joyner } 122*cb6b8299SEric Joyner 123*cb6b8299SEric Joyner static void 124*cb6b8299SEric Joyner ixl_iw_init(void) 125*cb6b8299SEric Joyner { 126*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 127*cb6b8299SEric Joyner 128*cb6b8299SEric Joyner LIST_INIT(&ixl_iw.pfs); 129*cb6b8299SEric Joyner mtx_init(&ixl_iw.mtx, "ixl_iw_pfs", NULL, MTX_DEF); 130*cb6b8299SEric Joyner ixl_iw.registered = false; 131*cb6b8299SEric Joyner 132*cb6b8299SEric Joyner return; 133*cb6b8299SEric Joyner } 134*cb6b8299SEric Joyner 135*cb6b8299SEric Joyner /****************************************************************************** 136*cb6b8299SEric Joyner * if_ixl internal API 137*cb6b8299SEric Joyner *****************************************************************************/ 138*cb6b8299SEric Joyner 139*cb6b8299SEric Joyner int 140*cb6b8299SEric Joyner ixl_iw_pf_init(struct ixl_pf *pf) 141*cb6b8299SEric Joyner { 142*cb6b8299SEric Joyner struct ixl_iw_pf_entry *pf_entry; 143*cb6b8299SEric Joyner struct ixl_iw_pf *pf_info; 144*cb6b8299SEric Joyner int err = 0; 145*cb6b8299SEric Joyner 146*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 147*cb6b8299SEric Joyner 148*cb6b8299SEric Joyner mtx_lock(&ixl_iw.mtx); 149*cb6b8299SEric Joyner 150*cb6b8299SEric Joyner LIST_FOREACH(pf_entry, &ixl_iw.pfs, node) 151*cb6b8299SEric Joyner if (pf_entry->pf == pf) 152*cb6b8299SEric Joyner break; 153*cb6b8299SEric Joyner if (pf_entry == NULL) { 154*cb6b8299SEric Joyner /* attempt to initialize PF not yet attached - sth is wrong */ 155*cb6b8299SEric Joyner device_printf(pf->dev, "%s: PF not found\n", __func__); 156*cb6b8299SEric Joyner err = ENOENT; 157*cb6b8299SEric Joyner goto out; 158*cb6b8299SEric Joyner } 159*cb6b8299SEric Joyner 160*cb6b8299SEric Joyner pf_info = &pf_entry->pf_info; 161*cb6b8299SEric Joyner 162*cb6b8299SEric Joyner pf_info->handle = (void *)pf; 163*cb6b8299SEric Joyner 164*cb6b8299SEric Joyner pf_info->ifp = pf->vsi.ifp; 165*cb6b8299SEric Joyner pf_info->dev = pf->dev; 166*cb6b8299SEric Joyner pf_info->pci_mem = pf->pci_mem; 167*cb6b8299SEric Joyner pf_info->pf_id = pf->hw.pf_id; 168*cb6b8299SEric Joyner pf_info->mtu = pf->vsi.ifp->if_mtu; 169*cb6b8299SEric Joyner 170*cb6b8299SEric Joyner pf_info->iw_msix.count = IXL_IW_VEC_COUNT(pf); 171*cb6b8299SEric Joyner pf_info->iw_msix.base = IXL_IW_VEC_BASE(pf); 172*cb6b8299SEric Joyner 173*cb6b8299SEric Joyner for (int i = 0; i < IXL_IW_MAX_USER_PRIORITY; i++) 174*cb6b8299SEric Joyner pf_info->qs_handle[i] = le16_to_cpu(pf->vsi.info.qs_handle[0]); 175*cb6b8299SEric Joyner 176*cb6b8299SEric Joyner pf_entry->state.pf = IXL_IW_PF_STATE_ON; 177*cb6b8299SEric Joyner if (ixl_iw.registered) { 178*cb6b8299SEric Joyner pf_entry->state.iw_scheduled = IXL_IW_PF_STATE_ON; 179*cb6b8299SEric Joyner taskqueue_enqueue(ixl_iw.tq, &pf_entry->iw_task); 180*cb6b8299SEric Joyner } 181*cb6b8299SEric Joyner 182*cb6b8299SEric Joyner out: 183*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 184*cb6b8299SEric Joyner 185*cb6b8299SEric Joyner return (err); 186*cb6b8299SEric Joyner } 187*cb6b8299SEric Joyner 188*cb6b8299SEric Joyner void 189*cb6b8299SEric Joyner ixl_iw_pf_stop(struct ixl_pf *pf) 190*cb6b8299SEric Joyner { 191*cb6b8299SEric Joyner struct ixl_iw_pf_entry *pf_entry; 192*cb6b8299SEric Joyner 193*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 194*cb6b8299SEric Joyner 195*cb6b8299SEric Joyner mtx_lock(&ixl_iw.mtx); 196*cb6b8299SEric Joyner 197*cb6b8299SEric Joyner LIST_FOREACH(pf_entry, &ixl_iw.pfs, node) 198*cb6b8299SEric Joyner if (pf_entry->pf == pf) 199*cb6b8299SEric Joyner break; 200*cb6b8299SEric Joyner if (pf_entry == NULL) { 201*cb6b8299SEric Joyner /* attempt to stop PF which has not been attached - sth is wrong */ 202*cb6b8299SEric Joyner device_printf(pf->dev, "%s: PF not found\n", __func__); 203*cb6b8299SEric Joyner goto out; 204*cb6b8299SEric Joyner } 205*cb6b8299SEric Joyner 206*cb6b8299SEric Joyner pf_entry->state.pf = IXL_IW_PF_STATE_OFF; 207*cb6b8299SEric Joyner if (pf_entry->state.iw_scheduled == IXL_IW_PF_STATE_ON) { 208*cb6b8299SEric Joyner pf_entry->state.iw_scheduled = IXL_IW_PF_STATE_OFF; 209*cb6b8299SEric Joyner if (ixl_iw.registered) 210*cb6b8299SEric Joyner taskqueue_enqueue(ixl_iw.tq, &pf_entry->iw_task); 211*cb6b8299SEric Joyner } 212*cb6b8299SEric Joyner 213*cb6b8299SEric Joyner out: 214*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 215*cb6b8299SEric Joyner 216*cb6b8299SEric Joyner return; 217*cb6b8299SEric Joyner } 218*cb6b8299SEric Joyner 219*cb6b8299SEric Joyner int 220*cb6b8299SEric Joyner ixl_iw_pf_attach(struct ixl_pf *pf) 221*cb6b8299SEric Joyner { 222*cb6b8299SEric Joyner struct ixl_iw_pf_entry *pf_entry; 223*cb6b8299SEric Joyner int err = 0; 224*cb6b8299SEric Joyner 225*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 226*cb6b8299SEric Joyner 227*cb6b8299SEric Joyner if (ixl_iw_ref_cnt == 0) 228*cb6b8299SEric Joyner ixl_iw_init(); 229*cb6b8299SEric Joyner 230*cb6b8299SEric Joyner mtx_lock(&ixl_iw.mtx); 231*cb6b8299SEric Joyner 232*cb6b8299SEric Joyner LIST_FOREACH(pf_entry, &ixl_iw.pfs, node) 233*cb6b8299SEric Joyner if (pf_entry->pf == pf) { 234*cb6b8299SEric Joyner device_printf(pf->dev, "%s: PF already exists\n", 235*cb6b8299SEric Joyner __func__); 236*cb6b8299SEric Joyner err = EEXIST; 237*cb6b8299SEric Joyner goto out; 238*cb6b8299SEric Joyner } 239*cb6b8299SEric Joyner 240*cb6b8299SEric Joyner pf_entry = malloc(sizeof(struct ixl_iw_pf_entry), 241*cb6b8299SEric Joyner M_DEVBUF, M_NOWAIT | M_ZERO); 242*cb6b8299SEric Joyner if (pf_entry == NULL) { 243*cb6b8299SEric Joyner device_printf(pf->dev, 244*cb6b8299SEric Joyner "%s: failed to allocate memory to attach new PF\n", 245*cb6b8299SEric Joyner __func__); 246*cb6b8299SEric Joyner err = ENOMEM; 247*cb6b8299SEric Joyner goto out; 248*cb6b8299SEric Joyner } 249*cb6b8299SEric Joyner pf_entry->pf = pf; 250*cb6b8299SEric Joyner pf_entry->state.pf = IXL_IW_PF_STATE_OFF; 251*cb6b8299SEric Joyner pf_entry->state.iw_scheduled = IXL_IW_PF_STATE_OFF; 252*cb6b8299SEric Joyner pf_entry->state.iw_current = IXL_IW_PF_STATE_OFF; 253*cb6b8299SEric Joyner 254*cb6b8299SEric Joyner LIST_INSERT_HEAD(&ixl_iw.pfs, pf_entry, node); 255*cb6b8299SEric Joyner ixl_iw_ref_cnt++; 256*cb6b8299SEric Joyner 257*cb6b8299SEric Joyner TASK_INIT(&pf_entry->iw_task, 0, ixl_iw_invoke_op, pf_entry); 258*cb6b8299SEric Joyner out: 259*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 260*cb6b8299SEric Joyner 261*cb6b8299SEric Joyner return (err); 262*cb6b8299SEric Joyner } 263*cb6b8299SEric Joyner 264*cb6b8299SEric Joyner int 265*cb6b8299SEric Joyner ixl_iw_pf_detach(struct ixl_pf *pf) 266*cb6b8299SEric Joyner { 267*cb6b8299SEric Joyner struct ixl_iw_pf_entry *pf_entry; 268*cb6b8299SEric Joyner int err = 0; 269*cb6b8299SEric Joyner 270*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 271*cb6b8299SEric Joyner 272*cb6b8299SEric Joyner mtx_lock(&ixl_iw.mtx); 273*cb6b8299SEric Joyner 274*cb6b8299SEric Joyner LIST_FOREACH(pf_entry, &ixl_iw.pfs, node) 275*cb6b8299SEric Joyner if (pf_entry->pf == pf) 276*cb6b8299SEric Joyner break; 277*cb6b8299SEric Joyner if (pf_entry == NULL) { 278*cb6b8299SEric Joyner /* attempt to stop PF which has not been attached - sth is wrong */ 279*cb6b8299SEric Joyner device_printf(pf->dev, "%s: PF not found\n", __func__); 280*cb6b8299SEric Joyner err = ENOENT; 281*cb6b8299SEric Joyner goto out; 282*cb6b8299SEric Joyner } 283*cb6b8299SEric Joyner 284*cb6b8299SEric Joyner if (pf_entry->state.pf != IXL_IW_PF_STATE_OFF) { 285*cb6b8299SEric Joyner /* attempt to detach PF which has not yet been stopped - sth is wrong */ 286*cb6b8299SEric Joyner device_printf(pf->dev, "%s: failed - PF is still active\n", 287*cb6b8299SEric Joyner __func__); 288*cb6b8299SEric Joyner err = EBUSY; 289*cb6b8299SEric Joyner goto out; 290*cb6b8299SEric Joyner } 291*cb6b8299SEric Joyner LIST_REMOVE(pf_entry, node); 292*cb6b8299SEric Joyner free(pf_entry, M_DEVBUF); 293*cb6b8299SEric Joyner ixl_iw_ref_cnt--; 294*cb6b8299SEric Joyner 295*cb6b8299SEric Joyner out: 296*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 297*cb6b8299SEric Joyner 298*cb6b8299SEric Joyner if (ixl_iw_ref_cnt == 0) 299*cb6b8299SEric Joyner ixl_iw_uninit(); 300*cb6b8299SEric Joyner 301*cb6b8299SEric Joyner return (err); 302*cb6b8299SEric Joyner } 303*cb6b8299SEric Joyner 304*cb6b8299SEric Joyner 305*cb6b8299SEric Joyner /****************************************************************************** 306*cb6b8299SEric Joyner * API exposed to iw_ixl module 307*cb6b8299SEric Joyner *****************************************************************************/ 308*cb6b8299SEric Joyner 309*cb6b8299SEric Joyner int 310*cb6b8299SEric Joyner ixl_iw_pf_reset(void *pf_handle) 311*cb6b8299SEric Joyner { 312*cb6b8299SEric Joyner struct ixl_pf *pf = (struct ixl_pf *)pf_handle; 313*cb6b8299SEric Joyner 314*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 315*cb6b8299SEric Joyner 316*cb6b8299SEric Joyner IXL_PF_LOCK(pf); 317*cb6b8299SEric Joyner ixl_init_locked(pf); 318*cb6b8299SEric Joyner IXL_PF_UNLOCK(pf); 319*cb6b8299SEric Joyner 320*cb6b8299SEric Joyner return (0); 321*cb6b8299SEric Joyner } 322*cb6b8299SEric Joyner 323*cb6b8299SEric Joyner int 324*cb6b8299SEric Joyner ixl_iw_pf_msix_init(void *pf_handle, 325*cb6b8299SEric Joyner struct ixl_iw_msix_mapping *msix_info) 326*cb6b8299SEric Joyner { 327*cb6b8299SEric Joyner struct ixl_pf *pf = (struct ixl_pf *)pf_handle; 328*cb6b8299SEric Joyner struct i40e_hw *hw = &pf->hw; 329*cb6b8299SEric Joyner u32 reg; 330*cb6b8299SEric Joyner int vec, i; 331*cb6b8299SEric Joyner 332*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 333*cb6b8299SEric Joyner 334*cb6b8299SEric Joyner if ((msix_info->aeq_vector < IXL_IW_VEC_BASE(pf)) || 335*cb6b8299SEric Joyner (msix_info->aeq_vector >= IXL_IW_VEC_LIMIT(pf))) { 336*cb6b8299SEric Joyner printf("%s: invalid MSIX vector (%i) for AEQ\n", 337*cb6b8299SEric Joyner __func__, msix_info->aeq_vector); 338*cb6b8299SEric Joyner return (EINVAL); 339*cb6b8299SEric Joyner } 340*cb6b8299SEric Joyner reg = I40E_PFINT_AEQCTL_CAUSE_ENA_MASK | 341*cb6b8299SEric Joyner (msix_info->aeq_vector << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT) | 342*cb6b8299SEric Joyner (msix_info->itr_indx << I40E_PFINT_AEQCTL_ITR_INDX_SHIFT); 343*cb6b8299SEric Joyner wr32(hw, I40E_PFINT_AEQCTL, reg); 344*cb6b8299SEric Joyner 345*cb6b8299SEric Joyner for (vec = IXL_IW_VEC_BASE(pf); vec < IXL_IW_VEC_LIMIT(pf); vec++) { 346*cb6b8299SEric Joyner for (i = 0; i < msix_info->ceq_cnt; i++) 347*cb6b8299SEric Joyner if (msix_info->ceq_vector[i] == vec) 348*cb6b8299SEric Joyner break; 349*cb6b8299SEric Joyner if (i == msix_info->ceq_cnt) { 350*cb6b8299SEric Joyner /* this vector has no CEQ mapped */ 351*cb6b8299SEric Joyner reg = I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK; 352*cb6b8299SEric Joyner wr32(hw, I40E_PFINT_LNKLSTN(vec - 1), reg); 353*cb6b8299SEric Joyner } else { 354*cb6b8299SEric Joyner reg = (i & I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK) | 355*cb6b8299SEric Joyner (I40E_QUEUE_TYPE_PE_CEQ << 356*cb6b8299SEric Joyner I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT); 357*cb6b8299SEric Joyner wr32(hw, I40E_PFINT_LNKLSTN(vec - 1), reg); 358*cb6b8299SEric Joyner 359*cb6b8299SEric Joyner reg = I40E_PFINT_CEQCTL_CAUSE_ENA_MASK | 360*cb6b8299SEric Joyner (vec << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT) | 361*cb6b8299SEric Joyner (msix_info->itr_indx << 362*cb6b8299SEric Joyner I40E_PFINT_CEQCTL_ITR_INDX_SHIFT) | 363*cb6b8299SEric Joyner (IXL_QUEUE_EOL << 364*cb6b8299SEric Joyner I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT); 365*cb6b8299SEric Joyner wr32(hw, I40E_PFINT_CEQCTL(i), reg); 366*cb6b8299SEric Joyner } 367*cb6b8299SEric Joyner } 368*cb6b8299SEric Joyner 369*cb6b8299SEric Joyner return (0); 370*cb6b8299SEric Joyner } 371*cb6b8299SEric Joyner 372*cb6b8299SEric Joyner int 373*cb6b8299SEric Joyner ixl_iw_register(struct ixl_iw_ops *ops) 374*cb6b8299SEric Joyner { 375*cb6b8299SEric Joyner struct ixl_iw_pf_entry *pf_entry; 376*cb6b8299SEric Joyner int err = 0; 377*cb6b8299SEric Joyner 378*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 379*cb6b8299SEric Joyner 380*cb6b8299SEric Joyner if (ixl_enable_iwarp == 0) { 381*cb6b8299SEric Joyner printf("%s: enable_iwarp is off, registering dropped\n", 382*cb6b8299SEric Joyner __func__); 383*cb6b8299SEric Joyner return (EACCES); 384*cb6b8299SEric Joyner } 385*cb6b8299SEric Joyner 386*cb6b8299SEric Joyner if ((ops->init == NULL) || (ops->stop == NULL)) { 387*cb6b8299SEric Joyner printf("%s: invalid iwarp driver ops\n", __func__); 388*cb6b8299SEric Joyner return (EINVAL); 389*cb6b8299SEric Joyner } 390*cb6b8299SEric Joyner 391*cb6b8299SEric Joyner mtx_lock(&ixl_iw.mtx); 392*cb6b8299SEric Joyner 393*cb6b8299SEric Joyner if (ixl_iw.registered) { 394*cb6b8299SEric Joyner printf("%s: iwarp driver already registered\n", __func__); 395*cb6b8299SEric Joyner err = EBUSY; 396*cb6b8299SEric Joyner goto out; 397*cb6b8299SEric Joyner } 398*cb6b8299SEric Joyner 399*cb6b8299SEric Joyner ixl_iw.tq = taskqueue_create("ixl_iw", M_NOWAIT, 400*cb6b8299SEric Joyner taskqueue_thread_enqueue, &ixl_iw.tq); 401*cb6b8299SEric Joyner if (ixl_iw.tq == NULL) { 402*cb6b8299SEric Joyner printf("%s: failed to create queue\n", __func__); 403*cb6b8299SEric Joyner err = ENOMEM; 404*cb6b8299SEric Joyner goto out; 405*cb6b8299SEric Joyner } 406*cb6b8299SEric Joyner taskqueue_start_threads(&ixl_iw.tq, 1, PI_NET, "ixl iw"); 407*cb6b8299SEric Joyner 408*cb6b8299SEric Joyner ixl_iw.ops = malloc(sizeof(struct ixl_iw_ops), 409*cb6b8299SEric Joyner M_DEVBUF, M_NOWAIT | M_ZERO); 410*cb6b8299SEric Joyner if (ixl_iw.ops == NULL) { 411*cb6b8299SEric Joyner printf("%s: failed to allocate memory\n", __func__); 412*cb6b8299SEric Joyner taskqueue_free(ixl_iw.tq); 413*cb6b8299SEric Joyner err = ENOMEM; 414*cb6b8299SEric Joyner goto out; 415*cb6b8299SEric Joyner } 416*cb6b8299SEric Joyner 417*cb6b8299SEric Joyner ixl_iw.ops->init = ops->init; 418*cb6b8299SEric Joyner ixl_iw.ops->stop = ops->stop; 419*cb6b8299SEric Joyner ixl_iw.registered = true; 420*cb6b8299SEric Joyner 421*cb6b8299SEric Joyner LIST_FOREACH(pf_entry, &ixl_iw.pfs, node) 422*cb6b8299SEric Joyner if (pf_entry->state.pf == IXL_IW_PF_STATE_ON) { 423*cb6b8299SEric Joyner pf_entry->state.iw_scheduled = IXL_IW_PF_STATE_ON; 424*cb6b8299SEric Joyner taskqueue_enqueue(ixl_iw.tq, &pf_entry->iw_task); 425*cb6b8299SEric Joyner } 426*cb6b8299SEric Joyner 427*cb6b8299SEric Joyner out: 428*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 429*cb6b8299SEric Joyner 430*cb6b8299SEric Joyner return (err); 431*cb6b8299SEric Joyner } 432*cb6b8299SEric Joyner 433*cb6b8299SEric Joyner int 434*cb6b8299SEric Joyner ixl_iw_unregister(void) 435*cb6b8299SEric Joyner { 436*cb6b8299SEric Joyner struct ixl_iw_pf_entry *pf_entry; 437*cb6b8299SEric Joyner 438*cb6b8299SEric Joyner INIT_DEBUGOUT("begin"); 439*cb6b8299SEric Joyner 440*cb6b8299SEric Joyner mtx_lock(&ixl_iw.mtx); 441*cb6b8299SEric Joyner 442*cb6b8299SEric Joyner if (!ixl_iw.registered) { 443*cb6b8299SEric Joyner printf("%s: failed - iwarp driver has not been registered\n", 444*cb6b8299SEric Joyner __func__); 445*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 446*cb6b8299SEric Joyner return (ENOENT); 447*cb6b8299SEric Joyner } 448*cb6b8299SEric Joyner 449*cb6b8299SEric Joyner LIST_FOREACH(pf_entry, &ixl_iw.pfs, node) 450*cb6b8299SEric Joyner if (pf_entry->state.iw_scheduled == IXL_IW_PF_STATE_ON) { 451*cb6b8299SEric Joyner pf_entry->state.iw_scheduled = IXL_IW_PF_STATE_OFF; 452*cb6b8299SEric Joyner taskqueue_enqueue(ixl_iw.tq, &pf_entry->iw_task); 453*cb6b8299SEric Joyner } 454*cb6b8299SEric Joyner 455*cb6b8299SEric Joyner ixl_iw.registered = false; 456*cb6b8299SEric Joyner 457*cb6b8299SEric Joyner mtx_unlock(&ixl_iw.mtx); 458*cb6b8299SEric Joyner 459*cb6b8299SEric Joyner LIST_FOREACH(pf_entry, &ixl_iw.pfs, node) 460*cb6b8299SEric Joyner taskqueue_drain(ixl_iw.tq, &pf_entry->iw_task); 461*cb6b8299SEric Joyner taskqueue_free(ixl_iw.tq); 462*cb6b8299SEric Joyner ixl_iw.tq = NULL; 463*cb6b8299SEric Joyner free(ixl_iw.ops, M_DEVBUF); 464*cb6b8299SEric Joyner ixl_iw.ops = NULL; 465*cb6b8299SEric Joyner 466*cb6b8299SEric Joyner return (0); 467*cb6b8299SEric Joyner } 468*cb6b8299SEric Joyner 469*cb6b8299SEric Joyner #endif /* IXL_IW */ 470