Path: blob/master/drivers/infiniband/hw/ehca/ehca_eq.c
15112 views
/*1* IBM eServer eHCA Infiniband device driver for Linux on POWER2*3* Event queue handling4*5* Authors: Waleri Fomin <[email protected]>6* Khadija Souissi <[email protected]>7* Reinhard Ernst <[email protected]>8* Heiko J Schick <[email protected]>9* Hoang-Nam Nguyen <[email protected]>10*11*12* Copyright (c) 2005 IBM Corporation13*14* All rights reserved.15*16* This source code is distributed under a dual license of GPL v2.0 and OpenIB17* BSD.18*19* OpenIB BSD License20*21* Redistribution and use in source and binary forms, with or without22* modification, are permitted provided that the following conditions are met:23*24* Redistributions of source code must retain the above copyright notice, this25* list of conditions and the following disclaimer.26*27* Redistributions in binary form must reproduce the above copyright notice,28* this list of conditions and the following disclaimer in the documentation29* and/or other materials30* provided with the distribution.31*32* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"33* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE34* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE35* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE36* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR37* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF38* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR39* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER40* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)41* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE42* POSSIBILITY OF SUCH DAMAGE.43*/4445#include "ehca_classes.h"46#include "ehca_irq.h"47#include "ehca_iverbs.h"48#include "ehca_qes.h"49#include "hcp_if.h"50#include "ipz_pt_fn.h"5152int ehca_create_eq(struct ehca_shca *shca,53struct ehca_eq *eq,54const enum ehca_eq_type type, const u32 length)55{56int ret;57u64 h_ret;58u32 nr_pages;59u32 i;60void *vpage;61struct ib_device *ib_dev = &shca->ib_device;6263spin_lock_init(&eq->spinlock);64spin_lock_init(&eq->irq_spinlock);65eq->is_initialized = 0;6667if (type != EHCA_EQ && type != EHCA_NEQ) {68ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq);69return -EINVAL;70}71if (!length) {72ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq);73return -EINVAL;74}7576h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,77&eq->pf,78type,79length,80&eq->ipz_eq_handle,81&eq->length,82&nr_pages, &eq->ist);8384if (h_ret != H_SUCCESS) {85ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);86return -EINVAL;87}8889ret = ipz_queue_ctor(NULL, &eq->ipz_queue, nr_pages,90EHCA_PAGESIZE, sizeof(struct ehca_eqe), 0, 0);91if (!ret) {92ehca_err(ib_dev, "Can't allocate EQ pages eq=%p", eq);93goto create_eq_exit1;94}9596for (i = 0; i < nr_pages; i++) {97u64 rpage;9899vpage = ipz_qpageit_get_inc(&eq->ipz_queue);100if (!vpage)101goto create_eq_exit2;102103rpage = virt_to_abs(vpage);104h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,105eq->ipz_eq_handle,106&eq->pf,1070, 0, rpage, 1);108109if (i == (nr_pages - 1)) {110/* last page */111vpage = ipz_qpageit_get_inc(&eq->ipz_queue);112if (h_ret != H_SUCCESS || vpage)113goto create_eq_exit2;114} else {115if (h_ret != H_PAGE_REGISTERED)116goto create_eq_exit2;117}118}119120ipz_qeit_reset(&eq->ipz_queue);121122/* register interrupt handlers and initialize work queues */123if (type == EHCA_EQ) {124tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);125126ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,127IRQF_DISABLED, "ehca_eq",128(void *)shca);129if (ret < 0)130ehca_err(ib_dev, "Can't map interrupt handler.");131} else if (type == EHCA_NEQ) {132tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);133134ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,135IRQF_DISABLED, "ehca_neq",136(void *)shca);137if (ret < 0)138ehca_err(ib_dev, "Can't map interrupt handler.");139}140141eq->is_initialized = 1;142143return 0;144145create_eq_exit2:146ipz_queue_dtor(NULL, &eq->ipz_queue);147148create_eq_exit1:149hipz_h_destroy_eq(shca->ipz_hca_handle, eq);150151return -EINVAL;152}153154void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq)155{156unsigned long flags;157void *eqe;158159spin_lock_irqsave(&eq->spinlock, flags);160eqe = ipz_eqit_eq_get_inc_valid(&eq->ipz_queue);161spin_unlock_irqrestore(&eq->spinlock, flags);162163return eqe;164}165166int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)167{168unsigned long flags;169u64 h_ret;170171ibmebus_free_irq(eq->ist, (void *)shca);172173spin_lock_irqsave(&shca_list_lock, flags);174eq->is_initialized = 0;175spin_unlock_irqrestore(&shca_list_lock, flags);176177tasklet_kill(&eq->interrupt_task);178179h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);180181if (h_ret != H_SUCCESS) {182ehca_err(&shca->ib_device, "Can't free EQ resources.");183return -EINVAL;184}185ipz_queue_dtor(NULL, &eq->ipz_queue);186187return 0;188}189190191