📄 lpfc_init.c
字号:
struct lpfc_iocbq *iocb; struct lpfc_dmabuf *mp1, *mp2; cnt += pring->missbufcnt; /* While there are buffers to post */ while (cnt > 0) { /* Allocate buffer for command iocb */ spin_lock_irq(phba->host->host_lock); iocb = lpfc_sli_get_iocbq(phba); spin_unlock_irq(phba->host->host_lock); if (iocb == NULL) { pring->missbufcnt = cnt; return cnt; } icmd = &iocb->iocb; /* 2 buffers can be posted per command */ /* Allocate buffer to post */ mp1 = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); if (mp1) mp1->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &mp1->phys); if (mp1 == 0 || mp1->virt == 0) { kfree(mp1); spin_lock_irq(phba->host->host_lock); lpfc_sli_release_iocbq(phba, iocb); spin_unlock_irq(phba->host->host_lock); pring->missbufcnt = cnt; return cnt; } INIT_LIST_HEAD(&mp1->list); /* Allocate buffer to post */ if (cnt > 1) { mp2 = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); if (mp2) mp2->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &mp2->phys); if (mp2 == 0 || mp2->virt == 0) { kfree(mp2); lpfc_mbuf_free(phba, mp1->virt, mp1->phys); kfree(mp1); spin_lock_irq(phba->host->host_lock); lpfc_sli_release_iocbq(phba, iocb); spin_unlock_irq(phba->host->host_lock); pring->missbufcnt = cnt; return cnt; } INIT_LIST_HEAD(&mp2->list); } else { mp2 = NULL; } icmd->un.cont64[0].addrHigh = putPaddrHigh(mp1->phys); icmd->un.cont64[0].addrLow = putPaddrLow(mp1->phys); icmd->un.cont64[0].tus.f.bdeSize = FCELSSIZE; icmd->ulpBdeCount = 1; cnt--; if (mp2) { icmd->un.cont64[1].addrHigh = putPaddrHigh(mp2->phys); icmd->un.cont64[1].addrLow = putPaddrLow(mp2->phys); icmd->un.cont64[1].tus.f.bdeSize = FCELSSIZE; cnt--; icmd->ulpBdeCount = 2; } icmd->ulpCommand = CMD_QUE_RING_BUF64_CN; icmd->ulpLe = 1; spin_lock_irq(phba->host->host_lock); if (lpfc_sli_issue_iocb(phba, pring, iocb, 0) == IOCB_ERROR) { lpfc_mbuf_free(phba, mp1->virt, mp1->phys); kfree(mp1); cnt++; if (mp2) { lpfc_mbuf_free(phba, mp2->virt, mp2->phys); kfree(mp2); cnt++; } lpfc_sli_release_iocbq(phba, iocb); pring->missbufcnt = cnt; spin_unlock_irq(phba->host->host_lock); return cnt; } spin_unlock_irq(phba->host->host_lock); lpfc_sli_ringpostbuf_put(phba, pring, mp1); if (mp2) { lpfc_sli_ringpostbuf_put(phba, pring, mp2); } } pring->missbufcnt = 0; return 0;}/************************************************************************//* *//* lpfc_post_rcv_buf *//* This routine post initial rcv buffers to the configured rings *//* *//************************************************************************/static intlpfc_post_rcv_buf(struct lpfc_hba * phba){ struct lpfc_sli *psli = &phba->sli; /* Ring 0, ELS / CT buffers */ lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], LPFC_BUF_RING0, 1); /* Ring 2 - FCP no buffers needed */ return 0;}#define S(N,V) (((V)<<(N))|((V)>>(32-(N))))/************************************************************************//* *//* lpfc_sha_init *//* *//************************************************************************/static voidlpfc_sha_init(uint32_t * HashResultPointer){ HashResultPointer[0] = 0x67452301; HashResultPointer[1] = 0xEFCDAB89; HashResultPointer[2] = 0x98BADCFE; HashResultPointer[3] = 0x10325476; HashResultPointer[4] = 0xC3D2E1F0;}/************************************************************************//* *//* lpfc_sha_iterate *//* *//************************************************************************/static voidlpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer){ int t; uint32_t TEMP; uint32_t A, B, C, D, E; t = 16; do { HashWorkingPointer[t] = S(1, HashWorkingPointer[t - 3] ^ HashWorkingPointer[t - 8] ^ HashWorkingPointer[t - 14] ^ HashWorkingPointer[t - 16]); } while (++t <= 79); t = 0; A = HashResultPointer[0]; B = HashResultPointer[1]; C = HashResultPointer[2]; D = HashResultPointer[3]; E = HashResultPointer[4]; do { if (t < 20) { TEMP = ((B & C) | ((~B) & D)) + 0x5A827999; } else if (t < 40) { TEMP = (B ^ C ^ D) + 0x6ED9EBA1; } else if (t < 60) { TEMP = ((B & C) | (B & D) | (C & D)) + 0x8F1BBCDC; } else { TEMP = (B ^ C ^ D) + 0xCA62C1D6; } TEMP += S(5, A) + E + HashWorkingPointer[t]; E = D; D = C; C = S(30, B); B = A; A = TEMP; } while (++t <= 79); HashResultPointer[0] += A; HashResultPointer[1] += B; HashResultPointer[2] += C; HashResultPointer[3] += D; HashResultPointer[4] += E;}/************************************************************************//* *//* lpfc_challenge_key *//* *//************************************************************************/static voidlpfc_challenge_key(uint32_t * RandomChallenge, uint32_t * HashWorking){ *HashWorking = (*RandomChallenge ^ *HashWorking);}/************************************************************************//* *//* lpfc_hba_init *//* *//************************************************************************/voidlpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit){ int t; uint32_t *HashWorking; uint32_t *pwwnn = phba->wwnn; HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL); if (!HashWorking) return; memset(HashWorking, 0, (80 * sizeof(uint32_t))); HashWorking[0] = HashWorking[78] = *pwwnn++; HashWorking[1] = HashWorking[79] = *pwwnn; for (t = 0; t < 7; t++) lpfc_challenge_key(phba->RandomData + t, HashWorking + t); lpfc_sha_init(hbainit); lpfc_sha_iterate(hbainit, HashWorking); kfree(HashWorking);}static voidlpfc_cleanup(struct lpfc_hba * phba, uint32_t save_bind){ struct lpfc_nodelist *ndlp, *next_ndlp; /* clean up phba - lpfc specific */ lpfc_can_disctmo(phba); list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list, nlp_listp) { lpfc_nlp_remove(phba, ndlp); } list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, nlp_listp) { lpfc_nlp_remove(phba, ndlp); } list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list, nlp_listp) { lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); } list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, nlp_listp) { lpfc_nlp_remove(phba, ndlp); } list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, nlp_listp) { lpfc_nlp_remove(phba, ndlp); } list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list, nlp_listp) { lpfc_nlp_remove(phba, ndlp); } list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, nlp_listp) { lpfc_nlp_remove(phba, ndlp); } list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, nlp_listp) { lpfc_nlp_remove(phba, ndlp); } INIT_LIST_HEAD(&phba->fc_nlpmap_list); INIT_LIST_HEAD(&phba->fc_nlpunmap_list); INIT_LIST_HEAD(&phba->fc_unused_list); INIT_LIST_HEAD(&phba->fc_plogi_list); INIT_LIST_HEAD(&phba->fc_adisc_list); INIT_LIST_HEAD(&phba->fc_reglogin_list); INIT_LIST_HEAD(&phba->fc_prli_list); INIT_LIST_HEAD(&phba->fc_npr_list); phba->fc_map_cnt = 0; phba->fc_unmap_cnt = 0; phba->fc_plogi_cnt = 0; phba->fc_adisc_cnt = 0; phba->fc_reglogin_cnt = 0; phba->fc_prli_cnt = 0; phba->fc_npr_cnt = 0; phba->fc_unused_cnt= 0; return;}static voidlpfc_establish_link_tmo(unsigned long ptr){ struct lpfc_hba *phba = (struct lpfc_hba *)ptr; unsigned long iflag; /* Re-establishing Link, timer expired */ lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, "%d:1300 Re-establishing Link, timer expired " "Data: x%x x%x\n", phba->brd_no, phba->fc_flag, phba->hba_state); spin_lock_irqsave(phba->host->host_lock, iflag); phba->fc_flag &= ~FC_ESTABLISH_LINK; spin_unlock_irqrestore(phba->host->host_lock, iflag);}static intlpfc_stop_timer(struct lpfc_hba * phba){ struct lpfc_sli *psli = &phba->sli; /* Instead of a timer, this has been converted to a * deferred procedding list. */ while (!list_empty(&phba->freebufList)) { struct lpfc_dmabuf *mp = NULL; list_remove_head((&phba->freebufList), mp, struct lpfc_dmabuf, list); if (mp) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); } } del_timer_sync(&phba->fc_estabtmo); del_timer_sync(&phba->fc_disctmo); del_timer_sync(&phba->fc_fdmitmo); del_timer_sync(&phba->els_tmofunc); psli = &phba->sli; del_timer_sync(&psli->mbox_tmo); return(1);}intlpfc_online(struct lpfc_hba * phba){ if (!phba) return 0; if (!(phba->fc_flag & FC_OFFLINE_MODE)) return 0; lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "%d:0458 Bring Adapter online\n", phba->brd_no); if (!lpfc_sli_queue_setup(phba)) return 1; if (lpfc_sli_hba_setup(phba)) /* Initialize the HBA */ return 1; spin_lock_irq(phba->host->host_lock); phba->fc_flag &= ~FC_OFFLINE_MODE; spin_unlock_irq(phba->host->host_lock); return 0;}intlpfc_offline(struct lpfc_hba * phba){ struct lpfc_sli_ring *pring; struct lpfc_sli *psli; unsigned long iflag; int i = 0; if (!phba) return 0; if (phba->fc_flag & FC_OFFLINE_MODE) return 0; psli = &phba->sli; pring = &psli->ring[psli->fcp_ring]; lpfc_linkdown(phba); /* The linkdown event takes 30 seconds to timeout. */ while (pring->txcmplq_cnt) { mdelay(10); if (i++ > 3000) break; } /* stop all timers associated with this hba */ lpfc_stop_timer(phba); phba->work_hba_events = 0; lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, "%d:0460 Bring Adapter offline\n", phba->brd_no); /* Bring down the SLI Layer and cleanup. The HBA is offline now. */ lpfc_sli_hba_down(phba); lpfc_cleanup(phba, 1); spin_lock_irqsave(phba->host->host_lock, iflag); phba->fc_flag |= FC_OFFLINE_MODE; spin_unlock_irqrestore(phba->host->host_lock, iflag); return 0;}/******************************************************************************* Function name: lpfc_scsi_free** Description: Called from lpfc_pci_remove_one free internal driver resources*******************************************************************************/static intlpfc_scsi_free(struct lpfc_hba * phba){ struct lpfc_scsi_buf *sb, *sb_next; struct lpfc_iocbq *io, *io_next; spin_lock_irq(phba->host->host_lock); /* Release all the lpfc_scsi_bufs maintained by this host. */ list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) { list_del(&sb->list); pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data, sb->dma_handle); kfree(sb); phba->total_scsi_bufs--; } /* Release all the lpfc_iocbq entries maintained by this host. */ list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) { list_del(&io->list); kfree(io); phba->total_iocbq_bufs--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -