ipmi: Break up i_ipmi_request
authorCorey Minyard <cminyard@mvista.com>
Thu, 5 Apr 2018 17:10:16 +0000 (12:10 -0500)
committerCorey Minyard <cminyard@mvista.com>
Wed, 18 Apr 2018 15:22:51 +0000 (10:22 -0500)
It was huge, and easily broken into pieces.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
drivers/char/ipmi/ipmi_msghandler.c

index a4c3336cec0645b3299c6b2f5c60ebd07ea3e581..e26e5b6900ee3d62ad70fd76a4d0230953db2a05 100644 (file)
@@ -1703,6 +1703,332 @@ static bool is_maintenance_mode_cmd(struct kernel_ipmi_msg *msg)
                || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST));
 }
 
+static int i_ipmi_req_sysintf(ipmi_smi_t             intf,
+                             struct ipmi_addr       *addr,
+                             long                   msgid,
+                             struct kernel_ipmi_msg *msg,
+                             struct ipmi_smi_msg    *smi_msg,
+                             struct ipmi_recv_msg   *recv_msg,
+                             int                    retries,
+                             unsigned int           retry_time_ms)
+{
+       struct ipmi_system_interface_addr *smi_addr;
+
+       if (msg->netfn & 1)
+               /* Responses are not allowed to the SMI. */
+               return -EINVAL;
+
+       smi_addr = (struct ipmi_system_interface_addr *) addr;
+       if (smi_addr->lun > 3) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       memcpy(&recv_msg->addr, smi_addr, sizeof(*smi_addr));
+
+       if ((msg->netfn == IPMI_NETFN_APP_REQUEST)
+           && ((msg->cmd == IPMI_SEND_MSG_CMD)
+               || (msg->cmd == IPMI_GET_MSG_CMD)
+               || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD))) {
+               /*
+                * We don't let the user do these, since we manage
+                * the sequence numbers.
+                */
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       if (is_maintenance_mode_cmd(msg)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
+               intf->auto_maintenance_timeout
+                       = maintenance_mode_timeout_ms;
+               if (!intf->maintenance_mode
+                   && !intf->maintenance_mode_enable) {
+                       intf->maintenance_mode_enable = true;
+                       maintenance_mode_update(intf);
+               }
+               spin_unlock_irqrestore(&intf->maintenance_mode_lock,
+                                      flags);
+       }
+
+       if (msg->data_len + 2 > IPMI_MAX_MSG_LENGTH) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EMSGSIZE;
+       }
+
+       smi_msg->data[0] = (msg->netfn << 2) | (smi_addr->lun & 0x3);
+       smi_msg->data[1] = msg->cmd;
+       smi_msg->msgid = msgid;
+       smi_msg->user_data = recv_msg;
+       if (msg->data_len > 0)
+               memcpy(&smi_msg->data[2], msg->data, msg->data_len);
+       smi_msg->data_size = msg->data_len + 2;
+       ipmi_inc_stat(intf, sent_local_commands);
+
+       return 0;
+}
+
+static int i_ipmi_req_ipmb(ipmi_smi_t             intf,
+                          struct ipmi_addr       *addr,
+                          long                   msgid,
+                          struct kernel_ipmi_msg *msg,
+                          struct ipmi_smi_msg    *smi_msg,
+                          struct ipmi_recv_msg   *recv_msg,
+                          unsigned char          source_address,
+                          unsigned char          source_lun,
+                          int                    retries,
+                          unsigned int           retry_time_ms)
+{
+       struct ipmi_ipmb_addr *ipmb_addr;
+       unsigned char ipmb_seq;
+       long seqid;
+       int broadcast = 0;
+       struct ipmi_channel *chans;
+       int rv = 0;
+
+       if (addr->channel >= IPMI_MAX_CHANNELS) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       chans = READ_ONCE(intf->channel_list)->c;
+
+       if (chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_IPMB) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
+               /*
+                * Broadcasts add a zero at the beginning of the
+                * message, but otherwise is the same as an IPMB
+                * address.
+                */
+               addr->addr_type = IPMI_IPMB_ADDR_TYPE;
+               broadcast = 1;
+               retries = 0; /* Don't retry broadcasts. */
+       }
+
+       /*
+        * 9 for the header and 1 for the checksum, plus
+        * possibly one for the broadcast.
+        */
+       if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EMSGSIZE;
+       }
+
+       ipmb_addr = (struct ipmi_ipmb_addr *) addr;
+       if (ipmb_addr->lun > 3) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr));
+
+       if (recv_msg->msg.netfn & 0x1) {
+               /*
+                * It's a response, so use the user's sequence
+                * from msgid.
+                */
+               ipmi_inc_stat(intf, sent_ipmb_responses);
+               format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
+                               msgid, broadcast,
+                               source_address, source_lun);
+
+               /*
+                * Save the receive message so we can use it
+                * to deliver the response.
+                */
+               smi_msg->user_data = recv_msg;
+       } else {
+               /* It's a command, so get a sequence for it. */
+               unsigned long flags;
+
+               spin_lock_irqsave(&intf->seq_lock, flags);
+
+               if (is_maintenance_mode_cmd(msg))
+                       intf->ipmb_maintenance_mode_timeout =
+                               maintenance_mode_timeout_ms;
+
+               if (intf->ipmb_maintenance_mode_timeout && retry_time_ms == 0)
+                       /* Different default in maintenance mode */
+                       retry_time_ms = default_maintenance_retry_ms;
+
+               /*
+                * Create a sequence number with a 1 second
+                * timeout and 4 retries.
+                */
+               rv = intf_next_seq(intf,
+                                  recv_msg,
+                                  retry_time_ms,
+                                  retries,
+                                  broadcast,
+                                  &ipmb_seq,
+                                  &seqid);
+               if (rv)
+                       /*
+                        * We have used up all the sequence numbers,
+                        * probably, so abort.
+                        */
+                       goto out_err;
+
+               ipmi_inc_stat(intf, sent_ipmb_commands);
+
+               /*
+                * Store the sequence number in the message,
+                * so that when the send message response
+                * comes back we can start the timer.
+                */
+               format_ipmb_msg(smi_msg, msg, ipmb_addr,
+                               STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
+                               ipmb_seq, broadcast,
+                               source_address, source_lun);
+
+               /*
+                * Copy the message into the recv message data, so we
+                * can retransmit it later if necessary.
+                */
+               memcpy(recv_msg->msg_data, smi_msg->data,
+                      smi_msg->data_size);
+               recv_msg->msg.data = recv_msg->msg_data;
+               recv_msg->msg.data_len = smi_msg->data_size;
+
+               /*
+                * We don't unlock until here, because we need
+                * to copy the completed message into the
+                * recv_msg before we release the lock.
+                * Otherwise, race conditions may bite us.  I
+                * know that's pretty paranoid, but I prefer
+                * to be correct.
+                */
+out_err:
+               spin_unlock_irqrestore(&intf->seq_lock, flags);
+       }
+
+       return rv;
+}
+
+static int i_ipmi_req_lan(ipmi_smi_t             intf,
+                         struct ipmi_addr       *addr,
+                         long                   msgid,
+                         struct kernel_ipmi_msg *msg,
+                         struct ipmi_smi_msg    *smi_msg,
+                         struct ipmi_recv_msg   *recv_msg,
+                         unsigned char          source_lun,
+                         int                    retries,
+                         unsigned int           retry_time_ms)
+{
+       struct ipmi_lan_addr  *lan_addr;
+       unsigned char ipmb_seq;
+       long seqid;
+       struct ipmi_channel *chans;
+       int rv = 0;
+
+       if (addr->channel >= IPMI_MAX_CHANNELS) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       chans = READ_ONCE(intf->channel_list)->c;
+
+       if ((chans[addr->channel].medium
+                               != IPMI_CHANNEL_MEDIUM_8023LAN)
+                       && (chans[addr->channel].medium
+                           != IPMI_CHANNEL_MEDIUM_ASYNC)) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       /* 11 for the header and 1 for the checksum. */
+       if ((msg->data_len + 12) > IPMI_MAX_MSG_LENGTH) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EMSGSIZE;
+       }
+
+       lan_addr = (struct ipmi_lan_addr *) addr;
+       if (lan_addr->lun > 3) {
+               ipmi_inc_stat(intf, sent_invalid_commands);
+               return -EINVAL;
+       }
+
+       memcpy(&recv_msg->addr, lan_addr, sizeof(*lan_addr));
+
+       if (recv_msg->msg.netfn & 0x1) {
+               /*
+                * It's a response, so use the user's sequence
+                * from msgid.
+                */
+               ipmi_inc_stat(intf, sent_lan_responses);
+               format_lan_msg(smi_msg, msg, lan_addr, msgid,
+                              msgid, source_lun);
+
+               /*
+                * Save the receive message so we can use it
+                * to deliver the response.
+                */
+               smi_msg->user_data = recv_msg;
+       } else {
+               /* It's a command, so get a sequence for it. */
+               unsigned long flags;
+
+               spin_lock_irqsave(&intf->seq_lock, flags);
+
+               /*
+                * Create a sequence number with a 1 second
+                * timeout and 4 retries.
+                */
+               rv = intf_next_seq(intf,
+                                  recv_msg,
+                                  retry_time_ms,
+                                  retries,
+                                  0,
+                                  &ipmb_seq,
+                                  &seqid);
+               if (rv)
+                       /*
+                        * We have used up all the sequence numbers,
+                        * probably, so abort.
+                        */
+                       goto out_err;
+
+               ipmi_inc_stat(intf, sent_lan_commands);
+
+               /*
+                * Store the sequence number in the message,
+                * so that when the send message response
+                * comes back we can start the timer.
+                */
+               format_lan_msg(smi_msg, msg, lan_addr,
+                              STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
+                              ipmb_seq, source_lun);
+
+               /*
+                * Copy the message into the recv message data, so we
+                * can retransmit it later if necessary.
+                */
+               memcpy(recv_msg->msg_data, smi_msg->data,
+                      smi_msg->data_size);
+               recv_msg->msg.data = recv_msg->msg_data;
+               recv_msg->msg.data_len = smi_msg->data_size;
+
+               /*
+                * We don't unlock until here, because we need
+                * to copy the completed message into the
+                * recv_msg before we release the lock.
+                * Otherwise, race conditions may bite us.  I
+                * know that's pretty paranoid, but I prefer
+                * to be correct.
+                */
+out_err:
+               spin_unlock_irqrestore(&intf->seq_lock, flags);
+       }
+
+       return rv;
+}
+
 /*
  * Separate from ipmi_request so that the user does not have to be
  * supplied in certain circumstances (mainly at panic time).  If
@@ -1723,11 +2049,9 @@ static int i_ipmi_request(ipmi_user_t          user,
                          int                  retries,
                          unsigned int         retry_time_ms)
 {
-       int                      rv = 0;
-       struct ipmi_smi_msg      *smi_msg;
-       struct ipmi_recv_msg     *recv_msg;
-       unsigned long            flags;
-
+       struct ipmi_smi_msg *smi_msg;
+       struct ipmi_recv_msg *recv_msg;
+       int rv = 0;
 
        if (supplied_recv)
                recv_msg = supplied_recv;
@@ -1765,322 +2089,32 @@ static int i_ipmi_request(ipmi_user_t          user,
        recv_msg->msg = *msg;
 
        if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
-               struct ipmi_system_interface_addr *smi_addr;
-
-               if (msg->netfn & 1) {
-                       /* Responses are not allowed to the SMI. */
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               smi_addr = (struct ipmi_system_interface_addr *) addr;
-               if (smi_addr->lun > 3) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               memcpy(&recv_msg->addr, smi_addr, sizeof(*smi_addr));
-
-               if ((msg->netfn == IPMI_NETFN_APP_REQUEST)
-                   && ((msg->cmd == IPMI_SEND_MSG_CMD)
-                       || (msg->cmd == IPMI_GET_MSG_CMD)
-                       || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD))) {
-                       /*
-                        * We don't let the user do these, since we manage
-                        * the sequence numbers.
-                        */
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               if (is_maintenance_mode_cmd(msg)) {
-                       spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
-                       intf->auto_maintenance_timeout
-                               = maintenance_mode_timeout_ms;
-                       if (!intf->maintenance_mode
-                           && !intf->maintenance_mode_enable) {
-                               intf->maintenance_mode_enable = true;
-                               maintenance_mode_update(intf);
-                       }
-                       spin_unlock_irqrestore(&intf->maintenance_mode_lock,
-                                              flags);
-               }
-
-               if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EMSGSIZE;
-                       goto out_err;
-               }
-
-               smi_msg->data[0] = (msg->netfn << 2) | (smi_addr->lun & 0x3);
-               smi_msg->data[1] = msg->cmd;
-               smi_msg->msgid = msgid;
-               smi_msg->user_data = recv_msg;
-               if (msg->data_len > 0)
-                       memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
-               smi_msg->data_size = msg->data_len + 2;
-               ipmi_inc_stat(intf, sent_local_commands);
+               rv = i_ipmi_req_sysintf(intf, addr, msgid, msg, smi_msg,
+                                       recv_msg, retries, retry_time_ms);
        } else if (is_ipmb_addr(addr) || is_ipmb_bcast_addr(addr)) {
-               struct ipmi_ipmb_addr *ipmb_addr;
-               unsigned char         ipmb_seq;
-               long                  seqid;
-               int                   broadcast = 0;
-               struct ipmi_channel   *chans;
-
-               if (addr->channel >= IPMI_MAX_CHANNELS) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               chans = READ_ONCE(intf->channel_list)->c;
-
-               if (chans[addr->channel].medium != IPMI_CHANNEL_MEDIUM_IPMB) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
-                       /*
-                        * Broadcasts add a zero at the beginning of the
-                        * message, but otherwise is the same as an IPMB
-                        * address.
-                        */
-                       addr->addr_type = IPMI_IPMB_ADDR_TYPE;
-                       broadcast = 1;
-                       retries = 0; /* Don't retry broadcasts. */
-               }
-
-               /*
-                * 9 for the header and 1 for the checksum, plus
-                * possibly one for the broadcast.
-                */
-               if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EMSGSIZE;
-                       goto out_err;
-               }
-
-               ipmb_addr = (struct ipmi_ipmb_addr *) addr;
-               if (ipmb_addr->lun > 3) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr));
-
-               if (recv_msg->msg.netfn & 0x1) {
-                       /*
-                        * It's a response, so use the user's sequence
-                        * from msgid.
-                        */
-                       ipmi_inc_stat(intf, sent_ipmb_responses);
-                       format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
-                                       msgid, broadcast,
-                                       source_address, source_lun);
-
-                       /*
-                        * Save the receive message so we can use it
-                        * to deliver the response.
-                        */
-                       smi_msg->user_data = recv_msg;
-               } else {
-                       /* It's a command, so get a sequence for it. */
-
-                       spin_lock_irqsave(&(intf->seq_lock), flags);
-
-                       if (is_maintenance_mode_cmd(msg))
-                               intf->ipmb_maintenance_mode_timeout =
-                                       maintenance_mode_timeout_ms;
-
-                       if (intf->ipmb_maintenance_mode_timeout &&
-                           retry_time_ms == 0)
-                               /* Different default in maintenance mode */
-                               retry_time_ms = default_maintenance_retry_ms;
-
-                       /*
-                        * Create a sequence number with a 1 second
-                        * timeout and 4 retries.
-                        */
-                       rv = intf_next_seq(intf,
-                                          recv_msg,
-                                          retry_time_ms,
-                                          retries,
-                                          broadcast,
-                                          &ipmb_seq,
-                                          &seqid);
-                       if (rv) {
-                               /*
-                                * We have used up all the sequence numbers,
-                                * probably, so abort.
-                                */
-                               spin_unlock_irqrestore(&(intf->seq_lock),
-                                                      flags);
-                               goto out_err;
-                       }
-
-                       ipmi_inc_stat(intf, sent_ipmb_commands);
-
-                       /*
-                        * Store the sequence number in the message,
-                        * so that when the send message response
-                        * comes back we can start the timer.
-                        */
-                       format_ipmb_msg(smi_msg, msg, ipmb_addr,
-                                       STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
-                                       ipmb_seq, broadcast,
-                                       source_address, source_lun);
-
-                       /*
-                        * Copy the message into the recv message data, so we
-                        * can retransmit it later if necessary.
-                        */
-                       memcpy(recv_msg->msg_data, smi_msg->data,
-                              smi_msg->data_size);
-                       recv_msg->msg.data = recv_msg->msg_data;
-                       recv_msg->msg.data_len = smi_msg->data_size;
-
-                       /*
-                        * We don't unlock until here, because we need
-                        * to copy the completed message into the
-                        * recv_msg before we release the lock.
-                        * Otherwise, race conditions may bite us.  I
-                        * know that's pretty paranoid, but I prefer
-                        * to be correct.
-                        */
-                       spin_unlock_irqrestore(&(intf->seq_lock), flags);
-               }
+               rv = i_ipmi_req_ipmb(intf, addr, msgid, msg, smi_msg, recv_msg,
+                                    source_address, source_lun,
+                                    retries, retry_time_ms);
        } else if (is_lan_addr(addr)) {
-               struct ipmi_lan_addr  *lan_addr;
-               unsigned char         ipmb_seq;
-               long                  seqid;
-               struct ipmi_channel   *chans;
-
-               if (addr->channel >= IPMI_MAX_CHANNELS) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               chans = READ_ONCE(intf->channel_list)->c;
-
-               if ((chans[addr->channel].medium
-                               != IPMI_CHANNEL_MEDIUM_8023LAN)
-                   && (chans[addr->channel].medium
-                               != IPMI_CHANNEL_MEDIUM_ASYNC)) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               /* 11 for the header and 1 for the checksum. */
-               if ((msg->data_len + 12) > IPMI_MAX_MSG_LENGTH) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EMSGSIZE;
-                       goto out_err;
-               }
-
-               lan_addr = (struct ipmi_lan_addr *) addr;
-               if (lan_addr->lun > 3) {
-                       ipmi_inc_stat(intf, sent_invalid_commands);
-                       rv = -EINVAL;
-                       goto out_err;
-               }
-
-               memcpy(&recv_msg->addr, lan_addr, sizeof(*lan_addr));
-
-               if (recv_msg->msg.netfn & 0x1) {
-                       /*
-                        * It's a response, so use the user's sequence
-                        * from msgid.
-                        */
-                       ipmi_inc_stat(intf, sent_lan_responses);
-                       format_lan_msg(smi_msg, msg, lan_addr, msgid,
-                                      msgid, source_lun);
-
-                       /*
-                        * Save the receive message so we can use it
-                        * to deliver the response.
-                        */
-                       smi_msg->user_data = recv_msg;
-               } else {
-                       /* It's a command, so get a sequence for it. */
-
-                       spin_lock_irqsave(&(intf->seq_lock), flags);
-
-                       /*
-                        * Create a sequence number with a 1 second
-                        * timeout and 4 retries.
-                        */
-                       rv = intf_next_seq(intf,
-                                          recv_msg,
-                                          retry_time_ms,
-                                          retries,
-                                          0,
-                                          &ipmb_seq,
-                                          &seqid);
-                       if (rv) {
-                               /*
-                                * We have used up all the sequence numbers,
-                                * probably, so abort.
-                                */
-                               spin_unlock_irqrestore(&(intf->seq_lock),
-                                                      flags);
-                               goto out_err;
-                       }
-
-                       ipmi_inc_stat(intf, sent_lan_commands);
-
-                       /*
-                        * Store the sequence number in the message,
-                        * so that when the send message response
-                        * comes back we can start the timer.
-                        */
-                       format_lan_msg(smi_msg, msg, lan_addr,
-                                      STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
-                                      ipmb_seq, source_lun);
-
-                       /*
-                        * Copy the message into the recv message data, so we
-                        * can retransmit it later if necessary.
-                        */
-                       memcpy(recv_msg->msg_data, smi_msg->data,
-                              smi_msg->data_size);
-                       recv_msg->msg.data = recv_msg->msg_data;
-                       recv_msg->msg.data_len = smi_msg->data_size;
-
-                       /*
-                        * We don't unlock until here, because we need
-                        * to copy the completed message into the
-                        * recv_msg before we release the lock.
-                        * Otherwise, race conditions may bite us.  I
-                        * know that's pretty paranoid, but I prefer
-                        * to be correct.
-                        */
-                       spin_unlock_irqrestore(&(intf->seq_lock), flags);
-               }
+               rv = i_ipmi_req_lan(intf, addr, msgid, msg, smi_msg, recv_msg,
+                                   source_lun, retries, retry_time_ms);
        } else {
            /* Unknown address type. */
                ipmi_inc_stat(intf, sent_invalid_commands);
                rv = -EINVAL;
-               goto out_err;
        }
 
-       ipmi_debug_msg("Send", smi_msg->data, smi_msg->data_size);
+       if (rv) {
+out_err:
+               ipmi_free_smi_msg(smi_msg);
+               ipmi_free_recv_msg(recv_msg);
+       } else {
+               ipmi_debug_msg("Send", smi_msg->data, smi_msg->data_size);
 
-       smi_send(intf, intf->handlers, smi_msg, priority);
+               smi_send(intf, intf->handlers, smi_msg, priority);
+       }
        rcu_read_unlock();
 
-       return 0;
-
- out_err:
-       rcu_read_unlock();
-       ipmi_free_smi_msg(smi_msg);
-       ipmi_free_recv_msg(recv_msg);
        return rv;
 }