Re: [PATCH 3/7] pciehp: poll cmd completion if hotplug interrupt is disabled

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

 



On Tue, 27 May 2008 19:05:26 +0900
Kenji Kaneshige <kaneshige.kenji@xxxxxxxxxxxxxx> wrote:

> Fix improper long wait for command completion in pciehp probing.
> 
> As described in PCI Express specification, software notification is
> not generated if the command that occurs as a result of a write to the
> Slot Control register that disables software notification of command
> completed events. Since pciehp driver doesn't take it into account,
> such command is issued in pciehp probing, and it causes improper long
> wait for command completion.
> 
> This patch changes the pciehp driver to take such command into
> account.
> 
> ...
>
> -static inline int pcie_wait_cmd(struct controller *ctrl)
> +static inline int pcie_poll_cmd(struct controller *ctrl)
> +{
> +	u16 slot_status;
> +	int timeout = 1000;
> +
> +	if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status))
> +		if (slot_status & CMD_COMPLETED)
> +			goto completed;
> +	for (timeout = 1000; timeout > 0; timeout -= 100) {
> +		msleep(100);
> +		if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status))
> +			if (slot_status & CMD_COMPLETED)
> +				goto completed;
> +	}
> +	return 0;	/* timeout */
> +
> +completed:
> +	pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
> +	return timeout;
> +}

This looks a bit ungainly.  Couldn't we do something along the lines of

static inline int pcie_poll_cmd(struct controller *ctrl)
{
	int timeout = 1000;

	while (timeout > 0) {
		u16 slot_status;
		if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) {
 			if (slot_status & CMD_COMPLETED) {
				pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
				break;
			}
		}
		msleep(100);
		timeout -= 100;
	}
	return timeout;
}

Also, I wonder if we wold get further improvements by polling at 1kHz
rather than at 10Hz.  Or maybe at 100Hz, as 1kHz might be problematic
on HZ=100 kernels.

> +static inline int pcie_wait_cmd(struct controller *ctrl, int poll)

These functions are too large to be inlined.

>  {
>  	int retval = 0;
>  	unsigned int msecs = pciehp_poll_mode ? 2500 : 1000;
>  	unsigned long timeout = msecs_to_jiffies(msecs);
>  	int rc;
>  
> -	rc = wait_event_interruptible_timeout(ctrl->queue,
> +	if (poll)
> +		rc = pcie_poll_cmd(ctrl);
> +	else
> +		rc = wait_event_interruptible_timeout(ctrl->queue,
>  					      !ctrl->cmd_busy, timeout);
>  	if (!rc)
>  		dbg("Command not completed in 1000 msec\n");
> @@ -331,8 +355,18 @@ static int pcie_write_cmd(struct control
>  	/*
>  	 * Wait for command completion.
>  	 */
> -	if (!retval && !ctrl->no_cmd_complete)
> -		retval = pcie_wait_cmd(ctrl);
> +	if (!retval && !ctrl->no_cmd_complete) {
> +		int poll = 0;
> +		/*
> +		 * if hotplug interrupt is not enabled or command
> +		 * completed interrupt is not enabled, we need to poll
> +		 * command completed event.
> +		 */
> +		if (!(slot_ctrl & HP_INTR_ENABLE) ||
> +		    !(slot_ctrl & CMD_CMPL_INTR_ENABLE))
> +			poll = 1;
> +                retval = pcie_wait_cmd(ctrl, poll);
> +	}
>   out:
>  	mutex_unlock(&ctrl->ctrl_lock);
>  	return retval;

--
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