aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_msghandler.c
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2005-06-24 01:01:42 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-24 03:05:23 -0400
commit3b6259432dee81f928c22c48c080d5f6325ed92e (patch)
tree4b22a1a9a547a6e3da9d1a45cd83d210d9398fcd /drivers/char/ipmi/ipmi_msghandler.c
parent8f43f84f13a49fe5f0f7d1595082b6d7ec6daa85 (diff)
[PATCH] ipmi: add power cycle capability
This patch to adds "power cycle" functionality to the IPMI power off module ipmi_poweroff. It also contains changes to support procfs control of the feature. The power cycle action is considered an optional chassis control in the IPMI specification. However, it is definitely useful when the hardware supports it. A power cycle is usually required in order to reset a firmware in a bad state. This action is critical to allow remote management of servers. The implementation adds power cycle as optional to the ipmi_poweroff module. It can be modified dynamically through the proc entry mentioned above. During a power down and enabled, the power cycle command is sent to the BMC firmware. If it fails either due to non-support or some error, it will retry to send the command as power off. Signed-off-by: Christopher A. Poblete <Chris_Poblete@dell.com> Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_msghandler.c')
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index ed75e96d0035..1813d0d198f1 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -54,7 +54,9 @@ static int ipmi_init_msghandler(void);
54 54
55static int initialized = 0; 55static int initialized = 0;
56 56
57static struct proc_dir_entry *proc_ipmi_root = NULL; 57#ifdef CONFIG_PROC_FS
58struct proc_dir_entry *proc_ipmi_root = NULL;
59#endif /* CONFIG_PROC_FS */
58 60
59#define MAX_EVENTS_IN_QUEUE 25 61#define MAX_EVENTS_IN_QUEUE 25
60 62
@@ -124,11 +126,13 @@ struct ipmi_channel
124 unsigned char protocol; 126 unsigned char protocol;
125}; 127};
126 128
129#ifdef CONFIG_PROC_FS
127struct ipmi_proc_entry 130struct ipmi_proc_entry
128{ 131{
129 char *name; 132 char *name;
130 struct ipmi_proc_entry *next; 133 struct ipmi_proc_entry *next;
131}; 134};
135#endif
132 136
133#define IPMI_IPMB_NUM_SEQ 64 137#define IPMI_IPMB_NUM_SEQ 64
134#define IPMI_MAX_CHANNELS 8 138#define IPMI_MAX_CHANNELS 8
@@ -156,10 +160,13 @@ struct ipmi_smi
156 struct ipmi_smi_handlers *handlers; 160 struct ipmi_smi_handlers *handlers;
157 void *send_info; 161 void *send_info;
158 162
163#ifdef CONFIG_PROC_FS
159 /* A list of proc entries for this interface. This does not 164 /* A list of proc entries for this interface. This does not
160 need a lock, only one thread creates it and only one thread 165 need a lock, only one thread creates it and only one thread
161 destroys it. */ 166 destroys it. */
167 spinlock_t proc_entry_lock;
162 struct ipmi_proc_entry *proc_entries; 168 struct ipmi_proc_entry *proc_entries;
169#endif
163 170
164 /* A table of sequence numbers for this interface. We use the 171 /* A table of sequence numbers for this interface. We use the
165 sequence numbers for IPMB messages that go out of the 172 sequence numbers for IPMB messages that go out of the
@@ -1470,8 +1477,9 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1470 read_proc_t *read_proc, write_proc_t *write_proc, 1477 read_proc_t *read_proc, write_proc_t *write_proc,
1471 void *data, struct module *owner) 1478 void *data, struct module *owner)
1472{ 1479{
1473 struct proc_dir_entry *file;
1474 int rv = 0; 1480 int rv = 0;
1481#ifdef CONFIG_PROC_FS
1482 struct proc_dir_entry *file;
1475 struct ipmi_proc_entry *entry; 1483 struct ipmi_proc_entry *entry;
1476 1484
1477 /* Create a list element. */ 1485 /* Create a list element. */
@@ -1497,10 +1505,13 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1497 file->write_proc = write_proc; 1505 file->write_proc = write_proc;
1498 file->owner = owner; 1506 file->owner = owner;
1499 1507
1508 spin_lock(&smi->proc_entry_lock);
1500 /* Stick it on the list. */ 1509 /* Stick it on the list. */
1501 entry->next = smi->proc_entries; 1510 entry->next = smi->proc_entries;
1502 smi->proc_entries = entry; 1511 smi->proc_entries = entry;
1512 spin_unlock(&smi->proc_entry_lock);
1503 } 1513 }
1514#endif /* CONFIG_PROC_FS */
1504 1515
1505 return rv; 1516 return rv;
1506} 1517}
@@ -1509,6 +1520,7 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
1509{ 1520{
1510 int rv = 0; 1521 int rv = 0;
1511 1522
1523#ifdef CONFIG_PROC_FS
1512 sprintf(smi->proc_dir_name, "%d", num); 1524 sprintf(smi->proc_dir_name, "%d", num);
1513 smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); 1525 smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
1514 if (!smi->proc_dir) 1526 if (!smi->proc_dir)
@@ -1531,14 +1543,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
1531 rv = ipmi_smi_add_proc_entry(smi, "version", 1543 rv = ipmi_smi_add_proc_entry(smi, "version",
1532 version_file_read_proc, NULL, 1544 version_file_read_proc, NULL,
1533 smi, THIS_MODULE); 1545 smi, THIS_MODULE);
1546#endif /* CONFIG_PROC_FS */
1534 1547
1535 return rv; 1548 return rv;
1536} 1549}
1537 1550
1538static void remove_proc_entries(ipmi_smi_t smi) 1551static void remove_proc_entries(ipmi_smi_t smi)
1539{ 1552{
1553#ifdef CONFIG_PROC_FS
1540 struct ipmi_proc_entry *entry; 1554 struct ipmi_proc_entry *entry;
1541 1555
1556 spin_lock(&smi->proc_entry_lock);
1542 while (smi->proc_entries) { 1557 while (smi->proc_entries) {
1543 entry = smi->proc_entries; 1558 entry = smi->proc_entries;
1544 smi->proc_entries = entry->next; 1559 smi->proc_entries = entry->next;
@@ -1547,7 +1562,9 @@ static void remove_proc_entries(ipmi_smi_t smi)
1547 kfree(entry->name); 1562 kfree(entry->name);
1548 kfree(entry); 1563 kfree(entry);
1549 } 1564 }
1565 spin_unlock(&smi->proc_entry_lock);
1550 remove_proc_entry(smi->proc_dir_name, proc_ipmi_root); 1566 remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);
1567#endif /* CONFIG_PROC_FS */
1551} 1568}
1552 1569
1553static int 1570static int
@@ -1694,6 +1711,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
1694 new_intf->seq_table[j].seqid = 0; 1711 new_intf->seq_table[j].seqid = 0;
1695 } 1712 }
1696 new_intf->curr_seq = 0; 1713 new_intf->curr_seq = 0;
1714#ifdef CONFIG_PROC_FS
1715 spin_lock_init(&(new_intf->proc_entry_lock));
1716#endif
1697 spin_lock_init(&(new_intf->waiting_msgs_lock)); 1717 spin_lock_init(&(new_intf->waiting_msgs_lock));
1698 INIT_LIST_HEAD(&(new_intf->waiting_msgs)); 1718 INIT_LIST_HEAD(&(new_intf->waiting_msgs));
1699 spin_lock_init(&(new_intf->events_lock)); 1719 spin_lock_init(&(new_intf->events_lock));
@@ -3085,6 +3105,7 @@ static int ipmi_init_msghandler(void)
3085 ipmi_interfaces[i] = NULL; 3105 ipmi_interfaces[i] = NULL;
3086 } 3106 }
3087 3107
3108#ifdef CONFIG_PROC_FS
3088 proc_ipmi_root = proc_mkdir("ipmi", NULL); 3109 proc_ipmi_root = proc_mkdir("ipmi", NULL);
3089 if (!proc_ipmi_root) { 3110 if (!proc_ipmi_root) {
3090 printk(KERN_ERR PFX "Unable to create IPMI proc dir"); 3111 printk(KERN_ERR PFX "Unable to create IPMI proc dir");
@@ -3092,6 +3113,7 @@ static int ipmi_init_msghandler(void)
3092 } 3113 }
3093 3114
3094 proc_ipmi_root->owner = THIS_MODULE; 3115 proc_ipmi_root->owner = THIS_MODULE;
3116#endif /* CONFIG_PROC_FS */
3095 3117
3096 init_timer(&ipmi_timer); 3118 init_timer(&ipmi_timer);
3097 ipmi_timer.data = 0; 3119 ipmi_timer.data = 0;
@@ -3129,7 +3151,9 @@ static __exit void cleanup_ipmi(void)
3129 atomic_inc(&stop_operation); 3151 atomic_inc(&stop_operation);
3130 del_timer_sync(&ipmi_timer); 3152 del_timer_sync(&ipmi_timer);
3131 3153
3154#ifdef CONFIG_PROC_FS
3132 remove_proc_entry(proc_ipmi_root->name, &proc_root); 3155 remove_proc_entry(proc_ipmi_root->name, &proc_root);
3156#endif /* CONFIG_PROC_FS */
3133 3157
3134 initialized = 0; 3158 initialized = 0;
3135 3159
@@ -3170,4 +3194,5 @@ EXPORT_SYMBOL(ipmi_get_my_address);
3170EXPORT_SYMBOL(ipmi_set_my_LUN); 3194EXPORT_SYMBOL(ipmi_set_my_LUN);
3171EXPORT_SYMBOL(ipmi_get_my_LUN); 3195EXPORT_SYMBOL(ipmi_get_my_LUN);
3172EXPORT_SYMBOL(ipmi_smi_add_proc_entry); 3196EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
3197EXPORT_SYMBOL(proc_ipmi_root);
3173EXPORT_SYMBOL(ipmi_user_set_run_to_completion); 3198EXPORT_SYMBOL(ipmi_user_set_run_to_completion);