mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-30 21:57:01 +00:00 
			
		
		
		
	 604158ade0
			
		
	
	
		604158ade0
		
	
	
	
	
		
			
			Add description for bfa driver module parameters. Signed-off-by: Jing Huang <huangj@brocade.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
		
			
				
	
	
		
			223 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
 | |
|  * All rights reserved
 | |
|  * www.brocade.com
 | |
|  *
 | |
|  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms of the GNU General Public License (GPL) Version 2 as
 | |
|  * published by the Free Software Foundation
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful, but
 | |
|  * WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * General Public License for more details.
 | |
|  */
 | |
| 
 | |
| #include "bfad_drv.h"
 | |
| #include "bfad_trcmod.h"
 | |
| 
 | |
| BFA_TRC_FILE(LDRV, INTR);
 | |
| 
 | |
| /**
 | |
|  *  bfa_isr BFA driver interrupt functions
 | |
|  */
 | |
| static int msix_disable_cb;
 | |
| static int msix_disable_ct;
 | |
| module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
 | |
| MODULE_PARM_DESC(msix_disable_cb, "Disable MSIX for Brocade-415/425/815/825"
 | |
| 		" cards, default=0, Range[false:0|true:1]");
 | |
| module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
 | |
| MODULE_PARM_DESC(msix_disable_ct, "Disable MSIX for Brocade-1010/1020/804"
 | |
| 		" cards, default=0, Range[false:0|true:1]");
 | |
| /**
 | |
|  * Line based interrupt handler.
 | |
|  */
 | |
| static irqreturn_t
 | |
| bfad_intx(int irq, void *dev_id)
 | |
| {
 | |
| 	struct bfad_s         *bfad = dev_id;
 | |
| 	struct list_head         doneq;
 | |
| 	unsigned long   flags;
 | |
| 	bfa_boolean_t rc;
 | |
| 
 | |
| 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 | |
| 	rc = bfa_intx(&bfad->bfa);
 | |
| 	if (!rc) {
 | |
| 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 | |
| 		return IRQ_NONE;
 | |
| 	}
 | |
| 
 | |
| 	bfa_comp_deq(&bfad->bfa, &doneq);
 | |
| 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 | |
| 
 | |
| 	if (!list_empty(&doneq)) {
 | |
| 		bfa_comp_process(&bfad->bfa, &doneq);
 | |
| 
 | |
| 		spin_lock_irqsave(&bfad->bfad_lock, flags);
 | |
| 		bfa_comp_free(&bfad->bfa, &doneq);
 | |
| 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 | |
| 		bfa_trc_fp(bfad, irq);
 | |
| 	}
 | |
| 
 | |
| 	return IRQ_HANDLED;
 | |
| 
 | |
| }
 | |
| 
 | |
| static irqreturn_t
 | |
| bfad_msix(int irq, void *dev_id)
 | |
| {
 | |
| 	struct bfad_msix_s *vec = dev_id;
 | |
| 	struct bfad_s *bfad = vec->bfad;
 | |
| 	struct list_head doneq;
 | |
| 	unsigned long   flags;
 | |
| 
 | |
| 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 | |
| 
 | |
| 	bfa_msix(&bfad->bfa, vec->msix.entry);
 | |
| 	bfa_comp_deq(&bfad->bfa, &doneq);
 | |
| 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 | |
| 
 | |
| 	if (!list_empty(&doneq)) {
 | |
| 		bfa_comp_process(&bfad->bfa, &doneq);
 | |
| 
 | |
| 		spin_lock_irqsave(&bfad->bfad_lock, flags);
 | |
| 		bfa_comp_free(&bfad->bfa, &doneq);
 | |
| 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 | |
| 	}
 | |
| 
 | |
| 	return IRQ_HANDLED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Initialize the MSIX entry table.
 | |
|  */
 | |
| static void
 | |
| bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
 | |
| 			 int mask, int max_bit)
 | |
| {
 | |
| 	int             i;
 | |
| 	int             match = 0x00000001;
 | |
| 
 | |
| 	for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
 | |
| 		if (mask & match) {
 | |
| 			bfad->msix_tab[bfad->nvec].msix.entry = i;
 | |
| 			bfad->msix_tab[bfad->nvec].bfad = bfad;
 | |
| 			msix_entries[bfad->nvec].entry = i;
 | |
| 			bfad->nvec++;
 | |
| 		}
 | |
| 
 | |
| 		match <<= 1;
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| int
 | |
| bfad_install_msix_handler(struct bfad_s *bfad)
 | |
| {
 | |
| 	int             i, error = 0;
 | |
| 
 | |
| 	for (i = 0; i < bfad->nvec; i++) {
 | |
| 		error = request_irq(bfad->msix_tab[i].msix.vector,
 | |
| 				    (irq_handler_t) bfad_msix, 0,
 | |
| 				    BFAD_DRIVER_NAME, &bfad->msix_tab[i]);
 | |
| 		bfa_trc(bfad, i);
 | |
| 		bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
 | |
| 		if (error) {
 | |
| 			int             j;
 | |
| 
 | |
| 			for (j = 0; j < i; j++)
 | |
| 				free_irq(bfad->msix_tab[j].msix.vector,
 | |
| 						&bfad->msix_tab[j]);
 | |
| 
 | |
| 			return 1;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Setup MSIX based interrupt.
 | |
|  */
 | |
| int
 | |
| bfad_setup_intr(struct bfad_s *bfad)
 | |
| {
 | |
| 	int error = 0;
 | |
| 	u32 mask = 0, i, num_bit = 0, max_bit = 0;
 | |
| 	struct msix_entry msix_entries[MAX_MSIX_ENTRY];
 | |
| 	struct pci_dev *pdev = bfad->pcidev;
 | |
| 
 | |
| 	/* Call BFA to get the msix map for this PCI function.  */
 | |
| 	bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
 | |
| 
 | |
| 	/* Set up the msix entry table */
 | |
| 	bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
 | |
| 
 | |
| 	if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
 | |
| 		(!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
 | |
| 
 | |
| 		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
 | |
| 		if (error) {
 | |
| 			/*
 | |
| 			 * Only error number of vector is available.
 | |
| 			 * We don't have a mechanism to map multiple
 | |
| 			 * interrupts into one vector, so even if we
 | |
| 			 * can try to request less vectors, we don't
 | |
| 			 * know how to associate interrupt events to
 | |
| 			 *  vectors. Linux doesn't dupicate vectors
 | |
| 			 * in the MSIX table for this case.
 | |
| 			 */
 | |
| 
 | |
| 			printk(KERN_WARNING "bfad%d: "
 | |
| 				"pci_enable_msix failed (%d),"
 | |
| 				" use line based.\n", bfad->inst_no, error);
 | |
| 
 | |
| 			goto line_based;
 | |
| 		}
 | |
| 
 | |
| 		/* Save the vectors */
 | |
| 		for (i = 0; i < bfad->nvec; i++) {
 | |
| 			bfa_trc(bfad, msix_entries[i].vector);
 | |
| 			bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
 | |
| 		}
 | |
| 
 | |
| 		bfa_msix_init(&bfad->bfa, bfad->nvec);
 | |
| 
 | |
| 		bfad->bfad_flags |= BFAD_MSIX_ON;
 | |
| 
 | |
| 		return error;
 | |
| 	}
 | |
| 
 | |
| line_based:
 | |
| 	error = 0;
 | |
| 	if (request_irq
 | |
| 	    (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
 | |
| 	     BFAD_DRIVER_NAME, bfad) != 0) {
 | |
| 		/* Enable interrupt handler failed */
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| 	return error;
 | |
| }
 | |
| 
 | |
| void
 | |
| bfad_remove_intr(struct bfad_s *bfad)
 | |
| {
 | |
| 	int             i;
 | |
| 
 | |
| 	if (bfad->bfad_flags & BFAD_MSIX_ON) {
 | |
| 		for (i = 0; i < bfad->nvec; i++)
 | |
| 			free_irq(bfad->msix_tab[i].msix.vector,
 | |
| 					&bfad->msix_tab[i]);
 | |
| 
 | |
| 		pci_disable_msix(bfad->pcidev);
 | |
| 		bfad->bfad_flags &= ~BFAD_MSIX_ON;
 | |
| 	} else {
 | |
| 		free_irq(bfad->pcidev->irq, bfad);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 |