mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	[BNX2]: Add 1-shot MSI handler for 5709.
The 5709 supports the one-shot MSI handler similar to some of the tg3 chips. In this mode, the MSI disables itself automatically until it is re-enabled at the end of NAPI poll. Put the request_irq/free_irq logic in common procedures. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									da3e4fbed2
								
							
						
					
					
						commit
						8e6a72c435
					
				
					 2 changed files with 81 additions and 41 deletions
				
			
		|  | @ -2261,6 +2261,23 @@ bnx2_msi(int irq, void *dev_instance) | |||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| 
 | ||||
| static irqreturn_t | ||||
| bnx2_msi_1shot(int irq, void *dev_instance) | ||||
| { | ||||
| 	struct net_device *dev = dev_instance; | ||||
| 	struct bnx2 *bp = netdev_priv(dev); | ||||
| 
 | ||||
| 	prefetch(bp->status_blk); | ||||
| 
 | ||||
| 	/* Return here if interrupt is disabled. */ | ||||
| 	if (unlikely(atomic_read(&bp->intr_sem) != 0)) | ||||
| 		return IRQ_HANDLED; | ||||
| 
 | ||||
| 	netif_rx_schedule(dev); | ||||
| 
 | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| 
 | ||||
| static irqreturn_t | ||||
| bnx2_interrupt(int irq, void *dev_instance) | ||||
| { | ||||
|  | @ -3759,13 +3776,17 @@ bnx2_init_chip(struct bnx2 *bp) | |||
| 	REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */ | ||||
| 
 | ||||
| 	if (CHIP_ID(bp) == CHIP_ID_5706_A1) | ||||
| 		REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS); | ||||
| 		val = BNX2_HC_CONFIG_COLLECT_STATS; | ||||
| 	else { | ||||
| 		REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE | | ||||
| 		       BNX2_HC_CONFIG_TX_TMR_MODE | | ||||
| 		       BNX2_HC_CONFIG_COLLECT_STATS); | ||||
| 		val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE | | ||||
| 		      BNX2_HC_CONFIG_COLLECT_STATS; | ||||
| 	} | ||||
| 
 | ||||
| 	if (bp->flags & ONE_SHOT_MSI_FLAG) | ||||
| 		val |= BNX2_HC_CONFIG_ONE_SHOT; | ||||
| 
 | ||||
| 	REG_WR(bp, BNX2_HC_CONFIG, val); | ||||
| 
 | ||||
| 	/* Clear internal stats counters. */ | ||||
| 	REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW); | ||||
| 
 | ||||
|  | @ -4610,6 +4631,38 @@ bnx2_restart_timer: | |||
| 	mod_timer(&bp->timer, jiffies + bp->current_interval); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| bnx2_request_irq(struct bnx2 *bp) | ||||
| { | ||||
| 	struct net_device *dev = bp->dev; | ||||
| 	int rc = 0; | ||||
| 
 | ||||
| 	if (bp->flags & USING_MSI_FLAG) { | ||||
| 		irq_handler_t	fn = bnx2_msi; | ||||
| 
 | ||||
| 		if (bp->flags & ONE_SHOT_MSI_FLAG) | ||||
| 			fn = bnx2_msi_1shot; | ||||
| 
 | ||||
| 		rc = request_irq(bp->pdev->irq, fn, 0, dev->name, dev); | ||||
| 	} else | ||||
| 		rc = request_irq(bp->pdev->irq, bnx2_interrupt, | ||||
| 				 IRQF_SHARED, dev->name, dev); | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| bnx2_free_irq(struct bnx2 *bp) | ||||
| { | ||||
| 	struct net_device *dev = bp->dev; | ||||
| 
 | ||||
| 	if (bp->flags & USING_MSI_FLAG) { | ||||
| 		free_irq(bp->pdev->irq, dev); | ||||
| 		pci_disable_msi(bp->pdev); | ||||
| 		bp->flags &= ~(USING_MSI_FLAG | ONE_SHOT_MSI_FLAG); | ||||
| 	} else | ||||
| 		free_irq(bp->pdev->irq, dev); | ||||
| } | ||||
| 
 | ||||
| /* Called with rtnl_lock */ | ||||
| static int | ||||
| bnx2_open(struct net_device *dev) | ||||
|  | @ -4626,24 +4679,15 @@ bnx2_open(struct net_device *dev) | |||
| 	if (rc) | ||||
| 		return rc; | ||||
| 
 | ||||
| 	if ((CHIP_ID(bp) != CHIP_ID_5706_A0) && | ||||
| 		(CHIP_ID(bp) != CHIP_ID_5706_A1) && | ||||
| 		!disable_msi) { | ||||
| 
 | ||||
| 	if ((bp->flags & MSI_CAP_FLAG) && !disable_msi) { | ||||
| 		if (pci_enable_msi(bp->pdev) == 0) { | ||||
| 			bp->flags |= USING_MSI_FLAG; | ||||
| 			rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name, | ||||
| 					dev); | ||||
| 		} | ||||
| 		else { | ||||
| 			rc = request_irq(bp->pdev->irq, bnx2_interrupt, | ||||
| 					IRQF_SHARED, dev->name, dev); | ||||
| 			if (CHIP_NUM(bp) == CHIP_NUM_5709) | ||||
| 				bp->flags |= ONE_SHOT_MSI_FLAG; | ||||
| 		} | ||||
| 	} | ||||
| 	else { | ||||
| 		rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED, | ||||
| 				dev->name, dev); | ||||
| 	} | ||||
| 	rc = bnx2_request_irq(bp); | ||||
| 
 | ||||
| 	if (rc) { | ||||
| 		bnx2_free_mem(bp); | ||||
| 		return rc; | ||||
|  | @ -4652,11 +4696,7 @@ bnx2_open(struct net_device *dev) | |||
| 	rc = bnx2_init_nic(bp); | ||||
| 
 | ||||
| 	if (rc) { | ||||
| 		free_irq(bp->pdev->irq, dev); | ||||
| 		if (bp->flags & USING_MSI_FLAG) { | ||||
| 			pci_disable_msi(bp->pdev); | ||||
| 			bp->flags &= ~USING_MSI_FLAG; | ||||
| 		} | ||||
| 		bnx2_free_irq(bp); | ||||
| 		bnx2_free_skbs(bp); | ||||
| 		bnx2_free_mem(bp); | ||||
| 		return rc; | ||||
|  | @ -4680,16 +4720,13 @@ bnx2_open(struct net_device *dev) | |||
| 			       bp->dev->name); | ||||
| 
 | ||||
| 			bnx2_disable_int(bp); | ||||
| 			free_irq(bp->pdev->irq, dev); | ||||
| 			pci_disable_msi(bp->pdev); | ||||
| 			bp->flags &= ~USING_MSI_FLAG; | ||||
| 			bnx2_free_irq(bp); | ||||
| 
 | ||||
| 			rc = bnx2_init_nic(bp); | ||||
| 
 | ||||
| 			if (!rc) { | ||||
| 				rc = request_irq(bp->pdev->irq, bnx2_interrupt, | ||||
| 					IRQF_SHARED, dev->name, dev); | ||||
| 			} | ||||
| 			if (!rc) | ||||
| 				rc = bnx2_request_irq(bp); | ||||
| 
 | ||||
| 			if (rc) { | ||||
| 				bnx2_free_skbs(bp); | ||||
| 				bnx2_free_mem(bp); | ||||
|  | @ -4927,11 +4964,7 @@ bnx2_close(struct net_device *dev) | |||
| 	else | ||||
| 		reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL; | ||||
| 	bnx2_reset_chip(bp, reset_code); | ||||
| 	free_irq(bp->pdev->irq, dev); | ||||
| 	if (bp->flags & USING_MSI_FLAG) { | ||||
| 		pci_disable_msi(bp->pdev); | ||||
| 		bp->flags &= ~USING_MSI_FLAG; | ||||
| 	} | ||||
| 	bnx2_free_irq(bp); | ||||
| 	bnx2_free_skbs(bp); | ||||
| 	bnx2_free_mem(bp); | ||||
| 	bp->link_up = 0; | ||||
|  | @ -6095,6 +6128,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) { | ||||
| 		if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) | ||||
| 			bp->flags |= MSI_CAP_FLAG; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 5708 cannot support DMA addresses > 40-bit.  */ | ||||
| 	if (CHIP_NUM(bp) == CHIP_NUM_5708) | ||||
| 		persist_dma_mask = dma_mask = DMA_40BIT_MASK; | ||||
|  |  | |||
|  | @ -6468,12 +6468,14 @@ struct bnx2 { | |||
| 	u32 			last_status_idx; | ||||
| 
 | ||||
| 	u32			flags; | ||||
| #define PCIX_FLAG			1 | ||||
| #define PCI_32BIT_FLAG			2 | ||||
| #define ONE_TDMA_FLAG			4	/* no longer used */ | ||||
| #define NO_WOL_FLAG			8 | ||||
| #define USING_MSI_FLAG			0x20 | ||||
| #define ASF_ENABLE_FLAG			0x40 | ||||
| #define PCIX_FLAG			0x00000001 | ||||
| #define PCI_32BIT_FLAG			0x00000002 | ||||
| #define ONE_TDMA_FLAG			0x00000004	/* no longer used */ | ||||
| #define NO_WOL_FLAG			0x00000008 | ||||
| #define USING_MSI_FLAG			0x00000020 | ||||
| #define ASF_ENABLE_FLAG			0x00000040 | ||||
| #define MSI_CAP_FLAG			0x00000080 | ||||
| #define ONE_SHOT_MSI_FLAG		0x00000100 | ||||
| 
 | ||||
| 	/* Put tx producer and consumer fields in separate cache lines. */ | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Michael Chan
						Michael Chan