Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 23199
b: refs/heads/master
c: a246fa4
h: refs/heads/master
i:
  23197: 98664bb
  23195: 9b779f5
  23191: cfef72b
  23183: db27275
  23167: 03c9085
v: v3
  • Loading branch information
Kenji Kaneshige authored and Greg Kroah-Hartman committed Mar 23, 2006
1 parent 0f27bb0 commit 1c9f072
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 62 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f7391f5325ea744f0632f7ef39a90085162743ac
refs/heads/master: a246fa4e9f0f1b5096a1cad0659d22fb10fb3732
7 changes: 4 additions & 3 deletions trunk/drivers/pci/hotplug/shpchp.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct slot {
struct list_head slot_list;
char name[SLOT_NAME_SIZE];
struct work_struct work; /* work for button event */
struct mutex lock;
};

struct event_info {
Expand Down Expand Up @@ -181,8 +182,8 @@ struct hotplug_params {
/* sysfs functions for the hotplug controller info */
extern void shpchp_create_ctrl_files (struct controller *ctrl);

extern int shpchp_enable_slot(struct slot *slot);
extern int shpchp_disable_slot(struct slot *slot);
extern int shpchp_sysfs_enable_slot(struct slot *slot);
extern int shpchp_sysfs_disable_slot(struct slot *slot);

extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id);
extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id);
Expand All @@ -200,7 +201,7 @@ extern int shpchprm_get_physical_slot_number(struct controller *ctrl,
u32 *sun, u8 busnum, u8 devnum);
extern void shpchp_remove_ctrl_files(struct controller *ctrl);
extern void cleanup_slots(struct controller *ctrl);
extern void shpchp_pushbutton_thread(void *data);
extern void queue_pushbutton_work(void *data);

/* Global variables */
extern struct list_head shpchp_ctrl_list;
Expand Down
8 changes: 5 additions & 3 deletions trunk/drivers/pci/hotplug/shpchp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,14 @@ static int init_slots(struct controller *ctrl)
slot->bus = ctrl->slot_bus;
slot->device = ctrl->slot_device_offset + i;
slot->hpc_ops = ctrl->hpc_ops;
mutex_init(&slot->lock);

if (shpchprm_get_physical_slot_number(ctrl, &sun,
slot->bus, slot->device))
goto error_info;

slot->number = sun;
INIT_WORK(&slot->work, shpchp_pushbutton_thread, slot);
INIT_WORK(&slot->work, queue_pushbutton_work, slot);

/* register this slot with the hotplug pci core */
hotplug_slot->private = slot;
Expand Down Expand Up @@ -188,6 +189,7 @@ void cleanup_slots(struct controller *ctrl)
slot = list_entry(tmp, struct slot, slot_list);
list_del(&slot->slot_list);
cancel_delayed_work(&slot->work);
flush_scheduled_work();
flush_workqueue(shpchp_wq);
pci_hp_deregister(slot->hotplug_slot);
}
Expand Down Expand Up @@ -244,7 +246,7 @@ static int enable_slot (struct hotplug_slot *hotplug_slot)

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

return shpchp_enable_slot(slot);
return shpchp_sysfs_enable_slot(slot);
}

static int disable_slot (struct hotplug_slot *hotplug_slot)
Expand All @@ -253,7 +255,7 @@ static int disable_slot (struct hotplug_slot *hotplug_slot)

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

return shpchp_disable_slot(slot);
return shpchp_sysfs_disable_slot(slot);
}

static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
Expand Down
227 changes: 172 additions & 55 deletions trunk/drivers/pci/hotplug/shpchp_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
#include "shpchp.h"

static void interrupt_event_handler(void *data);
static int shpchp_enable_slot(struct slot *p_slot);
static int shpchp_disable_slot(struct slot *p_slot);

static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
{
Expand All @@ -50,7 +52,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
info->p_slot = p_slot;
INIT_WORK(&info->work, interrupt_event_handler, info);

queue_work(shpchp_wq, &info->work);
schedule_work(&info->work);

return 0;
}
Expand All @@ -73,24 +75,6 @@ u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id)
info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
event_type = INT_BUTTON_PRESS;

if ((p_slot->state == BLINKINGON_STATE)
|| (p_slot->state == BLINKINGOFF_STATE)) {
/* Cancel if we are still blinking; this means that we press the
* attention again before the 5 sec. limit expires to cancel hot-add
* or hot-remove
*/
event_type = INT_BUTTON_CANCEL;
info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot);
} else if ((p_slot->state == POWERON_STATE)
|| (p_slot->state == POWEROFF_STATE)) {
/* Ignore if the slot is on power-on or power-off state; this
* means that the previous attention button action to hot-add or
* hot-remove is undergoing
*/
event_type = INT_BUTTON_IGNORE;
info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot);
}

queue_interrupt_event(p_slot, event_type);

return 0;
Expand Down Expand Up @@ -492,29 +476,73 @@ static int remove_board(struct slot *p_slot)
}


struct pushbutton_work_info {
struct slot *p_slot;
struct work_struct work;
};

/**
* shpchp_pushbutton_thread
*
* Scheduled procedure to handle blocking stuff for the pushbuttons
* Handles all pending events and exits.
*
*/
void shpchp_pushbutton_thread(void *data)
static void shpchp_pushbutton_thread(void *data)
{
struct slot *p_slot = data;
u8 getstatus;
struct pushbutton_work_info *info = data;
struct slot *p_slot = info->p_slot;

p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = POWEROFF_STATE;
mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case POWEROFF_STATE:
mutex_unlock(&p_slot->lock);
shpchp_disable_slot(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
} else {
p_slot->state = POWERON_STATE;
break;
case POWERON_STATE:
mutex_unlock(&p_slot->lock);
if (shpchp_enable_slot(p_slot))
p_slot->hpc_ops->green_led_off(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;
default:
break;
}
mutex_unlock(&p_slot->lock);

kfree(info);
}

void queue_pushbutton_work(void *data)
{
struct slot *p_slot = data;
struct pushbutton_work_info *info;

info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
err("%s: Cannot allocate memory\n", __FUNCTION__);
return;
}
info->p_slot = p_slot;
INIT_WORK(&info->work, shpchp_pushbutton_thread, info);

mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case BLINKINGOFF_STATE:
p_slot->state = POWEROFF_STATE;
break;
case BLINKINGON_STATE:
p_slot->state = POWERON_STATE;
break;
default:
goto out;
}
queue_work(shpchp_wq, &info->work);
out:
mutex_unlock(&p_slot->lock);
}

static int update_slot_info (struct slot *slot)
Expand All @@ -536,34 +564,15 @@ static int update_slot_info (struct slot *slot)
return result;
}

static void interrupt_event_handler(void *data)
/*
* Note: This function must be called with slot->lock held
*/
static void handle_button_press_event(struct slot *p_slot)
{
struct event_info *info = data;
struct slot *p_slot = info->p_slot;
u8 getstatus;

switch (info->event_type) {
case INT_BUTTON_CANCEL:
dbg("%s: button cancel\n", __FUNCTION__);
cancel_delayed_work(&p_slot->work);
switch (p_slot->state) {
case BLINKINGOFF_STATE:
p_slot->hpc_ops->green_led_on(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
break;
case BLINKINGON_STATE:
p_slot->hpc_ops->green_led_off(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
break;
default:
warn("Not a valid state\n");
return;
}
info(msg_button_cancel, p_slot->number);
p_slot->state = STATIC_STATE;
break;
case INT_BUTTON_PRESS:
dbg("%s: Button pressed\n", __FUNCTION__);
switch (p_slot->state) {
case STATIC_STATE:
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = BLINKINGOFF_STATE;
Expand All @@ -576,7 +585,51 @@ static void interrupt_event_handler(void *data)
p_slot->hpc_ops->green_led_blink(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);

queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
schedule_delayed_work(&p_slot->work, 5*HZ);
break;
case BLINKINGOFF_STATE:
case BLINKINGON_STATE:
/*
* Cancel if we are still blinking; this means that we
* press the attention again before the 5 sec. limit
* expires to cancel hot-add or hot-remove
*/
info("Button cancel on Slot(%s)\n", p_slot->name);
dbg("%s: button cancel\n", __FUNCTION__);
cancel_delayed_work(&p_slot->work);
if (p_slot->state == BLINKINGOFF_STATE)
p_slot->hpc_ops->green_led_on(p_slot);
else
p_slot->hpc_ops->green_led_off(p_slot);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
info(msg_button_cancel, p_slot->number);
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
case POWERON_STATE:
/*
* Ignore if the slot is on power-on or power-off state;
* this means that the previous attention button action
* to hot-add or hot-remove is undergoing
*/
info("Button ignore on Slot(%s)\n", p_slot->name);
update_slot_info(p_slot);
break;
default:
warn("Not a valid state\n");
break;
}
}

static void interrupt_event_handler(void *data)
{
struct event_info *info = data;
struct slot *p_slot = info->p_slot;

mutex_lock(&p_slot->lock);
switch (info->event_type) {
case INT_BUTTON_PRESS:
handle_button_press_event(p_slot);
break;
case INT_POWER_FAULT:
dbg("%s: power fault\n", __FUNCTION__);
Expand All @@ -587,12 +640,13 @@ static void interrupt_event_handler(void *data)
update_slot_info(p_slot);
break;
}
mutex_unlock(&p_slot->lock);

kfree(info);
}


int shpchp_enable_slot (struct slot *p_slot)
static int shpchp_enable_slot (struct slot *p_slot)
{
u8 getstatus = 0;
int rc, retval = -ENODEV;
Expand Down Expand Up @@ -647,7 +701,7 @@ int shpchp_enable_slot (struct slot *p_slot)
}


int shpchp_disable_slot (struct slot *p_slot)
static int shpchp_disable_slot (struct slot *p_slot)
{
u8 getstatus = 0;
int rc, retval = -ENODEV;
Expand Down Expand Up @@ -681,3 +735,66 @@ int shpchp_disable_slot (struct slot *p_slot)
return retval;
}

int shpchp_sysfs_enable_slot(struct slot *p_slot)
{
int retval = -ENODEV;

mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case BLINKINGON_STATE:
cancel_delayed_work(&p_slot->work);
case STATIC_STATE:
p_slot->state = POWERON_STATE;
mutex_unlock(&p_slot->lock);
retval = shpchp_enable_slot(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;
case POWERON_STATE:
info("Slot %s is already in powering on state\n",
p_slot->name);
break;
case BLINKINGOFF_STATE:
case POWEROFF_STATE:
info("Already enabled on slot %s\n", p_slot->name);
break;
default:
err("Not a valid state on slot %s\n", p_slot->name);
break;
}
mutex_unlock(&p_slot->lock);

return retval;
}

int shpchp_sysfs_disable_slot(struct slot *p_slot)
{
int retval = -ENODEV;

mutex_lock(&p_slot->lock);
switch (p_slot->state) {
case BLINKINGOFF_STATE:
cancel_delayed_work(&p_slot->work);
case STATIC_STATE:
p_slot->state = POWEROFF_STATE;
mutex_unlock(&p_slot->lock);
retval = shpchp_disable_slot(p_slot);
mutex_lock(&p_slot->lock);
p_slot->state = STATIC_STATE;
break;
case POWEROFF_STATE:
info("Slot %s is already in powering off state\n",
p_slot->name);
break;
case BLINKINGON_STATE:
case POWERON_STATE:
info("Already disabled on slot %s\n", p_slot->name);
break;
default:
err("Not a valid state on slot %s\n", p_slot->name);
break;
}
mutex_unlock(&p_slot->lock);

return retval;
}

0 comments on commit 1c9f072

Please sign in to comment.