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

Commit 5d386e1a authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Greg Kroah-Hartman
Browse files

pciehp: Event handling rework



The event handler of PCIEHP driver is unnecessarily very complex. In
addition, current event handler can only a fixed number of events at
the same time, and some of events would be lost if several number of
events happened at the same time.

This patch simplify the event handler using 'work queue', and it also
fix the above-mentioned issue.

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 f7bdd12d
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
extern int pciehp_poll_time;
extern int pciehp_debug;
extern int pciehp_force;
extern struct workqueue_struct *pciehp_wq;

#define dbg(format, arg...)						\
	do {								\
@@ -70,14 +71,16 @@ struct slot {
	struct list_head	slot_list;
	char name[SLOT_NAME_SIZE];
	unsigned long last_emi_toggle;
	struct delayed_work work;	/* work for button event */
	struct mutex lock;
};

struct event_info {
	u32 event_type;
	u8 hp_slot;
	struct slot *p_slot;
	struct work_struct work;
};

#define MAX_EVENTS		10
struct controller {
	struct controller *next;
	struct mutex crit_sect;		/* critical section mutex */
@@ -86,11 +89,9 @@ struct controller {
	int slot_num_inc;		/* 1 or -1 */
	struct pci_dev *pci_dev;
	struct list_head slot_list;
	struct event_info event_queue[MAX_EVENTS];
	struct slot *slot;
	struct hpc_ops *hpc_ops;
	wait_queue_head_t queue;	/* sleep & wake process */
	u8 next_event;
	u8 bus;
	u8 device;
	u8 function;
@@ -149,16 +150,15 @@ struct controller {
#define HP_SUPR_RM(cap)		(cap & HP_SUPR_RM_SUP)
#define EMI(cap)		(cap & EMI_PRSN)

extern int pciehp_event_start_thread(void);
extern void pciehp_event_stop_thread(void);
extern int pciehp_enable_slot(struct slot *slot);
extern int pciehp_disable_slot(struct slot *slot);
extern int pciehp_sysfs_enable_slot(struct slot *slot);
extern int pciehp_sysfs_disable_slot(struct slot *slot);
extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
extern int pciehp_configure_device(struct slot *p_slot);
extern int pciehp_unconfigure_device(struct slot *p_slot);
extern void queue_pushbutton_work(struct work_struct *work);
int pcie_init(struct controller *ctrl, struct pcie_device *dev);

/* Global variables */
+8 −36
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ int pciehp_debug;
int pciehp_poll_mode;
int pciehp_poll_time;
int pciehp_force;
struct workqueue_struct *pciehp_wq;
struct controller *pciehp_ctrl_list;

#define DRIVER_VERSION	"0.4"
@@ -62,7 +63,6 @@ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"

#define PCIE_MODULE_NAME "pciehp"

static int pcie_start_thread (void);
static int set_attention_status (struct hotplug_slot *slot, u8 value);
static int enable_slot		(struct hotplug_slot *slot);
static int disable_slot		(struct hotplug_slot *slot);
@@ -229,6 +229,8 @@ static int init_slots(struct controller *ctrl)
		slot->device = ctrl->slot_device_offset + i;
		slot->hpc_ops = ctrl->hpc_ops;
		slot->number = ctrl->first_slot;
		mutex_init(&slot->lock);
		INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work);

		/* register this slot with the hotplug pci core */
		hotplug_slot->private = slot;
@@ -286,6 +288,9 @@ static void cleanup_slots(struct controller *ctrl)
		if (EMI(ctrl->ctrlcap))
			sysfs_remove_file(&slot->hotplug_slot->kobj,
				&hotplug_slot_attr_lock.attr);
		cancel_delayed_work(&slot->work);
		flush_scheduled_work();
		flush_workqueue(pciehp_wq);
		pci_hp_deregister(slot->hotplug_slot);
	}
}
@@ -314,7 +319,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)

	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);

	return pciehp_enable_slot(slot);
	return pciehp_sysfs_enable_slot(slot);
}


@@ -324,7 +329,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)

	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);

	return pciehp_disable_slot(slot);
	return pciehp_sysfs_disable_slot(slot);
}

static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
@@ -466,9 +471,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_

	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);

	/*	Finish setting up the hot plug ctrl device */
	ctrl->next_event = 0;

	if (!pciehp_ctrl_list) {
		pciehp_ctrl_list = ctrl;
		ctrl->next = NULL;
@@ -496,22 +498,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
	return -ENODEV;
}


static int pcie_start_thread(void)
{
	int retval = 0;
	
	dbg("Initialize + Start the notification/polling mechanism \n");

	retval = pciehp_event_start_thread();
	if (retval) {
		dbg("pciehp_event_start_thread() failed\n");
		return retval;
	}

	return retval;
}

static void __exit unload_pciehpd(void)
{
	struct controller *ctrl;
@@ -529,10 +515,6 @@ static void __exit unload_pciehpd(void)

		kfree(tctrl);
	}

	/* Stop the notification mechanism */
	pciehp_event_stop_thread();

}

static void pciehp_remove (struct pcie_device *device)
@@ -585,21 +567,11 @@ static int __init pcied_init(void)
	pciehp_poll_mode = 1;
#endif

	retval = pcie_start_thread();
	if (retval)
		goto error_hpc_init;

	retval = pcie_port_service_register(&hpdriver_portdrv);
 	dbg("pcie_port_service_register = %d\n", retval);
  	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 	if (retval)
		dbg("%s: Failure to register service\n", __FUNCTION__);

error_hpc_init:
	if (retval) {
		pciehp_event_stop_thread();
	};

	return retval;
}