/* * This file is part of the Chelsio FCoE driver for Linux. * * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE.
*/
/* * csio_fwevt_handler - Common FW event handler routine. * @hw: HW module. * * This is the ISR for FW events. It is shared b/w MSIX * and INTx handlers.
*/ staticvoid
csio_fwevt_handler(struct csio_hw *hw)
{ int rv; unsignedlong flags;
spin_lock_irqsave(&hw->lock, flags); if (subop)
csio_scsi_closed(ioreq,
(struct list_head *)cbfn_q); else
csio_scsi_aborted(ioreq,
(struct list_head *)cbfn_q); /* * We call scsi_done for I/Os that driver thinks aborts * have timed out. If there is a race caused by FW * completing abort at the exact same time that the * driver has deteced the abort timeout, the following * check prevents calling of scsi_done twice for the * same command: once from the eh_abort_handler, another * from csio_scsi_isr_handler(). This also avoids the * need to check if csio_scsi_cmnd(req) is NULL in the * fast path.
*/
cmnd = csio_scsi_cmnd(ioreq); if (unlikely(cmnd == NULL))
list_del_init(&ioreq->sm.sm_list);
/* * csio_scsi_isr_handler() - Common SCSI ISR handler. * @iq: Ingress queue pointer. * * Processes SCSI completions on the SCSI IQ indicated by scm->iq_idx * by calling csio_wr_process_iq_idx. If there are completions on the * isr_cbfn_q, yank them out into a local queue and call their io_cbfns. * Once done, add these completions onto the freelist. * This routine is shared b/w MSIX and INTx.
*/ staticinline irqreturn_t
csio_scsi_isr_handler(struct csio_q *iq)
{ struct csio_hw *hw = (struct csio_hw *)iq->owner;
LIST_HEAD(cbfn_q); struct list_head *tmp; struct csio_scsim *scm; struct csio_ioreq *ioreq; int isr_completions = 0;
scm = csio_hw_to_scsim(hw);
if (unlikely(csio_wr_process_iq(hw, iq, csio_process_scsi_cmpl,
&cbfn_q) != 0)) return IRQ_NONE;
/* Call back the completion routines */
list_for_each(tmp, &cbfn_q) {
ioreq = (struct csio_ioreq *)tmp;
isr_completions++;
ioreq->io_cbfn(hw, ioreq); /* Release ddp buffer if used for this req */ if (unlikely(ioreq->dcopy))
csio_put_scsi_ddp_list_lock(hw, scm, &ioreq->gen_list,
ioreq->nsge);
}
if (isr_completions) { /* Return the ioreqs back to ioreq->freelist */
csio_put_scsi_ioreq_list_lock(hw, scm, &cbfn_q,
isr_completions);
}
return IRQ_HANDLED;
}
/* * csio_scsi_isr() - SCSI MSIX handler * @irq: * @dev_id: * * This is the top level SCSI MSIX handler. Calls csio_scsi_isr_handler() * for handling SCSI completions.
*/ static irqreturn_t
csio_scsi_isr(int irq, void *dev_id)
{ struct csio_q *iq = (struct csio_q *) dev_id; struct csio_hw *hw;
if (unlikely(!iq)) return IRQ_NONE;
hw = (struct csio_hw *)iq->owner;
if (unlikely(pci_channel_offline(hw->pdev))) {
CSIO_INC_STATS(hw, n_pcich_offline); return IRQ_NONE;
}
csio_scsi_isr_handler(iq);
return IRQ_HANDLED;
}
/* * csio_scsi_intx_handler() - SCSI INTx handler * @irq: * @dev_id: * * This is the top level SCSI INTx handler. Calls csio_scsi_isr_handler() * for handling SCSI completions.
*/ void
csio_scsi_intx_handler(struct csio_hw *hw, void *wr, uint32_t len, struct csio_fl_dma_buf *flb, void *priv)
{ struct csio_q *iq = priv;
staticvoid
csio_add_msix_desc(struct csio_hw *hw)
{ int i; struct csio_msix_entries *entryp = &hw->msix_entries[0]; int k = CSIO_EXTRA_VECS; int len = sizeof(entryp->desc) - 1; int cnt = hw->num_sqsets + k;
out_free_irqs: for (i = 0; i < k; i++)
free_irq(pci_irq_vector(pdev, i), hw->msix_entries[i].dev_id);
pci_free_irq_vectors(hw->pdev); return -EINVAL;
}
/* Reduce per-port max possible CPUs */ staticvoid
csio_reduce_sqsets(struct csio_hw *hw, int cnt)
{ int i; struct csio_scsi_cpu_info *info;
while (cnt < hw->num_sqsets) { for (i = 0; i < hw->num_pports; i++) {
info = &hw->scsi_cpu_info[i]; if (info->max_cpus > 1) {
info->max_cpus--;
hw->num_sqsets--; if (hw->num_sqsets <= cnt) break;
}
}
}
csio_dbg(hw, "Reduced sqsets to %d\n", hw->num_sqsets);
}
affd->nr_sets = hw->num_pports; for (i = 0; i < hw->num_pports; i++)
affd->set_size[i] = nvecs / hw->num_pports;
}
staticint
csio_enable_msix(struct csio_hw *hw)
{ int i, j, k, n, min, cnt; int extra = CSIO_EXTRA_VECS; struct csio_scsi_cpu_info *info; struct irq_affinity desc = {
.pre_vectors = CSIO_EXTRA_VECS,
.calc_sets = csio_calc_sets,
.priv = hw,
};
if (hw->num_pports > IRQ_AFFINITY_MAX_SETS) return -ENOSPC;
min = hw->num_pports + extra;
cnt = hw->num_sqsets + extra;
/* Max vectors required based on #niqs configured in fw */ if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS || !csio_is_hw_master(hw))
cnt = min_t(uint8_t, hw->cfg_niq, cnt);
/* Try MSIX, then MSI or fall back to INTx */ if ((csio_msi == 2) && !csio_enable_msix(hw))
hw->intr_mode = CSIO_IM_MSIX; else { /* Max iqs required based on #niqs configured in fw */ if (hw->flags & CSIO_HWF_USING_SOFT_PARAMS ||
!csio_is_hw_master(hw)) { int extra = CSIO_EXTRA_MSI_IQS;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.