Re: [PATCH 4/4] PCI: Extend pci_reset_function() to support PCI Advanced Feature

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

 



On Thursday 30 October 2008 21:42:51 Matthew Wilcox wrote:
> On Thu, Oct 30, 2008 at 01:32:17PM +0800, Sheng Yang wrote:
> > Some PCI device implemented PCI Advanced Feature, which is also support
> > Function Level Reset(FLR).
>
> I think patches 3 and 4 go off in the wrong direction.  Rather than have
> one megafunction that knows how to reset all devices, we should have
> something more like this:
>
> int pci_execute_reset_function(pdev)
> {
> 	int res;
>
> 	res = pcie_flr(pdev);
> 	if (res != -ENOTTY)
> 		return res;
>
> 	res = pci_af_flr(pdev);
> 	if (res != -ENOTTY)
> 		return res;
>
> 	if (pdev->driver && pdev->driver->reset)
> 		res = pdev->driver->reset(pdev);
>
> 	return res;
> }
>
> (Assuming we add a reset op to the pci_driver function).
>
> It's a bit tricky in that we'd like to test early if a device supports
> reset or not.

Thanks for reviewing!

Yes, I like this approach much better. But for pci_reset_function(), I think 
we still need a capability judgment. So how about like this?

int pci_execute_reset_function(pdev)
{
	int res;

 	res = __pci_check_reset_function_cap(pdev);

	switch (res) {
	case pcie_flr:
			res = pcie_flr(pdev);
			break;
	case pci_af_flr:
			res = pci_af_flr(pdev);
			break;
	case reset_op:
			if (pdev->driver && pdev->driver->reset)
				res = pdev->driver->reset(pdev);
			else
				res = -ENOTTY;
			break;
	default:
			res = -ENOTTY;
			break;
	}
	return res;
}

Of course the capability check is a little duplicate, but I think it's 
affordable.
-- 
regards
Yang, Sheng

>
> > Signed-off-by: Sheng Yang <sheng@xxxxxxxxxxxxxxx>
> > ---
> >  drivers/pci/pci.c |   38 ++++++++++++++++++++++++++++++++++++--
> >  1 files changed, 36 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index 2077aee..c432473 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -1752,6 +1752,7 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
> >  #endif
> >
> >  #define PCI_RESET_FUNC_CAP_PCIE_FLR	    0
> > +#define PCI_RESET_FUNC_CAP_PCI_AF_FLR	    1
> >  static int __pci_check_reset_function_cap(struct pci_dev *dev)
> >  {
> >  	int cappos;
> > @@ -1764,6 +1765,13 @@ static int __pci_check_reset_function_cap(struct
> > pci_dev *dev) return PCI_RESET_FUNC_CAP_PCIE_FLR;
> >  	}
> >
> > +	cappos = pci_find_capability(dev, PCI_CAP_ID_AF);
> > +	if (cappos) {
> > +		pci_read_config_byte(dev, cappos + PCI_AF_CAP, (u8 *)&cap);
> > +		if ((cap & PCI_AF_CAP_TP) && (cap & PCI_AF_CAP_FLR))
> > +			return PCI_RESET_FUNC_CAP_PCI_AF_FLR;
> > +	}
> > +
> >  	return -ENOTTY;
> >  }
> >
> > @@ -1798,7 +1806,8 @@ int pci_execute_reset_function(struct pci_dev *dev)
> >  	r = 0;
> >  	pci_block_user_cfg_access(dev);
> >
> > -	if (reset_cap == PCI_RESET_FUNC_CAP_PCIE_FLR) {
> > +	switch (reset_cap) {
> > +	case PCI_RESET_FUNC_CAP_PCIE_FLR:
> >  		/* Wait for Transaction Pending bit clean */
> >  		msleep(100);
> >  		cappos = pci_find_capability(dev, PCI_CAP_ID_EXP);
> > @@ -1816,8 +1825,33 @@ int pci_execute_reset_function(struct pci_dev
> > *dev) pci_write_config_word(dev, cappos + PCI_EXP_DEVCTL,
> >  				PCI_EXP_DEVCTL_BCR_FLR);
> >  		mdelay(100);
> > -	} else
> > +		break;
> > +
> > +	case PCI_RESET_FUNC_CAP_PCI_AF_FLR:
> > +		/* Wait for Transaction Pending bit clean */
> > +		msleep(100);
> > +		cappos = pci_find_capability(dev, PCI_CAP_ID_AF);
> > +		pci_read_config_byte(dev, cappos + PCI_AF_STATUS,
> > +				    (u8 *)&status);
> > +		if (status & PCI_AF_STATUS_TP) {
> > +			dev_info(&dev->dev, "Busy after 100ms while trying to"
> > +					" reset; sleeping for 1 second\n");
> > +			ssleep(1);
> > +			pci_read_config_byte(dev,
> > +					cappos + PCI_AF_STATUS, (u8 *)&status);
> > +			if (status & PCI_AF_STATUS_TP)
> > +				dev_info(&dev->dev, "Still busy after 1s; "
> > +					"proceeding with reset anyway\n");
> > +		}
> > +		pci_write_config_byte(dev, cappos + PCI_AF_CTRL,
> > +				PCI_AF_CTRL_FLR);
> > +		mdelay(100);
> > +		break;
> > +
> > +	default:
> >  		r = -ENOTTY;
> > +		break;
> > +	}
> >
> >  	pci_unblock_user_cfg_access(dev);
> >  	return r;
> > --
> > 1.5.4.5
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[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