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

Commit 0eb00613 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-4.18' of git://github.com/cminyard/linux-ipmi

Pull IPMI updates from Corey Minyard:
 "It's been a busy release for the IPMI driver. Some notable changes:

   - A user was running into timeout issues doing maintenance commands
     over the IPMB network behind an IPMI controller.

     Extend the maintenance mode concept to messages over IPMB and allow
     the timeouts to be tuned.

   - Lots of cleanup, style fixing, some bugfixes, and such.

   - At least one user was having trouble with the way the IPMI driver
     would lock the i2c driver module it used.

     The IPMI driver was not designed for hotplug. However, hotplug is a
     reality now, so the IPMI driver was modified to support hotplug.

   - The proc interface code is now completely removed. Long live sysfs!"

* tag 'for-linus-4.18' of git://github.com/cminyard/linux-ipmi: (35 commits)
  ipmi: Properly release srcu locks on error conditions
  ipmi: NPCM7xx KCS BMC: enable interrupt to the host
  ipmi:bt: Set the timeout before doing a capabilities check
  ipmi: Remove the proc interface
  ipmi_ssif: Fix uninitialized variable issue
  ipmi: add an NPCM7xx KCS BMC driver
  ipmi_si: Clean up shutdown a bit
  ipmi_si: Rename intf_num to si_num
  ipmi: Remove smi->intf checks
  ipmi_ssif: Get rid of unused intf_num
  ipmi: Get rid of ipmi_user_t and ipmi_smi_t in include files
  ipmi: ipmi_unregister_smi() cannot fail, have it return void
  ipmi_devintf: Add an error return on invalid ioctls
  ipmi: Remove usecount function from interfaces
  ipmi_ssif: Remove usecount handling
  ipmi: Remove condition on interface shutdown
  ipmi_ssif: Convert over to a shutdown handler
  ipmi_si: Convert over to a shutdown handler
  ipmi: Rework locking and shutdown for hot remove
  ipmi: Fix some counter issues
  ...
parents 84504930 048f7c3e
Loading
Loading
Loading
Loading
+39 −0
Original line number Original line Diff line number Diff line
* Nuvoton NPCM7xx KCS (Keyboard Controller Style) IPMI interface

The Nuvoton SOCs (NPCM7xx) are commonly used as BMCs
(Baseboard Management Controllers) and the KCS interface can be
used to perform in-band IPMI communication with their host.

Required properties:
- compatible : should be one of
    "nuvoton,npcm750-kcs-bmc"
- interrupts : interrupt generated by the controller
- kcs_chan : The KCS channel number in the controller

Example:

    lpc_kcs: lpc_kcs@f0007000 {
        compatible = "nuvoton,npcm750-lpc-kcs", "simple-mfd", "syscon";
        reg = <0xf0007000 0x40>;
        reg-io-width = <1>;

        #address-cells = <1>;
        #size-cells = <1>;
        ranges = <0x0 0xf0007000 0x40>;

        kcs1: kcs1@0 {
            compatible = "nuvoton,npcm750-kcs-bmc";
            reg = <0x0 0x40>;
            interrupts = <0 9 4>;
            kcs_chan = <1>;
            status = "disabled";
        };

        kcs2: kcs2@0 {
            compatible = "nuvoton,npcm750-kcs-bmc";
            reg = <0x0 0x40>;
            interrupts = <0 9 4>;
            kcs_chan = <2>;
            status = "disabled";
        };
    };
 No newline at end of file
+15 −8
Original line number Original line Diff line number Diff line
@@ -22,14 +22,6 @@ config IPMI_DMI_DECODE


if IPMI_HANDLER
if IPMI_HANDLER


config IPMI_PROC_INTERFACE
       bool 'Provide an interface for IPMI stats in /proc (deprecated)'
       depends on PROC_FS
       default y
       help
         Do not use this any more, use sysfs for this info.  It will be
	 removed in future kernel versions.

config IPMI_PANIC_EVENT
config IPMI_PANIC_EVENT
       bool 'Generate a panic event to all BMCs on a panic'
       bool 'Generate a panic event to all BMCs on a panic'
       help
       help
@@ -111,6 +103,21 @@ config ASPEED_KCS_IPMI_BMC
	  The driver implements the BMC side of the KCS contorller, it
	  The driver implements the BMC side of the KCS contorller, it
	  provides the access of KCS IO space for BMC side.
	  provides the access of KCS IO space for BMC side.


config NPCM7XX_KCS_IPMI_BMC
	depends on ARCH_NPCM7XX || COMPILE_TEST
	select IPMI_KCS_BMC
	select REGMAP_MMIO
	tristate "NPCM7xx KCS IPMI BMC driver"
	help
	  Provides a driver for the KCS (Keyboard Controller Style) IPMI
	  interface found on Nuvoton NPCM7xx SOCs.

	  The driver implements the BMC side of the KCS contorller, it
	  provides the access of KCS IO space for BMC side.

	  This support is also available as a module.  If so, the module
	  will be called kcs_bmc_npcm7xx.

config ASPEED_BT_IPMI_BMC
config ASPEED_BT_IPMI_BMC
	depends on ARCH_ASPEED || COMPILE_TEST
	depends on ARCH_ASPEED || COMPILE_TEST
       depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
       depends on REGMAP && REGMAP_MMIO && MFD_SYSCON
+1 −0
Original line number Original line Diff line number Diff line
@@ -24,3 +24,4 @@ obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o
obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o
obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o
+2 −1
Original line number Original line Diff line number Diff line
@@ -504,11 +504,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
		if (status & BT_H_BUSY)		/* clear a leftover H_BUSY */
		if (status & BT_H_BUSY)		/* clear a leftover H_BUSY */
			BT_CONTROL(BT_H_BUSY);
			BT_CONTROL(BT_H_BUSY);


		bt->timeout = bt->BT_CAP_req2rsp;

		/* Read BT capabilities if it hasn't been done yet */
		/* Read BT capabilities if it hasn't been done yet */
		if (!bt->BT_CAP_outreqs)
		if (!bt->BT_CAP_outreqs)
			BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN,
			BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN,
					SI_SM_CALL_WITHOUT_DELAY);
					SI_SM_CALL_WITHOUT_DELAY);
		bt->timeout = bt->BT_CAP_req2rsp;
		BT_SI_SM_RETURN(SI_SM_IDLE);
		BT_SI_SM_RETURN(SI_SM_IDLE);


	case BT_STATE_XACTION_START:
	case BT_STATE_XACTION_START:
+51 −78
Original line number Original line Diff line number Diff line
@@ -26,7 +26,7 @@


struct ipmi_file_private
struct ipmi_file_private
{
{
	ipmi_user_t          user;
	struct ipmi_user     *user;
	spinlock_t           recv_msg_lock;
	spinlock_t           recv_msg_lock;
	struct list_head     recv_msgs;
	struct list_head     recv_msgs;
	struct file          *file;
	struct file          *file;
@@ -37,7 +37,6 @@ struct ipmi_file_private
	unsigned int         default_retry_time_ms;
	unsigned int         default_retry_time_ms;
};
};


static DEFINE_MUTEX(ipmi_mutex);
static void file_receive_handler(struct ipmi_recv_msg *msg,
static void file_receive_handler(struct ipmi_recv_msg *msg,
				 void                 *handler_data)
				 void                 *handler_data)
{
{
@@ -45,17 +44,15 @@ static void file_receive_handler(struct ipmi_recv_msg *msg,
	int                      was_empty;
	int                      was_empty;
	unsigned long            flags;
	unsigned long            flags;


	spin_lock_irqsave(&(priv->recv_msg_lock), flags);
	spin_lock_irqsave(&priv->recv_msg_lock, flags);

	was_empty = list_empty(&priv->recv_msgs);
	was_empty = list_empty(&(priv->recv_msgs));
	list_add_tail(&msg->link, &priv->recv_msgs);
	list_add_tail(&(msg->link), &(priv->recv_msgs));
	spin_unlock_irqrestore(&priv->recv_msg_lock, flags);


	if (was_empty) {
	if (was_empty) {
		wake_up_interruptible(&priv->wait);
		wake_up_interruptible(&priv->wait);
		kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
		kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
	}
	}

	spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
}
}


static __poll_t ipmi_poll(struct file *file, poll_table *wait)
static __poll_t ipmi_poll(struct file *file, poll_table *wait)
@@ -68,7 +65,7 @@ static __poll_t ipmi_poll(struct file *file, poll_table *wait)


	spin_lock_irqsave(&priv->recv_msg_lock, flags);
	spin_lock_irqsave(&priv->recv_msg_lock, flags);


	if (!list_empty(&(priv->recv_msgs)))
	if (!list_empty(&priv->recv_msgs))
		mask |= (EPOLLIN | EPOLLRDNORM);
		mask |= (EPOLLIN | EPOLLRDNORM);


	spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
	spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
@@ -79,13 +76,8 @@ static __poll_t ipmi_poll(struct file *file, poll_table *wait)
static int ipmi_fasync(int fd, struct file *file, int on)
static int ipmi_fasync(int fd, struct file *file, int on)
{
{
	struct ipmi_file_private *priv = file->private_data;
	struct ipmi_file_private *priv = file->private_data;
	int                      result;

	mutex_lock(&ipmi_mutex); /* could race against open() otherwise */
	result = fasync_helper(fd, file, on, &priv->fasync_queue);
	mutex_unlock(&ipmi_mutex);


	return (result);
	return fasync_helper(fd, file, on, &priv->fasync_queue);
}
}


static const struct ipmi_user_hndl ipmi_hndlrs =
static const struct ipmi_user_hndl ipmi_hndlrs =
@@ -99,18 +91,16 @@ static int ipmi_open(struct inode *inode, struct file *file)
	int                      rv;
	int                      rv;
	struct ipmi_file_private *priv;
	struct ipmi_file_private *priv;



	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
	if (!priv)
		return -ENOMEM;
		return -ENOMEM;


	mutex_lock(&ipmi_mutex);
	priv->file = file;
	priv->file = file;


	rv = ipmi_create_user(if_num,
	rv = ipmi_create_user(if_num,
			      &ipmi_hndlrs,
			      &ipmi_hndlrs,
			      priv,
			      priv,
			      &(priv->user));
			      &priv->user);
	if (rv) {
	if (rv) {
		kfree(priv);
		kfree(priv);
		goto out;
		goto out;
@@ -118,8 +108,8 @@ static int ipmi_open(struct inode *inode, struct file *file)


	file->private_data = priv;
	file->private_data = priv;


	spin_lock_init(&(priv->recv_msg_lock));
	spin_lock_init(&priv->recv_msg_lock);
	INIT_LIST_HEAD(&(priv->recv_msgs));
	INIT_LIST_HEAD(&priv->recv_msgs);
	init_waitqueue_head(&priv->wait);
	init_waitqueue_head(&priv->wait);
	priv->fasync_queue = NULL;
	priv->fasync_queue = NULL;
	mutex_init(&priv->recv_mutex);
	mutex_init(&priv->recv_mutex);
@@ -129,7 +119,6 @@ static int ipmi_open(struct inode *inode, struct file *file)
	priv->default_retry_time_ms = 0;
	priv->default_retry_time_ms = 0;


out:
out:
	mutex_unlock(&ipmi_mutex);
	return rv;
	return rv;
}
}


@@ -146,13 +135,12 @@ static int ipmi_release(struct inode *inode, struct file *file)
	list_for_each_entry_safe(msg, next, &priv->recv_msgs, link)
	list_for_each_entry_safe(msg, next, &priv->recv_msgs, link)
		ipmi_free_recv_msg(msg);
		ipmi_free_recv_msg(msg);



	kfree(priv);
	kfree(priv);


	return 0;
	return 0;
}
}


static int handle_send_req(ipmi_user_t     user,
static int handle_send_req(struct ipmi_user *user,
			   struct ipmi_req *req,
			   struct ipmi_req *req,
			   int             retries,
			   int             retries,
			   unsigned int    retry_time_ms)
			   unsigned int    retry_time_ms)
@@ -189,8 +177,7 @@ static int handle_send_req(ipmi_user_t user,


		if (copy_from_user(msg.data,
		if (copy_from_user(msg.data,
				   req->msg.data,
				   req->msg.data,
				   req->msg.data_len))
				   req->msg.data_len)) {
		{
			rv = -EFAULT;
			rv = -EFAULT;
			goto out;
			goto out;
		}
		}
@@ -233,25 +220,24 @@ static int handle_recv(struct ipmi_file_private *priv,
	mutex_lock(&priv->recv_mutex);
	mutex_lock(&priv->recv_mutex);


	/* Grab the message off the list. */
	/* Grab the message off the list. */
	spin_lock_irqsave(&(priv->recv_msg_lock), flags);
	spin_lock_irqsave(&priv->recv_msg_lock, flags);
	if (list_empty(&(priv->recv_msgs))) {
	if (list_empty(&(priv->recv_msgs))) {
		spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
		spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
		rv = -EAGAIN;
		rv = -EAGAIN;
		goto recv_err;
		goto recv_err;
	}
	}
	entry = priv->recv_msgs.next;
	entry = priv->recv_msgs.next;
	msg = list_entry(entry, struct ipmi_recv_msg, link);
	msg = list_entry(entry, struct ipmi_recv_msg, link);
	list_del(entry);
	list_del(entry);
	spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
	spin_unlock_irqrestore(&priv->recv_msg_lock, flags);


	addr_len = ipmi_addr_length(msg->addr.addr_type);
	addr_len = ipmi_addr_length(msg->addr.addr_type);
	if (rsp->addr_len < addr_len)
	if (rsp->addr_len < addr_len) {
	{
		rv = -EINVAL;
		rv = -EINVAL;
		goto recv_putback_on_err;
		goto recv_putback_on_err;
	}
	}


	if (copy_to_user(rsp->addr, &(msg->addr), addr_len)) {
	if (copy_to_user(rsp->addr, &msg->addr, addr_len)) {
		rv = -EFAULT;
		rv = -EFAULT;
		goto recv_putback_on_err;
		goto recv_putback_on_err;
	}
	}
@@ -273,8 +259,7 @@ static int handle_recv(struct ipmi_file_private *priv,


		if (copy_to_user(rsp->msg.data,
		if (copy_to_user(rsp->msg.data,
				 msg->msg.data,
				 msg->msg.data,
				 msg->msg.data_len))
				 msg->msg.data_len)) {
		{
			rv = -EFAULT;
			rv = -EFAULT;
			goto recv_putback_on_err;
			goto recv_putback_on_err;
		}
		}
@@ -294,9 +279,9 @@ static int handle_recv(struct ipmi_file_private *priv,
recv_putback_on_err:
recv_putback_on_err:
	/* If we got an error, put the message back onto
	/* If we got an error, put the message back onto
	   the head of the queue. */
	   the head of the queue. */
	spin_lock_irqsave(&(priv->recv_msg_lock), flags);
	spin_lock_irqsave(&priv->recv_msg_lock, flags);
	list_add(entry, &(priv->recv_msgs));
	list_add(entry, &priv->recv_msgs);
	spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
	spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
recv_err:
recv_err:
	mutex_unlock(&priv->recv_mutex);
	mutex_unlock(&priv->recv_mutex);
	return rv;
	return rv;
@@ -307,7 +292,7 @@ static int copyout_recv(struct ipmi_recv *rsp, void __user *to)
	return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0;
	return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0;
}
}


static int ipmi_ioctl(struct file   *file,
static long ipmi_ioctl(struct file   *file,
		       unsigned int  cmd,
		       unsigned int  cmd,
		       unsigned long data)
		       unsigned long data)
{
{
@@ -320,16 +305,20 @@ static int ipmi_ioctl(struct file *file,
	case IPMICTL_SEND_COMMAND:
	case IPMICTL_SEND_COMMAND:
	{
	{
		struct ipmi_req req;
		struct ipmi_req req;
		int retries;
		unsigned int retry_time_ms;


		if (copy_from_user(&req, arg, sizeof(req))) {
		if (copy_from_user(&req, arg, sizeof(req))) {
			rv = -EFAULT;
			rv = -EFAULT;
			break;
			break;
		}
		}


		rv = handle_send_req(priv->user,
		mutex_lock(&priv->recv_mutex);
				     &req,
		retries = priv->default_retries;
				     priv->default_retries,
		retry_time_ms = priv->default_retry_time_ms;
				     priv->default_retry_time_ms);
		mutex_unlock(&priv->recv_mutex);

		rv = handle_send_req(priv->user, &req, retries, retry_time_ms);
		break;
		break;
	}
	}


@@ -569,8 +558,10 @@ static int ipmi_ioctl(struct file *file,
			break;
			break;
		}
		}


		mutex_lock(&priv->recv_mutex);
		priv->default_retries = parms.retries;
		priv->default_retries = parms.retries;
		priv->default_retry_time_ms = parms.retry_time_ms;
		priv->default_retry_time_ms = parms.retry_time_ms;
		mutex_unlock(&priv->recv_mutex);
		rv = 0;
		rv = 0;
		break;
		break;
	}
	}
@@ -579,8 +570,10 @@ static int ipmi_ioctl(struct file *file,
	{
	{
		struct ipmi_timing_parms parms;
		struct ipmi_timing_parms parms;


		mutex_lock(&priv->recv_mutex);
		parms.retries = priv->default_retries;
		parms.retries = priv->default_retries;
		parms.retry_time_ms = priv->default_retry_time_ms;
		parms.retry_time_ms = priv->default_retry_time_ms;
		mutex_unlock(&priv->recv_mutex);


		if (copy_to_user(arg, &parms, sizeof(parms))) {
		if (copy_to_user(arg, &parms, sizeof(parms))) {
			rv = -EFAULT;
			rv = -EFAULT;
@@ -615,30 +608,16 @@ static int ipmi_ioctl(struct file *file,
		rv = ipmi_set_maintenance_mode(priv->user, mode);
		rv = ipmi_set_maintenance_mode(priv->user, mode);
		break;
		break;
	}
	}
	}


	return rv;
	default:
		rv = -ENOTTY;
		break;
	}
	}
  
  
/*
	return rv;
 * Note: it doesn't make sense to take the BKL here but
 *       not in compat_ipmi_ioctl. -arnd
 */
static long ipmi_unlocked_ioctl(struct file   *file,
			        unsigned int  cmd,
			        unsigned long data)
{
	int ret;

	mutex_lock(&ipmi_mutex);
	ret = ipmi_ioctl(file, cmd, data);
	mutex_unlock(&ipmi_mutex);

	return ret;
}
}


#ifdef CONFIG_COMPAT
#ifdef CONFIG_COMPAT

/*
/*
 * The following code contains code for supporting 32-bit compatible
 * The following code contains code for supporting 32-bit compatible
 * ioctls on 64-bit kernels.  This allows running 32-bit apps on the
 * ioctls on 64-bit kernels.  This allows running 32-bit apps on the
@@ -749,15 +728,21 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
	{
	{
		struct ipmi_req	rp;
		struct ipmi_req	rp;
		struct compat_ipmi_req r32;
		struct compat_ipmi_req r32;
		int retries;
		unsigned int retry_time_ms;


		if (copy_from_user(&r32, compat_ptr(arg), sizeof(r32)))
		if (copy_from_user(&r32, compat_ptr(arg), sizeof(r32)))
			return -EFAULT;
			return -EFAULT;


		get_compat_ipmi_req(&rp, &r32);
		get_compat_ipmi_req(&rp, &r32);


		mutex_lock(&priv->recv_mutex);
		retries = priv->default_retries;
		retry_time_ms = priv->default_retry_time_ms;
		mutex_unlock(&priv->recv_mutex);

		return handle_send_req(priv->user, &rp,
		return handle_send_req(priv->user, &rp,
				priv->default_retries,
				       retries, retry_time_ms);
				priv->default_retry_time_ms);
	}
	}
	case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
	case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
	{
	{
@@ -791,25 +776,13 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
		return ipmi_ioctl(filep, cmd, arg);
		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
#endif


static const struct file_operations ipmi_fops = {
static const struct file_operations ipmi_fops = {
	.owner		= THIS_MODULE,
	.owner		= THIS_MODULE,
	.unlocked_ioctl	= ipmi_unlocked_ioctl,
	.unlocked_ioctl	= ipmi_ioctl,
#ifdef CONFIG_COMPAT
#ifdef CONFIG_COMPAT
	.compat_ioctl   = unlocked_compat_ipmi_ioctl,
	.compat_ioctl   = compat_ipmi_ioctl,
#endif
#endif
	.open		= ipmi_open,
	.open		= ipmi_open,
	.release	= ipmi_release,
	.release	= ipmi_release,
Loading