|
@@ -176,6 +176,42 @@ static int ipmi_request_in_rc_mode(ipmi_user_t user,
|
|
|
#define IPMI_ATCA_GET_ADDR_INFO_CMD 0x01
|
|
|
#define IPMI_PICMG_ID 0
|
|
|
|
|
|
+#define IPMI_NETFN_OEM 0x2e
|
|
|
+#define IPMI_ATCA_PPS_GRACEFUL_RESTART 0x11
|
|
|
+#define IPMI_ATCA_PPS_IANA "\x00\x40\x0A"
|
|
|
+#define IPMI_MOTOROLA_MANUFACTURER_ID 0x0000A1
|
|
|
+#define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID 0x0051
|
|
|
+
|
|
|
+static void (*atca_oem_poweroff_hook)(ipmi_user_t user) = NULL;
|
|
|
+
|
|
|
+static void pps_poweroff_atca (ipmi_user_t user)
|
|
|
+{
|
|
|
+ struct ipmi_system_interface_addr smi_addr;
|
|
|
+ struct kernel_ipmi_msg send_msg;
|
|
|
+ int rv;
|
|
|
+ /*
|
|
|
+ * Configure IPMI address for local access
|
|
|
+ */
|
|
|
+ smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
|
|
|
+ smi_addr.channel = IPMI_BMC_CHANNEL;
|
|
|
+ smi_addr.lun = 0;
|
|
|
+
|
|
|
+ printk(KERN_INFO PFX "PPS powerdown hook used");
|
|
|
+
|
|
|
+ send_msg.netfn = IPMI_NETFN_OEM;
|
|
|
+ send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART;
|
|
|
+ send_msg.data = IPMI_ATCA_PPS_IANA;
|
|
|
+ send_msg.data_len = 3;
|
|
|
+ rv = ipmi_request_in_rc_mode(user,
|
|
|
+ (struct ipmi_addr *) &smi_addr,
|
|
|
+ &send_msg);
|
|
|
+ if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
|
|
|
+ printk(KERN_ERR PFX "Unable to send ATCA ,"
|
|
|
+ " IPMI error 0x%x\n", rv);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
static int ipmi_atca_detect (ipmi_user_t user)
|
|
|
{
|
|
|
struct ipmi_system_interface_addr smi_addr;
|
|
@@ -201,6 +237,13 @@ static int ipmi_atca_detect (ipmi_user_t user)
|
|
|
rv = ipmi_request_wait_for_response(user,
|
|
|
(struct ipmi_addr *) &smi_addr,
|
|
|
&send_msg);
|
|
|
+
|
|
|
+ printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n", mfg_id, prod_id);
|
|
|
+ if((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID)
|
|
|
+ && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) {
|
|
|
+ printk(KERN_INFO PFX "Installing Pigeon Point Systems Poweroff Hook\n");
|
|
|
+ atca_oem_poweroff_hook = pps_poweroff_atca;
|
|
|
+ }
|
|
|
return !rv;
|
|
|
}
|
|
|
|
|
@@ -234,12 +277,19 @@ static void ipmi_poweroff_atca (ipmi_user_t user)
|
|
|
rv = ipmi_request_in_rc_mode(user,
|
|
|
(struct ipmi_addr *) &smi_addr,
|
|
|
&send_msg);
|
|
|
- if (rv) {
|
|
|
+ /** At this point, the system may be shutting down, and most
|
|
|
+ ** serial drivers (if used) will have interrupts turned off
|
|
|
+ ** it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE
|
|
|
+ ** return code
|
|
|
+ **/
|
|
|
+ if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
|
|
|
printk(KERN_ERR PFX "Unable to send ATCA powerdown message,"
|
|
|
" IPMI error 0x%x\n", rv);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ if(atca_oem_poweroff_hook)
|
|
|
+ return atca_oem_poweroff_hook(user);
|
|
|
out:
|
|
|
return;
|
|
|
}
|