mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	RDMA/qedr: properly check atomic capabilities
After checking the path upwards towards root complex, actualy check root complex atomic_req capability, and not our own NIC. Verify that the PCIe device control register's atomic egress block is cleared in the path. Verify that the PCIe version is at least 2. Signed-off-by: Ram Amrani <Ram.Amrani@cavium.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
		
							parent
							
								
									08c4cf51e3
								
							
						
					
					
						commit
						f92faaba11
					
				
					 2 changed files with 46 additions and 30 deletions
				
			
		| 
						 | 
					@ -340,43 +340,58 @@ static void qedr_remove_sysfiles(struct qedr_dev *dev)
 | 
				
			||||||
static void qedr_pci_set_atomic(struct qedr_dev *dev, struct pci_dev *pdev)
 | 
					static void qedr_pci_set_atomic(struct qedr_dev *dev, struct pci_dev *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pci_dev *bridge;
 | 
						struct pci_dev *bridge;
 | 
				
			||||||
	u32 val;
 | 
						u32 ctl2, cap2;
 | 
				
			||||||
 | 
						u16 flags;
 | 
				
			||||||
	dev->atomic_cap = IB_ATOMIC_NONE;
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bridge = pdev->bus->self;
 | 
						bridge = pdev->bus->self;
 | 
				
			||||||
	if (!bridge)
 | 
						if (!bridge)
 | 
				
			||||||
		return;
 | 
							goto disable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check whether we are connected directly or via a switch */
 | 
						/* Check atomic routing support all the way to root complex */
 | 
				
			||||||
	while (bridge && bridge->bus->parent) {
 | 
						while (bridge->bus->parent) {
 | 
				
			||||||
		DP_DEBUG(dev, QEDR_MSG_INIT,
 | 
							rc = pcie_capability_read_word(bridge, PCI_EXP_FLAGS, &flags);
 | 
				
			||||||
			 "Device is not connected directly to root. bridge->bus->number=%d primary=%d\n",
 | 
							if (rc || ((flags & PCI_EXP_FLAGS_VERS) < 2))
 | 
				
			||||||
			 bridge->bus->number, bridge->bus->primary);
 | 
								goto disable;
 | 
				
			||||||
		/* Need to check Atomic Op Routing Supported all the way to
 | 
					
 | 
				
			||||||
		 * root complex.
 | 
							rc = pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap2);
 | 
				
			||||||
		 */
 | 
							if (rc)
 | 
				
			||||||
		pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &val);
 | 
								goto disable;
 | 
				
			||||||
		if (!(val & PCI_EXP_DEVCAP2_ATOMIC_ROUTE)) {
 | 
					
 | 
				
			||||||
			pcie_capability_clear_word(pdev,
 | 
							rc = pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl2);
 | 
				
			||||||
						   PCI_EXP_DEVCTL2,
 | 
							if (rc)
 | 
				
			||||||
						   PCI_EXP_DEVCTL2_ATOMIC_REQ);
 | 
								goto disable;
 | 
				
			||||||
			return;
 | 
					
 | 
				
			||||||
		}
 | 
							if (!(cap2 & PCI_EXP_DEVCAP2_ATOMIC_ROUTE) ||
 | 
				
			||||||
 | 
							    (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK))
 | 
				
			||||||
 | 
								goto disable;
 | 
				
			||||||
		bridge = bridge->bus->parent->self;
 | 
							bridge = bridge->bus->parent->self;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	bridge = pdev->bus->self;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* according to bridge capability */
 | 
						rc = pcie_capability_read_word(bridge, PCI_EXP_FLAGS, &flags);
 | 
				
			||||||
	pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &val);
 | 
						if (rc || ((flags & PCI_EXP_FLAGS_VERS) < 2))
 | 
				
			||||||
	if (val & PCI_EXP_DEVCAP2_ATOMIC_COMP64) {
 | 
							goto disable;
 | 
				
			||||||
		pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2,
 | 
					
 | 
				
			||||||
					 PCI_EXP_DEVCTL2_ATOMIC_REQ);
 | 
						rc = pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap2);
 | 
				
			||||||
		dev->atomic_cap = IB_ATOMIC_GLOB;
 | 
						if (rc || !(cap2 & PCI_EXP_DEVCAP2_ATOMIC_COMP64))
 | 
				
			||||||
	} else {
 | 
							goto disable;
 | 
				
			||||||
		pcie_capability_clear_word(pdev, PCI_EXP_DEVCTL2,
 | 
					
 | 
				
			||||||
					   PCI_EXP_DEVCTL2_ATOMIC_REQ);
 | 
						/* Set atomic operations */
 | 
				
			||||||
	}
 | 
						pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2,
 | 
				
			||||||
 | 
									 PCI_EXP_DEVCTL2_ATOMIC_REQ);
 | 
				
			||||||
 | 
						dev->atomic_cap = IB_ATOMIC_GLOB;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DP_DEBUG(dev, QEDR_MSG_INIT, "Atomic capability enabled\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					disable:
 | 
				
			||||||
 | 
						pcie_capability_clear_word(pdev, PCI_EXP_DEVCTL2,
 | 
				
			||||||
 | 
									   PCI_EXP_DEVCTL2_ATOMIC_REQ);
 | 
				
			||||||
 | 
						dev->atomic_cap = IB_ATOMIC_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DP_DEBUG(dev, QEDR_MSG_INIT, "Atomic capability disabled\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct qed_rdma_ops *qed_ops;
 | 
					static const struct qed_rdma_ops *qed_ops;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -630,6 +630,7 @@
 | 
				
			||||||
#define  PCI_EXP_DEVCTL2_COMP_TIMEOUT	0x000f	/* Completion Timeout Value */
 | 
					#define  PCI_EXP_DEVCTL2_COMP_TIMEOUT	0x000f	/* Completion Timeout Value */
 | 
				
			||||||
#define  PCI_EXP_DEVCTL2_ARI		0x0020	/* Alternative Routing-ID */
 | 
					#define  PCI_EXP_DEVCTL2_ARI		0x0020	/* Alternative Routing-ID */
 | 
				
			||||||
#define PCI_EXP_DEVCTL2_ATOMIC_REQ	0x0040	/* Set Atomic requests */
 | 
					#define PCI_EXP_DEVCTL2_ATOMIC_REQ	0x0040	/* Set Atomic requests */
 | 
				
			||||||
 | 
					#define PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK 0x0080 /* Block atomic egress */
 | 
				
			||||||
#define  PCI_EXP_DEVCTL2_IDO_REQ_EN	0x0100	/* Allow IDO for requests */
 | 
					#define  PCI_EXP_DEVCTL2_IDO_REQ_EN	0x0100	/* Allow IDO for requests */
 | 
				
			||||||
#define  PCI_EXP_DEVCTL2_IDO_CMP_EN	0x0200	/* Allow IDO for completions */
 | 
					#define  PCI_EXP_DEVCTL2_IDO_CMP_EN	0x0200	/* Allow IDO for completions */
 | 
				
			||||||
#define  PCI_EXP_DEVCTL2_LTR_EN		0x0400	/* Enable LTR mechanism */
 | 
					#define  PCI_EXP_DEVCTL2_LTR_EN		0x0400	/* Enable LTR mechanism */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue