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