1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * ipmi_si.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * The interface to the IPMI driver for the system interfaces (KCS, SMIC, 5*1da177e4SLinus Torvalds * BT). 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * Author: MontaVista Software, Inc. 8*1da177e4SLinus Torvalds * Corey Minyard <minyard@mvista.com> 9*1da177e4SLinus Torvalds * source@mvista.com 10*1da177e4SLinus Torvalds * 11*1da177e4SLinus Torvalds * Copyright 2002 MontaVista Software Inc. 12*1da177e4SLinus Torvalds * 13*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 14*1da177e4SLinus Torvalds * under the terms of the GNU General Public License as published by the 15*1da177e4SLinus Torvalds * Free Software Foundation; either version 2 of the License, or (at your 16*1da177e4SLinus Torvalds * option) any later version. 17*1da177e4SLinus Torvalds * 18*1da177e4SLinus Torvalds * 19*1da177e4SLinus Torvalds * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 20*1da177e4SLinus Torvalds * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21*1da177e4SLinus Torvalds * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22*1da177e4SLinus Torvalds * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23*1da177e4SLinus Torvalds * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24*1da177e4SLinus Torvalds * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25*1da177e4SLinus Torvalds * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26*1da177e4SLinus Torvalds * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27*1da177e4SLinus Torvalds * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 28*1da177e4SLinus Torvalds * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29*1da177e4SLinus Torvalds * 30*1da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License along 31*1da177e4SLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 32*1da177e4SLinus Torvalds * 675 Mass Ave, Cambridge, MA 02139, USA. 33*1da177e4SLinus Torvalds */ 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds /* 36*1da177e4SLinus Torvalds * This file holds the "policy" for the interface to the SMI state 37*1da177e4SLinus Torvalds * machine. It does the configuration, handles timers and interrupts, 38*1da177e4SLinus Torvalds * and drives the real SMI state machine. 39*1da177e4SLinus Torvalds */ 40*1da177e4SLinus Torvalds 41*1da177e4SLinus Torvalds #include <linux/config.h> 42*1da177e4SLinus Torvalds #include <linux/module.h> 43*1da177e4SLinus Torvalds #include <linux/moduleparam.h> 44*1da177e4SLinus Torvalds #include <asm/system.h> 45*1da177e4SLinus Torvalds #include <linux/sched.h> 46*1da177e4SLinus Torvalds #include <linux/timer.h> 47*1da177e4SLinus Torvalds #include <linux/errno.h> 48*1da177e4SLinus Torvalds #include <linux/spinlock.h> 49*1da177e4SLinus Torvalds #include <linux/slab.h> 50*1da177e4SLinus Torvalds #include <linux/delay.h> 51*1da177e4SLinus Torvalds #include <linux/list.h> 52*1da177e4SLinus Torvalds #include <linux/pci.h> 53*1da177e4SLinus Torvalds #include <linux/ioport.h> 54*1da177e4SLinus Torvalds #include <asm/irq.h> 55*1da177e4SLinus Torvalds #ifdef CONFIG_HIGH_RES_TIMERS 56*1da177e4SLinus Torvalds #include <linux/hrtime.h> 57*1da177e4SLinus Torvalds # if defined(schedule_next_int) 58*1da177e4SLinus Torvalds /* Old high-res timer code, do translations. */ 59*1da177e4SLinus Torvalds # define get_arch_cycles(a) quick_update_jiffies_sub(a) 60*1da177e4SLinus Torvalds # define arch_cycles_per_jiffy cycles_per_jiffies 61*1da177e4SLinus Torvalds # endif 62*1da177e4SLinus Torvalds static inline void add_usec_to_timer(struct timer_list *t, long v) 63*1da177e4SLinus Torvalds { 64*1da177e4SLinus Torvalds t->sub_expires += nsec_to_arch_cycle(v * 1000); 65*1da177e4SLinus Torvalds while (t->sub_expires >= arch_cycles_per_jiffy) 66*1da177e4SLinus Torvalds { 67*1da177e4SLinus Torvalds t->expires++; 68*1da177e4SLinus Torvalds t->sub_expires -= arch_cycles_per_jiffy; 69*1da177e4SLinus Torvalds } 70*1da177e4SLinus Torvalds } 71*1da177e4SLinus Torvalds #endif 72*1da177e4SLinus Torvalds #include <linux/interrupt.h> 73*1da177e4SLinus Torvalds #include <linux/rcupdate.h> 74*1da177e4SLinus Torvalds #include <linux/ipmi_smi.h> 75*1da177e4SLinus Torvalds #include <asm/io.h> 76*1da177e4SLinus Torvalds #include "ipmi_si_sm.h" 77*1da177e4SLinus Torvalds #include <linux/init.h> 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds #define IPMI_SI_VERSION "v33" 80*1da177e4SLinus Torvalds 81*1da177e4SLinus Torvalds /* Measure times between events in the driver. */ 82*1da177e4SLinus Torvalds #undef DEBUG_TIMING 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds /* Call every 10 ms. */ 85*1da177e4SLinus Torvalds #define SI_TIMEOUT_TIME_USEC 10000 86*1da177e4SLinus Torvalds #define SI_USEC_PER_JIFFY (1000000/HZ) 87*1da177e4SLinus Torvalds #define SI_TIMEOUT_JIFFIES (SI_TIMEOUT_TIME_USEC/SI_USEC_PER_JIFFY) 88*1da177e4SLinus Torvalds #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a 89*1da177e4SLinus Torvalds short timeout */ 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds enum si_intf_state { 92*1da177e4SLinus Torvalds SI_NORMAL, 93*1da177e4SLinus Torvalds SI_GETTING_FLAGS, 94*1da177e4SLinus Torvalds SI_GETTING_EVENTS, 95*1da177e4SLinus Torvalds SI_CLEARING_FLAGS, 96*1da177e4SLinus Torvalds SI_CLEARING_FLAGS_THEN_SET_IRQ, 97*1da177e4SLinus Torvalds SI_GETTING_MESSAGES, 98*1da177e4SLinus Torvalds SI_ENABLE_INTERRUPTS1, 99*1da177e4SLinus Torvalds SI_ENABLE_INTERRUPTS2 100*1da177e4SLinus Torvalds /* FIXME - add watchdog stuff. */ 101*1da177e4SLinus Torvalds }; 102*1da177e4SLinus Torvalds 103*1da177e4SLinus Torvalds enum si_type { 104*1da177e4SLinus Torvalds SI_KCS, SI_SMIC, SI_BT 105*1da177e4SLinus Torvalds }; 106*1da177e4SLinus Torvalds 107*1da177e4SLinus Torvalds struct smi_info 108*1da177e4SLinus Torvalds { 109*1da177e4SLinus Torvalds ipmi_smi_t intf; 110*1da177e4SLinus Torvalds struct si_sm_data *si_sm; 111*1da177e4SLinus Torvalds struct si_sm_handlers *handlers; 112*1da177e4SLinus Torvalds enum si_type si_type; 113*1da177e4SLinus Torvalds spinlock_t si_lock; 114*1da177e4SLinus Torvalds spinlock_t msg_lock; 115*1da177e4SLinus Torvalds struct list_head xmit_msgs; 116*1da177e4SLinus Torvalds struct list_head hp_xmit_msgs; 117*1da177e4SLinus Torvalds struct ipmi_smi_msg *curr_msg; 118*1da177e4SLinus Torvalds enum si_intf_state si_state; 119*1da177e4SLinus Torvalds 120*1da177e4SLinus Torvalds /* Used to handle the various types of I/O that can occur with 121*1da177e4SLinus Torvalds IPMI */ 122*1da177e4SLinus Torvalds struct si_sm_io io; 123*1da177e4SLinus Torvalds int (*io_setup)(struct smi_info *info); 124*1da177e4SLinus Torvalds void (*io_cleanup)(struct smi_info *info); 125*1da177e4SLinus Torvalds int (*irq_setup)(struct smi_info *info); 126*1da177e4SLinus Torvalds void (*irq_cleanup)(struct smi_info *info); 127*1da177e4SLinus Torvalds unsigned int io_size; 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds /* Flags from the last GET_MSG_FLAGS command, used when an ATTN 130*1da177e4SLinus Torvalds is set to hold the flags until we are done handling everything 131*1da177e4SLinus Torvalds from the flags. */ 132*1da177e4SLinus Torvalds #define RECEIVE_MSG_AVAIL 0x01 133*1da177e4SLinus Torvalds #define EVENT_MSG_BUFFER_FULL 0x02 134*1da177e4SLinus Torvalds #define WDT_PRE_TIMEOUT_INT 0x08 135*1da177e4SLinus Torvalds unsigned char msg_flags; 136*1da177e4SLinus Torvalds 137*1da177e4SLinus Torvalds /* If set to true, this will request events the next time the 138*1da177e4SLinus Torvalds state machine is idle. */ 139*1da177e4SLinus Torvalds atomic_t req_events; 140*1da177e4SLinus Torvalds 141*1da177e4SLinus Torvalds /* If true, run the state machine to completion on every send 142*1da177e4SLinus Torvalds call. Generally used after a panic to make sure stuff goes 143*1da177e4SLinus Torvalds out. */ 144*1da177e4SLinus Torvalds int run_to_completion; 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds /* The I/O port of an SI interface. */ 147*1da177e4SLinus Torvalds int port; 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds /* The space between start addresses of the two ports. For 150*1da177e4SLinus Torvalds instance, if the first port is 0xca2 and the spacing is 4, then 151*1da177e4SLinus Torvalds the second port is 0xca6. */ 152*1da177e4SLinus Torvalds unsigned int spacing; 153*1da177e4SLinus Torvalds 154*1da177e4SLinus Torvalds /* zero if no irq; */ 155*1da177e4SLinus Torvalds int irq; 156*1da177e4SLinus Torvalds 157*1da177e4SLinus Torvalds /* The timer for this si. */ 158*1da177e4SLinus Torvalds struct timer_list si_timer; 159*1da177e4SLinus Torvalds 160*1da177e4SLinus Torvalds /* The time (in jiffies) the last timeout occurred at. */ 161*1da177e4SLinus Torvalds unsigned long last_timeout_jiffies; 162*1da177e4SLinus Torvalds 163*1da177e4SLinus Torvalds /* Used to gracefully stop the timer without race conditions. */ 164*1da177e4SLinus Torvalds volatile int stop_operation; 165*1da177e4SLinus Torvalds volatile int timer_stopped; 166*1da177e4SLinus Torvalds 167*1da177e4SLinus Torvalds /* The driver will disable interrupts when it gets into a 168*1da177e4SLinus Torvalds situation where it cannot handle messages due to lack of 169*1da177e4SLinus Torvalds memory. Once that situation clears up, it will re-enable 170*1da177e4SLinus Torvalds interrupts. */ 171*1da177e4SLinus Torvalds int interrupt_disabled; 172*1da177e4SLinus Torvalds 173*1da177e4SLinus Torvalds unsigned char ipmi_si_dev_rev; 174*1da177e4SLinus Torvalds unsigned char ipmi_si_fw_rev_major; 175*1da177e4SLinus Torvalds unsigned char ipmi_si_fw_rev_minor; 176*1da177e4SLinus Torvalds unsigned char ipmi_version_major; 177*1da177e4SLinus Torvalds unsigned char ipmi_version_minor; 178*1da177e4SLinus Torvalds 179*1da177e4SLinus Torvalds /* Slave address, could be reported from DMI. */ 180*1da177e4SLinus Torvalds unsigned char slave_addr; 181*1da177e4SLinus Torvalds 182*1da177e4SLinus Torvalds /* Counters and things for the proc filesystem. */ 183*1da177e4SLinus Torvalds spinlock_t count_lock; 184*1da177e4SLinus Torvalds unsigned long short_timeouts; 185*1da177e4SLinus Torvalds unsigned long long_timeouts; 186*1da177e4SLinus Torvalds unsigned long timeout_restarts; 187*1da177e4SLinus Torvalds unsigned long idles; 188*1da177e4SLinus Torvalds unsigned long interrupts; 189*1da177e4SLinus Torvalds unsigned long attentions; 190*1da177e4SLinus Torvalds unsigned long flag_fetches; 191*1da177e4SLinus Torvalds unsigned long hosed_count; 192*1da177e4SLinus Torvalds unsigned long complete_transactions; 193*1da177e4SLinus Torvalds unsigned long events; 194*1da177e4SLinus Torvalds unsigned long watchdog_pretimeouts; 195*1da177e4SLinus Torvalds unsigned long incoming_messages; 196*1da177e4SLinus Torvalds }; 197*1da177e4SLinus Torvalds 198*1da177e4SLinus Torvalds static void si_restart_short_timer(struct smi_info *smi_info); 199*1da177e4SLinus Torvalds 200*1da177e4SLinus Torvalds static void deliver_recv_msg(struct smi_info *smi_info, 201*1da177e4SLinus Torvalds struct ipmi_smi_msg *msg) 202*1da177e4SLinus Torvalds { 203*1da177e4SLinus Torvalds /* Deliver the message to the upper layer with the lock 204*1da177e4SLinus Torvalds released. */ 205*1da177e4SLinus Torvalds spin_unlock(&(smi_info->si_lock)); 206*1da177e4SLinus Torvalds ipmi_smi_msg_received(smi_info->intf, msg); 207*1da177e4SLinus Torvalds spin_lock(&(smi_info->si_lock)); 208*1da177e4SLinus Torvalds } 209*1da177e4SLinus Torvalds 210*1da177e4SLinus Torvalds static void return_hosed_msg(struct smi_info *smi_info) 211*1da177e4SLinus Torvalds { 212*1da177e4SLinus Torvalds struct ipmi_smi_msg *msg = smi_info->curr_msg; 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds /* Make it a reponse */ 215*1da177e4SLinus Torvalds msg->rsp[0] = msg->data[0] | 4; 216*1da177e4SLinus Torvalds msg->rsp[1] = msg->data[1]; 217*1da177e4SLinus Torvalds msg->rsp[2] = 0xFF; /* Unknown error. */ 218*1da177e4SLinus Torvalds msg->rsp_size = 3; 219*1da177e4SLinus Torvalds 220*1da177e4SLinus Torvalds smi_info->curr_msg = NULL; 221*1da177e4SLinus Torvalds deliver_recv_msg(smi_info, msg); 222*1da177e4SLinus Torvalds } 223*1da177e4SLinus Torvalds 224*1da177e4SLinus Torvalds static enum si_sm_result start_next_msg(struct smi_info *smi_info) 225*1da177e4SLinus Torvalds { 226*1da177e4SLinus Torvalds int rv; 227*1da177e4SLinus Torvalds struct list_head *entry = NULL; 228*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 229*1da177e4SLinus Torvalds struct timeval t; 230*1da177e4SLinus Torvalds #endif 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds /* No need to save flags, we aleady have interrupts off and we 233*1da177e4SLinus Torvalds already hold the SMI lock. */ 234*1da177e4SLinus Torvalds spin_lock(&(smi_info->msg_lock)); 235*1da177e4SLinus Torvalds 236*1da177e4SLinus Torvalds /* Pick the high priority queue first. */ 237*1da177e4SLinus Torvalds if (! list_empty(&(smi_info->hp_xmit_msgs))) { 238*1da177e4SLinus Torvalds entry = smi_info->hp_xmit_msgs.next; 239*1da177e4SLinus Torvalds } else if (! list_empty(&(smi_info->xmit_msgs))) { 240*1da177e4SLinus Torvalds entry = smi_info->xmit_msgs.next; 241*1da177e4SLinus Torvalds } 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds if (!entry) { 244*1da177e4SLinus Torvalds smi_info->curr_msg = NULL; 245*1da177e4SLinus Torvalds rv = SI_SM_IDLE; 246*1da177e4SLinus Torvalds } else { 247*1da177e4SLinus Torvalds int err; 248*1da177e4SLinus Torvalds 249*1da177e4SLinus Torvalds list_del(entry); 250*1da177e4SLinus Torvalds smi_info->curr_msg = list_entry(entry, 251*1da177e4SLinus Torvalds struct ipmi_smi_msg, 252*1da177e4SLinus Torvalds link); 253*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 254*1da177e4SLinus Torvalds do_gettimeofday(&t); 255*1da177e4SLinus Torvalds printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); 256*1da177e4SLinus Torvalds #endif 257*1da177e4SLinus Torvalds err = smi_info->handlers->start_transaction( 258*1da177e4SLinus Torvalds smi_info->si_sm, 259*1da177e4SLinus Torvalds smi_info->curr_msg->data, 260*1da177e4SLinus Torvalds smi_info->curr_msg->data_size); 261*1da177e4SLinus Torvalds if (err) { 262*1da177e4SLinus Torvalds return_hosed_msg(smi_info); 263*1da177e4SLinus Torvalds } 264*1da177e4SLinus Torvalds 265*1da177e4SLinus Torvalds rv = SI_SM_CALL_WITHOUT_DELAY; 266*1da177e4SLinus Torvalds } 267*1da177e4SLinus Torvalds spin_unlock(&(smi_info->msg_lock)); 268*1da177e4SLinus Torvalds 269*1da177e4SLinus Torvalds return rv; 270*1da177e4SLinus Torvalds } 271*1da177e4SLinus Torvalds 272*1da177e4SLinus Torvalds static void start_enable_irq(struct smi_info *smi_info) 273*1da177e4SLinus Torvalds { 274*1da177e4SLinus Torvalds unsigned char msg[2]; 275*1da177e4SLinus Torvalds 276*1da177e4SLinus Torvalds /* If we are enabling interrupts, we have to tell the 277*1da177e4SLinus Torvalds BMC to use them. */ 278*1da177e4SLinus Torvalds msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 279*1da177e4SLinus Torvalds msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); 282*1da177e4SLinus Torvalds smi_info->si_state = SI_ENABLE_INTERRUPTS1; 283*1da177e4SLinus Torvalds } 284*1da177e4SLinus Torvalds 285*1da177e4SLinus Torvalds static void start_clear_flags(struct smi_info *smi_info) 286*1da177e4SLinus Torvalds { 287*1da177e4SLinus Torvalds unsigned char msg[3]; 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds /* Make sure the watchdog pre-timeout flag is not set at startup. */ 290*1da177e4SLinus Torvalds msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 291*1da177e4SLinus Torvalds msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD; 292*1da177e4SLinus Torvalds msg[2] = WDT_PRE_TIMEOUT_INT; 293*1da177e4SLinus Torvalds 294*1da177e4SLinus Torvalds smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3); 295*1da177e4SLinus Torvalds smi_info->si_state = SI_CLEARING_FLAGS; 296*1da177e4SLinus Torvalds } 297*1da177e4SLinus Torvalds 298*1da177e4SLinus Torvalds /* When we have a situtaion where we run out of memory and cannot 299*1da177e4SLinus Torvalds allocate messages, we just leave them in the BMC and run the system 300*1da177e4SLinus Torvalds polled until we can allocate some memory. Once we have some 301*1da177e4SLinus Torvalds memory, we will re-enable the interrupt. */ 302*1da177e4SLinus Torvalds static inline void disable_si_irq(struct smi_info *smi_info) 303*1da177e4SLinus Torvalds { 304*1da177e4SLinus Torvalds if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { 305*1da177e4SLinus Torvalds disable_irq_nosync(smi_info->irq); 306*1da177e4SLinus Torvalds smi_info->interrupt_disabled = 1; 307*1da177e4SLinus Torvalds } 308*1da177e4SLinus Torvalds } 309*1da177e4SLinus Torvalds 310*1da177e4SLinus Torvalds static inline void enable_si_irq(struct smi_info *smi_info) 311*1da177e4SLinus Torvalds { 312*1da177e4SLinus Torvalds if ((smi_info->irq) && (smi_info->interrupt_disabled)) { 313*1da177e4SLinus Torvalds enable_irq(smi_info->irq); 314*1da177e4SLinus Torvalds smi_info->interrupt_disabled = 0; 315*1da177e4SLinus Torvalds } 316*1da177e4SLinus Torvalds } 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds static void handle_flags(struct smi_info *smi_info) 319*1da177e4SLinus Torvalds { 320*1da177e4SLinus Torvalds if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { 321*1da177e4SLinus Torvalds /* Watchdog pre-timeout */ 322*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 323*1da177e4SLinus Torvalds smi_info->watchdog_pretimeouts++; 324*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 325*1da177e4SLinus Torvalds 326*1da177e4SLinus Torvalds start_clear_flags(smi_info); 327*1da177e4SLinus Torvalds smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; 328*1da177e4SLinus Torvalds spin_unlock(&(smi_info->si_lock)); 329*1da177e4SLinus Torvalds ipmi_smi_watchdog_pretimeout(smi_info->intf); 330*1da177e4SLinus Torvalds spin_lock(&(smi_info->si_lock)); 331*1da177e4SLinus Torvalds } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { 332*1da177e4SLinus Torvalds /* Messages available. */ 333*1da177e4SLinus Torvalds smi_info->curr_msg = ipmi_alloc_smi_msg(); 334*1da177e4SLinus Torvalds if (!smi_info->curr_msg) { 335*1da177e4SLinus Torvalds disable_si_irq(smi_info); 336*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 337*1da177e4SLinus Torvalds return; 338*1da177e4SLinus Torvalds } 339*1da177e4SLinus Torvalds enable_si_irq(smi_info); 340*1da177e4SLinus Torvalds 341*1da177e4SLinus Torvalds smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); 342*1da177e4SLinus Torvalds smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD; 343*1da177e4SLinus Torvalds smi_info->curr_msg->data_size = 2; 344*1da177e4SLinus Torvalds 345*1da177e4SLinus Torvalds smi_info->handlers->start_transaction( 346*1da177e4SLinus Torvalds smi_info->si_sm, 347*1da177e4SLinus Torvalds smi_info->curr_msg->data, 348*1da177e4SLinus Torvalds smi_info->curr_msg->data_size); 349*1da177e4SLinus Torvalds smi_info->si_state = SI_GETTING_MESSAGES; 350*1da177e4SLinus Torvalds } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { 351*1da177e4SLinus Torvalds /* Events available. */ 352*1da177e4SLinus Torvalds smi_info->curr_msg = ipmi_alloc_smi_msg(); 353*1da177e4SLinus Torvalds if (!smi_info->curr_msg) { 354*1da177e4SLinus Torvalds disable_si_irq(smi_info); 355*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 356*1da177e4SLinus Torvalds return; 357*1da177e4SLinus Torvalds } 358*1da177e4SLinus Torvalds enable_si_irq(smi_info); 359*1da177e4SLinus Torvalds 360*1da177e4SLinus Torvalds smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); 361*1da177e4SLinus Torvalds smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD; 362*1da177e4SLinus Torvalds smi_info->curr_msg->data_size = 2; 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds smi_info->handlers->start_transaction( 365*1da177e4SLinus Torvalds smi_info->si_sm, 366*1da177e4SLinus Torvalds smi_info->curr_msg->data, 367*1da177e4SLinus Torvalds smi_info->curr_msg->data_size); 368*1da177e4SLinus Torvalds smi_info->si_state = SI_GETTING_EVENTS; 369*1da177e4SLinus Torvalds } else { 370*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 371*1da177e4SLinus Torvalds } 372*1da177e4SLinus Torvalds } 373*1da177e4SLinus Torvalds 374*1da177e4SLinus Torvalds static void handle_transaction_done(struct smi_info *smi_info) 375*1da177e4SLinus Torvalds { 376*1da177e4SLinus Torvalds struct ipmi_smi_msg *msg; 377*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 378*1da177e4SLinus Torvalds struct timeval t; 379*1da177e4SLinus Torvalds 380*1da177e4SLinus Torvalds do_gettimeofday(&t); 381*1da177e4SLinus Torvalds printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec); 382*1da177e4SLinus Torvalds #endif 383*1da177e4SLinus Torvalds switch (smi_info->si_state) { 384*1da177e4SLinus Torvalds case SI_NORMAL: 385*1da177e4SLinus Torvalds if (!smi_info->curr_msg) 386*1da177e4SLinus Torvalds break; 387*1da177e4SLinus Torvalds 388*1da177e4SLinus Torvalds smi_info->curr_msg->rsp_size 389*1da177e4SLinus Torvalds = smi_info->handlers->get_result( 390*1da177e4SLinus Torvalds smi_info->si_sm, 391*1da177e4SLinus Torvalds smi_info->curr_msg->rsp, 392*1da177e4SLinus Torvalds IPMI_MAX_MSG_LENGTH); 393*1da177e4SLinus Torvalds 394*1da177e4SLinus Torvalds /* Do this here becase deliver_recv_msg() releases the 395*1da177e4SLinus Torvalds lock, and a new message can be put in during the 396*1da177e4SLinus Torvalds time the lock is released. */ 397*1da177e4SLinus Torvalds msg = smi_info->curr_msg; 398*1da177e4SLinus Torvalds smi_info->curr_msg = NULL; 399*1da177e4SLinus Torvalds deliver_recv_msg(smi_info, msg); 400*1da177e4SLinus Torvalds break; 401*1da177e4SLinus Torvalds 402*1da177e4SLinus Torvalds case SI_GETTING_FLAGS: 403*1da177e4SLinus Torvalds { 404*1da177e4SLinus Torvalds unsigned char msg[4]; 405*1da177e4SLinus Torvalds unsigned int len; 406*1da177e4SLinus Torvalds 407*1da177e4SLinus Torvalds /* We got the flags from the SMI, now handle them. */ 408*1da177e4SLinus Torvalds len = smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 409*1da177e4SLinus Torvalds if (msg[2] != 0) { 410*1da177e4SLinus Torvalds /* Error fetching flags, just give up for 411*1da177e4SLinus Torvalds now. */ 412*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 413*1da177e4SLinus Torvalds } else if (len < 4) { 414*1da177e4SLinus Torvalds /* Hmm, no flags. That's technically illegal, but 415*1da177e4SLinus Torvalds don't use uninitialized data. */ 416*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 417*1da177e4SLinus Torvalds } else { 418*1da177e4SLinus Torvalds smi_info->msg_flags = msg[3]; 419*1da177e4SLinus Torvalds handle_flags(smi_info); 420*1da177e4SLinus Torvalds } 421*1da177e4SLinus Torvalds break; 422*1da177e4SLinus Torvalds } 423*1da177e4SLinus Torvalds 424*1da177e4SLinus Torvalds case SI_CLEARING_FLAGS: 425*1da177e4SLinus Torvalds case SI_CLEARING_FLAGS_THEN_SET_IRQ: 426*1da177e4SLinus Torvalds { 427*1da177e4SLinus Torvalds unsigned char msg[3]; 428*1da177e4SLinus Torvalds 429*1da177e4SLinus Torvalds /* We cleared the flags. */ 430*1da177e4SLinus Torvalds smi_info->handlers->get_result(smi_info->si_sm, msg, 3); 431*1da177e4SLinus Torvalds if (msg[2] != 0) { 432*1da177e4SLinus Torvalds /* Error clearing flags */ 433*1da177e4SLinus Torvalds printk(KERN_WARNING 434*1da177e4SLinus Torvalds "ipmi_si: Error clearing flags: %2.2x\n", 435*1da177e4SLinus Torvalds msg[2]); 436*1da177e4SLinus Torvalds } 437*1da177e4SLinus Torvalds if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ) 438*1da177e4SLinus Torvalds start_enable_irq(smi_info); 439*1da177e4SLinus Torvalds else 440*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 441*1da177e4SLinus Torvalds break; 442*1da177e4SLinus Torvalds } 443*1da177e4SLinus Torvalds 444*1da177e4SLinus Torvalds case SI_GETTING_EVENTS: 445*1da177e4SLinus Torvalds { 446*1da177e4SLinus Torvalds smi_info->curr_msg->rsp_size 447*1da177e4SLinus Torvalds = smi_info->handlers->get_result( 448*1da177e4SLinus Torvalds smi_info->si_sm, 449*1da177e4SLinus Torvalds smi_info->curr_msg->rsp, 450*1da177e4SLinus Torvalds IPMI_MAX_MSG_LENGTH); 451*1da177e4SLinus Torvalds 452*1da177e4SLinus Torvalds /* Do this here becase deliver_recv_msg() releases the 453*1da177e4SLinus Torvalds lock, and a new message can be put in during the 454*1da177e4SLinus Torvalds time the lock is released. */ 455*1da177e4SLinus Torvalds msg = smi_info->curr_msg; 456*1da177e4SLinus Torvalds smi_info->curr_msg = NULL; 457*1da177e4SLinus Torvalds if (msg->rsp[2] != 0) { 458*1da177e4SLinus Torvalds /* Error getting event, probably done. */ 459*1da177e4SLinus Torvalds msg->done(msg); 460*1da177e4SLinus Torvalds 461*1da177e4SLinus Torvalds /* Take off the event flag. */ 462*1da177e4SLinus Torvalds smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; 463*1da177e4SLinus Torvalds handle_flags(smi_info); 464*1da177e4SLinus Torvalds } else { 465*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 466*1da177e4SLinus Torvalds smi_info->events++; 467*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 468*1da177e4SLinus Torvalds 469*1da177e4SLinus Torvalds /* Do this before we deliver the message 470*1da177e4SLinus Torvalds because delivering the message releases the 471*1da177e4SLinus Torvalds lock and something else can mess with the 472*1da177e4SLinus Torvalds state. */ 473*1da177e4SLinus Torvalds handle_flags(smi_info); 474*1da177e4SLinus Torvalds 475*1da177e4SLinus Torvalds deliver_recv_msg(smi_info, msg); 476*1da177e4SLinus Torvalds } 477*1da177e4SLinus Torvalds break; 478*1da177e4SLinus Torvalds } 479*1da177e4SLinus Torvalds 480*1da177e4SLinus Torvalds case SI_GETTING_MESSAGES: 481*1da177e4SLinus Torvalds { 482*1da177e4SLinus Torvalds smi_info->curr_msg->rsp_size 483*1da177e4SLinus Torvalds = smi_info->handlers->get_result( 484*1da177e4SLinus Torvalds smi_info->si_sm, 485*1da177e4SLinus Torvalds smi_info->curr_msg->rsp, 486*1da177e4SLinus Torvalds IPMI_MAX_MSG_LENGTH); 487*1da177e4SLinus Torvalds 488*1da177e4SLinus Torvalds /* Do this here becase deliver_recv_msg() releases the 489*1da177e4SLinus Torvalds lock, and a new message can be put in during the 490*1da177e4SLinus Torvalds time the lock is released. */ 491*1da177e4SLinus Torvalds msg = smi_info->curr_msg; 492*1da177e4SLinus Torvalds smi_info->curr_msg = NULL; 493*1da177e4SLinus Torvalds if (msg->rsp[2] != 0) { 494*1da177e4SLinus Torvalds /* Error getting event, probably done. */ 495*1da177e4SLinus Torvalds msg->done(msg); 496*1da177e4SLinus Torvalds 497*1da177e4SLinus Torvalds /* Take off the msg flag. */ 498*1da177e4SLinus Torvalds smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL; 499*1da177e4SLinus Torvalds handle_flags(smi_info); 500*1da177e4SLinus Torvalds } else { 501*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 502*1da177e4SLinus Torvalds smi_info->incoming_messages++; 503*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 504*1da177e4SLinus Torvalds 505*1da177e4SLinus Torvalds /* Do this before we deliver the message 506*1da177e4SLinus Torvalds because delivering the message releases the 507*1da177e4SLinus Torvalds lock and something else can mess with the 508*1da177e4SLinus Torvalds state. */ 509*1da177e4SLinus Torvalds handle_flags(smi_info); 510*1da177e4SLinus Torvalds 511*1da177e4SLinus Torvalds deliver_recv_msg(smi_info, msg); 512*1da177e4SLinus Torvalds } 513*1da177e4SLinus Torvalds break; 514*1da177e4SLinus Torvalds } 515*1da177e4SLinus Torvalds 516*1da177e4SLinus Torvalds case SI_ENABLE_INTERRUPTS1: 517*1da177e4SLinus Torvalds { 518*1da177e4SLinus Torvalds unsigned char msg[4]; 519*1da177e4SLinus Torvalds 520*1da177e4SLinus Torvalds /* We got the flags from the SMI, now handle them. */ 521*1da177e4SLinus Torvalds smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 522*1da177e4SLinus Torvalds if (msg[2] != 0) { 523*1da177e4SLinus Torvalds printk(KERN_WARNING 524*1da177e4SLinus Torvalds "ipmi_si: Could not enable interrupts" 525*1da177e4SLinus Torvalds ", failed get, using polled mode.\n"); 526*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 527*1da177e4SLinus Torvalds } else { 528*1da177e4SLinus Torvalds msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 529*1da177e4SLinus Torvalds msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; 530*1da177e4SLinus Torvalds msg[2] = msg[3] | 1; /* enable msg queue int */ 531*1da177e4SLinus Torvalds smi_info->handlers->start_transaction( 532*1da177e4SLinus Torvalds smi_info->si_sm, msg, 3); 533*1da177e4SLinus Torvalds smi_info->si_state = SI_ENABLE_INTERRUPTS2; 534*1da177e4SLinus Torvalds } 535*1da177e4SLinus Torvalds break; 536*1da177e4SLinus Torvalds } 537*1da177e4SLinus Torvalds 538*1da177e4SLinus Torvalds case SI_ENABLE_INTERRUPTS2: 539*1da177e4SLinus Torvalds { 540*1da177e4SLinus Torvalds unsigned char msg[4]; 541*1da177e4SLinus Torvalds 542*1da177e4SLinus Torvalds /* We got the flags from the SMI, now handle them. */ 543*1da177e4SLinus Torvalds smi_info->handlers->get_result(smi_info->si_sm, msg, 4); 544*1da177e4SLinus Torvalds if (msg[2] != 0) { 545*1da177e4SLinus Torvalds printk(KERN_WARNING 546*1da177e4SLinus Torvalds "ipmi_si: Could not enable interrupts" 547*1da177e4SLinus Torvalds ", failed set, using polled mode.\n"); 548*1da177e4SLinus Torvalds } 549*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 550*1da177e4SLinus Torvalds break; 551*1da177e4SLinus Torvalds } 552*1da177e4SLinus Torvalds } 553*1da177e4SLinus Torvalds } 554*1da177e4SLinus Torvalds 555*1da177e4SLinus Torvalds /* Called on timeouts and events. Timeouts should pass the elapsed 556*1da177e4SLinus Torvalds time, interrupts should pass in zero. */ 557*1da177e4SLinus Torvalds static enum si_sm_result smi_event_handler(struct smi_info *smi_info, 558*1da177e4SLinus Torvalds int time) 559*1da177e4SLinus Torvalds { 560*1da177e4SLinus Torvalds enum si_sm_result si_sm_result; 561*1da177e4SLinus Torvalds 562*1da177e4SLinus Torvalds restart: 563*1da177e4SLinus Torvalds /* There used to be a loop here that waited a little while 564*1da177e4SLinus Torvalds (around 25us) before giving up. That turned out to be 565*1da177e4SLinus Torvalds pointless, the minimum delays I was seeing were in the 300us 566*1da177e4SLinus Torvalds range, which is far too long to wait in an interrupt. So 567*1da177e4SLinus Torvalds we just run until the state machine tells us something 568*1da177e4SLinus Torvalds happened or it needs a delay. */ 569*1da177e4SLinus Torvalds si_sm_result = smi_info->handlers->event(smi_info->si_sm, time); 570*1da177e4SLinus Torvalds time = 0; 571*1da177e4SLinus Torvalds while (si_sm_result == SI_SM_CALL_WITHOUT_DELAY) 572*1da177e4SLinus Torvalds { 573*1da177e4SLinus Torvalds si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); 574*1da177e4SLinus Torvalds } 575*1da177e4SLinus Torvalds 576*1da177e4SLinus Torvalds if (si_sm_result == SI_SM_TRANSACTION_COMPLETE) 577*1da177e4SLinus Torvalds { 578*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 579*1da177e4SLinus Torvalds smi_info->complete_transactions++; 580*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 581*1da177e4SLinus Torvalds 582*1da177e4SLinus Torvalds handle_transaction_done(smi_info); 583*1da177e4SLinus Torvalds si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); 584*1da177e4SLinus Torvalds } 585*1da177e4SLinus Torvalds else if (si_sm_result == SI_SM_HOSED) 586*1da177e4SLinus Torvalds { 587*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 588*1da177e4SLinus Torvalds smi_info->hosed_count++; 589*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 590*1da177e4SLinus Torvalds 591*1da177e4SLinus Torvalds /* Do the before return_hosed_msg, because that 592*1da177e4SLinus Torvalds releases the lock. */ 593*1da177e4SLinus Torvalds smi_info->si_state = SI_NORMAL; 594*1da177e4SLinus Torvalds if (smi_info->curr_msg != NULL) { 595*1da177e4SLinus Torvalds /* If we were handling a user message, format 596*1da177e4SLinus Torvalds a response to send to the upper layer to 597*1da177e4SLinus Torvalds tell it about the error. */ 598*1da177e4SLinus Torvalds return_hosed_msg(smi_info); 599*1da177e4SLinus Torvalds } 600*1da177e4SLinus Torvalds si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); 601*1da177e4SLinus Torvalds } 602*1da177e4SLinus Torvalds 603*1da177e4SLinus Torvalds /* We prefer handling attn over new messages. */ 604*1da177e4SLinus Torvalds if (si_sm_result == SI_SM_ATTN) 605*1da177e4SLinus Torvalds { 606*1da177e4SLinus Torvalds unsigned char msg[2]; 607*1da177e4SLinus Torvalds 608*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 609*1da177e4SLinus Torvalds smi_info->attentions++; 610*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 611*1da177e4SLinus Torvalds 612*1da177e4SLinus Torvalds /* Got a attn, send down a get message flags to see 613*1da177e4SLinus Torvalds what's causing it. It would be better to handle 614*1da177e4SLinus Torvalds this in the upper layer, but due to the way 615*1da177e4SLinus Torvalds interrupts work with the SMI, that's not really 616*1da177e4SLinus Torvalds possible. */ 617*1da177e4SLinus Torvalds msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 618*1da177e4SLinus Torvalds msg[1] = IPMI_GET_MSG_FLAGS_CMD; 619*1da177e4SLinus Torvalds 620*1da177e4SLinus Torvalds smi_info->handlers->start_transaction( 621*1da177e4SLinus Torvalds smi_info->si_sm, msg, 2); 622*1da177e4SLinus Torvalds smi_info->si_state = SI_GETTING_FLAGS; 623*1da177e4SLinus Torvalds goto restart; 624*1da177e4SLinus Torvalds } 625*1da177e4SLinus Torvalds 626*1da177e4SLinus Torvalds /* If we are currently idle, try to start the next message. */ 627*1da177e4SLinus Torvalds if (si_sm_result == SI_SM_IDLE) { 628*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 629*1da177e4SLinus Torvalds smi_info->idles++; 630*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 631*1da177e4SLinus Torvalds 632*1da177e4SLinus Torvalds si_sm_result = start_next_msg(smi_info); 633*1da177e4SLinus Torvalds if (si_sm_result != SI_SM_IDLE) 634*1da177e4SLinus Torvalds goto restart; 635*1da177e4SLinus Torvalds } 636*1da177e4SLinus Torvalds 637*1da177e4SLinus Torvalds if ((si_sm_result == SI_SM_IDLE) 638*1da177e4SLinus Torvalds && (atomic_read(&smi_info->req_events))) 639*1da177e4SLinus Torvalds { 640*1da177e4SLinus Torvalds /* We are idle and the upper layer requested that I fetch 641*1da177e4SLinus Torvalds events, so do so. */ 642*1da177e4SLinus Torvalds unsigned char msg[2]; 643*1da177e4SLinus Torvalds 644*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 645*1da177e4SLinus Torvalds smi_info->flag_fetches++; 646*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 647*1da177e4SLinus Torvalds 648*1da177e4SLinus Torvalds atomic_set(&smi_info->req_events, 0); 649*1da177e4SLinus Torvalds msg[0] = (IPMI_NETFN_APP_REQUEST << 2); 650*1da177e4SLinus Torvalds msg[1] = IPMI_GET_MSG_FLAGS_CMD; 651*1da177e4SLinus Torvalds 652*1da177e4SLinus Torvalds smi_info->handlers->start_transaction( 653*1da177e4SLinus Torvalds smi_info->si_sm, msg, 2); 654*1da177e4SLinus Torvalds smi_info->si_state = SI_GETTING_FLAGS; 655*1da177e4SLinus Torvalds goto restart; 656*1da177e4SLinus Torvalds } 657*1da177e4SLinus Torvalds 658*1da177e4SLinus Torvalds return si_sm_result; 659*1da177e4SLinus Torvalds } 660*1da177e4SLinus Torvalds 661*1da177e4SLinus Torvalds static void sender(void *send_info, 662*1da177e4SLinus Torvalds struct ipmi_smi_msg *msg, 663*1da177e4SLinus Torvalds int priority) 664*1da177e4SLinus Torvalds { 665*1da177e4SLinus Torvalds struct smi_info *smi_info = send_info; 666*1da177e4SLinus Torvalds enum si_sm_result result; 667*1da177e4SLinus Torvalds unsigned long flags; 668*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 669*1da177e4SLinus Torvalds struct timeval t; 670*1da177e4SLinus Torvalds #endif 671*1da177e4SLinus Torvalds 672*1da177e4SLinus Torvalds spin_lock_irqsave(&(smi_info->msg_lock), flags); 673*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 674*1da177e4SLinus Torvalds do_gettimeofday(&t); 675*1da177e4SLinus Torvalds printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); 676*1da177e4SLinus Torvalds #endif 677*1da177e4SLinus Torvalds 678*1da177e4SLinus Torvalds if (smi_info->run_to_completion) { 679*1da177e4SLinus Torvalds /* If we are running to completion, then throw it in 680*1da177e4SLinus Torvalds the list and run transactions until everything is 681*1da177e4SLinus Torvalds clear. Priority doesn't matter here. */ 682*1da177e4SLinus Torvalds list_add_tail(&(msg->link), &(smi_info->xmit_msgs)); 683*1da177e4SLinus Torvalds 684*1da177e4SLinus Torvalds /* We have to release the msg lock and claim the smi 685*1da177e4SLinus Torvalds lock in this case, because of race conditions. */ 686*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->msg_lock), flags); 687*1da177e4SLinus Torvalds 688*1da177e4SLinus Torvalds spin_lock_irqsave(&(smi_info->si_lock), flags); 689*1da177e4SLinus Torvalds result = smi_event_handler(smi_info, 0); 690*1da177e4SLinus Torvalds while (result != SI_SM_IDLE) { 691*1da177e4SLinus Torvalds udelay(SI_SHORT_TIMEOUT_USEC); 692*1da177e4SLinus Torvalds result = smi_event_handler(smi_info, 693*1da177e4SLinus Torvalds SI_SHORT_TIMEOUT_USEC); 694*1da177e4SLinus Torvalds } 695*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->si_lock), flags); 696*1da177e4SLinus Torvalds return; 697*1da177e4SLinus Torvalds } else { 698*1da177e4SLinus Torvalds if (priority > 0) { 699*1da177e4SLinus Torvalds list_add_tail(&(msg->link), &(smi_info->hp_xmit_msgs)); 700*1da177e4SLinus Torvalds } else { 701*1da177e4SLinus Torvalds list_add_tail(&(msg->link), &(smi_info->xmit_msgs)); 702*1da177e4SLinus Torvalds } 703*1da177e4SLinus Torvalds } 704*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->msg_lock), flags); 705*1da177e4SLinus Torvalds 706*1da177e4SLinus Torvalds spin_lock_irqsave(&(smi_info->si_lock), flags); 707*1da177e4SLinus Torvalds if ((smi_info->si_state == SI_NORMAL) 708*1da177e4SLinus Torvalds && (smi_info->curr_msg == NULL)) 709*1da177e4SLinus Torvalds { 710*1da177e4SLinus Torvalds start_next_msg(smi_info); 711*1da177e4SLinus Torvalds si_restart_short_timer(smi_info); 712*1da177e4SLinus Torvalds } 713*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->si_lock), flags); 714*1da177e4SLinus Torvalds } 715*1da177e4SLinus Torvalds 716*1da177e4SLinus Torvalds static void set_run_to_completion(void *send_info, int i_run_to_completion) 717*1da177e4SLinus Torvalds { 718*1da177e4SLinus Torvalds struct smi_info *smi_info = send_info; 719*1da177e4SLinus Torvalds enum si_sm_result result; 720*1da177e4SLinus Torvalds unsigned long flags; 721*1da177e4SLinus Torvalds 722*1da177e4SLinus Torvalds spin_lock_irqsave(&(smi_info->si_lock), flags); 723*1da177e4SLinus Torvalds 724*1da177e4SLinus Torvalds smi_info->run_to_completion = i_run_to_completion; 725*1da177e4SLinus Torvalds if (i_run_to_completion) { 726*1da177e4SLinus Torvalds result = smi_event_handler(smi_info, 0); 727*1da177e4SLinus Torvalds while (result != SI_SM_IDLE) { 728*1da177e4SLinus Torvalds udelay(SI_SHORT_TIMEOUT_USEC); 729*1da177e4SLinus Torvalds result = smi_event_handler(smi_info, 730*1da177e4SLinus Torvalds SI_SHORT_TIMEOUT_USEC); 731*1da177e4SLinus Torvalds } 732*1da177e4SLinus Torvalds } 733*1da177e4SLinus Torvalds 734*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->si_lock), flags); 735*1da177e4SLinus Torvalds } 736*1da177e4SLinus Torvalds 737*1da177e4SLinus Torvalds static void poll(void *send_info) 738*1da177e4SLinus Torvalds { 739*1da177e4SLinus Torvalds struct smi_info *smi_info = send_info; 740*1da177e4SLinus Torvalds 741*1da177e4SLinus Torvalds smi_event_handler(smi_info, 0); 742*1da177e4SLinus Torvalds } 743*1da177e4SLinus Torvalds 744*1da177e4SLinus Torvalds static void request_events(void *send_info) 745*1da177e4SLinus Torvalds { 746*1da177e4SLinus Torvalds struct smi_info *smi_info = send_info; 747*1da177e4SLinus Torvalds 748*1da177e4SLinus Torvalds atomic_set(&smi_info->req_events, 1); 749*1da177e4SLinus Torvalds } 750*1da177e4SLinus Torvalds 751*1da177e4SLinus Torvalds static int initialized = 0; 752*1da177e4SLinus Torvalds 753*1da177e4SLinus Torvalds /* Must be called with interrupts off and with the si_lock held. */ 754*1da177e4SLinus Torvalds static void si_restart_short_timer(struct smi_info *smi_info) 755*1da177e4SLinus Torvalds { 756*1da177e4SLinus Torvalds #if defined(CONFIG_HIGH_RES_TIMERS) 757*1da177e4SLinus Torvalds unsigned long flags; 758*1da177e4SLinus Torvalds unsigned long jiffies_now; 759*1da177e4SLinus Torvalds 760*1da177e4SLinus Torvalds if (del_timer(&(smi_info->si_timer))) { 761*1da177e4SLinus Torvalds /* If we don't delete the timer, then it will go off 762*1da177e4SLinus Torvalds immediately, anyway. So we only process if we 763*1da177e4SLinus Torvalds actually delete the timer. */ 764*1da177e4SLinus Torvalds 765*1da177e4SLinus Torvalds /* We already have irqsave on, so no need for it 766*1da177e4SLinus Torvalds here. */ 767*1da177e4SLinus Torvalds read_lock(&xtime_lock); 768*1da177e4SLinus Torvalds jiffies_now = jiffies; 769*1da177e4SLinus Torvalds smi_info->si_timer.expires = jiffies_now; 770*1da177e4SLinus Torvalds smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now); 771*1da177e4SLinus Torvalds 772*1da177e4SLinus Torvalds add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); 773*1da177e4SLinus Torvalds 774*1da177e4SLinus Torvalds add_timer(&(smi_info->si_timer)); 775*1da177e4SLinus Torvalds spin_lock_irqsave(&smi_info->count_lock, flags); 776*1da177e4SLinus Torvalds smi_info->timeout_restarts++; 777*1da177e4SLinus Torvalds spin_unlock_irqrestore(&smi_info->count_lock, flags); 778*1da177e4SLinus Torvalds } 779*1da177e4SLinus Torvalds #endif 780*1da177e4SLinus Torvalds } 781*1da177e4SLinus Torvalds 782*1da177e4SLinus Torvalds static void smi_timeout(unsigned long data) 783*1da177e4SLinus Torvalds { 784*1da177e4SLinus Torvalds struct smi_info *smi_info = (struct smi_info *) data; 785*1da177e4SLinus Torvalds enum si_sm_result smi_result; 786*1da177e4SLinus Torvalds unsigned long flags; 787*1da177e4SLinus Torvalds unsigned long jiffies_now; 788*1da177e4SLinus Torvalds unsigned long time_diff; 789*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 790*1da177e4SLinus Torvalds struct timeval t; 791*1da177e4SLinus Torvalds #endif 792*1da177e4SLinus Torvalds 793*1da177e4SLinus Torvalds if (smi_info->stop_operation) { 794*1da177e4SLinus Torvalds smi_info->timer_stopped = 1; 795*1da177e4SLinus Torvalds return; 796*1da177e4SLinus Torvalds } 797*1da177e4SLinus Torvalds 798*1da177e4SLinus Torvalds spin_lock_irqsave(&(smi_info->si_lock), flags); 799*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 800*1da177e4SLinus Torvalds do_gettimeofday(&t); 801*1da177e4SLinus Torvalds printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec); 802*1da177e4SLinus Torvalds #endif 803*1da177e4SLinus Torvalds jiffies_now = jiffies; 804*1da177e4SLinus Torvalds time_diff = ((jiffies_now - smi_info->last_timeout_jiffies) 805*1da177e4SLinus Torvalds * SI_USEC_PER_JIFFY); 806*1da177e4SLinus Torvalds smi_result = smi_event_handler(smi_info, time_diff); 807*1da177e4SLinus Torvalds 808*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->si_lock), flags); 809*1da177e4SLinus Torvalds 810*1da177e4SLinus Torvalds smi_info->last_timeout_jiffies = jiffies_now; 811*1da177e4SLinus Torvalds 812*1da177e4SLinus Torvalds if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { 813*1da177e4SLinus Torvalds /* Running with interrupts, only do long timeouts. */ 814*1da177e4SLinus Torvalds smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; 815*1da177e4SLinus Torvalds spin_lock_irqsave(&smi_info->count_lock, flags); 816*1da177e4SLinus Torvalds smi_info->long_timeouts++; 817*1da177e4SLinus Torvalds spin_unlock_irqrestore(&smi_info->count_lock, flags); 818*1da177e4SLinus Torvalds goto do_add_timer; 819*1da177e4SLinus Torvalds } 820*1da177e4SLinus Torvalds 821*1da177e4SLinus Torvalds /* If the state machine asks for a short delay, then shorten 822*1da177e4SLinus Torvalds the timer timeout. */ 823*1da177e4SLinus Torvalds if (smi_result == SI_SM_CALL_WITH_DELAY) { 824*1da177e4SLinus Torvalds spin_lock_irqsave(&smi_info->count_lock, flags); 825*1da177e4SLinus Torvalds smi_info->short_timeouts++; 826*1da177e4SLinus Torvalds spin_unlock_irqrestore(&smi_info->count_lock, flags); 827*1da177e4SLinus Torvalds #if defined(CONFIG_HIGH_RES_TIMERS) 828*1da177e4SLinus Torvalds read_lock(&xtime_lock); 829*1da177e4SLinus Torvalds smi_info->si_timer.expires = jiffies; 830*1da177e4SLinus Torvalds smi_info->si_timer.sub_expires 831*1da177e4SLinus Torvalds = get_arch_cycles(smi_info->si_timer.expires); 832*1da177e4SLinus Torvalds read_unlock(&xtime_lock); 833*1da177e4SLinus Torvalds add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); 834*1da177e4SLinus Torvalds #else 835*1da177e4SLinus Torvalds smi_info->si_timer.expires = jiffies + 1; 836*1da177e4SLinus Torvalds #endif 837*1da177e4SLinus Torvalds } else { 838*1da177e4SLinus Torvalds spin_lock_irqsave(&smi_info->count_lock, flags); 839*1da177e4SLinus Torvalds smi_info->long_timeouts++; 840*1da177e4SLinus Torvalds spin_unlock_irqrestore(&smi_info->count_lock, flags); 841*1da177e4SLinus Torvalds smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; 842*1da177e4SLinus Torvalds #if defined(CONFIG_HIGH_RES_TIMERS) 843*1da177e4SLinus Torvalds smi_info->si_timer.sub_expires = 0; 844*1da177e4SLinus Torvalds #endif 845*1da177e4SLinus Torvalds } 846*1da177e4SLinus Torvalds 847*1da177e4SLinus Torvalds do_add_timer: 848*1da177e4SLinus Torvalds add_timer(&(smi_info->si_timer)); 849*1da177e4SLinus Torvalds } 850*1da177e4SLinus Torvalds 851*1da177e4SLinus Torvalds static irqreturn_t si_irq_handler(int irq, void *data, struct pt_regs *regs) 852*1da177e4SLinus Torvalds { 853*1da177e4SLinus Torvalds struct smi_info *smi_info = data; 854*1da177e4SLinus Torvalds unsigned long flags; 855*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 856*1da177e4SLinus Torvalds struct timeval t; 857*1da177e4SLinus Torvalds #endif 858*1da177e4SLinus Torvalds 859*1da177e4SLinus Torvalds spin_lock_irqsave(&(smi_info->si_lock), flags); 860*1da177e4SLinus Torvalds 861*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 862*1da177e4SLinus Torvalds smi_info->interrupts++; 863*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 864*1da177e4SLinus Torvalds 865*1da177e4SLinus Torvalds if (smi_info->stop_operation) 866*1da177e4SLinus Torvalds goto out; 867*1da177e4SLinus Torvalds 868*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 869*1da177e4SLinus Torvalds do_gettimeofday(&t); 870*1da177e4SLinus Torvalds printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec); 871*1da177e4SLinus Torvalds #endif 872*1da177e4SLinus Torvalds smi_event_handler(smi_info, 0); 873*1da177e4SLinus Torvalds out: 874*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->si_lock), flags); 875*1da177e4SLinus Torvalds return IRQ_HANDLED; 876*1da177e4SLinus Torvalds } 877*1da177e4SLinus Torvalds 878*1da177e4SLinus Torvalds static struct ipmi_smi_handlers handlers = 879*1da177e4SLinus Torvalds { 880*1da177e4SLinus Torvalds .owner = THIS_MODULE, 881*1da177e4SLinus Torvalds .sender = sender, 882*1da177e4SLinus Torvalds .request_events = request_events, 883*1da177e4SLinus Torvalds .set_run_to_completion = set_run_to_completion, 884*1da177e4SLinus Torvalds .poll = poll, 885*1da177e4SLinus Torvalds }; 886*1da177e4SLinus Torvalds 887*1da177e4SLinus Torvalds /* There can be 4 IO ports passed in (with or without IRQs), 4 addresses, 888*1da177e4SLinus Torvalds a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS */ 889*1da177e4SLinus Torvalds 890*1da177e4SLinus Torvalds #define SI_MAX_PARMS 4 891*1da177e4SLinus Torvalds #define SI_MAX_DRIVERS ((SI_MAX_PARMS * 2) + 2) 892*1da177e4SLinus Torvalds static struct smi_info *smi_infos[SI_MAX_DRIVERS] = 893*1da177e4SLinus Torvalds { NULL, NULL, NULL, NULL }; 894*1da177e4SLinus Torvalds 895*1da177e4SLinus Torvalds #define DEVICE_NAME "ipmi_si" 896*1da177e4SLinus Torvalds 897*1da177e4SLinus Torvalds #define DEFAULT_KCS_IO_PORT 0xca2 898*1da177e4SLinus Torvalds #define DEFAULT_SMIC_IO_PORT 0xca9 899*1da177e4SLinus Torvalds #define DEFAULT_BT_IO_PORT 0xe4 900*1da177e4SLinus Torvalds #define DEFAULT_REGSPACING 1 901*1da177e4SLinus Torvalds 902*1da177e4SLinus Torvalds static int si_trydefaults = 1; 903*1da177e4SLinus Torvalds static char *si_type[SI_MAX_PARMS]; 904*1da177e4SLinus Torvalds #define MAX_SI_TYPE_STR 30 905*1da177e4SLinus Torvalds static char si_type_str[MAX_SI_TYPE_STR]; 906*1da177e4SLinus Torvalds static unsigned long addrs[SI_MAX_PARMS]; 907*1da177e4SLinus Torvalds static int num_addrs; 908*1da177e4SLinus Torvalds static unsigned int ports[SI_MAX_PARMS]; 909*1da177e4SLinus Torvalds static int num_ports; 910*1da177e4SLinus Torvalds static int irqs[SI_MAX_PARMS]; 911*1da177e4SLinus Torvalds static int num_irqs; 912*1da177e4SLinus Torvalds static int regspacings[SI_MAX_PARMS]; 913*1da177e4SLinus Torvalds static int num_regspacings = 0; 914*1da177e4SLinus Torvalds static int regsizes[SI_MAX_PARMS]; 915*1da177e4SLinus Torvalds static int num_regsizes = 0; 916*1da177e4SLinus Torvalds static int regshifts[SI_MAX_PARMS]; 917*1da177e4SLinus Torvalds static int num_regshifts = 0; 918*1da177e4SLinus Torvalds static int slave_addrs[SI_MAX_PARMS]; 919*1da177e4SLinus Torvalds static int num_slave_addrs = 0; 920*1da177e4SLinus Torvalds 921*1da177e4SLinus Torvalds 922*1da177e4SLinus Torvalds module_param_named(trydefaults, si_trydefaults, bool, 0); 923*1da177e4SLinus Torvalds MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the" 924*1da177e4SLinus Torvalds " default scan of the KCS and SMIC interface at the standard" 925*1da177e4SLinus Torvalds " address"); 926*1da177e4SLinus Torvalds module_param_string(type, si_type_str, MAX_SI_TYPE_STR, 0); 927*1da177e4SLinus Torvalds MODULE_PARM_DESC(type, "Defines the type of each interface, each" 928*1da177e4SLinus Torvalds " interface separated by commas. The types are 'kcs'," 929*1da177e4SLinus Torvalds " 'smic', and 'bt'. For example si_type=kcs,bt will set" 930*1da177e4SLinus Torvalds " the first interface to kcs and the second to bt"); 931*1da177e4SLinus Torvalds module_param_array(addrs, long, &num_addrs, 0); 932*1da177e4SLinus Torvalds MODULE_PARM_DESC(addrs, "Sets the memory address of each interface, the" 933*1da177e4SLinus Torvalds " addresses separated by commas. Only use if an interface" 934*1da177e4SLinus Torvalds " is in memory. Otherwise, set it to zero or leave" 935*1da177e4SLinus Torvalds " it blank."); 936*1da177e4SLinus Torvalds module_param_array(ports, int, &num_ports, 0); 937*1da177e4SLinus Torvalds MODULE_PARM_DESC(ports, "Sets the port address of each interface, the" 938*1da177e4SLinus Torvalds " addresses separated by commas. Only use if an interface" 939*1da177e4SLinus Torvalds " is a port. Otherwise, set it to zero or leave" 940*1da177e4SLinus Torvalds " it blank."); 941*1da177e4SLinus Torvalds module_param_array(irqs, int, &num_irqs, 0); 942*1da177e4SLinus Torvalds MODULE_PARM_DESC(irqs, "Sets the interrupt of each interface, the" 943*1da177e4SLinus Torvalds " addresses separated by commas. Only use if an interface" 944*1da177e4SLinus Torvalds " has an interrupt. Otherwise, set it to zero or leave" 945*1da177e4SLinus Torvalds " it blank."); 946*1da177e4SLinus Torvalds module_param_array(regspacings, int, &num_regspacings, 0); 947*1da177e4SLinus Torvalds MODULE_PARM_DESC(regspacings, "The number of bytes between the start address" 948*1da177e4SLinus Torvalds " and each successive register used by the interface. For" 949*1da177e4SLinus Torvalds " instance, if the start address is 0xca2 and the spacing" 950*1da177e4SLinus Torvalds " is 2, then the second address is at 0xca4. Defaults" 951*1da177e4SLinus Torvalds " to 1."); 952*1da177e4SLinus Torvalds module_param_array(regsizes, int, &num_regsizes, 0); 953*1da177e4SLinus Torvalds MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes." 954*1da177e4SLinus Torvalds " This should generally be 1, 2, 4, or 8 for an 8-bit," 955*1da177e4SLinus Torvalds " 16-bit, 32-bit, or 64-bit register. Use this if you" 956*1da177e4SLinus Torvalds " the 8-bit IPMI register has to be read from a larger" 957*1da177e4SLinus Torvalds " register."); 958*1da177e4SLinus Torvalds module_param_array(regshifts, int, &num_regshifts, 0); 959*1da177e4SLinus Torvalds MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the." 960*1da177e4SLinus Torvalds " IPMI register, in bits. For instance, if the data" 961*1da177e4SLinus Torvalds " is read from a 32-bit word and the IPMI data is in" 962*1da177e4SLinus Torvalds " bit 8-15, then the shift would be 8"); 963*1da177e4SLinus Torvalds module_param_array(slave_addrs, int, &num_slave_addrs, 0); 964*1da177e4SLinus Torvalds MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for" 965*1da177e4SLinus Torvalds " the controller. Normally this is 0x20, but can be" 966*1da177e4SLinus Torvalds " overridden by this parm. This is an array indexed" 967*1da177e4SLinus Torvalds " by interface number."); 968*1da177e4SLinus Torvalds 969*1da177e4SLinus Torvalds 970*1da177e4SLinus Torvalds #define IPMI_MEM_ADDR_SPACE 1 971*1da177e4SLinus Torvalds #define IPMI_IO_ADDR_SPACE 2 972*1da177e4SLinus Torvalds 973*1da177e4SLinus Torvalds #if defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_X86) || defined(CONFIG_PCI) 974*1da177e4SLinus Torvalds static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr) 975*1da177e4SLinus Torvalds { 976*1da177e4SLinus Torvalds int i; 977*1da177e4SLinus Torvalds 978*1da177e4SLinus Torvalds for (i = 0; i < SI_MAX_PARMS; ++i) { 979*1da177e4SLinus Torvalds /* Don't check our address. */ 980*1da177e4SLinus Torvalds if (i == intf) 981*1da177e4SLinus Torvalds continue; 982*1da177e4SLinus Torvalds if (si_type[i] != NULL) { 983*1da177e4SLinus Torvalds if ((addr_space == IPMI_MEM_ADDR_SPACE && 984*1da177e4SLinus Torvalds base_addr == addrs[i]) || 985*1da177e4SLinus Torvalds (addr_space == IPMI_IO_ADDR_SPACE && 986*1da177e4SLinus Torvalds base_addr == ports[i])) 987*1da177e4SLinus Torvalds return 0; 988*1da177e4SLinus Torvalds } 989*1da177e4SLinus Torvalds else 990*1da177e4SLinus Torvalds break; 991*1da177e4SLinus Torvalds } 992*1da177e4SLinus Torvalds 993*1da177e4SLinus Torvalds return 1; 994*1da177e4SLinus Torvalds } 995*1da177e4SLinus Torvalds #endif 996*1da177e4SLinus Torvalds 997*1da177e4SLinus Torvalds static int std_irq_setup(struct smi_info *info) 998*1da177e4SLinus Torvalds { 999*1da177e4SLinus Torvalds int rv; 1000*1da177e4SLinus Torvalds 1001*1da177e4SLinus Torvalds if (!info->irq) 1002*1da177e4SLinus Torvalds return 0; 1003*1da177e4SLinus Torvalds 1004*1da177e4SLinus Torvalds rv = request_irq(info->irq, 1005*1da177e4SLinus Torvalds si_irq_handler, 1006*1da177e4SLinus Torvalds SA_INTERRUPT, 1007*1da177e4SLinus Torvalds DEVICE_NAME, 1008*1da177e4SLinus Torvalds info); 1009*1da177e4SLinus Torvalds if (rv) { 1010*1da177e4SLinus Torvalds printk(KERN_WARNING 1011*1da177e4SLinus Torvalds "ipmi_si: %s unable to claim interrupt %d," 1012*1da177e4SLinus Torvalds " running polled\n", 1013*1da177e4SLinus Torvalds DEVICE_NAME, info->irq); 1014*1da177e4SLinus Torvalds info->irq = 0; 1015*1da177e4SLinus Torvalds } else { 1016*1da177e4SLinus Torvalds printk(" Using irq %d\n", info->irq); 1017*1da177e4SLinus Torvalds } 1018*1da177e4SLinus Torvalds 1019*1da177e4SLinus Torvalds return rv; 1020*1da177e4SLinus Torvalds } 1021*1da177e4SLinus Torvalds 1022*1da177e4SLinus Torvalds static void std_irq_cleanup(struct smi_info *info) 1023*1da177e4SLinus Torvalds { 1024*1da177e4SLinus Torvalds if (!info->irq) 1025*1da177e4SLinus Torvalds return; 1026*1da177e4SLinus Torvalds 1027*1da177e4SLinus Torvalds free_irq(info->irq, info); 1028*1da177e4SLinus Torvalds } 1029*1da177e4SLinus Torvalds 1030*1da177e4SLinus Torvalds static unsigned char port_inb(struct si_sm_io *io, unsigned int offset) 1031*1da177e4SLinus Torvalds { 1032*1da177e4SLinus Torvalds unsigned int *addr = io->info; 1033*1da177e4SLinus Torvalds 1034*1da177e4SLinus Torvalds return inb((*addr)+(offset*io->regspacing)); 1035*1da177e4SLinus Torvalds } 1036*1da177e4SLinus Torvalds 1037*1da177e4SLinus Torvalds static void port_outb(struct si_sm_io *io, unsigned int offset, 1038*1da177e4SLinus Torvalds unsigned char b) 1039*1da177e4SLinus Torvalds { 1040*1da177e4SLinus Torvalds unsigned int *addr = io->info; 1041*1da177e4SLinus Torvalds 1042*1da177e4SLinus Torvalds outb(b, (*addr)+(offset * io->regspacing)); 1043*1da177e4SLinus Torvalds } 1044*1da177e4SLinus Torvalds 1045*1da177e4SLinus Torvalds static unsigned char port_inw(struct si_sm_io *io, unsigned int offset) 1046*1da177e4SLinus Torvalds { 1047*1da177e4SLinus Torvalds unsigned int *addr = io->info; 1048*1da177e4SLinus Torvalds 1049*1da177e4SLinus Torvalds return (inw((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; 1050*1da177e4SLinus Torvalds } 1051*1da177e4SLinus Torvalds 1052*1da177e4SLinus Torvalds static void port_outw(struct si_sm_io *io, unsigned int offset, 1053*1da177e4SLinus Torvalds unsigned char b) 1054*1da177e4SLinus Torvalds { 1055*1da177e4SLinus Torvalds unsigned int *addr = io->info; 1056*1da177e4SLinus Torvalds 1057*1da177e4SLinus Torvalds outw(b << io->regshift, (*addr)+(offset * io->regspacing)); 1058*1da177e4SLinus Torvalds } 1059*1da177e4SLinus Torvalds 1060*1da177e4SLinus Torvalds static unsigned char port_inl(struct si_sm_io *io, unsigned int offset) 1061*1da177e4SLinus Torvalds { 1062*1da177e4SLinus Torvalds unsigned int *addr = io->info; 1063*1da177e4SLinus Torvalds 1064*1da177e4SLinus Torvalds return (inl((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff; 1065*1da177e4SLinus Torvalds } 1066*1da177e4SLinus Torvalds 1067*1da177e4SLinus Torvalds static void port_outl(struct si_sm_io *io, unsigned int offset, 1068*1da177e4SLinus Torvalds unsigned char b) 1069*1da177e4SLinus Torvalds { 1070*1da177e4SLinus Torvalds unsigned int *addr = io->info; 1071*1da177e4SLinus Torvalds 1072*1da177e4SLinus Torvalds outl(b << io->regshift, (*addr)+(offset * io->regspacing)); 1073*1da177e4SLinus Torvalds } 1074*1da177e4SLinus Torvalds 1075*1da177e4SLinus Torvalds static void port_cleanup(struct smi_info *info) 1076*1da177e4SLinus Torvalds { 1077*1da177e4SLinus Torvalds unsigned int *addr = info->io.info; 1078*1da177e4SLinus Torvalds int mapsize; 1079*1da177e4SLinus Torvalds 1080*1da177e4SLinus Torvalds if (addr && (*addr)) { 1081*1da177e4SLinus Torvalds mapsize = ((info->io_size * info->io.regspacing) 1082*1da177e4SLinus Torvalds - (info->io.regspacing - info->io.regsize)); 1083*1da177e4SLinus Torvalds 1084*1da177e4SLinus Torvalds release_region (*addr, mapsize); 1085*1da177e4SLinus Torvalds } 1086*1da177e4SLinus Torvalds kfree(info); 1087*1da177e4SLinus Torvalds } 1088*1da177e4SLinus Torvalds 1089*1da177e4SLinus Torvalds static int port_setup(struct smi_info *info) 1090*1da177e4SLinus Torvalds { 1091*1da177e4SLinus Torvalds unsigned int *addr = info->io.info; 1092*1da177e4SLinus Torvalds int mapsize; 1093*1da177e4SLinus Torvalds 1094*1da177e4SLinus Torvalds if (!addr || (!*addr)) 1095*1da177e4SLinus Torvalds return -ENODEV; 1096*1da177e4SLinus Torvalds 1097*1da177e4SLinus Torvalds info->io_cleanup = port_cleanup; 1098*1da177e4SLinus Torvalds 1099*1da177e4SLinus Torvalds /* Figure out the actual inb/inw/inl/etc routine to use based 1100*1da177e4SLinus Torvalds upon the register size. */ 1101*1da177e4SLinus Torvalds switch (info->io.regsize) { 1102*1da177e4SLinus Torvalds case 1: 1103*1da177e4SLinus Torvalds info->io.inputb = port_inb; 1104*1da177e4SLinus Torvalds info->io.outputb = port_outb; 1105*1da177e4SLinus Torvalds break; 1106*1da177e4SLinus Torvalds case 2: 1107*1da177e4SLinus Torvalds info->io.inputb = port_inw; 1108*1da177e4SLinus Torvalds info->io.outputb = port_outw; 1109*1da177e4SLinus Torvalds break; 1110*1da177e4SLinus Torvalds case 4: 1111*1da177e4SLinus Torvalds info->io.inputb = port_inl; 1112*1da177e4SLinus Torvalds info->io.outputb = port_outl; 1113*1da177e4SLinus Torvalds break; 1114*1da177e4SLinus Torvalds default: 1115*1da177e4SLinus Torvalds printk("ipmi_si: Invalid register size: %d\n", 1116*1da177e4SLinus Torvalds info->io.regsize); 1117*1da177e4SLinus Torvalds return -EINVAL; 1118*1da177e4SLinus Torvalds } 1119*1da177e4SLinus Torvalds 1120*1da177e4SLinus Torvalds /* Calculate the total amount of memory to claim. This is an 1121*1da177e4SLinus Torvalds * unusual looking calculation, but it avoids claiming any 1122*1da177e4SLinus Torvalds * more memory than it has to. It will claim everything 1123*1da177e4SLinus Torvalds * between the first address to the end of the last full 1124*1da177e4SLinus Torvalds * register. */ 1125*1da177e4SLinus Torvalds mapsize = ((info->io_size * info->io.regspacing) 1126*1da177e4SLinus Torvalds - (info->io.regspacing - info->io.regsize)); 1127*1da177e4SLinus Torvalds 1128*1da177e4SLinus Torvalds if (request_region(*addr, mapsize, DEVICE_NAME) == NULL) 1129*1da177e4SLinus Torvalds return -EIO; 1130*1da177e4SLinus Torvalds return 0; 1131*1da177e4SLinus Torvalds } 1132*1da177e4SLinus Torvalds 1133*1da177e4SLinus Torvalds static int try_init_port(int intf_num, struct smi_info **new_info) 1134*1da177e4SLinus Torvalds { 1135*1da177e4SLinus Torvalds struct smi_info *info; 1136*1da177e4SLinus Torvalds 1137*1da177e4SLinus Torvalds if (!ports[intf_num]) 1138*1da177e4SLinus Torvalds return -ENODEV; 1139*1da177e4SLinus Torvalds 1140*1da177e4SLinus Torvalds if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, 1141*1da177e4SLinus Torvalds ports[intf_num])) 1142*1da177e4SLinus Torvalds return -ENODEV; 1143*1da177e4SLinus Torvalds 1144*1da177e4SLinus Torvalds info = kmalloc(sizeof(*info), GFP_KERNEL); 1145*1da177e4SLinus Torvalds if (!info) { 1146*1da177e4SLinus Torvalds printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); 1147*1da177e4SLinus Torvalds return -ENOMEM; 1148*1da177e4SLinus Torvalds } 1149*1da177e4SLinus Torvalds memset(info, 0, sizeof(*info)); 1150*1da177e4SLinus Torvalds 1151*1da177e4SLinus Torvalds info->io_setup = port_setup; 1152*1da177e4SLinus Torvalds info->io.info = &(ports[intf_num]); 1153*1da177e4SLinus Torvalds info->io.addr = NULL; 1154*1da177e4SLinus Torvalds info->io.regspacing = regspacings[intf_num]; 1155*1da177e4SLinus Torvalds if (!info->io.regspacing) 1156*1da177e4SLinus Torvalds info->io.regspacing = DEFAULT_REGSPACING; 1157*1da177e4SLinus Torvalds info->io.regsize = regsizes[intf_num]; 1158*1da177e4SLinus Torvalds if (!info->io.regsize) 1159*1da177e4SLinus Torvalds info->io.regsize = DEFAULT_REGSPACING; 1160*1da177e4SLinus Torvalds info->io.regshift = regshifts[intf_num]; 1161*1da177e4SLinus Torvalds info->irq = 0; 1162*1da177e4SLinus Torvalds info->irq_setup = NULL; 1163*1da177e4SLinus Torvalds *new_info = info; 1164*1da177e4SLinus Torvalds 1165*1da177e4SLinus Torvalds if (si_type[intf_num] == NULL) 1166*1da177e4SLinus Torvalds si_type[intf_num] = "kcs"; 1167*1da177e4SLinus Torvalds 1168*1da177e4SLinus Torvalds printk("ipmi_si: Trying \"%s\" at I/O port 0x%x\n", 1169*1da177e4SLinus Torvalds si_type[intf_num], ports[intf_num]); 1170*1da177e4SLinus Torvalds return 0; 1171*1da177e4SLinus Torvalds } 1172*1da177e4SLinus Torvalds 1173*1da177e4SLinus Torvalds static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset) 1174*1da177e4SLinus Torvalds { 1175*1da177e4SLinus Torvalds return readb((io->addr)+(offset * io->regspacing)); 1176*1da177e4SLinus Torvalds } 1177*1da177e4SLinus Torvalds 1178*1da177e4SLinus Torvalds static void mem_outb(struct si_sm_io *io, unsigned int offset, 1179*1da177e4SLinus Torvalds unsigned char b) 1180*1da177e4SLinus Torvalds { 1181*1da177e4SLinus Torvalds writeb(b, (io->addr)+(offset * io->regspacing)); 1182*1da177e4SLinus Torvalds } 1183*1da177e4SLinus Torvalds 1184*1da177e4SLinus Torvalds static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset) 1185*1da177e4SLinus Torvalds { 1186*1da177e4SLinus Torvalds return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) 1187*1da177e4SLinus Torvalds && 0xff; 1188*1da177e4SLinus Torvalds } 1189*1da177e4SLinus Torvalds 1190*1da177e4SLinus Torvalds static void mem_outw(struct si_sm_io *io, unsigned int offset, 1191*1da177e4SLinus Torvalds unsigned char b) 1192*1da177e4SLinus Torvalds { 1193*1da177e4SLinus Torvalds writeb(b << io->regshift, (io->addr)+(offset * io->regspacing)); 1194*1da177e4SLinus Torvalds } 1195*1da177e4SLinus Torvalds 1196*1da177e4SLinus Torvalds static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset) 1197*1da177e4SLinus Torvalds { 1198*1da177e4SLinus Torvalds return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) 1199*1da177e4SLinus Torvalds && 0xff; 1200*1da177e4SLinus Torvalds } 1201*1da177e4SLinus Torvalds 1202*1da177e4SLinus Torvalds static void mem_outl(struct si_sm_io *io, unsigned int offset, 1203*1da177e4SLinus Torvalds unsigned char b) 1204*1da177e4SLinus Torvalds { 1205*1da177e4SLinus Torvalds writel(b << io->regshift, (io->addr)+(offset * io->regspacing)); 1206*1da177e4SLinus Torvalds } 1207*1da177e4SLinus Torvalds 1208*1da177e4SLinus Torvalds #ifdef readq 1209*1da177e4SLinus Torvalds static unsigned char mem_inq(struct si_sm_io *io, unsigned int offset) 1210*1da177e4SLinus Torvalds { 1211*1da177e4SLinus Torvalds return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift) 1212*1da177e4SLinus Torvalds && 0xff; 1213*1da177e4SLinus Torvalds } 1214*1da177e4SLinus Torvalds 1215*1da177e4SLinus Torvalds static void mem_outq(struct si_sm_io *io, unsigned int offset, 1216*1da177e4SLinus Torvalds unsigned char b) 1217*1da177e4SLinus Torvalds { 1218*1da177e4SLinus Torvalds writeq(b << io->regshift, (io->addr)+(offset * io->regspacing)); 1219*1da177e4SLinus Torvalds } 1220*1da177e4SLinus Torvalds #endif 1221*1da177e4SLinus Torvalds 1222*1da177e4SLinus Torvalds static void mem_cleanup(struct smi_info *info) 1223*1da177e4SLinus Torvalds { 1224*1da177e4SLinus Torvalds unsigned long *addr = info->io.info; 1225*1da177e4SLinus Torvalds int mapsize; 1226*1da177e4SLinus Torvalds 1227*1da177e4SLinus Torvalds if (info->io.addr) { 1228*1da177e4SLinus Torvalds iounmap(info->io.addr); 1229*1da177e4SLinus Torvalds 1230*1da177e4SLinus Torvalds mapsize = ((info->io_size * info->io.regspacing) 1231*1da177e4SLinus Torvalds - (info->io.regspacing - info->io.regsize)); 1232*1da177e4SLinus Torvalds 1233*1da177e4SLinus Torvalds release_mem_region(*addr, mapsize); 1234*1da177e4SLinus Torvalds } 1235*1da177e4SLinus Torvalds kfree(info); 1236*1da177e4SLinus Torvalds } 1237*1da177e4SLinus Torvalds 1238*1da177e4SLinus Torvalds static int mem_setup(struct smi_info *info) 1239*1da177e4SLinus Torvalds { 1240*1da177e4SLinus Torvalds unsigned long *addr = info->io.info; 1241*1da177e4SLinus Torvalds int mapsize; 1242*1da177e4SLinus Torvalds 1243*1da177e4SLinus Torvalds if (!addr || (!*addr)) 1244*1da177e4SLinus Torvalds return -ENODEV; 1245*1da177e4SLinus Torvalds 1246*1da177e4SLinus Torvalds info->io_cleanup = mem_cleanup; 1247*1da177e4SLinus Torvalds 1248*1da177e4SLinus Torvalds /* Figure out the actual readb/readw/readl/etc routine to use based 1249*1da177e4SLinus Torvalds upon the register size. */ 1250*1da177e4SLinus Torvalds switch (info->io.regsize) { 1251*1da177e4SLinus Torvalds case 1: 1252*1da177e4SLinus Torvalds info->io.inputb = mem_inb; 1253*1da177e4SLinus Torvalds info->io.outputb = mem_outb; 1254*1da177e4SLinus Torvalds break; 1255*1da177e4SLinus Torvalds case 2: 1256*1da177e4SLinus Torvalds info->io.inputb = mem_inw; 1257*1da177e4SLinus Torvalds info->io.outputb = mem_outw; 1258*1da177e4SLinus Torvalds break; 1259*1da177e4SLinus Torvalds case 4: 1260*1da177e4SLinus Torvalds info->io.inputb = mem_inl; 1261*1da177e4SLinus Torvalds info->io.outputb = mem_outl; 1262*1da177e4SLinus Torvalds break; 1263*1da177e4SLinus Torvalds #ifdef readq 1264*1da177e4SLinus Torvalds case 8: 1265*1da177e4SLinus Torvalds info->io.inputb = mem_inq; 1266*1da177e4SLinus Torvalds info->io.outputb = mem_outq; 1267*1da177e4SLinus Torvalds break; 1268*1da177e4SLinus Torvalds #endif 1269*1da177e4SLinus Torvalds default: 1270*1da177e4SLinus Torvalds printk("ipmi_si: Invalid register size: %d\n", 1271*1da177e4SLinus Torvalds info->io.regsize); 1272*1da177e4SLinus Torvalds return -EINVAL; 1273*1da177e4SLinus Torvalds } 1274*1da177e4SLinus Torvalds 1275*1da177e4SLinus Torvalds /* Calculate the total amount of memory to claim. This is an 1276*1da177e4SLinus Torvalds * unusual looking calculation, but it avoids claiming any 1277*1da177e4SLinus Torvalds * more memory than it has to. It will claim everything 1278*1da177e4SLinus Torvalds * between the first address to the end of the last full 1279*1da177e4SLinus Torvalds * register. */ 1280*1da177e4SLinus Torvalds mapsize = ((info->io_size * info->io.regspacing) 1281*1da177e4SLinus Torvalds - (info->io.regspacing - info->io.regsize)); 1282*1da177e4SLinus Torvalds 1283*1da177e4SLinus Torvalds if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL) 1284*1da177e4SLinus Torvalds return -EIO; 1285*1da177e4SLinus Torvalds 1286*1da177e4SLinus Torvalds info->io.addr = ioremap(*addr, mapsize); 1287*1da177e4SLinus Torvalds if (info->io.addr == NULL) { 1288*1da177e4SLinus Torvalds release_mem_region(*addr, mapsize); 1289*1da177e4SLinus Torvalds return -EIO; 1290*1da177e4SLinus Torvalds } 1291*1da177e4SLinus Torvalds return 0; 1292*1da177e4SLinus Torvalds } 1293*1da177e4SLinus Torvalds 1294*1da177e4SLinus Torvalds static int try_init_mem(int intf_num, struct smi_info **new_info) 1295*1da177e4SLinus Torvalds { 1296*1da177e4SLinus Torvalds struct smi_info *info; 1297*1da177e4SLinus Torvalds 1298*1da177e4SLinus Torvalds if (!addrs[intf_num]) 1299*1da177e4SLinus Torvalds return -ENODEV; 1300*1da177e4SLinus Torvalds 1301*1da177e4SLinus Torvalds if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, 1302*1da177e4SLinus Torvalds addrs[intf_num])) 1303*1da177e4SLinus Torvalds return -ENODEV; 1304*1da177e4SLinus Torvalds 1305*1da177e4SLinus Torvalds info = kmalloc(sizeof(*info), GFP_KERNEL); 1306*1da177e4SLinus Torvalds if (!info) { 1307*1da177e4SLinus Torvalds printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); 1308*1da177e4SLinus Torvalds return -ENOMEM; 1309*1da177e4SLinus Torvalds } 1310*1da177e4SLinus Torvalds memset(info, 0, sizeof(*info)); 1311*1da177e4SLinus Torvalds 1312*1da177e4SLinus Torvalds info->io_setup = mem_setup; 1313*1da177e4SLinus Torvalds info->io.info = &addrs[intf_num]; 1314*1da177e4SLinus Torvalds info->io.addr = NULL; 1315*1da177e4SLinus Torvalds info->io.regspacing = regspacings[intf_num]; 1316*1da177e4SLinus Torvalds if (!info->io.regspacing) 1317*1da177e4SLinus Torvalds info->io.regspacing = DEFAULT_REGSPACING; 1318*1da177e4SLinus Torvalds info->io.regsize = regsizes[intf_num]; 1319*1da177e4SLinus Torvalds if (!info->io.regsize) 1320*1da177e4SLinus Torvalds info->io.regsize = DEFAULT_REGSPACING; 1321*1da177e4SLinus Torvalds info->io.regshift = regshifts[intf_num]; 1322*1da177e4SLinus Torvalds info->irq = 0; 1323*1da177e4SLinus Torvalds info->irq_setup = NULL; 1324*1da177e4SLinus Torvalds *new_info = info; 1325*1da177e4SLinus Torvalds 1326*1da177e4SLinus Torvalds if (si_type[intf_num] == NULL) 1327*1da177e4SLinus Torvalds si_type[intf_num] = "kcs"; 1328*1da177e4SLinus Torvalds 1329*1da177e4SLinus Torvalds printk("ipmi_si: Trying \"%s\" at memory address 0x%lx\n", 1330*1da177e4SLinus Torvalds si_type[intf_num], addrs[intf_num]); 1331*1da177e4SLinus Torvalds return 0; 1332*1da177e4SLinus Torvalds } 1333*1da177e4SLinus Torvalds 1334*1da177e4SLinus Torvalds 1335*1da177e4SLinus Torvalds #ifdef CONFIG_ACPI_INTERPRETER 1336*1da177e4SLinus Torvalds 1337*1da177e4SLinus Torvalds #include <linux/acpi.h> 1338*1da177e4SLinus Torvalds 1339*1da177e4SLinus Torvalds /* Once we get an ACPI failure, we don't try any more, because we go 1340*1da177e4SLinus Torvalds through the tables sequentially. Once we don't find a table, there 1341*1da177e4SLinus Torvalds are no more. */ 1342*1da177e4SLinus Torvalds static int acpi_failure = 0; 1343*1da177e4SLinus Torvalds 1344*1da177e4SLinus Torvalds /* For GPE-type interrupts. */ 1345*1da177e4SLinus Torvalds static u32 ipmi_acpi_gpe(void *context) 1346*1da177e4SLinus Torvalds { 1347*1da177e4SLinus Torvalds struct smi_info *smi_info = context; 1348*1da177e4SLinus Torvalds unsigned long flags; 1349*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 1350*1da177e4SLinus Torvalds struct timeval t; 1351*1da177e4SLinus Torvalds #endif 1352*1da177e4SLinus Torvalds 1353*1da177e4SLinus Torvalds spin_lock_irqsave(&(smi_info->si_lock), flags); 1354*1da177e4SLinus Torvalds 1355*1da177e4SLinus Torvalds spin_lock(&smi_info->count_lock); 1356*1da177e4SLinus Torvalds smi_info->interrupts++; 1357*1da177e4SLinus Torvalds spin_unlock(&smi_info->count_lock); 1358*1da177e4SLinus Torvalds 1359*1da177e4SLinus Torvalds if (smi_info->stop_operation) 1360*1da177e4SLinus Torvalds goto out; 1361*1da177e4SLinus Torvalds 1362*1da177e4SLinus Torvalds #ifdef DEBUG_TIMING 1363*1da177e4SLinus Torvalds do_gettimeofday(&t); 1364*1da177e4SLinus Torvalds printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec); 1365*1da177e4SLinus Torvalds #endif 1366*1da177e4SLinus Torvalds smi_event_handler(smi_info, 0); 1367*1da177e4SLinus Torvalds out: 1368*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(smi_info->si_lock), flags); 1369*1da177e4SLinus Torvalds 1370*1da177e4SLinus Torvalds return ACPI_INTERRUPT_HANDLED; 1371*1da177e4SLinus Torvalds } 1372*1da177e4SLinus Torvalds 1373*1da177e4SLinus Torvalds static int acpi_gpe_irq_setup(struct smi_info *info) 1374*1da177e4SLinus Torvalds { 1375*1da177e4SLinus Torvalds acpi_status status; 1376*1da177e4SLinus Torvalds 1377*1da177e4SLinus Torvalds if (!info->irq) 1378*1da177e4SLinus Torvalds return 0; 1379*1da177e4SLinus Torvalds 1380*1da177e4SLinus Torvalds /* FIXME - is level triggered right? */ 1381*1da177e4SLinus Torvalds status = acpi_install_gpe_handler(NULL, 1382*1da177e4SLinus Torvalds info->irq, 1383*1da177e4SLinus Torvalds ACPI_GPE_LEVEL_TRIGGERED, 1384*1da177e4SLinus Torvalds &ipmi_acpi_gpe, 1385*1da177e4SLinus Torvalds info); 1386*1da177e4SLinus Torvalds if (status != AE_OK) { 1387*1da177e4SLinus Torvalds printk(KERN_WARNING 1388*1da177e4SLinus Torvalds "ipmi_si: %s unable to claim ACPI GPE %d," 1389*1da177e4SLinus Torvalds " running polled\n", 1390*1da177e4SLinus Torvalds DEVICE_NAME, info->irq); 1391*1da177e4SLinus Torvalds info->irq = 0; 1392*1da177e4SLinus Torvalds return -EINVAL; 1393*1da177e4SLinus Torvalds } else { 1394*1da177e4SLinus Torvalds printk(" Using ACPI GPE %d\n", info->irq); 1395*1da177e4SLinus Torvalds return 0; 1396*1da177e4SLinus Torvalds } 1397*1da177e4SLinus Torvalds } 1398*1da177e4SLinus Torvalds 1399*1da177e4SLinus Torvalds static void acpi_gpe_irq_cleanup(struct smi_info *info) 1400*1da177e4SLinus Torvalds { 1401*1da177e4SLinus Torvalds if (!info->irq) 1402*1da177e4SLinus Torvalds return; 1403*1da177e4SLinus Torvalds 1404*1da177e4SLinus Torvalds acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); 1405*1da177e4SLinus Torvalds } 1406*1da177e4SLinus Torvalds 1407*1da177e4SLinus Torvalds /* 1408*1da177e4SLinus Torvalds * Defined at 1409*1da177e4SLinus Torvalds * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf 1410*1da177e4SLinus Torvalds */ 1411*1da177e4SLinus Torvalds struct SPMITable { 1412*1da177e4SLinus Torvalds s8 Signature[4]; 1413*1da177e4SLinus Torvalds u32 Length; 1414*1da177e4SLinus Torvalds u8 Revision; 1415*1da177e4SLinus Torvalds u8 Checksum; 1416*1da177e4SLinus Torvalds s8 OEMID[6]; 1417*1da177e4SLinus Torvalds s8 OEMTableID[8]; 1418*1da177e4SLinus Torvalds s8 OEMRevision[4]; 1419*1da177e4SLinus Torvalds s8 CreatorID[4]; 1420*1da177e4SLinus Torvalds s8 CreatorRevision[4]; 1421*1da177e4SLinus Torvalds u8 InterfaceType; 1422*1da177e4SLinus Torvalds u8 IPMIlegacy; 1423*1da177e4SLinus Torvalds s16 SpecificationRevision; 1424*1da177e4SLinus Torvalds 1425*1da177e4SLinus Torvalds /* 1426*1da177e4SLinus Torvalds * Bit 0 - SCI interrupt supported 1427*1da177e4SLinus Torvalds * Bit 1 - I/O APIC/SAPIC 1428*1da177e4SLinus Torvalds */ 1429*1da177e4SLinus Torvalds u8 InterruptType; 1430*1da177e4SLinus Torvalds 1431*1da177e4SLinus Torvalds /* If bit 0 of InterruptType is set, then this is the SCI 1432*1da177e4SLinus Torvalds interrupt in the GPEx_STS register. */ 1433*1da177e4SLinus Torvalds u8 GPE; 1434*1da177e4SLinus Torvalds 1435*1da177e4SLinus Torvalds s16 Reserved; 1436*1da177e4SLinus Torvalds 1437*1da177e4SLinus Torvalds /* If bit 1 of InterruptType is set, then this is the I/O 1438*1da177e4SLinus Torvalds APIC/SAPIC interrupt. */ 1439*1da177e4SLinus Torvalds u32 GlobalSystemInterrupt; 1440*1da177e4SLinus Torvalds 1441*1da177e4SLinus Torvalds /* The actual register address. */ 1442*1da177e4SLinus Torvalds struct acpi_generic_address addr; 1443*1da177e4SLinus Torvalds 1444*1da177e4SLinus Torvalds u8 UID[4]; 1445*1da177e4SLinus Torvalds 1446*1da177e4SLinus Torvalds s8 spmi_id[1]; /* A '\0' terminated array starts here. */ 1447*1da177e4SLinus Torvalds }; 1448*1da177e4SLinus Torvalds 1449*1da177e4SLinus Torvalds static int try_init_acpi(int intf_num, struct smi_info **new_info) 1450*1da177e4SLinus Torvalds { 1451*1da177e4SLinus Torvalds struct smi_info *info; 1452*1da177e4SLinus Torvalds acpi_status status; 1453*1da177e4SLinus Torvalds struct SPMITable *spmi; 1454*1da177e4SLinus Torvalds char *io_type; 1455*1da177e4SLinus Torvalds u8 addr_space; 1456*1da177e4SLinus Torvalds 1457*1da177e4SLinus Torvalds if (acpi_failure) 1458*1da177e4SLinus Torvalds return -ENODEV; 1459*1da177e4SLinus Torvalds 1460*1da177e4SLinus Torvalds status = acpi_get_firmware_table("SPMI", intf_num+1, 1461*1da177e4SLinus Torvalds ACPI_LOGICAL_ADDRESSING, 1462*1da177e4SLinus Torvalds (struct acpi_table_header **) &spmi); 1463*1da177e4SLinus Torvalds if (status != AE_OK) { 1464*1da177e4SLinus Torvalds acpi_failure = 1; 1465*1da177e4SLinus Torvalds return -ENODEV; 1466*1da177e4SLinus Torvalds } 1467*1da177e4SLinus Torvalds 1468*1da177e4SLinus Torvalds if (spmi->IPMIlegacy != 1) { 1469*1da177e4SLinus Torvalds printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy); 1470*1da177e4SLinus Torvalds return -ENODEV; 1471*1da177e4SLinus Torvalds } 1472*1da177e4SLinus Torvalds 1473*1da177e4SLinus Torvalds if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 1474*1da177e4SLinus Torvalds addr_space = IPMI_MEM_ADDR_SPACE; 1475*1da177e4SLinus Torvalds else 1476*1da177e4SLinus Torvalds addr_space = IPMI_IO_ADDR_SPACE; 1477*1da177e4SLinus Torvalds if (!is_new_interface(-1, addr_space, spmi->addr.address)) 1478*1da177e4SLinus Torvalds return -ENODEV; 1479*1da177e4SLinus Torvalds 1480*1da177e4SLinus Torvalds if (!spmi->addr.register_bit_width) { 1481*1da177e4SLinus Torvalds acpi_failure = 1; 1482*1da177e4SLinus Torvalds return -ENODEV; 1483*1da177e4SLinus Torvalds } 1484*1da177e4SLinus Torvalds 1485*1da177e4SLinus Torvalds /* Figure out the interface type. */ 1486*1da177e4SLinus Torvalds switch (spmi->InterfaceType) 1487*1da177e4SLinus Torvalds { 1488*1da177e4SLinus Torvalds case 1: /* KCS */ 1489*1da177e4SLinus Torvalds si_type[intf_num] = "kcs"; 1490*1da177e4SLinus Torvalds break; 1491*1da177e4SLinus Torvalds 1492*1da177e4SLinus Torvalds case 2: /* SMIC */ 1493*1da177e4SLinus Torvalds si_type[intf_num] = "smic"; 1494*1da177e4SLinus Torvalds break; 1495*1da177e4SLinus Torvalds 1496*1da177e4SLinus Torvalds case 3: /* BT */ 1497*1da177e4SLinus Torvalds si_type[intf_num] = "bt"; 1498*1da177e4SLinus Torvalds break; 1499*1da177e4SLinus Torvalds 1500*1da177e4SLinus Torvalds default: 1501*1da177e4SLinus Torvalds printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n", 1502*1da177e4SLinus Torvalds spmi->InterfaceType); 1503*1da177e4SLinus Torvalds return -EIO; 1504*1da177e4SLinus Torvalds } 1505*1da177e4SLinus Torvalds 1506*1da177e4SLinus Torvalds info = kmalloc(sizeof(*info), GFP_KERNEL); 1507*1da177e4SLinus Torvalds if (!info) { 1508*1da177e4SLinus Torvalds printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); 1509*1da177e4SLinus Torvalds return -ENOMEM; 1510*1da177e4SLinus Torvalds } 1511*1da177e4SLinus Torvalds memset(info, 0, sizeof(*info)); 1512*1da177e4SLinus Torvalds 1513*1da177e4SLinus Torvalds if (spmi->InterruptType & 1) { 1514*1da177e4SLinus Torvalds /* We've got a GPE interrupt. */ 1515*1da177e4SLinus Torvalds info->irq = spmi->GPE; 1516*1da177e4SLinus Torvalds info->irq_setup = acpi_gpe_irq_setup; 1517*1da177e4SLinus Torvalds info->irq_cleanup = acpi_gpe_irq_cleanup; 1518*1da177e4SLinus Torvalds } else if (spmi->InterruptType & 2) { 1519*1da177e4SLinus Torvalds /* We've got an APIC/SAPIC interrupt. */ 1520*1da177e4SLinus Torvalds info->irq = spmi->GlobalSystemInterrupt; 1521*1da177e4SLinus Torvalds info->irq_setup = std_irq_setup; 1522*1da177e4SLinus Torvalds info->irq_cleanup = std_irq_cleanup; 1523*1da177e4SLinus Torvalds } else { 1524*1da177e4SLinus Torvalds /* Use the default interrupt setting. */ 1525*1da177e4SLinus Torvalds info->irq = 0; 1526*1da177e4SLinus Torvalds info->irq_setup = NULL; 1527*1da177e4SLinus Torvalds } 1528*1da177e4SLinus Torvalds 1529*1da177e4SLinus Torvalds regspacings[intf_num] = spmi->addr.register_bit_width / 8; 1530*1da177e4SLinus Torvalds info->io.regspacing = spmi->addr.register_bit_width / 8; 1531*1da177e4SLinus Torvalds regsizes[intf_num] = regspacings[intf_num]; 1532*1da177e4SLinus Torvalds info->io.regsize = regsizes[intf_num]; 1533*1da177e4SLinus Torvalds regshifts[intf_num] = spmi->addr.register_bit_offset; 1534*1da177e4SLinus Torvalds info->io.regshift = regshifts[intf_num]; 1535*1da177e4SLinus Torvalds 1536*1da177e4SLinus Torvalds if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { 1537*1da177e4SLinus Torvalds io_type = "memory"; 1538*1da177e4SLinus Torvalds info->io_setup = mem_setup; 1539*1da177e4SLinus Torvalds addrs[intf_num] = spmi->addr.address; 1540*1da177e4SLinus Torvalds info->io.info = &(addrs[intf_num]); 1541*1da177e4SLinus Torvalds } else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) { 1542*1da177e4SLinus Torvalds io_type = "I/O"; 1543*1da177e4SLinus Torvalds info->io_setup = port_setup; 1544*1da177e4SLinus Torvalds ports[intf_num] = spmi->addr.address; 1545*1da177e4SLinus Torvalds info->io.info = &(ports[intf_num]); 1546*1da177e4SLinus Torvalds } else { 1547*1da177e4SLinus Torvalds kfree(info); 1548*1da177e4SLinus Torvalds printk("ipmi_si: Unknown ACPI I/O Address type\n"); 1549*1da177e4SLinus Torvalds return -EIO; 1550*1da177e4SLinus Torvalds } 1551*1da177e4SLinus Torvalds 1552*1da177e4SLinus Torvalds *new_info = info; 1553*1da177e4SLinus Torvalds 1554*1da177e4SLinus Torvalds printk("ipmi_si: ACPI/SPMI specifies \"%s\" %s SI @ 0x%lx\n", 1555*1da177e4SLinus Torvalds si_type[intf_num], io_type, (unsigned long) spmi->addr.address); 1556*1da177e4SLinus Torvalds return 0; 1557*1da177e4SLinus Torvalds } 1558*1da177e4SLinus Torvalds #endif 1559*1da177e4SLinus Torvalds 1560*1da177e4SLinus Torvalds #ifdef CONFIG_X86 1561*1da177e4SLinus Torvalds typedef struct dmi_ipmi_data 1562*1da177e4SLinus Torvalds { 1563*1da177e4SLinus Torvalds u8 type; 1564*1da177e4SLinus Torvalds u8 addr_space; 1565*1da177e4SLinus Torvalds unsigned long base_addr; 1566*1da177e4SLinus Torvalds u8 irq; 1567*1da177e4SLinus Torvalds u8 offset; 1568*1da177e4SLinus Torvalds u8 slave_addr; 1569*1da177e4SLinus Torvalds } dmi_ipmi_data_t; 1570*1da177e4SLinus Torvalds 1571*1da177e4SLinus Torvalds static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; 1572*1da177e4SLinus Torvalds static int dmi_data_entries; 1573*1da177e4SLinus Torvalds 1574*1da177e4SLinus Torvalds typedef struct dmi_header 1575*1da177e4SLinus Torvalds { 1576*1da177e4SLinus Torvalds u8 type; 1577*1da177e4SLinus Torvalds u8 length; 1578*1da177e4SLinus Torvalds u16 handle; 1579*1da177e4SLinus Torvalds } dmi_header_t; 1580*1da177e4SLinus Torvalds 1581*1da177e4SLinus Torvalds static int decode_dmi(dmi_header_t *dm, int intf_num) 1582*1da177e4SLinus Torvalds { 1583*1da177e4SLinus Torvalds u8 *data = (u8 *)dm; 1584*1da177e4SLinus Torvalds unsigned long base_addr; 1585*1da177e4SLinus Torvalds u8 reg_spacing; 1586*1da177e4SLinus Torvalds u8 len = dm->length; 1587*1da177e4SLinus Torvalds dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; 1588*1da177e4SLinus Torvalds 1589*1da177e4SLinus Torvalds ipmi_data->type = data[4]; 1590*1da177e4SLinus Torvalds 1591*1da177e4SLinus Torvalds memcpy(&base_addr, data+8, sizeof(unsigned long)); 1592*1da177e4SLinus Torvalds if (len >= 0x11) { 1593*1da177e4SLinus Torvalds if (base_addr & 1) { 1594*1da177e4SLinus Torvalds /* I/O */ 1595*1da177e4SLinus Torvalds base_addr &= 0xFFFE; 1596*1da177e4SLinus Torvalds ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; 1597*1da177e4SLinus Torvalds } 1598*1da177e4SLinus Torvalds else { 1599*1da177e4SLinus Torvalds /* Memory */ 1600*1da177e4SLinus Torvalds ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE; 1601*1da177e4SLinus Torvalds } 1602*1da177e4SLinus Torvalds /* If bit 4 of byte 0x10 is set, then the lsb for the address 1603*1da177e4SLinus Torvalds is odd. */ 1604*1da177e4SLinus Torvalds ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); 1605*1da177e4SLinus Torvalds 1606*1da177e4SLinus Torvalds ipmi_data->irq = data[0x11]; 1607*1da177e4SLinus Torvalds 1608*1da177e4SLinus Torvalds /* The top two bits of byte 0x10 hold the register spacing. */ 1609*1da177e4SLinus Torvalds reg_spacing = (data[0x10] & 0xC0) >> 6; 1610*1da177e4SLinus Torvalds switch(reg_spacing){ 1611*1da177e4SLinus Torvalds case 0x00: /* Byte boundaries */ 1612*1da177e4SLinus Torvalds ipmi_data->offset = 1; 1613*1da177e4SLinus Torvalds break; 1614*1da177e4SLinus Torvalds case 0x01: /* 32-bit boundaries */ 1615*1da177e4SLinus Torvalds ipmi_data->offset = 4; 1616*1da177e4SLinus Torvalds break; 1617*1da177e4SLinus Torvalds case 0x02: /* 16-byte boundaries */ 1618*1da177e4SLinus Torvalds ipmi_data->offset = 16; 1619*1da177e4SLinus Torvalds break; 1620*1da177e4SLinus Torvalds default: 1621*1da177e4SLinus Torvalds /* Some other interface, just ignore it. */ 1622*1da177e4SLinus Torvalds return -EIO; 1623*1da177e4SLinus Torvalds } 1624*1da177e4SLinus Torvalds } else { 1625*1da177e4SLinus Torvalds /* Old DMI spec. */ 1626*1da177e4SLinus Torvalds ipmi_data->base_addr = base_addr; 1627*1da177e4SLinus Torvalds ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; 1628*1da177e4SLinus Torvalds ipmi_data->offset = 1; 1629*1da177e4SLinus Torvalds } 1630*1da177e4SLinus Torvalds 1631*1da177e4SLinus Torvalds ipmi_data->slave_addr = data[6]; 1632*1da177e4SLinus Torvalds 1633*1da177e4SLinus Torvalds if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { 1634*1da177e4SLinus Torvalds dmi_data_entries++; 1635*1da177e4SLinus Torvalds return 0; 1636*1da177e4SLinus Torvalds } 1637*1da177e4SLinus Torvalds 1638*1da177e4SLinus Torvalds memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t)); 1639*1da177e4SLinus Torvalds 1640*1da177e4SLinus Torvalds return -1; 1641*1da177e4SLinus Torvalds } 1642*1da177e4SLinus Torvalds 1643*1da177e4SLinus Torvalds static int dmi_table(u32 base, int len, int num) 1644*1da177e4SLinus Torvalds { 1645*1da177e4SLinus Torvalds u8 *buf; 1646*1da177e4SLinus Torvalds struct dmi_header *dm; 1647*1da177e4SLinus Torvalds u8 *data; 1648*1da177e4SLinus Torvalds int i=1; 1649*1da177e4SLinus Torvalds int status=-1; 1650*1da177e4SLinus Torvalds int intf_num = 0; 1651*1da177e4SLinus Torvalds 1652*1da177e4SLinus Torvalds buf = ioremap(base, len); 1653*1da177e4SLinus Torvalds if(buf==NULL) 1654*1da177e4SLinus Torvalds return -1; 1655*1da177e4SLinus Torvalds 1656*1da177e4SLinus Torvalds data = buf; 1657*1da177e4SLinus Torvalds 1658*1da177e4SLinus Torvalds while(i<num && (data - buf) < len) 1659*1da177e4SLinus Torvalds { 1660*1da177e4SLinus Torvalds dm=(dmi_header_t *)data; 1661*1da177e4SLinus Torvalds 1662*1da177e4SLinus Torvalds if((data-buf+dm->length) >= len) 1663*1da177e4SLinus Torvalds break; 1664*1da177e4SLinus Torvalds 1665*1da177e4SLinus Torvalds if (dm->type == 38) { 1666*1da177e4SLinus Torvalds if (decode_dmi(dm, intf_num) == 0) { 1667*1da177e4SLinus Torvalds intf_num++; 1668*1da177e4SLinus Torvalds if (intf_num >= SI_MAX_DRIVERS) 1669*1da177e4SLinus Torvalds break; 1670*1da177e4SLinus Torvalds } 1671*1da177e4SLinus Torvalds } 1672*1da177e4SLinus Torvalds 1673*1da177e4SLinus Torvalds data+=dm->length; 1674*1da177e4SLinus Torvalds while((data-buf) < len && (*data || data[1])) 1675*1da177e4SLinus Torvalds data++; 1676*1da177e4SLinus Torvalds data+=2; 1677*1da177e4SLinus Torvalds i++; 1678*1da177e4SLinus Torvalds } 1679*1da177e4SLinus Torvalds iounmap(buf); 1680*1da177e4SLinus Torvalds 1681*1da177e4SLinus Torvalds return status; 1682*1da177e4SLinus Torvalds } 1683*1da177e4SLinus Torvalds 1684*1da177e4SLinus Torvalds inline static int dmi_checksum(u8 *buf) 1685*1da177e4SLinus Torvalds { 1686*1da177e4SLinus Torvalds u8 sum=0; 1687*1da177e4SLinus Torvalds int a; 1688*1da177e4SLinus Torvalds 1689*1da177e4SLinus Torvalds for(a=0; a<15; a++) 1690*1da177e4SLinus Torvalds sum+=buf[a]; 1691*1da177e4SLinus Torvalds return (sum==0); 1692*1da177e4SLinus Torvalds } 1693*1da177e4SLinus Torvalds 1694*1da177e4SLinus Torvalds static int dmi_decode(void) 1695*1da177e4SLinus Torvalds { 1696*1da177e4SLinus Torvalds u8 buf[15]; 1697*1da177e4SLinus Torvalds u32 fp=0xF0000; 1698*1da177e4SLinus Torvalds 1699*1da177e4SLinus Torvalds #ifdef CONFIG_SIMNOW 1700*1da177e4SLinus Torvalds return -1; 1701*1da177e4SLinus Torvalds #endif 1702*1da177e4SLinus Torvalds 1703*1da177e4SLinus Torvalds while(fp < 0xFFFFF) 1704*1da177e4SLinus Torvalds { 1705*1da177e4SLinus Torvalds isa_memcpy_fromio(buf, fp, 15); 1706*1da177e4SLinus Torvalds if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) 1707*1da177e4SLinus Torvalds { 1708*1da177e4SLinus Torvalds u16 num=buf[13]<<8|buf[12]; 1709*1da177e4SLinus Torvalds u16 len=buf[7]<<8|buf[6]; 1710*1da177e4SLinus Torvalds u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; 1711*1da177e4SLinus Torvalds 1712*1da177e4SLinus Torvalds if(dmi_table(base, len, num) == 0) 1713*1da177e4SLinus Torvalds return 0; 1714*1da177e4SLinus Torvalds } 1715*1da177e4SLinus Torvalds fp+=16; 1716*1da177e4SLinus Torvalds } 1717*1da177e4SLinus Torvalds 1718*1da177e4SLinus Torvalds return -1; 1719*1da177e4SLinus Torvalds } 1720*1da177e4SLinus Torvalds 1721*1da177e4SLinus Torvalds static int try_init_smbios(int intf_num, struct smi_info **new_info) 1722*1da177e4SLinus Torvalds { 1723*1da177e4SLinus Torvalds struct smi_info *info; 1724*1da177e4SLinus Torvalds dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; 1725*1da177e4SLinus Torvalds char *io_type; 1726*1da177e4SLinus Torvalds 1727*1da177e4SLinus Torvalds if (intf_num >= dmi_data_entries) 1728*1da177e4SLinus Torvalds return -ENODEV; 1729*1da177e4SLinus Torvalds 1730*1da177e4SLinus Torvalds switch(ipmi_data->type) { 1731*1da177e4SLinus Torvalds case 0x01: /* KCS */ 1732*1da177e4SLinus Torvalds si_type[intf_num] = "kcs"; 1733*1da177e4SLinus Torvalds break; 1734*1da177e4SLinus Torvalds case 0x02: /* SMIC */ 1735*1da177e4SLinus Torvalds si_type[intf_num] = "smic"; 1736*1da177e4SLinus Torvalds break; 1737*1da177e4SLinus Torvalds case 0x03: /* BT */ 1738*1da177e4SLinus Torvalds si_type[intf_num] = "bt"; 1739*1da177e4SLinus Torvalds break; 1740*1da177e4SLinus Torvalds default: 1741*1da177e4SLinus Torvalds return -EIO; 1742*1da177e4SLinus Torvalds } 1743*1da177e4SLinus Torvalds 1744*1da177e4SLinus Torvalds info = kmalloc(sizeof(*info), GFP_KERNEL); 1745*1da177e4SLinus Torvalds if (!info) { 1746*1da177e4SLinus Torvalds printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); 1747*1da177e4SLinus Torvalds return -ENOMEM; 1748*1da177e4SLinus Torvalds } 1749*1da177e4SLinus Torvalds memset(info, 0, sizeof(*info)); 1750*1da177e4SLinus Torvalds 1751*1da177e4SLinus Torvalds if (ipmi_data->addr_space == 1) { 1752*1da177e4SLinus Torvalds io_type = "memory"; 1753*1da177e4SLinus Torvalds info->io_setup = mem_setup; 1754*1da177e4SLinus Torvalds addrs[intf_num] = ipmi_data->base_addr; 1755*1da177e4SLinus Torvalds info->io.info = &(addrs[intf_num]); 1756*1da177e4SLinus Torvalds } else if (ipmi_data->addr_space == 2) { 1757*1da177e4SLinus Torvalds io_type = "I/O"; 1758*1da177e4SLinus Torvalds info->io_setup = port_setup; 1759*1da177e4SLinus Torvalds ports[intf_num] = ipmi_data->base_addr; 1760*1da177e4SLinus Torvalds info->io.info = &(ports[intf_num]); 1761*1da177e4SLinus Torvalds } else { 1762*1da177e4SLinus Torvalds kfree(info); 1763*1da177e4SLinus Torvalds printk("ipmi_si: Unknown SMBIOS I/O Address type.\n"); 1764*1da177e4SLinus Torvalds return -EIO; 1765*1da177e4SLinus Torvalds } 1766*1da177e4SLinus Torvalds 1767*1da177e4SLinus Torvalds regspacings[intf_num] = ipmi_data->offset; 1768*1da177e4SLinus Torvalds info->io.regspacing = regspacings[intf_num]; 1769*1da177e4SLinus Torvalds if (!info->io.regspacing) 1770*1da177e4SLinus Torvalds info->io.regspacing = DEFAULT_REGSPACING; 1771*1da177e4SLinus Torvalds info->io.regsize = DEFAULT_REGSPACING; 1772*1da177e4SLinus Torvalds info->io.regshift = regshifts[intf_num]; 1773*1da177e4SLinus Torvalds 1774*1da177e4SLinus Torvalds info->slave_addr = ipmi_data->slave_addr; 1775*1da177e4SLinus Torvalds 1776*1da177e4SLinus Torvalds irqs[intf_num] = ipmi_data->irq; 1777*1da177e4SLinus Torvalds 1778*1da177e4SLinus Torvalds *new_info = info; 1779*1da177e4SLinus Torvalds 1780*1da177e4SLinus Torvalds printk("ipmi_si: Found SMBIOS-specified state machine at %s" 1781*1da177e4SLinus Torvalds " address 0x%lx, slave address 0x%x\n", 1782*1da177e4SLinus Torvalds io_type, (unsigned long)ipmi_data->base_addr, 1783*1da177e4SLinus Torvalds ipmi_data->slave_addr); 1784*1da177e4SLinus Torvalds return 0; 1785*1da177e4SLinus Torvalds } 1786*1da177e4SLinus Torvalds #endif /* CONFIG_X86 */ 1787*1da177e4SLinus Torvalds 1788*1da177e4SLinus Torvalds #ifdef CONFIG_PCI 1789*1da177e4SLinus Torvalds 1790*1da177e4SLinus Torvalds #define PCI_ERMC_CLASSCODE 0x0C0700 1791*1da177e4SLinus Torvalds #define PCI_HP_VENDOR_ID 0x103C 1792*1da177e4SLinus Torvalds #define PCI_MMC_DEVICE_ID 0x121A 1793*1da177e4SLinus Torvalds #define PCI_MMC_ADDR_CW 0x10 1794*1da177e4SLinus Torvalds 1795*1da177e4SLinus Torvalds /* Avoid more than one attempt to probe pci smic. */ 1796*1da177e4SLinus Torvalds static int pci_smic_checked = 0; 1797*1da177e4SLinus Torvalds 1798*1da177e4SLinus Torvalds static int find_pci_smic(int intf_num, struct smi_info **new_info) 1799*1da177e4SLinus Torvalds { 1800*1da177e4SLinus Torvalds struct smi_info *info; 1801*1da177e4SLinus Torvalds int error; 1802*1da177e4SLinus Torvalds struct pci_dev *pci_dev = NULL; 1803*1da177e4SLinus Torvalds u16 base_addr; 1804*1da177e4SLinus Torvalds int fe_rmc = 0; 1805*1da177e4SLinus Torvalds 1806*1da177e4SLinus Torvalds if (pci_smic_checked) 1807*1da177e4SLinus Torvalds return -ENODEV; 1808*1da177e4SLinus Torvalds 1809*1da177e4SLinus Torvalds pci_smic_checked = 1; 1810*1da177e4SLinus Torvalds 1811*1da177e4SLinus Torvalds if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, 1812*1da177e4SLinus Torvalds NULL))) 1813*1da177e4SLinus Torvalds ; 1814*1da177e4SLinus Torvalds else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) && 1815*1da177e4SLinus Torvalds pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID) 1816*1da177e4SLinus Torvalds fe_rmc = 1; 1817*1da177e4SLinus Torvalds else 1818*1da177e4SLinus Torvalds return -ENODEV; 1819*1da177e4SLinus Torvalds 1820*1da177e4SLinus Torvalds error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); 1821*1da177e4SLinus Torvalds if (error) 1822*1da177e4SLinus Torvalds { 1823*1da177e4SLinus Torvalds pci_dev_put(pci_dev); 1824*1da177e4SLinus Torvalds printk(KERN_ERR 1825*1da177e4SLinus Torvalds "ipmi_si: pci_read_config_word() failed (%d).\n", 1826*1da177e4SLinus Torvalds error); 1827*1da177e4SLinus Torvalds return -ENODEV; 1828*1da177e4SLinus Torvalds } 1829*1da177e4SLinus Torvalds 1830*1da177e4SLinus Torvalds /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ 1831*1da177e4SLinus Torvalds if (!(base_addr & 0x0001)) 1832*1da177e4SLinus Torvalds { 1833*1da177e4SLinus Torvalds pci_dev_put(pci_dev); 1834*1da177e4SLinus Torvalds printk(KERN_ERR 1835*1da177e4SLinus Torvalds "ipmi_si: memory mapped I/O not supported for PCI" 1836*1da177e4SLinus Torvalds " smic.\n"); 1837*1da177e4SLinus Torvalds return -ENODEV; 1838*1da177e4SLinus Torvalds } 1839*1da177e4SLinus Torvalds 1840*1da177e4SLinus Torvalds base_addr &= 0xFFFE; 1841*1da177e4SLinus Torvalds if (!fe_rmc) 1842*1da177e4SLinus Torvalds /* Data register starts at base address + 1 in eRMC */ 1843*1da177e4SLinus Torvalds ++base_addr; 1844*1da177e4SLinus Torvalds 1845*1da177e4SLinus Torvalds if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { 1846*1da177e4SLinus Torvalds pci_dev_put(pci_dev); 1847*1da177e4SLinus Torvalds return -ENODEV; 1848*1da177e4SLinus Torvalds } 1849*1da177e4SLinus Torvalds 1850*1da177e4SLinus Torvalds info = kmalloc(sizeof(*info), GFP_KERNEL); 1851*1da177e4SLinus Torvalds if (!info) { 1852*1da177e4SLinus Torvalds pci_dev_put(pci_dev); 1853*1da177e4SLinus Torvalds printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); 1854*1da177e4SLinus Torvalds return -ENOMEM; 1855*1da177e4SLinus Torvalds } 1856*1da177e4SLinus Torvalds memset(info, 0, sizeof(*info)); 1857*1da177e4SLinus Torvalds 1858*1da177e4SLinus Torvalds info->io_setup = port_setup; 1859*1da177e4SLinus Torvalds ports[intf_num] = base_addr; 1860*1da177e4SLinus Torvalds info->io.info = &(ports[intf_num]); 1861*1da177e4SLinus Torvalds info->io.regspacing = regspacings[intf_num]; 1862*1da177e4SLinus Torvalds if (!info->io.regspacing) 1863*1da177e4SLinus Torvalds info->io.regspacing = DEFAULT_REGSPACING; 1864*1da177e4SLinus Torvalds info->io.regsize = DEFAULT_REGSPACING; 1865*1da177e4SLinus Torvalds info->io.regshift = regshifts[intf_num]; 1866*1da177e4SLinus Torvalds 1867*1da177e4SLinus Torvalds *new_info = info; 1868*1da177e4SLinus Torvalds 1869*1da177e4SLinus Torvalds irqs[intf_num] = pci_dev->irq; 1870*1da177e4SLinus Torvalds si_type[intf_num] = "smic"; 1871*1da177e4SLinus Torvalds 1872*1da177e4SLinus Torvalds printk("ipmi_si: Found PCI SMIC at I/O address 0x%lx\n", 1873*1da177e4SLinus Torvalds (long unsigned int) base_addr); 1874*1da177e4SLinus Torvalds 1875*1da177e4SLinus Torvalds pci_dev_put(pci_dev); 1876*1da177e4SLinus Torvalds return 0; 1877*1da177e4SLinus Torvalds } 1878*1da177e4SLinus Torvalds #endif /* CONFIG_PCI */ 1879*1da177e4SLinus Torvalds 1880*1da177e4SLinus Torvalds static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) 1881*1da177e4SLinus Torvalds { 1882*1da177e4SLinus Torvalds #ifdef CONFIG_PCI 1883*1da177e4SLinus Torvalds if (find_pci_smic(intf_num, new_info)==0) 1884*1da177e4SLinus Torvalds return 0; 1885*1da177e4SLinus Torvalds #endif 1886*1da177e4SLinus Torvalds /* Include other methods here. */ 1887*1da177e4SLinus Torvalds 1888*1da177e4SLinus Torvalds return -ENODEV; 1889*1da177e4SLinus Torvalds } 1890*1da177e4SLinus Torvalds 1891*1da177e4SLinus Torvalds 1892*1da177e4SLinus Torvalds static int try_get_dev_id(struct smi_info *smi_info) 1893*1da177e4SLinus Torvalds { 1894*1da177e4SLinus Torvalds unsigned char msg[2]; 1895*1da177e4SLinus Torvalds unsigned char *resp; 1896*1da177e4SLinus Torvalds unsigned long resp_len; 1897*1da177e4SLinus Torvalds enum si_sm_result smi_result; 1898*1da177e4SLinus Torvalds int rv = 0; 1899*1da177e4SLinus Torvalds 1900*1da177e4SLinus Torvalds resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); 1901*1da177e4SLinus Torvalds if (!resp) 1902*1da177e4SLinus Torvalds return -ENOMEM; 1903*1da177e4SLinus Torvalds 1904*1da177e4SLinus Torvalds /* Do a Get Device ID command, since it comes back with some 1905*1da177e4SLinus Torvalds useful info. */ 1906*1da177e4SLinus Torvalds msg[0] = IPMI_NETFN_APP_REQUEST << 2; 1907*1da177e4SLinus Torvalds msg[1] = IPMI_GET_DEVICE_ID_CMD; 1908*1da177e4SLinus Torvalds smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); 1909*1da177e4SLinus Torvalds 1910*1da177e4SLinus Torvalds smi_result = smi_info->handlers->event(smi_info->si_sm, 0); 1911*1da177e4SLinus Torvalds for (;;) 1912*1da177e4SLinus Torvalds { 1913*1da177e4SLinus Torvalds if (smi_result == SI_SM_CALL_WITH_DELAY) { 1914*1da177e4SLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 1915*1da177e4SLinus Torvalds schedule_timeout(1); 1916*1da177e4SLinus Torvalds smi_result = smi_info->handlers->event( 1917*1da177e4SLinus Torvalds smi_info->si_sm, 100); 1918*1da177e4SLinus Torvalds } 1919*1da177e4SLinus Torvalds else if (smi_result == SI_SM_CALL_WITHOUT_DELAY) 1920*1da177e4SLinus Torvalds { 1921*1da177e4SLinus Torvalds smi_result = smi_info->handlers->event( 1922*1da177e4SLinus Torvalds smi_info->si_sm, 0); 1923*1da177e4SLinus Torvalds } 1924*1da177e4SLinus Torvalds else 1925*1da177e4SLinus Torvalds break; 1926*1da177e4SLinus Torvalds } 1927*1da177e4SLinus Torvalds if (smi_result == SI_SM_HOSED) { 1928*1da177e4SLinus Torvalds /* We couldn't get the state machine to run, so whatever's at 1929*1da177e4SLinus Torvalds the port is probably not an IPMI SMI interface. */ 1930*1da177e4SLinus Torvalds rv = -ENODEV; 1931*1da177e4SLinus Torvalds goto out; 1932*1da177e4SLinus Torvalds } 1933*1da177e4SLinus Torvalds 1934*1da177e4SLinus Torvalds /* Otherwise, we got some data. */ 1935*1da177e4SLinus Torvalds resp_len = smi_info->handlers->get_result(smi_info->si_sm, 1936*1da177e4SLinus Torvalds resp, IPMI_MAX_MSG_LENGTH); 1937*1da177e4SLinus Torvalds if (resp_len < 6) { 1938*1da177e4SLinus Torvalds /* That's odd, it should be longer. */ 1939*1da177e4SLinus Torvalds rv = -EINVAL; 1940*1da177e4SLinus Torvalds goto out; 1941*1da177e4SLinus Torvalds } 1942*1da177e4SLinus Torvalds 1943*1da177e4SLinus Torvalds if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0)) { 1944*1da177e4SLinus Torvalds /* That's odd, it shouldn't be able to fail. */ 1945*1da177e4SLinus Torvalds rv = -EINVAL; 1946*1da177e4SLinus Torvalds goto out; 1947*1da177e4SLinus Torvalds } 1948*1da177e4SLinus Torvalds 1949*1da177e4SLinus Torvalds /* Record info from the get device id, in case we need it. */ 1950*1da177e4SLinus Torvalds smi_info->ipmi_si_dev_rev = resp[4] & 0xf; 1951*1da177e4SLinus Torvalds smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f; 1952*1da177e4SLinus Torvalds smi_info->ipmi_si_fw_rev_minor = resp[6]; 1953*1da177e4SLinus Torvalds smi_info->ipmi_version_major = resp[7] & 0xf; 1954*1da177e4SLinus Torvalds smi_info->ipmi_version_minor = resp[7] >> 4; 1955*1da177e4SLinus Torvalds 1956*1da177e4SLinus Torvalds out: 1957*1da177e4SLinus Torvalds kfree(resp); 1958*1da177e4SLinus Torvalds return rv; 1959*1da177e4SLinus Torvalds } 1960*1da177e4SLinus Torvalds 1961*1da177e4SLinus Torvalds static int type_file_read_proc(char *page, char **start, off_t off, 1962*1da177e4SLinus Torvalds int count, int *eof, void *data) 1963*1da177e4SLinus Torvalds { 1964*1da177e4SLinus Torvalds char *out = (char *) page; 1965*1da177e4SLinus Torvalds struct smi_info *smi = data; 1966*1da177e4SLinus Torvalds 1967*1da177e4SLinus Torvalds switch (smi->si_type) { 1968*1da177e4SLinus Torvalds case SI_KCS: 1969*1da177e4SLinus Torvalds return sprintf(out, "kcs\n"); 1970*1da177e4SLinus Torvalds case SI_SMIC: 1971*1da177e4SLinus Torvalds return sprintf(out, "smic\n"); 1972*1da177e4SLinus Torvalds case SI_BT: 1973*1da177e4SLinus Torvalds return sprintf(out, "bt\n"); 1974*1da177e4SLinus Torvalds default: 1975*1da177e4SLinus Torvalds return 0; 1976*1da177e4SLinus Torvalds } 1977*1da177e4SLinus Torvalds } 1978*1da177e4SLinus Torvalds 1979*1da177e4SLinus Torvalds static int stat_file_read_proc(char *page, char **start, off_t off, 1980*1da177e4SLinus Torvalds int count, int *eof, void *data) 1981*1da177e4SLinus Torvalds { 1982*1da177e4SLinus Torvalds char *out = (char *) page; 1983*1da177e4SLinus Torvalds struct smi_info *smi = data; 1984*1da177e4SLinus Torvalds 1985*1da177e4SLinus Torvalds out += sprintf(out, "interrupts_enabled: %d\n", 1986*1da177e4SLinus Torvalds smi->irq && !smi->interrupt_disabled); 1987*1da177e4SLinus Torvalds out += sprintf(out, "short_timeouts: %ld\n", 1988*1da177e4SLinus Torvalds smi->short_timeouts); 1989*1da177e4SLinus Torvalds out += sprintf(out, "long_timeouts: %ld\n", 1990*1da177e4SLinus Torvalds smi->long_timeouts); 1991*1da177e4SLinus Torvalds out += sprintf(out, "timeout_restarts: %ld\n", 1992*1da177e4SLinus Torvalds smi->timeout_restarts); 1993*1da177e4SLinus Torvalds out += sprintf(out, "idles: %ld\n", 1994*1da177e4SLinus Torvalds smi->idles); 1995*1da177e4SLinus Torvalds out += sprintf(out, "interrupts: %ld\n", 1996*1da177e4SLinus Torvalds smi->interrupts); 1997*1da177e4SLinus Torvalds out += sprintf(out, "attentions: %ld\n", 1998*1da177e4SLinus Torvalds smi->attentions); 1999*1da177e4SLinus Torvalds out += sprintf(out, "flag_fetches: %ld\n", 2000*1da177e4SLinus Torvalds smi->flag_fetches); 2001*1da177e4SLinus Torvalds out += sprintf(out, "hosed_count: %ld\n", 2002*1da177e4SLinus Torvalds smi->hosed_count); 2003*1da177e4SLinus Torvalds out += sprintf(out, "complete_transactions: %ld\n", 2004*1da177e4SLinus Torvalds smi->complete_transactions); 2005*1da177e4SLinus Torvalds out += sprintf(out, "events: %ld\n", 2006*1da177e4SLinus Torvalds smi->events); 2007*1da177e4SLinus Torvalds out += sprintf(out, "watchdog_pretimeouts: %ld\n", 2008*1da177e4SLinus Torvalds smi->watchdog_pretimeouts); 2009*1da177e4SLinus Torvalds out += sprintf(out, "incoming_messages: %ld\n", 2010*1da177e4SLinus Torvalds smi->incoming_messages); 2011*1da177e4SLinus Torvalds 2012*1da177e4SLinus Torvalds return (out - ((char *) page)); 2013*1da177e4SLinus Torvalds } 2014*1da177e4SLinus Torvalds 2015*1da177e4SLinus Torvalds /* Returns 0 if initialized, or negative on an error. */ 2016*1da177e4SLinus Torvalds static int init_one_smi(int intf_num, struct smi_info **smi) 2017*1da177e4SLinus Torvalds { 2018*1da177e4SLinus Torvalds int rv; 2019*1da177e4SLinus Torvalds struct smi_info *new_smi; 2020*1da177e4SLinus Torvalds 2021*1da177e4SLinus Torvalds 2022*1da177e4SLinus Torvalds rv = try_init_mem(intf_num, &new_smi); 2023*1da177e4SLinus Torvalds if (rv) 2024*1da177e4SLinus Torvalds rv = try_init_port(intf_num, &new_smi); 2025*1da177e4SLinus Torvalds #ifdef CONFIG_ACPI_INTERPRETER 2026*1da177e4SLinus Torvalds if ((rv) && (si_trydefaults)) { 2027*1da177e4SLinus Torvalds rv = try_init_acpi(intf_num, &new_smi); 2028*1da177e4SLinus Torvalds } 2029*1da177e4SLinus Torvalds #endif 2030*1da177e4SLinus Torvalds #ifdef CONFIG_X86 2031*1da177e4SLinus Torvalds if ((rv) && (si_trydefaults)) { 2032*1da177e4SLinus Torvalds rv = try_init_smbios(intf_num, &new_smi); 2033*1da177e4SLinus Torvalds } 2034*1da177e4SLinus Torvalds #endif 2035*1da177e4SLinus Torvalds if ((rv) && (si_trydefaults)) { 2036*1da177e4SLinus Torvalds rv = try_init_plug_and_play(intf_num, &new_smi); 2037*1da177e4SLinus Torvalds } 2038*1da177e4SLinus Torvalds 2039*1da177e4SLinus Torvalds 2040*1da177e4SLinus Torvalds if (rv) 2041*1da177e4SLinus Torvalds return rv; 2042*1da177e4SLinus Torvalds 2043*1da177e4SLinus Torvalds /* So we know not to free it unless we have allocated one. */ 2044*1da177e4SLinus Torvalds new_smi->intf = NULL; 2045*1da177e4SLinus Torvalds new_smi->si_sm = NULL; 2046*1da177e4SLinus Torvalds new_smi->handlers = NULL; 2047*1da177e4SLinus Torvalds 2048*1da177e4SLinus Torvalds if (!new_smi->irq_setup) { 2049*1da177e4SLinus Torvalds new_smi->irq = irqs[intf_num]; 2050*1da177e4SLinus Torvalds new_smi->irq_setup = std_irq_setup; 2051*1da177e4SLinus Torvalds new_smi->irq_cleanup = std_irq_cleanup; 2052*1da177e4SLinus Torvalds } 2053*1da177e4SLinus Torvalds 2054*1da177e4SLinus Torvalds /* Default to KCS if no type is specified. */ 2055*1da177e4SLinus Torvalds if (si_type[intf_num] == NULL) { 2056*1da177e4SLinus Torvalds if (si_trydefaults) 2057*1da177e4SLinus Torvalds si_type[intf_num] = "kcs"; 2058*1da177e4SLinus Torvalds else { 2059*1da177e4SLinus Torvalds rv = -EINVAL; 2060*1da177e4SLinus Torvalds goto out_err; 2061*1da177e4SLinus Torvalds } 2062*1da177e4SLinus Torvalds } 2063*1da177e4SLinus Torvalds 2064*1da177e4SLinus Torvalds /* Set up the state machine to use. */ 2065*1da177e4SLinus Torvalds if (strcmp(si_type[intf_num], "kcs") == 0) { 2066*1da177e4SLinus Torvalds new_smi->handlers = &kcs_smi_handlers; 2067*1da177e4SLinus Torvalds new_smi->si_type = SI_KCS; 2068*1da177e4SLinus Torvalds } else if (strcmp(si_type[intf_num], "smic") == 0) { 2069*1da177e4SLinus Torvalds new_smi->handlers = &smic_smi_handlers; 2070*1da177e4SLinus Torvalds new_smi->si_type = SI_SMIC; 2071*1da177e4SLinus Torvalds } else if (strcmp(si_type[intf_num], "bt") == 0) { 2072*1da177e4SLinus Torvalds new_smi->handlers = &bt_smi_handlers; 2073*1da177e4SLinus Torvalds new_smi->si_type = SI_BT; 2074*1da177e4SLinus Torvalds } else { 2075*1da177e4SLinus Torvalds /* No support for anything else yet. */ 2076*1da177e4SLinus Torvalds rv = -EIO; 2077*1da177e4SLinus Torvalds goto out_err; 2078*1da177e4SLinus Torvalds } 2079*1da177e4SLinus Torvalds 2080*1da177e4SLinus Torvalds /* Allocate the state machine's data and initialize it. */ 2081*1da177e4SLinus Torvalds new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); 2082*1da177e4SLinus Torvalds if (!new_smi->si_sm) { 2083*1da177e4SLinus Torvalds printk(" Could not allocate state machine memory\n"); 2084*1da177e4SLinus Torvalds rv = -ENOMEM; 2085*1da177e4SLinus Torvalds goto out_err; 2086*1da177e4SLinus Torvalds } 2087*1da177e4SLinus Torvalds new_smi->io_size = new_smi->handlers->init_data(new_smi->si_sm, 2088*1da177e4SLinus Torvalds &new_smi->io); 2089*1da177e4SLinus Torvalds 2090*1da177e4SLinus Torvalds /* Now that we know the I/O size, we can set up the I/O. */ 2091*1da177e4SLinus Torvalds rv = new_smi->io_setup(new_smi); 2092*1da177e4SLinus Torvalds if (rv) { 2093*1da177e4SLinus Torvalds printk(" Could not set up I/O space\n"); 2094*1da177e4SLinus Torvalds goto out_err; 2095*1da177e4SLinus Torvalds } 2096*1da177e4SLinus Torvalds 2097*1da177e4SLinus Torvalds spin_lock_init(&(new_smi->si_lock)); 2098*1da177e4SLinus Torvalds spin_lock_init(&(new_smi->msg_lock)); 2099*1da177e4SLinus Torvalds spin_lock_init(&(new_smi->count_lock)); 2100*1da177e4SLinus Torvalds 2101*1da177e4SLinus Torvalds /* Do low-level detection first. */ 2102*1da177e4SLinus Torvalds if (new_smi->handlers->detect(new_smi->si_sm)) { 2103*1da177e4SLinus Torvalds rv = -ENODEV; 2104*1da177e4SLinus Torvalds goto out_err; 2105*1da177e4SLinus Torvalds } 2106*1da177e4SLinus Torvalds 2107*1da177e4SLinus Torvalds /* Attempt a get device id command. If it fails, we probably 2108*1da177e4SLinus Torvalds don't have a SMI here. */ 2109*1da177e4SLinus Torvalds rv = try_get_dev_id(new_smi); 2110*1da177e4SLinus Torvalds if (rv) 2111*1da177e4SLinus Torvalds goto out_err; 2112*1da177e4SLinus Torvalds 2113*1da177e4SLinus Torvalds /* Try to claim any interrupts. */ 2114*1da177e4SLinus Torvalds new_smi->irq_setup(new_smi); 2115*1da177e4SLinus Torvalds 2116*1da177e4SLinus Torvalds INIT_LIST_HEAD(&(new_smi->xmit_msgs)); 2117*1da177e4SLinus Torvalds INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs)); 2118*1da177e4SLinus Torvalds new_smi->curr_msg = NULL; 2119*1da177e4SLinus Torvalds atomic_set(&new_smi->req_events, 0); 2120*1da177e4SLinus Torvalds new_smi->run_to_completion = 0; 2121*1da177e4SLinus Torvalds 2122*1da177e4SLinus Torvalds new_smi->interrupt_disabled = 0; 2123*1da177e4SLinus Torvalds new_smi->timer_stopped = 0; 2124*1da177e4SLinus Torvalds new_smi->stop_operation = 0; 2125*1da177e4SLinus Torvalds 2126*1da177e4SLinus Torvalds /* Start clearing the flags before we enable interrupts or the 2127*1da177e4SLinus Torvalds timer to avoid racing with the timer. */ 2128*1da177e4SLinus Torvalds start_clear_flags(new_smi); 2129*1da177e4SLinus Torvalds /* IRQ is defined to be set when non-zero. */ 2130*1da177e4SLinus Torvalds if (new_smi->irq) 2131*1da177e4SLinus Torvalds new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; 2132*1da177e4SLinus Torvalds 2133*1da177e4SLinus Torvalds /* The ipmi_register_smi() code does some operations to 2134*1da177e4SLinus Torvalds determine the channel information, so we must be ready to 2135*1da177e4SLinus Torvalds handle operations before it is called. This means we have 2136*1da177e4SLinus Torvalds to stop the timer if we get an error after this point. */ 2137*1da177e4SLinus Torvalds init_timer(&(new_smi->si_timer)); 2138*1da177e4SLinus Torvalds new_smi->si_timer.data = (long) new_smi; 2139*1da177e4SLinus Torvalds new_smi->si_timer.function = smi_timeout; 2140*1da177e4SLinus Torvalds new_smi->last_timeout_jiffies = jiffies; 2141*1da177e4SLinus Torvalds new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; 2142*1da177e4SLinus Torvalds add_timer(&(new_smi->si_timer)); 2143*1da177e4SLinus Torvalds 2144*1da177e4SLinus Torvalds rv = ipmi_register_smi(&handlers, 2145*1da177e4SLinus Torvalds new_smi, 2146*1da177e4SLinus Torvalds new_smi->ipmi_version_major, 2147*1da177e4SLinus Torvalds new_smi->ipmi_version_minor, 2148*1da177e4SLinus Torvalds new_smi->slave_addr, 2149*1da177e4SLinus Torvalds &(new_smi->intf)); 2150*1da177e4SLinus Torvalds if (rv) { 2151*1da177e4SLinus Torvalds printk(KERN_ERR 2152*1da177e4SLinus Torvalds "ipmi_si: Unable to register device: error %d\n", 2153*1da177e4SLinus Torvalds rv); 2154*1da177e4SLinus Torvalds goto out_err_stop_timer; 2155*1da177e4SLinus Torvalds } 2156*1da177e4SLinus Torvalds 2157*1da177e4SLinus Torvalds rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", 2158*1da177e4SLinus Torvalds type_file_read_proc, NULL, 2159*1da177e4SLinus Torvalds new_smi, THIS_MODULE); 2160*1da177e4SLinus Torvalds if (rv) { 2161*1da177e4SLinus Torvalds printk(KERN_ERR 2162*1da177e4SLinus Torvalds "ipmi_si: Unable to create proc entry: %d\n", 2163*1da177e4SLinus Torvalds rv); 2164*1da177e4SLinus Torvalds goto out_err_stop_timer; 2165*1da177e4SLinus Torvalds } 2166*1da177e4SLinus Torvalds 2167*1da177e4SLinus Torvalds rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", 2168*1da177e4SLinus Torvalds stat_file_read_proc, NULL, 2169*1da177e4SLinus Torvalds new_smi, THIS_MODULE); 2170*1da177e4SLinus Torvalds if (rv) { 2171*1da177e4SLinus Torvalds printk(KERN_ERR 2172*1da177e4SLinus Torvalds "ipmi_si: Unable to create proc entry: %d\n", 2173*1da177e4SLinus Torvalds rv); 2174*1da177e4SLinus Torvalds goto out_err_stop_timer; 2175*1da177e4SLinus Torvalds } 2176*1da177e4SLinus Torvalds 2177*1da177e4SLinus Torvalds *smi = new_smi; 2178*1da177e4SLinus Torvalds 2179*1da177e4SLinus Torvalds printk(" IPMI %s interface initialized\n", si_type[intf_num]); 2180*1da177e4SLinus Torvalds 2181*1da177e4SLinus Torvalds return 0; 2182*1da177e4SLinus Torvalds 2183*1da177e4SLinus Torvalds out_err_stop_timer: 2184*1da177e4SLinus Torvalds new_smi->stop_operation = 1; 2185*1da177e4SLinus Torvalds 2186*1da177e4SLinus Torvalds /* Wait for the timer to stop. This avoids problems with race 2187*1da177e4SLinus Torvalds conditions removing the timer here. */ 2188*1da177e4SLinus Torvalds while (!new_smi->timer_stopped) { 2189*1da177e4SLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 2190*1da177e4SLinus Torvalds schedule_timeout(1); 2191*1da177e4SLinus Torvalds } 2192*1da177e4SLinus Torvalds 2193*1da177e4SLinus Torvalds out_err: 2194*1da177e4SLinus Torvalds if (new_smi->intf) 2195*1da177e4SLinus Torvalds ipmi_unregister_smi(new_smi->intf); 2196*1da177e4SLinus Torvalds 2197*1da177e4SLinus Torvalds new_smi->irq_cleanup(new_smi); 2198*1da177e4SLinus Torvalds 2199*1da177e4SLinus Torvalds /* Wait until we know that we are out of any interrupt 2200*1da177e4SLinus Torvalds handlers might have been running before we freed the 2201*1da177e4SLinus Torvalds interrupt. */ 2202*1da177e4SLinus Torvalds synchronize_kernel(); 2203*1da177e4SLinus Torvalds 2204*1da177e4SLinus Torvalds if (new_smi->si_sm) { 2205*1da177e4SLinus Torvalds if (new_smi->handlers) 2206*1da177e4SLinus Torvalds new_smi->handlers->cleanup(new_smi->si_sm); 2207*1da177e4SLinus Torvalds kfree(new_smi->si_sm); 2208*1da177e4SLinus Torvalds } 2209*1da177e4SLinus Torvalds new_smi->io_cleanup(new_smi); 2210*1da177e4SLinus Torvalds 2211*1da177e4SLinus Torvalds return rv; 2212*1da177e4SLinus Torvalds } 2213*1da177e4SLinus Torvalds 2214*1da177e4SLinus Torvalds static __init int init_ipmi_si(void) 2215*1da177e4SLinus Torvalds { 2216*1da177e4SLinus Torvalds int rv = 0; 2217*1da177e4SLinus Torvalds int pos = 0; 2218*1da177e4SLinus Torvalds int i; 2219*1da177e4SLinus Torvalds char *str; 2220*1da177e4SLinus Torvalds 2221*1da177e4SLinus Torvalds if (initialized) 2222*1da177e4SLinus Torvalds return 0; 2223*1da177e4SLinus Torvalds initialized = 1; 2224*1da177e4SLinus Torvalds 2225*1da177e4SLinus Torvalds /* Parse out the si_type string into its components. */ 2226*1da177e4SLinus Torvalds str = si_type_str; 2227*1da177e4SLinus Torvalds if (*str != '\0') { 2228*1da177e4SLinus Torvalds for (i=0; (i<SI_MAX_PARMS) && (*str != '\0'); i++) { 2229*1da177e4SLinus Torvalds si_type[i] = str; 2230*1da177e4SLinus Torvalds str = strchr(str, ','); 2231*1da177e4SLinus Torvalds if (str) { 2232*1da177e4SLinus Torvalds *str = '\0'; 2233*1da177e4SLinus Torvalds str++; 2234*1da177e4SLinus Torvalds } else { 2235*1da177e4SLinus Torvalds break; 2236*1da177e4SLinus Torvalds } 2237*1da177e4SLinus Torvalds } 2238*1da177e4SLinus Torvalds } 2239*1da177e4SLinus Torvalds 2240*1da177e4SLinus Torvalds printk(KERN_INFO "IPMI System Interface driver version " 2241*1da177e4SLinus Torvalds IPMI_SI_VERSION); 2242*1da177e4SLinus Torvalds if (kcs_smi_handlers.version) 2243*1da177e4SLinus Torvalds printk(", KCS version %s", kcs_smi_handlers.version); 2244*1da177e4SLinus Torvalds if (smic_smi_handlers.version) 2245*1da177e4SLinus Torvalds printk(", SMIC version %s", smic_smi_handlers.version); 2246*1da177e4SLinus Torvalds if (bt_smi_handlers.version) 2247*1da177e4SLinus Torvalds printk(", BT version %s", bt_smi_handlers.version); 2248*1da177e4SLinus Torvalds printk("\n"); 2249*1da177e4SLinus Torvalds 2250*1da177e4SLinus Torvalds #ifdef CONFIG_X86 2251*1da177e4SLinus Torvalds dmi_decode(); 2252*1da177e4SLinus Torvalds #endif 2253*1da177e4SLinus Torvalds 2254*1da177e4SLinus Torvalds rv = init_one_smi(0, &(smi_infos[pos])); 2255*1da177e4SLinus Torvalds if (rv && !ports[0] && si_trydefaults) { 2256*1da177e4SLinus Torvalds /* If we are trying defaults and the initial port is 2257*1da177e4SLinus Torvalds not set, then set it. */ 2258*1da177e4SLinus Torvalds si_type[0] = "kcs"; 2259*1da177e4SLinus Torvalds ports[0] = DEFAULT_KCS_IO_PORT; 2260*1da177e4SLinus Torvalds rv = init_one_smi(0, &(smi_infos[pos])); 2261*1da177e4SLinus Torvalds if (rv) { 2262*1da177e4SLinus Torvalds /* No KCS - try SMIC */ 2263*1da177e4SLinus Torvalds si_type[0] = "smic"; 2264*1da177e4SLinus Torvalds ports[0] = DEFAULT_SMIC_IO_PORT; 2265*1da177e4SLinus Torvalds rv = init_one_smi(0, &(smi_infos[pos])); 2266*1da177e4SLinus Torvalds } 2267*1da177e4SLinus Torvalds if (rv) { 2268*1da177e4SLinus Torvalds /* No SMIC - try BT */ 2269*1da177e4SLinus Torvalds si_type[0] = "bt"; 2270*1da177e4SLinus Torvalds ports[0] = DEFAULT_BT_IO_PORT; 2271*1da177e4SLinus Torvalds rv = init_one_smi(0, &(smi_infos[pos])); 2272*1da177e4SLinus Torvalds } 2273*1da177e4SLinus Torvalds } 2274*1da177e4SLinus Torvalds if (rv == 0) 2275*1da177e4SLinus Torvalds pos++; 2276*1da177e4SLinus Torvalds 2277*1da177e4SLinus Torvalds for (i=1; i < SI_MAX_PARMS; i++) { 2278*1da177e4SLinus Torvalds rv = init_one_smi(i, &(smi_infos[pos])); 2279*1da177e4SLinus Torvalds if (rv == 0) 2280*1da177e4SLinus Torvalds pos++; 2281*1da177e4SLinus Torvalds } 2282*1da177e4SLinus Torvalds 2283*1da177e4SLinus Torvalds if (smi_infos[0] == NULL) { 2284*1da177e4SLinus Torvalds printk("ipmi_si: Unable to find any System Interface(s)\n"); 2285*1da177e4SLinus Torvalds return -ENODEV; 2286*1da177e4SLinus Torvalds } 2287*1da177e4SLinus Torvalds 2288*1da177e4SLinus Torvalds return 0; 2289*1da177e4SLinus Torvalds } 2290*1da177e4SLinus Torvalds module_init(init_ipmi_si); 2291*1da177e4SLinus Torvalds 2292*1da177e4SLinus Torvalds static void __exit cleanup_one_si(struct smi_info *to_clean) 2293*1da177e4SLinus Torvalds { 2294*1da177e4SLinus Torvalds int rv; 2295*1da177e4SLinus Torvalds unsigned long flags; 2296*1da177e4SLinus Torvalds 2297*1da177e4SLinus Torvalds if (! to_clean) 2298*1da177e4SLinus Torvalds return; 2299*1da177e4SLinus Torvalds 2300*1da177e4SLinus Torvalds /* Tell the timer and interrupt handlers that we are shutting 2301*1da177e4SLinus Torvalds down. */ 2302*1da177e4SLinus Torvalds spin_lock_irqsave(&(to_clean->si_lock), flags); 2303*1da177e4SLinus Torvalds spin_lock(&(to_clean->msg_lock)); 2304*1da177e4SLinus Torvalds 2305*1da177e4SLinus Torvalds to_clean->stop_operation = 1; 2306*1da177e4SLinus Torvalds 2307*1da177e4SLinus Torvalds to_clean->irq_cleanup(to_clean); 2308*1da177e4SLinus Torvalds 2309*1da177e4SLinus Torvalds spin_unlock(&(to_clean->msg_lock)); 2310*1da177e4SLinus Torvalds spin_unlock_irqrestore(&(to_clean->si_lock), flags); 2311*1da177e4SLinus Torvalds 2312*1da177e4SLinus Torvalds /* Wait until we know that we are out of any interrupt 2313*1da177e4SLinus Torvalds handlers might have been running before we freed the 2314*1da177e4SLinus Torvalds interrupt. */ 2315*1da177e4SLinus Torvalds synchronize_kernel(); 2316*1da177e4SLinus Torvalds 2317*1da177e4SLinus Torvalds /* Wait for the timer to stop. This avoids problems with race 2318*1da177e4SLinus Torvalds conditions removing the timer here. */ 2319*1da177e4SLinus Torvalds while (!to_clean->timer_stopped) { 2320*1da177e4SLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 2321*1da177e4SLinus Torvalds schedule_timeout(1); 2322*1da177e4SLinus Torvalds } 2323*1da177e4SLinus Torvalds 2324*1da177e4SLinus Torvalds /* Interrupts and timeouts are stopped, now make sure the 2325*1da177e4SLinus Torvalds interface is in a clean state. */ 2326*1da177e4SLinus Torvalds while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) { 2327*1da177e4SLinus Torvalds poll(to_clean); 2328*1da177e4SLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 2329*1da177e4SLinus Torvalds schedule_timeout(1); 2330*1da177e4SLinus Torvalds } 2331*1da177e4SLinus Torvalds 2332*1da177e4SLinus Torvalds rv = ipmi_unregister_smi(to_clean->intf); 2333*1da177e4SLinus Torvalds if (rv) { 2334*1da177e4SLinus Torvalds printk(KERN_ERR 2335*1da177e4SLinus Torvalds "ipmi_si: Unable to unregister device: errno=%d\n", 2336*1da177e4SLinus Torvalds rv); 2337*1da177e4SLinus Torvalds } 2338*1da177e4SLinus Torvalds 2339*1da177e4SLinus Torvalds to_clean->handlers->cleanup(to_clean->si_sm); 2340*1da177e4SLinus Torvalds 2341*1da177e4SLinus Torvalds kfree(to_clean->si_sm); 2342*1da177e4SLinus Torvalds 2343*1da177e4SLinus Torvalds to_clean->io_cleanup(to_clean); 2344*1da177e4SLinus Torvalds } 2345*1da177e4SLinus Torvalds 2346*1da177e4SLinus Torvalds static __exit void cleanup_ipmi_si(void) 2347*1da177e4SLinus Torvalds { 2348*1da177e4SLinus Torvalds int i; 2349*1da177e4SLinus Torvalds 2350*1da177e4SLinus Torvalds if (!initialized) 2351*1da177e4SLinus Torvalds return; 2352*1da177e4SLinus Torvalds 2353*1da177e4SLinus Torvalds for (i=0; i<SI_MAX_DRIVERS; i++) { 2354*1da177e4SLinus Torvalds cleanup_one_si(smi_infos[i]); 2355*1da177e4SLinus Torvalds } 2356*1da177e4SLinus Torvalds } 2357*1da177e4SLinus Torvalds module_exit(cleanup_ipmi_si); 2358*1da177e4SLinus Torvalds 2359*1da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 2360