📄 ibmphp_hpc.c
字号:
} else timeout--; } } ctlr_ptr->status = status; } // cleanup // remove physical to logical address mapping if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) iounmap (wpg_bbar); free_hpc_access (); debug_polling ("%s - Exit rc[%d]\n", __func__, rc); return rc;}/*----------------------------------------------------------------------* Name: get_hpc_access()** Action: make sure only one process can access HPC at one time*---------------------------------------------------------------------*/static void get_hpc_access (void){ mutex_lock(&sem_hpcaccess);}/*----------------------------------------------------------------------* Name: free_hpc_access()*---------------------------------------------------------------------*/void free_hpc_access (void){ mutex_unlock(&sem_hpcaccess);}/*----------------------------------------------------------------------* Name: ibmphp_lock_operations()** Action: make sure only one process can change the data structure*---------------------------------------------------------------------*/void ibmphp_lock_operations (void){ down (&semOperations); to_debug = 1;}/*----------------------------------------------------------------------* Name: ibmphp_unlock_operations()*---------------------------------------------------------------------*/void ibmphp_unlock_operations (void){ debug ("%s - Entry\n", __func__); up (&semOperations); to_debug = 0; debug ("%s - Exit\n", __func__);}/*----------------------------------------------------------------------* Name: poll_hpc()*---------------------------------------------------------------------*/#define POLL_LATCH_REGISTER 0#define POLL_SLOTS 1#define POLL_SLEEP 2static int poll_hpc(void *data){ struct slot myslot; struct slot *pslot = NULL; struct list_head *pslotlist; int rc; int poll_state = POLL_LATCH_REGISTER; u8 oldlatchlow = 0x00; u8 curlatchlow = 0x00; int poll_count = 0; u8 ctrl_count = 0x00; debug ("%s - Entry\n", __func__); while (!kthread_should_stop()) { /* try to get the lock to do some kind of hardware access */ down (&semOperations); switch (poll_state) { case POLL_LATCH_REGISTER: oldlatchlow = curlatchlow; ctrl_count = 0x00; list_for_each (pslotlist, &ibmphp_slot_head) { if (ctrl_count >= ibmphp_get_total_controllers()) break; pslot = list_entry (pslotlist, struct slot, ibm_slot_list); if (pslot->ctrl->ctlr_relative_id == ctrl_count) { ctrl_count++; if (READ_SLOT_LATCH (pslot->ctrl)) { rc = ibmphp_hpc_readslot (pslot, READ_SLOTLATCHLOWREG, &curlatchlow); if (oldlatchlow != curlatchlow) process_changeinlatch (oldlatchlow, curlatchlow, pslot->ctrl); } } } ++poll_count; poll_state = POLL_SLEEP; break; case POLL_SLOTS: list_for_each (pslotlist, &ibmphp_slot_head) { pslot = list_entry (pslotlist, struct slot, ibm_slot_list); // make a copy of the old status memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot)); rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); if ((myslot.status != pslot->status) || (myslot.ext_status != pslot->ext_status)) process_changeinstatus (pslot, &myslot); } ctrl_count = 0x00; list_for_each (pslotlist, &ibmphp_slot_head) { if (ctrl_count >= ibmphp_get_total_controllers()) break; pslot = list_entry (pslotlist, struct slot, ibm_slot_list); if (pslot->ctrl->ctlr_relative_id == ctrl_count) { ctrl_count++; if (READ_SLOT_LATCH (pslot->ctrl)) rc = ibmphp_hpc_readslot (pslot, READ_SLOTLATCHLOWREG, &curlatchlow); } } ++poll_count; poll_state = POLL_SLEEP; break; case POLL_SLEEP: /* don't sleep with a lock on the hardware */ up (&semOperations); msleep(POLL_INTERVAL_SEC * 1000); if (kthread_should_stop()) break; down (&semOperations); if (poll_count >= POLL_LATCH_CNT) { poll_count = 0; poll_state = POLL_SLOTS; } else poll_state = POLL_LATCH_REGISTER; break; } /* give up the hardware semaphore */ up (&semOperations); /* sleep for a short time just for good measure */ msleep(100); } up (&sem_exit); debug ("%s - Exit\n", __func__); return 0;}/*----------------------------------------------------------------------* Name: process_changeinstatus** Action: compare old and new slot status, process the change in status** Input: pointer to slot struct, old slot struct** Return 0 or error codes* Value:** Side* Effects: None.** Notes:*---------------------------------------------------------------------*/static int process_changeinstatus (struct slot *pslot, struct slot *poldslot){ u8 status; int rc = 0; u8 disable = 0; u8 update = 0; debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); // bit 0 - HPC_SLOT_POWER if ((pslot->status & 0x01) != (poldslot->status & 0x01)) update = 1; // bit 1 - HPC_SLOT_CONNECT // ignore // bit 2 - HPC_SLOT_ATTN if ((pslot->status & 0x04) != (poldslot->status & 0x04)) update = 1; // bit 3 - HPC_SLOT_PRSNT2 // bit 4 - HPC_SLOT_PRSNT1 if (((pslot->status & 0x08) != (poldslot->status & 0x08)) || ((pslot->status & 0x10) != (poldslot->status & 0x10))) update = 1; // bit 5 - HPC_SLOT_PWRGD if ((pslot->status & 0x20) != (poldslot->status & 0x20)) // OFF -> ON: ignore, ON -> OFF: disable slot if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) disable = 1; // bit 6 - HPC_SLOT_BUS_SPEED // ignore // bit 7 - HPC_SLOT_LATCH if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { update = 1; // OPEN -> CLOSE if (pslot->status & 0x80) { if (SLOT_PWRGD (pslot->status)) { // power goes on and off after closing latch // check again to make sure power is still ON msleep(1000); rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status); if (SLOT_PWRGD (status)) update = 1; else // overwrite power in pslot to OFF pslot->status &= ~HPC_SLOT_POWER; } } // CLOSE -> OPEN else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) { disable = 1; } // else - ignore } // bit 4 - HPC_SLOT_BLINK_ATTN if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) update = 1; if (disable) { debug ("process_changeinstatus - disable slot\n"); pslot->flag = 0; rc = ibmphp_do_disable_slot (pslot); } if (update || disable) { ibmphp_update_slot_info (pslot); } debug ("%s - Exit rc[%d] disable[%x] update[%x]\n", __func__, rc, disable, update); return rc;}/*----------------------------------------------------------------------* Name: process_changeinlatch** Action: compare old and new latch reg status, process the change** Input: old and current latch register status** Return 0 or error codes* Value:*---------------------------------------------------------------------*/static int process_changeinlatch (u8 old, u8 new, struct controller *ctrl){ struct slot myslot, *pslot; u8 i; u8 mask; int rc = 0; debug ("%s - Entry old[%x], new[%x]\n", __func__, old, new); // bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) { mask = 0x01 << i; if ((mask & old) != (mask & new)) { pslot = ibmphp_get_slot_from_physical_num (i); if (pslot) { memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot)); rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); debug ("%s - call process_changeinstatus for slot[%d]\n", __func__, i); process_changeinstatus (pslot, &myslot); } else { rc = -EINVAL; err ("%s - Error bad pointer for slot[%d]\n", __func__, i); } } } debug ("%s - Exit rc[%d]\n", __func__, rc); return rc;}/*----------------------------------------------------------------------* Name: ibmphp_hpc_start_poll_thread** Action: start polling thread*---------------------------------------------------------------------*/int __init ibmphp_hpc_start_poll_thread (void){ debug ("%s - Entry\n", __func__); ibmphp_poll_thread = kthread_run(poll_hpc, NULL, "hpc_poll"); if (IS_ERR(ibmphp_poll_thread)) { err ("%s - Error, thread not started\n", __func__); return PTR_ERR(ibmphp_poll_thread); } return 0;}/*----------------------------------------------------------------------* Name: ibmphp_hpc_stop_poll_thread** Action: stop polling thread and cleanup*---------------------------------------------------------------------*/void __exit ibmphp_hpc_stop_poll_thread (void){ debug ("%s - Entry\n", __func__); kthread_stop(ibmphp_poll_thread); debug ("before locking operations \n"); ibmphp_lock_operations (); debug ("after locking operations \n"); // wait for poll thread to exit debug ("before sem_exit down \n"); down (&sem_exit); debug ("after sem_exit down \n"); // cleanup debug ("before free_hpc_access \n"); free_hpc_access (); debug ("after free_hpc_access \n"); ibmphp_unlock_operations (); debug ("after unlock operations \n"); up (&sem_exit); debug ("after sem exit up\n"); debug ("%s - Exit\n", __func__);}/*----------------------------------------------------------------------* Name: hpc_wait_ctlr_notworking** Action: wait until the controller is in a not working state** Return 0, HPC_ERROR* Value:*---------------------------------------------------------------------*/static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void __iomem *wpg_bbar, u8 * pstatus){ int rc = 0; u8 done = 0; debug_polling ("hpc_wait_ctlr_notworking - Entry timeout[%d]\n", timeout); while (!done) { *pstatus = ctrl_read (ctlr_ptr, wpg_bbar, WPG_CTLR_INDEX); if (*pstatus == HPC_ERROR) { rc = HPC_ERROR; done = 1; } if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO) done = 1; if (!done) { msleep(1000); if (timeout < 1) { done = 1; err ("HPCreadslot - Error ctlr timeout\n"); rc = HPC_ERROR; } else timeout--; } } debug_polling ("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n", rc, *pstatus); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -