Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44ef4cef authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Greg Kroah-Hartman
Browse files

pciehp: cleanup wait command completion



This patch cleans up the code to wait for command completion.

Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarKristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 75e13178
Loading
Loading
Loading
Loading
+0 −18
Original line number Original line Diff line number Diff line
@@ -173,24 +173,6 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
	return NULL;
	return NULL;
}
}


static inline int wait_for_ctrl_irq(struct controller *ctrl)
{
	DECLARE_WAITQUEUE(wait, current);

	add_wait_queue(&ctrl->queue, &wait);
	if (!pciehp_poll_mode)
		/* Sleep for up to 1 second */
		msleep_interruptible(1000);
	else
		msleep_interruptible(2500);
	
	remove_wait_queue(&ctrl->queue, &wait);
	if (signal_pending(current))
		return -EINTR;

	return 0;
}

struct hpc_ops {
struct hpc_ops {
	int (*power_on_slot)(struct slot *slot);
	int (*power_on_slot)(struct slot *slot);
	int (*power_off_slot)(struct slot *slot);
	int (*power_off_slot)(struct slot *slot);
+1 −13
Original line number Original line Diff line number Diff line
@@ -374,25 +374,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
		pciehp_ctrl_list = ctrl;
		pciehp_ctrl_list = ctrl;
	}
	}


	/* Wait for exclusive access to hardware */
	mutex_lock(&ctrl->ctrl_lock);

	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
	
	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
		if (rc) {
		if (rc)
			/* Done with exclusive hardware access */
			mutex_unlock(&ctrl->ctrl_lock);
			goto err_out_free_ctrl_slot;
			goto err_out_free_ctrl_slot;
		} else
			/* Wait for the command to complete */
			wait_for_ctrl_irq (ctrl);
	}
	}


	/* Done with exclusive hardware access */
	mutex_unlock(&ctrl->ctrl_lock);

	return 0;
	return 0;


err_out_free_ctrl_slot:
err_out_free_ctrl_slot:
+48 −157
Original line number Original line Diff line number Diff line
@@ -229,35 +229,25 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)


static void set_slot_off(struct controller *ctrl, struct slot * pslot)
static void set_slot_off(struct controller *ctrl, struct slot * pslot)
{
{
	/* Wait for exclusive access to hardware */
	mutex_lock(&ctrl->ctrl_lock);

	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
	if (POWER_CTRL(ctrl->ctrlcap)) {
	if (POWER_CTRL(ctrl->ctrlcap)) {
		if (pslot->hpc_ops->power_off_slot(pslot)) {   
		if (pslot->hpc_ops->power_off_slot(pslot)) {   
			err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
			err("%s: Issue of Slot Power Off command failed\n",
			mutex_unlock(&ctrl->ctrl_lock);
			    __FUNCTION__);
			return;
			return;
		}
		}
		wait_for_ctrl_irq (ctrl);
	}
	}


	if (PWR_LED(ctrl->ctrlcap)) {
	if (PWR_LED(ctrl->ctrlcap))
		pslot->hpc_ops->green_led_off(pslot);   
		pslot->hpc_ops->green_led_off(pslot);   
		wait_for_ctrl_irq (ctrl);
	}


	if (ATTN_LED(ctrl->ctrlcap)) {
	if (ATTN_LED(ctrl->ctrlcap)) {
		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
		if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
			err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
			err("%s: Issue of Set Attention Led command failed\n",
			mutex_unlock(&ctrl->ctrl_lock);
			    __FUNCTION__);
			return;
			return;
		}
		}
		wait_for_ctrl_irq (ctrl);
	}
	}

	/* Done with exclusive hardware access */
	mutex_unlock(&ctrl->ctrl_lock);
}
}


/**
/**
@@ -270,7 +260,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
static int board_added(struct slot *p_slot)
static int board_added(struct slot *p_slot)
{
{
	u8 hp_slot;
	u8 hp_slot;
	int rc = 0;
	int retval = 0;
	struct controller *ctrl = p_slot->ctrl;
	struct controller *ctrl = p_slot->ctrl;


	hp_slot = p_slot->device - ctrl->slot_device_offset;
	hp_slot = p_slot->device - ctrl->slot_device_offset;
@@ -279,51 +269,36 @@ static int board_added(struct slot *p_slot)
			__FUNCTION__, p_slot->device,
			__FUNCTION__, p_slot->device,
			ctrl->slot_device_offset, hp_slot);
			ctrl->slot_device_offset, hp_slot);


	/* Wait for exclusive access to hardware */
	mutex_lock(&ctrl->ctrl_lock);

	if (POWER_CTRL(ctrl->ctrlcap)) {
	if (POWER_CTRL(ctrl->ctrlcap)) {
		/* Power on slot */
		/* Power on slot */
		rc = p_slot->hpc_ops->power_on_slot(p_slot);
		retval = p_slot->hpc_ops->power_on_slot(p_slot);
		if (rc) {
		if (retval)
			mutex_unlock(&ctrl->ctrl_lock);
			return retval;
			return -1;
		}

		/* Wait for the command to complete */
		wait_for_ctrl_irq (ctrl);
	}
	}
	
	
	if (PWR_LED(ctrl->ctrlcap)) {
	if (PWR_LED(ctrl->ctrlcap))
		p_slot->hpc_ops->green_led_blink(p_slot);
		p_slot->hpc_ops->green_led_blink(p_slot);


		/* Wait for the command to complete */
		wait_for_ctrl_irq (ctrl);
	}

	/* Done with exclusive hardware access */
	mutex_unlock(&ctrl->ctrl_lock);

	/* Wait for ~1 second */
	/* Wait for ~1 second */
	wait_for_ctrl_irq (ctrl);
	msleep(1000);


	/* Check link training status */
	/* Check link training status */
	rc = p_slot->hpc_ops->check_lnk_status(ctrl);  
	retval = p_slot->hpc_ops->check_lnk_status(ctrl);
	if (rc) {
	if (retval) {
		err("%s: Failed to check link status\n", __FUNCTION__);
		err("%s: Failed to check link status\n", __FUNCTION__);
		set_slot_off(ctrl, p_slot);
		set_slot_off(ctrl, p_slot);
		return rc;
		return retval;
	}
	}


	/* Check for a power fault */
	/* Check for a power fault */
	if (p_slot->hpc_ops->query_power_fault(p_slot)) {
	if (p_slot->hpc_ops->query_power_fault(p_slot)) {
		dbg("%s: power fault detected\n", __FUNCTION__);
		dbg("%s: power fault detected\n", __FUNCTION__);
		rc = POWER_FAILURE;
		retval = POWER_FAILURE;
		goto err_exit;
		goto err_exit;
	}
	}


	rc = pciehp_configure_device(p_slot);
	retval = pciehp_configure_device(p_slot);
	if (rc) {
	if (retval) {
		err("Cannot add device 0x%x:%x\n", p_slot->bus,
		err("Cannot add device 0x%x:%x\n", p_slot->bus,
		    p_slot->device);
		    p_slot->device);
		goto err_exit;
		goto err_exit;
@@ -334,26 +309,16 @@ static int board_added(struct slot *p_slot)
	 */
	 */
	if (pcie_mch_quirk)
	if (pcie_mch_quirk)
		pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
		pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
	if (PWR_LED(ctrl->ctrlcap)) {
	if (PWR_LED(ctrl->ctrlcap))
		/* Wait for exclusive access to hardware */
  		mutex_lock(&ctrl->ctrl_lock);

  		p_slot->hpc_ops->green_led_on(p_slot);
  		p_slot->hpc_ops->green_led_on(p_slot);


  		/* Wait for the command to complete */
  		wait_for_ctrl_irq (ctrl);
  	
  		/* Done with exclusive hardware access */
  		mutex_unlock(&ctrl->ctrl_lock);
  	}
	return 0;
	return 0;


err_exit:
err_exit:
	set_slot_off(ctrl, p_slot);
	set_slot_off(ctrl, p_slot);
	return -1;
	return retval;
}
}



/**
/**
 * remove_board - Turns off slot and LED's
 * remove_board - Turns off slot and LED's
 *
 *
@@ -362,45 +327,33 @@ static int remove_board(struct slot *p_slot)
{
{
	u8 device;
	u8 device;
	u8 hp_slot;
	u8 hp_slot;
	int rc;
	int retval = 0;
	struct controller *ctrl = p_slot->ctrl;
	struct controller *ctrl = p_slot->ctrl;


	if (pciehp_unconfigure_device(p_slot))
	retval = pciehp_unconfigure_device(p_slot);
		return 1;
	if (retval)
		return retval;


	device = p_slot->device;
	device = p_slot->device;

	hp_slot = p_slot->device - ctrl->slot_device_offset;
	hp_slot = p_slot->device - ctrl->slot_device_offset;
	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
	p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);


	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
	dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);


	/* Wait for exclusive access to hardware */
	mutex_lock(&ctrl->ctrl_lock);

	if (POWER_CTRL(ctrl->ctrlcap)) {
	if (POWER_CTRL(ctrl->ctrlcap)) {
		/* power off slot */
		/* power off slot */
		rc = p_slot->hpc_ops->power_off_slot(p_slot);
		retval = p_slot->hpc_ops->power_off_slot(p_slot);
		if (rc) {
		if (retval) {
			err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
			err("%s: Issue of Slot Disable command failed\n",
			mutex_unlock(&ctrl->ctrl_lock);
			    __FUNCTION__);
			return rc;
			return retval;
		}
		}
		/* Wait for the command to complete */
		wait_for_ctrl_irq (ctrl);
	}
	}


	if (PWR_LED(ctrl->ctrlcap)) {
	if (PWR_LED(ctrl->ctrlcap))
		/* turn off Green LED */
		/* turn off Green LED */
		p_slot->hpc_ops->green_led_off(p_slot);
		p_slot->hpc_ops->green_led_off(p_slot);


		/* Wait for the command to complete */
		wait_for_ctrl_irq (ctrl);
	}

	/* Done with exclusive hardware access */
	mutex_unlock(&ctrl->ctrl_lock);

	return 0;
	return 0;
}
}


@@ -444,18 +397,10 @@ static void pciehp_pushbutton_thread(unsigned long slot)
		dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
		dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
				p_slot->bus, p_slot->device);
				p_slot->bus, p_slot->device);


		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
		if (pciehp_enable_slot(p_slot) &&
			/* Wait for exclusive access to hardware */
		    PWR_LED(p_slot->ctrl->ctrlcap))
			mutex_lock(&p_slot->ctrl->ctrl_lock);

			p_slot->hpc_ops->green_led_off(p_slot);
			p_slot->hpc_ops->green_led_off(p_slot);


			/* Wait for the command to complete */
			wait_for_ctrl_irq (p_slot->ctrl);

			/* Done with exclusive hardware access */
			mutex_unlock(&p_slot->ctrl->ctrl_lock);
		}
		p_slot->state = STATIC_STATE;
		p_slot->state = STATIC_STATE;
	}
	}


@@ -494,18 +439,10 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
		dbg("%s: adding bus:device(%x:%x)\n",
		dbg("%s: adding bus:device(%x:%x)\n",
				__FUNCTION__, p_slot->bus, p_slot->device);
				__FUNCTION__, p_slot->bus, p_slot->device);


		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
		if (pciehp_enable_slot(p_slot) &&
			/* Wait for exclusive access to hardware */
		    PWR_LED(p_slot->ctrl->ctrlcap))
			mutex_lock(&p_slot->ctrl->ctrl_lock);

			p_slot->hpc_ops->green_led_off(p_slot);
			p_slot->hpc_ops->green_led_off(p_slot);


			/* Wait for the command to complete */
			wait_for_ctrl_irq (p_slot->ctrl);

			/* Done with exclusive hardware access */
			mutex_unlock(&p_slot->ctrl->ctrl_lock);
		}
		p_slot->state = STATIC_STATE;
		p_slot->state = STATIC_STATE;
	}
	}


@@ -616,40 +553,18 @@ static void interrupt_event_handler(struct controller *ctrl)


					switch (p_slot->state) {
					switch (p_slot->state) {
					case BLINKINGOFF_STATE:
					case BLINKINGOFF_STATE:
						/* Wait for exclusive access to hardware */
						if (PWR_LED(ctrl->ctrlcap))
						mutex_lock(&ctrl->ctrl_lock);
						
						if (PWR_LED(ctrl->ctrlcap)) {
							p_slot->hpc_ops->green_led_on(p_slot);
							p_slot->hpc_ops->green_led_on(p_slot);
							/* Wait for the command to complete */
							wait_for_ctrl_irq (ctrl);
						}
						if (ATTN_LED(ctrl->ctrlcap)) {
							p_slot->hpc_ops->set_attention_status(p_slot, 0);


							/* Wait for the command to complete */
						if (ATTN_LED(ctrl->ctrlcap))
							wait_for_ctrl_irq (ctrl);
							p_slot->hpc_ops->set_attention_status(p_slot, 0);
						}
						/* Done with exclusive hardware access */
						mutex_unlock(&ctrl->ctrl_lock);
						break;
						break;
					case BLINKINGON_STATE:
					case BLINKINGON_STATE:
						/* Wait for exclusive access to hardware */
						if (PWR_LED(ctrl->ctrlcap))
						mutex_lock(&ctrl->ctrl_lock);

						if (PWR_LED(ctrl->ctrlcap)) {
							p_slot->hpc_ops->green_led_off(p_slot);
							p_slot->hpc_ops->green_led_off(p_slot);
							/* Wait for the command to complete */
							wait_for_ctrl_irq (ctrl);
						}
						if (ATTN_LED(ctrl->ctrlcap)){
							p_slot->hpc_ops->set_attention_status(p_slot, 0);
							/* Wait for the command to complete */
							wait_for_ctrl_irq (ctrl);
						}
						/* Done with exclusive hardware access */
						mutex_unlock(&ctrl->ctrl_lock);


						if (ATTN_LED(ctrl->ctrlcap))
							p_slot->hpc_ops->set_attention_status(p_slot, 0);
						break;
						break;
					default:
					default:
						warn("Not a valid state\n");
						warn("Not a valid state\n");
@@ -676,26 +591,13 @@ static void interrupt_event_handler(struct controller *ctrl)
							info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot));
							info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot));
						}
						}


						/* Wait for exclusive access to hardware */
						mutex_lock(&ctrl->ctrl_lock);

						/* blink green LED and turn off amber */
						/* blink green LED and turn off amber */
						if (PWR_LED(ctrl->ctrlcap)) {
						if (PWR_LED(ctrl->ctrlcap))
							p_slot->hpc_ops->green_led_blink(p_slot);
							p_slot->hpc_ops->green_led_blink(p_slot);
							/* Wait for the command to complete */
							wait_for_ctrl_irq (ctrl);
						}


						if (ATTN_LED(ctrl->ctrlcap)) {
						if (ATTN_LED(ctrl->ctrlcap))
							p_slot->hpc_ops->set_attention_status(p_slot, 0);
							p_slot->hpc_ops->set_attention_status(p_slot, 0);


							/* Wait for the command to complete */
							wait_for_ctrl_irq (ctrl);
						}

						/* Done with exclusive hardware access */
						mutex_unlock(&ctrl->ctrl_lock);

						init_timer(&p_slot->task_event);
						init_timer(&p_slot->task_event);
						p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
						p_slot->task_event.expires = jiffies + 5 * HZ;   /* 5 second delay */
						p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
						p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
@@ -708,21 +610,11 @@ static void interrupt_event_handler(struct controller *ctrl)
				else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
				else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
					if (POWER_CTRL(ctrl->ctrlcap)) {
					if (POWER_CTRL(ctrl->ctrlcap)) {
						dbg("power fault\n");
						dbg("power fault\n");
						/* Wait for exclusive access to hardware */
						if (ATTN_LED(ctrl->ctrlcap))
						mutex_lock(&ctrl->ctrl_lock);

						if (ATTN_LED(ctrl->ctrlcap)) {
							p_slot->hpc_ops->set_attention_status(p_slot, 1);
							p_slot->hpc_ops->set_attention_status(p_slot, 1);
							wait_for_ctrl_irq (ctrl);
						}


						if (PWR_LED(ctrl->ctrlcap)) {
						if (PWR_LED(ctrl->ctrlcap))
							p_slot->hpc_ops->green_led_off(p_slot);
							p_slot->hpc_ops->green_led_off(p_slot);
							wait_for_ctrl_irq (ctrl);
						}

						/* Done with exclusive hardware access */
						mutex_unlock(&ctrl->ctrl_lock);
					}
					}
				}
				}
				/***********SURPRISE REMOVAL********************/
				/***********SURPRISE REMOVAL********************/
@@ -750,7 +642,6 @@ static void interrupt_event_handler(struct controller *ctrl)
	}
	}
}
}



int pciehp_enable_slot(struct slot *p_slot)
int pciehp_enable_slot(struct slot *p_slot)
{
{
	u8 getstatus = 0;
	u8 getstatus = 0;
+33 −5
Original line number Original line Diff line number Diff line
@@ -249,6 +249,24 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)
	add_timer(&ctrl->poll_timer);
	add_timer(&ctrl->poll_timer);
}
}


static inline int pcie_wait_cmd(struct controller *ctrl)
{
	DECLARE_WAITQUEUE(wait, current);

	add_wait_queue(&ctrl->queue, &wait);
	if (!pciehp_poll_mode)
		/* Sleep for up to 1 second */
		msleep_interruptible(1000);
	else
		msleep_interruptible(2500);

	remove_wait_queue(&ctrl->queue, &wait);
	if (signal_pending(current))
		return -EINTR;

	return 0;
}

static int pcie_write_cmd(struct slot *slot, u16 cmd)
static int pcie_write_cmd(struct slot *slot, u16 cmd)
{
{
	struct controller *ctrl = slot->ctrl;
	struct controller *ctrl = slot->ctrl;
@@ -257,24 +275,34 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)


	DBG_ENTER_ROUTINE 
	DBG_ENTER_ROUTINE 


	mutex_lock(&ctrl->ctrl_lock);

	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
	retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
	if (retval) {
	if (retval) {
		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
		err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
		return retval;
		goto out;
	}
	}


	if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { 
	if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { 
		/* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue 
		/* After 1 sec and CMD_COMPLETED still not set, just
		   the next command according to spec.  Just print out the error message */
		   proceed forward to issue the next command according
		dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
		   to spec.  Just print out the error message */
		dbg("%s: CMD_COMPLETED not clear after 1 sec.\n",
		    __FUNCTION__);
	}
	}


	retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE));
	retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE));
	if (retval) {
	if (retval) {
		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
		err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
		return retval;
		goto out;
	}
	}


	/*
	 * Wait for command completion.
	 */
	retval = pcie_wait_cmd(ctrl);
 out:
	mutex_unlock(&ctrl->ctrl_lock);
	DBG_LEAVE_ROUTINE 
	DBG_LEAVE_ROUTINE 
	return retval;
	return retval;
}
}