Re: [PATCH] drivers: char: ipmi: Replaced kmalloc and strcpy with kstrdup

2013-03-18 Thread Corey Minyard

On 03/16/2013 09:16 AM, Alexandru Gheorghiu wrote:

Replaced calls to kmalloc followed by strcpy with a sincle call to kstrdup.
Patch found using coccinelle.

Signed-off-by: Alexandru Gheorghiu 
---
  drivers/char/ipmi/ipmi_msghandler.c |3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c 
b/drivers/char/ipmi/ipmi_msghandler.c
index 053201b..617b443 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2037,12 +2037,11 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
-   entry->name = kmalloc(strlen(name)+1, GFP_KERNEL);
+   entry->name = kstrdup(name, GFP_KERNEL);
if (!entry->name) {
kfree(entry);
return -ENOMEM;
}
-   strcpy(entry->name, name);
  
  	file = proc_create_data(name, 0, smi->proc_dir, proc_ops, data);

if (!file) {

Looks good to me.

Acked-by: Corey Minyard 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] drivers: char: ipmi: Replaced kmalloc and strcpy with kstrdup

2013-03-18 Thread Corey Minyard

On 03/16/2013 09:16 AM, Alexandru Gheorghiu wrote:

Replaced calls to kmalloc followed by strcpy with a sincle call to kstrdup.
Patch found using coccinelle.

Signed-off-by: Alexandru Gheorghiu 
---
  drivers/char/ipmi/ipmi_msghandler.c |3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c 
b/drivers/char/ipmi/ipmi_msghandler.c
index 053201b..617b443 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2037,12 +2037,11 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
-   entry->name = kmalloc(strlen(name)+1, GFP_KERNEL);
+   entry->name = kstrdup(name, GFP_KERNEL);
if (!entry->name) {
kfree(entry);
return -ENOMEM;
}
-   strcpy(entry->name, name);
  
  	file = proc_create_data(name, 0, smi->proc_dir, proc_ops, data);

if (!file) {

Actually, I should say that I've pulled this into my tree.

Thanks,

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Linux IPMI subsystem hang

2013-03-18 Thread Corey Minyard

On 03/15/2013 01:57 PM, Daniel Kahn Gillmor wrote:

On Tue 2013-03-12 22:23:37 -0400, Daniel Kahn Gillmor wrote:


I am working with a Lenovo ThinkCentre M78, model 4865-A14, and it seems
to have trouble with the IPMI subsystem.

udev seems to hang for about 3 minutes at startup, ultimately failing
with the following messages:

udevd[416]: worker [495] unexpectedly returned with status 0x0100
udevd[416]: worker [495] failed while handling 
'/devices/pci:00/:00:15.2/:03:00.3'

This hang happens whether i'm running linux kernel 3.2 or 3.8, using
either x86 or x86_64 kernels.

trying with udev 175-7.1 (from debian unstable) and kernel 3.2, i see
that the failure message is:

udevd[548]: timeout: killing '/sbin/modprobe -b 
pci:v10ECd816Csv17AAsd3089bc0Csc07i01' [623]

and:

[5.650931] ipmi message handler version 39.2
[5.916958] IPMI System Interface driver.
[5.921153] ipmi_si :03:00.3: probing via PCI
[5.925851] ipmi_si :03:00.3: [io  0xe000-0xe0ff] regsize 1 spacing 1 
irq 17
[5.933727] ipmi_si: Adding PCI-specified kcs state machine
[5.939554] ipmi_si: Trying PCI-specified kcs state machine at i/o address 
0xe000, slave address 0x0, irq 17
[  406.916061] ipmi_si: There appears to be no BMC at this location

with kernel 3.8, the last line ("There appears to be no BMC at this
location") isn't emitted, but the delay/hang with modprobe still
happens.

I think the first alias in ipmi_si.ko is what is causing this to be triggered:

0 krazy:~# modinfo ipmi_si | grep ^alias
alias:  pci:v*d*sv*sd*bc0Csc07i*
alias:  pci:v103Cd121Asv*sd*bc*sc*i*
0 krazy:~#

since the bc0Csc07 matches the [0c07] identifier from lspci:


03:00.3 IPMI SMIC interface [0c07]: Realtek Semiconductor Co., Ltd. Device 
[10ec:816c] (rev 01) (prog-if 01)

It seems like there are four plausible cases:

  0) this is actually an IPMI device, but the hardware is broken.

  1) this is an IPMI device, but it does not implement some part of the
 IPMI spec that ipmi_si.ko expects to be implemented, and ipmi_si.ko
 cannot detect this cleanly.

  2) this device is not an IPMI device at all, and is mislabeled in its
 PCI identifiers somehow.

  3) this device is not an IPMI device at all, it is properly labeled,
 and the module's internal aliasing (and lspci's index?) is
 overgeneral and misidentifies the device.

How can i distinguish between these cases?


I would guess that the register spacing is wrong.  The spec has a 
protocol for determining register spacing, but according to the spec it 
only works for KCS interfaces.  Since this is a SMIC interface, it's not 
implemented.


You can hardcode values in ipmi_pci_probe_regspacing() in 
drivers/char/ipmi/ipmi_si_intf.c to see if that makes a difference. I'd 
guess 4, but it might be 16.  I can think about trying the protocol on 
SMIC, perhaps it will work there, too.


-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/8] IPMI: Change device node ordering to reflect probe order

2008-02-13 Thread Corey Minyard
From: Carol Hebert <[EMAIL PROTECTED]>

Currently, on systems with multiple BMC interfaces, the ipmi device
names are being created in reverse order relative to how they are
discovered on the system (e.g. on an IBM x3950 multinode server with N
nodes, the device name for the BMC in the first node is /dev/ipmiN-1 and
the device name for the BMC in the last node is /dev/ipmi0, etc.). The
problem is caused by the list handling routines chosen in dmi_scan.c.
Using list_add() causes the multiple ipmi devices to be added to the
device list using a stack-paradigm and so the ipmi driver subsequently
pulls them off during initialization in LIFO order.  This patch changes
the dmi_save_ipmi_device() list handling paradigm to a queue, thereby
allowing the ipmi driver to build the ipmi device names in the order in
which they are found on the system.

Signed-off-by: Carol Hebert <[EMAIL PROTECTED]>
Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

--- linux-2.6.24.orig/drivers/firmware/dmi_scan.c   2008-01-30 
11:21:55.0 -0800
+++ linux-2.6.24/drivers/firmware/dmi_scan.c2008-01-30 11:18:05.0 
-0800
@@ -219,7 +219,7 @@ static void __init dmi_save_ipmi_device(
dev->name = "IPMI controller";
dev->device_data = data;
 
-   list_add(&dev->list, &dmi_devices);
+   list_add_tail(&dev->list, &dmi_devices);
 }
 
 /*

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 7/8] IPMI: convert locked counters to atomics

2008-02-13 Thread Corey Minyard
From: Konstantin Baydarov <[EMAIL PROTECTED]>

Atomics are a lot more efficient and neat than using a lock.
  
Signed-off-by: Konstantin Baydarov <[EMAIL PROTECTED]>
Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
@@ -67,7 +67,6 @@ static struct proc_dir_entry *proc_ipmi_
the max message timer.  This is in milliseconds. */
 #define MAX_MSG_TIMEOUT6
 
-
 /*
  * The main "user" data structure.
  */
@@ -186,6 +185,76 @@ struct bmc_device
struct device_attribute aux_firmware_rev_attr;
 };
 
+struct ipmi_stats
+{
+   /* Commands we got that were invalid. */
+   atomic_t sent_invalid_commands;
+
+   /* Commands we sent to the MC. */
+   atomic_t sent_local_commands;
+   /* Responses from the MC that were delivered to a user. */
+   atomic_t handled_local_responses;
+   /* Responses from the MC that were not delivered to a user. */
+   atomic_t unhandled_local_responses;
+
+   /* Commands we sent out to the IPMB bus. */
+   atomic_t sent_ipmb_commands;
+   /* Commands sent on the IPMB that had errors on the SEND CMD */
+   atomic_t sent_ipmb_command_errs;
+   /* Each retransmit increments this count. */
+   atomic_t retransmitted_ipmb_commands;
+   /* When a message times out (runs out of retransmits) this is
+   incremented. */
+   atomic_t timed_out_ipmb_commands;
+
+   /* This is like above, but for broadcasts.  Broadcasts are
+   *not* included in the above count (they are expected to
+   time out). */
+   atomic_t timed_out_ipmb_broadcasts;
+
+   /* Responses I have sent to the IPMB bus. */
+   atomic_t sent_ipmb_responses;
+
+   /* The response was delivered to the user. */
+   atomic_t handled_ipmb_responses;
+   /* The response had invalid data in it. */
+   atomic_t invalid_ipmb_responses;
+   /* The response didn't have anyone waiting for it. */
+   atomic_t unhandled_ipmb_responses;
+
+   /* Commands we sent out to the IPMB bus. */
+   atomic_t sent_lan_commands;
+   /* Commands sent on the IPMB that had errors on the SEND CMD */
+   atomic_t sent_lan_command_errs;
+   /* Each retransmit increments this count. */
+   atomic_t retransmitted_lan_commands;
+   /* When a message times out (runs out of retransmits) this is
+   incremented. */
+   atomic_t timed_out_lan_commands;
+
+   /* Responses I have sent to the IPMB bus. */
+   atomic_t sent_lan_responses;
+
+   /* The response was delivered to the user. */
+   atomic_t handled_lan_responses;
+   /* The response had invalid data in it. */
+   atomic_t invalid_lan_responses;
+   /* The response didn't have anyone waiting for it. */
+   atomic_t unhandled_lan_responses;
+
+   /* The command was delivered to the user. */
+   atomic_t handled_commands;
+   /* The command had invalid data in it. */
+   atomic_t invalid_commands;
+   /* The command didn't have anyone waiting for it. */
+   atomic_t unhandled_commands;
+
+   /* Invalid data in an event. */
+   atomic_t invalid_events;
+   /* Events that were received with the proper format. */
+   atomic_t events;
+};
+
 #define IPMI_IPMB_NUM_SEQ  64
 #define IPMI_MAX_CHANNELS   16
 struct ipmi_smi
@@ -286,75 +355,7 @@ struct ipmi_smi
struct proc_dir_entry *proc_dir;
char  proc_dir_name[10];
 
-   spinlock_t   counter_lock; /* For making counters atomic. */
-
-   /* Commands we got that were invalid. */
-   unsigned int sent_invalid_commands;
-
-   /* Commands we sent to the MC. */
-   unsigned int sent_local_commands;
-   /* Responses from the MC that were delivered to a user. */
-   unsigned int handled_local_responses;
-   /* Responses from the MC that were not delivered to a user. */
-   unsigned int unhandled_local_responses;
-
-   /* Commands we sent out to the IPMB bus. */
-   unsigned int sent_ipmb_commands;
-   /* Commands sent on the IPMB that had errors on the SEND CMD */
-   unsigned int sent_ipmb_command_errs;
-   /* Each retransmit increments this count. */
-   unsigned int retransmitted_ipmb_commands;
-   /* When a message times out (runs out of retransmits) this is
-   incremented. */
-   unsigned int timed_out_ipmb_commands;
-
-   /* This is like above, but for broadcasts.  Broadcasts are
-   *not* included in the above count (they are expected to
-   time out). */
-   unsigned int timed_out_ipmb_broadcasts;
-
-   /* Responses I have sent to the IPMB bus. */
-   unsigned int sent_ipmb_responses;
-
-

[PATCH 6/8] IPMI: Update driver version

2008-02-13 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Enough bug fixes and changes that we need a new driver version.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.23/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.23.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.23/drivers/char/ipmi/ipmi_msghandler.c
@@ -47,7 +47,7 @@
 
 #define PFX "IPMI message handler: "
 
-#define IPMI_DRIVER_VERSION "39.1"
+#define IPMI_DRIVER_VERSION "39.2"
 
 static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/8] IPMI: Hold ATTN until upper layer ready

2008-02-13 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Hold handling of ATTN until the upper layer has reported that it is
ready.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
Cc: Patrick Schoeller <[EMAIL PROTECTED]>
---

Index: linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
@@ -723,8 +723,11 @@ static enum si_sm_result smi_event_handl
si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
}
 
-   /* We prefer handling attn over new messages. */
-   if (si_sm_result == SI_SM_ATTN)
+   /*
+* We prefer handling attn over new messages.  But don't do
+* this if there is not yet an upper layer to handle anything.
+*/
+   if (likely(smi_info->intf) && si_sm_result == SI_SM_ATTN)
{
unsigned char msg[2];
 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/8] IPMI: Run to completion fixes

2008-02-13 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

The "run_to_completion" mode was somewhat broken.  Locks need to be
avoided in run_to_completion mode, and it shouldn't be used by normal
users, just internally for panic situations.

This patch removes locks in run_to_completion mode and removes the
user call for setting the mode.  The only user was the poweroff
code, but it was easily converted to use the polling interface.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.21/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.21.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.21/drivers/char/ipmi/ipmi_msghandler.c
@@ -1197,13 +1197,6 @@ int ipmi_unregister_for_cmd(ipmi_user_t 
return rv;
 }
 
-void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
-{
-   ipmi_smi_t intf = user->intf;
-   if (intf->handlers)
-   intf->handlers->set_run_to_completion(intf->send_info, val);
-}
-
 static unsigned char
 ipmb_checksum(unsigned char *data, int size)
 {
@@ -4201,5 +4194,4 @@ EXPORT_SYMBOL(ipmi_get_my_address);
 EXPORT_SYMBOL(ipmi_set_my_LUN);
 EXPORT_SYMBOL(ipmi_get_my_LUN);
 EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
-EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
 EXPORT_SYMBOL(ipmi_free_recv_msg);
Index: linux-2.6.21/drivers/char/ipmi/ipmi_poweroff.c
===
--- linux-2.6.21.orig/drivers/char/ipmi/ipmi_poweroff.c
+++ linux-2.6.21/drivers/char/ipmi/ipmi_poweroff.c
@@ -99,11 +99,14 @@ static unsigned char ipmi_version;
allocate them, since we may be in a panic situation.  The whole
thing is single-threaded, anyway, so multiple messages are not
required. */
+static atomic_t dummy_count = ATOMIC_INIT(0);
 static void dummy_smi_free(struct ipmi_smi_msg *msg)
 {
+   atomic_dec(&dummy_count);
 }
 static void dummy_recv_free(struct ipmi_recv_msg *msg)
 {
+   atomic_dec(&dummy_count);
 }
 static struct ipmi_smi_msg halt_smi_msg =
 {
@@ -152,17 +155,28 @@ static int ipmi_request_wait_for_respons
return halt_recv_msg.msg.data[0];
 }
 
-/* We are in run-to-completion mode, no completion is desired. */
+/* Wait for message to complete, spinning. */
 static int ipmi_request_in_rc_mode(ipmi_user_tuser,
   struct ipmi_addr   *addr,
   struct kernel_ipmi_msg *send_msg)
 {
int rv;
 
+   atomic_set(&dummy_count, 2);
rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
  &halt_smi_msg, &halt_recv_msg, 0);
-   if (rv)
+   if (rv) {
+   atomic_set(&dummy_count, 0);
return rv;
+   }
+
+   /*
+* Spin until our message is done.
+*/
+   while (atomic_read(&dummy_count) > 0) {
+   ipmi_poll_interface(user);
+   barrier();
+   }
 
return halt_recv_msg.msg.data[0];
 }
@@ -531,9 +545,7 @@ static void ipmi_poweroff_function (void
return;
 
/* Use run-to-completion mode, since interrupts may be off. */
-   ipmi_user_set_run_to_completion(ipmi_user, 1);
specific_poweroff_func(ipmi_user);
-   ipmi_user_set_run_to_completion(ipmi_user, 0);
 }
 
 /* Wait for an IPMI interface to be installed, the first one installed
Index: linux-2.6.21/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.21.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.21/drivers/char/ipmi/ipmi_si_intf.c
@@ -809,56 +809,54 @@ static void sender(void*
return;
}
 
-   spin_lock_irqsave(&(smi_info->msg_lock), flags);
 #ifdef DEBUG_TIMING
do_gettimeofday(&t);
printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
 
if (smi_info->run_to_completion) {
-   /* If we are running to completion, then throw it in
-  the list and run transactions until everything is
-  clear.  Priority doesn't matter here. */
+   /*
+* If we are running to completion, then throw it in
+* the list and run transactions until everything is
+* clear.  Priority doesn't matter here.
+*/
+
+   /*
+* Run to completion means we are single-threaded, no
+* need for locks.
+*/
list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
 
-   /* We have to release the msg lock and claim the smi
-  lock in this case, because of race conditions. */
-   spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
-
-   spin_lock_irqsave(&a

[PATCH 4/8] IPMI: Don't grab locks in run-to-completion mode

2008-02-13 Thread Corey Minyard
From: Konstantin Baydarov <[EMAIL PROTECTED]>

This patch prevents deadlocks in IPMI panic handler caused by msg_lock
in smi_info structure and waiting_msgs_lock in ipmi_smi structure.
  
Signed-off-by: Konstantin Baydarov <[EMAIL PROTECTED]>
Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
@@ -289,7 +289,8 @@ static enum si_sm_result start_next_msg(
 
/* No need to save flags, we aleady have interrupts off and we
   already hold the SMI lock. */
-   spin_lock(&(smi_info->msg_lock));
+   if (!smi_info->run_to_completion)
+   spin_lock(&(smi_info->msg_lock));
 
/* Pick the high priority queue first. */
if (!list_empty(&(smi_info->hp_xmit_msgs))) {
@@ -329,7 +330,8 @@ static enum si_sm_result start_next_msg(
rv = SI_SM_CALL_WITHOUT_DELAY;
}
out:
-   spin_unlock(&(smi_info->msg_lock));
+   if (!smi_info->run_to_completion)
+   spin_unlock(&(smi_info->msg_lock));
 
return rv;
 }
Index: linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
@@ -351,8 +351,16 @@ struct ipmi_smi
 
/* Invalid data in an event. */
unsigned int invalid_events;
+
/* Events that were received with the proper format. */
unsigned int events;
+
+   /*
+* run_to_completion duplicate of smb_info, smi_info
+* and ipmi_serial_info structures. Used to decrease numbers of
+* parameters passed by "low" level IPMI code.
+*/
+   int run_to_completion;
 };
 #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev)
 
@@ -3451,8 +3459,9 @@ static int handle_new_recv_msg(ipmi_smi_
 void ipmi_smi_msg_received(ipmi_smi_t  intf,
   struct ipmi_smi_msg *msg)
 {
-   unsigned long flags;
+   unsigned long flags = 0; /* keep us warning-free. */
int   rv;
+   int   run_to_completion;
 
 
if ((msg->data_size >= 2)
@@ -3501,21 +3510,30 @@ void ipmi_smi_msg_received(ipmi_smi_t   
 
/* To preserve message order, if the list is not empty, we
tack this message onto the end of the list. */
-   spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+   run_to_completion = intf->run_to_completion;
+   barrier();
+   if (!run_to_completion)
+   spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
if (!list_empty(&intf->waiting_msgs)) {
list_add_tail(&msg->link, &intf->waiting_msgs);
-   spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+   if (!run_to_completion)
+   spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
goto out;
}
-   spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+   if (!run_to_completion)
+   spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);

rv = handle_new_recv_msg(intf, msg);
if (rv > 0) {
/* Could not handle the message now, just add it to a
list to handle later. */
-   spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+   run_to_completion = intf->run_to_completion;
+   barrier();
+   if (!run_to_completion)
+   spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
list_add_tail(&msg->link, &intf->waiting_msgs);
-   spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+   if (!run_to_completion)
+   spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
} else if (rv == 0) {
ipmi_free_smi_msg(msg);
}
@@ -3884,6 +3902,7 @@ static void send_panic_events(char *str)
/* Interface is not ready. */
continue;
 
+   intf->run_to_completion = 1;
/* Send the event announcing the panic. */
intf->handlers->set_run_to_completion(intf->send_info, 1);
i_ipmi_request(NULL,
@@ -4059,6 +4078,7 @@ static int panic_event(struct notifier_b
/* Interface is not ready. */
continue;
 
+   intf->run_to_completion = 1;
intf->handlers->set_run_to_completion(intf->send_info, 1);
}
 
--

[PATCH 5/8] IPMI: Don't print event queue full on every event

2008-02-13 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Don't print out that the event queue is full on every event, only
print something out when it becomes full or becomes not full.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.23/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.23.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.23/drivers/char/ipmi/ipmi_msghandler.c
@@ -253,7 +253,8 @@ struct ipmi_smi
spinlock_t   events_lock; /* For dealing with event stuff. */
struct list_head waiting_events;
unsigned int waiting_events_count; /* How many events in queue? */
-   int  delivering_events;
+   char delivering_events;
+   char event_msg_printed;
 
/* The event receiver for my BMC, only really used at panic
   shutdown as a place to store this. */
@@ -1075,6 +1076,11 @@ int ipmi_set_gets_events(ipmi_user_t use
list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link)
list_move_tail(&msg->link, &msgs);
intf->waiting_events_count = 0;
+   if (intf->event_msg_printed) {
+   printk(KERN_WARNING PFX "Event queue no longer"
+  " full\n");
+   intf->event_msg_printed = 0;
+   }
 
intf->delivering_events = 1;
spin_unlock_irqrestore(&intf->events_lock, flags);
@@ -3253,11 +3259,12 @@ static int handle_read_event_rsp(ipmi_sm
copy_event_into_recv_msg(recv_msg, msg);
list_add_tail(&(recv_msg->link), &(intf->waiting_events));
intf->waiting_events_count++;
-   } else {
+   } else if (!intf->event_msg_printed) {
/* There's too many things in the queue, discard this
   message. */
-   printk(KERN_WARNING PFX "Event queue full, discarding an"
-  " incoming event\n");
+   printk(KERN_WARNING PFX "Event queue full, discarding"
+  " incoming events\n");
+   intf->event_msg_printed = 1;
}
 
  out:
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 8/8] IPMI: Convert locked counters to atomics in the system interface

2008-02-13 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Atomics are faster and neater than locked counters.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
@@ -120,6 +120,22 @@ static struct device_driver ipmi_driver 
.bus = &platform_bus_type
 };
 
+struct smi_stats
+{
+   atomic_t short_timeouts;
+   atomic_t long_timeouts;
+   atomic_t timeout_restarts;
+   atomic_t idles;
+   atomic_t interrupts;
+   atomic_t attentions;
+   atomic_t flag_fetches;
+   atomic_t hosed_count;
+   atomic_t complete_transactions;
+   atomic_t events;
+   atomic_t watchdog_pretimeouts;
+   atomic_t incoming_messages;
+};
+
 struct smi_info
 {
intintf_num;
@@ -216,25 +232,17 @@ struct smi_info
unsigned char slave_addr;
 
/* Counters and things for the proc filesystem. */
-   spinlock_t count_lock;
-   unsigned long short_timeouts;
-   unsigned long long_timeouts;
-   unsigned long timeout_restarts;
-   unsigned long idles;
-   unsigned long interrupts;
-   unsigned long attentions;
-   unsigned long flag_fetches;
-   unsigned long hosed_count;
-   unsigned long complete_transactions;
-   unsigned long events;
-   unsigned long watchdog_pretimeouts;
-   unsigned long incoming_messages;
+   struct smi_stats stats;
 
 struct task_struct *thread;
 
struct list_head link;
 };
 
+#define smi_inc_stat(smi, stat) atomic_inc(&(smi)->stats.stat)
+#define smi_get_stat(smi, stat) \
+   ((unsigned int) atomic_read(&smi->stats.stat))
+
 #define SI_MAX_PARMS 4
 
 static int force_kipmid[SI_MAX_PARMS];
@@ -398,9 +406,7 @@ static void handle_flags(struct smi_info
  retry:
if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
/* Watchdog pre-timeout */
-   spin_lock(&smi_info->count_lock);
-   smi_info->watchdog_pretimeouts++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, watchdog_pretimeouts);
 
start_clear_flags(smi_info);
smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
@@ -545,9 +551,7 @@ static void handle_transaction_done(stru
smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
handle_flags(smi_info);
} else {
-   spin_lock(&smi_info->count_lock);
-   smi_info->events++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, events);
 
/* Do this before we deliver the message
   because delivering the message releases the
@@ -581,9 +585,7 @@ static void handle_transaction_done(stru
smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
handle_flags(smi_info);
} else {
-   spin_lock(&smi_info->count_lock);
-   smi_info->incoming_messages++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, incoming_messages);
 
/* Do this before we deliver the message
   because delivering the message releases the
@@ -700,18 +702,14 @@ static enum si_sm_result smi_event_handl
 
if (si_sm_result == SI_SM_TRANSACTION_COMPLETE)
{
-   spin_lock(&smi_info->count_lock);
-   smi_info->complete_transactions++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, complete_transactions);
 
handle_transaction_done(smi_info);
si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
}
else if (si_sm_result == SI_SM_HOSED)
{
-   spin_lock(&smi_info->count_lock);
-   smi_info->hosed_count++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, hosed_count);
 
/* Do the before return_hosed_msg, because that
   releases the lock. */
@@ -733,9 +731,7 @@ static enum si_sm_result smi_event_handl
{
unsigned char msg[2];
 
-   spin_lock(&smi_info->count_lock);
-   smi_info->attentions++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, attentions);
 
/* Got a attn, send down a get message flags to see
what's causing it.  It would be better to handl

Re: [PATCH 7/8] IPMI: convert locked counters to atomics

2008-02-13 Thread Corey Minyard

Andrew Morton wrote:

The code forgot to initialise all of these.

It just so happens that the all-bits-zero pattern works correctly for all
current architectures, so the code should work OK.  But there is no reason
(I hope) why an architecture cannot implement atomic_t as

struct atomic_t {
int counter;
spinlock_t lock;
};

in which case the results of ATOMIC_INIT() may _not_ be all-zeroes, in
which case the code will deadlock.

So.  It works, but it's grubby.   Do you still wish to proceed?
  

Thanks.  Don't proceed for now, I'll work up new patches.

-corey

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/8] IPMI: Run to completion fixes

2008-02-13 Thread Corey Minyard

Andrew Morton wrote:

On Wed, 13 Feb 2008 10:23:42 -0600
Corey Minyard <[EMAIL PROTECTED]> wrote:

  

From: Corey Minyard <[EMAIL PROTECTED]>

The "run_to_completion" mode was somewhat broken.  Locks need to be
avoided in run_to_completion mode, and it shouldn't be used by normal
users, just internally for panic situations.

This patch removes locks in run_to_completion mode and removes the
user call for setting the mode.  The only user was the poweroff
code, but it was easily converted to use the polling interface.

+   /*
+* Spin until our message is done.
+*/
+   while (atomic_read(&dummy_count) > 0) {
+   ipmi_poll_interface(user);
+   barrier();
+   }



we'd normally use cpu_relax() here.
  

Yes, that's what I should have used.  I'll submit a new patch to fix this.

-corey

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 6/8] IPMI: Update driver version

2008-02-14 Thread Corey Minyard

Andrew Morton wrote:

On Wed, 13 Feb 2008 10:30:48 -0600
Corey Minyard <[EMAIL PROTECTED]> wrote:

  

Enough bug fixes and changes that we need a new driver version.



Are none of them serious enough to warrant a 2.6.24.x backport?
  

No, nothing really terribly urgent.  Just minor stuff.

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/4] IPMI: convert locked counters to atomics

2008-02-14 Thread Corey Minyard
From: Konstantin Baydarov <[EMAIL PROTECTED]>

Atomics are a lot more efficient and neat than using a lock.
  
Signed-off-by: Konstantin Baydarov <[EMAIL PROTECTED]>
Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
@@ -67,7 +67,6 @@ static struct proc_dir_entry *proc_ipmi_
the max message timer.  This is in milliseconds. */
 #define MAX_MSG_TIMEOUT6
 
-
 /*
  * The main "user" data structure.
  */
@@ -186,6 +185,96 @@ struct bmc_device
struct device_attribute aux_firmware_rev_attr;
 };
 
+/*
+ * Various statistics for IPMI, these index stats[] in the ipmi_smi
+ * structure.
+ */
+/* Commands we got from the user that were invalid. */
+#define IPMI_STAT_sent_invalid_commands0
+
+/* Commands we sent to the MC. */
+#define IPMI_STAT_sent_local_commands  1
+
+/* Responses from the MC that were delivered to a user. */
+#define IPMI_STAT_handled_local_responses  2
+
+/* Responses from the MC that were not delivered to a user. */
+#define IPMI_STAT_unhandled_local_responses3
+
+/* Commands we sent out to the IPMB bus. */
+#define IPMI_STAT_sent_ipmb_commands   4
+
+/* Commands sent on the IPMB that had errors on the SEND CMD */
+#define IPMI_STAT_sent_ipmb_command_errs   5
+
+/* Each retransmit increments this count. */
+#define IPMI_STAT_retransmitted_ipmb_commands  6
+
+/* When a message times out (runs out of retransmits) this is incremented. */
+#define IPMI_STAT_timed_out_ipmb_commands  7
+
+/*
+ * This is like above, but for broadcasts.  Broadcasts are
+ * *not* included in the above count (they are expected to
+ * time out).
+ */
+#define IPMI_STAT_timed_out_ipmb_broadcasts8
+
+/* Responses I have sent to the IPMB bus. */
+#define IPMI_STAT_sent_ipmb_responses  9
+
+/* The response was delivered to the user. */
+#define IPMI_STAT_handled_ipmb_responses   10
+
+/* The response had invalid data in it. */
+#define IPMI_STAT_invalid_ipmb_responses   11
+
+/* The response didn't have anyone waiting for it. */
+#define IPMI_STAT_unhandled_ipmb_responses 12
+
+/* Commands we sent out to the IPMB bus. */
+#define IPMI_STAT_sent_lan_commands13
+
+/* Commands sent on the IPMB that had errors on the SEND CMD */
+#define IPMI_STAT_sent_lan_command_errs14
+
+/* Each retransmit increments this count. */
+#define IPMI_STAT_retransmitted_lan_commands   15
+
+/* When a message times out (runs out of retransmits) this is incremented. */
+#define IPMI_STAT_timed_out_lan_commands   16
+
+/* Responses I have sent to the IPMB bus. */
+#define IPMI_STAT_sent_lan_responses   17
+
+/* The response was delivered to the user. */
+#define IPMI_STAT_handled_lan_responses18
+
+/* The response had invalid data in it. */
+#define IPMI_STAT_invalid_lan_responses19
+
+/* The response didn't have anyone waiting for it. */
+#define IPMI_STAT_unhandled_lan_responses  20
+
+/* The command was delivered to the user. */
+#define IPMI_STAT_handled_commands 21
+
+/* The command had invalid data in it. */
+#define IPMI_STAT_invalid_commands 22
+
+/* The command didn't have anyone waiting for it. */
+#define IPMI_STAT_unhandled_commands   23
+
+/* Invalid data in an event. */
+#define IPMI_STAT_invalid_events   24
+
+/* Events that were received with the proper format. */
+#define IPMI_STAT_events   25
+
+/* When you add a statistic, you must update this value. */
+#define IPMI_NUM_STATS 26
+
+
 #define IPMI_IPMB_NUM_SEQ  64
 #define IPMI_MAX_CHANNELS   16
 struct ipmi_smi
@@ -286,75 +375,7 @@ struct ipmi_smi
struct proc_dir_entry *proc_dir;
char  proc_dir_name[10];
 
-   spinlock_t   counter_lock; /* For making counters atomic. */
-
-   /* Commands we got that were invalid. */
-   unsigned int sent_invalid_commands;
-
-   /* Commands we sent to the MC. */
-   unsigned int sent_local_commands;
-   /* Responses from the MC that were delivered to a user. */
-   unsigned int handled_local_responses;
-   /* Responses from the MC that were not delivered to a user. */
-   unsigned int unhandled_local_responses;
-
-   /* Commands we sent out to the IPMB bus. */
-   unsigned int sent_ipmb_commands;
-   /* Commands sent on the IPMB that had errors on the SEND CMD */
-   unsigned int sent_ipmb_command_errs;
-

[PATCH 1/4] IPMI: Change barrier to cpu_relax in poweroff code

2008-02-14 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Change a barrier to cpu_relax(), which is more appropriate for a
polling loop.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.24/drivers/char/ipmi/ipmi_poweroff.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_poweroff.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_poweroff.c
@@ -175,7 +175,7 @@ static int ipmi_request_in_rc_mode(ipmi_
 */
while (atomic_read(&dummy_count) > 0) {
ipmi_poll_interface(user);
-   barrier();
+   cpu_relax();
}
 
return halt_recv_msg.msg.data[0];
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/4] IPMI: Convert locked counters to atomics in the system interface

2008-02-14 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Atomics are faster and neater than locked counters.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---

Index: linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
@@ -120,6 +120,27 @@ static struct device_driver ipmi_driver 
.bus = &platform_bus_type
 };
 
+
+/*
+ * Indexes into stats[] in smi_info below.
+ */
+
+#define SI_STAT_short_timeouts 0
+#define SI_STAT_long_timeouts  1
+#define SI_STAT_timeout_restarts   2
+#define SI_STAT_idles  3
+#define SI_STAT_interrupts 4
+#define SI_STAT_attentions 5
+#define SI_STAT_flag_fetches   6
+#define SI_STAT_hosed_count7
+#define SI_STAT_complete_transactions  8
+#define SI_STAT_events 9
+#define SI_STAT_watchdog_pretimeouts   10
+#define SI_STAT_incoming_messages  11
+
+/* If you add a stat, you must update this value. */
+#define SI_NUM_STATS   12
+
 struct smi_info
 {
intintf_num;
@@ -216,25 +237,18 @@ struct smi_info
unsigned char slave_addr;
 
/* Counters and things for the proc filesystem. */
-   spinlock_t count_lock;
-   unsigned long short_timeouts;
-   unsigned long long_timeouts;
-   unsigned long timeout_restarts;
-   unsigned long idles;
-   unsigned long interrupts;
-   unsigned long attentions;
-   unsigned long flag_fetches;
-   unsigned long hosed_count;
-   unsigned long complete_transactions;
-   unsigned long events;
-   unsigned long watchdog_pretimeouts;
-   unsigned long incoming_messages;
+   atomic_t stats[SI_NUM_STATS];
 
 struct task_struct *thread;
 
struct list_head link;
 };
 
+#define smi_inc_stat(smi, stat) \
+   atomic_inc(&(smi)->stats[SI_STAT_ ## stat])
+#define smi_get_stat(smi, stat) \
+   ((unsigned int) atomic_read(&(smi)->stats[SI_STAT_ ## stat]))
+
 #define SI_MAX_PARMS 4
 
 static int force_kipmid[SI_MAX_PARMS];
@@ -398,9 +412,7 @@ static void handle_flags(struct smi_info
  retry:
if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
/* Watchdog pre-timeout */
-   spin_lock(&smi_info->count_lock);
-   smi_info->watchdog_pretimeouts++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, watchdog_pretimeouts);
 
start_clear_flags(smi_info);
smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
@@ -545,9 +557,7 @@ static void handle_transaction_done(stru
smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
handle_flags(smi_info);
} else {
-   spin_lock(&smi_info->count_lock);
-   smi_info->events++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, events);
 
/* Do this before we deliver the message
   because delivering the message releases the
@@ -581,9 +591,7 @@ static void handle_transaction_done(stru
smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
handle_flags(smi_info);
} else {
-   spin_lock(&smi_info->count_lock);
-   smi_info->incoming_messages++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, incoming_messages);
 
/* Do this before we deliver the message
   because delivering the message releases the
@@ -700,18 +708,14 @@ static enum si_sm_result smi_event_handl
 
if (si_sm_result == SI_SM_TRANSACTION_COMPLETE)
{
-   spin_lock(&smi_info->count_lock);
-   smi_info->complete_transactions++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, complete_transactions);
 
handle_transaction_done(smi_info);
si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
}
else if (si_sm_result == SI_SM_HOSED)
{
-   spin_lock(&smi_info->count_lock);
-   smi_info->hosed_count++;
-   spin_unlock(&smi_info->count_lock);
+   smi_inc_stat(smi_info, hosed_count);
 
/* Do the before return_hosed_msg, because that
   releases the lock. */
@@ -733,9 +737,7 @@ static enum si_sm_result smi_event_handl
{
unsigned char msg[2];
 
-   spin_lock(&smi_info->count_lock);
-  

[PATCH 2/4] IPMI: Remove unnecessary memory barriers

2008-02-14 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Remove some unnecessary barriers.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---
This can be folded into ipmi-dont-grab-locks-in-run-to-completion-mode.patch

Index: linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
@@ -3518,7 +3518,6 @@ void ipmi_smi_msg_received(ipmi_smi_t   
/* To preserve message order, if the list is not empty, we
tack this message onto the end of the list. */
run_to_completion = intf->run_to_completion;
-   barrier();
if (!run_to_completion)
spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
if (!list_empty(&intf->waiting_msgs)) {
@@ -3535,7 +3534,6 @@ void ipmi_smi_msg_received(ipmi_smi_t   
/* Could not handle the message now, just add it to a
list to handle later. */
run_to_completion = intf->run_to_completion;
-   barrier();
if (!run_to_completion)
spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
list_add_tail(&msg->link, &intf->waiting_msgs);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/4] IPMI: convert locked counters to atomics

2008-02-14 Thread Corey Minyard

Andrew Morton wrote:

+   for (i = 0; i < IPMI_NUM_STATS; i++)
+   atomic_set(&intf->stats[i], 0);



And this is why it would be very hard for any architecture to ever
implement atomic_t as

struct atomic_t {
int counter;
spinlock_t lock;
};

The interface assumes that atomic_set() fully initialises the atomic_t, and
that atomic_set() can be used agaisnt both an uninitialised atomic_t and
against an already-initialised atomic_t.  IOW, we don't have atomic_init().

So would our hypothetical future architcture's atomic_set() do spin_lock(),
or would it do spin_lock_init()?  Either one is wrong in many atomic_set
callsites.

Oh well.
  

Yeah, I thought the same thing when I did this.  Do we start working
on an atomic_init()?  It would be easy enough to set it to atomic_set()
for current architectures.

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Openipmi-developer] [PATCH 3/4] IPMI: convert locked counters to atomics

2008-02-15 Thread Corey Minyard

Peter Zijlstra wrote:

On Thu, 2008-02-14 at 12:30 -0600, Corey Minyard wrote:

  

+/* The command didn't have anyone waiting for it. */
+#define IPMI_STAT_unhandled_commands   23
+
+/* Invalid data in an event. */
+#define IPMI_STAT_invalid_events   24
+
+/* Events that were received with the proper format. */
+#define IPMI_STAT_events   25
+
+/* When you add a statistic, you must update this value. */
+#define IPMI_NUM_STATS 26



This shouts enum to me..
  
Someone else asked about this, and I wasn't too sure.  It seems from the 
CodingStyle document that enums are preferred for things like this, but 
I current kernel code seems a mixed bag.  An enum is cleaner and more 
reliable, IMHO.  I'll convert it, I think.


Thanks,

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/5] IPMI: convert message handler defines to an enum

2008-02-15 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Convert the #defines for statistics into an enum in the IPMI message
handler.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
Cc: Peter Zijlstra <[EMAIL PROTECTED]>
---
Ok to merge into ipmi-convert-locked-counters-to-atomics.patch

Index: linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_msghandler.c
@@ -189,90 +189,99 @@ struct bmc_device
  * Various statistics for IPMI, these index stats[] in the ipmi_smi
  * structure.
  */
-/* Commands we got from the user that were invalid. */
-#define IPMI_STAT_sent_invalid_commands0
+enum ipmi_stat_indexes {
+   /* Commands we got from the user that were invalid. */
+   IPMI_STAT_sent_invalid_commands = 0,
 
-/* Commands we sent to the MC. */
-#define IPMI_STAT_sent_local_commands  1
+   /* Commands we sent to the MC. */
+   IPMI_STAT_sent_local_commands,
 
-/* Responses from the MC that were delivered to a user. */
-#define IPMI_STAT_handled_local_responses  2
+   /* Responses from the MC that were delivered to a user. */
+   IPMI_STAT_handled_local_responses,
 
-/* Responses from the MC that were not delivered to a user. */
-#define IPMI_STAT_unhandled_local_responses3
+   /* Responses from the MC that were not delivered to a user. */
+   IPMI_STAT_unhandled_local_responses,
 
-/* Commands we sent out to the IPMB bus. */
-#define IPMI_STAT_sent_ipmb_commands   4
+   /* Commands we sent out to the IPMB bus. */
+   IPMI_STAT_sent_ipmb_commands,
 
-/* Commands sent on the IPMB that had errors on the SEND CMD */
-#define IPMI_STAT_sent_ipmb_command_errs   5
+   /* Commands sent on the IPMB that had errors on the SEND CMD */
+   IPMI_STAT_sent_ipmb_command_errs,
 
-/* Each retransmit increments this count. */
-#define IPMI_STAT_retransmitted_ipmb_commands  6
+   /* Each retransmit increments this count. */
+   IPMI_STAT_retransmitted_ipmb_commands,
 
-/* When a message times out (runs out of retransmits) this is incremented. */
-#define IPMI_STAT_timed_out_ipmb_commands  7
+   /*
+* When a message times out (runs out of retransmits) this is
+* incremented.
+*/
+   IPMI_STAT_timed_out_ipmb_commands,
 
-/*
- * This is like above, but for broadcasts.  Broadcasts are
- * *not* included in the above count (they are expected to
- * time out).
- */
-#define IPMI_STAT_timed_out_ipmb_broadcasts8
+   /*
+* This is like above, but for broadcasts.  Broadcasts are
+* *not* included in the above count (they are expected to
+* time out).
+*/
+   IPMI_STAT_timed_out_ipmb_broadcasts,
 
-/* Responses I have sent to the IPMB bus. */
-#define IPMI_STAT_sent_ipmb_responses  9
+   /* Responses I have sent to the IPMB bus. */
+   IPMI_STAT_sent_ipmb_responses,
 
-/* The response was delivered to the user. */
-#define IPMI_STAT_handled_ipmb_responses   10
+   /* The response was delivered to the user. */
+   IPMI_STAT_handled_ipmb_responses,
 
-/* The response had invalid data in it. */
-#define IPMI_STAT_invalid_ipmb_responses   11
+   /* The response had invalid data in it. */
+   IPMI_STAT_invalid_ipmb_responses,
 
-/* The response didn't have anyone waiting for it. */
-#define IPMI_STAT_unhandled_ipmb_responses 12
+   /* The response didn't have anyone waiting for it. */
+   IPMI_STAT_unhandled_ipmb_responses,
 
-/* Commands we sent out to the IPMB bus. */
-#define IPMI_STAT_sent_lan_commands13
+   /* Commands we sent out to the IPMB bus. */
+   IPMI_STAT_sent_lan_commands,
 
-/* Commands sent on the IPMB that had errors on the SEND CMD */
-#define IPMI_STAT_sent_lan_command_errs14
+   /* Commands sent on the IPMB that had errors on the SEND CMD */
+   IPMI_STAT_sent_lan_command_errs,
 
-/* Each retransmit increments this count. */
-#define IPMI_STAT_retransmitted_lan_commands   15
+   /* Each retransmit increments this count. */
+   IPMI_STAT_retransmitted_lan_commands,
 
-/* When a message times out (runs out of retransmits) this is incremented. */
-#define IPMI_STAT_timed_out_lan_commands   16
+   /*
+* When a message times out (runs out of retransmits) this is
+* incremented.
+*/
+   IPMI_STAT_timed_out_lan_commands,
 
-/* Responses I have sent to the IPMB bus. */
-#define IPMI_STAT_sent_lan_responses   17
+   /* Responses I have sent to the IPMB bus. */
+   IPMI_STAT_sent_lan_responses,
 
-/* The response was delivered to the user. */
-#define IPMI_STAT_handled_lan_respons

[PATCH 2/5] IPMI: Convert system interface defines to an enum

2008-02-15 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Convert the #defines for statistics into an enum in the IPMI system
interface and remove the unused timeout_restart statistic.  And comment
what these statistics mean.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
Cc: Peter Zijlstra <[EMAIL PROTECTED]>
---
Ok to merge into
ipmi-convert-locked-counters-to-atomics-in-the-system-interface.patch

Index: linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.24.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.24/drivers/char/ipmi/ipmi_si_intf.c
@@ -124,22 +124,50 @@ static struct device_driver ipmi_driver 
 /*
  * Indexes into stats[] in smi_info below.
  */
+enum si_stat_indexes {
+   /*
+* Number of times the driver requested a timer while an operation
+* was in progress.
+*/
+   SI_STAT_short_timeouts = 0,
+
+   /*
+* Number of times the driver requested a timer while nothing was in
+* progress.
+*/
+   SI_STAT_long_timeouts,
+
+   /* Number of times the interface was idle while being polled. */
+   SI_STAT_idles,
+
+   /* Number of interrupts the driver handled. */
+   SI_STAT_interrupts,
+
+   /* Number of time the driver got an ATTN from the hardware. */
+   SI_STAT_attentions,
 
-#define SI_STAT_short_timeouts 0
-#define SI_STAT_long_timeouts  1
-#define SI_STAT_timeout_restarts   2
-#define SI_STAT_idles  3
-#define SI_STAT_interrupts 4
-#define SI_STAT_attentions 5
-#define SI_STAT_flag_fetches   6
-#define SI_STAT_hosed_count7
-#define SI_STAT_complete_transactions  8
-#define SI_STAT_events 9
-#define SI_STAT_watchdog_pretimeouts   10
-#define SI_STAT_incoming_messages  11
+   /* Number of times the driver requested flags from the hardware. */
+   SI_STAT_flag_fetches,
 
-/* If you add a stat, you must update this value. */
-#define SI_NUM_STATS   12
+   /* Number of times the hardware didn't follow the state machine. */
+   SI_STAT_hosed_count,
+
+   /* Number of completed messages. */
+   SI_STAT_complete_transactions,
+
+   /* Number of IPMI events received from the hardware. */
+   SI_STAT_events,
+
+   /* Number of watchdog pretimeouts. */
+   SI_STAT_watchdog_pretimeouts,
+
+   /* Number of asyncronous messages received. */
+   SI_STAT_incoming_messages,
+
+
+   /* This *must* remain last, add new values above this. */
+   SI_NUM_STATS
+};
 
 struct smi_info
 {
@@ -2400,8 +2428,6 @@ static int stat_file_read_proc(char *pag
   smi_get_stat(smi, short_timeouts));
out += sprintf(out, "long_timeouts: %u\n",
   smi_get_stat(smi, long_timeouts));
-   out += sprintf(out, "timeout_restarts:  %u\n",
-  smi_get_stat(smi, timeout_restarts));
out += sprintf(out, "idles: %u\n",
   smi_get_stat(smi, idles));
out += sprintf(out, "interrupts:%u\n",
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch 3/5] IPMI: Style fixes in the base code

2008-02-15 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Lots of style fixes for the base IPMI driver.  No functional changes.
Basically fixes everything reported by checkpatch and fixes the comment
style.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Patch is too big for the list, per the Submitting Patches document.  It
is available at:

http://mysite.verizon.net/tcminyard/ipmi-style-fixes.patch
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch 4/5] IPMI: Style fixes in the system interface code

2008-02-15 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Lots of style fixes for the IPMI system interface driver.  No
functional changes.  Basically fixes everything reported by checkpatch
and fixes the comment style.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
Cc: Rocky Craig <[EMAIL PROTECTED]>
Cc: Hannes Schulz <[EMAIL PROTECTED]>

Patch is too big for the list, per the Submitting Patches document.  It
is available at:
http://mysite.verizon.net/tcminyard/ipmi-system-interface-style-fixes.patch
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[Patch 5/5] IPMI: Style fixes in the misc code

2008-02-15 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Lots of style fixes for the miscellaneous IPMI files.  No functional
changes.  Basically fixes everything reported by checkpatch and fixes
the comment style.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Patch is too big for the list, per the Submitting Patches document.  It
is available at:
http://mysite.verizon.net/tcminyard/ipmi-misc-style-fixes.patch
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ACPI: Reorder IPMI driver before any other ACPI drivers

2012-09-20 Thread Corey Minyard

On 09/20/2012 08:26 PM, Matthew Garrett wrote:

On Thu, Sep 20, 2012 at 08:19:48PM -0500, Corey Minyard wrote:

On 09/20/2012 04:46 PM, Matthew Garrett wrote:

Drivers may make calls that require the ACPI IPMI driver to have been
initialised already, so make sure that it appears earlier in the build
order.

The IPMI driver uses the ACPI namespace as an option to know the
address and characteristics of the device.  Does that still work?

Yes, the ACPI interpreter is initialised earlier than the IPMI driver
discovery.


Cool, I'm good with these, then.

Thanks,

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/5] IPMI: Fix some uninitialized warning

2012-10-26 Thread Corey Minyard

On 10/22/2012 06:49 PM, Andrew Morton wrote:

On Tue, 16 Oct 2012 15:53:39 -0500
miny...@acm.org wrote:


From: Corey Minyard 

There was a spot where the compiler couldn't tell some variables
would be set.  So initialize them to make the warning go away.

Signed-off-by: Corey Minyard 
---
  drivers/char/ipmi/ipmi_msghandler.c |2 +-
  1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c 
b/drivers/char/ipmi/ipmi_msghandler.c
index 2c29942..a0c84bb 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -1880,7 +1880,7 @@ int ipmi_request_supply_msgs(ipmi_user_t  user,
 struct ipmi_recv_msg *supplied_recv,
 int  priority)
  {
-   unsigned char saddr, lun;
+   unsigned char saddr = 0, lun = 0;
int   rv;
  
  	if (!user)

The kernel build actually generates quite a lot of "bar uninitialised"
warnings for foo(&bar) expressions.  I just ignore them, because later
versions of gcc stopped doing that.

The fix is OK, I suppose.  But it will cause additional code to be
emitted.  Using uninitialized_var() avoids that, and makes things
clearer to the reader.
Well, warnings annoy me, especially when I get the emails about them.  
But I suppose that's the point of the emails :).


I'll do a patch to switch it to uninitialized_var() for the next set of 
things I send.  Thanks.


-corey

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch v2] ipmi: info leak in compat_ipmi_ioctl()

2013-05-31 Thread Corey Minyard

On 05/31/2013 07:46 AM, Dan Carpenter wrote:

On x86_64 there is a 4 byte hole between ->recv_type and ->addr.


Got it, in my tree now.  Thanks.



Signed-off-by: Dan Carpenter 
---
v2: fixed the changelog a little.  Also added LKML because the
openipmi is a moderated list (and the moderator thought my email was
spam).


I apologize, the list gets a lot of spam, and I must have made a mistake.

-corey



diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 9eb360f..8e306ac 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -810,6 +810,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned 
int cmd,
struct ipmi_recv   __user *precv64;
struct ipmi_recv   recv64;
  
+		memset(&recv64, 0, sizeof(recv64));

if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
return -EFAULT;
  


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 03/13] ACPI/IPMI: Fix race caused by the unprotected ACPI IPMI transfers

2013-07-25 Thread Corey Minyard

On 07/25/2013 07:06 AM, Rafael J. Wysocki wrote:

On Thursday, July 25, 2013 03:09:35 AM Zheng, Lv wrote:

-stable according to the previous conversation.


From: Rafael J. Wysocki [mailto:r...@sisk.pl]
Sent: Thursday, July 25, 2013 7:38 AM

On Tuesday, July 23, 2013 04:09:15 PM Lv Zheng wrote:

This patch fixes races caused by unprotected ACPI IPMI transfers.

We can see the following crashes may occur:
1. There is no tx_msg_lock held for iterating tx_msg_list in
ipmi_flush_tx_msg() while it is parellel unlinked on failure in
acpi_ipmi_space_handler() under protection of tx_msg_lock.
2. There is no lock held for freeing tx_msg in acpi_ipmi_space_handler()
while it is parellel accessed in ipmi_flush_tx_msg() and
ipmi_msg_handler().

This patch enhances tx_msg_lock to protect all tx_msg accesses to
solve this issue.  Then tx_msg_lock is always held around complete()
and tx_msg accesses.
Calling smp_wmb() before setting msg_done flag so that messages
completed due to flushing will not be handled as 'done' messages while
their contents are not vaild.

Signed-off-by: Lv Zheng 
Cc: Zhao Yakui 
Reviewed-by: Huang Ying 
---
  drivers/acpi/acpi_ipmi.c |   10 --
  1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index
b37c189..527ee43 100644
--- a/drivers/acpi/acpi_ipmi.c
+++ b/drivers/acpi/acpi_ipmi.c
@@ -230,11 +230,14 @@ static void ipmi_flush_tx_msg(struct

acpi_ipmi_device *ipmi)

struct acpi_ipmi_msg *tx_msg, *temp;
int count = HZ / 10;
struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+   unsigned long flags;

+   spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
/* wake up the sleep thread on the Tx msg */
complete(&tx_msg->tx_complete);
}
+   spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);

/* wait for about 100ms to flush the tx message list */
while (count--) {
@@ -268,13 +271,12 @@ static void ipmi_msg_handler(struct

ipmi_recv_msg *msg, void *user_msg_data)

break;
}
}
-   spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);

if (!msg_found) {
dev_warn(&pnp_dev->dev,
 "Unexpected response (msg id %ld) is returned.\n",
 msg->msgid);
-   goto out_msg;
+   goto out_lock;
}

/* copy the response data to Rx_data buffer */ @@ -286,10 +288,14 @@
static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void

*user_msg_data)

}
tx_msg->rx_len = msg->msg.data_len;
memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len);
+   /* tx_msg content must be valid before setting msg_done flag */
+   smp_wmb();

That's suspicious.

If you need the write barrier here, you'll most likely need a read barrier
somewhere else.  Where's that?

It might depend on whether the content written before the smp_wmb() is used or 
not by the other side codes under the condition set after the smp_wmb().

So comment could be treated as 2 parts:
1. do we need a paired smp_rmb().
2. do we need a smp_wmb().

For 1.
If we want a paired smp_rmb(), then it will appear in this function:

186 static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
187 acpi_integer *value, int rem_time)
188 {
189 struct acpi_ipmi_buffer *buffer;
190
191 /*
192  * value is also used as output parameter. It represents the 
response
193  * IPMI message returned by IPMI command.
194  */
195 buffer = (struct acpi_ipmi_buffer *)value;
196 if (!rem_time && !msg->msg_done) {
197 buffer->status = ACPI_IPMI_TIMEOUT;
198 return;
199 }
200 /*
201  * If the flag of msg_done is not set or the recv length is zero, it
202  * means that the IPMI command is not executed correctly.
203  * The status code will be ACPI_IPMI_UNKNOWN.
204  */
205 if (!msg->msg_done || !msg->rx_len) {
206 buffer->status = ACPI_IPMI_UNKNOWN;
207 return;
208 }
+ smp_rmb();
209 /*
210  * If the IPMI response message is obtained correctly, the status 
code
211  * will be ACPI_IPMI_OK
212  */
213 buffer->status = ACPI_IPMI_OK;
214 buffer->length = msg->rx_len;
215 memcpy(buffer->data, msg->rx_data, msg->rx_len);
216 }

If we don't then there will only be msg content not correctly read from 
msg->rx_data.
Note that the rx_len is 0 during initialization and will never exceed the 
sizeof(buffer->data), so the read is safe.

Being without smp_rmb() is also OK in this case, since:
1. buffer->data will never be used when buffer->status is not ACPI_IPMI_OK and
2. the smp_rmb()/smp_wmb() added in this patch will be 

Re: [PATCH 03/13] ACPI/IPMI: Fix race caused by the unprotected ACPI IPMI transfers

2013-07-25 Thread Corey Minyard

On 07/25/2013 07:16 PM, Zheng, Lv wrote:


If I understand this correctly, the problem would be if:

rem_time = wait_for_completion_timeout(&tx_msg->tx_complete,
  IPMI_TIMEOUT);

returns on a timeout, then checks msg_done and races with something setting
msg_done.  If that is the case, you would need the smp_rmb() before checking
msg_done.

However, the timeout above is unnecessary.  You are using
ipmi_request_settime(), so you can set the timeout when the IPMI command
fails and returns a failure message.  The driver guarantees a return message
for each request.  Just remove the timeout from the completion, set the
timeout and retries in the ipmi request, and the completion should handle the
barrier issues.

It's just difficult for me to determine retry count and timeout value, maybe 
retry=0, timeout=IPMI_TIMEOUT is OK.
The code of the timeout completion is already there, I think the quick fix code 
should not introduce this logic.
I'll add a new patch to apply your comment.


Since it is a local BMC, I doubt a retry is required.  That is probably 
fine.  Or you could set retry=1 and timeout=IPMI_TIMEOUT/2 if you wanted 
to be more sure, but I doubt it would make a difference.  The only time 
you really need to worry about retries is if you are resetting the BMC 
or it is being overloaded.





Plus, from a quick glance at the code, it doesn't look like it will properly 
handle a
situation where the timeout occurs and is handled then the response comes in
later.

PATCH 07 fixed this issue.
Here we just need the smp_rmb() or holding tx_msg_lock() around the 
acpi_format_ipmi_response().


If you apply the fix like I suggest, then the race goes away.  If 
there's no timeout and it just waits for the completion, things get a 
lot simpler.




Thanks for commenting.


No problem, thanks for working on this.

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ipmi: ipmi_devintf: compat_ioctl method failes to take ipmi_mutex

2013-05-16 Thread Corey Minyard
Yes, you are right.  I've pulled this in to my tree.  Looking at this, 
ipmi_mutex really should go away and be replaced bu something that 
scales better, but I guess it's not that critical for IPMI.


-corey

On 05/13/2013 02:39 PM, Benjamin LaHaise wrote:

When a 32 bit version of ipmitool is used on a 64 bit kernel, the
ipmi_devintf code fails to correctly acquire ipmi_mutex.  This results in
incomplete data being retrieved in some cases, or other possible failures.
Add a wrapper around compat_ipmi_ioctl() to take ipmi_mutex to fix this.
This is probably a candidate for -stable as well.

Signed-off-by: Benjamin LaHaise 
---
  drivers/char/ipmi/ipmi_devintf.c |   14 +-
  1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 9eb360f..d5a5f02 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -837,13 +837,25 @@ static long compat_ipmi_ioctl(struct file *filep, 
unsigned int cmd,
return ipmi_ioctl(filep, cmd, arg);
}
  }
+
+static long unlocked_compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+  unsigned long arg)
+{
+   int ret;
+
+   mutex_lock(&ipmi_mutex);
+   ret = compat_ipmi_ioctl(filep, cmd, arg);
+   mutex_unlock(&ipmi_mutex);
+
+   return ret;
+}
  #endif
  
  static const struct file_operations ipmi_fops = {

.owner  = THIS_MODULE,
.unlocked_ioctl = ipmi_unlocked_ioctl,
  #ifdef CONFIG_COMPAT
-   .compat_ioctl   = compat_ipmi_ioctl,
+   .compat_ioctl   = unlocked_compat_ipmi_ioctl,
  #endif
.open   = ipmi_open,
.release= ipmi_release,


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/4] ipmi: Improve error messages on failed irq enable

2013-05-16 Thread Corey Minyard
When the interrupt enable message returns an error, the messages are
not entirely accurate nor helpful.  So improve them.

Signed-off-by: Corey Minyard 
Cc: Andy Lutomirski 
---
 drivers/char/ipmi/ipmi_si_intf.c |   16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 313538a..af4b23f 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -663,8 +663,10 @@ static void handle_transaction_done(struct smi_info 
*smi_info)
/* We got the flags from the SMI, now handle them. */
smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
if (msg[2] != 0) {
-   dev_warn(smi_info->dev, "Could not enable interrupts"
-", failed get, using polled mode.\n");
+   dev_warn(smi_info->dev,
+"Couldn't get irq info: %x.\n", msg[2]);
+   dev_warn(smi_info->dev,
+"Maybe ok, but ipmi might run very slowly.\n");
smi_info->si_state = SI_NORMAL;
} else {
msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
@@ -685,10 +687,12 @@ static void handle_transaction_done(struct smi_info 
*smi_info)
 
/* We got the flags from the SMI, now handle them. */
smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
-   if (msg[2] != 0)
-   dev_warn(smi_info->dev, "Could not enable interrupts"
-", failed set, using polled mode.\n");
-   else
+   if (msg[2] != 0) {
+   dev_warn(smi_info->dev,
+"Couldn't set irq info: %x.\n", msg[2]);
+   dev_warn(smi_info->dev,
+"Maybe ok, but ipmi might run very slowly.\n");
+   } else
smi_info->interrupt_disabled = 0;
smi_info->si_state = SI_NORMAL;
break;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/4] drivers: char: ipmi: Replaced kmalloc and strcpy with kstrdup

2013-05-16 Thread Corey Minyard
From: Alexandru Gheorghiu 

Replaced calls to kmalloc followed by strcpy with a sincle call to kstrdup.
Patch found using coccinelle.

Signed-off-by: Alexandru Gheorghiu 
Signed-off-by: Corey Minyard 
---
 drivers/char/ipmi/ipmi_msghandler.c |3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_msghandler.c 
b/drivers/char/ipmi/ipmi_msghandler.c
index 4d439d2..4445fa1 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2037,12 +2037,11 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
-   entry->name = kmalloc(strlen(name)+1, GFP_KERNEL);
+   entry->name = kstrdup(name, GFP_KERNEL);
if (!entry->name) {
kfree(entry);
return -ENOMEM;
}
-   strcpy(entry->name, name);
 
file = proc_create_data(name, 0, smi->proc_dir, proc_ops, data);
if (!file) {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/4] ipmi: Some minor fixes

2013-05-16 Thread Corey Minyard
Some minor fixes I had queued up.  The last one came in recently (patch 4) 
and it and patch 2 are candidates for stable-kernel.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/4] drivers/char/ipmi: memcpy, need additional 2 bytes to avoid memory overflow

2013-05-16 Thread Corey Minyard
From: Chen Gang 

  when calling memcpy, read_data and write_data need additional 2 bytes.

  write_data:
for checking:  "if (size > IPMI_MAX_MSG_LENGTH)"
for operating: "memcpy(bt->write_data + 3, data + 1, size - 1)"

  read_data:
for checking:  "if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH)"
for operating: "memcpy(data + 2, bt->read_data + 4, msg_len - 2)"

Signed-off-by: Chen Gang 
Signed-off-by: Corey Minyard 
Cc: sta...@vger.kernel.org
---
 drivers/char/ipmi/ipmi_bt_sm.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index cdd4c09f..a22a7a5 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -95,9 +95,9 @@ struct si_sm_data {
enum bt_states  state;
unsigned char   seq;/* BT sequence number */
struct si_sm_io *io;
-   unsigned char   write_data[IPMI_MAX_MSG_LENGTH];
+   unsigned char   write_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */
int write_count;
-   unsigned char   read_data[IPMI_MAX_MSG_LENGTH];
+   unsigned char   read_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */
int read_count;
int truncated;
longtimeout;/* microseconds countdown */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/4] ipmi: ipmi_devintf: compat_ioctl method fails to take ipmi_mutex

2013-05-16 Thread Corey Minyard
From: Benjamin LaHaise 

When a 32 bit version of ipmitool is used on a 64 bit kernel, the
ipmi_devintf code fails to correctly acquire ipmi_mutex.  This results in
incomplete data being retrieved in some cases, or other possible failures.
Add a wrapper around compat_ipmi_ioctl() to take ipmi_mutex to fix this.

Signed-off-by: Benjamin LaHaise 
Signed-off-by: Corey Minyard 
Cc: sta...@vger.kernel.org
---
 drivers/char/ipmi/ipmi_devintf.c |   14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 9eb360f..d5a5f02 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -837,13 +837,25 @@ static long compat_ipmi_ioctl(struct file *filep, 
unsigned int cmd,
return ipmi_ioctl(filep, cmd, arg);
}
 }
+
+static long unlocked_compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+  unsigned long arg)
+{
+   int ret;
+
+   mutex_lock(&ipmi_mutex);
+   ret = compat_ipmi_ioctl(filep, cmd, arg);
+   mutex_unlock(&ipmi_mutex);
+
+   return ret;
+}
 #endif
 
 static const struct file_operations ipmi_fops = {
.owner  = THIS_MODULE,
.unlocked_ioctl = ipmi_unlocked_ioctl,
 #ifdef CONFIG_COMPAT
-   .compat_ioctl   = compat_ipmi_ioctl,
+   .compat_ioctl   = unlocked_compat_ipmi_ioctl,
 #endif
.open   = ipmi_open,
.release= ipmi_release,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/4] ipmi: Improve error messages on failed irq enable

2013-05-16 Thread Corey Minyard

On 05/16/2013 05:23 PM, Andy Lutomirski wrote:


 /* We got the flags from the SMI, now handle them. */
 smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
-   if (msg[2] != 0)
-   dev_warn(smi_info->dev, "Could not enable interrupts"
-", failed set, using polled mode.\n");
-   else
+   if (msg[2] != 0) {
+   dev_warn(smi_info->dev,
+"Couldn't set irq info: %x.\n", msg[2]);
+   dev_warn(smi_info->dev,
+"Maybe ok, but ipmi might run very slowly.\n");
+   } else
Minor nit: it would be nice if these warnings were collapsed into a
single printk -- that would save me a whitelist entry of acceptable
KERN_WARNING messages :)


Yeah, the trouble is that checkpatch will give a warning if you split a 
string
between two lines or if a line is longer than 80 characters.  I'm not 
creative
enough to fit it into a single line.  Maybe I'm trying to be too literal 
here,

but I split it into two prints to avoid the warning.



My Dell 12g server says:

[97627.407724] ipmi_si ipmi_si.0: Using irq 10
[97627.421369] ipmi_si ipmi_si.0: Couldn't set irq info: cc.
[97627.427389] ipmi_si ipmi_si.0: Maybe ok, but ipmi might run very slowly.

Tested-by: Andy Lutomirski 


Thanks a bunch.

-corey


--Andy


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] drivers/char/ipmi: memcpy, need additional 2 bytes to avoid memory overflow

2013-03-29 Thread Corey Minyard

Yes, this is correct, I've pulled it into my tree.

-corey

On 03/29/2013 02:18 AM, Chen Gang wrote:

   when calling memcpy, read_data and write_data need additional 2 bytes.

   write_data:
 for checking:  "if (size > IPMI_MAX_MSG_LENGTH)"
 for operating: "memcpy(bt->write_data + 3, data + 1, size - 1)"

   read_data:
 for checking:  "if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH)"
 for operating: "memcpy(data + 2, bt->read_data + 4, msg_len - 2)"


Signed-off-by: Chen Gang 
---
  drivers/char/ipmi/ipmi_bt_sm.c |4 ++--
  1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index cdd4c09f..a22a7a5 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -95,9 +95,9 @@ struct si_sm_data {
enum bt_states  state;
unsigned char   seq;/* BT sequence number */
struct si_sm_io *io;
-   unsigned char   write_data[IPMI_MAX_MSG_LENGTH];
+   unsigned char   write_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */
int write_count;
-   unsigned char   read_data[IPMI_MAX_MSG_LENGTH];
+   unsigned char   read_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */
int read_count;
int truncated;
longtimeout;/* microseconds countdown */


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] CRIS: Fix I/O macros

2012-08-04 Thread Corey Minyard

Can we get something like this in?  It would fix a lot of build regressions.

-corey

On 07/09/2012 03:22 PM, miny...@acm.org wrote:

From: Corey Minyard 

The inb/outb macros for CRIS are broken from a number of points of
view, missing () around parameters and they have an unprotected if
statement in them.  This was breaking the compile of IPMI on CRIS
and thus I was being annoyed by build regressions, so I fixed them.

Plus I don't think they would have worked at all, since the data
values were missing "&" and the outsl had a "3" instead of a "4"
for the size.  From what I can tell, this stuff is not used at all,
so this can't be any more broken than it was before, anyway.

Signed-off-by: Corey Minyard 
---
  arch/cris/include/asm/io.h |   39 +--
  1 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h
index 32567bc..ac12ae2 100644
--- a/arch/cris/include/asm/io.h
+++ b/arch/cris/include/asm/io.h
@@ -133,12 +133,39 @@ static inline void writel(unsigned int b, volatile void 
__iomem *addr)
  #define insb(port,addr,count) (cris_iops ? 
cris_iops->read_io(port,addr,1,count) : 0)
  #define insw(port,addr,count) (cris_iops ? 
cris_iops->read_io(port,addr,2,count) : 0)
  #define insl(port,addr,count) (cris_iops ? 
cris_iops->read_io(port,addr,4,count) : 0)
-#define outb(data,port) if (cris_iops) 
cris_iops->write_io(port,(void*)(unsigned)data,1,1)
-#define outw(data,port) if (cris_iops) 
cris_iops->write_io(port,(void*)(unsigned)data,2,1)
-#define outl(data,port) if (cris_iops) 
cris_iops->write_io(port,(void*)(unsigned)data,4,1)
-#define outsb(port,addr,count) if(cris_iops) 
cris_iops->write_io(port,(void*)addr,1,count)
-#define outsw(port,addr,count) if(cris_iops) 
cris_iops->write_io(port,(void*)addr,2,count)
-#define outsl(port,addr,count) if(cris_iops) 
cris_iops->write_io(port,(void*)addr,3,count)
+static inline void outb(unsigned char data, unsigned int port)
+{
+   if (cris_iops)
+   cris_iops->write_io(port, (void *) &data, 1, 1);
+}
+static inline void outw(unsigned short data, unsigned int port)
+{
+   if (cris_iops)
+   cris_iops->write_io(port, (void *) &data, 2, 1);
+}
+static inline void outl(unsigned int data, unsigned int port)
+{
+   if (cris_iops)
+   cris_iops->write_io(port, (void *) &data, 4, 1);
+}
+static inline void outsb(unsigned int port, const void *addr,
+unsigned long count)
+{
+   if (cris_iops)
+   cris_iops->write_io(port, (void *)addr, 1, count);
+}
+static inline void outsw(unsigned int port, const void *addr,
+unsigned long count)
+{
+   if (cris_iops)
+   cris_iops->write_io(port, (void *)addr, 2, count);
+}
+static inline void outsl(unsigned int port, const void *addr,
+unsigned long count)
+{
+   if (cris_iops)
+   cris_iops->write_io(port, (void *)addr, 4, count);
+}
  
  /*

   * Convert a physical pointer to a virtual kernel pointer for /dev/mem


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ACPI: Reorder IPMI driver before any other ACPI drivers

2012-09-20 Thread Corey Minyard

On 09/20/2012 04:46 PM, Matthew Garrett wrote:

Drivers may make calls that require the ACPI IPMI driver to have been
initialised already, so make sure that it appears earlier in the build
order.


The IPMI driver uses the ACPI namespace as an option to know the address 
and characteristics of the device.  Does that still work?


-corey



Signed-off-by: Matthew Garrett 
---
  drivers/acpi/Makefile | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 47199e2..82422fe 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -47,6 +47,10 @@ acpi-y   += video_detect.o
  endif
  
  # These are (potentially) separate modules

+
+# IPMI may be used by other drivers, so it has to initialise before them
+obj-$(CONFIG_ACPI_IPMI)+= acpi_ipmi.o
+
  obj-$(CONFIG_ACPI_AC) += ac.o
  obj-$(CONFIG_ACPI_BUTTON) += button.o
  obj-$(CONFIG_ACPI_FAN)+= fan.o
@@ -70,6 +74,5 @@ processor-y   += processor_idle.o 
processor_thermal.o
  processor-$(CONFIG_CPU_FREQ)  += processor_perflib.o
  
  obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o

-obj-$(CONFIG_ACPI_IPMI)+= acpi_ipmi.o
  
  obj-$(CONFIG_ACPI_APEI)		+= apei/


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Openipmi-developer] [PATCH 3/4] IPMI: convert locked counters to atomics

2008-02-20 Thread Corey Minyard

Matt Domsch wrote:

On Thu, Feb 14, 2008 at 12:30:51PM -0600, Corey Minyard wrote:
  

From: Konstantin Baydarov <[EMAIL PROTECTED]>

Atomics are a lot more efficient and neat than using a lock.



per_cpu variables are a lot more efficient and neat than using locks
for simple statistics.  no cache line bouncing to increment the
counter.  Are these read so often that atomics are really better?
  
I agree, I'll put this in the plan for the future.  I don't have time to 
do it at this point, but the changes made in these patches should make 
it easy to change in the future.


Thanks,

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] Move console redirect to pid namespace

2013-02-14 Thread Corey Minyard

On 02/13/2013 01:08 PM, Eric W. Biederman wrote:

Bruno Prémont  writes:


CCing containers list

On Fri, 08 February 2013 miny...@acm.org wrote:

From: Corey Minyard 

The console redirect - ioctl(fd, TIOCCONS) - is not in a namespace,
thus a container can do a redirect and grab all the I/O on the host
and all container consoles.

This change puts the redirect in the pid namespace.

Signed-off-by: Corey Minyard 
---

I'm pretty sure this patch is not correct, but I'm not quite sure the
best way to fix this.  I'm not 100% sure that the pid namespace is the
right place, but it seemed the most reasonable of all the choices.  The
other obvious choice is the mount namespace, but it didn't seem as good
a fit.

With recent changes, tying it to init user namespace might even be
better.

With recent changes this is tied to the initial user namespace.  So the
simple solution to this and so many other similiar security problems is
to run your container in a user namespace.

The permission check currently is capable(CAP_SYS_ADMIN) which requires
the caller to have the CAP_SYS_ADMIN in the initial user namespace.


I'm not sure I follow.  Are these changes in k.org, or in another 
repository someplace?




Is there a desire to have TIOCCONS not just fail in a container but to
have TIOCCONS work in a container specific way?


Well, my desire is for the host console to work properly if a container 
uses TIOCCONS :-).  It seems to me that the most consistent way to 
handle this is to have TIOCCONS in a container redirect the container's 
console.





The other problem is that I don't think you can call fput() from
destroy_pid_namespace().  That can be called from interrupt context,
and I don't think fput() is safe there.  I know it's not safe in 3.4
with the RT patch applied.  However, the only way I've come up with to
fix it is to add a workqueue, and that seems a bit heavy for this.

Actually getting destroy_pid_namespace out of interrupt context wouldn't
be the worst thing in the world.


I would agree, but it would still require something like a workqueue.  
Is there a better mechanism?


-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] Move console redirect to pid namespace

2013-02-15 Thread Corey Minyard

On 02/14/2013 10:23 PM, Eric W. Biederman wrote:



With recent changes this is tied to the initial user namespace.  So the
simple solution to this and so many other similiar security problems is
to run your container in a user namespace.

The permission check currently is capable(CAP_SYS_ADMIN) which requires
the caller to have the CAP_SYS_ADMIN in the initial user namespace.

I'm not sure I follow.  Are these changes in k.org, or in another
repository someplace?

In k.org. 3.7 would work. 3.8-rcX would work even better.

root in a user namespace does not have permission to call TIOCCONS.


Ok, that's good enough for me.  I don't have a compelling reason to make 
it work, beyond liking consistency.


Thank you,

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ipmi: add new kernel options to prevent automatic ipmi init

2012-12-13 Thread Corey Minyard

Well, the built-in driver works on systems that have more than one interface
and more than one BMC, and multiple IPMBs (and all of the other channel
types for that matter, and the driver handles all the multiplexing and nasty
addressing).  There is, in fact, no arbitrary limit, and IBM tested
this fairly extensively with some of their systems.  I'm not sure why you
would need a custom driver, and if there are some custom things that need
to be done for your servers, I'd be happy to add that.  I've worked with a
number of other vendors to get changes like this in.  And then ipmitool,
freeipmi, openipmi, etc. will work with the device.

I don't have a big problem with this patch.  I wonder why you would want
to compile the standard driver into your kernel if you expected to load a
module with a custom driver later, though.  None of the distros I know of
compile it in, it's always a module.

You can also dynamically remove the device from the driver using the hot
add/remove capability.  To remove it, you can do:
  echo remove,`cat /proc/ipmi/0/params`
and it will disassociate that device (IPMI interface 0 in this case) 
from the

driver.  So you can iterate through all the devices in /proc/ipmi and
remove them all at startup.

If none of the above options work for you, we can go ahead with this
patch.  Just wanted to let you know that current options exist, and see
if you wanted to take a different direction.

-corey

On 12/13/2012 12:40 PM, Tony Camuso wrote:

The configuration change building ipmi_si into the kernel precludes the
use of a custom driver that can utilize more than one KCS interface,
multiple IPMBs, and more than one BMC. This capability is important for
fault-tolerant systems.

Even if the kernel option ipmi_si.trydefaults=0 is specified, ipmi_si
discovers and claims one of the KCS interfaces on a Stratus server.
The inability to now prevent the kernel from managing this device is a
regression from previous kernels. The regression breaks a capability
fault-tolerant vendors have relied upon.

To support both ACPI opregion access and the need to avoid activation
of ipmi_si on some platforms, we've added two new kernel options,
ipmi_si.tryacpi and ipmi_si.trydmi be added to prevent ipmi_si from
initializing when these options are set to 0 on the kernel command line.
With these options at the default value of 1, ipmi_si init proceeds
according to the kernel default.

Tested-by: Jim Paradis 
Signed-off-by: Robert Evans 
Signed-off-by: Jim Paradis 
Signed-off-by: Tony Camuso 
---
  drivers/char/ipmi/ipmi_si_intf.c | 28 
  1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 20ab5b3..0a441cf 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1208,6 +1208,12 @@ static int smi_num; /* Used to sequence the SMIs */
  #define DEFAULT_REGSPACING1
  #define DEFAULT_REGSIZE   1
  
+#ifdef CONFIG_ACPI

+static int   si_tryacpi = 1;
+#endif
+#ifdef CONFIG_DMI
+static int   si_trydmi = 1;
+#endif
  static bool  si_trydefaults = 1;
  static char  *si_type[SI_MAX_PARMS];
  #define MAX_SI_TYPE_STR 30
@@ -1238,6 +1244,16 @@ MODULE_PARM_DESC(hotmod, "Add and remove interfaces.  
See"
 " Documentation/IPMI.txt in the kernel sources for the"
 " gory details.");
  
+#ifdef CONFIG_ACPI

+module_param_named(tryacpi, si_tryacpi, bool, 0);
+MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the"
+" default scan of the interfaces identified via ACPI");
+#endif
+#ifdef CONFIG_DMI
+module_param_named(trydmi, si_trydmi, bool, 0);
+MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the"
+" default scan of the interfaces identified via DMI");
+#endif
  module_param_named(trydefaults, si_trydefaults, bool, 0);
  MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the"
 " default scan of the KCS and SMIC interface at the standard"
@@ -3408,16 +3424,20 @@ static int init_ipmi_si(void)
  #endif
  
  #ifdef CONFIG_ACPI

-   pnp_register_driver(&ipmi_pnp_driver);
-   pnp_registered = 1;
+   if (si_tryacpi) {
+   pnp_register_driver(&ipmi_pnp_driver);
+   pnp_registered = 1;
+   }
  #endif
  
  #ifdef CONFIG_DMI

-   dmi_find_bmc();
+   if (si_trydmi)
+   dmi_find_bmc();
  #endif
  
  #ifdef CONFIG_ACPI

-   spmi_find_bmc();
+   if (si_tryacpi)
+   spmi_find_bmc();
  #endif
  
  	/* We prefer devices with interrupts, but in the case of a machine


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ipmi: add new kernel options to prevent automatic ipmi init

2012-12-14 Thread Corey Minyard

On 12/14/2012 10:25 AM, Evans, Robert wrote:

Corey,

Thanks for the thoughtful reply.  Below I respond in detail to
these three points.

1) Why building a variant kernel with ipmi_si as a module is not
feasible.

2) User mode access to IPMI on Stratus systems (e.g. ipmitool).

3) ipmi_si hot removal seems to not work as needed.

Stratus might be able to use the hot removal option instead of the
proposed patch if hot removal can remove all interfaces from usage
by ipmi_si.  Our testing of this option was not successful as
shown below.

  - - -

1) Why building a variant kernel with ipmi_si as a module is not
feasible:

Stratus sells servers based upon Red Hat Enterprise Linux (RHEL).
In the next release of RHEL, ipmi_si will be built into the kernel
so that access to ACPI opregion is available early in kernel
startup.  Stratus systems run the Red Hat kernel so that the
system is certified and supported by Red Hat.  For this reason
using a custom kernel configured to build ipmi_si as a module is
not an option.


Yes, the RHEL engineer explained this to me, and it makes sense now. Thanks.




2) User mode access to IPMI on Stratus systems:

Although Stratus provides a replacement for ipmi_si, we depend
on ipmi_msghandler and ipmi_devintf.  The device /dev/ipmi0 is
present and this device is utilized by the user-mode system
management software Stratus supplies.

Therefore other programs like ipmitool can send IPMI commands and
get responses on Stratus systems.


Ah, ok. That's good.





3) Hot removal of the KCS interfaces discovered by ipmi_si seems
to not do enough... One KCS cannot successfully be removed:

Based upon your suggestion, we tried to use hot removal.  With
RHEL 6.4 Beta (kernel-2.6.32-343.el6), Stratus attempted to hot
remove the IPMI interfaces.  This was booted with
  "ipmi_si.trydefaults=0"
although we expect that kernel option to have no effect since a
BMC is found before the defaults would be tried.

This is logged when ipmi_si initializes indicating that both BMCs
were discovered:

ipmi message handler version 39.2
IPMI System Interface driver.
ipmi_si: Trying ACPI-specified kcs state machine at i/o address 0xca2,
slave address 0x0, irq 0
ipmi: Found new BMC (man_id: 0x77,  prod_id: 0x05c6, dev_id: 0x41)
IPMI kcs interface initialized
ipmi_si: Adding SMBIOS-specified kcs state machine
ipmi_si: Trying SMBIOS-specified kcs state machine at i/o address 0xda2,
slave address 0x20, irq 0
ipmi: interfacing existing BMC (man_id: 0x77, prod_id: 0x05c6,
dev_id: 0x41)
IPMI kcs interface initialized

Although there are two different BMCs, because it says
  "interfacing existing BMC"
it appears that ipmi_si assumes they are the same BMC.


That's happening in the message handler and it happens because the
manufacturer, product, and device id all match. From the spec:

   The Device ID is typically used in combination with the Product ID
   field such
   that the Device IDs for different controllers are unique under a
   given Product
   ID. A controller can optionally use the Device ID as an ‘instance’
   identifier if
   more than one controller of that kind is used in the system.
   (Section 20.1)

Different controllers in the same system are supposed to have different 
device

IDs.



Also, I notice the slave address for the first KCS (port CA2) seems
wrong.  Maybe these findings are relevant to what happens next.


Probably not relevant. It's not correct because, for some bizarre
reason, the slave address is not present in the ACPI information.
The slave address is only used by the message handler for the
IPMB return address on messages routed over IPMB.

It is odd that one interface is specified in ACPI and the other in DMI.
You can specify all of them in both tables.



After ipmi_si has been initialized, a script runs to load ftmod, the
module that contains the Stratus IPMI driver.  This code was added to
hot remove the interfaces discovered by ipmi_si before loading ftmod:

for i in $(cd /proc/ipmi; ls)
do
 dev="IPMI${i}"
 params="$(cat /proc/ipmi/${i}/params)"
 msg="Considering removal of dev: ${dev} ${params}"
 logger -p kern.info -t `basename ${0}` "${msg}"
 echo "${msg}" > /dev/console
 [ -n "${params}" ] &&
echo "remove,`cat /proc/ipmi/${i}/params`" \
> /sys/module/ipmi_si/parameters/hotmod
done

In the console log we can see this script run prior to loading the
Stratus ftmod.ko and we also see that ftmod exposes a BMC:

Considering removal of dev: IPMI0
kcs,i/o,0xca2,rsp=1,rsi=1,rsh=0,irq=0,ipmb=0
Considering removal of dev: IPMI1
kcs,i/o,0xda2,rsp=1,rsi=1,rsh=0,irq=0,ipmb=32
ftmod: module license 'LGPL' taints kernel.
Disabling lock debugging due to kernel taint
FTMOD version lsb-ft-ftmod-9.0.4-209
ftmod: GLOBAL_SIZE=4194304
ftmod: global_cc_memory 0x88003740
ipmi: Found new BMC (man_id: 0x00,  prod_id: 0x, dev_id: 0x00)
ipmi device interface

The KCS at port DA2 is removed from use by ipmi_si.  However, the

Re: [PATCH] namespace: Add an identifier to the namespace file

2012-09-26 Thread Corey Minyard
On 09/26/2012 07:48 PM, Eric W. Biederman wrote:
> I have fixed up Serge's email address and the linux-kernel email
> address.
>
> Corey Minyard  writes:
>
>> On 09/26/2012 07:16 PM, Eric W. Biederman wrote:
>>> miny...@acm.org writes:
>>>
>>>> From: Corey Minyard 
>>>>
>>>> Add a unique identifier to the network namespace file.  Each namespace
>>>> will have an identifier, making it possible to find if two programs are
>>>> in the same namespace, or if a program is using a persistent
>>>> namespace.
>>> Corey.
>>>
>>> Please have a peak inside of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git 
>>> userns-always-map-user-v59
>>>
>>> That implements consistent inode numbers across all of the
>>> /proc//ns/net files in the same network namespace so it is possible
>>> to detect if one task is in the same network namespace as another.
>>>
>>> I believe that should have what you need.
>> I did think about that, but I didn't do that for two reasons: 1) It
>> seemed to go against the grain of procfs (well, and it seemed harder,
>> too) and 2) I would like to add a netfilter based upon namespace.
>>
>> The first one is now moot, of course, but I'm not sure what to do about
>> the second one. I know we have customers that are using our current VRF
>> implementation to do exactly that, but I couldn't think of a way to do
>> that. Perhaps I can use the proc inode number, because it will be fixed.
>> I'll have to look into that.
> For netfilter or any other interface what should happen is that a file
> descriptor is passed in and the network namespace is derived from the
> file descriptor.
>
> Given that netfilter is per network namespace I'm not certain how
> filtering per network namespace would make sense.
>
> When I have poked my nose into netfilter I have had the hard problem
> that I have not figured out how to translate the parameters supplied
> by userspace into a more appropriate in kernel form, so I'm not certain
> how to implement passing a file descriptor into netfilter efficiently.

Yeah, that's kind of where I am stuck, too. netfilter used to be global,
so if it's not, this may be a "You can't do that any more".

>>> I need to get my act together on a merge strategy for that bit of code.
>>>
>>>
>>>> Signed-off-by: Corey Minyard 
>>>> ---
>>>> The persistent network namespaces are quite useful, but I really need
>>>> a way to determine if a program is running in one of these namespaces.
>>>> I'm not sure if this is the best way, but I couldn't come up with
>>>> much else that sounded feasible to me.
>>> A globally unique name that I need another to implement yet another
>>> namespace to deal with is something I don't even want to think about.
>> I'm not sure it's quite that bad :-).
> It is.
>
> Imagine a system with one netork namespace per user, running containers
> using vrfs.  It isn't hard to imagine plausible solutions that get you
> nested 3 deep.

I read through all the patches you had for this, and I realized what you
meant. Yeah, it's that bad.

Thanks again.

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] PM / IPMI: Remove empty legacy PCI PM callbacks

2012-07-06 Thread Corey Minyard

Looks fine to me.

Acked-by: Corey Minyard 

On 07/06/2012 03:02 PM, Rafael J. Wysocki wrote:

From: Rafael J. Wysocki 

The legacy PM callbacks provided by the IPMI PCI driver are
empty routines returning 0, so they can be safely dropped.

Signed-off-by: Rafael J. Wysocki 
---
  drivers/char/ipmi/ipmi_si_intf.c |   16 
  1 file changed, 16 deletions(-)

Index: linux/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux/drivers/char/ipmi/ipmi_si_intf.c
@@ -2503,18 +2503,6 @@ static void __devexit ipmi_pci_remove(st
cleanup_one_si(info);
  }
  
-#ifdef CONFIG_PM

-static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-   return 0;
-}
-
-static int ipmi_pci_resume(struct pci_dev *pdev)
-{
-   return 0;
-}
-#endif
-
  static struct pci_device_id ipmi_pci_devices[] = {
{ PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
{ PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
@@ -2527,10 +2515,6 @@ static struct pci_driver ipmi_pci_driver
.id_table = ipmi_pci_devices,
.probe =ipmi_pci_probe,
.remove =   __devexit_p(ipmi_pci_remove),
-#ifdef CONFIG_PM
-   .suspend =  ipmi_pci_suspend,
-   .resume =   ipmi_pci_resume,
-#endif
  };
  #endif /* CONFIG_PCI */
  



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Better precision in rusage and virtual itimers?

2000-11-13 Thread Corey Minyard

I've looked through the scheduling code and searched pretty much
everywhere I could think of and I've found nothing on this, so it's
time to escalate :-).

The measurement of CPU usage and virtual itimers is crude at best.
It's actually possible to set a relatively short virtual itimer (say,
50ms) and have it use almost no CPU before going off.  I have actually
had this happen.  For larger values and for gross rusage measurements,
this current scheme is probably ok, but for more fine-grained stuff it
is not ok.

Most, if not all, modern CPUs have a high-precision clock that could
easily track CPU usage down to the microsecond level.

My questions are: has anyone done any work on this?  If not, and, if I
was willing to do the work, would it be likely to be accepted?

What I would like to do is the following:

 * Add a way to get to a high-precision clock that architectures can
   provide.

 * Modify fields in task_struct to optionally support higher precision.

 * Add some optional code before and after switch_to() to update the
   timer values and rusage values.

 * Add a way for architectures to report when they enter and leave
   system code (for tracking system verses user usage).

All of this, of course, would be optional and the old way would still
be available.

Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/



Problem autonegotiation with tulip driver?

2000-11-13 Thread Corey Minyard

In the current version (and may previous versions) of the tulip driver
in media.c in the function tulip_select_media() with mleaf->type being
2 or 4, we have the following code:

  if (p[1] & 0x40) {  /* SIA (CSR13-15) setup values are provided. */
  csr13val = setup[0];
  csr14val = setup[1];
  csr15dir = (setup[3]<<16) | setup[2];
  csr15val = (setup[4]<<16) | setup[2];
  outl(0, ioaddr + CSR13);
  outl(csr14val, ioaddr + CSR14);
  outl(csr15dir, ioaddr + CSR15); /* Direction */
  outl(csr15val, ioaddr + CSR15); /* Data */
  outl(csr13val, ioaddr + CSR13);
  } else {
  csr13val = 1;
  csr14val = 0x0003FF7F;
 ^^
  csr15dir = (setup[0]<<16) | 0x0008;
  csr15val = (setup[1]<<16) | 0x0008;

In the value underscored above, autonegotiation of the media is turned
off if the eeprom doesn't provide the CSR14 value.  This doesn't seem
right (and doesn't work on our Ramix cards), it seems like you would
want to leave autonegotiation on here (the value would be 0x0003).
Without this, our Ramix cards will not autonegotiate.  With the
change, they work great.

Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/



Problem autonegotiation with tulip driver?

2000-11-13 Thread Corey Minyard

In the current version (and may previous versions) of the tulip driver
in media.c in the function tulip_select_media() with mleaf->type being
2 or 4, we have the following code:

  if (p[1] & 0x40) {  /* SIA (CSR13-15) setup values are provided. */
  csr13val = setup[0];
  csr14val = setup[1];
  csr15dir = (setup[3]<<16) | setup[2];
  csr15val = (setup[4]<<16) | setup[2];
  outl(0, ioaddr + CSR13);
  outl(csr14val, ioaddr + CSR14);
  outl(csr15dir, ioaddr + CSR15); /* Direction */
  outl(csr15val, ioaddr + CSR15); /* Data */
  outl(csr13val, ioaddr + CSR13);
  } else {
  csr13val = 1;
  csr14val = 0x0003FF7F;
 ^^
  csr15dir = (setup[0]<<16) | 0x0008;
  csr15val = (setup[1]<<16) | 0x0008;

In the value underscored above, autonegotiation of the media is turned
off if the eeprom doesn't provide the CSR14 value.  This doesn't seem
right (and doesn't work on our Ramix cards), it seems like you would
want to leave autonegotiation on here (the value would be 0x0003).
Without this, our Ramix cards will not autonegotiate.  With the
change, they work great.

Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/



[PATCH] Make CPU usage and virtual itimers accurate

2000-11-16 Thread Corey Minyard

I have patches written to improve the accuracy of CPU measurement
(getrusage()) and virtual itimers.  This lets the amount of CPU used
by a process be measured fairly accurately.  The patches are on my web
page: http://members.home.com/minyard

This is if anyone is interested.  I don't know if anyone has any
interest in putting these into the main kernel.  The patches are only
turned on if the configuration option is set on, so it shouldn't
affect anything otherwise.

Patches are against 2.4.0-test10 and 2.2.16.  I have not tested the
2.2.16 patch yet.

Some text from the web page:

The current method of measure CPU usage of a process in Linux is crude
at best.  For most applications, that is fine, but for some it is
critical to know how much CPU you have used.  Also, using setitimer's
viritual timers have a rather crude measurement mechanism, if the
timer tick hits when the task is running then an entire tick is added
to the processes time.  It's actually possible to use no CPU and still
time out.  CPU measurement is done the same way.

The following patch fixes all that.  They add a kernel configuration
parameter that allows high-resolution (microsecond) timing of task CPU
usage.  There are a few caveats:

 * It only works on PowerPC right now.  If someone wants to do an
   Intel port (or another platform port), feel free to send me the
   patches.

 * It costs extra time in interrupts, exceptions, and system calls.
   There is no real way around this, to accurately count system time
   verses user time you have to know when the kernel is running verses
   the user process.  (If you don't enable the configuration option,
   there is no affect from the patch)

 * There is some wierd interaction with gettimeofday.  If I have a
   loop calling gettimeofday, the system doesn't seem to keep time
   properly.  I haven't figured this out yet.  It may not be this
   patch, either.  As long as you don't use gettimeofday a few
   thousand times a second, though, you should be ok.

 * The patches are new and, of course, experimental.  They may crash
   your system and destroy all your data.

 * I have not tested the 2.2.16 patch at all, I have just gotten it to
   compile.


Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/



[PATCH] Remove redundancy from i2c-core.c

2005-04-06 Thread Corey Minyard

Call i2c_transfer() from i2c_master_send() and i2c_master_recv()
to avoid the redundant code that was in all three functions.  It
also removes unnecessary debug statements as suggested by Jean
Delvare.

This is important for the non-blocking interfaces because they
will have to handle a non-blocking interface in this area.  Having
it in one place greatly simplifies the changes.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.12-rc1/drivers/i2c/i2c-core.c
===
--- linux-2.6.12-rc1.orig/drivers/i2c/i2c-core.c
+++ linux-2.6.12-rc1/drivers/i2c/i2c-core.c
@@ -612,27 +612,17 @@
 	struct i2c_adapter *adap=client->adapter;
 	struct i2c_msg msg;
 
-	if (client->adapter->algo->master_xfer) {
-		msg.addr   = client->addr;
-		msg.flags = client->flags & I2C_M_TEN;
-		msg.len = count;
-		msg.buf = (char *)buf;
+	msg.addr   = client->addr;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.len = count;
+	msg.buf = (char *)buf;
 	
-		dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
-			count);
-	
-		down(&adap->bus_lock);
-		ret = adap->algo->master_xfer(adap,&msg,1);
-		up(&adap->bus_lock);
-
-		/* if everything went ok (i.e. 1 msg transmitted), return #bytes
-		 * transmitted, else error code.
-		 */
-		return (ret == 1 )? count : ret;
-	} else {
-		dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-		return -ENOSYS;
-	}
+	ret = i2c_transfer(adap, &msg, 1);
+
+	/* if everything went ok (i.e. 1 msg transmitted), return #bytes
+	 * transmitted, else error code.
+	 */
+	return (ret == 1 )? count : ret;
 }
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
@@ -640,31 +630,19 @@
 	struct i2c_adapter *adap=client->adapter;
 	struct i2c_msg msg;
 	int ret;
-	if (client->adapter->algo->master_xfer) {
-		msg.addr   = client->addr;
-		msg.flags = client->flags & I2C_M_TEN;
-		msg.flags |= I2C_M_RD;
-		msg.len = count;
-		msg.buf = buf;
 
-		dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
-			count);
-	
-		down(&adap->bus_lock);
-		ret = adap->algo->master_xfer(adap,&msg,1);
-		up(&adap->bus_lock);
-	
-		dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n",
-			ret, count, client->addr);
-	
-		/* if everything went ok (i.e. 1 msg transmitted), return #bytes
-	 	* transmitted, else error code.
-	 	*/
-		return (ret == 1 )? count : ret;
-	} else {
-		dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-		return -ENOSYS;
-	}
+	msg.addr   = client->addr;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.flags |= I2C_M_RD;
+	msg.len = count;
+	msg.buf = buf;
+
+	ret = i2c_transfer(adap, &msg, 1);
+
+	/* if everything went ok (i.e. 1 msg transmitted), return #bytes
+	 * transmitted, else error code.
+	 */
+	return (ret == 1 )? count : ret;
 }
 
 


Re: [PATCH 2.6.11.6] Add power cycle to ipmi_poweroff module

2005-04-08 Thread Corey Minyard
[EMAIL PROTECTED] wrote:
Below is a patch to add "power cycle" functionality to the IPMI power
off module ipmi_poweroff.
A new module param is added to support this:
parmtype:   do_power_cycle:int
parm:   do_power_cycle: Set to 1 to enable power cycle instead
of power down. Power cycle is contingent on hardware support, otherwise
it defaults back to power down.
This parameter can also be dynamically modified through the proc
filesystem:
/proc/ipmi//poweroff
 

This should probably be /proc/sys/dev/ipmi/power_cycle_on_halt.  Most 
things to control a system go there.  The /proc/sys/dev/ipmi directory 
should probably be created by the base IPMI file, too.

Thinking about it a little more, this should really be an option for 
reset, not for power off (thus making the name power_cycle_on_reset).  
I'm not sure how easy that will be to tie into.  It doesn't look easy; 
there's not something like pm_power_off for reset.

All the proc fs stuff should be ifdef-ed appropriately so it will 
compile with procfs turned off.

-Corey
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 <[EMAIL PROTECTED]>
--
Chris Poblete
Software Engineer
Dell OpenManage Instrumentation
= drivers/char/ipmi/ipmi_poweroff.c linux-2.6.11.6 vi edited =
--- linux-2.6.11.6/drivers/char/ipmi/ipmi_poweroff.c.orig
2005-03-25 21:28:22.0 -0600
+++ linux-2.6.11.6/drivers/char/ipmi/ipmi_poweroff.c2005-04-07
18:36:10.656537656 -0500
@@ -34,6 +34,8 @@
#include 
#include 
#include 
+#include 
+#include 
#include 
#include 
#include 
@@ -41,6 +43,13 @@
#define PFX "IPMI poweroff: "
#define IPMI_POWEROFF_VERSION   "v33"
+/* container to flag power cycle instead of power down */
+static int do_power_cycle = 0;
+
+/* parameter definition to allow user to flag power cycle */
+module_param(do_power_cycle, int, 0);
+MODULE_PARM_DESC(do_power_cycle, " Set to 1 to enable power cycle
instead of power down. Power cycle is contingent on hardware support,
otherwise it defaults back to power down.");
+
/* Where to we insert our poweroff function? */
extern void (*pm_power_off)(void);
@@ -349,23 +358,37 @@ static void ipmi_poweroff_chassis (ipmi_
smi_addr.channel = IPMI_BMC_CHANNEL;
smi_addr.lun = 0;
-   printk(KERN_INFO PFX "Powering down via IPMI chassis control
command\n");
+ powercyclefailed:
+   printk(KERN_INFO PFX "Powering %s via IPMI chassis control
command\n",
+   ((do_power_cycle != 1) ? "down" : "cycle"));
/*
 * Power down
 */
send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
-   data[0] = 0; /* Power down */
+   if (do_power_cycle != 1) {
+   data[0] = 0; /* Power down */
+   } else {
+   data[0] = 2; /* Power cycle */
+   }
send_msg.data = data;
send_msg.data_len = sizeof(data);
rv = ipmi_request_in_rc_mode(user,
 (struct ipmi_addr *) &smi_addr,
 &send_msg);
if (rv) {
-   printk(KERN_ERR PFX "Unable to send chassis powerdown
message,"
-  " IPMI error 0x%x\n", rv);
-   goto out;
+   if (do_power_cycle != 1) {
+   printk(KERN_ERR PFX "Unable to send chassis
power " \
+   "down message, IPMI error 0x%x\n", rv);
+   goto out;
+} else {
+   /* power cycle failed, default to power down */
+   printk(KERN_ERR PFX "Unable to send chassis
power " \
+   "cycle message, IPMI error 0x%x\n", rv);
+   do_power_cycle = 0;
+   goto powercyclefailed;
+}
}
 out:
@@ -418,6 +441,110 @@ static void ipmi_poweroff_function (void
ipmi_user_set_run_to_completion(ipmi_user, 0);
}
+/* procfs global memory */
+static struct proc_dir_entry *proc_ipo_root = NULL;
+static struct proc_dir_entry *proc_ipo_dir = NULL;
+static char ipo_dirname[4];
+
+/* displays properties to proc */
+static int proc_read_do_power_cycle(char *page, char **start,
+   off_t off, int count,
+   int *eof, void *data)
+{
+   /* sanity check */
+   if (data != NULL) {
+   return spri

Re: [PATCH 2.6.11.6] Add power cycle to ipmi_poweroff module

2005-04-08 Thread Corey Minyard
[EMAIL PROTECTED] wrote:
The message handler and si are already using /proc/ipmi/. The
patch code simply reuse it. By the way, shouldn't we be using sysfs?
 

Yes, we should.  There's not much sysfs support in the ipmi driver yet; 
a patch to add class stuff is in the mm kernels, but nothing for the 
device stuff.

As for separating from power_off, it just seem so simple to integrate
the power cycle command into the power_off code. It could definitely be
a separate module.
 

It's probably ok to leave it like it is for now.  I really wasn't 
talking about separating, I was talking about what user operation causes 
the power cycle.  It would be nice if you could tie this to reset 
instead of poweroff, but that's not a huge deal.  It would take a while 
to get that infrastructure into the kernel.

-Corey
Thanks,
-Chris Poblete
-Original Message-
From: Corey Minyard [mailto:[EMAIL PROTECTED] 
Sent: Friday, April 08, 2005 10:35 AM
To: Poblete, Chris
Cc: linux-kernel@vger.kernel.org; [EMAIL PROTECTED]
Subject: Re: [PATCH 2.6.11.6] Add power cycle to ipmi_poweroff module

[EMAIL PROTECTED] wrote:
 

Below is a patch to add "power cycle" functionality to the IPMI power 
off module ipmi_poweroff.

A new module param is added to support this:
parmtype:   do_power_cycle:int
parm:   do_power_cycle: Set to 1 to enable power cycle instead
of power down. Power cycle is contingent on hardware support, otherwise
   

 

it defaults back to power down.
This parameter can also be dynamically modified through the proc
filesystem:
/proc/ipmi//poweroff
   

This should probably be /proc/sys/dev/ipmi/power_cycle_on_halt.  Most
things to control a system go there.  The /proc/sys/dev/ipmi directory
should probably be created by the base IPMI file, too.
Thinking about it a little more, this should really be an option for
reset, not for power off (thus making the name power_cycle_on_reset).  
I'm not sure how easy that will be to tie into.  It doesn't look easy;
there's not something like pm_power_off for reset.

All the proc fs stuff should be ifdef-ed appropriately so it will
compile with procfs turned off.
-Corey
 

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 <[EMAIL PROTECTED]>
--
Chris Poblete
Software Engineer
Dell OpenManage Instrumentation
= drivers/char/ipmi/ipmi_poweroff.c linux-2.6.11.6 vi edited =
--- linux-2.6.11.6/drivers/char/ipmi/ipmi_poweroff.c.orig
2005-03-25 21:28:22.0 -0600
+++ linux-2.6.11.6/drivers/char/ipmi/ipmi_poweroff.c2005-04-07
18:36:10.656537656 -0500
@@ -34,6 +34,8 @@
#include 
#include 
#include 
+#include 
+#include 
#include 
#include 
#include 
@@ -41,6 +43,13 @@
#define PFX "IPMI poweroff: "
#define IPMI_POWEROFF_VERSION   "v33"
+/* container to flag power cycle instead of power down */ static int 
+do_power_cycle = 0;
+
+/* parameter definition to allow user to flag power cycle */ 
+module_param(do_power_cycle, int, 0); MODULE_PARM_DESC(do_power_cycle,
   

 

+" Set to 1 to enable power cycle
instead of power down. Power cycle is contingent on hardware support, 
otherwise it defaults back to power down.");
+
/* Where to we insert our poweroff function? */ extern void 
(*pm_power_off)(void);

@@ -349,23 +358,37 @@ static void ipmi_poweroff_chassis (ipmi_
   smi_addr.channel = IPMI_BMC_CHANNEL;
   smi_addr.lun = 0;
-   printk(KERN_INFO PFX "Powering down via IPMI chassis control
command\n");
+ powercyclefailed:
+   printk(KERN_INFO PFX "Powering %s via IPMI chassis control
command\n",
+   ((do_power_cycle != 1) ? "down" : "cycle"));
/*
 * Power down
 */
send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
-   data[0] = 0; /* Power down */
+   if (do_power_cycle != 1) {
+   data[0] = 0; /* Power down */
+   } else {
+   data[0] = 2; /* Power cycle */
+   }
send_msg.data = data;
send_msg.data_len = sizeof(data);
rv = ipmi_request_in_rc_mode(user,
 (struct ipmi_addr *) &smi_addr,
 &send_msg);
if (rv) {
-   prin

Re: dmi_table counting in ipmi_si_intf.c

2005-08-09 Thread Corey Minyard
I have no idea why that value was a "1".  However, looking at this, the 
"0" does seem correct; this is a valid patch.


-Corey

Vernon Mauery wrote:


I am working on getting one of the IBM blades to use ipmi and have run
into a problem.  The driver doesn't load because it says it can't find
the device.

dmidecode shows that there are 39 entries and that the last one is the
BMC.  I looked into dmi_table and noticed that it parses the table by
length and by number of entries.  But I found that it goes from i=1 to
i
---

diff -uar a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
--- a/drivers/char/ipmi/ipmi_si_intf.c  2005-08-09 08:11:41.0 -0700
+++ b/drivers/char/ipmi/ipmi_si_intf.c  2005-08-09 08:12:51.0 -0700
@@ -1690,7 +1690,7 @@ static int dmi_table(u32 base, int len, 
	u8 		  __iomem *buf;

struct dmi_header __iomem *dm;
u8__iomem *data;
-   int   i=1;
+   int   i=0;
int   status=-1;
int   intf_num = 0;



 



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 4/5] 2.6.13-rc5-mm1, IPMI, use dmi_find_device()

2005-08-10 Thread Corey Minyard
Andrew, this patch (along with the patch 3/5) works fine for me and is
an obvious improvement to the IPMI driver.  You will need to remove the
patch named dmi_table-counting-in-ipmi_si_intfc.patch first.

Thanks, Andrey.

-Corey

On Wed, 2005-08-10 at 14:32 +0400, Andrey Panin wrote:
> This patch replaces homebrew DMI scanning code in IPMI System Interface driver
> with dmi_find_device() call.
> 
> Signed-off-by: Andrey Panin <[EMAIL PROTECTED]>
> 
>  drivers/char/ipmi/ipmi_si_intf.c |  105 
> ++-
>  1 files changed, 17 insertions(+), 88 deletions(-)
> 
> diff -urdpNX /usr/share/dontdiff 
> linux-2.6.13-rc5-mm1.vanilla/drivers/char/ipmi/ipmi_si_intf.c 
> linux-2.6.13-rc5-mm1/drivers/char/ipmi/ipmi_si_intf.c
> --- linux-2.6.13-rc5-mm1.vanilla/drivers/char/ipmi/ipmi_si_intf.c 
> 2005-08-08 14:32:07.0 +0400
> +++ linux-2.6.13-rc5-mm1/drivers/char/ipmi/ipmi_si_intf.c 2005-08-08 
> 11:39:00.0 +0400
> @@ -75,6 +75,7 @@ static inline void add_usec_to_timer(str
>  #include 
>  #include "ipmi_si_sm.h"
>  #include 
> +#include 
>  
>  /* Measure times between events in the driver. */
>  #undef DEBUG_TIMING
> @@ -1642,22 +1643,15 @@ typedef struct dmi_ipmi_data
>  static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
>  static int dmi_data_entries;
>  
> -typedef struct dmi_header
> -{
> - u8  type;
> - u8  length;
> - u16 handle;
> -} dmi_header_t;
> -
> -static int decode_dmi(dmi_header_t __iomem *dm, int intf_num)
> +static int __init decode_dmi(struct dmi_header *dm, int intf_num)
>  {
> - u8  __iomem *data = (u8 __iomem *)dm;
> + u8 *data = (u8 *)dm;
>   unsigned long   base_addr;
>   u8  reg_spacing;
> - u8  len = readb(&dm->length);
> + u8  len = dm->length;
>   dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
>  
> - ipmi_data->type = readb(&data[4]);
> + ipmi_data->type = data[4];
>  
>   memcpy(&base_addr, data+8, sizeof(unsigned long));
>   if (len >= 0x11) {
> @@ -1672,12 +1666,12 @@ static int decode_dmi(dmi_header_t __iom
>   }
>   /* If bit 4 of byte 0x10 is set, then the lsb for the address
>  is odd. */
> - ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) 
> >> 4);
> + ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
>  
> - ipmi_data->irq = readb(&data[0x11]);
> + ipmi_data->irq = data[0x11];
>  
>   /* The top two bits of byte 0x10 hold the register spacing. */
> - reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6;
> + reg_spacing = (data[0x10] & 0xC0) >> 6;
>   switch(reg_spacing){
>   case 0x00: /* Byte boundaries */
>   ipmi_data->offset = 1;
> @@ -1705,7 +1699,7 @@ static int decode_dmi(dmi_header_t __iom
>   ipmi_data->offset = 1;
>   }
>  
> - ipmi_data->slave_addr = readb(&data[6]);
> + ipmi_data->slave_addr = data[6];
>  
>   if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
>   dmi_data_entries++;
> @@ -1717,82 +1711,17 @@ static int decode_dmi(dmi_header_t __iom
>   return -1;
>  }
>  
> -static int dmi_table(u32 base, int len, int num)
> -{
> - u8__iomem *buf;
> - struct dmi_header __iomem *dm;
> - u8__iomem *data;
> - int   i=1;
> - int   status=-1;
> - int   intf_num = 0;
> -
> - buf = ioremap(base, len);
> - if(buf==NULL)
> - return -1;
> -
> - data = buf;
> -
> - while(i - {
> - dm=(dmi_header_t __iomem *)data;
> -
> - if((data-buf+readb(&dm->length)) >= len)
> - break;
> -
> - if (readb(&dm->type) == 38) {
> - if (decode_dmi(dm, intf_num) == 0) {
> - intf_num++;
> - if (intf_num >= SI_MAX_DRIVERS)
> - break;
> - }
> - }
> -
> - data+=readb(&dm->length);
> - while((data-buf) < len && (readb(data)||readb(data+1)))
> - data++;
> - data+=2;
> - i++;
> - }
> - iounmap(buf);
> -
> - return status;
> -}
> -
> -static inline int dmi_checksum(u8 *buf)
> -{
> - u8   sum=0;
> - int  a;
> -
> - for(a=0; a<15; a++)
> - sum+=buf[a];
> - return (sum==0);
> -}
> -
> -static int dmi_decode(void)
> +static void __init dmi_find_bmc(void)
>  {
> - u8   buf[15];
> - u32  fp=0xF;
> -
> -#ifdef CONFIG_SIMNOW
> - return -1;
> -#endif
> + struct dmi_device *dev = NULL;
> + int intf_num = 0;
>  
> - while(fp < 0xF)
> - {
> - isa_memcpy_fromio(buf, fp, 15);
> - if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(bu

[PATCH] Fix panic in the IPMI driver

2005-08-11 Thread Corey Minyard

This panic would only occur in saving panic information to the
system log in another panic, and only when sending the panic
information to a remote management controller, so it's not a huge
deal, but needs to be fixed.  Hopefully pasting the message inline
will work ok (testing showed it to be fine, though mozilla did wierd
things with inline text), as I can't get thunderbird to attach a patch
with a valid mimetype (and inline makes everyone happier, I
guess).


The "null message handler" in the IPMI driver is used in startup
and panic situations to handle messages.  It was only designed to
work with messages from the local management controller, but in
some cases it was used to get messages from remote management
controllers, and the system would then panic.  This patch makes
the "null message handler" in the IPMI driver more general so
it works with any kind of message.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

drivers/char/ipmi/ipmi_msghandler.c |  107 
++--

include/linux/ipmi.h|3 -
2 files changed, 69 insertions(+), 41 deletions(-)

Index: linux-2.6.13-rc5/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.13-rc5.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.13-rc5/drivers/char/ipmi/ipmi_msghandler.c
@@ -219,7 +219,7 @@
   interface comes in with a NULL user, call this routine with
   it.  Note that the message will still be freed by the
   caller.  This only works on the system interface. */
-void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg);
+void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg);

/* When we are scanning the channels for an SMI, this will
   tell which channel we are scanning. */
@@ -459,7 +459,27 @@

static void deliver_response(struct ipmi_recv_msg *msg)
{
-msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
+if (! msg->user) {
+ipmi_smi_tintf = msg->user_msg_data;
+unsigned long flags;
+
+/* Special handling for NULL users. */
+if (intf->null_user_handler) {
+intf->null_user_handler(intf, msg);
+spin_lock_irqsave(&intf->counter_lock, flags);
+intf->handled_local_responses++;
+spin_unlock_irqrestore(&intf->counter_lock, flags);
+} else {
+/* No handler, so give up. */
+spin_lock_irqsave(&intf->counter_lock, flags);
+intf->unhandled_local_responses++;
+spin_unlock_irqrestore(&intf->counter_lock, flags);
+}
+ipmi_free_recv_msg(msg);
+} else {
+msg->user->handler->ipmi_recv_hndl(msg,
+   msg->user->handler_data);
+}
}

/* Find the next sequence number not being used and add the given
@@ -1389,6 +1409,8 @@
unsigned char saddr, lun;
int   rv;

+if (! user)
+return -EINVAL;
rv = check_addr(user->intf, addr, &saddr, &lun);
if (rv)
return rv;
@@ -1418,6 +1440,8 @@
unsigned char saddr, lun;
int   rv;

+if (! user)
+return -EINVAL;
rv = check_addr(user->intf, addr, &saddr, &lun);
if (rv)
return rv;
@@ -1638,7 +1662,7 @@
  (struct ipmi_addr *) &si,
  0,
  &msg,
-  NULL,
+  intf,
  NULL,
  NULL,
  0,
@@ -1648,19 +1672,20 @@
}

static void
-channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
int rv = 0;
int chan;

-if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
-&& (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD))
+if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
+&& (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
+&& (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD))
{
/* It's the one we want */
-if (msg->rsp[2] != 0) {
+if (msg->msg.data[0] != 0) {
/* Got an error from the channel, just go on. */

-if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) {
+if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
/* If the MC does not support this
   command, that is legal.  We just
   assume it has one IPMB at channel
@@ -1677,13 +1702,13 @@
}
goto next_channel;
}
-if (msg->rsp_size < 6) {
+if (msg->msg.data_len < 4) {
/* Message not big enough, just go on. */
goto next_channel;
}
chan = intf->curr_channel;
-intf->channels[chan].medium = msg-&g

Re: [PATCH 2.6.12.4] ACPI oops during ipmi_si driver init

2005-08-17 Thread Corey Minyard

Peter Martuccelli wrote:


On Mon, 2005-08-15 at 18:13, Bjorn Helgaas wrote:
 


On Friday 12 August 2005 1:44 pm, Peter Martuccelli wrote:
   


Stumbled into this problem working on the ipmi_si driver.  When the
ipmi_si driver initialization fails the acpi_tb_get_table 
call, after rsdt_info has been allocated, acpi_get_firmware_table()

will oops trying to reference off rsdt_info->pointer in the cleanup
code.
 


I don't know whether the ACPI patch is correct or desirable, but
I think the ipmi_si ACPI discovery is bogus (it was probably
written before the current ACPI and PNPACPI driver registration
interfaces were stable).

Currently, ipmi_si uses the static SPMI table to locate the
device.  But the static table should only be used if we need
the device very early, before the ACPI namespace is available.

I don't think we use the device early, so we should use
pnp_register_driver() to claim the appropriate PNP IDs.
Or we might have to use acpi_bus_register_driver() since
it looks like it uses ACPI-specific features like GPEs.
   


Adding in Corey to the discussion regarding ipmi_si initialization,
waiting on Len to decide on the ACPI fix.
 

I couldn't find any documentation on how the ACPI interfaces work, so 
I'm kind of in the dark.


Basically, the IPMI system interface needs information from a specific 
IPMI table to know how to configure itself.  Those tables can reference 
GPEs, so the driver can use those (though AFAIK it has never been tested).


From spending 30 minutes searching and looking at things, I have no 
idea how to tie this in.  Can you point me to some docs?  Or do I have 
to spend hours digging?


-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] IPMI driver update part 1, add per-channel IPMB addresses

2005-08-03 Thread Corey Minyard




ipmi-per-channel-slave-address.patch
Description: unknown/unknown


[PATCH] IPMI driver update part 3, watchdog/NMI interaction fixes

2005-08-03 Thread Corey Minyard




ipmi_wdog_nmi_fixes.patch
Description: unknown/unknown


[PATCH] IPMI driver update part 4, allow userland to include ipmi.h

2005-08-03 Thread Corey Minyard




ipmi_compiler_h_include.patch
Description: unknown/unknown


[PATCH] IPMI driver update part 2, high-res timer support fixes

2005-08-03 Thread Corey Minyard




ipmi_hrt_fixes.diff
Description: unknown/unknown


[PATCH] IPMI driver update part 6, clean up versioning of the IPMI driver

2005-08-03 Thread Corey Minyard




ipmi-add-module-info-tags.patch
Description: unknown/unknown


[PATCH] IPMI driver update part 5, OEM flag handling and hacks for some Dell machines

2005-08-03 Thread Corey Minyard




ipmi-add-per-OEM-data-available-handlers.patch
Description: unknown/unknown


Re: [PATCH] IPMI driver update part 1, add per-channel IPMB addresses

2005-08-04 Thread Corey Minyard

Andrew Morton wrote:


Corey Minyard <[EMAIL PROTECTED]> wrote:
 


ipmi-per-channel-slave-address.patch  unknown/unknown (13533 bytes)]
   



Could you fix up the mimetype, please?  It makes it hard for various email
clients.
 


Dang, you switch to a new mail client and everything is screwed up.  Sorry.

 


IPMI allows multiple IPMB channels on a single interface, and
each channel might have a different IPMB address.  However, the
driver has only one IPMB address that it uses for everything.
This patch adds new IOCTLS and a new internal interface for
setting per-channel IPMB addresses and LUNs.  New systems are
coming out with support for multiple IPMB channels, and they
are broken without this patch.

...
+   for (i=0; i   



Preferred coding style is actually

for (i = 0; i < IPMI_MAX_CHANNELS; i++)

but we've kinda lost that fight in drivers :(
 

Ok, I'll see what I can do.  It's the wrong way all over the driver 
right now.


 


+#define IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 24, struct 
ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 25, struct 
ipmi_channel_lun_address_set)
+#define IPMICTL_SET_MY_CHANNEL_LUN_CMD_IOR(IPMI_IOC_MAGIC, 26, struct 
ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_LUN_CMD_IOR(IPMI_IOC_MAGIC, 27, struct 
ipmi_channel_lun_address_set)
   



Are these all OK wrt compat handling?
 

Yes, it is a structure of an unsigned short and an unsigned char, so it 
should be ok.


 


case IPMICTL_SET_MY_ADDRESS_CMD:
{
unsigned int val;
...
case IPMICTL_GET_MY_ADDRESS_CMD:
{
-   unsigned int val;
+   unsigned int  val;
+   unsigned char rval;
...
case IPMICTL_GET_MY_LUN_CMD:
{
-   unsigned int val;
+   unsigned int  val;
+   unsigned char rval;
+
...
+   case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
+   {
+   struct ipmi_channel_lun_address_set val;
...
+   case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
+   {
+   struct ipmi_channel_lun_address_set val;
...
+   case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
+   {
+   struct ipmi_channel_lun_address_set val;
...
+   case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
+   {
+   struct ipmi_channel_lun_address_set val;
...
case IPMICTL_SET_TIMING_PARMS_CMD:
{
struct ipmi_timing_parms parms;

   



Be aware that this function will use more stack space than it needs to: gcc
will create a separate stack slot for all the above locals.

Hence it would be better to declare them all at the start of the function. 
Faster, too - less dcache footprint.


Maybe not as nice from a purist point of view, but it does allow you to
lose those braces in the switch statement...
 

Hmm, I assumed that gcc would optimize and allocate the stack as it 
needed it without waste.  Ok, easy enough to fix.


Thanks,

-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] IPMI: driver model and sysfs support

2005-08-30 Thread Corey Minyard
This is very good.  I believe the structure is correct, but I'm not a 
sysfs expert.


There are a few things we need to deal with, though.

* There are some significant changes to versioning in the
 driver that are in the mm tree right now (you can pull them from
 
http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.13-rc6/2.6.13-rc6-mm2/broken-out)


* There are some coding style problems.  You have places like:
 +static void ipmi_bmc_unregister(struct ipmi_si_device *si,
 + struct ipmi_bmc_device *bmc){
 The '{' for functions and structures needs to be on it's own line.
 Also, several:
 + if(bmc->guid_present){
 that need spaces after the 'if' and before the '{'.
 The patch also adds some trailing spaces to empty lines, the
 following is a telltale sign:
 -
 +
 There was also one place where you added unneeded braces to
 a single statement and another where you deleted the empty line
 between two functions.
 These are all standard kernel coding style rules.

* I'd prefer to store the product id, device id, and manufacturer id
 decoded.  This makes it easier to handle (no need to use "memcmp"
 to compare) and print.  The printing of the product id, for instance,
 will be rather unnatural in product_id_show().

* guids are not printable strings (see guid_show()).

* The printing of the guid in ipmi_bmc_register is, well, kind of ugly.
 It should probably be moved to its own function that lets you pass in
 the rest of the string.

-Corey

Yani Ioannou wrote:


Hi Corey,

Here is a patch against 2.6.13 I've been working on (and mentioned to
you at OLS), that adds support for the 2.6 driver model, and sysfs to
the ipmi subsystem. It is loosely inspired by the USB driver model
system. There is a driver struct added for the ipmi_msghandler, and
one for each system interface 'driver' (for each state machine in
ipmi_si). A device struct is created for each system interface in the
system, and for each unique BMC on the system, with a symlink between
each system interface and the bmc it interfaces to. Each bmc has a set
of fundamental device attributes, and each of the drivers has a
version attribute reflecting the driver/state machine versions.
Furthermore each of these devices is registered as a class_device with
the ipmi class (moved to ipmi_msghandler) as bmcx and smix.

This in effect creates the following sysfs interface on a machine with
a single BMC and two interfaces:

/sys/
|-- block
|-- bus
|   |-- platform
|   |   |-- devices
|   |   |   |-- ipmi_bmc.0 -> ../../../devices/platform/ipmi_bmc.0
|   |   |   |-- ipmi_si.0 -> ../../../devices/platform/ipmi_si.0
|   |   |   |-- ipmi_si.1 -> ../../../devices/platform/ipmi_si.1
|   |   `-- drivers
|   |   |-- ipmi_bt_sm
|   |   |   |-- bind
|   |   |   |-- ipmi_si.1 -> ../../../../devices/platform/ipmi_si.1
|   |   |   |-- unbind
|   |   |   `-- version
|   |   |-- ipmi_kcs_sm
|   |   |   |-- bind
|   |   |   |-- ipmi_si.0 -> ../../../../devices/platform/ipmi_si.0
|   |   |   |-- unbind
|   |   |   `-- version
|   |   |-- ipmi_msghandler
|   |   |   |-- bind
|   |   |   |-- ipmi_bmc.0 -> ../../../../devices/platform/ipmi_bmc.0
|   |   |   |-- unbind
|   |   |   `-- version
|-- class
|   |-- ipmi
|   |   |-- bmc0
|   |   |   `-- device -> ../../../devices/platform/ipmi_bmc.0
|   |   |-- ipmi0
|   |   |   `-- dev
|   |   |-- ipmi1
|   |   |   `-- dev
|   |   |-- smi0
|   |   |   `-- device -> ../../../devices/platform/ipmi_si.0
|   |   `-- smi1
|   |   `-- device -> ../../../devices/platform/ipmi_si.1
|-- devices
|   |-- platform
|   |   |-- ipmi_bmc.0
|   |   |   |-- bus -> ../../../bus/platform
|   |   |   |-- device_id
|   |   |   |-- driver -> ../../../bus/platform/drivers/ipmi_msghandler
|   |   |   |-- firmware_revision
|   |   |   |-- ipmi_version
|   |   |   |-- power
|   |   |   |   `-- state
|   |   |   |-- product_id
|   |   |   `-- revision
|   |   |-- ipmi_si.0
|   |   |   |-- bmc -> ../../../devices/platform/ipmi_bmc.0
|   |   |   |-- bus -> ../../../bus/platform
|   |   |   |-- driver -> ../../../bus/platform/drivers/ipmi_kcs_sm
|   |   |   `-- power
|   |   |   `-- state
|   |   |-- ipmi_si.1
|   |   |   |-- bmc -> ../../../devices/platform/ipmi_bmc.0
|   |   |   |-- bus -> ../../../bus/platform
|   |   |   |-- driver -> ../../../bus/platform/drivers/ipmi_bt_sm
|   |   |   `-- power
|   |   |   `-- state
|-- kernel
|-- module
|   |-- ipmi_devintf
|   |   |-- refcnt
|   |   `-- sections
|   |   `-- __param
|   |-- ipmi_msghandler
|   |   |-- refcnt
|   |   `-- sections
|   |   |-- __ksymtab
|   |   `-- __ksymtab_strings
|   |-- ipmi_si
|   |   |-- refcnt
|   |   `-- sections
|   |   `-- __param
`-- power

My motiviation for the patch is to have a device struct (bmc) to
register with the new hwmon class for my in-progress hwmon driver
ipmi_sensors. With this patch the driver can create device attributes
under bmc devices representing sensor reading

Re: [RFC][CFLART] ipmi procfs bogosity

2005-09-01 Thread Corey Minyard
Indeed, this function is badly written.  In rewriting, I couldn't find a
nice function for reading integers from userspace, and the proc_dointvec
stuff didn't seem terribly suitable.  So I wrote my own general
function, which I can move someplace else if someone likes.  Patch is
attached.  It should not affect correct usage of this file.

Thank you for pointing this out.

Andrew, can you include this?  Matt, can you test?

-Corey

On Thu, 2005-09-01 at 07:43 +0100, [EMAIL PROTECTED] wrote:
> drivers/char/ipmi/ipmi_poweroff.c::proc_write_chassctrl()
>   a) does sscanf on userland pointer
>   b) does sscanf on array that is not guaranteed to have NUL in it
>   c) interprets input in incredibly cretinous way:
> if strings doesn't start with a decimal number => as if it was "0".
> if it starts with decimal number equal to 0 (e.g. is "-splat") - as if
> it was "0".
> if it starts with decimal number equal to 2 (e.g. is "2FOAD") - as if
> it was "2".
> otherwise - -EINVAL.
>   In any case that doesn't end up with -EINVAL, pretend that entire
> buffer had been written.
> 
> (a) and (b) are immediate bugs; (c) is a valid reason for immediate severe
> LARTing of the pervert who had done _that_ in a user-visible API.
> 
> Note that API _is_ user-visible, so we can't blindly change it - not without
> checking WTF do its users actually write to /proc/ipmi/poweroff_control.
> 
> Could somebody comment on the actual uses of that FPOS?  My preference would
> be to remove the damn thing completely - it's too ugly to live.
The IPMI power control function proc_write_chassctrl was badly
written, it directly used userspace pointers, it assumed that
strings were NULL terminated, and it used the evil sscanf function.
This adds a new function to read integers from userspace and
uses this function to get the integer in question.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.13/drivers/char/ipmi/ipmi_poweroff.c
===
--- linux-2.6.13.orig/drivers/char/ipmi/ipmi_poweroff.c
+++ linux-2.6.13/drivers/char/ipmi/ipmi_poweroff.c
@@ -40,6 +40,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #define PFX "IPMI poweroff: "
 
@@ -545,27 +547,179 @@ static int proc_read_chassctrl(char *pag
 			poweroff_control);
 }
 
+/*
+ * Convert a character to an integer, returning -1 if the character is
+ * not a valid digit for "base".
+ */
+static int convdigit(char ch, int base)
+{
+	int v;
+	if ((ch >= '0') && (ch <= '9'))
+		v = ch - '0';
+	else if ((ch >= 'A') && (ch <= 'Z'))
+		v = ch - 'A' + 10;
+	else if ((ch >= 'a') && (ch <= 'z'))
+		v = ch - 'a' + 10;
+	else
+		return -1;
+	if (v >= base)
+		return -1;
+	return v;
+}
+
+/*
+ * Get a unsigned long from userspace, much like strtoul, but getting
+ * the data from userspace.  This is a little complicated to use, but
+ * is quite flexible.
+ *
+ * @buffer - is a pointer to the start of the user buffer.  Basically,
+ * this will read from buffer+*pos up to buffer+count-1.
+ * @pos - points to the start offset in buffer to start reading at.
+ * pos will be updated to the current location after the scan upon return.
+ * May be NULL, where it is assumed to be zero.
+ * @count - the total buffer length.
+ * @fbase - forces the base.  If this value is zero 0, the base will be
+ * hex if the string starts with 0x, octal if it starts with 0, and
+ * decimal otherwise.
+ * @stop_at_inval - a flag that, if true, causes the function to
+ * return if it already has a valid number and has reached an invalid
+ * character.  "pos" will be set to the offset of the invalid
+ * character upon return.  If false, the entire buffer is expected to
+ * be a single integer value surrounded by optional space characters.
+ *
+ * Unlike strtoul, the value is returned in the "val" parameter.  The
+ * return value of this function is a errno if negative or the number
+ * of characters processed if positive.
+ */
+static ssize_t user_strtoul(const char __user *buffer, loff_t *ppos,
+			size_t count, int fbase, int stop_at_inval,
+			unsigned long *val)
+{
+	unsigned long newval = 0;
+	char  buf[20];
+	unsigned int  rc;
+	unsigned int  i;
+	enum { SC_ST, SC_ST2, SC_AFTPRE, SC_DAT, SC_END } state = SC_ST;
+	int   base = fbase;
+	loff_tstart;
+	loff_tpos;
+
+	if (ppos)
+		pos = *ppos;
+	else
+		pos = 0;
+	start = pos;
+	count -= pos;
+	if (base == 0)
+		base = 10;
+	while (count > 0) {
+		rc = min(count, (size_t) sizeof(buf));
+		if (copy_from_user(buf, buffer + pos, rc))
+			return -EFAULT;
+		for (i = 0; i < rc; i++) {
+			char ch = buf[i];

[PATCH] Add hacks for IPMI chassis poweroff for certain Dell servers

2005-09-01 Thread Corey Minyard


This patch allows Dell servers with IPMI controllers that predate IPMI
1.5 to use the standard poweroff or powercycle commands.  These
systems firmware don't set the chassis capability bit in the Get
Device ID, but they do implement the standard poweroff and powercycle
commands.

Tested on RHEL3 kernel 2.4.21-20.ELsmp on a PowerEdge 2600.  The
standard ipmi_poweroff driver cannot drive these systems.  With this
patch, they power off or powercycle as expected.

 drivers/char/ipmi/ipmi_poweroff.c |   24 
 1 files changed, 24 insertions(+)

Signed-off-by: Matt Domsch <[EMAIL PROTECTED]>
Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.13/drivers/char/ipmi/ipmi_poweroff.c
===
--- linux-2.6.13.orig/drivers/char/ipmi/ipmi_poweroff.c
+++ linux-2.6.13/drivers/char/ipmi/ipmi_poweroff.c
@@ -64,6 +64,7 @@ MODULE_PARM_DESC(poweroff_control, " Set
 static unsigned int mfg_id;
 static unsigned int prod_id;
 static unsigned char capabilities;
+static unsigned char ipmi_version;
 
 /* We use our own messages for this operation, we don't let the system
allocate them, since we may be in a panic situation.  The whole
@@ -339,6 +340,25 @@ static void ipmi_poweroff_cpi1 (ipmi_use
 }
 
 /*
+ * ipmi_dell_chassis_detect()
+ * Dell systems with IPMI < 1.5 don't set the chassis capability bit
+ * but they can handle a chassis poweroff or powercycle command.
+ */
+
+#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
+static int ipmi_dell_chassis_detect (ipmi_user_t user)
+{
+	const char ipmi_version_major = ipmi_version & 0xF;
+	const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
+	const char mfr[3]=DELL_IANA_MFR_ID;
+	if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&
+	ipmi_version_major <= 1 &&
+	ipmi_version_minor < 5)
+		return 1;
+	return 0;
+}
+
+/*
  * Standard chassis support
  */
 
@@ -415,6 +435,9 @@ static struct poweroff_function poweroff
 	{ .platform_type	= "CPI1",
 	  .detect		= ipmi_cpi1_detect,
 	  .poweroff_func	= ipmi_poweroff_cpi1 },
+	{ .platform_type	= "chassis",
+	  .detect		= ipmi_dell_chassis_detect,
+	  .poweroff_func	= ipmi_poweroff_chassis },
 	/* Chassis should generally be last, other things should override
 	   it. */
 	{ .platform_type	= "chassis",
@@ -500,6 +523,7 @@ static void ipmi_po_new_smi(int if_num)
 	prod_id = (halt_recv_msg.msg.data[10]
 		   | (halt_recv_msg.msg.data[11] << 8));
 	capabilities = halt_recv_msg.msg.data[6];
+	ipmi_version = halt_recv_msg.msg.data[5];
 
 
 	/* Scan for a poweroff method */


Re: [RFC][CFLART] ipmi procfs bogosity

2005-09-01 Thread Corey Minyard

[EMAIL PROTECTED] wrote:


On Thu, Sep 01, 2005 at 11:41:42AM -0500, Corey Minyard wrote:
 


Indeed, this function is badly written.  In rewriting, I couldn't find a
nice function for reading integers from userspace, and the proc_dointvec
stuff didn't seem terribly suitable.  So I wrote my own general
function, which I can move someplace else if someone likes.  Patch is
attached.  It should not affect correct usage of this file.
   



Eeeek...  Much, _much_ simpler approach would be to have

char buf[10];
if (count > 9)
return -EINVAL;
if (copy_from_user(buf, buffer, count))
return -EFAULT;
buf[count] = '\0';
/* use sscanf() or anything normal */

Would that change behaviour in any cases you care about?
 


Because then, for a general solution that avoids integer
perversion, you need something like:

   char buf[10];
   char *end;

   if (count > (sizeof(buf) - 1))
   return -EINVAL;
   if (copy_from_user(buf, buffer, count))
   return -EFAULT;
   buf[count] = '\0';
   newval = simple_strtoul(buf, &end, 0);
   if (buf == end)
   /* Empty string or first char not a number */
   return -EINVAL;
   if (*end && ! isspace(*end))
   /* Bogus number. */
   return -EINVAL;


To me, It's a lot nicer to do:

   rv = user_strtoul();
   if (rv < 0)
   return rv;

Plus the scanning function I wrote handles arbitrary leading and 
trailing space, etc.  Not a big deal, but a little nicer.


-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] part 2 - remove unused fields from the IPMI driver

2005-09-01 Thread Corey Minyard

This removes the unused "all_cmd_rcvr" variable from the
IPMI driver.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.13/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.13.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.13/drivers/char/ipmi/ipmi_msghandler.c
@@ -202,12 +202,6 @@ struct ipmi_smi
 	struct list_head waiting_events;
 	unsigned int waiting_events_count; /* How many events in queue? */
 
-	/* This will be non-null if someone registers to receive all
-	   IPMI commands (this is for interface emulation).  There
-	   may not be any things in the cmd_rcvrs list above when
-	   this is registered. */
-	ipmi_user_t all_cmd_rcvr;
-
 	/* The event receiver for my BMC, only really used at panic
 	   shutdown as a place to store this. */
 	unsigned char event_receiver;
@@ -867,11 +861,6 @@ int ipmi_register_for_cmd(ipmi_user_t   
 
 	read_lock(&(user->intf->users_lock));
 	write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
-	if (user->intf->all_cmd_rcvr != NULL) {
-		rv = -EBUSY;
-		goto out_unlock;
-	}
-
 	/* Make sure the command/netfn is not already registered. */
 	list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) {
 		if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {
@@ -886,7 +875,7 @@ int ipmi_register_for_cmd(ipmi_user_t   
 		rcvr->user = user;
 		list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
 	}
- out_unlock:
+
 	write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
 	read_unlock(&(user->intf->users_lock));
 
@@ -1799,7 +1788,6 @@ int ipmi_register_smi(struct ipmi_smi_ha
 			rwlock_init(&(new_intf->cmd_rcvr_lock));
 			init_waitqueue_head(&new_intf->waitq);
 			INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
-			new_intf->all_cmd_rcvr = NULL;
 
 			spin_lock_init(&(new_intf->counter_lock));
 
@@ -2037,15 +2025,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_
 
 	read_lock(&(intf->cmd_rcvr_lock));
 	
-	if (intf->all_cmd_rcvr) {
-		user = intf->all_cmd_rcvr;
-	} else {
-		/* Find the command/netfn. */
-		list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
-			if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
-user = rcvr->user;
-break;
-			}
+	/* Find the command/netfn. */
+	list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+		if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+			user = rcvr->user;
+			break;
 		}
 	}
 	read_unlock(&(intf->cmd_rcvr_lock));
@@ -,15 +2206,11 @@ static int handle_lan_get_msg_cmd(ipmi_s
 
 	read_lock(&(intf->cmd_rcvr_lock));
 
-	if (intf->all_cmd_rcvr) {
-		user = intf->all_cmd_rcvr;
-	} else {
-		/* Find the command/netfn. */
-		list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
-			if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
-user = rcvr->user;
-break;
-			}
+	/* Find the command/netfn. */
+	list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
+		if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
+			user = rcvr->user;
+			break;
 		}
 	}
 	read_unlock(&(intf->cmd_rcvr_lock));


[PATCH] part 3 - Convert IPMI driver over to use refcounts

2005-09-01 Thread Corey Minyard

The IPMI driver uses read/write locks to ensure that things
exist while they are in use.  This is bad from a number of
points of view.  This patch removes the rwlocks and uses
refcounts and a special synced list (the entries can be
refcounted and removal is blocked while an entry is in
use).

 drivers/char/ipmi/ipmi_msghandler.c | 1153 +---
 1 files changed, 692 insertions(+), 461 deletions(-)

Index: linux-2.6.13/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.13.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.13/drivers/char/ipmi/ipmi_msghandler.c
@@ -38,7 +38,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -65,9 +64,210 @@ struct proc_dir_entry *proc_ipmi_root = 
the max message timer.  This is in milliseconds. */
 #define MAX_MSG_TIMEOUT		6
 
-struct ipmi_user
+
+/*
+ * The following is an implementation of a list that allows traversals
+ * and additions/deletions at the same time.  If a list item is in use
+ * while the deletion is occurring, then the deletion will block until
+ * the list item is no longer in use.
+ */
+#include 
+#include 
+struct synced_list
+{
+	struct list_head head;
+	spinlock_t   lock;
+};
+
+struct synced_list_entry
+{
+	struct list_head  link;
+	atomic_t  usecount;
+
+	struct list_head  task_list;
+};
+
+/* Return values for match functions. */
+#define SYNCED_LIST_NO_MATCH		0
+#define SYNCED_LIST_MATCH_STOP		1
+#define SYNCED_LIST_MATCH_CONTINUE	-1
+
+/* Can be used for synced list find and clear operations for finding
+   and deleting a specific entry. */
+static int match_entry(struct synced_list_entry *e, void *match_data)
+{
+	if (e == match_data)
+		return SYNCED_LIST_MATCH_STOP;
+	else
+		return SYNCED_LIST_NO_MATCH;
+}
+
+struct synced_list_entry_task_q
 {
 	struct list_head link;
+	task_t   *process;
+};
+
+static inline void init_synced_list(struct synced_list *list)
+{
+	INIT_LIST_HEAD(&list->head);
+	spin_lock_init(&list->lock);
+}
+
+/* Called with the list head lock held */
+static void synced_list_wake(struct synced_list_entry *entry)
+{
+	struct synced_list_entry_task_q *e;
+
+	if (!atomic_dec_and_test(&entry->usecount))
+		/* Another thread is using the entry, too. */
+		return;
+
+	list_for_each_entry(e, &entry->task_list, link)
+		wake_up_process(e->process);
+}
+
+/* Can only be called on entries that have been "gotten". */
+#define synced_list_put_entry(pos, head) \
+	synced_list_before_exit(pos, head)
+/* Must be called with head->lock already held. */
+#define synced_list_put_entry_nolock(pos, head) \
+	synced_list_wake(pos);
+
+#define synced_list_for_each_entry(pos, l, entry, flags)		\
+	for ((spin_lock_irqsave(&(l)->lock, flags),			  \
+	  pos = container_of((l)->head.next, typeof(*(pos)),entry.link)); \
+	 (prefetch((pos)->entry.link.next),  \
+	  &(pos)->entry.link != (&(l)->head)			  \
+	? (atomic_inc(&(pos)->entry.usecount),			  \
+   spin_unlock_irqrestore(&(l)->lock, flags), 1)	  \
+	: (spin_unlock_irqrestore(&(l)->lock, flags), 0));	  \
+	 (spin_lock_irqsave(&(l)->lock, flags),			  \
+	  synced_list_wake(&(pos)->entry),  \
+  pos = container_of((pos)->entry.link.next, typeof(*(pos)),  \
+ entry.link)))
+
+/* If you must exit a synced_list_for_each_entry loop abnormally (with
+   a break, return, goto) then you *must* call this first, with the
+   current entry.  Otherwise, the entry will be left locked. */
+static void synced_list_before_exit(struct synced_list_entry *entry,
+struct synced_list *head)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&head->lock, flags);
+	synced_list_wake(entry);
+	spin_unlock_irqrestore(&head->lock, flags);
+}
+
+/* Can only be called in a synced list loop.  This will preserve the
+   entry at least until synced_list_put_entry() is called. */
+#define synced_list_get_entry(pos) atomic_inc(&(pos)->usecount)
+
+/* Must be called with head->lock already held. */
+static void synced_list_add_nolock(struct synced_list *head,
+   struct synced_list_entry *entry)
+{
+	atomic_set(&entry->usecount, 0);
+	INIT_LIST_HEAD(&entry->task_list);
+	list_add(&entry->link, &head->head);
+}
+
+static void synced_list_add(struct synced_list *head,
+			struct synced_list_entry *entry)
+{
+	spin_lock_irq(&head->lock);
+	synced_list_add_nolock(head, entry);
+	spin_unlock_irq(&head->lock);
+}
+
+/*
+ * See the SYNCED_LIST_MATCH... defines for the return values from the
+ * "match" function.  If the free function is non-NULL, it will be
+ * called with the entry after it is removed from the list.  This must
+ * be called with the head->lock already held.
+ */
+static int synced_list_clear(struct synced_list *head,
+			 int (*match)(struct synced_list_entry *,
+	  void *),
+			 void (*free)(struct synced_list_entry *),
+			 v

[PATCH] part 1 - IPMI style cleanups

2005-09-01 Thread Corey Minyard

Clean up various style issues in the IPMI driver.  Should be
no functional changes.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.13/drivers/char/ipmi/ipmi_poweroff.c
===
--- linux-2.6.13.orig/drivers/char/ipmi/ipmi_poweroff.c
+++ linux-2.6.13/drivers/char/ipmi/ipmi_poweroff.c
@@ -527,7 +527,7 @@ static void ipmi_po_new_smi(int if_num)
 
 
 	/* Scan for a poweroff method */
-	for (i=0; i> 26) & 0x3f);\
 		seqid = (msgid & 0x3f);\
-} while(0)
+} while (0)
 
 #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3f)
 
@@ -326,7 +326,7 @@ int ipmi_smi_watcher_register(struct ipm
 	down_read(&interfaces_sem);
 	down_write(&smi_watchers_sem);
 	list_add(&(watcher->link), &smi_watchers);
-	for (i=0; inew_smi(i);
 		}
@@ -496,9 +496,9 @@ static int intf_next_seq(ipmi_smi_t 
 	int  rv = 0;
 	unsigned int i;
 
-	for (i=intf->curr_seq;
+	for (i = intf->curr_seq;
 	 (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
-	 i=(i+1)%IPMI_IPMB_NUM_SEQ)
+	 i = (i+1)%IPMI_IPMB_NUM_SEQ)
 	{
 		if (! intf->seq_table[i].inuse)
 			break;
@@ -733,7 +733,7 @@ static int ipmi_destroy_user_nolock(ipmi
 
 	/* Remove the user from the interfaces sequence table. */
 	spin_lock_irqsave(&(user->intf->seq_lock), flags);
-	for (i=0; iintf->seq_table[i].inuse
 		&& (user->intf->seq_table[i].recv_msg->user == user))
 		{
@@ -1370,7 +1370,7 @@ static inline int i_ipmi_request(ipmi_us
 #ifdef DEBUG_MSGING
 	{
 		int m;
-		for (m=0; mdata_size; m++)
+		for (m = 0; m < smi_msg->data_size; m++)
 			printk(" %2.2x", smi_msg->data[m]);
 		printk("\n");
 	}
@@ -1467,7 +1467,7 @@ static int ipmb_file_read_proc(char *pag
 	inti;
 	intrv= 0;
 
-	for (i=0; ichannels[i].address);
 	out[rv-1] = '\n'; /* Replace the final space with a newline */
 	out[rv] = '\0';
@@ -1766,12 +1766,12 @@ int ipmi_register_smi(struct ipmi_smi_ha
 	rv = -ENOMEM;
 
 	down_write(&interfaces_sem);
-	for (i=0; iintf_num = i;
 			new_intf->version_major = version_major;
 			new_intf->version_minor = version_minor;
-			for (j=0; jchannels[j].address
 	= IPMI_BMC_SLAVE_ADDR;
 new_intf->channels[j].lun = 2;
@@ -1783,7 +1783,7 @@ int ipmi_register_smi(struct ipmi_smi_ha
 			new_intf->handlers = handlers;
 			new_intf->send_info = send_info;
 			spin_lock_init(&(new_intf->seq_lock));
-			for (j=0; jseq_table[j].inuse = 0;
 new_intf->seq_table[j].seqid = 0;
 			}
@@ -1891,7 +1891,7 @@ static void clean_up_interface_data(ipmi
 	free_recv_msg_list(&(intf->waiting_events));
 	free_cmd_rcvr_list(&(intf->cmd_rcvrs));
 
-	for (i=0; iseq_table[i].inuse)
 		&& (intf->seq_table[i].recv_msg))
 		{
@@ -1910,7 +1910,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
 	down_write(&interfaces_sem);
 	if (list_empty(&(intf->users)))
 	{
-		for (i=0; idata_size; m++)
+		for (m = 0; m < msg->data_size; m++)
 			printk(" %2.2x", msg->data[m]);
 		printk("\n");
 	}
@@ -2469,7 +2469,7 @@ static int handle_new_recv_msg(ipmi_smi_
 #ifdef DEBUG_MSGING
 	int m;
 	printk("Recv:");
-	for (m=0; mrsp_size; m++)
+	for (m = 0; m < msg->rsp_size; m++)
 		printk(" %2.2x", msg->rsp[m]);
 	printk("\n");
 #endif
@@ -2703,7 +2703,7 @@ smi_from_recv_msg(ipmi_smi_t intf, struc
 	{
 		int m;
 		printk("Resend: ");
-		for (m=0; mdata_size; m++)
+		for (m = 0; m < smi_msg->data_size; m++)
 			printk(" %2.2x", smi_msg->data[m]);
 		printk("\n");
 	}
@@ -2724,7 +2724,7 @@ ipmi_timeout_handler(long timeout_period
 	INIT_LIST_HEAD(&timeouts);
 
 	spin_lock(&interfaces_lock);
-	for (i=0; iseq_lock), flags);
-		for (j=0; jseq_table[j]);
 			if (!ent->inuse)
 continue;
@@ -2789,7 +2789,7 @@ ipmi_timeout_handler(long timeout_period
 spin_unlock(&intf->counter_lock);
 smi_msg = smi_from_recv_msg(intf,
 		ent->recv_msg, j, ent->seqid);
-if(!smi_msg)
+if (! smi_msg)
 	continue;
 
 spin_unlock_irqrestore(&(intf->seq_lock),flags);
@@ -2820,7 +2820,7 @@ static void ipmi_request_event(void)
 	inti;
 
 	spin_lock(&interfaces_lock);
-	for (i=0; ixmit_msgs.next;
 	}
 
-	if (!entry) {
+	if (! entry) {
 		smi_info->curr_msg = NULL;
 		rv = SI_SM_IDLE;
 	} else {
@@ -328,7 +328,7 @@ static void start_clear_flags(struct smi
memory, we will re-enable the interrupt. */
 static inline void disable_si_irq(struct smi_info *smi_info)
 {
-	if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
+	if ((smi_info->irq) && (! smi_info->interrupt_disabled)) {
 		disable_irq_nosync(smi_info->irq);
 		smi_info->interrupt_disabled = 1;
 	}
@@ -359,7 +359,7 @@ static void handle_flags(stru

Re: [RFC][CFLART] ipmi procfs bogosity

2005-09-01 Thread Corey Minyard

Andrew Morton wrote:


Corey Minyard <[EMAIL PROTECTED]> wrote:
 


Indeed, this function is badly written.  In rewriting, I couldn't find a
nice function for reading integers from userspace, and the proc_dointvec
stuff didn't seem terribly suitable.
   



We write numbers into profs files all the time.  Is there something
different about the IPMI requirement which makes the approach used by, say,
dirty_writeback_centisecs_handler() inappropriate?
 

Ok, that's probably better, and this probably belongs in 
/proc/sys/dev/ipmi.  This is new enough that it doesn't matter, I don't 
think any one is using it yet.


Patch is attached.

-Corey


ipmi-poweroff-fix-chassis-ctrl.patch
Description: unknown/unknown


Re: [PATCH] part 3 - Convert IPMI driver over to use refcounts

2005-09-02 Thread Corey Minyard

Andrew Morton wrote:


The IPMI driver uses read/write locks to ensure that things
exist while they are in use.  This is bad from a number of
points of view.  This patch removes the rwlocks and uses
refcounts and a special synced list (the entries can be
refcounted and removal is blocked while an entry is in
use).

   



This:

 


+
+struct synced_list_entry_task_q
{
struct list_head link;
+   task_t   *process;
+};
+
   



 


+#define synced_list_for_each_entry(pos, l, entry, flags)   \
+   for ((spin_lock_irqsave(&(l)->lock, flags),\
+ pos = container_of((l)->head.next, typeof(*(pos)),entry.link)); \
+(prefetch((pos)->entry.link.next), 
   \
+ &(pos)->entry.link != (&(l)->head)\
+   ? (atomic_inc(&(pos)->entry.usecount), \
+   spin_unlock_irqrestore(&(l)->lock, flags), 1)  \
+   : (spin_unlock_irqrestore(&(l)->lock, flags), 0)); \
+(spin_lock_irqsave(&(l)->lock, flags),\
+ synced_list_wake(&(pos)->entry), \
+  pos = container_of((pos)->entry.link.next, typeof(*(pos)),  \
+entry.link)))
   



(gad)
 

Yes, I was trying to preserve list semantics and it got out of hand. It 
is pretty ugly.




And this:

 


+static int synced_list_clear(struct synced_list *head,
+int (*match)(struct synced_list_entry *,
+ void *),
+void (*free)(struct synced_list_entry *),
+void *match_data)
+{
+   struct synced_list_entry *ent, *ent2;
+   int  rv = -ENODEV;
+   int  mrv = SYNCED_LIST_MATCH_CONTINUE;
+
+   spin_lock_irq(&head->lock);
+ restart:
+   list_for_each_entry_safe(ent, ent2, &head->head, link) {
+   if (match) {
+   mrv = match(ent, match_data);
+   if (mrv == SYNCED_LIST_NO_MATCH)
+   continue;
+   }
+   if (atomic_read(&ent->usecount)) {
+   struct synced_list_entry_task_q e;
+   e.process = current;
+   list_add(&e.link, &ent->task_list);
+   __set_current_state(TASK_UNINTERRUPTIBLE);
+   spin_unlock_irq(&head->lock);
+   schedule();
+   spin_lock_irq(&head->lock);
+   list_del(&e.link);
+   goto restart;
+   }
+   list_del(&ent->link);
+   rv = 0;
+   if (free)
+   free(ent);
+   if (mrv == SYNCED_LIST_MATCH_STOP)
+   break;
+   }
+   spin_unlock_irq(&head->lock);
+   return rv;
+}
   



Look awfully similar to wait_queue_head_t.  Are you sure existing
infrastructure cannot be used?
 

I already had a lock and it seemed wasteful to have two locks. And it 
didn't really save much code and it didn't quite fit.


Basically, I need a notifier list that avoids traversal/removal race 
conditions. An asynchronous event or command comes in and you need to 
inform all the users who are waiting for events or commands. I don't 
think anything like that exists currently (the current notifier list has 
no lock on traversal). I don't want a lock around the whole traversal 
because doing callbacks with locks held is not a good idea.


The list I created simply blocks a deleter while the item is in use. 
There may be a better way to handle this, I'll think about it (and take 
any suggestions :). I read some stuff about RCU when looking at this, 
and it didn't seem suitable at the time, but I just reread it and it 
seems like it would be fine. I'll remove all this garbage and replace it 
with an RCU list.


 


1 files changed, 692 insertions(+), 461 deletions(-)
   



Ow.  Why is it worthwhile?
 

The change is definately needed. The driver, as it currently is, holds 
read locks for very long periods of time. It does this to make sure 
various objects don't get deleted. Holding read locks for this long is 
bad, and this is the job of refcounts. It's hard to break up changing 
fundamental underpinnings like this.


The patch is big, and from the above it looks like it is not quite 
ready. I'll continue to look at it.


Thank you,

-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] ARM: Ignore memory tags with invalid data

2008-01-21 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

The DNS-323 system has several bogus memory entries in the tag table,
and it caused the system to crash at startup.  Ignore tag entries that
are obviously bogus.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>
---
 arch/arm/kernel/setup.c |7 ++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bf56eb3..dfdb469 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -630,7 +630,12 @@ __tagtable(ATAG_CORE, parse_tag_core);
 
 static int __init parse_tag_mem32(const struct tag *tag)
 {
-   if (meminfo.nr_banks >= NR_BANKS) {
+   /*
+* Make sure that the memory size is non-zero, page aligned,
+* and that it doesn't overflow the meminfo table.
+*/
+   if (meminfo.nr_banks >= NR_BANKS || tag->u.mem.size & ~PAGE_MASK ||
+   tag->u.mem.size == 0 || tag->u.mem.start & ~PAGE_MASK) {
printk(KERN_WARNING
   "Ignoring memory bank 0x%08x size %dKB\n",
tag->u.mem.start, tag->u.mem.size / 1024);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] ARM: Ignore memory tags with invalid data

2008-01-22 Thread Corey Minyard

Ben Dooks wrote:

On Mon, Jan 21, 2008 at 10:05:56PM -0600, Corey Minyard wrote:
  

From: Corey Minyard <[EMAIL PROTECTED]>

The DNS-323 system has several bogus memory entries in the tag table,
and it caused the system to crash at startup.  Ignore tag entries that
are obviously bogus.



This should have gone to the linux-arm-kernel mailing list as well,
so that all the people interested in ARM can see it as soon as
possible. See [EMAIL PROTECTED]
  
You have to be a member to post, and I'm not a member.  I guess I'll 
join, though it seems somewhat pointless for a single patch.



The only suggestion I could think of would to be change to having
an check_tag_mem32() function, or put each check on its own line
to make it easier to read what each check is doing.

ie:
if (meminfo.nr_banks >= NR_BANKS ||
tag->u.mem.size & ~PAGE_MASK || /* size is unaligned */
tag->u.mem.size == 0 ||  /* no memory here */
	tag->u.mem.start & ~PAGE_MASK)  /* start is unaligned */ 
	{


(even without the comments it makes it easier to see what each test
is.
  

That's fine, it is easier to read.

Thanks,

-corey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [Openipmi-developer] modprobing ipmi_si on Dell Power Edge 2600 make the terminal hang kernel ver. >= 2.6.20

2008-01-22 Thread Corey Minyard

Matt Domsch wrote:

On Tue, Jan 22, 2008 at 06:50:31AM -0600, Matt Domsch wrote:
  

On Mon, Jan 21, 2008 at 09:40:59AM +0800, william cheng wrote:


Dear all,

We got some problem on modprobing the ipmi_si module on Dell
Power Edge 2600.
  

I've asked someone to look into this.



and I've filed this as
http://bugzilla.kernel.org/show_bug.cgi?id=9793
  

I've posted a response to that bugzilla entry.

-corey

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/4] docs: convert kref semaphore to mutex

2007-12-21 Thread Corey Minyard

Yes, a good idea.

Acked-by: Corey Minyard <[EMAIL PROTECTED]>

Daniel Walker wrote:

Just converting this documentation semaphore reference, since we don't
want to promote semaphore usage.

Signed-off-by: Daniel Walker <[EMAIL PROTECTED]>

---
 Documentation/kref.txt |   20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

Index: linux-2.6.23/Documentation/kref.txt
===
--- linux-2.6.23.orig/Documentation/kref.txt
+++ linux-2.6.23/Documentation/kref.txt
@@ -141,10 +141,10 @@ The last rule (rule 3) is the nastiest o
 instance, you have a list of items that are each kref-ed, and you wish
 to get the first one.  You can't just pull the first item off the list
 and kref_get() it.  That violates rule 3 because you are not already
-holding a valid pointer.  You must add locks or semaphores.  For
-instance:
+holding a valid pointer.  You must add a mutex (or some other lock).
+For instance:
 
-static DECLARE_MUTEX(sem);

+static DEFINE_MUTEX(mutex);
 static LIST_HEAD(q);
 struct my_data
 {
@@ -155,12 +155,12 @@ struct my_data
 static struct my_data *get_entry()
 {
struct my_data *entry = NULL;
-   down(&sem);
+   mutex_lock(&mutex);
if (!list_empty(&q)) {
entry = container_of(q.next, struct my_q_entry, link);
kref_get(&entry->refcount);
}
-   up(&sem);
+   mutex_unlock(&mutex);
return entry;
 }
 
@@ -174,9 +174,9 @@ static void release_entry(struct kref *r
 
 static void put_entry(struct my_data *entry)

 {
-   down(&sem);
+   mutex_lock(&mutex);
kref_put(&entry->refcount, release_entry);
-   up(&sem);
+   mutex_unlock(&mutex);
 }
 
 The kref_put() return value is useful if you do not want to hold the

@@ -191,13 +191,13 @@ static void release_entry(struct kref *r
 
 static void put_entry(struct my_data *entry)

 {
-   down(&sem);
+   mutex_lock(&mutex);
if (kref_put(&entry->refcount, release_entry)) {
list_del(&entry->link);
-   up(&sem);
+   mutex_unlock(&mutex);
kfree(entry);
} else
-   up(&sem);
+   mutex_unlock(&mutex);
 }
 
 This is really more useful if you have to call other routines as part


  


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] ipmi: add the standard watchdog timeout ioctls

2007-11-20 Thread Corey Minyard
From: Corey Minyard <[EMAIL PROTECTED]>

Add the standard IOCTLs to the IPMI driver for setting and getting
the pretimeout.  Tested by Benoît Guillon.

Signed off by: Corey Minyard <[EMAIL PROTECTED]>
Cc: Benoît Guillon <[EMAIL PROTECTED]>
---
Index: linux-2.6.23/drivers/char/ipmi/ipmi_watchdog.c
===
--- linux-2.6.23.orig/drivers/char/ipmi/ipmi_watchdog.c
+++ linux-2.6.23/drivers/char/ipmi/ipmi_watchdog.c
@@ -683,6 +683,7 @@ static int ipmi_ioctl(struct inode *inod
return 0;
 
case WDIOC_SET_PRETIMEOUT:
+   case WDIOC_SETPRETIMEOUT:
i = copy_from_user(&val, argp, sizeof(int));
if (i)
return -EFAULT;
@@ -690,6 +691,7 @@ static int ipmi_ioctl(struct inode *inod
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
 
case WDIOC_GET_PRETIMEOUT:
+   case WDIOC_GETPRETIMEOUT:
i = copy_to_user(argp, &pretimeout, sizeof(pretimeout));
if (i)
return -EFAULT;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: ipmi_watchdog can not reset the kernel panic machine

2007-11-25 Thread Corey Minyard
The watchdog is "off" by default, meaning that you have to have 
something actually start resetting the watchdog before it will start 
running.  That's why you are seeing this behavior.


There is a start_now option that will start the watchdog when it is 
loaded, but then it will reset the system unless something resets the 
watchdog periodically, and you have a limited time to start this operation.


On a panic, the IPMI driver attempts to preserve the state of the 
watchdog and (if running) increase the timeout time to allow a kdump or 
something like that to occur.  That's the purpose of the code you 
reference.  It is not to start a reset operation on any panic.  It used 
to start a reset on every panic, but that cause problems for many users.


-corey

Andrew Morton wrote:

(cc's added)

On Fri, 23 Nov 2007 20:28:41 -0800 (PST) [EMAIL PROTECTED] wrote:

  

Build kernel-2.6.24-rc3.  pmi_watchdog can not reset the kernel panic
machine.  The watchdog can never to record panic information to IPMI SEL.

1. I disable auto reset when kernel panic by echo "0" >
/proc/sys/kernel/panic

2.  modprobe ipmi_watchdog timeout=120 action=reset

3.  Load a driver, the driver will call panic() when  ioctl to call into
the driver.

4.  By ioctl call into the driver,  panic the system.

in wdog_panic_handler, I printk "ipmi_watchdog_state=WDOG_TIMEOUT_NONE"
so, the watchdog can never to record panic information to IPMI SEL.


static int wdog_panic_handler(struct notifier_block *this,
  unsigned long event,
  void  *unused)
{
static int panic_event_handled = 0;

/* On a panic, if we have a panic timeout, make sure to extend
   the watchdog timer to a reasonable value to complete the
   panic, if the watchdog timer is running.  Plus the
   pretimeout is meaningless at panic time. */
if (watchdog_user && !panic_event_handled &&
ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
/* Make sure we do this only once. */
panic_event_handled = 1;

timeout = 255;
pretimeout = 0;
panic_halt_ipmi_set_timeout();
}

return NOTIFY_OK;
}



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] Add sysfs support to the IPMI driver

2005-03-12 Thread Corey Minyard
The IPMI driver has long needed to tie into the device model (and I've 
long been hoping someone else would do it).  I finally gave up and spent 
the time to learn how to do it.  I think this is right, it seems to work 
on on my system.

-Corey
Add support for sysfs to the IPMI device interface.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-mm1/drivers/char/ipmi/ipmi_devintf.c
===
--- linux-2.6.11-mm1.orig/drivers/char/ipmi/ipmi_devintf.c
+++ linux-2.6.11-mm1/drivers/char/ipmi/ipmi_devintf.c
@@ -44,6 +44,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define IPMI_DEVINTF_VERSION "v33"
 
@@ -519,15 +520,24 @@
 		 " interface.  Other values will set the major device number"
 		 " to that value.");
 
+static struct class_simple *ipmi_class;
+
 static void ipmi_new_smi(int if_num)
 {
+	char  name[10];
+	dev_t dev = MKDEV(ipmi_major, if_num);
+
 	devfs_mk_cdev(MKDEV(ipmi_major, if_num),
 		  S_IFCHR | S_IRUSR | S_IWUSR,
 		  "ipmidev/%d", if_num);
+
+	snprintf(name, sizeof(name), "ipmi%d", if_num);
+	class_simple_device_add(ipmi_class, dev, NULL, name);
 }
 
 static void ipmi_smi_gone(int if_num)
 {
+	class_simple_device_remove(MKDEV(ipmi_major, if_num));
 	devfs_remove("ipmidev/%d", if_num);
 }
 
@@ -548,8 +558,15 @@
 	printk(KERN_INFO "ipmi device interface version "
 	   IPMI_DEVINTF_VERSION "\n");
 
+	ipmi_class = class_simple_create(THIS_MODULE, "ipmi");
+	if (IS_ERR(ipmi_class)) {
+		printk(KERN_ERR "ipmi: can't register device class\n");
+		return PTR_ERR(ipmi_class);
+	}
+
 	rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
 	if (rv < 0) {
+		class_simple_destroy(ipmi_class);
 		printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
 		return rv;
 	}
@@ -563,6 +580,7 @@
 	rv = ipmi_smi_watcher_register(&smi_watcher);
 	if (rv) {
 		unregister_chrdev(ipmi_major, DEVICE_NAME);
+		class_simple_destroy(ipmi_class);
 		printk(KERN_WARNING "ipmi: can't register smi watcher\n");
 		return rv;
 	}
@@ -573,6 +591,7 @@
 
 static __exit void cleanup_ipmi(void)
 {
+	class_simple_destroy(ipmi_class);
 	ipmi_smi_watcher_unregister(&smi_watcher);
 	devfs_remove(DEVICE_NAME);
 	unregister_chrdev(ipmi_major, DEVICE_NAME);


Re: [PATCH] Add sysfs support to the IPMI driver

2005-03-13 Thread Corey Minyard
Greg KH wrote:
On Sat, Mar 12, 2005 at 10:57:24PM -0600, Corey Minyard wrote:
 

The IPMI driver has long needed to tie into the device model (and I've 
long been hoping someone else would do it).  I finally gave up and spent 
the time to learn how to do it.  I think this is right, it seems to work 
on on my system.
   

Looks good.  One minor question:
 

+
+	snprintf(name, sizeof(name), "ipmi%d", if_num);
+	class_simple_device_add(ipmi_class, dev, NULL, name);
   

What do ipmi class devices live on?  pci devices?  i2c devices?
platform devices?  Or are they purely virtual things?
 

Good question.  I struggled with this for a little while and decided the 
class interface was important to have in first and I'd figure out the 
rest later.  They live in different places depending on the particular 
low-level interface.  Some live on the I2C bus (and will show up there 
in sysfs with the I2C driver).  Some live on the ISA bus, some are 
memory-mapped, some are on the PCI bus (though there is not a driver for 
PCI support yet), and some sit on the end of a serial port (driver is in 
the works).  I know, it's a mess, but there's not much I can do about 
these crazy hardware manufacturers.

I wasn't sure where to handle all this.  The I2C and PCI bus side of 
things should be handled.  However, the others probably need to sit 
someplace on a bus, right?  That should probably be handled in the 
low-level code that actually knows where the hardware sits.

Thanks,
-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] Add a non-blocking interface to the I2C code, part 1

2005-03-18 Thread Corey Minyard
Greg KH wrote:
On Wed, Mar 02, 2005 at 01:58:51PM -0600, Corey Minyard wrote:
 

This patch reorganizes the I2C SMBus formatting code to make it more
suitable for the upcoming non-blocking changes.
   

You are changing too much stuff here to claim it's just a
reorganization:
	- variable name changes for no reason
 

Well, yes.  Both "adap" and "adapter" are used to refer to the same 
thing in the file; "adap" seemed to be the most common usage so I chose 
that for the new functions I added. In one place I changed adapter to 
adap.  I also changed "res" to "result".  I can fix those.  Or I can 
submit a patch first that renames the adap and adapter to make the usage 
consistent (I would prefer adapter).

	- coding style changes (improper ones at that)
 

I don't see that.  The ugliest thing about this is the functions that 
take the massive numbers of parameters, but that goes away in the next 
patch which puts all the data into a single data structure and passes it 
around.  The code here was also very inconsistent about use of spaces, 
like x(a,b,c) vs x(a, b, c), "struct a *b" vs "struct a * b", "a=b" vs 
"a = b".  It's hard to know what was right.  The changes I made in these 
respects was to try to make it use the usage most common in the file.

If you like, I can do a pass and make everything consistent in the file 
as part of the previous patch I talked about.

	- logic changes.
 

I tried very hard not to make logic changes.  Now I see there were two 
places where the function checked client->adapter->algo->master_xfer 
then called i2c_transfer(), which did the same check and returned the 
same error if it was NULL.  I removed the redundant check.  That belongs 
in a separate patch.  I couldn't find any others.

What exactly are you doing with this patch, and why?
 

The i2c main functions do the following:
 Format the data for transmission
 Send the data to the next layer down for handling
 Clean up the results
The original code did all this in single big functions.  This patch 
breaks the formatting and cleanup operations into separate functions.  
Beyond one big function being ugly, the non-blocking code needs this 
because it needs to perform these separately.  When you start the 
operation, the non-blocking code needs to do the format then return.  
Later on, when the operation is complete, the thread of execution 
handling the completion will do the cleanup.

-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH][alpha] "pm_power_off" [drivers/char/ipmi/ipmi_poweroff.ko] undefined!

2005-03-23 Thread Corey Minyard
This is not the right fix.  I know of IPMI hardware on ppc and xscale 
systems.  There should be nothing general in the driver that limits it 
to x86/ia64.

pm_power_off is defined in linux/pm.h.  Shouldn't it be available 
everywhere?

-Corey
Ivan Kokshaysky wrote:
On Tue, Mar 22, 2005 at 04:53:12PM -0500, Jeff Garzik wrote:
 

Although I suppose its possible that some alpha machines have SMI 
hardware, I don't think I've ever seen ACPI or IPMI on any alpha.
   

Yes, this stuff doesn't exist. I think it would be correct to add
the following to drivers/char/ipmi/Kconfig, like it's done for ACPI:
menu "IPMI"
+   depends on IA64 || X86
config IPMI_HANDLER
  tristate 'IPMI top-level message handler'
+   depends on IA64 || X86
Ivan.
 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] I2C Part 1 - Remove some redundancy from the i2c-core.c file

2005-03-23 Thread Corey Minyard
This is a series of patches to add a non-blocking interface to the I2C 
driver.  Hopefully it is broken into small enough functional changes.  
I'm not posting the whole series right now, just the first few.
Call i2c_transfer() from i2c_master_send() and i2c_master_recv()
to avoid the redundant code that was in all three functions.

This is important for the non-blocking interfaces because they
will have to handle a non-blocking interface in this area.  Having
it in one place greatly simplifies the changes.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc4/drivers/i2c/i2c-core.c
===
--- linux-2.6.11-rc4.orig/drivers/i2c/i2c-core.c
+++ linux-2.6.11-rc4/drivers/i2c/i2c-core.c
@@ -606,27 +606,20 @@
 	struct i2c_adapter *adap=client->adapter;
 	struct i2c_msg msg;
 
-	if (client->adapter->algo->master_xfer) {
-		msg.addr   = client->addr;
-		msg.flags = client->flags & I2C_M_TEN;
-		msg.len = count;
-		msg.buf = (char *)buf;
+	msg.addr   = client->addr;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.len = count;
+	msg.buf = (char *)buf;
 	
-		dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
-			count);
-	
-		down(&adap->bus_lock);
-		ret = adap->algo->master_xfer(adap,&msg,1);
-		up(&adap->bus_lock);
+	dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
+		count);
 
-		/* if everything went ok (i.e. 1 msg transmitted), return #bytes
-		 * transmitted, else error code.
-		 */
-		return (ret == 1 )? count : ret;
-	} else {
-		dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-		return -ENOSYS;
-	}
+	ret = i2c_transfer(adap, &msg, 1);
+
+	/* if everything went ok (i.e. 1 msg transmitted), return #bytes
+	 * transmitted, else error code.
+	 */
+	return (ret == 1 )? count : ret;
 }
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
@@ -634,31 +627,25 @@
 	struct i2c_adapter *adap=client->adapter;
 	struct i2c_msg msg;
 	int ret;
-	if (client->adapter->algo->master_xfer) {
-		msg.addr   = client->addr;
-		msg.flags = client->flags & I2C_M_TEN;
-		msg.flags |= I2C_M_RD;
-		msg.len = count;
-		msg.buf = buf;
 
-		dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
-			count);
-	
-		down(&adap->bus_lock);
-		ret = adap->algo->master_xfer(adap,&msg,1);
-		up(&adap->bus_lock);
+	msg.addr   = client->addr;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.flags |= I2C_M_RD;
+	msg.len = count;
+	msg.buf = buf;
+
+	dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
+		count);
 	
-		dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n",
-			ret, count, client->addr);
+	ret = i2c_transfer(adap, &msg, 1);
+
+	dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n",
+		ret, count, client->addr);
 	
-		/* if everything went ok (i.e. 1 msg transmitted), return #bytes
-	 	* transmitted, else error code.
-	 	*/
-		return (ret == 1 )? count : ret;
-	} else {
-		dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-		return -ENOSYS;
-	}
+	/* if everything went ok (i.e. 1 msg transmitted), return #bytes
+	 * transmitted, else error code.
+	 */
+	return (ret == 1 )? count : ret;
 }
 
 


[PATCH] I2C Part 2 - Break up the formatting code into individual functions

2005-03-23 Thread Corey Minyard

This patch reorganizes the I2C SMBus formatting code to make it more
suitable for the upcoming non-blocking changes.

The I2C main functions do the following:

 Format the data for transmission
 Send the data to the next layer down for handling
 Clean up the results

The original code did all this in single big function.  This patch
breaks the formatting and cleanup operations into separate functions.
Beyond one big function being ugly, the non-blocking code needs this
because it needs to perform these separately.  When you start the
operation, the non-blocking code needs to do the format then return.
Later on, when the operation is complete, the thread of execution
handling the completion will do the cleanup.

This patch does create some functions with lots of parameters.  That
goes away in a future patch that consolidates the data for an I2C
operation into a single data structure.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-mm1/drivers/i2c/i2c-core.c
===
--- linux-2.6.11-mm1.orig/drivers/i2c/i2c-core.c
+++ linux-2.6.11-mm1/drivers/i2c/i2c-core.c
@@ -1038,25 +1038,127 @@
 	}
 }
 
-/* Simulate a SMBus command using the i2c protocol 
-   No checking of parameters is done!  */
-static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, 
-   unsigned short flags,
-   char read_write, u8 command, int size, 
-   union i2c_smbus_data * data)
-{
-	/* So we need to generate a series of msgs. In the case of writing, we
-	  need to use only one message; when reading, we need two. We initialize
-	  most things with sane defaults, to keep the code below somewhat
-	  simpler. */
-	unsigned char msgbuf0[34];
-	unsigned char msgbuf1[34];
+static int i2c_smbus_complete_entry(struct i2c_adapter * adapter, u16 addr,
+unsigned short flags, char read_write,
+u8 command, int size,
+union i2c_smbus_data * data,
+int swpec, u8 partial,
+int result)
+{
+	if (result < 0)
+		return result;
+
+	if(swpec &&
+	   size != I2C_SMBUS_QUICK &&
+	   size != I2C_SMBUS_I2C_BLOCK_DATA &&
+	   (read_write == I2C_SMBUS_READ ||
+	size == I2C_SMBUS_PROC_CALL_PEC ||
+	size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
+		if(i2c_smbus_check_pec(addr,
+   command,
+   size,
+   partial,
+   data))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void i2c_smbus_format_entry(struct i2c_adapter * adapter, u16 addr,
+   unsigned short *flags, char read_write,
+   u8 command, int *size,
+   union i2c_smbus_data * data,
+   int *swpec, u8 *partial)
+{
+	*swpec = 0;
+	*partial = 0;
+	*flags &= I2C_M_TEN | I2C_CLIENT_PEC;
+	if((*flags & I2C_CLIENT_PEC) &&
+	   !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
+		*swpec = 1;
+		if(read_write == I2C_SMBUS_READ &&
+		   *size == I2C_SMBUS_BLOCK_DATA)
+			*size = I2C_SMBUS_BLOCK_DATA_PEC;
+		else if(*size == I2C_SMBUS_PROC_CALL)
+			*size = I2C_SMBUS_PROC_CALL_PEC;
+		else if(*size == I2C_SMBUS_BLOCK_PROC_CALL) {
+			unsigned char *sdata = data->block;
+			i2c_smbus_add_pec(addr, command, I2C_SMBUS_BLOCK_DATA,
+	  data);
+			*partial = sdata[sdata[0] + 1];
+			*size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
+		} else if(read_write == I2C_SMBUS_WRITE &&
+		  *size != I2C_SMBUS_QUICK &&
+		  *size != I2C_SMBUS_I2C_BLOCK_DATA)
+			*size = i2c_smbus_add_pec(addr, command, *size, data);
+	}
+}
+
+static int i2c_smbus_emu_complete(struct i2c_adapter * adapter, u16 addr,
+  unsigned short flags, char read_write,
+  u8 command, int size, 
+  union i2c_smbus_data * data,
+  struct i2c_msg *msg,
+  int swpec, u8 partial,
+  int result)
+{
+	unsigned char *msgbuf0 = msg[0].buf;
+	unsigned char *msgbuf1 = msg[1].buf;
+	int i;
+
+
+	if (result < 0)
+		return result;
+
+	if (read_write != I2C_SMBUS_READ)
+		return result;
+
+	switch(size) {
+	case I2C_SMBUS_BYTE:
+		data->byte = msgbuf0[0];
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		data->byte = msgbuf1[0];
+		break;
+	case I2C_SMBUS_WORD_DATA: 
+	case I2C_SMBUS_PROC_CALL:
+		data->word = msgbuf1[0]|(msgbuf1[1] << 8);
+		break;
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+		/* fixed at 32 for now */
+		data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
+		for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
+			data->block[i+1] = msgbuf1[i];
+		break;
+	}
+
+	return i2c_smbus_complete_entry(adapter, addr, flags,
+	read_write, command,
+	size, data, swpec, partial, result);
+}
+
+static int i2c_smbus_emu_format(struct i2c_adapter *adapter, u16 addr,
+unsigned short flags, char read_write,
+u8 command, int size, 
+union i2c_smbus_data * data,
+struct i2c_msg *msg)
+{
+	/* So we need to generate a series of msgs. In the case of
+	   writin

[PATCH] I2C Part 3 - Add an operation queue data structure

2005-03-23 Thread Corey Minyard

This patch adds an operation queue structure and converts over the
passing around of data to use the operation queue.  The op queue
entry will be used for queueing in the non-blocking case.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-mm1/drivers/i2c/i2c-core.c
===
--- linux-2.6.11-mm1.orig/drivers/i2c/i2c-core.c
+++ linux-2.6.11-mm1/drivers/i2c/i2c-core.c
@@ -582,24 +582,45 @@
  * 
  */
 
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
+static void i2c_transfer_entry(struct i2c_adapter * adap,
+			   struct i2c_op_q_entry * entry)
 {
-	int ret;
-
+	entry->xfer_type = I2C_OP_I2C;
+	entry->complete = NULL;
 	if (adap->algo->master_xfer) {
- 	 	dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num);
+ 	 	dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n",
+			entry->i2c.num);
 
 		down(&adap->bus_lock);
-		ret = adap->algo->master_xfer(adap,msgs,num);
+		entry->result = adap->algo->master_xfer(adap, entry->i2c.msgs,
+			entry->i2c.num);
 		up(&adap->bus_lock);
-
-		return ret;
+		if (entry->complete)
+		entry->complete(adap, entry);
 	} else {
 		dev_dbg(&adap->dev, "I2C level transfers not supported\n");
-		return -ENOSYS;
+		entry->result = -ENOSYS;
 	}
 }
 
+int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
+{
+	struct i2c_op_q_entry *entry;
+	int   rv;
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+	return -ENOMEM;
+
+	entry->i2c.msgs = msgs;
+	entry->i2c.num = num;
+
+	i2c_transfer_entry(adap, entry);
+	rv = entry->result;
+	kfree(entry);
+	return rv;
+}
+
 int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
 {
 	int ret;
@@ -1038,185 +1059,181 @@
 	}
 }
 
-static int i2c_smbus_complete_entry(struct i2c_adapter * adapter, u16 addr,
-unsigned short flags, char read_write,
-u8 command, int size,
-union i2c_smbus_data * data,
-int swpec, u8 partial,
-int result)
-{
-	if (result < 0)
-		return result;
-
-	if(swpec &&
-	   size != I2C_SMBUS_QUICK &&
-	   size != I2C_SMBUS_I2C_BLOCK_DATA &&
-	   (read_write == I2C_SMBUS_READ ||
-	size == I2C_SMBUS_PROC_CALL_PEC ||
-	size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
-		if(i2c_smbus_check_pec(addr,
-   command,
-   size,
-   partial,
-   data))
-			return -EINVAL;
-	}
+static void i2c_smbus_complete_entry(struct i2c_adapter * adapter,
+ struct i2c_op_q_entry * entry)
+{
+	if (entry->result < 0)
+		return;
 
-	return 0;
+	if(entry->swpec &&
+	   entry->smbus.size != I2C_SMBUS_QUICK &&
+	   entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA &&
+	   (entry->smbus.read_write == I2C_SMBUS_READ ||
+	entry->smbus.size == I2C_SMBUS_PROC_CALL_PEC ||
+	entry->smbus.size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
+		if(i2c_smbus_check_pec(entry->smbus.addr,
+   entry->smbus.command,
+   entry->smbus.size,
+   entry->partial,
+   entry->smbus.data))
+			entry->result = -EINVAL;
+	}
 }
 
-static void i2c_smbus_format_entry(struct i2c_adapter * adapter, u16 addr,
-   unsigned short *flags, char read_write,
-   u8 command, int *size,
-   union i2c_smbus_data * data,
-   int *swpec, u8 *partial)
-{
-	*swpec = 0;
-	*partial = 0;
-	*flags &= I2C_M_TEN | I2C_CLIENT_PEC;
-	if((*flags & I2C_CLIENT_PEC) &&
+static void i2c_smbus_format_entry(struct i2c_adapter * adapter,
+   struct i2c_op_q_entry * entry)
+{
+	entry->swpec = 0;
+	entry->partial = 0;
+	entry->smbus.flags &= I2C_M_TEN | I2C_CLIENT_PEC;
+	if((entry->smbus.flags & I2C_CLIENT_PEC) &&
 	   !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
-		*swpec = 1;
-		if(read_write == I2C_SMBUS_READ &&
-		   *size == I2C_SMBUS_BLOCK_DATA)
-			*size = I2C_SMBUS_BLOCK_DATA_PEC;
-		else if(*size == I2C_SMBUS_PROC_CALL)
-			*size = I2C_SMBUS_PROC_CALL_PEC;
-		else if(*size == I2C_SMBUS_BLOCK_PROC_CALL) {
-			unsigned char *sdata = data->block;
-			i2c_smbus_add_pec(addr, command, I2C_SMBUS_BLOCK_DATA,
-	  data);
-			*partial = sdata[sdata[0] + 1];
-			*size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
-		} else if(read_write == I2C_SMBUS_WRITE &&
-		  *size != I2C_SMBUS_QUICK &&
-		  *size != I2C_SMBUS_I2C_BLOCK_DATA)
-			*size = i2c_smbus_add_pec(addr, command, *size, data);
+		entry->swpec = 1;
+		if(entry->smbus.read_write == I2C_SMBUS_READ &&
+		   entry->smbus.size == I2C_SMBUS_BLOCK_DATA)
+			entry->smbus.size = I2C_SMBUS_BLOCK_DATA_PEC;
+		else if(entry->smbus.size == I2C_SMBUS_PROC_CALL)
+			entry->smbu

[PATCH] Update to IPMI driver to support old DMI spec

2005-02-09 Thread Corey Minyard
BTW, I'm also working with the person who had the trouble with the I2C 
non-blocking driver updates, but we haven't figured it out yet.  
Hopefully soon.  (Though that has nothing to do with this patch.)

Thanks,
-Corey
The 1999 version of the DMI spec had a different configuration
than the newer versions for the IPMI configuration information.
This patch handles the differences between the two.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc3/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.11-rc3.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.11-rc3/drivers/char/ipmi/ipmi_si_intf.c
@@ -1578,46 +1578,53 @@
u8  *data = (u8 *)dm;
unsigned long   base_addr;
u8  reg_spacing;
+   u8  len = dm->length; 
dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
 
ipmi_data->type = data[4];
 
memcpy(&base_addr, data+8, sizeof(unsigned long));
-   if (base_addr & 1) {
-   /* I/O */
-   base_addr &= 0xFFFE;
+   if (len >= 0x11) {
+   if (base_addr & 1) {
+   /* I/O */
+   base_addr &= 0xFFFE;
+   ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
+   }
+   else {
+   /* Memory */
+   ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
+   }
+   /* If bit 4 of byte 0x10 is set, then the lsb for the address
+  is odd. */
+   ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
+
+   ipmi_data->irq = data[0x11];
+
+   /* The top two bits of byte 0x10 hold the register spacing. */
+   reg_spacing = (data[0x10] & 0xC0) >> 6;
+   switch(reg_spacing){
+   case 0x00: /* Byte boundaries */
+   ipmi_data->offset = 1;
+   break;
+   case 0x01: /* 32-bit boundaries */
+   ipmi_data->offset = 4;
+   break;
+   case 0x02: /* 16-byte boundaries */
+   ipmi_data->offset = 16;
+   break;
+   default:
+   /* Some other interface, just ignore it. */
+   return -EIO;
+   }
+   } else {
+   /* Old DMI spec. */
+   ipmi_data->base_addr = base_addr;
ipmi_data->addr_space = IPMI_IO_ADDR_SPACE;
-   }
-   else {
-   /* Memory */
-   ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
-   }
-
-   /* The top two bits of byte 0x10 hold the register spacing. */
-   reg_spacing = (data[0x10] & 0xC0) >> 6;
-   switch(reg_spacing){
-   case 0x00: /* Byte boundaries */
ipmi_data->offset = 1;
-   break;
-   case 0x01: /* 32-bit boundaries */
-   ipmi_data->offset = 4;
-   break;
-   case 0x02: /* 16-byte boundaries */
-   ipmi_data->offset = 16;
-   break;
-   default:
-   /* Some other interface, just ignore it. */
-   return -EIO;
}
 
ipmi_data->slave_addr = data[6];
 
-   /* If bit 4 of byte 0x10 is set, then the lsb for the address
-  is odd. */
-   ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
-
-   ipmi_data->irq = data[0x11];
-
if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
dmi_data_entries++;
return 0;


[PATCH] Fix IPMI SMBus driver to select the I2C layer instead of depend on it

2005-02-09 Thread Corey Minyard
This is on top of the IPMI SMBus driver in the current mm kernel.
Thanks,
-Corey
Make the IPMI SMBus select I2C, not depend on it, so I2C gets
enabled properly when the IPMI SMBus is enabled.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc3/drivers/char/ipmi/Kconfig
===
--- linux-2.6.11-rc3.orig/drivers/char/ipmi/Kconfig
+++ linux-2.6.11-rc3/drivers/char/ipmi/Kconfig
@@ -53,7 +53,8 @@
 
 config IPMI_SMB
tristate 'IPMI SMBus handler'
-   depends on IPMI_HANDLER && I2C
+   depends on IPMI_HANDLER
+   select I2C
help
  Provides a driver for a SMBus interface to a BMC, meaning that you
 have a driver that must be accessed over an I2C bus instead of a


Re: [PATCH] Update to IPMI driver to support old DMI spec

2005-02-09 Thread Corey Minyard
Bukie Mabayoje wrote:
Corey Minyard wrote:
 

BTW, I'm also working with the person who had the trouble with the I2C
non-blocking driver updates, but we haven't figured it out yet.
Hopefully soon.  (Though that has nothing to do with this patch.)
Thanks,
-Corey
 ---
The 1999 version of the DMI spec had a different configuration
than the newer versions for the IPMI configuration information.
   

Are you referring to the System Management BIOS Reference Specification  version 2.3.1 16 March 1999?
 

Yes, that is correct.
-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Fw: [Bug 4171] New: bttv seems broken here

2005-02-10 Thread Corey Minyard
JJ Luza and I found the problem.  A patch to the I2C non-blocking 
changes is attached.  JJ was a tremendous help on this.

-Corey
Andrew Morton wrote:
Not sure who to blame here ;)
Corey made some i2c changes...
Begin forwarded message:
Date: Sat, 5 Feb 2005 13:36:53 -0800
From: [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Subject: [Bug 4171] New: bttv seems broken here
http://bugme.osdl.org/show_bug.cgi?id=4171
  Summary: bttv seems broken here
   Kernel Version: 2.6.11-rc3-mm1
   Status: NEW
 Severity: normal
Distribution: Debian Sid
Hardware Environment: Nforce2 + gforce4 + leadtek winfast TV 2000 (Bt878)  
Software Environment: kernel module is snd_bt87x (and tuner and bttv), and tv 
app is xdtv. 
Problem Description: I can't watch tv with this kernel (it worked with 
2.6.10). There is no image or sound with xdtv, and I get these errors sent by 
kernel when I try to access the bttv device : 

 


The I2C non-blocking patch would incorrectly return success in some
cases because it wasn't updating the proper result variable.  This
patch fixes the problem.  The bttv driver now works properly with
the I2C non-blocking patch.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc3/drivers/i2c/i2c-core.c
===
--- linux-2.6.11-rc3.orig/drivers/i2c/i2c-core.c
+++ linux-2.6.11-rc3/drivers/i2c/i2c-core.c
@@ -899,9 +899,11 @@
  entry->i2c.num);
up(&adap->bus_lock);
 
+   entry->result = ret;
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
+   entry->result = -ENOSYS;
return -ENOSYS;
}
 }
@@ -1491,7 +1493,7 @@
msg[0].len = 1;
msg[1].addr = entry->smbus.addr;
msg[1].flags = entry->smbus.flags | I2C_M_RD;
-   msg[1].len = 1;
+   msg[1].len = 0;
 
msgbuf0[0] = entry->smbus.command;
switch(entry->smbus.size) {
@@ -1593,17 +1595,17 @@
 
 /* Simulate a SMBus command using the i2c protocol 
No checking of parameters is done!  */
-static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adap,
-  struct i2c_op_q_entry * entry)
+static void i2c_smbus_xfer_emulated(struct i2c_adapter * adap,
+   struct i2c_op_q_entry * entry)
 
 {
-   if (i2c_smbus_emu_format(adap, entry))
-   return -EINVAL;
-
-   if (i2c_transfer_entry(adap, entry) < 0)
-   return -EINVAL;
+   if (i2c_smbus_emu_format(adap, entry)) {
+   entry->result = -EINVAL;
+   return;
+   }
 
-   return entry->result;
+   /* Return value will be put into entry->result. */
+   i2c_transfer_entry(adap, entry);
 }
 
 s32 i2c_smbus_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,


Re: 2.6.11-rc3-mm2

2005-02-10 Thread Corey Minyard
Andrew Morton wrote:
ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.11-rc3/2.6.11-rc3-mm2/
- Added the mlock and !SCHED_OTHER Linux Security Module for the audio guys.
 It seems that nothing else is going to come along and this is completely
 encapsulated.
- Various other stuff.  If anyone has a patch in here which they think
 should be in 2.6.11, please let me know.  I'm intending to merge the
 following into 2.6.11:
alpha-add-missing-dma_mapping_error.patch
fix-compat-shmget-overflow.patch
fix-shmget-for-ppc64-s390-64-sparc64.patch
binfmt_elf-clearing-bss-may-fail.patch
qlogic-warning-fixes.patch
oprofile-exittext-referenced-in-inittext.patch
force-read-implies-exec-for-all-32bit-processes-in-x86-64.patch
oprofile-arm-xscale1-pmu-support-fix.patch
 

The following one should probably go in:
+update-to-ipmi-driver-to-support-old-dmi-spec.patch
 

Systems with old data will not work correctly without it.  There seems 
to be a few of them out there.

-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] Fix IPMI LAN bridging

2005-02-11 Thread Corey Minyard

The size of LAN bridged messages was not being returned properly from
the function that calculated address sizes.  This fixes the problem.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc3/drivers/char/ipmi/ipmi_msghandler.c
===
--- linux-2.6.11-rc3.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.11-rc3/drivers/char/ipmi/ipmi_msghandler.c
@@ -480,6 +480,9 @@
return sizeof(struct ipmi_ipmb_addr);
}
 
+   if (addr_type == IPMI_LAN_ADDR_TYPE)
+   return sizeof(struct ipmi_lan_addr);
+
return 0;
 }
 


Re: Adding an async I2C interface

2005-01-27 Thread Corey Minyard
Mark Studebaker wrote:
is there a way to do this solely in i2c-core without having to
add support to all the drivers?
Yes and no.  In order to support this async operation, the driver cannot 
block and do things like msleep() or schedule().  It has to start the 
operation, return, and either let polling or an interrupt drive the 
continued operation.  Thus for async operations the driver has to be 
modified.  However, if async operation is not required, the driver can 
stay as is.

I've been working on this and will probably have a patch tomorrow.  I've 
modified the piix4 and the i801 drivers, I probably won't do any more 
myself unless the need arises, since I can't test any others.  Note that 
this still supports the old driver interface, so no drivers need to be 
rewritten.  That way, they only need to be modified if something needs 
the async interface.  So drivers that have an RTC on them or that 
support IPMI BMCs could be rewritten, but nothing else needs to be done.

I've also noticed a somewhat cavalier attitude in this code with respect 
to return values.  I've cleaned some of that up so return values are not 
just -1 on error, but are proper errno values.  However, I've only fixed 
the core code and the drivers I've worked on.

Thanks,
-Corey
Corey Minyard wrote:
I have an IPMI interface driver that sits on top of the I2C code.  I'd
like to get it into the mainstream kernel, but I have a few problems
to solve first before I can do that.  The I2C code is synchronous and
must run from a task context.  The IPMI driver has certain
operations that occur at panic time, including:
  * Storing panic information in IPMI's system event log
  * Extending the watchdog timer so it doesn't go off during panic
operations (like kernel coredumps).
  * Powering the system off
I can't really put the IPMI SMB interface into the kernel until I can
do those operations.  Also, I understand that some vendors put RTC
chips onto the I2C bus and this must be accessed outside task context,
too.  I would really like add asynchronous interface to the I2C bus
drivers.  I propose:
  * Adding an async send interface to the busses that does a callback
when the operation is complete.
  * Adding a poll interface to the busses.  The I2C core code could
call this if a synchronous call is made from task context (much
like all the current drivers do right now).  For asyncronous
operation, the I2C core code would call it from a timer
interrupt.  If the driver supported interrupts, polling from the
timer interrupt would not be necessary.
  * Add async operations for the user to call, including access to the
polling code.
  * If the driver didn't support an async send, it would work as it
does today and the async calls would return ENOSYS.
This way, the bus drivers on I2C could be converted on a
driver-by-driver basis.  The IPMI code could query to see if the
driver supported async operations.  And the RTC code could use it,
too.
Is this ok with the I2C community?  I would do the base work and
convert over a few drivers.
Thanks,
-Corey

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Adding an async I2C interface

2005-01-28 Thread Corey Minyard
Bukie Mabayoje wrote:
I will be glad to work with on this,  I have some exposure to the BMC. 
See text below in blue.

bukie
Corey Minyard wrote:
Mark Studebaker wrote:
> is there a way to do this solely in i2c-core without having to
> add support to all the drivers?
Yes and no.  In order to support this async operation, the driver cannot
block and do things like msleep() or schedule().
The Interface driver must be a user space driver.
That is precisely the problem.  What happens if you need to get to the 
i2c bus but you are not running from a task context?

It has to start the
operation, return, and either let polling or an interrupt drive the
continued operation.  Thus for async operations the driver has to be
modified.  However, if async operation is not required, the driver can
stay as is.
I've been working on this and will probably have a patch tomorrow.  I've
modified the piix4 and the i801 drivers, I probably won't do any more
myself unless the need arises, since I can't test any others.  Note that
this still supports the old driver interface, so no drivers need to be
rewritten.  That way, they only need to be modified if something needs
the async interface.  So drivers that have an RTC on them or that
support IPMI BMCs could be rewritten, but nothing else needs to be done.
I've also noticed a somewhat cavalier attitude in this code with respect
to return values.  I've cleaned some of that up so return values are not
just -1 on error, but are proper errno values.  However, I've only fixed
the core code and the drivers I've worked on.
Thanks,
-Corey
>
> Corey Minyard wrote:
>
>> I have an IPMI interface driver that sits on top of the I2C code.  
I'd
>> like to get it into the mainstream kernel, but I have a few problems
>> to solve first before I can do that.  The I2C code is synchronous and
>> must run from a task context.

I am not sure what you mean that the I2C code is synchronous. I2C bus 
is Asynchronous which means that the data clock is not included in the 
data. The Sender and Receiver agrees on the timing parameters prior to 
the bus transaction.
I mean the driver, not the hardware.  By the I2C driver being 
synchronous, I mean that you call a function, the whole operation occurs 
in the function, and then the function returns the result.  By 
asynchronous, I mean that you tell the driver to start an operation and 
the driver starts it and immediately returns.  It then uses interrupts, 
timers, or polling calls to drive the operation of the interface.  When 
the operation is done, the results are reported back through a callback 
function provided when the driver started.

Plus there are SMB alerts which the hardware can generate 
asynchronously.  The I2C driver has no concept of that right now.

The IPMI driver has certain
>> operations that occur at panic time, including:
>>
>>   * Storing panic information in IPMI's system event log
>>   * Extending the watchdog timer so it doesn't go off during panic
>> operations (like kernel coredumps).
>>   * Powering the system off
>>
Is this driver compliant with the IPMI spec? Because the above should 
be a sensor that must be enable or disable. A driver should not make 
sure a decision by itself.
There are two parts here.  There is the I2C driver and the IPMI driver 
that sits on top of it.  I'm really only taking about the I2C driver 
here, I need asynchronous operation from the I2C driver to do those 
things in the IPMI driver.

 
>> I can't really put the IPMI SMB interface into the kernel until I can
>> do those operations.  Also, I understand that some vendors put RTC
>> chips onto the I2C bus and this must be accessed outside task 
context,
>> too.
What the vendor put on the board doesn't matter with respect to IPMI. 
What matter is that you have access to the Master where the slave you 
talking to is connect on the I2C bus.

I would really like add asynchronous interface to the I2C bus
>> drivers.
Do you mean a  blocking and non blocking I/O?
Yes, that is a better term.  I'll switch to using that.
-Corey
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] Add a non-blocking I2C interface

2005-01-28 Thread Corey Minyard
Here's the code that I have so far for adding a non-blocking interface 
to the I2C interface.  I've debated whether to do this as a patch or 
just post the files, because the patch is about half the size of the 
files.  I've decided on the diff for now, it seems to be fairly 
readable.  This is relative to 2.6.11-rc2.

I have not extensively tested this patch.  I've done eeprom operations 
on the piix4 and i801 chips both with and without updating the those 
interface for non-blocking operation.  I'm going to test the block 
transfers with the IPMI driver when I get access to a system (this 
weekend).  This is posted for comment.

This patch doesn't actually change much.  It adds a queue entry that is 
used to pass around the message data (and is obviously used for queuing 
:).  But this mostly is using the queue entry for data, breaking the 
operations into smaller functions, and doing the polling in the i2c-core 
code instead of the drivers themselves (for non-blocking capable 
drivers).  Function for unchanged drivers should be unchanged.

This does not implement SMB Alert, which should improve the performace 
of the IPMI SMB driver.  I'll do that in the future and just poll the 
interface for now.

I'll post the changes to the i801 driver next.
This patch requires the fixes to the completion code that Mike Waychison 
posted a few days ago 
(http://marc.theaimsgroup.com/?l=linux-kernel&m=110669761400454&w=2).  
Otherwise the wait_for_completion_interruptible() and 
wait_for_completion_timeout() are broken.

In case you missed the previous discussion, I need a non-blocking 
interface in the I2C code for use by the IPMI SMB driver.  The driver 
needs to be able to do things like store panic information in the SEL, 
ping the watchdog timer while in a panic, and power the system off.  The 
current I2C driver requires a task context, but you can't exactly do 
things at panic time with a task context.

-Corey
Index: linux-2.6.11-rc2/drivers/i2c/i2c-core.c
===
--- linux-2.6.11-rc2.orig/drivers/i2c/i2c-core.c2005-01-26 
15:59:53.0 -0600
+++ linux-2.6.11-rc2/drivers/i2c/i2c-core.c 2005-01-28 08:54:00.0 
-0600
@@ -30,8 +30,14 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+static int i2c_stop_timer(struct i2c_adapter * adap);
+static void i2c_start_timer(struct i2c_adapter * adap,
+   struct i2c_op_q_entry * entry);
+
+#define USEC_PER_JIFFIE (100 / HZ)
 
 static LIST_HEAD(adapters);
 static LIST_HEAD(drivers);
@@ -134,11 +140,26 @@
}
 
adap->nr =  id & MAX_ID_MASK;
+   spin_lock_init(&adap->q_lock);
+   INIT_LIST_HEAD(&adap->q);
init_MUTEX(&adap->bus_lock);
init_MUTEX(&adap->clist_lock);
list_add_tail(&adap->list,&adapters);
INIT_LIST_HEAD(&adap->clients);
 
+   adap->timer = kmalloc(sizeof(*adap->timer), GFP_KERNEL);
+   if (!adap->timer) {
+   res = -ENOMEM;
+   goto out_unlock;
+   }
+   
+   init_timer(&adap->timer->timer);
+   spin_lock_init(&adap->timer->lock);
+   adap->timer->deleted = 0;
+   adap->timer->running = 0;
+   adap->timer->next_call_time = 0;
+   adap->timer->adapter = adap;
+
/* Add the adapter to the driver core.
 * If the parent pointer is not set up,
 * we add this adapter to the host bus.
@@ -181,6 +202,7 @@
struct i2c_driver *driver;
struct i2c_client *client;
int res = 0;
+   unsigned long flags;
 
down(&core_lists);
 
@@ -233,6 +255,17 @@
device_unregister(&adap->dev);
list_del(&adap->list);
 
+   /* Stop the timer and free its memory */
+   spin_lock_irqsave(&adap->timer->lock, flags);
+   if (i2c_stop_timer(adap)) {
+   spin_unlock_irqrestore(&adap->timer->lock, flags);
+   kfree(adap->timer);
+   } else {
+   adap->timer->deleted = 1;
+   spin_unlock_irqrestore(&adap->timer->lock, flags);
+   }
+   adap->timer = NULL;
+
/* wait for sysfs to drop all references */
wait_for_completion(&adap->dev_released);
wait_for_completion(&adap->class_dev_released);
@@ -583,15 +616,283 @@
  * 
  */
 
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
+/* Must be called with the q_lock held. */
+static void i2c_start_entry(struct i2c_adapter * adap,
+   struct i2c_op_q_entry * entry)
+{
+   entry->started = 1;
+   switch (entry->xfer_type) {
+   case I2C_OP_I2C:
+   adap->algo->master_start(adap, entry);
+   break;
+   case I2C_OP_SMBUS:
+   adap->algo->smbus_start(adap, entry);
+   break;
+   default:
+   entry->result = -EINVAL;
+   i2c_op_done(adap, entry);
+   }
+
+   if 

[PATCH] Updates for the i801 driver to support the I2C non-blocking interface

2005-01-28 Thread Corey Minyard
Here's the changes required for the i801 driver.  See the previous post 
for the patch to add a non-blocking interface to the I2C driver.

Like the core I2C changes, this is mostly breaking the functions into 
smaller pieces and calling them from the appropriate places.

-Corey
Index: linux-2.6.11-rc2/drivers/i2c/busses/i2c-i801.c
===
--- linux-2.6.11-rc2.orig/drivers/i2c/busses/i2c-i801.c 2005-01-27 
13:09:12.0 -0600
+++ linux-2.6.11-rc2/drivers/i2c/busses/i2c-i801.c  2005-01-27 
13:46:23.0 -0600
@@ -79,7 +79,8 @@
 #define SMBHSTCFG_I2C_EN   4
 
 /* Other settings */
-#define MAX_TIMEOUT100
+#define MAX_TIMEOUT_US 10
+#define RETRY_TIME_US  500 /* Retry minimum is 500us */
 #define ENABLE_INT90   /* set to 0x01 to enable - untested */
 
 /* I801 command constants */
@@ -105,21 +106,31 @@
 "Forcibly enable the I801 at the given address. "
 "EXTREMELY DANGEROUS!");
 
-static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data,
- char read_write, int command);
-
 static unsigned short i801_smba;
 static struct pci_dev *I801_dev;
 static int isich4;
 
+struct i801_i2c_data
+{
+   int i;
+   int len;
+   unsigned char hostc;
+   int block;
+   int hwpec;
+   int xact;
+   int hststs;
+   int wait_intr;
+   int finished;
+};
+struct i801_i2c_data i801_data;
+
 static int i801_setup(struct pci_dev *dev)
 {
int error_return = 0;
unsigned char temp;
 
/* Note: we keep on searching until we have found 'function 3' */
-   if(PCI_FUNC(dev->devfn) != 3)
+   if (PCI_FUNC(dev->devfn) != 3)
return -ENODEV;
 
I801_dev = dev;
@@ -136,7 +147,7 @@
} else {
pci_read_config_word(I801_dev, SMBBA, &i801_smba);
i801_smba &= 0xfff0;
-   if(i801_smba == 0) {
+   if (i801_smba == 0) {
dev_err(&dev->dev, "SMB base address uninitialized"
"- upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV;
@@ -180,12 +191,93 @@
return error_return;
 }
 
-static int i801_transaction(void)
+static void i801_check_hststs(struct i2c_adapter *adap,
+ struct i2c_op_q_entry *entry,
+ struct i801_i2c_data *d)
+{
+   if (d->hststs & 0x10) {
+   entry->result = -EIO;
+   dev_dbg(&I801_dev->dev,
+   "Error: Failed bus transaction\n");
+   } else if (d->hststs & 0x08) {
+   entry->result = -EIO;
+   dev_err(&I801_dev->dev, "Bus collision!\n");
+   /* Clock stops and slave is stuck in mid-transmission */
+   } else if (d->hststs & 0x04) {
+   entry->result = -EIO;
+   dev_dbg(&I801_dev->dev, "Error: no response!\n");
+   }
+}
+
+static void i801_finish(struct i2c_adapter *adap,
+   struct i2c_op_q_entry *entry,
+   struct i801_i2c_data *d)
+{
+   d->finished = 1;
+
+#ifdef HAVE_PEC
+   if (isich4 && d->hwpec) {
+   if (entry->smbus.size != I2C_SMBUS_QUICK &&
+  entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA)
+   outb_p(0, SMBAUXCTL);
+   }
+#endif
+
+   if (d->block || (entry->result < 0) ||
+  ((entry->smbus.read_write == I2C_SMBUS_WRITE)
+   || (d->xact == I801_QUICK)))
+   return;
+
+   switch (d->xact & 0x7f) {
+   case I801_BYTE: /* Result put in SMBHSTDAT0 */
+   case I801_BYTE_DATA:
+   entry->smbus.data->byte = inb_p(SMBHSTDAT0);
+   break;
+   case I801_WORD_DATA:
+   entry->smbus.data->word = inb_p(SMBHSTDAT0)
+   + (inb_p(SMBHSTDAT1) << 8);
+   break;
+   }
+}
+
+static void i801_transaction_final_check(struct i2c_adapter *adap,
+struct i2c_op_q_entry *entry,
+struct i801_i2c_data *d)
+{
+   i801_check_hststs(adap, entry, d);
+
+   if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
+   outb_p(inb(SMBHSTSTS), SMBHSTSTS);
+
+   if ((d->hststs = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+   dev_dbg(&I801_dev->dev, "Failed reset at end of transaction"
+   "(%02x)\n", d->hststs);
+   }
+   dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
+   "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
+   inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+   inb_p(SMBHSTDAT1));
+}
+
+static void i801_transaction_poll(struct i2c_adapter *adap,
+ struct i2c_op_q_entry *entry,
+  

[PATCH] Changes to the I2C driver to support a non-blocking interface

2005-02-01 Thread Corey Minyard
Following is a patch to add a non-blocking interface to I2C.  I need 
this because I need to be able to do I2C things at panic time in the 
IPMI SMB driver.  It should also help systems with an RTC on the I2C bus 
since they need access to the RTC in situations without a task context.

-Corey
This patch adds a non-blocking interface to the I2C code.  This
is needed by some RTC drivers on the I2C bus and is needed by
the IPMI code so it can do things at panic time.

The non-blocking interface requires changes to the driver
below it.  The current drivers will work as-is, but will not
be able to use the non-blocking interfaces.

This is been tested with a PIIX4 and i801 driver modified to use
the asynchronous interface.  The eeprom code and the IPMI SMB
driver were tested on top of it.  The IPMI SMB driver was
modified to use the SMB interface, and I ran it for many
hours without problem under moderate to heavy load.

The changes are rather extensive, but are mostly reorganization
and the addition of the async interface.

This also adds back in the i2c_smbus_read_block_data() function
which is needed by the IPMI SMB driver (coming soon).

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc2/drivers/i2c/i2c-core.c
===
--- linux-2.6.11-rc2.orig/drivers/i2c/i2c-core.c
+++ linux-2.6.11-rc2/drivers/i2c/i2c-core.c
@@ -30,8 +30,14 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
+static int i2c_stop_timer(struct i2c_adapter * adap);
+static void i2c_start_timer(struct i2c_adapter * adap,
+   struct i2c_op_q_entry * entry);
+
+#define USEC_PER_JIFFIE (100 / HZ)
 
 static LIST_HEAD(adapters);
 static LIST_HEAD(drivers);
@@ -134,11 +140,26 @@
}
 
adap->nr =  id & MAX_ID_MASK;
+   spin_lock_init(&adap->q_lock);
+   INIT_LIST_HEAD(&adap->q);
init_MUTEX(&adap->bus_lock);
init_MUTEX(&adap->clist_lock);
list_add_tail(&adap->list,&adapters);
INIT_LIST_HEAD(&adap->clients);
 
+   adap->timer = kmalloc(sizeof(*adap->timer), GFP_KERNEL);
+   if (!adap->timer) {
+   res = -ENOMEM;
+   goto out_unlock;
+   }
+   
+   init_timer(&adap->timer->timer);
+   spin_lock_init(&adap->timer->lock);
+   adap->timer->deleted = 0;
+   adap->timer->running = 0;
+   adap->timer->next_call_time = 0;
+   adap->timer->adapter = adap;
+
/* Add the adapter to the driver core.
 * If the parent pointer is not set up,
 * we add this adapter to the host bus.
@@ -181,6 +202,7 @@
struct i2c_driver *driver;
struct i2c_client *client;
int res = 0;
+   unsigned long flags;
 
down(&core_lists);
 
@@ -233,6 +255,17 @@
device_unregister(&adap->dev);
list_del(&adap->list);
 
+   /* Stop the timer and free its memory */
+   spin_lock_irqsave(&adap->timer->lock, flags);
+   if (i2c_stop_timer(adap)) {
+   spin_unlock_irqrestore(&adap->timer->lock, flags);
+   kfree(adap->timer);
+   } else {
+   adap->timer->deleted = 1;
+   spin_unlock_irqrestore(&adap->timer->lock, flags);
+   }
+   adap->timer = NULL;
+
/* wait for sysfs to drop all references */
wait_for_completion(&adap->dev_released);
wait_for_completion(&adap->class_dev_released);
@@ -583,15 +616,287 @@
  * 
  */
 
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
+#define entry_completed(e) (atomic_read(&(e)->completed) <= 0)
+
+/* Must be called with the q_lock held. */
+static void i2c_start_entry(struct i2c_adapter * adap,
+   struct i2c_op_q_entry * entry)
+{
+   entry->started = 1;
+   switch (entry->xfer_type) {
+   case I2C_OP_I2C:
+   adap->algo->master_start(adap, entry);
+   break;
+   case I2C_OP_SMBUS:
+   adap->algo->smbus_start(adap, entry);
+   break;
+   default:
+   entry->result = -EINVAL;
+   i2c_op_done(adap, entry);
+   }
+
+   if (!entry_completed(entry) && entry->use_timer)
+   i2c_start_timer(adap, entry);
+}
+
+/* Get the first entry off the head of the queue and lock it there.
+   The entry is guaranteed to remain first in the list and the handler
+   not be called until i2c_entry_put() is called. */
+static struct i2c_op_q_entry *_i2c_entry_get(struct i2c_adapter * adap)
 {
-   int ret;
+   struct i2c_op_q_entry * entry = NULL;
+
+   if (!list_empty(&adap->q)) {
+   struct list_head * link = adap-&

[PATCH] Minor IPMI enhancements

2005-02-01 Thread Corey Minyard


This patch cleans up the DMI handling so that multiple interfaces
can be reported from the DMI tables and so that the DMI slave
address can be transferred up to the upper layer.  It also adds
an option to specify the slave address as an init parm and removes
some unnecessary initializers.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc2/drivers/char/ipmi/ipmi_si_intf.c
===
--- linux-2.6.11-rc2.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-2.6.11-rc2/drivers/char/ipmi/ipmi_si_intf.c
@@ -176,6 +176,9 @@
unsigned char ipmi_version_major;
unsigned char ipmi_version_minor;
 
+   /* Slave address, could be reported from DMI. */
+   unsigned char slave_addr;
+
/* Counters and things for the proc filesystem. */
spinlock_t count_lock;
unsigned long short_timeouts;
@@ -407,7 +410,7 @@
/* Error fetching flags, just give up for
   now. */
smi_info->si_state = SI_NORMAL;
-   } else if (len < 3) {
+   } else if (len < 4) {
/* Hmm, no flags.  That's technically illegal, but
   don't use uninitialized data. */
smi_info->si_state = SI_NORMAL;
@@ -897,21 +900,23 @@
 #define DEFAULT_REGSPACING 1
 
 static int   si_trydefaults = 1;
-static char  *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL };
+static char  *si_type[SI_MAX_PARMS];
 #define MAX_SI_TYPE_STR 30
 static char  si_type_str[MAX_SI_TYPE_STR];
-static unsigned long addrs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_addrs = 0;
-static unsigned int  ports[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_ports = 0;
-static int   irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_irqs = 0;
-static int   regspacings[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static unsigned long addrs[SI_MAX_PARMS];
+static int num_addrs;
+static unsigned int  ports[SI_MAX_PARMS];
+static int num_ports;
+static int   irqs[SI_MAX_PARMS];
+static int num_irqs;
+static int   regspacings[SI_MAX_PARMS];
 static int num_regspacings = 0;
-static int   regsizes[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int   regsizes[SI_MAX_PARMS];
 static int num_regsizes = 0;
-static int   regshifts[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int   regshifts[SI_MAX_PARMS];
 static int num_regshifts = 0;
+static int slave_addrs[SI_MAX_PARMS];
+static int num_slave_addrs = 0;
 
 
 module_param_named(trydefaults, si_trydefaults, bool, 0);
@@ -955,6 +960,12 @@
 " IPMI register, in bits.  For instance, if the data"
 " is read from a 32-bit word and the IPMI data is in"
 " bit 8-15, then the shift would be 8");
+module_param_array(slave_addrs, int, &num_slave_addrs, 0);
+MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
+" the controller.  Normally this is 0x20, but can be"
+" overridden by this parm.  This is an array indexed"
+" by interface number.");
+
 
 #define IPMI_MEM_ADDR_SPACE 1
 #define IPMI_IO_ADDR_SPACE  2
@@ -1542,7 +1553,6 @@
 #endif
 
 #ifdef CONFIG_X86
-
 typedef struct dmi_ipmi_data
 {
u8  type;
@@ -1550,24 +1560,29 @@
unsigned long   base_addr;
u8  irq;
u8  offset;
-}dmi_ipmi_data_t;
+   u8  slave_addr;
+} dmi_ipmi_data_t;
+
+static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
+static int dmi_data_entries;
 
 typedef struct dmi_header
 {
u8  type;
u8  length;
u16 handle;
-}dmi_header_t;
+} dmi_header_t;
 
-static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
+static int decode_dmi(dmi_header_t *dm, int intf_num)
 {
u8  *data = (u8 *)dm;
unsigned long   base_addr;
u8  reg_spacing;
+   dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
 
-   ipmi_data->type = data[0x04];
+   ipmi_data->type = data[4];
 
-   memcpy(&base_addr,&data[0x08],sizeof(unsigned long));
+   memcpy(&base_addr, data+8, sizeof(unsigned long));
if (base_addr & 1) {
/* I/O */
base_addr &= 0xFFFE;
@@ -1591,33 +1606,36 @@
ipmi_data->offset = 16;
break;
default:
-   printk("ipmi_si: Unknown SMBIOS IPMI Base Addr"
-  " Modifier: 0x%x\n", reg_spacing);
+   /* Some other interface, just ignore it. */
return -EIO;
}
 
+   ipmi_data->slave_addr = data[6];
+
/* If bit 4 of byte 0x10 is set, then the lsb for the address
   

[PATCH] Modify the i801 I2C driver to use the non-blocking interface.

2005-02-01 Thread Corey Minyard
I just posted my proposed non-blocking changes to the i2c driver.  This 
is the changes for the i801 driver.
This patch modifies the I801 SMBus driver to use the non-blocking
interface.

Signed-off-by: Corey Minyard <[EMAIL PROTECTED]>

Index: linux-2.6.11-rc2/drivers/i2c/busses/i2c-i801.c
===
--- linux-2.6.11-rc2.orig/drivers/i2c/busses/i2c-i801.c
+++ linux-2.6.11-rc2/drivers/i2c/busses/i2c-i801.c
@@ -40,6 +40,14 @@
 
 /* Note: we assume there can only be one I801, with one SMBus interface */
 
+/* Another note: This interface is extremely sensitive to timing and
+   failure handling.  If you don't wait at least one jiffie after
+   starting the transaction before checking things, you will screw it
+   up.  If you don't wait a jiffie after the final check, you will
+   screw it up.  If you screw it up by these manners or by abandoning
+   an operation in progress, the I2C bus is likely stuck and won't
+   work any more.  Gotta love this hardware. */
+
 #include 
 #include 
 #include 
@@ -79,7 +87,8 @@
 #define SMBHSTCFG_I2C_EN   4
 
 /* Other settings */
-#define MAX_TIMEOUT100
+#define MAX_TIMEOUT_US 10
+#define RETRY_TIME_US  500 /* Retry minimum is 500us */
 #define ENABLE_INT90   /* set to 0x01 to enable - untested */
 
 /* I801 command constants */
@@ -105,21 +114,35 @@
 "Forcibly enable the I801 at the given address. "
 "EXTREMELY DANGEROUS!");
 
-static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data,
- char read_write, int command);
-
 static unsigned short i801_smba;
 static struct pci_dev *I801_dev;
 static int isich4;
 
+struct i801_i2c_data
+{
+   int i;
+   int len;
+   unsigned char hostc;
+   int block;
+   int hwpec;
+   int xact;
+   int hststs;
+   int wait_intr;
+   int finished;
+
+   /* Used to handle removal race conditions. */
+   int in_removal;
+   int in_use;
+};
+struct i801_i2c_data i801_data;
+
 static int i801_setup(struct pci_dev *dev)
 {
int error_return = 0;
unsigned char temp;
 
/* Note: we keep on searching until we have found 'function 3' */
-   if(PCI_FUNC(dev->devfn) != 3)
+   if (PCI_FUNC(dev->devfn) != 3)
return -ENODEV;
 
I801_dev = dev;
@@ -136,7 +159,7 @@
} else {
pci_read_config_word(I801_dev, SMBBA, &i801_smba);
i801_smba &= 0xfff0;
-   if(i801_smba == 0) {
+   if (i801_smba == 0) {
dev_err(&dev->dev, "SMB base address uninitialized"
"- upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV;
@@ -180,12 +203,93 @@
return error_return;
 }
 
-static int i801_transaction(void)
+static void i801_check_hststs(struct i2c_adapter *adap,
+ struct i2c_op_q_entry *entry,
+ struct i801_i2c_data *d)
+{
+   if (d->hststs & 0x10) {
+   entry->result = -EIO;
+   dev_dbg(&I801_dev->dev,
+   "Error: Failed bus transaction\n");
+   } else if (d->hststs & 0x08) {
+   entry->result = -EIO;
+   dev_err(&I801_dev->dev, "Bus collision!\n");
+   /* Clock stops and slave is stuck in mid-transmission */
+   } else if (d->hststs & 0x04) {
+   entry->result = -EIO;
+   dev_dbg(&I801_dev->dev, "Error: no response!\n");
+   }
+}
+
+static void i801_finish(struct i2c_adapter *adap,
+   struct i2c_op_q_entry *entry,
+   struct i801_i2c_data *d)
+{
+   d->finished = 1;
+
+#ifdef HAVE_PEC
+   if (isich4 && d->hwpec) {
+   if (entry->smbus.size != I2C_SMBUS_QUICK &&
+  entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA)
+   outb_p(0, SMBAUXCTL);
+   }
+#endif
+
+   if (d->block || (entry->result < 0) ||
+  ((entry->smbus.read_write == I2C_SMBUS_WRITE)
+   || (d->xact == I801_QUICK)))
+   return;
+
+   switch (d->xact & 0x7f) {
+   case I801_BYTE: /* Result put in SMBHSTDAT0 */
+   case I801_BYTE_DATA:
+   entry->smbus.data->byte = inb_p(SMBHSTDAT0);
+   break;
+   case I801_WORD_DATA:
+   entry->smbus.data->word = inb_p(SMBHSTDAT0)
+   + (inb_p(SMBHSTDAT1) << 8);
+   break;
+   }
+}
+
+static void i801_transaction_final_check(struct i2c_adapter *adap,
+struct i2c_op_q

  1   2   3   4   5   6   7   >