Re: [PATCH v3] PCI: vmd: Issue secondary bus reset and vmd domain window reset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 7/28/2021 4:21 PM, Derrick, Jonathan wrote:
> Hey Nirmal
>
> On 7/28/2021 3:46 PM, Nirmal Patel wrote:
>> In order to properly re-initialize the VMD domain during repetitive driver
>> attachment or reboot tests, ensure that the VMD root ports are
>> re-initialized to a blank state that can be re-enumerated appropriately
>> by the PCI core. This is performed by re-initializing all of the bridge
>> windows to ensure that PCI core enumeration does not detect potentially
>> invalid bridge windows and misinterpret them as firmware-assigned windows,
>> when they simply may be invalid bridge window information from a previous
>> boot.
>>
>> During VT-d passthrough repetitive reboot tests, it was determined that
>> the VMD domain needed to be reset in order to allow downstream devices
>> to reinitialize properly. This is done using setting secondary bus
>> reset bit of each of the VMD root port and will propagate reset through
>> downstream bridges.
> Can we better combine these two paragraphs?
I will try to create better summary.
>
>
>> v2->v3: Combining two functions into one, Remove redundant definations
>>         and Formatting fixes
> Below the dashes please
Ack
>
>> Signed-off-by: Nirmal Patel <nirmal.patel@xxxxxxxxxxxxxxx>
>> Reviewed-by: Jon Derrick <jonathan.derrick@xxxxxxxxx>
> Not yet :)
Sorry about that. will fix it.
>
>> ---
>>  drivers/pci/controller/vmd.c | 63 ++++++++++++++++++++++++++++++++++++
>>  1 file changed, 63 insertions(+)
>>
>> diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
>> index e3fcdfec58b3..e2c0de700e61 100644
>> --- a/drivers/pci/controller/vmd.c
>> +++ b/drivers/pci/controller/vmd.c
>> @@ -15,6 +15,9 @@
>>  #include <linux/srcu.h>
>>  #include <linux/rculist.h>
>>  #include <linux/rcupdate.h>
>> +#include <linux/delay.h>
>> +#include <linux/pci_regs.h>
>> +#include <linux/pci_ids.h>
> Do you need to include pci_regs.h and pci_ids.h?
Works without including header files too.
>
>
>>  
>>  #include <asm/irqdomain.h>
>>  #include <asm/device.h>
>> @@ -447,6 +450,64 @@ static struct pci_ops vmd_ops = {
>>  	.write		= vmd_pci_write,
>>  };
>>  
>> +static void vmd_domain_reset(struct vmd_dev *vmd)
>> +{
>> +	char __iomem *base;
>> +	char __iomem *addr;
>> +	u16 ctl;
>> +	int dev_seq;
>> +	int max_devs = 32;
>> +	int max_buses = resource_size(&vmd->resources[0]);
>> +	int bus_seq;
>> +	u8 functions;
>> +	u8 fn_seq;
>> +	u8 hdr_type;
>> +
>> +	for(bus_seq = 0; bus_seq < max_buses; bus_seq++) {
>> +		for (dev_seq = 0; dev_seq < max_devs; dev_seq++) {
> No need for max_devs - just open-code '32'
Ack.
>
>
>> +			base = vmd->cfgbar
>> +					+ PCIE_ECAM_OFFSET(bus_seq,
>> +					   PCI_DEVFN(dev_seq, 0), PCI_VENDOR_ID);
> How about:
> 			base = vmd->cfgbar + PCIE_ECAM_OFFSET(bus_seq,
> 				 PCI_DEVFN(dev_seq, 0), PCI_VENDOR_ID);
Ack.
>
>
>> +
>> +			if (readw(base) != PCI_VENDOR_ID_INTEL)
>> +				continue;
> Now that it's iterating all of the bridges in all of the buses, should
> it be limited to Intel devices?
Ack. I will remove it. It shouldn't have significant performance hit.
>
>
>> +
>> +			hdr_type = readb(base + PCI_HEADER_TYPE) & PCI_HEADER_TYPE_MASK;
>> +			if (hdr_type != PCI_HEADER_TYPE_BRIDGE)
>> +				continue;
>> +
>> +			functions = !!(hdr_type & 0x80) ? 8 : 1;
>> +			for (fn_seq = 0; fn_seq < functions; fn_seq++)
>> +			{
>> +				addr = vmd->cfgbar
>> +						+ PCIE_ECAM_OFFSET(0x0,
>> +						   PCI_DEVFN(dev_seq, fn_seq), PCI_VENDOR_ID);
> Can you do the same as above here? Putting PCIE_ECAM_OFFSET on the same
> line as vmd->cfgbar? Also could you change bus from 0x0 to 0?
Yes.
>
>
>> +				if (readw(addr) != PCI_VENDOR_ID_INTEL)
>> +					continue;
> Is this necessary?
Ack.
>
>
>> +
>> +				memset_io((vmd->cfgbar +
>> +				 PCIE_ECAM_OFFSET(0x0,PCI_DEVFN(dev_seq, fn_seq),PCI_IO_BASE)),
> Needs a space after the commas, and please use 0 instead of 0x0.
Ack.
>
>
>> +				 0, PCI_ROM_ADDRESS1 - PCI_IO_BASE);
>> +			}
>> +
>> +			if (readw(base + PCI_CLASS_DEVICE) != PCI_CLASS_BRIDGE_PCI)
>> +				continue;
>> +
>> +			/* pci_reset_secondary_bus() */
>> +			ctl = readw(base + PCI_BRIDGE_CONTROL);
>> +			ctl |= PCI_BRIDGE_CTL_BUS_RESET;
>> +			writew(ctl, base + PCI_BRIDGE_CONTROL);
>> +			readw(base + PCI_BRIDGE_CONTROL);
>> +			msleep(2);
>> +
>> +			ctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
>> +			writew(ctl, base + PCI_BRIDGE_CONTROL);
>> +			readw(base + PCI_BRIDGE_CONTROL);
>> +		}
>> +	}
>> +	ssleep(1);
>> +}
>> +
>>  static void vmd_attach_resources(struct vmd_dev *vmd)
>>  {
>>  	vmd->dev->resource[VMD_MEMBAR1].child = &vmd->resources[1];
>> @@ -747,6 +808,8 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
>>  	if (vmd->irq_domain)
>>  		dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
>>  
>> +	vmd_domain_reset(vmd);
>> +
> I'd remove this blank line
Ack.
>
>>  	pci_scan_child_bus(vmd->bus);
>>  	pci_assign_unassigned_bus_resources(vmd->bus);
>>  
>>




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux