public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
  • * [PATCH 1/3] pci: VPD access timeout increase
           [not found] ` <20080828111323.GI7908@solarflare.com>
           [not found]   ` <20080903155316.1a0a5698@extreme>
    @ 2008-09-03 22:57   ` Stephen Hemminger
      2008-09-04 12:52     ` Matthew Wilcox
      2008-09-04 16:07     ` [PATCH] Return value from schedule() Matthew Wilcox
      1 sibling, 2 replies; 16+ messages in thread
    From: Stephen Hemminger @ 2008-09-03 22:57 UTC (permalink / raw)
      To: Ben Hutchings, Jesse Barnes; +Cc: linux-kernel, netdev, linux-pci
    
    Accessing the VPD area can take a long time. There are comments in the
    SysKonnect vendor driver that it can take up to 25ms.  The existing vpd
    access code fails consistently on my hardware.
    
    Change the access routines to:
      * use a mutex rather than spinning with IRQ's disabled and lock held
      * have a longer timeout
      * call schedule while spinning to provide some responsivness
    
    Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
    
    
    --- a/drivers/pci/access.c	2008-09-02 10:42:12.000000000 -0700
    +++ b/drivers/pci/access.c	2008-09-03 08:47:49.000000000 -0700
    @@ -133,7 +133,7 @@ PCI_USER_WRITE_CONFIG(dword, u32)
     
     struct pci_vpd_pci22 {
     	struct pci_vpd base;
    -	spinlock_t lock; /* controls access to hardware and the flags */
    +	struct mutex lock;
     	u8	cap;
     	bool	busy;
     	bool	flag; /* value of F bit to wait for */
    @@ -144,29 +144,30 @@ static int pci_vpd_pci22_wait(struct pci
     {
     	struct pci_vpd_pci22 *vpd =
     		container_of(dev->vpd, struct pci_vpd_pci22, base);
    -	u16 flag, status;
    -	int wait;
    +	u16 flag = vpd->flag ? PCI_VPD_ADDR_F : 0;
    +	unsigned long timeout = jiffies + (vpd->flag ? HZ/50 : HZ/10);
    +	u16 status;
     	int ret;
     
     	if (!vpd->busy)
     		return 0;
     
    -	flag = vpd->flag ? PCI_VPD_ADDR_F : 0;
    -	wait = vpd->flag ? 10 : 1000; /* read: 100 us; write: 10 ms */
    -	for (;;) {
    -		ret = pci_user_read_config_word(dev,
    -						vpd->cap + PCI_VPD_ADDR,
    -						&status);
    -		if (ret < 0)
    -			return ret;
    +	while ( (ret = pci_user_read_config_word(dev,
    +						 vpd->cap + PCI_VPD_ADDR,
    +						 &status)) == 0) {
     		if ((status & PCI_VPD_ADDR_F) == flag) {
     			vpd->busy = false;
    -			return 0;
    +			break;
     		}
    -		if (wait-- == 0)
    +
    +		if (time_after(jiffies, timeout))
     			return -ETIMEDOUT;
    -		udelay(10);
    +		if (signal_pending(current))
    +			return -EINTR;
    +		schedule();
     	}
    +
    +	return ret;
     }
     
     static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
    @@ -183,7 +184,7 @@ static int pci_vpd_pci22_read(struct pci
     	if (size == 0)
     		return 0;
     
    -	spin_lock_irq(&vpd->lock);
    +	mutex_lock(&vpd->lock);
     	ret = pci_vpd_pci22_wait(dev);
     	if (ret < 0)
     		goto out;
    @@ -199,7 +200,7 @@ static int pci_vpd_pci22_read(struct pci
     	ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA,
     					 &val);
     out:
    -	spin_unlock_irq(&vpd->lock);
    +	mutex_unlock(&vpd->lock);
     	if (ret < 0)
     		return ret;
     
    @@ -231,7 +232,7 @@ static int pci_vpd_pci22_write(struct pc
     	val |= ((u8) *buf++) << 16;
     	val |= ((u32)(u8) *buf++) << 24;
     
    -	spin_lock_irq(&vpd->lock);
    +	mutex_lock(&vpd->lock);
     	ret = pci_vpd_pci22_wait(dev);
     	if (ret < 0)
     		goto out;
    @@ -247,7 +248,7 @@ static int pci_vpd_pci22_write(struct pc
     	vpd->flag = 0;
     	ret = pci_vpd_pci22_wait(dev);
     out:
    -	spin_unlock_irq(&vpd->lock);
    +	mutex_unlock(&vpd->lock);
     	if (ret < 0)
     		return ret;
     
    @@ -279,7 +280,7 @@ int pci_vpd_pci22_init(struct pci_dev *d
     
     	vpd->base.len = PCI_VPD_PCI22_SIZE;
     	vpd->base.ops = &pci_vpd_pci22_ops;
    -	spin_lock_init(&vpd->lock);
    +	mutex_init(&vpd->lock);
     	vpd->cap = cap;
     	vpd->busy = false;
     	dev->vpd = &vpd->base;
    
    ^ permalink raw reply	[flat|nested] 16+ messages in thread

  • end of thread, other threads:[~2008-09-09  4:37 UTC | newest]
    
    Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
    -- links below jump to the message on this page --
         [not found] <20080827204626.4b65862f@extreme>
         [not found] ` <20080828111323.GI7908@solarflare.com>
         [not found]   ` <20080903155316.1a0a5698@extreme>
    2008-09-03 22:57     ` [PATCH 2/3] pci: revise VPD access interface Stephen Hemminger
    2008-09-03 23:00       ` [PATCH 3/3] sky2: use pci_read_vpd to read info during boot Stephen Hemminger
    2008-09-04  7:36         ` Jeff Garzik
    2008-09-09  4:36           ` Jesse Barnes
    2008-09-03 22:57   ` [PATCH 1/3] pci: VPD access timeout increase Stephen Hemminger
    2008-09-04 12:52     ` Matthew Wilcox
    2008-09-04 14:19       ` Ben Hutchings
    2008-09-04 16:10         ` Matthew Wilcox
    2008-09-04 16:32         ` Stephen Hemminger
    2008-09-04 16:07     ` [PATCH] Return value from schedule() Matthew Wilcox
    2008-09-04 16:14       ` Ingo Molnar
    2008-09-04 16:21         ` Matthew Wilcox
    2008-09-04 17:30           ` Arjan van de Ven
    2008-09-04 17:48             ` Matthew Wilcox
    2008-09-04 19:05               ` Stephen Hemminger
    2008-09-05  7:40                 ` Peter Zijlstra
    

    This is a public inbox, see mirroring instructions
    for how to clone and mirror all data and code used for this inbox