X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fpci%2Fhotplug%2Fshpchp_hpc.c;h=5183a45d45b50f6a02b5ada18cdeb9e9a0893624;hb=e1cca7e8d484390169777b423a7fe46c7021fec1;hp=0f9798df470429a90f08d7f4e8824d5f234fc191;hpb=f82bc1762e0e74b7e0040a4d83be06d32c37fc2e;p=linux-2.6 diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 0f9798df47..5183a45d45 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -35,38 +35,6 @@ #include "shpchp.h" -#ifdef DEBUG -#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ -#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ -#define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */ -#define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */ -#define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT) -#define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE) -/* Redefine this flagword to set debug level */ -#define DEBUG_LEVEL DBG_K_STANDARD - -#define DEFINE_DBG_BUFFER char __dbg_str_buf[256]; - -#define DBG_PRINT( dbg_flags, args... ) \ - do { \ - if ( DEBUG_LEVEL & ( dbg_flags ) ) \ - { \ - int len; \ - len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \ - __FILE__, __LINE__, __FUNCTION__ ); \ - sprintf( __dbg_str_buf + len, args ); \ - printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \ - } \ - } while (0) - -#define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]"); -#define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]"); -#else -#define DEFINE_DBG_BUFFER -#define DBG_ENTER_ROUTINE -#define DBG_LEAVE_ROUTINE -#endif /* DEBUG */ - /* Slot Available Register I field definition */ #define SLOT_33MHZ 0x0000001f #define SLOT_66MHZ_PCIX 0x00001f00 @@ -211,45 +179,40 @@ #define SLOT_EVENT_LATCH 0x2 #define SLOT_SERR_INT_MASK 0x3 -DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ -static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ -static int ctlr_seq_num = 0; /* Controller sequenc # */ -static spinlock_t list_lock; - static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); -static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs); -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec); +static irqreturn_t shpc_isr(int irq, void *dev_id); +static void start_int_poll_timer(struct controller *ctrl, int sec); static int hpc_check_cmd_status(struct controller *ctrl); static inline u8 shpc_readb(struct controller *ctrl, int reg) { - return readb(ctrl->hpc_ctlr_handle->creg + reg); + return readb(ctrl->creg + reg); } static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val) { - writeb(val, ctrl->hpc_ctlr_handle->creg + reg); + writeb(val, ctrl->creg + reg); } static inline u16 shpc_readw(struct controller *ctrl, int reg) { - return readw(ctrl->hpc_ctlr_handle->creg + reg); + return readw(ctrl->creg + reg); } static inline void shpc_writew(struct controller *ctrl, int reg, u16 val) { - writew(val, ctrl->hpc_ctlr_handle->creg + reg); + writew(val, ctrl->creg + reg); } static inline u32 shpc_readl(struct controller *ctrl, int reg) { - return readl(ctrl->hpc_ctlr_handle->creg + reg); + return readl(ctrl->creg + reg); } static inline void shpc_writel(struct controller *ctrl, int reg, u32 val) { - writel(val, ctrl->hpc_ctlr_handle->creg + reg); + writel(val, ctrl->creg + reg); } static inline int shpc_indirect_read(struct controller *ctrl, int index, @@ -268,55 +231,80 @@ static inline int shpc_indirect_read(struct controller *ctrl, int index, /* * This is the interrupt polling timeout function. */ -static void int_poll_timeout(unsigned long lphp_ctlr) +static void int_poll_timeout(unsigned long data) { - struct php_ctlr_state_s *php_ctlr = - (struct php_ctlr_state_s *)lphp_ctlr; - - DBG_ENTER_ROUTINE + struct controller *ctrl = (struct controller *)data; /* Poll for interrupt events. regs == NULL => polling */ - shpc_isr(0, php_ctlr->callback_instance_id, NULL); + shpc_isr(0, ctrl); - init_timer(&php_ctlr->int_poll_timer); + init_timer(&ctrl->poll_timer); if (!shpchp_poll_time) shpchp_poll_time = 2; /* default polling interval is 2 sec */ - start_int_poll_timer(php_ctlr, shpchp_poll_time); - - DBG_LEAVE_ROUTINE + start_int_poll_timer(ctrl, shpchp_poll_time); } /* * This function starts the interrupt polling timer. */ -static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) +static void start_int_poll_timer(struct controller *ctrl, int sec) { /* Clamp to sane value */ if ((sec <= 0) || (sec > 60)) sec = 2; - php_ctlr->int_poll_timer.function = &int_poll_timeout; - php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; - php_ctlr->int_poll_timer.expires = jiffies + sec * HZ; - add_timer(&php_ctlr->int_poll_timer); + ctrl->poll_timer.function = &int_poll_timeout; + ctrl->poll_timer.data = (unsigned long)ctrl; + ctrl->poll_timer.expires = jiffies + sec * HZ; + add_timer(&ctrl->poll_timer); +} + +static inline int is_ctrl_busy(struct controller *ctrl) +{ + u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); + return cmd_status & 0x1; +} + +/* + * Returns 1 if SHPC finishes executing a command within 1 sec, + * otherwise returns 0. + */ +static inline int shpc_poll_ctrl_busy(struct controller *ctrl) +{ + int i; + + if (!is_ctrl_busy(ctrl)) + return 1; + + /* Check every 0.1 sec for a total of 1 sec */ + for (i = 0; i < 10; i++) { + msleep(100); + if (!is_ctrl_busy(ctrl)) + return 1; + } + + return 0; } static inline int shpc_wait_cmd(struct controller *ctrl) { int retval = 0; - unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; - unsigned long timeout = msecs_to_jiffies(timeout_msec); - int rc = wait_event_interruptible_timeout(ctrl->queue, - !ctrl->cmd_busy, timeout); - if (!rc) { + unsigned long timeout = msecs_to_jiffies(1000); + int rc; + + if (shpchp_poll_mode) + rc = shpc_poll_ctrl_busy(ctrl); + else + rc = wait_event_interruptible_timeout(ctrl->queue, + !is_ctrl_busy(ctrl), timeout); + if (!rc && is_ctrl_busy(ctrl)) { retval = -EIO; - err("Command not completed in %d msec\n", timeout_msec); + err("Command not completed in 1000 msec\n"); } else if (rc < 0) { retval = -EINTR; info("Command was interrupted by a signal\n"); } - ctrl->cmd_busy = 0; return retval; } @@ -327,26 +315,13 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) u16 cmd_status; int retval = 0; u16 temp_word; - int i; - - DBG_ENTER_ROUTINE mutex_lock(&slot->ctrl->cmd_lock); - for (i = 0; i < 10; i++) { - cmd_status = shpc_readw(ctrl, CMD_STATUS); - - if (!(cmd_status & 0x1)) - break; - /* Check every 0.1 sec for a total of 1 sec*/ - msleep(100); - } - - cmd_status = shpc_readw(ctrl, CMD_STATUS); - - if (cmd_status & 0x1) { + if (!shpc_poll_ctrl_busy(ctrl)) { /* After 1 sec and and the controller is still busy */ - err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); + err("%s : Controller is still busy after 1 sec.\n", + __FUNCTION__); retval = -EBUSY; goto out; } @@ -354,11 +329,10 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) ++t_slot; temp_word = (t_slot << 8) | (cmd & 0xFF); dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd); - + /* To make sure the Controller Busy bit is 0 before we send out the - * command. + * command. */ - slot->ctrl->cmd_busy = 1; shpc_writew(ctrl, CMD, temp_word); /* @@ -376,20 +350,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) } out: mutex_unlock(&slot->ctrl->cmd_lock); - - DBG_LEAVE_ROUTINE return retval; } static int hpc_check_cmd_status(struct controller *ctrl) { - u16 cmd_status; int retval = 0; + u16 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; - DBG_ENTER_ROUTINE - - cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; - switch (cmd_status >> 1) { case 0: retval = 0; @@ -410,7 +378,6 @@ static int hpc_check_cmd_status(struct controller *ctrl) retval = cmd_status; } - DBG_LEAVE_ROUTINE return retval; } @@ -418,13 +385,8 @@ static int hpc_check_cmd_status(struct controller *ctrl) static int hpc_get_attention_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg; - u8 state; - - DBG_ENTER_ROUTINE - - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u8 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; switch (state) { case ATN_LED_STATE_ON: @@ -441,20 +403,14 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) break; } - DBG_LEAVE_ROUTINE return 0; } static int hpc_get_power_status(struct slot * slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg; - u8 state; - - DBG_ENTER_ROUTINE - - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u8 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; switch (state) { case SLOT_STATE_PWRONLY: @@ -471,7 +427,6 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) break; } - DBG_LEAVE_ROUTINE return 0; } @@ -479,30 +434,21 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) static int hpc_get_latch_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg; - - DBG_ENTER_ROUTINE + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ - DBG_LEAVE_ROUTINE return 0; } static int hpc_get_adapter_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg; - u8 state; - - DBG_ENTER_ROUTINE + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u8 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; *status = (state != 0x3) ? 1 : 0; - DBG_LEAVE_ROUTINE return 0; } @@ -510,11 +456,8 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) { struct controller *ctrl = slot->ctrl; - DBG_ENTER_ROUTINE - *prog_int = shpc_readb(ctrl, PROG_INTERFACE); - DBG_LEAVE_ROUTINE return 0; } @@ -526,8 +469,6 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) u8 m66_cap = !!(slot_reg & MHZ66_CAP); u8 pi, pcix_cap; - DBG_ENTER_ROUTINE - if ((retval = hpc_get_prog_int(slot, &pi))) return retval; @@ -569,21 +510,15 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) } dbg("Adapter speed = %d\n", *value); - DBG_LEAVE_ROUTINE return retval; } static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) { - struct controller *ctrl = slot->ctrl; - u16 sec_bus_status; - u8 pi; int retval = 0; - - DBG_ENTER_ROUTINE - - pi = shpc_readb(ctrl, PROG_INTERFACE); - sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); + struct controller *ctrl = slot->ctrl; + u16 sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); + u8 pi = shpc_readb(ctrl, PROG_INTERFACE); if (pi == 2) { *mode = (sec_bus_status & 0x0100) >> 8; @@ -592,21 +527,14 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) } dbg("Mode 1 ECC cap = %d\n", *mode); - - DBG_LEAVE_ROUTINE return retval; } static int hpc_query_power_fault(struct slot * slot) { struct controller *ctrl = slot->ctrl; - u32 slot_reg; - - DBG_ENTER_ROUTINE - - slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - DBG_LEAVE_ROUTINE /* Note: Logic 0 => fault */ return !(slot_reg & POWER_FAULT); } @@ -616,7 +544,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) u8 slot_cmd = 0; switch (value) { - case 0 : + case 0 : slot_cmd = SET_ATTN_OFF; /* OFF */ break; case 1: @@ -648,38 +576,11 @@ static void hpc_set_green_led_blink(struct slot *slot) shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK); } -int shpc_get_ctlr_slot_config(struct controller *ctrl, - int *num_ctlr_slots, /* number of slots in this HPC */ - int *first_device_num, /* PCI dev num of the first slot in this SHPC */ - int *physical_slot_num, /* phy slot num of the first slot in this SHPC */ - int *updown, /* physical_slot_num increament: 1 or -1 */ - int *flags) -{ - u32 slot_config; - - DBG_ENTER_ROUTINE - - slot_config = shpc_readl(ctrl, SLOT_CONFIG); - *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8; - *num_ctlr_slots = slot_config & SLOT_NUM; - *physical_slot_num = (slot_config & PSN) >> 16; - *updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1; - - dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num); - - DBG_LEAVE_ROUTINE - return 0; -} - static void hpc_release_ctlr(struct controller *ctrl) { - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; - struct php_ctlr_state_s *p, *p_prev; int i; u32 slot_reg, serr_int; - DBG_ENTER_ROUTINE - /* * Mask event interrupts and SERRs of all slots */ @@ -704,40 +605,15 @@ static void hpc_release_ctlr(struct controller *ctrl) serr_int &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); - if (shpchp_poll_mode) { - del_timer(&php_ctlr->int_poll_timer); - } else { - if (php_ctlr->irq) { - free_irq(php_ctlr->irq, ctrl); - php_ctlr->irq = 0; - pci_disable_msi(php_ctlr->pci_dev); - } + if (shpchp_poll_mode) + del_timer(&ctrl->poll_timer); + else { + free_irq(ctrl->pci_dev->irq, ctrl); + pci_disable_msi(ctrl->pci_dev); } - if (php_ctlr->pci_dev) { - iounmap(php_ctlr->creg); - release_mem_region(ctrl->mmio_base, ctrl->mmio_size); - php_ctlr->pci_dev = NULL; - } - - spin_lock(&list_lock); - p = php_ctlr_list_head; - p_prev = NULL; - while (p) { - if (p == php_ctlr) { - if (p_prev) - p_prev->pnext = p->pnext; - else - php_ctlr_list_head = p->pnext; - break; - } else { - p_prev = p; - p = p->pnext; - } - } - spin_unlock(&list_lock); - - kfree(php_ctlr); + iounmap(ctrl->creg); + release_mem_region(ctrl->mmio_base, ctrl->mmio_size); /* * If this is the last controller to be released, destroy the @@ -745,62 +621,43 @@ static void hpc_release_ctlr(struct controller *ctrl) */ if (atomic_dec_and_test(&shpchp_num_controllers)) destroy_workqueue(shpchp_wq); - -DBG_LEAVE_ROUTINE - } static int hpc_power_on_slot(struct slot * slot) { int retval; - DBG_ENTER_ROUTINE - retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); - if (retval) { + if (retval) err("%s: Write command failed!\n", __FUNCTION__); - return retval; - } - DBG_LEAVE_ROUTINE - - return 0; + return retval; } static int hpc_slot_enable(struct slot * slot) { int retval; - DBG_ENTER_ROUTINE - /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); - if (retval) { + if (retval) err("%s: Write command failed!\n", __FUNCTION__); - return retval; - } - DBG_LEAVE_ROUTINE - return 0; + return retval; } static int hpc_slot_disable(struct slot * slot) { int retval; - DBG_ENTER_ROUTINE - /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); - if (retval) { + if (retval) err("%s: Write command failed!\n", __FUNCTION__); - return retval; - } - DBG_LEAVE_ROUTINE - return 0; + return retval; } static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) @@ -809,8 +666,6 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) struct controller *ctrl = slot->ctrl; u8 pi, cmd; - DBG_ENTER_ROUTINE - pi = shpc_readb(ctrl, PROG_INTERFACE); if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) return -EINVAL; @@ -866,14 +721,12 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) if (retval) err("%s: Write command failed!\n", __FUNCTION__); - DBG_LEAVE_ROUTINE return retval; } -static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t shpc_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; - struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u32 serr_int, slot_reg, intr_loc, intr_loc2; int hp_slot; @@ -882,7 +735,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) if (!intr_loc) return IRQ_NONE; - dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); + dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); if(!shpchp_poll_mode) { /* @@ -895,12 +748,12 @@ static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); intr_loc2 = shpc_readl(ctrl, INTR_LOC); - dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } if (intr_loc & CMD_INTR_PENDING) { - /* - * Command Complete Interrupt Pending + /* + * Command Complete Interrupt Pending * RO only - clear by writing 1 to the Command Completion * Detect bit in Controller SERR-INT register */ @@ -908,14 +761,13 @@ static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) serr_int &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); - ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } if (!(intr_loc & ~CMD_INTR_PENDING)) goto out; - for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { /* To find out which slot has interrupt pending */ if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) continue; @@ -925,20 +777,16 @@ static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) __FUNCTION__, hp_slot, slot_reg); if (slot_reg & MRL_CHANGE_DETECTED) - php_ctlr->switch_change_callback( - hp_slot, php_ctlr->callback_instance_id); + shpchp_handle_switch_change(hp_slot, ctrl); if (slot_reg & BUTTON_PRESS_DETECTED) - php_ctlr->attention_button_callback( - hp_slot, php_ctlr->callback_instance_id); + shpchp_handle_attention_button(hp_slot, ctrl); if (slot_reg & PRSNT_CHANGE_DETECTED) - php_ctlr->presence_change_callback( - hp_slot , php_ctlr->callback_instance_id); + shpchp_handle_presence_change(hp_slot, ctrl); if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) - php_ctlr->power_fault_callback( - hp_slot, php_ctlr->callback_instance_id); + shpchp_handle_power_fault(hp_slot, ctrl); /* Clear all slot events */ slot_reg &= ~SLOT_REG_RSVDZ_MASK; @@ -951,7 +799,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs) serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); } - + return IRQ_HANDLED; } @@ -964,8 +812,6 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); - DBG_ENTER_ROUTINE - if (pi == 2) { if (slot_avail2 & SLOT_133MHZ_PCIX_533) bus_speed = PCI_SPEED_133MHz_PCIX_533; @@ -998,7 +844,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) *value = bus_speed; dbg("Max bus speed = %d\n", bus_speed); - DBG_LEAVE_ROUTINE + return retval; } @@ -1011,8 +857,6 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) u8 pi = shpc_readb(ctrl, PROG_INTERFACE); u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); - DBG_ENTER_ROUTINE - if ((pi == 1) && (speed_mode > 4)) { *value = PCI_SPEED_UNKNOWN; return -ENODEV; @@ -1068,7 +912,6 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) } dbg("Current bus speed = %d\n", bus_speed); - DBG_LEAVE_ROUTINE return retval; } @@ -1076,7 +919,7 @@ static struct hpc_ops shpchp_hpc_ops = { .power_on_slot = hpc_power_on_slot, .slot_enable = hpc_slot_enable, .slot_disable = hpc_slot_disable, - .set_bus_speed_mode = hpc_set_bus_speed_mode, + .set_bus_speed_mode = hpc_set_bus_speed_mode, .set_attention_status = hpc_set_attention_status, .get_power_status = hpc_get_power_status, .get_attention_status = hpc_get_attention_status, @@ -1093,34 +936,20 @@ static struct hpc_ops shpchp_hpc_ops = { .green_led_on = hpc_set_green_led_on, .green_led_off = hpc_set_green_led_off, .green_led_blink = hpc_set_green_led_blink, - + .release_ctlr = hpc_release_ctlr, }; -int shpc_init(struct controller * ctrl, struct pci_dev * pdev) +int shpc_init(struct controller *ctrl, struct pci_dev *pdev) { - struct php_ctlr_state_s *php_ctlr, *p; - void *instance_id = ctrl; - int rc, num_slots = 0; + int rc = -1, num_slots = 0; u8 hp_slot; u32 shpc_base_offset; u32 tempdword, slot_reg, slot_config; u8 i; - DBG_ENTER_ROUTINE - ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ - spin_lock_init(&list_lock); - php_ctlr = kzalloc(sizeof(*php_ctlr), GFP_KERNEL); - - if (!php_ctlr) { /* allocate controller state data */ - err("%s: HPC controller memory allocation error!\n", __FUNCTION__); - goto abort; - } - - php_ctlr->pci_dev = pdev; /* save pci_dev in context */ - if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)) { /* amd shpc driver doesn't use Base Offset; assume 0 */ @@ -1130,20 +959,20 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); if (!ctrl->cap_offset) { err("%s : cap_offset == 0\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort; } dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); if (rc) { err("%s: cannot read base_offset\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort; } rc = shpc_indirect_read(ctrl, 3, &tempdword); if (rc) { err("%s: cannot read slot config\n", __FUNCTION__); - goto abort_free_ctlr; + goto abort; } num_slots = tempdword & SLOT_NUM; dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); @@ -1153,7 +982,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) if (rc) { err("%s: cannot read creg (index = %d)\n", __FUNCTION__, i); - goto abort_free_ctlr; + goto abort; } dbg("%s: offset %d: value %x\n", __FUNCTION__,i, tempdword); @@ -1164,25 +993,30 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) ctrl->mmio_size = 0x24 + 0x4 * num_slots; } - info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, + info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); - - if (pci_enable_device(pdev)) - goto abort_free_ctlr; + + rc = pci_enable_device(pdev); + if (rc) { + err("%s: pci_enable_device failed\n", __FUNCTION__); + goto abort; + } if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { err("%s: cannot reserve MMIO region\n", __FUNCTION__); - goto abort_free_ctlr; + rc = -1; + goto abort; } - php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); - if (!php_ctlr->creg) { + ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); + if (!ctrl->creg) { err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, ctrl->mmio_size, ctrl->mmio_base); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); - goto abort_free_ctlr; + rc = -1; + goto abort; } - dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); + dbg("%s: ctrl->creg %p\n", __FUNCTION__, ctrl->creg); mutex_init(&ctrl->crit_sect); mutex_init(&ctrl->cmd_lock); @@ -1190,23 +1024,14 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) /* Setup wait queue */ init_waitqueue_head(&ctrl->queue); - /* Find the IRQ */ - php_ctlr->irq = pdev->irq; - php_ctlr->attention_button_callback = shpchp_handle_attention_button, - php_ctlr->switch_change_callback = shpchp_handle_switch_change; - php_ctlr->presence_change_callback = shpchp_handle_presence_change; - php_ctlr->power_fault_callback = shpchp_handle_power_fault; - php_ctlr->callback_instance_id = instance_id; - - ctrl->hpc_ctlr_handle = php_ctlr; ctrl->hpc_ops = &shpchp_hpc_ops; /* Return PCI Controller Info */ slot_config = shpc_readl(ctrl, SLOT_CONFIG); - php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; - php_ctlr->num_slots = slot_config & SLOT_NUM; - dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); - dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); + ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; + ctrl->num_slots = slot_config & SLOT_NUM; + ctrl->first_slot = (slot_config & PSN) >> 16; + ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1; /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); @@ -1221,7 +1046,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) /* Mask the MRL sensor SERR Mask of individual slot in * Slot SERR-INT Mask & clear all the existing event if any */ - for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); @@ -1232,25 +1057,28 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) slot_reg &= ~SLOT_REG_RSVDZ_MASK; shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } - - if (shpchp_poll_mode) {/* Install interrupt polling code */ - /* Install and start the interrupt polling timer */ - init_timer(&php_ctlr->int_poll_timer); - start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ + + if (shpchp_poll_mode) { + /* Install interrupt polling timer. Start with 10 sec delay */ + init_timer(&ctrl->poll_timer); + start_int_poll_timer(ctrl, 10); } else { /* Installs the interrupt handler */ rc = pci_enable_msi(pdev); if (rc) { info("Can't get msi for the hotplug controller\n"); info("Use INTx for the hotplug controller\n"); - } else - php_ctlr->irq = pdev->irq; - - rc = request_irq(php_ctlr->irq, shpc_isr, IRQF_SHARED, MY_NAME, (void *) ctrl); - dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); + } + + rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, + MY_NAME, (void *)ctrl); + dbg("%s: request_irq %d for hpc%d (returns %d)\n", + __FUNCTION__, ctrl->pci_dev->irq, + atomic_read(&shpchp_num_controllers), rc); if (rc) { - err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); - goto abort_free_ctlr; + err("Can't get irq %d for the hotplug controller\n", + ctrl->pci_dev->irq); + goto abort_iounmap; } } dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __FUNCTION__, @@ -1258,38 +1086,22 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) PCI_FUNC(pdev->devfn), pdev->irq); get_hp_hw_control_from_firmware(pdev); - /* Add this HPC instance into the HPC list */ - spin_lock(&list_lock); - if (php_ctlr_list_head == 0) { - php_ctlr_list_head = php_ctlr; - p = php_ctlr_list_head; - p->pnext = NULL; - } else { - p = php_ctlr_list_head; - - while (p->pnext) - p = p->pnext; - - p->pnext = php_ctlr; - } - spin_unlock(&list_lock); - - ctlr_seq_num++; - /* * If this is the first controller to be initialized, * initialize the shpchpd work queue */ if (atomic_add_return(1, &shpchp_num_controllers) == 1) { shpchp_wq = create_singlethread_workqueue("shpchpd"); - if (!shpchp_wq) - return -ENOMEM; + if (!shpchp_wq) { + rc = -ENOMEM; + goto abort_iounmap; + } } /* * Unmask all event interrupts of all slots */ - for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, hp_slot, slot_reg); @@ -1308,13 +1120,11 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); } - DBG_LEAVE_ROUTINE return 0; /* We end up here for the many possible ways to fail this API. */ -abort_free_ctlr: - kfree(php_ctlr); +abort_iounmap: + iounmap(ctrl->creg); abort: - DBG_LEAVE_ROUTINE - return -1; + return rc; }