Re: [Openipmi-developer] [PATCH] ipmi_si: Fix crash when using hard-coded device

2019-02-22 Thread Corey Minyard
On Fri, Feb 22, 2019 at 05:11:49PM +0800, Yang Yingliang wrote:
> Tested-by: Yang Yingliang 

Thanks for testing.

This is queued for 5.1.  I'd like to let the soak a bit in linux-next.
It is tagged for a backport to stable releases.

-corey

> 
> [  128.069528] ipmi_si: IPMI System Interface driver
> [  128.069556] ipmi_si dmi-ipmi-si.0: ipmi_platform: probing via SMBIOS
> [  128.069559] ipmi_platform: ipmi_si: SMBIOS: io 0xe4 regsize 1 spacing 1
> irq 0
> [  128.069561] ipmi_si: Adding SMBIOS-specified bt state machine
> [  128.069657] ipmi_si hisi-lpc-ipmi.1.auto: ipmi_platform: probing via ACPI
> [  128.069694] ipmi_si hisi-lpc-ipmi.1.auto: ipmi_platform: [io
> 0xffc0e3-0xffc0e7] regsize 1 spacing 1 irq 0
> [  128.069696] ipmi_si hisi-lpc-ipmi.1.auto: Hard-coded device at this
> address already exists
> [  128.069815] ipmi_si hardcode-ipmi-si.0: ipmi_platform: probing via
> hardcoded
> [  128.069817] ipmi_platform: ipmi_si: hardcoded: io 0xffc0e3 regsize 1
> spacing 1 irq 0
> [  128.069819] ipmi_si: Adding hardcoded-specified bt state machine
> [  128.069892] ipmi_si: Trying SMBIOS-specified bt state machine at i/o
> address 0xe4, slave address 0x0, irq 0
> [  128.069896] ipmi_si dmi-ipmi-si.0: Could not set up I/O space
> [  128.069900] ipmi_si: Trying hardcoded-specified bt state machine at i/o
> address 0xffc0e3, slave address 0x0, irq 0
> [  128.081782] ipmi_si hardcode-ipmi-si.0: bt cap response too short: 3
> [  128.081784] ipmi_si hardcode-ipmi-si.0: using default values
> [  128.081786] ipmi_si hardcode-ipmi-si.0: req2rsp=5 secs retries=2
> [  128.157855] ipmi_si hardcode-ipmi-si.0: IPMI message handler: Found new
> BMC (man_id: 0x0007db, prod_id: 0x0001, dev_id: 0x01)
> [  128.441860] ipmi_si hardcode-ipmi-si.0: IPMI bt interface initialized
> 
> On 2019/2/22 2:33, miny...@acm.org wrote:
> > From: Corey Minyard 
> > 
> > When excuting a command like:
> >modprobe ipmi_si ports=0xffc0e3 type=bt
> > The system would get an oops.
> > 
> > The trouble here is that ipmi_si_hardcode_find_bmc() is called before
> > ipmi_si_platform_init(), but initialization of the hard-coded device
> > creates an IPMI platform device, which won't be initialized yet.
> > 
> > The real trouble is that hard-coded devices aren't created with
> > any device, and the fixup is done later.  So do it right, create the
> > hard-coded devices as normal platform devices.
> > 
> > This required adding some new resource types to the IPMI platform
> > code for passing information required by the hard-coded device
> > and adding some code to remove the hard-coded platform devices
> > on module removal.
> > 
> > To enforce the "hard-coded devices passed by the user take priority
> > over firmware devices" rule, some special code was added to check
> > and see if a hard-coded device already exists.
> > 
> > Reported-by: Yang Yingliang 
> > Signed-off-by: Corey Minyard 
> > ---
> > 
> > I believe this is the right fix.  Can you test/review and send the
> > results?
> > 
> > Thanks,
> > 
> > -corey
> > 
> >   drivers/char/ipmi/ipmi_si.h  |   4 +-
> >   drivers/char/ipmi/ipmi_si_hardcode.c | 236 ---
> >   drivers/char/ipmi/ipmi_si_intf.c |  23 ++-
> >   drivers/char/ipmi/ipmi_si_platform.c |  25 ++-
> >   4 files changed, 214 insertions(+), 74 deletions(-)
> > 
> > diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h
> > index 52f6152d1fcb..7ae52c17618e 100644
> > --- a/drivers/char/ipmi/ipmi_si.h
> > +++ b/drivers/char/ipmi/ipmi_si.h
> > @@ -25,7 +25,9 @@ void ipmi_irq_finish_setup(struct si_sm_io *io);
> >   int ipmi_si_remove_by_dev(struct device *dev);
> >   void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
> > unsigned long addr);
> > -int ipmi_si_hardcode_find_bmc(void);
> > +void ipmi_hardcode_init(void);
> > +void ipmi_si_hardcode_exit(void);
> > +int ipmi_si_hardcode_match(int addr_type, unsigned long addr);
> >   void ipmi_si_platform_init(void);
> >   void ipmi_si_platform_shutdown(void);
> > diff --git a/drivers/char/ipmi/ipmi_si_hardcode.c 
> > b/drivers/char/ipmi/ipmi_si_hardcode.c
> > index 487642809c58..1e5783961b0d 100644
> > --- a/drivers/char/ipmi/ipmi_si_hardcode.c
> > +++ b/drivers/char/ipmi/ipmi_si_hardcode.c
> > @@ -3,6 +3,7 @@
> >   #define pr_fmt(fmt) "ipmi_hardcode: " fmt
> >   #include 
> > +#include 
> >   #include "ipmi_si.h"
> >   /*
> > @@ -12,23 +13,22 @@
> >   #define SI_MAX_PARMS 4
> > -static char  *si_type[SI_MAX_PARMS];
> >   #define MAX_SI_TYPE_STR 30
> > -static char  si_type_str[MAX_SI_TYPE_STR];
> > +static char  si_type_str[MAX_SI_TYPE_STR] __initdata;
> >   static unsigned long addrs[SI_MAX_PARMS];
> >   static unsigned int num_addrs;
> >   static unsigned int  ports[SI_MAX_PARMS];
> >   static unsigned int num_ports;
> > -static int   irqs[SI_MAX_PARMS];
> > -static unsigned int num_irqs;
> > -static int   regspacings[SI_MAX_PARMS];
> > -static unsigned int 

Re: [Openipmi-developer] [PATCH] ipmi_si: Fix crash when using hard-coded device

2019-02-22 Thread Yang Yingliang

Tested-by: Yang Yingliang 

[  128.069528] ipmi_si: IPMI System Interface driver
[  128.069556] ipmi_si dmi-ipmi-si.0: ipmi_platform: probing via SMBIOS
[  128.069559] ipmi_platform: ipmi_si: SMBIOS: io 0xe4 regsize 1 spacing 
1 irq 0

[  128.069561] ipmi_si: Adding SMBIOS-specified bt state machine
[  128.069657] ipmi_si hisi-lpc-ipmi.1.auto: ipmi_platform: probing via ACPI
[  128.069694] ipmi_si hisi-lpc-ipmi.1.auto: ipmi_platform: [io 
0xffc0e3-0xffc0e7] regsize 1 spacing 1 irq 0
[  128.069696] ipmi_si hisi-lpc-ipmi.1.auto: Hard-coded device at this 
address already exists
[  128.069815] ipmi_si hardcode-ipmi-si.0: ipmi_platform: probing via 
hardcoded
[  128.069817] ipmi_platform: ipmi_si: hardcoded: io 0xffc0e3 regsize 1 
spacing 1 irq 0

[  128.069819] ipmi_si: Adding hardcoded-specified bt state machine
[  128.069892] ipmi_si: Trying SMBIOS-specified bt state machine at i/o 
address 0xe4, slave address 0x0, irq 0

[  128.069896] ipmi_si dmi-ipmi-si.0: Could not set up I/O space
[  128.069900] ipmi_si: Trying hardcoded-specified bt state machine at 
i/o address 0xffc0e3, slave address 0x0, irq 0

[  128.081782] ipmi_si hardcode-ipmi-si.0: bt cap response too short: 3
[  128.081784] ipmi_si hardcode-ipmi-si.0: using default values
[  128.081786] ipmi_si hardcode-ipmi-si.0: req2rsp=5 secs retries=2
[  128.157855] ipmi_si hardcode-ipmi-si.0: IPMI message handler: Found 
new BMC (man_id: 0x0007db, prod_id: 0x0001, dev_id: 0x01)

[  128.441860] ipmi_si hardcode-ipmi-si.0: IPMI bt interface initialized

On 2019/2/22 2:33, miny...@acm.org wrote:

From: Corey Minyard 

When excuting a command like:
   modprobe ipmi_si ports=0xffc0e3 type=bt
The system would get an oops.

The trouble here is that ipmi_si_hardcode_find_bmc() is called before
ipmi_si_platform_init(), but initialization of the hard-coded device
creates an IPMI platform device, which won't be initialized yet.

The real trouble is that hard-coded devices aren't created with
any device, and the fixup is done later.  So do it right, create the
hard-coded devices as normal platform devices.

This required adding some new resource types to the IPMI platform
code for passing information required by the hard-coded device
and adding some code to remove the hard-coded platform devices
on module removal.

To enforce the "hard-coded devices passed by the user take priority
over firmware devices" rule, some special code was added to check
and see if a hard-coded device already exists.

Reported-by: Yang Yingliang 
Signed-off-by: Corey Minyard 
---

I believe this is the right fix.  Can you test/review and send the
results?

Thanks,

-corey

  drivers/char/ipmi/ipmi_si.h  |   4 +-
  drivers/char/ipmi/ipmi_si_hardcode.c | 236 ---
  drivers/char/ipmi/ipmi_si_intf.c |  23 ++-
  drivers/char/ipmi/ipmi_si_platform.c |  25 ++-
  4 files changed, 214 insertions(+), 74 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h
index 52f6152d1fcb..7ae52c17618e 100644
--- a/drivers/char/ipmi/ipmi_si.h
+++ b/drivers/char/ipmi/ipmi_si.h
@@ -25,7 +25,9 @@ void ipmi_irq_finish_setup(struct si_sm_io *io);
  int ipmi_si_remove_by_dev(struct device *dev);
  void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
unsigned long addr);
-int ipmi_si_hardcode_find_bmc(void);
+void ipmi_hardcode_init(void);
+void ipmi_si_hardcode_exit(void);
+int ipmi_si_hardcode_match(int addr_type, unsigned long addr);
  void ipmi_si_platform_init(void);
  void ipmi_si_platform_shutdown(void);
  
diff --git a/drivers/char/ipmi/ipmi_si_hardcode.c b/drivers/char/ipmi/ipmi_si_hardcode.c

index 487642809c58..1e5783961b0d 100644
--- a/drivers/char/ipmi/ipmi_si_hardcode.c
+++ b/drivers/char/ipmi/ipmi_si_hardcode.c
@@ -3,6 +3,7 @@
  #define pr_fmt(fmt) "ipmi_hardcode: " fmt
  
  #include 

+#include 
  #include "ipmi_si.h"
  
  /*

@@ -12,23 +13,22 @@
  
  #define SI_MAX_PARMS 4
  
-static char  *si_type[SI_MAX_PARMS];

  #define MAX_SI_TYPE_STR 30
-static char  si_type_str[MAX_SI_TYPE_STR];
+static char  si_type_str[MAX_SI_TYPE_STR] __initdata;
  static unsigned long addrs[SI_MAX_PARMS];
  static unsigned int num_addrs;
  static unsigned int  ports[SI_MAX_PARMS];
  static unsigned int num_ports;
-static int   irqs[SI_MAX_PARMS];
-static unsigned int num_irqs;
-static int   regspacings[SI_MAX_PARMS];
-static unsigned int num_regspacings;
-static int   regsizes[SI_MAX_PARMS];
-static unsigned int num_regsizes;
-static int   regshifts[SI_MAX_PARMS];
-static unsigned int num_regshifts;
-static int slave_addrs[SI_MAX_PARMS]; /* Leaving 0 chooses the default value */
-static unsigned int num_slave_addrs;
+static int   irqs[SI_MAX_PARMS] __initdata;
+static unsigned int num_irqs __initdata;
+static int   regspacings[SI_MAX_PARMS] __initdata;
+static unsigned int num_regspacings __initdata;
+static int   regsizes[SI_MAX_PARMS] 

[Openipmi-developer] [PATCH] ipmi_si: Fix crash when using hard-coded device

2019-02-21 Thread minyard
From: Corey Minyard 

When excuting a command like:
  modprobe ipmi_si ports=0xffc0e3 type=bt
The system would get an oops.

The trouble here is that ipmi_si_hardcode_find_bmc() is called before
ipmi_si_platform_init(), but initialization of the hard-coded device
creates an IPMI platform device, which won't be initialized yet.

The real trouble is that hard-coded devices aren't created with
any device, and the fixup is done later.  So do it right, create the
hard-coded devices as normal platform devices.

This required adding some new resource types to the IPMI platform
code for passing information required by the hard-coded device
and adding some code to remove the hard-coded platform devices
on module removal.

To enforce the "hard-coded devices passed by the user take priority
over firmware devices" rule, some special code was added to check
and see if a hard-coded device already exists.

Reported-by: Yang Yingliang 
Signed-off-by: Corey Minyard 
---

I believe this is the right fix.  Can you test/review and send the
results?

Thanks,

-corey

 drivers/char/ipmi/ipmi_si.h  |   4 +-
 drivers/char/ipmi/ipmi_si_hardcode.c | 236 ---
 drivers/char/ipmi/ipmi_si_intf.c |  23 ++-
 drivers/char/ipmi/ipmi_si_platform.c |  25 ++-
 4 files changed, 214 insertions(+), 74 deletions(-)

diff --git a/drivers/char/ipmi/ipmi_si.h b/drivers/char/ipmi/ipmi_si.h
index 52f6152d1fcb..7ae52c17618e 100644
--- a/drivers/char/ipmi/ipmi_si.h
+++ b/drivers/char/ipmi/ipmi_si.h
@@ -25,7 +25,9 @@ void ipmi_irq_finish_setup(struct si_sm_io *io);
 int ipmi_si_remove_by_dev(struct device *dev);
 void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
unsigned long addr);
-int ipmi_si_hardcode_find_bmc(void);
+void ipmi_hardcode_init(void);
+void ipmi_si_hardcode_exit(void);
+int ipmi_si_hardcode_match(int addr_type, unsigned long addr);
 void ipmi_si_platform_init(void);
 void ipmi_si_platform_shutdown(void);
 
diff --git a/drivers/char/ipmi/ipmi_si_hardcode.c 
b/drivers/char/ipmi/ipmi_si_hardcode.c
index 487642809c58..1e5783961b0d 100644
--- a/drivers/char/ipmi/ipmi_si_hardcode.c
+++ b/drivers/char/ipmi/ipmi_si_hardcode.c
@@ -3,6 +3,7 @@
 #define pr_fmt(fmt) "ipmi_hardcode: " fmt
 
 #include 
+#include 
 #include "ipmi_si.h"
 
 /*
@@ -12,23 +13,22 @@
 
 #define SI_MAX_PARMS 4
 
-static char  *si_type[SI_MAX_PARMS];
 #define MAX_SI_TYPE_STR 30
-static char  si_type_str[MAX_SI_TYPE_STR];
+static char  si_type_str[MAX_SI_TYPE_STR] __initdata;
 static unsigned long addrs[SI_MAX_PARMS];
 static unsigned int num_addrs;
 static unsigned int  ports[SI_MAX_PARMS];
 static unsigned int num_ports;
-static int   irqs[SI_MAX_PARMS];
-static unsigned int num_irqs;
-static int   regspacings[SI_MAX_PARMS];
-static unsigned int num_regspacings;
-static int   regsizes[SI_MAX_PARMS];
-static unsigned int num_regsizes;
-static int   regshifts[SI_MAX_PARMS];
-static unsigned int num_regshifts;
-static int slave_addrs[SI_MAX_PARMS]; /* Leaving 0 chooses the default value */
-static unsigned int num_slave_addrs;
+static int   irqs[SI_MAX_PARMS] __initdata;
+static unsigned int num_irqs __initdata;
+static int   regspacings[SI_MAX_PARMS] __initdata;
+static unsigned int num_regspacings __initdata;
+static int   regsizes[SI_MAX_PARMS] __initdata;
+static unsigned int num_regsizes __initdata;
+static int   regshifts[SI_MAX_PARMS] __initdata;
+static unsigned int num_regshifts __initdata;
+static int slave_addrs[SI_MAX_PARMS] __initdata;
+static unsigned int num_slave_addrs __initdata;
 
 module_param_string(type, si_type_str, MAX_SI_TYPE_STR, 0);
 MODULE_PARM_DESC(type, "Defines the type of each interface, each"
@@ -73,12 +73,133 @@ MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave 
address for"
 " overridden by this parm.  This is an array indexed"
 " by interface number.");
 
-int ipmi_si_hardcode_find_bmc(void)
+static struct platform_device *ipmi_hc_pdevs[SI_MAX_PARMS];
+
+static void __init ipmi_hardcode_init_one(const char *si_type_str,
+ unsigned int i,
+ unsigned long addr,
+ unsigned int flags)
 {
-   int ret = -ENODEV;
-   int i;
-   struct si_sm_io io;
+   struct platform_device *pdev;
+   unsigned int num_r = 1, size;
+   struct resource r[4];
+   struct property_entry p[6];
+   enum si_type si_type;
+   unsigned int regspacing, regsize;
+   int rv;
+
+   memset(p, 0, sizeof(p));
+   memset(r, 0, sizeof(r));
+
+   if (!si_type_str || !*si_type_str || strcmp(si_type_str, "kcs") == 0) {
+   size = 2;
+   si_type = SI_KCS;
+   } else if (strcmp(si_type_str, "smic") == 0) {
+   size = 2;
+   si_type = SI_SMIC;
+   }