/******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.broadcom.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of version 2 of the GNU General * * Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful. * * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * * TO BE LEGALLY INVALID. See the GNU General Public License for * * more details, a copy of which can be found in the file COPYING * * included with this package. * *******************************************************************/ #include <linux/blkdev.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/lockdep.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_transport_fc.h> #include <scsi/fc/fc_fs.h> #include <linux/crash_dump.h> #ifdef CONFIG_X86 #include <asm/set_memory.h> #endif #include "lpfc_hw4.h" #include "lpfc_hw.h" #include "lpfc_sli.h" #include "lpfc_sli4.h" #include "lpfc_nl.h" #include "lpfc_disc.h" #include "lpfc.h" #include "lpfc_scsi.h" #include "lpfc_nvme.h" #include "lpfc_crtn.h" #include "lpfc_logmsg.h" #include "lpfc_compat.h" #include "lpfc_debugfs.h" #include "lpfc_vport.h" #include "lpfc_version.h" /* There are only four IOCB completion types. */ lpfc_iocb_type; /* Provide function prototypes local to this module. */ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *, uint8_t *, uint32_t *); static struct lpfc_iocbq * lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, struct lpfc_iocbq *rspiocbq); static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *, struct hbq_dmabuf *); static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf); static bool lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe); static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *, int); static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, struct lpfc_eqe *eqe, enum lpfc_poll_mode poll_mode); static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba); static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba); static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q); static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe); static uint16_t lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeq, struct lpfc_sglq *sglq); union lpfc_wqe128 lpfc_iread_cmd_template; union lpfc_wqe128 lpfc_iwrite_cmd_template; union lpfc_wqe128 lpfc_icmnd_cmd_template; /* Setup WQE templates for IOs */ void lpfc_wqe_cmd_template(void) { … } #if defined(CONFIG_64BIT) && defined(__LITTLE_ENDIAN) /** * lpfc_sli4_pcimem_bcopy - SLI4 memory copy function * @srcp: Source memory pointer. * @destp: Destination memory pointer. * @cnt: Number of words required to be copied. * Must be a multiple of sizeof(uint64_t) * * This function is used for copying data between driver memory * and the SLI WQ. This function also changes the endianness * of each word if native endianness is different from SLI * endianness. This function can be called with or without * lock. **/ static void lpfc_sli4_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt) { … } #else #define lpfc_sli4_pcimem_bcopy … #endif /** * lpfc_sli4_wq_put - Put a Work Queue Entry on an Work Queue * @q: The Work Queue to operate on. * @wqe: The work Queue Entry to put on the Work queue. * * This routine will copy the contents of @wqe to the next available entry on * the @q. This function will then ring the Work Queue Doorbell to signal the * HBA to start processing the Work Queue Entry. This function returns 0 if * successful. If no entries are available on @q then this function will return * -ENOMEM. * The caller is expected to hold the hbalock when calling this routine. **/ static int lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 *wqe) { … } /** * lpfc_sli4_wq_release - Updates internal hba index for WQ * @q: The Work Queue to operate on. * @index: The index to advance the hba index to. * * This routine will update the HBA index of a queue to reflect consumption of * Work Queue Entries by the HBA. When the HBA indicates that it has consumed * an entry the host calls this function to update the queue's internal * pointers. **/ static void lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index) { … } /** * lpfc_sli4_mq_put - Put a Mailbox Queue Entry on an Mailbox Queue * @q: The Mailbox Queue to operate on. * @mqe: The Mailbox Queue Entry to put on the Work queue. * * This routine will copy the contents of @mqe to the next available entry on * the @q. This function will then ring the Work Queue Doorbell to signal the * HBA to start processing the Work Queue Entry. This function returns 0 if * successful. If no entries are available on @q then this function will return * -ENOMEM. * The caller is expected to hold the hbalock when calling this routine. **/ static uint32_t lpfc_sli4_mq_put(struct lpfc_queue *q, struct lpfc_mqe *mqe) { … } /** * lpfc_sli4_mq_release - Updates internal hba index for MQ * @q: The Mailbox Queue to operate on. * * This routine will update the HBA index of a queue to reflect consumption of * a Mailbox Queue Entry by the HBA. When the HBA indicates that it has consumed * an entry the host calls this function to update the queue's internal * pointers. This routine returns the number of entries that were consumed by * the HBA. **/ static uint32_t lpfc_sli4_mq_release(struct lpfc_queue *q) { … } /** * lpfc_sli4_eq_get - Gets the next valid EQE from a EQ * @q: The Event Queue to get the first valid EQE from * * This routine will get the first valid Event Queue Entry from @q, update * the queue's internal hba index, and return the EQE. If no valid EQEs are in * the Queue (no more work to do), or the Queue is full of EQEs that have been * processed, but not popped back to the HBA then this routine will return NULL. **/ static struct lpfc_eqe * lpfc_sli4_eq_get(struct lpfc_queue *q) { … } /** * lpfc_sli4_eq_clr_intr - Turn off interrupts from this EQ * @q: The Event Queue to disable interrupts * **/ void lpfc_sli4_eq_clr_intr(struct lpfc_queue *q) { … } /** * lpfc_sli4_if6_eq_clr_intr - Turn off interrupts from this EQ * @q: The Event Queue to disable interrupts * **/ void lpfc_sli4_if6_eq_clr_intr(struct lpfc_queue *q) { … } /** * lpfc_sli4_write_eq_db - write EQ DB for eqe's consumed or arm state * @phba: adapter with EQ * @q: The Event Queue that the host has completed processing for. * @count: Number of elements that have been consumed * @arm: Indicates whether the host wants to arms this CQ. * * This routine will notify the HBA, by ringing the doorbell, that count * number of EQEs have been processed. The @arm parameter indicates whether * the queue should be rearmed when ringing the doorbell. **/ void lpfc_sli4_write_eq_db(struct lpfc_hba *phba, struct lpfc_queue *q, uint32_t count, bool arm) { … } /** * lpfc_sli4_if6_write_eq_db - write EQ DB for eqe's consumed or arm state * @phba: adapter with EQ * @q: The Event Queue that the host has completed processing for. * @count: Number of elements that have been consumed * @arm: Indicates whether the host wants to arms this CQ. * * This routine will notify the HBA, by ringing the doorbell, that count * number of EQEs have been processed. The @arm parameter indicates whether * the queue should be rearmed when ringing the doorbell. **/ void lpfc_sli4_if6_write_eq_db(struct lpfc_hba *phba, struct lpfc_queue *q, uint32_t count, bool arm) { … } static void __lpfc_sli4_consume_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, struct lpfc_eqe *eqe) { … } static void lpfc_sli4_eqcq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq) { … } static int lpfc_sli4_process_eq(struct lpfc_hba *phba, struct lpfc_queue *eq, u8 rearm, enum lpfc_poll_mode poll_mode) { … } /** * lpfc_sli4_cq_get - Gets the next valid CQE from a CQ * @q: The Completion Queue to get the first valid CQE from * * This routine will get the first valid Completion Queue Entry from @q, update * the queue's internal hba index, and return the CQE. If no valid CQEs are in * the Queue (no more work to do), or the Queue is full of CQEs that have been * processed, but not popped back to the HBA then this routine will return NULL. **/ static struct lpfc_cqe * lpfc_sli4_cq_get(struct lpfc_queue *q) { … } static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe) { … } /** * lpfc_sli4_write_cq_db - write cq DB for entries consumed or arm state. * @phba: the adapter with the CQ * @q: The Completion Queue that the host has completed processing for. * @count: the number of elements that were consumed * @arm: Indicates whether the host wants to arms this CQ. * * This routine will notify the HBA, by ringing the doorbell, that the * CQEs have been processed. The @arm parameter specifies whether the * queue should be rearmed when ringing the doorbell. **/ void lpfc_sli4_write_cq_db(struct lpfc_hba *phba, struct lpfc_queue *q, uint32_t count, bool arm) { … } /** * lpfc_sli4_if6_write_cq_db - write cq DB for entries consumed or arm state. * @phba: the adapter with the CQ * @q: The Completion Queue that the host has completed processing for. * @count: the number of elements that were consumed * @arm: Indicates whether the host wants to arms this CQ. * * This routine will notify the HBA, by ringing the doorbell, that the * CQEs have been processed. The @arm parameter specifies whether the * queue should be rearmed when ringing the doorbell. **/ void lpfc_sli4_if6_write_cq_db(struct lpfc_hba *phba, struct lpfc_queue *q, uint32_t count, bool arm) { … } /* * lpfc_sli4_rq_put - Put a Receive Buffer Queue Entry on a Receive Queue * * This routine will copy the contents of @wqe to the next available entry on * the @q. This function will then ring the Receive Queue Doorbell to signal the * HBA to start processing the Receive Queue Entry. This function returns the * index that the rqe was copied to if successful. If no entries are available * on @q then this function will return -ENOMEM. * The caller is expected to hold the hbalock when calling this routine. **/ int lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq, struct lpfc_rqe *hrqe, struct lpfc_rqe *drqe) { … } /* * lpfc_sli4_rq_release - Updates internal hba index for RQ * * This routine will update the HBA index of a queue to reflect consumption of * one Receive Queue Entry by the HBA. When the HBA indicates that it has * consumed an entry the host calls this function to update the queue's * internal pointers. This routine returns the number of entries that were * consumed by the HBA. **/ static uint32_t lpfc_sli4_rq_release(struct lpfc_queue *hq, struct lpfc_queue *dq) { … } /** * lpfc_cmd_iocb - Get next command iocb entry in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function returns pointer to next command iocb entry * in the command ring. The caller must hold hbalock to prevent * other threads consume the next command iocb. * SLI-2/SLI-3 provide different sized iocbs. **/ static inline IOCB_t * lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_resp_iocb - Get next response iocb entry in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function returns pointer to next response iocb entry * in the response ring. The caller must hold hbalock to make sure * that no other thread consume the next response iocb. * SLI-2/SLI-3 provide different sized iocbs. **/ static inline IOCB_t * lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * __lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool * @phba: Pointer to HBA context object. * * This function is called with hbalock held. This function * allocates a new driver iocb object from the iocb pool. If the * allocation is successful, it returns pointer to the newly * allocated iocb object else it returns NULL. **/ struct lpfc_iocbq * __lpfc_sli_get_iocbq(struct lpfc_hba *phba) { … } /** * __lpfc_clear_active_sglq - Remove the active sglq for this XRI. * @phba: Pointer to HBA context object. * @xritag: XRI value. * * This function clears the sglq pointer from the array of active * sglq's. The xritag that is passed in is used to index into the * array. Before the xritag can be used it needs to be adjusted * by subtracting the xribase. * * Returns sglq ponter = success, NULL = Failure. **/ struct lpfc_sglq * __lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xritag) { … } /** * __lpfc_get_active_sglq - Get the active sglq for this XRI. * @phba: Pointer to HBA context object. * @xritag: XRI value. * * This function returns the sglq pointer from the array of active * sglq's. The xritag that is passed in is used to index into the * array. Before the xritag can be used it needs to be adjusted * by subtracting the xribase. * * Returns sglq ponter = success, NULL = Failure. **/ struct lpfc_sglq * __lpfc_get_active_sglq(struct lpfc_hba *phba, uint16_t xritag) { … } /** * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap. * @phba: Pointer to HBA context object. * @xritag: xri used in this exchange. * @rrq: The RRQ to be cleared. * **/ void lpfc_clr_rrq_active(struct lpfc_hba *phba, uint16_t xritag, struct lpfc_node_rrq *rrq) { … } /** * lpfc_handle_rrq_active - Checks if RRQ has waithed RATOV. * @phba: Pointer to HBA context object. * * This function is called with hbalock held. This function * Checks if stop_time (ratov from setting rrq active) has * been reached, if it has and the send_rrq flag is set then * it will call lpfc_send_rrq. If the send_rrq flag is not set * then it will just call the routine to clear the rrq and * free the rrq resource. * The timer is set to the next rrq that is going to expire before * leaving the routine. * **/ void lpfc_handle_rrq_active(struct lpfc_hba *phba) { … } /** * lpfc_get_active_rrq - Get the active RRQ for this exchange. * @vport: Pointer to vport context object. * @xri: The xri used in the exchange. * @did: The targets DID for this exchange. * * returns NULL = rrq not found in the phba->active_rrq_list. * rrq = rrq for this xri and target. **/ struct lpfc_node_rrq * lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did) { … } /** * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport. * @vport: Pointer to vport context object. * @ndlp: Pointer to the lpfc_node_list structure. * If ndlp is NULL Remove all active RRQs for this vport from the * phba->active_rrq_list and clear the rrq. * If ndlp is not NULL then only remove rrqs for this vport & this ndlp. **/ void lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { … } /** * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap. * @phba: Pointer to HBA context object. * @ndlp: Targets nodelist pointer for this exchange. * @xritag: the xri in the bitmap to test. * * This function returns: * 0 = rrq not active for this xri * 1 = rrq is valid for this xri. **/ int lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint16_t xritag) { … } /** * lpfc_set_rrq_active - set RRQ active bit in xri_bitmap. * @phba: Pointer to HBA context object. * @ndlp: nodelist pointer for this target. * @xritag: xri used in this exchange. * @rxid: Remote Exchange ID. * @send_rrq: Flag used to determine if we should send rrq els cmd. * * This function takes the hbalock. * The active bit is always set in the active rrq xri_bitmap even * if there is no slot avaiable for the other rrq information. * * returns 0 rrq actived for this xri * < 0 No memory or invalid ndlp. **/ int lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, uint16_t xritag, uint16_t rxid, uint16_t send_rrq) { … } /** * __lpfc_sli_get_els_sglq - Allocates an iocb object from sgl pool * @phba: Pointer to HBA context object. * @piocbq: Pointer to the iocbq. * * The driver calls this function with either the nvme ls ring lock * or the fc els ring lock held depending on the iocb usage. This function * gets a new driver sglq object from the sglq list. If the list is not empty * then it is successful, it returns pointer to the newly allocated sglq * object else it returns NULL. **/ static struct lpfc_sglq * __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) { … } /** * __lpfc_sli_get_nvmet_sglq - Allocates an iocb object from sgl pool * @phba: Pointer to HBA context object. * @piocbq: Pointer to the iocbq. * * This function is called with the sgl_list lock held. This function * gets a new driver sglq object from the sglq list. If the * list is not empty then it is successful, it returns pointer to the newly * allocated sglq object else it returns NULL. **/ struct lpfc_sglq * __lpfc_sli_get_nvmet_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) { … } /** * lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool * @phba: Pointer to HBA context object. * * This function is called with no lock held. This function * allocates a new driver iocb object from the iocb pool. If the * allocation is successful, it returns pointer to the newly * allocated iocb object else it returns NULL. **/ struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *phba) { … } /** * __lpfc_sli_release_iocbq_s4 - Release iocb to the iocb pool * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * * This function is called to release the driver iocb object * to the iocb pool. The iotag in the iocb object * does not change for each use of the iocb object. This function * clears all other fields of the iocb object when it is freed. * The sqlq structure that holds the xritag and phys and virtual * mappings for the scatter gather list is retrieved from the * active array of sglq. The get of the sglq pointer also clears * the entry in the array. If the status of the IO indiactes that * this IO was aborted then the sglq entry it put on the * lpfc_abts_els_sgl_list until the CQ_ABORTED_XRI is received. If the * IO has good status or fails for any other reason then the sglq * entry is added to the free list (lpfc_els_sgl_list). The hbalock is * asserted held in the code path calling this routine. **/ static void __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { … } /** * __lpfc_sli_release_iocbq_s3 - Release iocb to the iocb pool * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * * This function is called to release the driver iocb object to the * iocb pool. The iotag in the iocb object does not change for each * use of the iocb object. This function clears all other fields of * the iocb object when it is freed. The hbalock is asserted held in * the code path calling this routine. **/ static void __lpfc_sli_release_iocbq_s3(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { … } /** * __lpfc_sli_release_iocbq - Release iocb to the iocb pool * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * * This function is called with hbalock held to release driver * iocb object to the iocb pool. The iotag in the iocb object * does not change for each use of the iocb object. This function * clears all other fields of the iocb object when it is freed. **/ static void __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { … } /** * lpfc_sli_release_iocbq - Release iocb to the iocb pool * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * * This function is called with no lock held to release the iocb to * iocb pool. **/ void lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { … } /** * lpfc_sli_cancel_iocbs - Cancel all iocbs from a list. * @phba: Pointer to HBA context object. * @iocblist: List of IOCBs. * @ulpstatus: ULP status in IOCB command field. * @ulpWord4: ULP word-4 in IOCB command field. * * This function is called with a list of IOCBs to cancel. It cancels the IOCB * on the list by invoking the complete callback function associated with the * IOCB with the provided @ulpstatus and @ulpword4 set to the IOCB commond * fields. **/ void lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, uint32_t ulpstatus, uint32_t ulpWord4) { … } /** * lpfc_sli_iocb_cmd_type - Get the iocb type * @iocb_cmnd: iocb command code. * * This function is called by ring event handler function to get the iocb type. * This function translates the iocb command to an iocb command type used to * decide the final disposition of each completed IOCB. * The function returns * LPFC_UNKNOWN_IOCB if it is an unsupported iocb * LPFC_SOL_IOCB if it is a solicited iocb completion * LPFC_ABORT_IOCB if it is an abort iocb * LPFC_UNSOL_IOCB if it is an unsolicited iocb * * The caller is not required to hold any lock. **/ static lpfc_iocb_type lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) { … } /** * lpfc_sli_ring_map - Issue config_ring mbox for all rings * @phba: Pointer to HBA context object. * * This function is called from SLI initialization code * to configure every ring of the HBA's SLI interface. The * caller is not required to hold any lock. This function issues * a config_ring mailbox command for each ring. * This function returns zero if successful else returns a negative * error code. **/ static int lpfc_sli_ring_map(struct lpfc_hba *phba) { … } /** * lpfc_sli_ringtxcmpl_put - Adds new iocb to the txcmplq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to the driver iocb object. * * The driver calls this function with the hbalock held for SLI3 ports or * the ring lock held for SLI4 ports. The function adds the * new iocb to txcmplq of the given ring. This function always returns * 0. If this function is called for ELS ring, this function checks if * there is a vport associated with the ELS command. This function also * starts els_tmofunc timer if this is an ELS command. **/ static int lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocb) { … } /** * lpfc_sli_ringtx_get - Get first element of the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function is called with hbalock held to get next * iocb in txq of the given ring. If there is any iocb in * the txq, the function returns first iocb in the list after * removing the iocb from the list, else it returns NULL. **/ struct lpfc_iocbq * lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. * @rspiocb: Pointer to driver response iocb object. * * This routine will inform the driver of any BW adjustments we need * to make. These changes will be picked up during the next CMF * timer interrupt. In addition, any BW changes will be logged * with LOG_CGN_MGMT. **/ static void lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { … } /** * lpfc_issue_cmf_sync_wqe - Issue a CMF_SYNC_WQE * @phba: Pointer to HBA context object. * @ms: ms to set in WQE interval, 0 means use init op * @total: Total rcv bytes for this interval * * This routine is called every CMF timer interrupt. Its purpose is * to issue a CMF_SYNC_WQE to the firmware to inform it of any events * that may indicate we have congestion (FPINs or Signals). Upon * completion, the firmware will indicate any BW restrictions the * driver may need to take. **/ int lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total) { … } /** * lpfc_sli_next_iocb_slot - Get next iocb slot in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function is called with hbalock held and the caller must post the * iocb without releasing the lock. If the caller releases the lock, * iocb slot returned by the function is not guaranteed to be available. * The function returns pointer to the next available iocb slot if there * is available slot in the ring, else it returns NULL. * If the get index of the ring is ahead of the put index, the function * will post an error attention event to the worker thread to take the * HBA to offline state. **/ static IOCB_t * lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_sli_next_iotag - Get an iotag for the iocb * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * * This function gets an iotag for the iocb. If there is no unused iotag and * the iocbq_lookup_len < 0xffff, this function allocates a bigger iotag_lookup * array and assigns a new iotag. * The function returns the allocated iotag if successful, else returns zero. * Zero is not a valid iotag. * The caller is not required to hold any lock. **/ uint16_t lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { … } /** * lpfc_sli_submit_iocb - Submit an iocb to the firmware * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @iocb: Pointer to iocb slot in the ring. * @nextiocb: Pointer to driver iocb object which need to be * posted to firmware. * * This function is called to post a new iocb to the firmware. This * function copies the new iocb to ring iocb slot and updates the * ring pointers. It adds the new iocb to txcmplq if there is * a completion call back for this iocb else the function will free the * iocb object. The hbalock is asserted held in the code path calling * this routine. **/ static void lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, IOCB_t *iocb, struct lpfc_iocbq *nextiocb) { … } /** * lpfc_sli_update_full_ring - Update the chip attention register * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * The caller is not required to hold any lock for calling this function. * This function updates the chip attention bits for the ring to inform firmware * that there are pending work to be done for this ring and requests an * interrupt when there is space available in the ring. This function is * called when the driver is unable to post more iocbs to the ring due * to unavailability of space in the ring. **/ static void lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_sli_update_ring - Update chip attention register * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function updates the chip attention register bit for the * given ring to inform HBA that there is more work to be done * in this ring. The caller is not required to hold any lock. **/ static void lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_sli_resume_iocb - Process iocbs in the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function is called with hbalock held to post pending iocbs * in the txq to the firmware. This function is called when driver * detects space available in the ring. **/ static void lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_sli_next_hbq_slot - Get next hbq entry for the HBQ * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * * This function is called with hbalock held to get the next * available slot for the given HBQ. If there is free slot * available for the HBQ it will return pointer to the next available * HBQ entry else it will return NULL. **/ static struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) { … } /** * lpfc_sli_hbqbuf_free_all - Free all the hbq buffers * @phba: Pointer to HBA context object. * * This function is called with no lock held to free all the * hbq buffers while uninitializing the SLI interface. It also * frees the HBQ buffers returned by the firmware but not yet * processed by the upper layers. **/ void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) { … } /** * lpfc_sli_hbq_to_firmware - Post the hbq buffer to firmware * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * @hbq_buf: Pointer to HBQ buffer. * * This function is called with the hbalock held to post a * hbq buffer to the firmware. If the function finds an empty * slot in the HBQ, it will post the buffer. The function will return * pointer to the hbq entry if it successfully post the buffer * else it will return NULL. **/ static int lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, struct hbq_dmabuf *hbq_buf) { … } /** * lpfc_sli_hbq_to_firmware_s3 - Post the hbq buffer to SLI3 firmware * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * @hbq_buf: Pointer to HBQ buffer. * * This function is called with the hbalock held to post a hbq buffer to the * firmware. If the function finds an empty slot in the HBQ, it will post the * buffer and place it on the hbq_buffer_list. The function will return zero if * it successfully post the buffer else it will return an error. **/ static int lpfc_sli_hbq_to_firmware_s3(struct lpfc_hba *phba, uint32_t hbqno, struct hbq_dmabuf *hbq_buf) { … } /** * lpfc_sli_hbq_to_firmware_s4 - Post the hbq buffer to SLI4 firmware * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * @hbq_buf: Pointer to HBQ buffer. * * This function is called with the hbalock held to post an RQE to the SLI4 * firmware. If able to post the RQE to the RQ it will queue the hbq entry to * the hbq_buffer_list and return zero, otherwise it will return an error. **/ static int lpfc_sli_hbq_to_firmware_s4(struct lpfc_hba *phba, uint32_t hbqno, struct hbq_dmabuf *hbq_buf) { … } /* HBQ for ELS and CT traffic. */ static struct lpfc_hbq_init lpfc_els_hbq = …; /* Array of HBQs */ struct lpfc_hbq_init *lpfc_hbq_defs[] = …; /** * lpfc_sli_hbqbuf_fill_hbqs - Post more hbq buffers to HBQ * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * @count: Number of HBQ buffers to be posted. * * This function is called with no lock held to post more hbq buffers to the * given HBQ. The function returns the number of HBQ buffers successfully * posted. **/ static int lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) { … } /** * lpfc_sli_hbqbuf_add_hbqs - Post more HBQ buffers to firmware * @phba: Pointer to HBA context object. * @qno: HBQ number. * * This function posts more buffers to the HBQ. This function * is called with no lock held. The function returns the number of HBQ entries * successfully allocated. **/ int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno) { … } /** * lpfc_sli_hbqbuf_init_hbqs - Post initial buffers to the HBQ * @phba: Pointer to HBA context object. * @qno: HBQ queue number. * * This function is called from SLI initialization code path with * no lock held to post initial HBQ buffers to firmware. The * function returns the number of HBQ entries successfully allocated. **/ static int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno) { … } /* * lpfc_sli_hbqbuf_get - Remove the first hbq off of an hbq list * * This function removes the first hbq buffer on an hbq list and returns a * pointer to that buffer. If it finds no buffers on the list it returns NULL. **/ static struct hbq_dmabuf * lpfc_sli_hbqbuf_get(struct list_head *rb_list) { … } /** * lpfc_sli_rqbuf_get - Remove the first dma buffer off of an RQ list * @phba: Pointer to HBA context object. * @hrq: HBQ number. * * This function removes the first RQ buffer on an RQ buffer list and returns a * pointer to that buffer. If it finds no buffers on the list it returns NULL. **/ static struct rqb_dmabuf * lpfc_sli_rqbuf_get(struct lpfc_hba *phba, struct lpfc_queue *hrq) { … } /** * lpfc_sli_hbqbuf_find - Find the hbq buffer associated with a tag * @phba: Pointer to HBA context object. * @tag: Tag of the hbq buffer. * * This function searches for the hbq buffer associated with the given tag in * the hbq buffer list. If it finds the hbq buffer, it returns the hbq_buffer * otherwise it returns NULL. **/ static struct hbq_dmabuf * lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) { … } /** * lpfc_sli_free_hbq - Give back the hbq buffer to firmware * @phba: Pointer to HBA context object. * @hbq_buffer: Pointer to HBQ buffer. * * This function is called with hbalock. This function gives back * the hbq buffer to firmware. If the HBQ does not have space to * post the buffer, it will free the buffer. **/ void lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer) { … } /** * lpfc_sli_chk_mbx_command - Check if the mailbox is a legitimate mailbox * @mbxCommand: mailbox command code. * * This function is called by the mailbox event handler function to verify * that the completed mailbox command is a legitimate mailbox command. If the * completed mailbox is not known to the function, it will return MBX_SHUTDOWN * and the mailbox event handler will take the HBA offline. **/ static int lpfc_sli_chk_mbx_command(uint8_t mbxCommand) { … } /** * lpfc_sli_wake_mbox_wait - lpfc_sli_issue_mbox_wait mbox completion handler * @phba: Pointer to HBA context object. * @pmboxq: Pointer to mailbox command. * * This is completion handler function for mailbox commands issued from * lpfc_sli_issue_mbox_wait function. This function is called by the * mailbox event handler function with no lock held. This function * will wake up thread waiting on the wait queue pointed by context1 * of the mailbox. **/ void lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { … } static void __lpfc_sli_rpi_release(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { … } void lpfc_sli_rpi_release(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { … } /** * lpfc_sli_def_mbox_cmpl - Default mailbox completion handler * @phba: Pointer to HBA context object. * @pmb: Pointer to mailbox object. * * This function is the default mailbox completion handler. It * frees the memory resources associated with the completed mailbox * command. If the completed command is a REG_LOGIN mailbox command, * this function will issue a UREG_LOGIN to re-claim the RPI. **/ void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { … } /** * lpfc_sli4_unreg_rpi_cmpl_clr - mailbox completion handler * @phba: Pointer to HBA context object. * @pmb: Pointer to mailbox object. * * This function is the unreg rpi mailbox completion handler. It * frees the memory resources associated with the completed mailbox * command. An additional reference is put on the ndlp to prevent * lpfc_nlp_release from freeing the rpi bit in the bitmask before * the unreg mailbox command completes, this routine puts the * reference back. * **/ void lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { … } /** * lpfc_sli_handle_mb_event - Handle mailbox completions from firmware * @phba: Pointer to HBA context object. * * This function is called with no lock held. This function processes all * the completed mailbox commands and gives it to upper layers. The interrupt * service routine processes mailbox completion interrupt and adds completed * mailbox commands to the mboxq_cmpl queue and signals the worker thread. * Worker thread call lpfc_sli_handle_mb_event, which will return the * completed mailbox commands in mboxq_cmpl queue to the upper layers. This * function returns the mailbox commands to the upper layer by calling the * completion handler function of each mailbox. **/ int lpfc_sli_handle_mb_event(struct lpfc_hba *phba) { … } /** * lpfc_sli_get_buff - Get the buffer associated with the buffer tag * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @tag: buffer tag. * * This function is called with no lock held. When QUE_BUFTAG_BIT bit * is set in the tag the buffer is posted for a particular exchange, * the function will return the buffer without replacing the buffer. * If the buffer is for unsolicited ELS or CT traffic, this function * returns the buffer and also posts another buffer to the firmware. **/ static struct lpfc_dmabuf * lpfc_sli_get_buff(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint32_t tag) { … } /** * lpfc_nvme_unsol_ls_handler - Process an unsolicited event data buffer * containing a NVME LS request. * @phba: pointer to lpfc hba data structure. * @piocb: pointer to the iocbq struct representing the sequence starting * frame. * * This routine initially validates the NVME LS, validates there is a login * with the port that sent the LS, and then calls the appropriate nvme host * or target LS request handler. **/ static void lpfc_nvme_unsol_ls_handler(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) { … } /** * lpfc_complete_unsol_iocb - Complete an unsolicited sequence * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @saveq: Pointer to the iocbq struct representing the sequence starting frame. * @fch_r_ctl: the r_ctl for the first frame of the sequence. * @fch_type: the type for the first frame of the sequence. * * This function is called with no lock held. This function uses the r_ctl and * type of the received sequence to find the correct callback function to call * to process the sequence. **/ static int lpfc_complete_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *saveq, uint32_t fch_r_ctl, uint32_t fch_type) { … } static void lpfc_sli_prep_unsol_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *saveq) { … } /** * lpfc_sli_process_unsol_iocb - Unsolicited iocb handler * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @saveq: Pointer to the unsolicited iocb. * * This function is called with no lock held by the ring event handler * when there is an unsolicited iocb posted to the response ring by the * firmware. This function gets the buffer associated with the iocbs * and calls the event handler for the ring. This function handles both * qring buffers and hbq buffers. * When the function returns 1 the caller can free the iocb object otherwise * upper layer functions will free the iocb objects. **/ static int lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *saveq) { … } /** * lpfc_sli_iocbq_lookup - Find command iocb for the given response iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @prspiocb: Pointer to response iocb object. * * This function looks up the iocb_lookup table to get the command iocb * corresponding to the given response iocb using the iotag of the * response iocb. The driver calls this function with the hbalock held * for SLI3 ports or the ring lock held for SLI4 ports. * This function returns the command iocb object if it finds the command * iocb else returns NULL. **/ static struct lpfc_iocbq * lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *prspiocb) { … } /** * lpfc_sli_iocbq_lookup_by_tag - Find command iocb for the iotag * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @iotag: IOCB tag. * * This function looks up the iocb_lookup table to get the command iocb * corresponding to the given iotag. The driver calls this function with * the ring lock held because this function is an SLI4 port only helper. * This function returns the command iocb object if it finds the command * iocb else returns NULL. **/ static struct lpfc_iocbq * lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint16_t iotag) { … } /** * lpfc_sli_process_sol_iocb - process solicited iocb completion * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @saveq: Pointer to the response iocb to be processed. * * This function is called by the ring event handler for non-fcp * rings when there is a new response iocb in the response ring. * The caller is not required to hold any locks. This function * gets the command iocb associated with the response iocb and * calls the completion handler for the command iocb. If there * is no completion handler, the function will free the resources * associated with command iocb. If the response iocb is for * an already aborted command iocb, the status of the completion * is changed to IOSTAT_LOCAL_REJECT/IOERR_SLI_ABORTED. * This function always returns 1. **/ static int lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *saveq) { … } /** * lpfc_sli_rsp_pointers_error - Response ring pointer error handler * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function is called from the iocb ring event handlers when * put pointer is ahead of the get pointer for a ring. This function signal * an error attention condition to the worker thread and the worker * thread will transition the HBA to offline state. **/ static void lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_poll_eratt - Error attention polling timer timeout handler * @t: Context to fetch pointer to address of HBA context object from. * * This function is invoked by the Error Attention polling timer when the * timer times out. It will check the SLI Error Attention register for * possible attention events. If so, it will post an Error Attention event * and wake up worker thread to process it. Otherwise, it will set up the * Error Attention polling timer for the next poll. **/ void lpfc_poll_eratt(struct timer_list *t) { … } /** * lpfc_sli_handle_fast_ring_event - Handle ring events on FCP ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mask: Host attention register mask for this ring. * * This function is called from the interrupt context when there is a ring * event for the fcp ring. The caller does not hold any lock. * The function processes each response iocb in the response ring until it * finds an iocb with LE bit set and chains all the iocbs up to the iocb with * LE bit set. The function will call the completion handler of the command iocb * if the response iocb indicates a completion for a command iocb or it is * an abort completion. The function will call lpfc_sli_process_unsol_iocb * function if this is an unsolicited iocb. * This routine presumes LPFC_FCP_RING handling and doesn't bother * to check it explicitly. */ int lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint32_t mask) { … } /** * lpfc_sli_sp_handle_rspiocb - Handle slow-path response iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @rspiocbp: Pointer to driver response IOCB object. * * This function is called from the worker thread when there is a slow-path * response IOCB to process. This function chains all the response iocbs until * seeing the iocb with the LE bit set. The function will call * lpfc_sli_process_sol_iocb function if the response iocb indicates a * completion of a command iocb. The function will call the * lpfc_sli_process_unsol_iocb function if this is an unsolicited iocb. * The function frees the resources or calls the completion handler if this * iocb is an abort completion. The function returns NULL when the response * iocb has the LE bit set and all the chained iocbs are processed, otherwise * this function shall chain the iocb on to the iocb_continueq and return the * response iocb passed in. **/ static struct lpfc_iocbq * lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *rspiocbp) { … } /** * lpfc_sli_handle_slow_ring_event - Wrapper func for handling slow-path iocbs * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mask: Host attention register mask for this ring. * * This routine wraps the actual slow_ring event process routine from the * API jump table function pointer from the lpfc_hba struct. **/ void lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint32_t mask) { … } /** * lpfc_sli_handle_slow_ring_event_s3 - Handle SLI3 ring event for non-FCP rings * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mask: Host attention register mask for this ring. * * This function is called from the worker thread when there is a ring event * for non-fcp rings. The caller does not hold any lock. The function will * remove each response iocb in the response ring and calls the handle * response iocb routine (lpfc_sli_sp_handle_rspiocb) to process it. **/ static void lpfc_sli_handle_slow_ring_event_s3(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint32_t mask) { … } /** * lpfc_sli_handle_slow_ring_event_s4 - Handle SLI4 slow-path els events * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mask: Host attention register mask for this ring. * * This function is called from the worker thread when there is a pending * ELS response iocb on the driver internal slow-path response iocb worker * queue. The caller does not hold any lock. The function will remove each * response iocb from the response worker queue and calls the handle * response iocb routine (lpfc_sli_sp_handle_rspiocb) to process it. **/ static void lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint32_t mask) { … } /** * lpfc_sli_abort_iocb_ring - Abort all iocbs in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * * This function aborts all iocbs in the given ring and frees all the iocb * objects in txq. This function issues an abort iocb for all the iocb commands * in txcmplq. The iocbs in the txcmplq is not guaranteed to complete before * the return of this function. The caller is not required to hold any locks. **/ void lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { … } /** * lpfc_sli_abort_fcp_rings - Abort all iocbs in all FCP rings * @phba: Pointer to HBA context object. * * This function aborts all iocbs in FCP rings and frees all the iocb * objects in txq. This function issues an abort iocb for all the iocb commands * in txcmplq. The iocbs in the txcmplq is not guaranteed to complete before * the return of this function. The caller is not required to hold any locks. **/ void lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba) { … } /** * lpfc_sli_flush_io_rings - flush all iocbs in the IO ring * @phba: Pointer to HBA context object. * * This function flushes all iocbs in the IO ring and frees all the iocb * objects in txq and txcmplq. This function will not issue abort iocbs * for all the iocb commands in txcmplq, they will just be returned with * IOERR_SLI_DOWN. This function is invoked with EEH when device's PCI * slot has been permanently disabled. **/ void lpfc_sli_flush_io_rings(struct lpfc_hba *phba) { … } /** * lpfc_sli_brdready_s3 - Check for sli3 host ready status * @phba: Pointer to HBA context object. * @mask: Bit mask to be checked. * * This function reads the host status register and compares * with the provided bit mask to check if HBA completed * the restart. This function will wait in a loop for the * HBA to complete restart. If the HBA does not restart within * 15 iterations, the function will reset the HBA again. The * function returns 1 when HBA fail to restart otherwise returns * zero. **/ static int lpfc_sli_brdready_s3(struct lpfc_hba *phba, uint32_t mask) { … } /** * lpfc_sli_brdready_s4 - Check for sli4 host ready status * @phba: Pointer to HBA context object. * @mask: Bit mask to be checked. * * This function checks the host status register to check if HBA is * ready. This function will wait in a loop for the HBA to be ready * If the HBA is not ready , the function will will reset the HBA PCI * function again. The function returns 1 when HBA fail to be ready * otherwise returns zero. **/ static int lpfc_sli_brdready_s4(struct lpfc_hba *phba, uint32_t mask) { … } /** * lpfc_sli_brdready - Wrapper func for checking the hba readyness * @phba: Pointer to HBA context object. * @mask: Bit mask to be checked. * * This routine wraps the actual SLI3 or SLI4 hba readyness check routine * from the API jump table function pointer from the lpfc_hba struct. **/ int lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask) { … } #define BARRIER_TEST_PATTERN … /** * lpfc_reset_barrier - Make HBA ready for HBA reset * @phba: Pointer to HBA context object. * * This function is called before resetting an HBA. This function is called * with hbalock held and requests HBA to quiesce DMAs before a reset. **/ void lpfc_reset_barrier(struct lpfc_hba *phba) { … } /** * lpfc_sli_brdkill - Issue a kill_board mailbox command * @phba: Pointer to HBA context object. * * This function issues a kill_board mailbox command and waits for * the error attention interrupt. This function is called for stopping * the firmware processing. The caller is not required to hold any * locks. This function calls lpfc_hba_down_post function to free * any pending commands after the kill. The function will return 1 when it * fails to kill the board else will return 0. **/ int lpfc_sli_brdkill(struct lpfc_hba *phba) { … } /** * lpfc_sli_brdreset - Reset a sli-2 or sli-3 HBA * @phba: Pointer to HBA context object. * * This function resets the HBA by writing HC_INITFF to the control * register. After the HBA resets, this function resets all the iocb ring * indices. This function disables PCI layer parity checking during * the reset. * This function returns 0 always. * The caller is not required to hold any locks. **/ int lpfc_sli_brdreset(struct lpfc_hba *phba) { … } /** * lpfc_sli4_brdreset - Reset a sli-4 HBA * @phba: Pointer to HBA context object. * * This function resets a SLI4 HBA. This function disables PCI layer parity * checking during resets the device. The caller is not required to hold * any locks. * * This function returns 0 on success else returns negative error code. **/ int lpfc_sli4_brdreset(struct lpfc_hba *phba) { … } /** * lpfc_sli_brdrestart_s3 - Restart a sli-3 hba * @phba: Pointer to HBA context object. * * This function is called in the SLI initialization code path to * restart the HBA. The caller is not required to hold any lock. * This function writes MBX_RESTART mailbox command to the SLIM and * resets the HBA. At the end of the function, it calls lpfc_hba_down_post * function to free any pending commands. The function enables * POST only during the first initialization. The function returns zero. * The function does not guarantee completion of MBX_RESTART mailbox * command before the return of this function. **/ static int lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) { … } /** * lpfc_sli_brdrestart_s4 - Restart the sli-4 hba * @phba: Pointer to HBA context object. * * This function is called in the SLI initialization code path to restart * a SLI4 HBA. The caller is not required to hold any lock. * At the end of the function, it calls lpfc_hba_down_post function to * free any pending commands. **/ static int lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) { … } /** * lpfc_sli_brdrestart - Wrapper func for restarting hba * @phba: Pointer to HBA context object. * * This routine wraps the actual SLI3 or SLI4 hba restart routine from the * API jump table function pointer from the lpfc_hba struct. **/ int lpfc_sli_brdrestart(struct lpfc_hba *phba) { … } /** * lpfc_sli_chipset_init - Wait for the restart of the HBA after a restart * @phba: Pointer to HBA context object. * * This function is called after a HBA restart to wait for successful * restart of the HBA. Successful restart of the HBA is indicated by * HS_FFRDY and HS_MBRDY bits. If the HBA fails to restart even after 15 * iteration, the function will restart the HBA again. The function returns * zero if HBA successfully restarted else returns negative error code. **/ int lpfc_sli_chipset_init(struct lpfc_hba *phba) { … } /** * lpfc_sli_hbq_count - Get the number of HBQs to be configured * * This function calculates and returns the number of HBQs required to be * configured. **/ int lpfc_sli_hbq_count(void) { … } /** * lpfc_sli_hbq_entry_count - Calculate total number of hbq entries * * This function adds the number of hbq entries in every HBQ to get * the total number of hbq entries required for the HBA and returns * the total count. **/ static int lpfc_sli_hbq_entry_count(void) { … } /** * lpfc_sli_hbq_size - Calculate memory required for all hbq entries * * This function calculates amount of memory required for all hbq entries * to be configured and returns the total memory required. **/ int lpfc_sli_hbq_size(void) { … } /** * lpfc_sli_hbq_setup - configure and initialize HBQs * @phba: Pointer to HBA context object. * * This function is called during the SLI initialization to configure * all the HBQs and post buffers to the HBQ. The caller is not * required to hold any locks. This function will return zero if successful * else it will return negative error code. **/ static int lpfc_sli_hbq_setup(struct lpfc_hba *phba) { … } /** * lpfc_sli4_rb_setup - Initialize and post RBs to HBA * @phba: Pointer to HBA context object. * * This function is called during the SLI initialization to configure * all the HBQs and post buffers to the HBQ. The caller is not * required to hold any locks. This function will return zero if successful * else it will return negative error code. **/ static int lpfc_sli4_rb_setup(struct lpfc_hba *phba) { … } /** * lpfc_sli_config_port - Issue config port mailbox command * @phba: Pointer to HBA context object. * @sli_mode: sli mode - 2/3 * * This function is called by the sli initialization code path * to issue config_port mailbox command. This function restarts the * HBA firmware and issues a config_port mailbox command to configure * the SLI interface in the sli mode specified by sli_mode * variable. The caller is not required to hold any locks. * The function returns 0 if successful, else returns negative error * code. **/ int lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) { … } /** * lpfc_sli_hba_setup - SLI initialization function * @phba: Pointer to HBA context object. * * This function is the main SLI initialization function. This function * is called by the HBA initialization code, HBA reset code and HBA * error attention handler code. Caller is not required to hold any * locks. This function issues config_port mailbox command to configure * the SLI, setup iocb rings and HBQ rings. In the end the function * calls the config_port_post function to issue init_link mailbox * command and to start the discovery. The function will return zero * if successful, else it will return negative error code. **/ int lpfc_sli_hba_setup(struct lpfc_hba *phba) { … } /** * lpfc_sli4_read_fcoe_params - Read fcoe params from conf region * @phba: Pointer to HBA context object. * * This function issue a dump mailbox command to read config region * 23 and parse the records in the region and populate driver * data structure. **/ static int lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba) { … } /** * lpfc_sli4_read_rev - Issue READ_REV and collect vpd data * @phba: pointer to lpfc hba data structure. * @mboxq: pointer to the LPFC_MBOXQ_t structure. * @vpd: pointer to the memory to hold resulting port vpd data. * @vpd_size: On input, the number of bytes allocated to @vpd. * On output, the number of data bytes in @vpd. * * This routine executes a READ_REV SLI4 mailbox command. In * addition, this routine gets the port vpd data. * * Return codes * 0 - successful * -ENOMEM - could not allocated memory. **/ static int lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, uint8_t *vpd, uint32_t *vpd_size) { … } /** * lpfc_sli4_get_ctl_attr - Retrieve SLI4 device controller attributes * @phba: pointer to lpfc hba data structure. * * This routine retrieves SLI4 device physical port name this PCI function * is attached to. * * Return codes * 0 - successful * otherwise - failed to retrieve controller attributes **/ static int lpfc_sli4_get_ctl_attr(struct lpfc_hba *phba) { … } /** * lpfc_sli4_retrieve_pport_name - Retrieve SLI4 device physical port name * @phba: pointer to lpfc hba data structure. * * This routine retrieves SLI4 device physical port name this PCI function * is attached to. * * Return codes * 0 - successful * otherwise - failed to retrieve physical port name **/ static int lpfc_sli4_retrieve_pport_name(struct lpfc_hba *phba) { … } /** * lpfc_sli4_arm_cqeq_intr - Arm sli-4 device completion and event queues * @phba: pointer to lpfc hba data structure. * * This routine is called to explicitly arm the SLI4 device's completion and * event queues **/ static void lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba) { … } /** * lpfc_sli4_get_avail_extnt_rsrc - Get available resource extent count. * @phba: Pointer to HBA context object. * @type: The resource extent type. * @extnt_count: buffer to hold port available extent count. * @extnt_size: buffer to hold element count per extent. * * This function calls the port and retrievs the number of available * extents and their size for a particular extent type. * * Returns: 0 if successful. Nonzero otherwise. **/ int lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, uint16_t *extnt_count, uint16_t *extnt_size) { … } /** * lpfc_sli4_chk_avail_extnt_rsrc - Check for available SLI4 resource extents. * @phba: Pointer to HBA context object. * @type: The extent type to check. * * This function reads the current available extents from the port and checks * if the extent count or extent size has changed since the last access. * Callers use this routine post port reset to understand if there is a * extent reprovisioning requirement. * * Returns: * -Error: error indicates problem. * 1: Extent count or size has changed. * 0: No changes. **/ static int lpfc_sli4_chk_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type) { … } /** * lpfc_sli4_cfg_post_extnts - * @phba: Pointer to HBA context object. * @extnt_cnt: number of available extents. * @type: the extent type (rpi, xri, vfi, vpi). * @emb: buffer to hold either MBX_EMBED or MBX_NEMBED operation. * @mbox: pointer to the caller's allocated mailbox structure. * * This function executes the extents allocation request. It also * takes care of the amount of memory needed to allocate or get the * allocated extents. It is the caller's responsibility to evaluate * the response. * * Returns: * -Error: Error value describes the condition found. * 0: if successful **/ static int lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t extnt_cnt, uint16_t type, bool *emb, LPFC_MBOXQ_t *mbox) { … } /** * lpfc_sli4_alloc_extent - Allocate an SLI4 resource extent. * @phba: Pointer to HBA context object. * @type: The resource extent type to allocate. * * This function allocates the number of elements for the specified * resource type. **/ static int lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type) { … } /** * lpfc_sli4_dealloc_extent - Deallocate an SLI4 resource extent. * @phba: Pointer to HBA context object. * @type: the extent's type. * * This function deallocates all extents of a particular resource type. * SLI4 does not allow for deallocating a particular extent range. It * is the caller's responsibility to release all kernel memory resources. **/ static int lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) { … } static void lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox, uint32_t feature) { … } /** * lpfc_ras_stop_fwlog: Disable FW logging by the adapter * @phba: Pointer to HBA context object. * * Disable FW logging into host memory on the adapter. To * be done before reading logs from the host memory. **/ void lpfc_ras_stop_fwlog(struct lpfc_hba *phba) { … } /** * lpfc_sli4_ras_dma_free - Free memory allocated for FW logging. * @phba: Pointer to HBA context object. * * This function is called to free memory allocated for RAS FW logging * support in the driver. **/ void lpfc_sli4_ras_dma_free(struct lpfc_hba *phba) { … } /** * lpfc_sli4_ras_dma_alloc: Allocate memory for FW support * @phba: Pointer to HBA context object. * @fwlog_buff_count: Count of buffers to be created. * * This routine DMA memory for Log Write Position Data[LPWD] and buffer * to update FW log is posted to the adapter. * Buffer count is calculated based on module param ras_fwlog_buffsize * Size of each buffer posted to FW is 64K. **/ static int lpfc_sli4_ras_dma_alloc(struct lpfc_hba *phba, uint32_t fwlog_buff_count) { … } /** * lpfc_sli4_ras_mbox_cmpl: Completion handler for RAS MBX command * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * * Completion handler for driver's RAS MBX command to the device. **/ static void lpfc_sli4_ras_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { … } /** * lpfc_sli4_ras_fwlog_init: Initialize memory and post RAS MBX command * @phba: pointer to lpfc hba data structure. * @fwlog_level: Logging verbosity level. * @fwlog_enable: Enable/Disable logging. * * Initialize memory and post mailbox command to enable FW logging in host * memory. **/ int lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba, uint32_t fwlog_level, uint32_t fwlog_enable) { … } /** * lpfc_sli4_ras_setup - Check if RAS supported on the adapter * @phba: Pointer to HBA context object. * * Check if RAS is supported on the adapter and initialize it. **/ void lpfc_sli4_ras_setup(struct lpfc_hba *phba) { … } /** * lpfc_sli4_alloc_resource_identifiers - Allocate all SLI4 resource extents. * @phba: Pointer to HBA context object. * * This function allocates all SLI4 resource identifiers. **/ int lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) { … } /** * lpfc_sli4_dealloc_resource_identifiers - Deallocate all SLI4 resource extents. * @phba: Pointer to HBA context object. * * This function allocates the number of elements for the specified * resource type. **/ int lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) { … } /** * lpfc_sli4_get_allocated_extnts - Get the port's allocated extents. * @phba: Pointer to HBA context object. * @type: The resource extent type. * @extnt_cnt: buffer to hold port extent count response * @extnt_size: buffer to hold port extent size response. * * This function calls the port to read the host allocated extents * for a particular type. **/ int lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type, uint16_t *extnt_cnt, uint16_t *extnt_size) { … } /** * lpfc_sli4_repost_sgl_list - Repost the buffers sgl pages as block * @phba: pointer to lpfc hba data structure. * @sgl_list: linked link of sgl buffers to post * @cnt: number of linked list buffers * * This routine walks the list of buffers that have been allocated and * repost them to the port by using SGL block post. This is needed after a * pci_function_reset/warm_start or start. It attempts to construct blocks * of buffer sgls which contains contiguous xris and uses the non-embedded * SGL block post mailbox commands to post them to the port. For single * buffer sgl with non-contiguous xri, if any, it shall use embedded SGL post * mailbox command for posting. * * Returns: 0 = success, non-zero failure. **/ static int lpfc_sli4_repost_sgl_list(struct lpfc_hba *phba, struct list_head *sgl_list, int cnt) { … } /** * lpfc_sli4_repost_io_sgl_list - Repost all the allocated nvme buffer sgls * @phba: pointer to lpfc hba data structure. * * This routine walks the list of nvme buffers that have been allocated and * repost them to the port by using SGL block post. This is needed after a * pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine * is responsible for moving all nvme buffers on the lpfc_abts_nvme_sgl_list * to the lpfc_io_buf_list. If the repost fails, reject all nvme buffers. * * Returns: 0 = success, non-zero failure. **/ static int lpfc_sli4_repost_io_sgl_list(struct lpfc_hba *phba) { … } static void lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) { … } int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, struct lpfc_queue *drq, int count, int idx) { … } static void lpfc_mbx_cmpl_read_lds_params(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { … } int lpfc_read_lds_params(struct lpfc_hba *phba) { … } static void lpfc_mbx_cmpl_cgn_set_ftrs(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { … } int lpfc_config_cgn_signal(struct lpfc_hba *phba) { … } /** * lpfc_init_idle_stat_hb - Initialize idle_stat tracking * @phba: pointer to lpfc hba data structure. * * This routine initializes the per-eq idle_stat to dynamically dictate * polling decisions. * * Return codes: * None **/ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba) { … } static void lpfc_sli4_dip(struct lpfc_hba *phba) { … } /** * lpfc_rx_monitor_create_ring - Initialize ring buffer for rx_monitor * @rx_monitor: Pointer to lpfc_rx_info_monitor object * @entries: Number of rx_info_entry objects to allocate in ring * * Return: * 0 - Success * ENOMEM - Failure to kmalloc **/ int lpfc_rx_monitor_create_ring(struct lpfc_rx_info_monitor *rx_monitor, u32 entries) { … } /** * lpfc_rx_monitor_destroy_ring - Free ring buffer for rx_monitor * @rx_monitor: Pointer to lpfc_rx_info_monitor object * * Called after cancellation of cmf_timer. **/ void lpfc_rx_monitor_destroy_ring(struct lpfc_rx_info_monitor *rx_monitor) { … } /** * lpfc_rx_monitor_record - Insert an entry into rx_monitor's ring * @rx_monitor: Pointer to lpfc_rx_info_monitor object * @entry: Pointer to rx_info_entry * * Used to insert an rx_info_entry into rx_monitor's ring. Note that this is a * deep copy of rx_info_entry not a shallow copy of the rx_info_entry ptr. * * This is called from lpfc_cmf_timer, which is in timer/softirq context. * * In cases of old data overflow, we do a best effort of FIFO order. **/ void lpfc_rx_monitor_record(struct lpfc_rx_info_monitor *rx_monitor, struct rx_info_entry *entry) { … } /** * lpfc_rx_monitor_report - Read out rx_monitor's ring * @phba: Pointer to lpfc_hba object * @rx_monitor: Pointer to lpfc_rx_info_monitor object * @buf: Pointer to char buffer that will contain rx monitor info data * @buf_len: Length buf including null char * @max_read_entries: Maximum number of entries to read out of ring * * Used to dump/read what's in rx_monitor's ring buffer. * * If buf is NULL || buf_len == 0, then it is implied that we want to log the * information to kmsg instead of filling out buf. * * Return: * Number of entries read out of the ring **/ u32 lpfc_rx_monitor_report(struct lpfc_hba *phba, struct lpfc_rx_info_monitor *rx_monitor, char *buf, u32 buf_len, u32 max_read_entries) { … } /** * lpfc_cmf_setup - Initialize idle_stat tracking * @phba: Pointer to HBA context object. * * This is called from HBA setup during driver load or when the HBA * comes online. this does all the initialization to support CMF and MI. **/ static int lpfc_cmf_setup(struct lpfc_hba *phba) { … } static int lpfc_set_host_tm(struct lpfc_hba *phba) { … } /** * lpfc_sli4_hba_setup - SLI4 device initialization PCI function * @phba: Pointer to HBA context object. * * This function is the main SLI4 device initialization PCI function. This * function is called by the HBA initialization code, HBA reset code and * HBA error attention handler code. Caller is not required to hold any * locks. **/ int lpfc_sli4_hba_setup(struct lpfc_hba *phba) { … } /** * lpfc_mbox_timeout - Timeout call back function for mbox timer * @t: Context to fetch pointer to hba structure from. * * This is the callback function for mailbox timer. The mailbox * timer is armed when a new mailbox command is issued and the timer * is deleted when the mailbox complete. The function is called by * the kernel timer code when a mailbox does not complete within * expected time. This function wakes up the worker thread to * process the mailbox timeout and returns. All the processing is * done by the worker thread function lpfc_mbox_timeout_handler. **/ void lpfc_mbox_timeout(struct timer_list *t) { … } /** * lpfc_sli4_mbox_completions_pending - check to see if any mailbox completions * are pending * @phba: Pointer to HBA context object. * * This function checks if any mailbox completions are present on the mailbox * completion queue. **/ static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) { … } /** * lpfc_sli4_process_missed_mbox_completions - process mbox completions * that were missed. * @phba: Pointer to HBA context object. * * For sli4, it is possible to miss an interrupt. As such mbox completions * maybe missed causing erroneous mailbox timeouts to occur. This function * checks to see if mbox completions are on the mailbox completion queue * and will process all the completions associated with the eq for the * mailbox completion queue. **/ static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) { … } /** * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout * @phba: Pointer to HBA context object. * * This function is called from worker thread when a mailbox command times out. * The caller is not required to hold any locks. This function will reset the * HBA and recover all the pending commands. **/ void lpfc_mbox_timeout_handler(struct lpfc_hba *phba) { … } /** * lpfc_sli_issue_mbox_s3 - Issue an SLI3 mailbox command to firmware * @phba: Pointer to HBA context object. * @pmbox: Pointer to mailbox object. * @flag: Flag indicating how the mailbox need to be processed. * * This function is called by discovery code and HBA management code * to submit a mailbox command to firmware with SLI-3 interface spec. This * function gets the hbalock to protect the data structures. * The mailbox command can be submitted in polling mode, in which case * this function will wait in a polling loop for the completion of the * mailbox. * If the mailbox is submitted in no_wait mode (not polling) the * function will submit the command and returns immediately without waiting * for the mailbox completion. The no_wait is supported only when HBA * is in SLI2/SLI3 mode - interrupts are enabled. * The SLI interface allows only one mailbox pending at a time. If the * mailbox is issued in polling mode and there is already a mailbox * pending, then the function will return an error. If the mailbox is issued * in NO_WAIT mode and there is a mailbox pending already, the function * will return MBX_BUSY after queuing the mailbox into mailbox queue. * The sli layer owns the mailbox object until the completion of mailbox * command if this function return MBX_BUSY or MBX_SUCCESS. For all other * return codes the caller owns the mailbox command after the return of * the function. **/ static int lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) { … } /** * lpfc_sli4_async_mbox_block - Block posting SLI4 asynchronous mailbox command * @phba: Pointer to HBA context object. * * The function blocks the posting of SLI4 asynchronous mailbox commands from * the driver internal pending mailbox queue. It will then try to wait out the * possible outstanding mailbox command before return. * * Returns: * 0 - the outstanding mailbox command completed; otherwise, the wait for * the outstanding mailbox command timed out. **/ static int lpfc_sli4_async_mbox_block(struct lpfc_hba *phba) { … } /** * lpfc_sli4_async_mbox_unblock - Block posting SLI4 async mailbox command * @phba: Pointer to HBA context object. * * The function unblocks and resume posting of SLI4 asynchronous mailbox * commands from the driver internal pending mailbox queue. It makes sure * that there is no outstanding mailbox command before resuming posting * asynchronous mailbox commands. If, for any reason, there is outstanding * mailbox command, it will try to wait it out before resuming asynchronous * mailbox command posting. **/ static void lpfc_sli4_async_mbox_unblock(struct lpfc_hba *phba) { … } /** * lpfc_sli4_wait_bmbx_ready - Wait for bootstrap mailbox register ready * @phba: Pointer to HBA context object. * @mboxq: Pointer to mailbox object. * * The function waits for the bootstrap mailbox register ready bit from * port for twice the regular mailbox command timeout value. * * 0 - no timeout on waiting for bootstrap mailbox register ready. * MBXERR_ERROR - wait for bootstrap mailbox register timed out or port * is in an unrecoverable state. **/ static int lpfc_sli4_wait_bmbx_ready(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { … } /** * lpfc_sli4_post_sync_mbox - Post an SLI4 mailbox to the bootstrap mailbox * @phba: Pointer to HBA context object. * @mboxq: Pointer to mailbox object. * * The function posts a mailbox to the port. The mailbox is expected * to be comletely filled in and ready for the port to operate on it. * This routine executes a synchronous completion operation on the * mailbox by polling for its completion. * * The caller must not be holding any locks when calling this routine. * * Returns: * MBX_SUCCESS - mailbox posted successfully * Any of the MBX error values. **/ static int lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { … } /** * lpfc_sli_issue_mbox_s4 - Issue an SLI4 mailbox command to firmware * @phba: Pointer to HBA context object. * @mboxq: Pointer to mailbox object. * @flag: Flag indicating how the mailbox need to be processed. * * This function is called by discovery code and HBA management code to submit * a mailbox command to firmware with SLI-4 interface spec. * * Return codes the caller owns the mailbox command after the return of the * function. **/ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, uint32_t flag) { … } /** * lpfc_sli4_post_async_mbox - Post an SLI4 mailbox command to device * @phba: Pointer to HBA context object. * * This function is called by worker thread to send a mailbox command to * SLI4 HBA firmware. * **/ int lpfc_sli4_post_async_mbox(struct lpfc_hba *phba) { … } /** * lpfc_sli_issue_mbox - Wrapper func for issuing mailbox command * @phba: Pointer to HBA context object. * @pmbox: Pointer to mailbox object. * @flag: Flag indicating how the mailbox need to be processed. * * This routine wraps the actual SLI3 or SLI4 mailbox issuing routine from * the API jump table function pointer from the lpfc_hba struct. * * Return codes the caller owns the mailbox command after the return of the * function. **/ int lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) { … } /** * lpfc_mbox_api_table_setup - Set up mbox api function jump table * @phba: The hba struct for which this call is being executed. * @dev_grp: The HBA PCI-Device group number. * * This routine sets up the mbox interface API function jump table in @phba * struct. * Returns: 0 - success, -ENODEV - failure. **/ int lpfc_mbox_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) { … } /** * __lpfc_sli_ringtx_put - Add an iocb to the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to address of newly added command iocb. * * This function is called with hbalock held for SLI3 ports or * the ring lock held for SLI4 ports to add a command * iocb to the txq when SLI layer cannot submit the command iocb * to the ring. **/ void __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocb) { … } /** * lpfc_sli_next_iocb - Get the next iocb in the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to address of newly added command iocb. * * This function is called with hbalock held before a new * iocb is submitted to the firmware. This function checks * txq to flush the iocbs in txq to Firmware before * submitting new iocbs to the Firmware. * If there are iocbs in the txq which need to be submitted * to firmware, lpfc_sli_next_iocb returns the first element * of the txq after dequeuing it from txq. * If there is no iocb in the txq then the function will return * *piocb and *piocb is set to NULL. Caller needs to check * *piocb to find if there are more commands in the txq. **/ static struct lpfc_iocbq * lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq **piocb) { … } /** * __lpfc_sli_issue_iocb_s3 - SLI3 device lockless ver of lpfc_sli_issue_iocb * @phba: Pointer to HBA context object. * @ring_number: SLI ring number to issue iocb on. * @piocb: Pointer to command iocb. * @flag: Flag indicating if this command can be put into txq. * * __lpfc_sli_issue_iocb_s3 is used by other functions in the driver to issue * an iocb command to an HBA with SLI-3 interface spec. If the PCI slot is * recovering from error state, if HBA is resetting or if LPFC_STOP_IOCB_EVENT * flag is turned on, the function returns IOCB_ERROR. When the link is down, * this function allows only iocbs for posting buffers. This function finds * next available slot in the command ring and posts the command to the * available slot and writes the port attention register to request HBA start * processing new iocb. If there is no slot available in the ring and * flag & SLI_IOCB_RET_IOCB is set, the new iocb is added to the txq, otherwise * the function returns IOCB_BUSY. * * This function is called with hbalock held. The function will return success * after it successfully submit the iocb to firmware or after adding to the * txq. **/ static int __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { … } /** * __lpfc_sli_issue_fcp_io_s3 - SLI3 device for sending fcp io iocb * @phba: Pointer to HBA context object. * @ring_number: SLI ring number to issue wqe on. * @piocb: Pointer to command iocb. * @flag: Flag indicating if this command can be put into txq. * * __lpfc_sli_issue_fcp_io_s3 is wrapper function to invoke lockless func to * send an iocb command to an HBA with SLI-3 interface spec. * * This function takes the hbalock before invoking the lockless version. * The function will return success after it successfully submit the wqe to * firmware or after adding to the txq. **/ static int __lpfc_sli_issue_fcp_io_s3(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { … } /** * __lpfc_sli_issue_fcp_io_s4 - SLI4 device for sending fcp io wqe * @phba: Pointer to HBA context object. * @ring_number: SLI ring number to issue wqe on. * @piocb: Pointer to command iocb. * @flag: Flag indicating if this command can be put into txq. * * __lpfc_sli_issue_fcp_io_s4 is used by other functions in the driver to issue * an wqe command to an HBA with SLI-4 interface spec. * * This function is a lockless version. The function will return success * after it successfully submit the wqe to firmware or after adding to the * txq. **/ static int __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { … } void lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) { … } /** * __lpfc_sli_issue_iocb_s4 - SLI4 device lockless ver of lpfc_sli_issue_iocb * @phba: Pointer to HBA context object. * @ring_number: SLI ring number to issue iocb on. * @piocb: Pointer to command iocb. * @flag: Flag indicating if this command can be put into txq. * * __lpfc_sli_issue_iocb_s4 is used by other functions in the driver to issue * an iocb command to an HBA with SLI-4 interface spec. * * This function is called with ringlock held. The function will return success * after it successfully submit the iocb to firmware or after adding to the * txq. **/ static int __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { … } /* * lpfc_sli_issue_fcp_io - Wrapper func for issuing fcp i/o * * This routine wraps the actual fcp i/o function for issusing WQE for sli-4 * or IOCB for sli-3 function. * pointer from the lpfc_hba struct. * * Return codes: * IOCB_ERROR - Error * IOCB_SUCCESS - Success * IOCB_BUSY - Busy **/ int lpfc_sli_issue_fcp_io(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { … } /* * __lpfc_sli_issue_iocb - Wrapper func of lockless version for issuing iocb * * This routine wraps the actual lockless version for issusing IOCB function * pointer from the lpfc_hba struct. * * Return codes: * IOCB_ERROR - Error * IOCB_SUCCESS - Success * IOCB_BUSY - Busy **/ int __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { … } static void __lpfc_sli_prep_els_req_rsp_s3(struct lpfc_iocbq *cmdiocbq, struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did, u32 elscmd, u8 tmo, u8 expect_rsp) { … } static void __lpfc_sli_prep_els_req_rsp_s4(struct lpfc_iocbq *cmdiocbq, struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did, u32 elscmd, u8 tmo, u8 expect_rsp) { … } void lpfc_sli_prep_els_req_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, u16 cmd_size, u32 did, u32 elscmd, u8 tmo, u8 expect_rsp) { … } static void __lpfc_sli_prep_gen_req_s3(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry, u8 tmo) { … } static void __lpfc_sli_prep_gen_req_s4(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry, u8 tmo) { … } void lpfc_sli_prep_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, u16 rpi, u32 num_entry, u8 tmo) { … } static void __lpfc_sli_prep_xmit_seq64_s3(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id, u32 num_entry, u8 rctl, u8 last_seq, u8 cr_cx_cmd) { … } static void __lpfc_sli_prep_xmit_seq64_s4(struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id, u32 full_size, u8 rctl, u8 last_seq, u8 cr_cx_cmd) { … } void lpfc_sli_prep_xmit_seq64(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, struct lpfc_dmabuf *bmp, u16 rpi, u16 ox_id, u32 num_entry, u8 rctl, u8 last_seq, u8 cr_cx_cmd) { … } static void __lpfc_sli_prep_abort_xri_s3(struct lpfc_iocbq *cmdiocbq, u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid, bool ia, bool wqec) { … } static void __lpfc_sli_prep_abort_xri_s4(struct lpfc_iocbq *cmdiocbq, u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid, bool ia, bool wqec) { … } void lpfc_sli_prep_abort_xri(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, u16 ulp_context, u16 iotag, u8 ulp_class, u16 cqid, bool ia, bool wqec) { … } /** * lpfc_sli_api_table_setup - Set up sli api function jump table * @phba: The hba struct for which this call is being executed. * @dev_grp: The HBA PCI-Device group number. * * This routine sets up the SLI interface API function jump table in @phba * struct. * Returns: 0 - success, -ENODEV - failure. **/ int lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) { … } /** * lpfc_sli4_calc_ring - Calculates which ring to use * @phba: Pointer to HBA context object. * @piocb: Pointer to command iocb. * * For SLI4 only, FCP IO can deferred to one fo many WQs, based on * hba_wqidx, thus we need to calculate the corresponding ring. * Since ABORTS must go on the same WQ of the command they are * aborting, we use command's hba_wqidx. */ struct lpfc_sli_ring * lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) { … } inline void lpfc_sli4_poll_eq(struct lpfc_queue *eq) { … } /** * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb * @phba: Pointer to HBA context object. * @ring_number: Ring number * @piocb: Pointer to command iocb. * @flag: Flag indicating if this command can be put into txq. * * lpfc_sli_issue_iocb is a wrapper around __lpfc_sli_issue_iocb * function. This function gets the hbalock and calls * __lpfc_sli_issue_iocb function and will return the error returned * by __lpfc_sli_issue_iocb function. This wrapper is used by * functions which do not hold hbalock. **/ int lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { … } /** * lpfc_extra_ring_setup - Extra ring setup function * @phba: Pointer to HBA context object. * * This function is called while driver attaches with the * HBA to setup the extra ring. The extra ring is used * only when driver needs to support target mode functionality * or IP over FC functionalities. * * This function is called with no lock held. SLI3 only. **/ static int lpfc_extra_ring_setup( struct lpfc_hba *phba) { … } static void lpfc_sli_post_recovery_event(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { … } /* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port. * @phba: Pointer to HBA context object. * @iocbq: Pointer to iocb object. * * The async_event handler calls this routine when it receives * an ASYNC_STATUS_CN event from the port. The port generates * this event when an Abort Sequence request to an rport fails * twice in succession. The abort could be originated by the * driver or by the port. The ABTS could have been for an ELS * or FCP IO. The port only generates this event when an ABTS * fails to complete after one retry. */ static void lpfc_sli_abts_err_handler(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) { … } /* lpfc_sli4_abts_err_handler - handle a failed ABTS request from an SLI4 port. * @phba: pointer to HBA context object. * @ndlp: nodelist pointer for the impacted rport. * @axri: pointer to the wcqe containing the failed exchange. * * The driver calls this routine when it receives an ABORT_XRI_FCP CQE from the * port. The port generates this event when an abort exchange request to an * rport fails twice in succession with no reply. The abort could be originated * by the driver or by the port. The ABTS could have been for an ELS or FCP IO. */ void lpfc_sli4_abts_err_handler(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, struct sli4_wcqe_xri_aborted *axri) { … } /** * lpfc_sli_async_event_handler - ASYNC iocb handler function * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @iocbq: Pointer to iocb object. * * This function is called by the slow ring event handler * function when there is an ASYNC event iocb in the ring. * This function is called with no lock held. * Currently this function handles only temperature related * ASYNC events. The function decodes the temperature sensor * event message and posts events for the management applications. **/ static void lpfc_sli_async_event_handler(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, struct lpfc_iocbq * iocbq) { … } /** * lpfc_sli4_setup - SLI ring setup function * @phba: Pointer to HBA context object. * * lpfc_sli_setup sets up rings of the SLI interface with * number of iocbs per ring and iotags. This function is * called while driver attach to the HBA and before the * interrupts are enabled. So there is no need for locking. * * This function always returns 0. **/ int lpfc_sli4_setup(struct lpfc_hba *phba) { … } /** * lpfc_sli_setup - SLI ring setup function * @phba: Pointer to HBA context object. * * lpfc_sli_setup sets up rings of the SLI interface with * number of iocbs per ring and iotags. This function is * called while driver attach to the HBA and before the * interrupts are enabled. So there is no need for locking. * * This function always returns 0. SLI3 only. **/ int lpfc_sli_setup(struct lpfc_hba *phba) { … } /** * lpfc_sli4_queue_init - Queue initialization function * @phba: Pointer to HBA context object. * * lpfc_sli4_queue_init sets up mailbox queues and iocb queues for each * ring. This function also initializes ring indices of each ring. * This function is called during the initialization of the SLI * interface of an HBA. * This function is called with no lock held and always returns * 1. **/ void lpfc_sli4_queue_init(struct lpfc_hba *phba) { … } /** * lpfc_sli_queue_init - Queue initialization function * @phba: Pointer to HBA context object. * * lpfc_sli_queue_init sets up mailbox queues and iocb queues for each * ring. This function also initializes ring indices of each ring. * This function is called during the initialization of the SLI * interface of an HBA. * This function is called with no lock held and always returns * 1. **/ void lpfc_sli_queue_init(struct lpfc_hba *phba) { … } /** * lpfc_sli_mbox_sys_flush - Flush mailbox command sub-system * @phba: Pointer to HBA context object. * * This routine flushes the mailbox command subsystem. It will unconditionally * flush all the mailbox commands in the three possible stages in the mailbox * command sub-system: pending mailbox command queue; the outstanding mailbox * command; and completed mailbox command queue. It is caller's responsibility * to make sure that the driver is in the proper state to flush the mailbox * command sub-system. Namely, the posting of mailbox commands into the * pending mailbox command queue from the various clients must be stopped; * either the HBA is in a state that it will never works on the outstanding * mailbox command (such as in EEH or ERATT conditions) or the outstanding * mailbox command has been completed. **/ static void lpfc_sli_mbox_sys_flush(struct lpfc_hba *phba) { … } /** * lpfc_sli_host_down - Vport cleanup function * @vport: Pointer to virtual port object. * * lpfc_sli_host_down is called to clean up the resources * associated with a vport before destroying virtual * port data structures. * This function does following operations: * - Free discovery resources associated with this virtual * port. * - Free iocbs associated with this virtual port in * the txq. * - Send abort for all iocb commands associated with this * vport in txcmplq. * * This function is called with no lock held and always returns 1. **/ int lpfc_sli_host_down(struct lpfc_vport *vport) { … } /** * lpfc_sli_hba_down - Resource cleanup function for the HBA * @phba: Pointer to HBA context object. * * This function cleans up all iocb, buffers, mailbox commands * while shutting down the HBA. This function is called with no * lock held and always returns 1. * This function does the following to cleanup driver resources: * - Free discovery resources for each virtual port * - Cleanup any pending fabric iocbs * - Iterate through the iocb txq and free each entry * in the list. * - Free up any buffer posted to the HBA * - Free mailbox commands in the mailbox queue. **/ int lpfc_sli_hba_down(struct lpfc_hba *phba) { … } /** * lpfc_sli_pcimem_bcopy - SLI memory copy function * @srcp: Source memory pointer. * @destp: Destination memory pointer. * @cnt: Number of words required to be copied. * * This function is used for copying data between driver memory * and the SLI memory. This function also changes the endianness * of each word if native endianness is different from SLI * endianness. This function can be called with or without * lock. **/ void lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt) { … } /** * lpfc_sli_bemem_bcopy - SLI memory copy function * @srcp: Source memory pointer. * @destp: Destination memory pointer. * @cnt: Number of words required to be copied. * * This function is used for copying data between a data structure * with big endian representation to local endianness. * This function can be called with or without lock. **/ void lpfc_sli_bemem_bcopy(void *srcp, void *destp, uint32_t cnt) { … } /** * lpfc_sli_ringpostbuf_put - Function to add a buffer to postbufq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mp: Pointer to driver buffer object. * * This function is called with no lock held. * It always return zero after adding the buffer to the postbufq * buffer list. **/ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_dmabuf *mp) { … } /** * lpfc_sli_get_buffer_tag - allocates a tag for a CMD_QUE_XRI64_CX buffer * @phba: Pointer to HBA context object. * * When HBQ is enabled, buffers are searched based on tags. This function * allocates a tag for buffer posted using CMD_QUE_XRI64_CX iocb. The * tag is bit wise or-ed with QUE_BUFTAG_BIT to make sure that the tag * does not conflict with tags of buffer posted for unsolicited events. * The function returns the allocated tag. The function is called with * no locks held. **/ uint32_t lpfc_sli_get_buffer_tag(struct lpfc_hba *phba) { … } /** * lpfc_sli_ring_taggedbuf_get - find HBQ buffer associated with given tag * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @tag: Buffer tag. * * Buffers posted using CMD_QUE_XRI64_CX iocb are in pring->postbufq * list. After HBA DMA data to these buffers, CMD_IOCB_RET_XRI64_CX * iocb is posted to the response ring with the tag of the buffer. * This function searches the pring->postbufq list using the tag * to find buffer associated with CMD_IOCB_RET_XRI64_CX * iocb. If the buffer is found then lpfc_dmabuf object of the * buffer is returned to the caller else NULL is returned. * This function is called with no lock held. **/ struct lpfc_dmabuf * lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, uint32_t tag) { … } /** * lpfc_sli_ringpostbuf_get - search buffers for unsolicited CT and ELS events * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @phys: DMA address of the buffer. * * This function searches the buffer list using the dma_address * of unsolicited event to find the driver's lpfc_dmabuf object * corresponding to the dma_address. The function returns the * lpfc_dmabuf object if a buffer is found else it returns NULL. * This function is called by the ct and els unsolicited event * handlers to get the buffer associated with the unsolicited * event. * * This function is called with no lock held. **/ struct lpfc_dmabuf * lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, dma_addr_t phys) { … } /** * lpfc_sli_abort_els_cmpl - Completion handler for the els abort iocbs * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. * @rspiocb: Pointer to driver response iocb object. * * This function is the completion handler for the abort iocbs for * ELS commands. This function is called from the ELS ring event * handler with no lock held. This function frees memory resources * associated with the abort iocb. **/ static void lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { … } /** * lpfc_ignore_els_cmpl - Completion handler for aborted ELS command * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. * @rspiocb: Pointer to driver response iocb object. * * The function is called from SLI ring event handler with no * lock held. This function is the completion handler for ELS commands * which are aborted. The function frees memory resources used for * the aborted ELS commands. **/ void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { … } /** * lpfc_sli_issue_abort_iotag - Abort function for a command iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @cmdiocb: Pointer to driver command iocb object. * @cmpl: completion function. * * This function issues an abort iocb for the provided command iocb. In case * of unloading, the abort iocb will not be issued to commands on the ELS * ring. Instead, the callback function shall be changed to those commands * so that nothing happens when them finishes. This function is called with * hbalock held andno ring_lock held (SLI4). The function returns IOCB_SUCCESS * when the command iocb is an abort request. * **/ int lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *cmdiocb, void *cmpl) { … } /** * lpfc_sli_hba_iocb_abort - Abort all iocbs to an hba. * @phba: pointer to lpfc HBA data structure. * * This routine will abort all pending and outstanding iocbs to an HBA. **/ void lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba) { … } /** * lpfc_sli_validate_fcp_iocb_for_abort - filter iocbs appropriate for FCP aborts * @iocbq: Pointer to iocb object. * @vport: Pointer to driver virtual port object. * * This function acts as an iocb filter for functions which abort FCP iocbs. * * Return values * -ENODEV, if a null iocb or vport ptr is encountered * -EINVAL, if the iocb is not an FCP I/O, not on the TX cmpl queue, premarked as * driver already started the abort process, or is an abort iocb itself * 0, passes criteria for aborting the FCP I/O iocb **/ static int lpfc_sli_validate_fcp_iocb_for_abort(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport) { … } /** * lpfc_sli_validate_fcp_iocb - validate commands associated with a SCSI target * @iocbq: Pointer to driver iocb object. * @vport: Pointer to driver virtual port object. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST * * This function acts as an iocb filter for validating a lun/SCSI target/SCSI * host. * * It will return * 0 if the filtering criteria is met for the given iocb and will return * 1 if the filtering criteria is not met. * If ctx_cmd == LPFC_CTX_LUN, the function returns 0 only if the * given iocb is for the SCSI device specified by vport, tgt_id and * lun_id parameter. * If ctx_cmd == LPFC_CTX_TGT, the function returns 0 only if the * given iocb is for the SCSI target specified by vport and tgt_id * parameters. * If ctx_cmd == LPFC_CTX_HOST, the function returns 0 only if the * given iocb is for the SCSI host associated with the given vport. * This function is called with no locks held. **/ static int lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) { … } /** * lpfc_sli_sum_iocb - Function to count the number of FCP iocbs pending * @vport: Pointer to virtual port. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST. * * This function returns number of FCP commands pending for the vport. * When ctx_cmd == LPFC_CTX_LUN, the function returns number of FCP * commands pending on the vport associated with SCSI device specified * by tgt_id and lun_id parameters. * When ctx_cmd == LPFC_CTX_TGT, the function returns number of FCP * commands pending on the vport associated with SCSI target specified * by tgt_id parameter. * When ctx_cmd == LPFC_CTX_HOST, the function returns number of FCP * commands pending on the vport. * This function returns the number of iocbs which satisfy the filter. * This function is called without any lock held. **/ int lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) { … } /** * lpfc_sli_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs * @phba: Pointer to HBA context object * @cmdiocb: Pointer to command iocb object. * @rspiocb: Pointer to response iocb object. * * This function is called when an aborted FCP iocb completes. This * function is called by the ring event handler with no lock held. * This function frees the iocb. **/ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { … } /** * lpfc_sli_abort_iocb - issue abort for all commands on a host/target/LUN * @vport: Pointer to virtual port. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. * @abort_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST. * * This function sends an abort command for every SCSI command * associated with the given virtual port pending on the ring * filtered by lpfc_sli_validate_fcp_iocb_for_abort and then * lpfc_sli_validate_fcp_iocb function. The ordering for validation before * submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort * followed by lpfc_sli_validate_fcp_iocb. * * When abort_cmd == LPFC_CTX_LUN, the function sends abort only to the * FCP iocbs associated with lun specified by tgt_id and lun_id * parameters * When abort_cmd == LPFC_CTX_TGT, the function sends abort only to the * FCP iocbs associated with SCSI target specified by tgt_id parameter. * When abort_cmd == LPFC_CTX_HOST, the function sends abort to all * FCP iocbs associated with virtual port. * The pring used for SLI3 is sli3_ring[LPFC_FCP_RING], for SLI4 * lpfc_sli4_calc_ring is used. * This function returns number of iocbs it failed to abort. * This function is called with no locks held. **/ int lpfc_sli_abort_iocb(struct lpfc_vport *vport, u16 tgt_id, u64 lun_id, lpfc_ctx_cmd abort_cmd) { … } /** * lpfc_sli_abort_taskmgmt - issue abort for all commands on a host/target/LUN * @vport: Pointer to virtual port. * @pring: Pointer to driver SLI ring object. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. * @cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST. * * This function sends an abort command for every SCSI command * associated with the given virtual port pending on the ring * filtered by lpfc_sli_validate_fcp_iocb_for_abort and then * lpfc_sli_validate_fcp_iocb function. The ordering for validation before * submitting abort iocbs must be lpfc_sli_validate_fcp_iocb_for_abort * followed by lpfc_sli_validate_fcp_iocb. * * When taskmgmt_cmd == LPFC_CTX_LUN, the function sends abort only to the * FCP iocbs associated with lun specified by tgt_id and lun_id * parameters * When taskmgmt_cmd == LPFC_CTX_TGT, the function sends abort only to the * FCP iocbs associated with SCSI target specified by tgt_id parameter. * When taskmgmt_cmd == LPFC_CTX_HOST, the function sends abort to all * FCP iocbs associated with virtual port. * This function returns number of iocbs it aborted . * This function is called with no locks held right after a taskmgmt * command is sent. **/ int lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd cmd) { … } /** * lpfc_sli_wake_iocb_wait - lpfc_sli_issue_iocb_wait's completion handler * @phba: Pointer to HBA context object. * @cmdiocbq: Pointer to command iocb. * @rspiocbq: Pointer to response iocb. * * This function is the completion handler for iocbs issued using * lpfc_sli_issue_iocb_wait function. This function is called by the * ring event handler function without any lock held. This function * can be called from both worker thread context and interrupt * context. This function also can be called from other thread which * cleans up the SLI layer objects. * This function copy the contents of the response iocb to the * response iocb memory object provided by the caller of * lpfc_sli_issue_iocb_wait and then wakes up the thread which * sleeps for the iocb completion. **/ static void lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocbq, struct lpfc_iocbq *rspiocbq) { … } /** * lpfc_chk_iocb_flg - Test IOCB flag with lock held. * @phba: Pointer to HBA context object.. * @piocbq: Pointer to command iocb. * @flag: Flag to test. * * This routine grabs the hbalock and then test the cmd_flag to * see if the passed in flag is set. * Returns: * 1 if flag is set. * 0 if flag is not set. **/ static int lpfc_chk_iocb_flg(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, uint32_t flag) { … } /** * lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands * @phba: Pointer to HBA context object.. * @ring_number: Ring number * @piocb: Pointer to command iocb. * @prspiocbq: Pointer to response iocb. * @timeout: Timeout in number of seconds. * * This function issues the iocb to firmware and waits for the * iocb to complete. The cmd_cmpl field of the shall be used * to handle iocbs which time out. If the field is NULL, the * function shall free the iocbq structure. If more clean up is * needed, the caller is expected to provide a completion function * that will provide the needed clean up. If the iocb command is * not completed within timeout seconds, the function will either * free the iocbq structure (if cmd_cmpl == NULL) or execute the * completion function set in the cmd_cmpl field and then return * a status of IOCB_TIMEDOUT. The caller should not free the iocb * resources if this function returns IOCB_TIMEDOUT. * The function waits for the iocb completion using an * non-interruptible wait. * This function will sleep while waiting for iocb completion. * So, this function should not be called from any context which * does not allow sleeping. Due to the same reason, this function * cannot be called with interrupt disabled. * This function assumes that the iocb completions occur while * this function sleep. So, this function cannot be called from * the thread which process iocb completion for this ring. * This function clears the cmd_flag of the iocb object before * issuing the iocb and the iocb completion handler sets this * flag and wakes this thread when the iocb completes. * The contents of the response iocb will be copied to prspiocbq * by the completion handler when the command completes. * This function returns IOCB_SUCCESS when success. * This function is called with no lock held. **/ int lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, struct lpfc_iocbq *prspiocbq, uint32_t timeout) { … } /** * lpfc_sli_issue_mbox_wait - Synchronous function to issue mailbox * @phba: Pointer to HBA context object. * @pmboxq: Pointer to driver mailbox object. * @timeout: Timeout in number of seconds. * * This function issues the mailbox to firmware and waits for the * mailbox command to complete. If the mailbox command is not * completed within timeout seconds, it returns MBX_TIMEOUT. * The function waits for the mailbox completion using an * interruptible wait. If the thread is woken up due to a * signal, MBX_TIMEOUT error is returned to the caller. Caller * should not free the mailbox resources, if this function returns * MBX_TIMEOUT. * This function will sleep while waiting for mailbox completion. * So, this function should not be called from any context which * does not allow sleeping. Due to the same reason, this function * cannot be called with interrupt disabled. * This function assumes that the mailbox completion occurs while * this function sleep. So, this function cannot be called from * the worker thread which processes mailbox completion. * This function is called in the context of HBA management * applications. * This function returns MBX_SUCCESS when successful. * This function is called with no lock held. **/ int lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, uint32_t timeout) { … } /** * lpfc_sli_mbox_sys_shutdown - shutdown mailbox command sub-system * @phba: Pointer to HBA context. * @mbx_action: Mailbox shutdown options. * * This function is called to shutdown the driver's mailbox sub-system. * It first marks the mailbox sub-system is in a block state to prevent * the asynchronous mailbox command from issued off the pending mailbox * command queue. If the mailbox command sub-system shutdown is due to * HBA error conditions such as EEH or ERATT, this routine shall invoke * the mailbox sub-system flush routine to forcefully bring down the * mailbox sub-system. Otherwise, if it is due to normal condition (such * as with offline or HBA function reset), this routine will wait for the * outstanding mailbox command to complete before invoking the mailbox * sub-system flush routine to gracefully bring down mailbox sub-system. **/ void lpfc_sli_mbox_sys_shutdown(struct lpfc_hba *phba, int mbx_action) { … } /** * lpfc_sli_eratt_read - read sli-3 error attention events * @phba: Pointer to HBA context. * * This function is called to read the SLI3 device error attention registers * for possible error attention events. The caller must hold the hostlock * with spin_lock_irq(). * * This function returns 1 when there is Error Attention in the Host Attention * Register and returns 0 otherwise. **/ static int lpfc_sli_eratt_read(struct lpfc_hba *phba) { … } /** * lpfc_sli4_eratt_read - read sli-4 error attention events * @phba: Pointer to HBA context. * * This function is called to read the SLI4 device error attention registers * for possible error attention events. The caller must hold the hostlock * with spin_lock_irq(). * * This function returns 1 when there is Error Attention in the Host Attention * Register and returns 0 otherwise. **/ static int lpfc_sli4_eratt_read(struct lpfc_hba *phba) { … } /** * lpfc_sli_check_eratt - check error attention events * @phba: Pointer to HBA context. * * This function is called from timer soft interrupt context to check HBA's * error attention register bit for error attention events. * * This function returns 1 when there is Error Attention in the Host Attention * Register and returns 0 otherwise. **/ int lpfc_sli_check_eratt(struct lpfc_hba *phba) { … } /** * lpfc_intr_state_check - Check device state for interrupt handling * @phba: Pointer to HBA context. * * This inline routine checks whether a device or its PCI slot is in a state * that the interrupt should be handled. * * This function returns 0 if the device or the PCI slot is in a state that * interrupt should be handled, otherwise -EIO. */ static inline int lpfc_intr_state_check(struct lpfc_hba *phba) { … } /** * lpfc_sli_sp_intr_handler - Slow-path interrupt handler to SLI-3 device * @irq: Interrupt number. * @dev_id: The device context pointer. * * This function is directly called from the PCI layer as an interrupt * service routine when device with SLI-3 interface spec is enabled with * MSI-X multi-message interrupt mode and there are slow-path events in * the HBA. However, when the device is enabled with either MSI or Pin-IRQ * interrupt mode, this function is called as part of the device-level * interrupt handler. When the PCI slot is in error recovery or the HBA * is undergoing initialization, the interrupt handler will not process * the interrupt. The link attention and ELS ring attention events are * handled by the worker thread. The interrupt handler signals the worker * thread and returns for these events. This function is called without * any lock held. It gets the hbalock to access and update SLI data * structures. * * This function returns IRQ_HANDLED when interrupt is handled else it * returns IRQ_NONE. **/ irqreturn_t lpfc_sli_sp_intr_handler(int irq, void *dev_id) { … } /* lpfc_sli_sp_intr_handler */ /** * lpfc_sli_fp_intr_handler - Fast-path interrupt handler to SLI-3 device. * @irq: Interrupt number. * @dev_id: The device context pointer. * * This function is directly called from the PCI layer as an interrupt * service routine when device with SLI-3 interface spec is enabled with * MSI-X multi-message interrupt mode and there is a fast-path FCP IOCB * ring event in the HBA. However, when the device is enabled with either * MSI or Pin-IRQ interrupt mode, this function is called as part of the * device-level interrupt handler. When the PCI slot is in error recovery * or the HBA is undergoing initialization, the interrupt handler will not * process the interrupt. The SCSI FCP fast-path ring event are handled in * the intrrupt context. This function is called without any lock held. * It gets the hbalock to access and update SLI data structures. * * This function returns IRQ_HANDLED when interrupt is handled else it * returns IRQ_NONE. **/ irqreturn_t lpfc_sli_fp_intr_handler(int irq, void *dev_id) { … } /* lpfc_sli_fp_intr_handler */ /** * lpfc_sli_intr_handler - Device-level interrupt handler to SLI-3 device * @irq: Interrupt number. * @dev_id: The device context pointer. * * This function is the HBA device-level interrupt handler to device with * SLI-3 interface spec, called from the PCI layer when either MSI or * Pin-IRQ interrupt mode is enabled and there is an event in the HBA which * requires driver attention. This function invokes the slow-path interrupt * attention handling function and fast-path interrupt attention handling * function in turn to process the relevant HBA attention events. This * function is called without any lock held. It gets the hbalock to access * and update SLI data structures. * * This function returns IRQ_HANDLED when interrupt is handled, else it * returns IRQ_NONE. **/ irqreturn_t lpfc_sli_intr_handler(int irq, void *dev_id) { … } /* lpfc_sli_intr_handler */ /** * lpfc_sli4_els_xri_abort_event_proc - Process els xri abort event * @phba: pointer to lpfc hba data structure. * * This routine is invoked by the worker thread to process all the pending * SLI4 els abort xri events. **/ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba) { … } /** * lpfc_sli4_els_preprocess_rspiocbq - Get response iocbq from els wcqe * @phba: Pointer to HBA context object. * @irspiocbq: Pointer to work-queue completion queue entry. * * This routine handles an ELS work-queue completion event and construct * a pseudo response ELS IOCBQ from the SLI4 ELS WCQE for the common * discovery engine to handle. * * Return: Pointer to the receive IOCBQ, NULL otherwise. **/ static struct lpfc_iocbq * lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, struct lpfc_iocbq *irspiocbq) { … } inline struct lpfc_cq_event * lpfc_cq_event_setup(struct lpfc_hba *phba, void *entry, int size) { … } /** * lpfc_sli4_sp_handle_async_event - Handle an asynchronous event * @phba: Pointer to HBA context object. * @mcqe: Pointer to mailbox completion queue entry. * * This routine process a mailbox completion queue entry with asynchronous * event. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_sp_handle_async_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) { … } /** * lpfc_sli4_sp_handle_mbox_event - Handle a mailbox completion event * @phba: Pointer to HBA context object. * @mcqe: Pointer to mailbox completion queue entry. * * This routine process a mailbox completion queue entry with mailbox * completion event. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) { … } /** * lpfc_sli4_sp_handle_mcqe - Process a mailbox completion queue entry * @phba: Pointer to HBA context object. * @cq: Pointer to associated CQ * @cqe: Pointer to mailbox completion queue entry. * * This routine process a mailbox completion queue entry, it invokes the * proper mailbox complete handling or asynchronous event handling routine * according to the MCQE's async bit. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_sp_handle_mcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe) { … } /** * lpfc_sli4_sp_handle_els_wcqe - Handle els work-queue completion event * @phba: Pointer to HBA context object. * @cq: Pointer to associated CQ * @wcqe: Pointer to work-queue completion queue entry. * * This routine handles an ELS work-queue completion event. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_wcqe_complete *wcqe) { … } /** * lpfc_sli4_sp_handle_rel_wcqe - Handle slow-path WQ entry consumed event * @phba: Pointer to HBA context object. * @wcqe: Pointer to work-queue completion queue entry. * * This routine handles slow-path WQ entry consumed event by invoking the * proper WQ release routine to the slow-path WQ. **/ static void lpfc_sli4_sp_handle_rel_wcqe(struct lpfc_hba *phba, struct lpfc_wcqe_release *wcqe) { … } /** * lpfc_sli4_sp_handle_abort_xri_wcqe - Handle a xri abort event * @phba: Pointer to HBA context object. * @cq: Pointer to a WQ completion queue. * @wcqe: Pointer to work-queue completion queue entry. * * This routine handles an XRI abort event. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_sp_handle_abort_xri_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct sli4_wcqe_xri_aborted *wcqe) { … } #define FC_RCTL_MDS_DIAGS … /** * lpfc_sli4_sp_handle_rcqe - Process a receive-queue completion queue entry * @phba: Pointer to HBA context object. * @rcqe: Pointer to receive-queue completion queue entry. * * This routine process a receive-queue completion queue entry. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) { … } /** * lpfc_sli4_sp_handle_cqe - Process a slow path completion queue entry * @phba: Pointer to HBA context object. * @cq: Pointer to the completion queue. * @cqe: Pointer to a completion queue entry. * * This routine process a slow-path work-queue or receive queue completion queue * entry. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe) { … } /** * lpfc_sli4_sp_handle_eqe - Process a slow-path event queue entry * @phba: Pointer to HBA context object. * @eqe: Pointer to fast-path event queue entry. * @speq: Pointer to slow-path event queue. * * This routine process a event queue entry from the slow-path event queue. * It will check the MajorCode and MinorCode to determine this is for a * completion event on a completion queue, if not, an error shall be logged * and just return. Otherwise, it will get to the corresponding completion * queue and process all the entries on that completion queue, rearm the * completion queue, and then return. * **/ static void lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe, struct lpfc_queue *speq) { … } /** * __lpfc_sli4_process_cq - Process elements of a CQ * @phba: Pointer to HBA context object. * @cq: Pointer to CQ to be processed * @handler: Routine to process each cqe * @delay: Pointer to usdelay to set in case of rescheduling of the handler * * This routine processes completion queue entries in a CQ. While a valid * queue element is found, the handler is called. During processing checks * are made for periodic doorbell writes to let the hardware know of * element consumption. * * If the max limit on cqes to process is hit, or there are no more valid * entries, the loop stops. If we processed a sufficient number of elements, * meaning there is sufficient load, rather than rearming and generating * another interrupt, a cq rescheduling delay will be set. A delay of 0 * indicates no rescheduling. * * Returns True if work scheduled, False otherwise. **/ static bool __lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq, bool (*handler)(struct lpfc_hba *, struct lpfc_queue *, struct lpfc_cqe *), unsigned long *delay) { … } /** * __lpfc_sli4_sp_process_cq - Process a slow-path event queue entry * @cq: pointer to CQ to process * * This routine calls the cq processing routine with a handler specific * to the type of queue bound to it. * * The CQ routine returns two values: the first is the calling status, * which indicates whether work was queued to the background discovery * thread. If true, the routine should wakeup the discovery thread; * the second is the delay parameter. If non-zero, rather than rearming * the CQ and yet another interrupt, the CQ handler should be queued so * that it is processed in a subsequent polling action. The value of * the delay indicates when to reschedule it. **/ static void __lpfc_sli4_sp_process_cq(struct lpfc_queue *cq) { … } /** * lpfc_sli4_sp_process_cq - slow-path work handler when started by * interrupt * @work: pointer to work element * * translates from the work handler and calls the slow-path handler. **/ static void lpfc_sli4_sp_process_cq(struct work_struct *work) { … } /** * lpfc_sli4_dly_sp_process_cq - slow-path work handler when started by timer * @work: pointer to work element * * translates from the work handler and calls the slow-path handler. **/ static void lpfc_sli4_dly_sp_process_cq(struct work_struct *work) { … } /** * lpfc_sli4_fp_handle_fcp_wcqe - Process fast-path work queue completion entry * @phba: Pointer to HBA context object. * @cq: Pointer to associated CQ * @wcqe: Pointer to work-queue completion queue entry. * * This routine process a fast-path work queue completion entry from fast-path * event queue for FCP command response completion. **/ static void lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_wcqe_complete *wcqe) { … } /** * lpfc_sli4_fp_handle_rel_wcqe - Handle fast-path WQ entry consumed event * @phba: Pointer to HBA context object. * @cq: Pointer to completion queue. * @wcqe: Pointer to work-queue completion queue entry. * * This routine handles an fast-path WQ entry consumed event by invoking the * proper WQ release routine to the slow-path WQ. **/ static void lpfc_sli4_fp_handle_rel_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_wcqe_release *wcqe) { … } /** * lpfc_sli4_nvmet_handle_rcqe - Process a receive-queue completion queue entry * @phba: Pointer to HBA context object. * @cq: Pointer to completion queue. * @rcqe: Pointer to receive-queue completion queue entry. * * This routine process a receive-queue completion queue entry. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_rcqe *rcqe) { … } /** * lpfc_sli4_fp_handle_cqe - Process fast-path work queue completion entry * @phba: adapter with cq * @cq: Pointer to the completion queue. * @cqe: Pointer to fast-path completion queue entry. * * This routine process a fast-path work queue completion entry from fast-path * event queue for FCP command response completion. * * Return: true if work posted to worker thread, otherwise false. **/ static bool lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe) { … } /** * __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry * @cq: Pointer to CQ to be processed * * This routine calls the cq processing routine with the handler for * fast path CQEs. * * The CQ routine returns two values: the first is the calling status, * which indicates whether work was queued to the background discovery * thread. If true, the routine should wakeup the discovery thread; * the second is the delay parameter. If non-zero, rather than rearming * the CQ and yet another interrupt, the CQ handler should be queued so * that it is processed in a subsequent polling action. The value of * the delay indicates when to reschedule it. **/ static void __lpfc_sli4_hba_process_cq(struct lpfc_queue *cq) { … } /** * lpfc_sli4_hba_process_cq - fast-path work handler when started by * interrupt * @work: pointer to work element * * translates from the work handler and calls the fast-path handler. **/ static void lpfc_sli4_hba_process_cq(struct work_struct *work) { … } /** * lpfc_sli4_hba_handle_eqe - Process a fast-path event queue entry * @phba: Pointer to HBA context object. * @eq: Pointer to the queue structure. * @eqe: Pointer to fast-path event queue entry. * @poll_mode: poll_mode to execute processing the cq. * * This routine process a event queue entry from the fast-path event queue. * It will check the MajorCode and MinorCode to determine this is for a * completion event on a completion queue, if not, an error shall be logged * and just return. Otherwise, it will get to the corresponding completion * queue and process all the entries on the completion queue, rearm the * completion queue, and then return. **/ static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *phba, struct lpfc_queue *eq, struct lpfc_eqe *eqe, enum lpfc_poll_mode poll_mode) { … } /** * lpfc_sli4_dly_hba_process_cq - fast-path work handler when started by timer * @work: pointer to work element * * translates from the work handler and calls the fast-path handler. **/ static void lpfc_sli4_dly_hba_process_cq(struct work_struct *work) { … } /** * lpfc_sli4_hba_intr_handler - HBA interrupt handler to SLI-4 device * @irq: Interrupt number. * @dev_id: The device context pointer. * * This function is directly called from the PCI layer as an interrupt * service routine when device with SLI-4 interface spec is enabled with * MSI-X multi-message interrupt mode and there is a fast-path FCP IOCB * ring event in the HBA. However, when the device is enabled with either * MSI or Pin-IRQ interrupt mode, this function is called as part of the * device-level interrupt handler. When the PCI slot is in error recovery * or the HBA is undergoing initialization, the interrupt handler will not * process the interrupt. The SCSI FCP fast-path ring event are handled in * the intrrupt context. This function is called without any lock held. * It gets the hbalock to access and update SLI data structures. Note that, * the FCP EQ to FCP CQ are one-to-one map such that the FCP EQ index is * equal to that of FCP CQ index. * * The link attention and ELS ring attention events are handled * by the worker thread. The interrupt handler signals the worker thread * and returns for these events. This function is called without any lock * held. It gets the hbalock to access and update SLI data structures. * * This function returns IRQ_HANDLED when interrupt is handled, IRQ_WAKE_THREAD * when interrupt is scheduled to be handled from a threaded irq context, or * else returns IRQ_NONE. **/ irqreturn_t lpfc_sli4_hba_intr_handler(int irq, void *dev_id) { … } /* lpfc_sli4_hba_intr_handler */ /** * lpfc_sli4_intr_handler - Device-level interrupt handler for SLI-4 device * @irq: Interrupt number. * @dev_id: The device context pointer. * * This function is the device-level interrupt handler to device with SLI-4 * interface spec, called from the PCI layer when either MSI or Pin-IRQ * interrupt mode is enabled and there is an event in the HBA which requires * driver attention. This function invokes the slow-path interrupt attention * handling function and fast-path interrupt attention handling function in * turn to process the relevant HBA attention events. This function is called * without any lock held. It gets the hbalock to access and update SLI data * structures. * * This function returns IRQ_HANDLED when interrupt is handled, else it * returns IRQ_NONE. **/ irqreturn_t lpfc_sli4_intr_handler(int irq, void *dev_id) { … } /* lpfc_sli4_intr_handler */ void lpfc_sli4_poll_hbtimer(struct timer_list *t) { … } static inline void lpfc_sli4_add_to_poll_list(struct lpfc_queue *eq) { … } static inline void lpfc_sli4_remove_from_poll_list(struct lpfc_queue *eq) { … } void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba) { … } static inline void __lpfc_sli4_switch_eqmode(struct lpfc_queue *eq, uint8_t mode) { … } void lpfc_sli4_start_polling(struct lpfc_queue *eq) { … } void lpfc_sli4_stop_polling(struct lpfc_queue *eq) { … } /** * lpfc_sli4_queue_free - free a queue structure and associated memory * @queue: The queue structure to free. * * This function frees a queue structure and the DMAable memory used for * the host resident queue. This function must be called after destroying the * queue on the HBA. **/ void lpfc_sli4_queue_free(struct lpfc_queue *queue) { … } /** * lpfc_sli4_queue_alloc - Allocate and initialize a queue structure * @phba: The HBA that this queue is being created on. * @page_size: The size of a queue page * @entry_size: The size of each queue entry for this queue. * @entry_count: The number of entries that this queue will handle. * @cpu: The cpu that will primarily utilize this queue. * * This function allocates a queue structure and the DMAable memory used for * the host resident queue. This function must be called before creating the * queue on the HBA. **/ struct lpfc_queue * lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size, uint32_t entry_size, uint32_t entry_count, int cpu) { … } /** * lpfc_dual_chute_pci_bar_map - Map pci base address register to host memory * @phba: HBA structure that indicates port to create a queue on. * @pci_barset: PCI BAR set flag. * * This function shall perform iomap of the specified PCI BAR address to host * memory address if not already done so and return it. The returned host * memory address can be NULL. */ static void __iomem * lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset) { … } /** * lpfc_modify_hba_eq_delay - Modify Delay Multiplier on EQs * @phba: HBA structure that EQs are on. * @startq: The starting EQ index to modify * @numq: The number of EQs (consecutive indexes) to modify * @usdelay: amount of delay * * This function revises the EQ delay on 1 or more EQs. The EQ delay * is set either by writing to a register (if supported by the SLI Port) * or by mailbox command. The mailbox command allows several EQs to be * updated at once. * * The @phba struct is used to send a mailbox command to HBA. The @startq * is used to get the starting EQ index to change. The @numq value is * used to specify how many consecutive EQ indexes, starting at EQ index, * are to be changed. This function is asynchronous and will wait for any * mailbox commands to finish before returning. * * On success this function will return a zero. If unable to allocate * enough memory this function will return -ENOMEM. If a mailbox command * fails this function will return -ENXIO. Note: on ENXIO, some EQs may * have had their delay multipler changed. **/ void lpfc_modify_hba_eq_delay(struct lpfc_hba *phba, uint32_t startq, uint32_t numq, uint32_t usdelay) { … } /** * lpfc_eq_create - Create an Event Queue on the HBA * @phba: HBA structure that indicates port to create a queue on. * @eq: The queue structure to use to create the event queue. * @imax: The maximum interrupt per second limit. * * This function creates an event queue, as detailed in @eq, on a port, * described by @phba by sending an EQ_CREATE mailbox command to the HBA. * * The @phba struct is used to send mailbox command to HBA. The @eq struct * is used to get the entry count and entry size that are necessary to * determine the number of pages to allocate and use for this queue. This * function will send the EQ_CREATE mailbox command to the HBA to setup the * event queue. This function is asynchronous and will wait for the mailbox * command to finish before continuing. * * On success this function will return a zero. If unable to allocate enough * memory this function will return -ENOMEM. If the queue create mailbox command * fails this function will return -ENXIO. **/ int lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) { … } /** * lpfc_sli4_hba_intr_handler_th - SLI4 HBA threaded interrupt handler * @irq: Interrupt number. * @dev_id: The device context pointer. * * This routine is a mirror of lpfc_sli4_hba_intr_handler, but executed within * threaded irq context. * * Returns * IRQ_HANDLED - interrupt is handled * IRQ_NONE - otherwise **/ irqreturn_t lpfc_sli4_hba_intr_handler_th(int irq, void *dev_id) { … } /** * lpfc_cq_create - Create a Completion Queue on the HBA * @phba: HBA structure that indicates port to create a queue on. * @cq: The queue structure to use to create the completion queue. * @eq: The event queue to bind this completion queue to. * @type: Type of queue (EQ, GCQ, MCQ, WCQ, etc). * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc). * * This function creates a completion queue, as detailed in @wq, on a port, * described by @phba by sending a CQ_CREATE mailbox command to the HBA. * * The @phba struct is used to send mailbox command to HBA. The @cq struct * is used to get the entry count and entry size that are necessary to * determine the number of pages to allocate and use for this queue. The @eq * is used to indicate which event queue to bind this completion queue to. This * function will send the CQ_CREATE mailbox command to the HBA to setup the * completion queue. This function is asynchronous and will wait for the mailbox * command to finish before continuing. * * On success this function will return a zero. If unable to allocate enough * memory this function will return -ENOMEM. If the queue create mailbox command * fails this function will return -ENXIO. **/ int lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_queue *eq, uint32_t type, uint32_t subtype) { … } /** * lpfc_cq_create_set - Create a set of Completion Queues on the HBA for MRQ * @phba: HBA structure that indicates port to create a queue on. * @cqp: The queue structure array to use to create the completion queues. * @hdwq: The hardware queue array with the EQ to bind completion queues to. * @type: Type of queue (EQ, GCQ, MCQ, WCQ, etc). * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc). * * This function creates a set of completion queue, s to support MRQ * as detailed in @cqp, on a port, * described by @phba by sending a CREATE_CQ_SET mailbox command to the HBA. * * The @phba struct is used to send mailbox command to HBA. The @cq struct * is used to get the entry count and entry size that are necessary to * determine the number of pages to allocate and use for this queue. The @eq * is used to indicate which event queue to bind this completion queue to. This * function will send the CREATE_CQ_SET mailbox command to the HBA to setup the * completion queue. This function is asynchronous and will wait for the mailbox * command to finish before continuing. * * On success this function will return a zero. If unable to allocate enough * memory this function will return -ENOMEM. If the queue create mailbox command * fails this function will return -ENXIO. **/ int lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, struct lpfc_sli4_hdw_queue *hdwq, uint32_t type, uint32_t subtype) { … } /** * lpfc_mq_create_fb_init - Send MCC_CREATE without async events registration * @phba: HBA structure that indicates port to create a queue on. * @mq: The queue structure to use to create the mailbox queue. * @mbox: An allocated pointer to type LPFC_MBOXQ_t * @cq: The completion queue to associate with this cq. * * This function provides failback (fb) functionality when the * mq_create_ext fails on older FW generations. It's purpose is identical * to mq_create_ext otherwise. * * This routine cannot fail as all attributes were previously accessed and * initialized in mq_create_ext. **/ static void lpfc_mq_create_fb_init(struct lpfc_hba *phba, struct lpfc_queue *mq, LPFC_MBOXQ_t *mbox, struct lpfc_queue *cq) { … } /** * lpfc_mq_create - Create a mailbox Queue on the HBA * @phba: HBA structure that indicates port to create a queue on. * @mq: The queue structure to use to create the mailbox queue. * @cq: The completion queue to associate with this cq. * @subtype: The queue's subtype. * * This function creates a mailbox queue, as detailed in @mq, on a port, * described by @phba by sending a MQ_CREATE mailbox command to the HBA. * * The @phba struct is used to send mailbox command to HBA. The @cq struct * is used to get the entry count and entry size that are necessary to * determine the number of pages to allocate and use for this queue. This * function will send the MQ_CREATE mailbox command to the HBA to setup the * mailbox queue. This function is asynchronous and will wait for the mailbox * command to finish before continuing. * * On success this function will return a zero. If unable to allocate enough * memory this function will return -ENOMEM. If the queue create mailbox command * fails this function will return -ENXIO. **/ int32_t lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, struct lpfc_queue *cq, uint32_t subtype) { … } /** * lpfc_wq_create - Create a Work Queue on the HBA * @phba: HBA structure that indicates port to create a queue on. * @wq: The queue structure to use to create the work queue. * @cq: The completion queue to bind this work queue to. * @subtype: The subtype of the work queue indicating its functionality. * * This function creates a work queue, as detailed in @wq, on a port, described * by @phba by sending a WQ_CREATE mailbox command to the HBA. * * The @phba struct is used to send mailbox command to HBA. The @wq struct * is used to get the entry count and entry size that are necessary to * determine the number of pages to allocate and use for this queue. The @cq * is used to indicate which completion queue to bind this work queue to. This * function will send the WQ_CREATE mailbox command to the HBA to setup the * work queue. This function is asynchronous and will wait for the mailbox * command to finish before continuing. * * On success this function will return a zero. If unable to allocate enough * memory this function will return -ENOMEM. If the queue create mailbox command * fails this function will return -ENXIO. **/ int lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, struct lpfc_queue *cq, uint32_t subtype) { … } /** * lpfc_rq_create - Create a Receive Queue on the HBA * @phba: HBA structure that indicates port to create a queue on. * @hrq: The queue structure to use to create the header receive queue. * @drq: The queue structure to use to create the data receive queue. * @cq: The completion queue to bind this work queue to. * @subtype: The subtype of the work queue indicating its functionality. * * This function creates a receive buffer queue pair , as detailed in @hrq and * @drq, on a port, described by @phba by sending a RQ_CREATE mailbox command * to the HBA. * * The @phba struct is used to send mailbox command to HBA. The @drq and @hrq * struct is used to get the entry count that is necessary to determine the * number of pages to use for this queue. The @cq is used to indicate which * completion queue to bind received buffers that are posted to these queues to. * This function will send the RQ_CREATE mailbox command to the HBA to setup the * receive queue pair. This function is asynchronous and will wait for the * mailbox command to finish before continuing. * * On success this function will return a zero. If unable to allocate enough * memory this function will return -ENOMEM. If the queue create mailbox command * fails this function will return -ENXIO. **/ int lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, struct lpfc_queue *drq, struct lpfc_queue *cq, uint32_t subtype) { … } /** * lpfc_mrq_create - Create MRQ Receive Queues on the HBA * @phba: HBA structure that indicates port to create a queue on. * @hrqp: The queue structure array to use to create the header receive queues. * @drqp: The queue structure array to use to create the data receive queues. * @cqp: The completion queue array to bind these receive queues to. * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc). * * This function creates a receive buffer queue pair , as detailed in @hrq and * @drq, on a port, described by @phba by sending a RQ_CREATE mailbox command * to the HBA. * * The @phba struct is used to send mailbox command to HBA. The @drq and @hrq * struct is used to get the entry count that is necessary to determine the * number of pages to use for this queue. The @cq is used to indicate which * completion queue to bind received buffers that are posted to these queues to. * This function will send the RQ_CREATE mailbox command to the HBA to setup the * receive queue pair. This function is asynchronous and will wait for the * mailbox command to finish before continuing. * * On success this function will return a zero. If unable to allocate enough * memory this function will return -ENOMEM. If the queue create mailbox command * fails this function will return -ENXIO. **/ int lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp, struct lpfc_queue **drqp, struct lpfc_queue **cqp, uint32_t subtype) { … } /** * lpfc_eq_destroy - Destroy an event Queue on the HBA * @phba: HBA structure that indicates port to destroy a queue on. * @eq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @eq by sending an mailbox * command, specific to the type of queue, to the HBA. * * The @eq struct is used to get the queue ID of the queue to destroy. * * On success this function will return a zero. If the queue destroy mailbox * command fails this function will return -ENXIO. **/ int lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq) { … } /** * lpfc_cq_destroy - Destroy a Completion Queue on the HBA * @phba: HBA structure that indicates port to destroy a queue on. * @cq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @cq by sending an mailbox * command, specific to the type of queue, to the HBA. * * The @cq struct is used to get the queue ID of the queue to destroy. * * On success this function will return a zero. If the queue destroy mailbox * command fails this function will return -ENXIO. **/ int lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq) { … } /** * lpfc_mq_destroy - Destroy a Mailbox Queue on the HBA * @phba: HBA structure that indicates port to destroy a queue on. * @mq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @mq by sending an mailbox * command, specific to the type of queue, to the HBA. * * The @mq struct is used to get the queue ID of the queue to destroy. * * On success this function will return a zero. If the queue destroy mailbox * command fails this function will return -ENXIO. **/ int lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq) { … } /** * lpfc_wq_destroy - Destroy a Work Queue on the HBA * @phba: HBA structure that indicates port to destroy a queue on. * @wq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @wq by sending an mailbox * command, specific to the type of queue, to the HBA. * * The @wq struct is used to get the queue ID of the queue to destroy. * * On success this function will return a zero. If the queue destroy mailbox * command fails this function will return -ENXIO. **/ int lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq) { … } /** * lpfc_rq_destroy - Destroy a Receive Queue on the HBA * @phba: HBA structure that indicates port to destroy a queue on. * @hrq: The queue structure associated with the queue to destroy. * @drq: The queue structure associated with the queue to destroy. * * This function destroys a queue, as detailed in @rq by sending an mailbox * command, specific to the type of queue, to the HBA. * * The @rq struct is used to get the queue ID of the queue to destroy. * * On success this function will return a zero. If the queue destroy mailbox * command fails this function will return -ENXIO. **/ int lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq, struct lpfc_queue *drq) { … } /** * lpfc_sli4_post_sgl - Post scatter gather list for an XRI to HBA * @phba: The virtual port for which this call being executed. * @pdma_phys_addr0: Physical address of the 1st SGL page. * @pdma_phys_addr1: Physical address of the 2nd SGL page. * @xritag: the xritag that ties this io to the SGL pages. * * This routine will post the sgl pages for the IO that has the xritag * that is in the iocbq structure. The xritag is assigned during iocbq * creation and persists for as long as the driver is loaded. * if the caller has fewer than 256 scatter gather segments to map then * pdma_phys_addr1 should be 0. * If the caller needs to map more than 256 scatter gather segment then * pdma_phys_addr1 should be a valid physical address. * physical address for SGLs must be 64 byte aligned. * If you are going to map 2 SGL's then the first one must have 256 entries * the second sgl can have between 1 and 256 entries. * * Return codes: * 0 - Success * -ENXIO, -ENOMEM - Failure **/ int lpfc_sli4_post_sgl(struct lpfc_hba *phba, dma_addr_t pdma_phys_addr0, dma_addr_t pdma_phys_addr1, uint16_t xritag) { … } /** * lpfc_sli4_alloc_xri - Get an available rpi in the device's range * @phba: pointer to lpfc hba data structure. * * This routine is invoked to post rpi header templates to the * HBA consistent with the SLI-4 interface spec. This routine * posts a SLI4_PAGE_SIZE memory region to the port to hold up to * SLI4_PAGE_SIZE modulo 64 rpi context headers. * * Returns * A nonzero rpi defined as rpi_base <= rpi < max_rpi if successful * LPFC_RPI_ALLOC_ERROR if no rpis are available. **/ static uint16_t lpfc_sli4_alloc_xri(struct lpfc_hba *phba) { … } /** * __lpfc_sli4_free_xri - Release an xri for reuse. * @phba: pointer to lpfc hba data structure. * @xri: xri to release. * * This routine is invoked to release an xri to the pool of * available rpis maintained by the driver. **/ static void __lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri) { … } /** * lpfc_sli4_free_xri - Release an xri for reuse. * @phba: pointer to lpfc hba data structure. * @xri: xri to release. * * This routine is invoked to release an xri to the pool of * available rpis maintained by the driver. **/ void lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri) { … } /** * lpfc_sli4_next_xritag - Get an xritag for the io * @phba: Pointer to HBA context object. * * This function gets an xritag for the iocb. If there is no unused xritag * it will return 0xffff. * The function returns the allocated xritag if successful, else returns zero. * Zero is not a valid xritag. * The caller is not required to hold any lock. **/ uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *phba) { … } /** * lpfc_sli4_post_sgl_list - post a block of ELS sgls to the port. * @phba: pointer to lpfc hba data structure. * @post_sgl_list: pointer to els sgl entry list. * @post_cnt: number of els sgl entries on the list. * * This routine is invoked to post a block of driver's sgl pages to the * HBA using non-embedded mailbox command. No Lock is held. This routine * is only called when the driver is loading and after all IO has been * stopped. **/ static int lpfc_sli4_post_sgl_list(struct lpfc_hba *phba, struct list_head *post_sgl_list, int post_cnt) { … } /** * lpfc_sli4_post_io_sgl_block - post a block of nvme sgl list to firmware * @phba: pointer to lpfc hba data structure. * @nblist: pointer to nvme buffer list. * @count: number of scsi buffers on the list. * * This routine is invoked to post a block of @count scsi sgl pages from a * SCSI buffer list @nblist to the HBA using non-embedded mailbox command. * No Lock is held. * **/ static int lpfc_sli4_post_io_sgl_block(struct lpfc_hba *phba, struct list_head *nblist, int count) { … } /** * lpfc_sli4_post_io_sgl_list - Post blocks of nvme buffer sgls from a list * @phba: pointer to lpfc hba data structure. * @post_nblist: pointer to the nvme buffer list. * @sb_count: number of nvme buffers. * * This routine walks a list of nvme buffers that was passed in. It attempts * to construct blocks of nvme buffer sgls which contains contiguous xris and * uses the non-embedded SGL block post mailbox commands to post to the port. * For single NVME buffer sgl with non-contiguous xri, if any, it shall use * embedded SGL post mailbox command for posting. The @post_nblist passed in * must be local list, thus no lock is needed when manipulate the list. * * Returns: 0 = failure, non-zero number of successfully posted buffers. **/ int lpfc_sli4_post_io_sgl_list(struct lpfc_hba *phba, struct list_head *post_nblist, int sb_count) { … } /** * lpfc_fc_frame_check - Check that this frame is a valid frame to handle * @phba: pointer to lpfc_hba struct that the frame was received on * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) * * This function checks the fields in the @fc_hdr to see if the FC frame is a * valid type of frame that the LPFC driver will handle. This function will * return a zero if the frame is a valid frame or a non zero value when the * frame does not pass the check. **/ static int lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr) { … } /** * lpfc_fc_hdr_get_vfi - Get the VFI from an FC frame * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) * * This function processes the FC header to retrieve the VFI from the VF * header, if one exists. This function will return the VFI if one exists * or 0 if no VSAN Header exists. **/ static uint32_t lpfc_fc_hdr_get_vfi(struct fc_frame_header *fc_hdr) { … } /** * lpfc_fc_frame_to_vport - Finds the vport that a frame is destined to * @phba: Pointer to the HBA structure to search for the vport on * @fc_hdr: A pointer to the FC Header data (In Big Endian Format) * @fcfi: The FC Fabric ID that the frame came from * @did: Destination ID to match against * * This function searches the @phba for a vport that matches the content of the * @fc_hdr passed in and the @fcfi. This function uses the @fc_hdr to fetch the * VFI, if the Virtual Fabric Tagging Header exists, and the DID. This function * returns the matching vport pointer or NULL if unable to match frame to a * vport. **/ static struct lpfc_vport * lpfc_fc_frame_to_vport(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr, uint16_t fcfi, uint32_t did) { … } /** * lpfc_update_rcv_time_stamp - Update vport's rcv seq time stamp * @vport: The vport to work on. * * This function updates the receive sequence time stamp for this vport. The * receive sequence time stamp indicates the time that the last frame of the * the sequence that has been idle for the longest amount of time was received. * the driver uses this time stamp to indicate if any received sequences have * timed out. **/ static void lpfc_update_rcv_time_stamp(struct lpfc_vport *vport) { … } /** * lpfc_cleanup_rcv_buffers - Cleans up all outstanding receive sequences. * @vport: The vport that the received sequences were sent to. * * This function cleans up all outstanding received sequences. This is called * by the driver when a link event or user action invalidates all the received * sequences. **/ void lpfc_cleanup_rcv_buffers(struct lpfc_vport *vport) { … } /** * lpfc_rcv_seq_check_edtov - Cleans up timed out receive sequences. * @vport: The vport that the received sequences were sent to. * * This function determines whether any received sequences have timed out by * first checking the vport's rcv_buffer_time_stamp. If this time_stamp * indicates that there is at least one timed out sequence this routine will * go through the received sequences one at a time from most inactive to most * active to determine which ones need to be cleaned up. Once it has determined * that a sequence needs to be cleaned up it will simply free up the resources * without sending an abort. **/ void lpfc_rcv_seq_check_edtov(struct lpfc_vport *vport) { … } /** * lpfc_fc_frame_add - Adds a frame to the vport's list of received sequences * @vport: pointer to a vitural port * @dmabuf: pointer to a dmabuf that describes the hdr and data of the FC frame * * This function searches through the existing incomplete sequences that have * been sent to this @vport. If the frame matches one of the incomplete * sequences then the dbuf in the @dmabuf is added to the list of frames that * make up that sequence. If no sequence is found that matches this frame then * the function will add the hbuf in the @dmabuf to the @vport's rcv_buffer_list * This function returns a pointer to the first dmabuf in the sequence list that * the frame was linked to. **/ static struct hbq_dmabuf * lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) { … } /** * lpfc_sli4_abort_partial_seq - Abort partially assembled unsol sequence * @vport: pointer to a vitural port * @dmabuf: pointer to a dmabuf that describes the FC sequence * * This function tries to abort from the partially assembed sequence, described * by the information from basic abbort @dmabuf. It checks to see whether such * partially assembled sequence held by the driver. If so, it shall free up all * the frames from the partially assembled sequence. * * Return * true -- if there is matching partially assembled sequence present and all * the frames freed with the sequence; * false -- if there is no matching partially assembled sequence present so * nothing got aborted in the lower layer driver **/ static bool lpfc_sli4_abort_partial_seq(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) { … } /** * lpfc_sli4_abort_ulp_seq - Abort assembled unsol sequence from ulp * @vport: pointer to a vitural port * @dmabuf: pointer to a dmabuf that describes the FC sequence * * This function tries to abort from the assembed sequence from upper level * protocol, described by the information from basic abbort @dmabuf. It * checks to see whether such pending context exists at upper level protocol. * If so, it shall clean up the pending context. * * Return * true -- if there is matching pending context of the sequence cleaned * at ulp; * false -- if there is no matching pending context of the sequence present * at ulp. **/ static bool lpfc_sli4_abort_ulp_seq(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) { … } /** * lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler * @phba: Pointer to HBA context object. * @cmd_iocbq: pointer to the command iocbq structure. * @rsp_iocbq: pointer to the response iocbq structure. * * This function handles the sequence abort response iocb command complete * event. It properly releases the memory allocated to the sequence abort * accept iocb. **/ static void lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmd_iocbq, struct lpfc_iocbq *rsp_iocbq) { … } /** * lpfc_sli4_xri_inrange - check xri is in range of xris owned by driver. * @phba: Pointer to HBA context object. * @xri: xri id in transaction. * * This function validates the xri maps to the known range of XRIs allocated an * used by the driver. **/ uint16_t lpfc_sli4_xri_inrange(struct lpfc_hba *phba, uint16_t xri) { … } /** * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort * @vport: pointer to a virtual port. * @fc_hdr: pointer to a FC frame header. * @aborted: was the partially assembled receive sequence successfully aborted * * This function sends a basic response to a previous unsol sequence abort * event after aborting the sequence handling. **/ void lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, struct fc_frame_header *fc_hdr, bool aborted) { … } /** * lpfc_sli4_handle_unsol_abort - Handle sli-4 unsolicited abort event * @vport: Pointer to the vport on which this sequence was received * @dmabuf: pointer to a dmabuf that describes the FC sequence * * This function handles an SLI-4 unsolicited abort event. If the unsolicited * receive sequence is only partially assembed by the driver, it shall abort * the partially assembled frames for the sequence. Otherwise, if the * unsolicited receive sequence has been completely assembled and passed to * the Upper Layer Protocol (ULP), it then mark the per oxid status for the * unsolicited sequence has been aborted. After that, it will issue a basic * accept to accept the abort. **/ static void lpfc_sli4_handle_unsol_abort(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) { … } /** * lpfc_seq_complete - Indicates if a sequence is complete * @dmabuf: pointer to a dmabuf that describes the FC sequence * * This function checks the sequence, starting with the frame described by * @dmabuf, to see if all the frames associated with this sequence are present. * the frames associated with this sequence are linked to the @dmabuf using the * dbuf list. This function looks for two major things. 1) That the first frame * has a sequence count of zero. 2) There is a frame with last frame of sequence * set. 3) That there are no holes in the sequence count. The function will * return 1 when the sequence is complete, otherwise it will return 0. **/ static int lpfc_seq_complete(struct hbq_dmabuf *dmabuf) { … } /** * lpfc_prep_seq - Prep sequence for ULP processing * @vport: Pointer to the vport on which this sequence was received * @seq_dmabuf: pointer to a dmabuf that describes the FC sequence * * This function takes a sequence, described by a list of frames, and creates * a list of iocbq structures to describe the sequence. This iocbq list will be * used to issue to the generic unsolicited sequence handler. This routine * returns a pointer to the first iocbq in the list. If the function is unable * to allocate an iocbq then it throw out the received frames that were not * able to be described and return a pointer to the first iocbq. If unable to * allocate any iocbqs (including the first) this function will return NULL. **/ static struct lpfc_iocbq * lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) { … } static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) { … } static void lpfc_sli4_mds_loopback_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { … } static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) { … } /** * lpfc_sli4_handle_received_buffer - Handle received buffers from firmware * @phba: Pointer to HBA context object. * @dmabuf: Pointer to a dmabuf that describes the FC sequence. * * This function is called with no lock held. This function processes all * the received buffers and gives it to upper layers when a received buffer * indicates that it is the final frame in the sequence. The interrupt * service routine processes received buffers at interrupt contexts. * Worker thread calls lpfc_sli4_handle_received_buffer, which will call the * appropriate receive function when the final frame in a sequence is received. **/ void lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf) { … } /** * lpfc_sli4_post_all_rpi_hdrs - Post the rpi header memory region to the port * @phba: pointer to lpfc hba data structure. * * This routine is invoked to post rpi header templates to the * HBA consistent with the SLI-4 interface spec. This routine * posts a SLI4_PAGE_SIZE memory region to the port to hold up to * SLI4_PAGE_SIZE modulo 64 rpi context headers. * * This routine does not require any locks. It's usage is expected * to be driver load or reset recovery when the driver is * sequential. * * Return codes * 0 - successful * -EIO - The mailbox failed to complete successfully. * When this error occurs, the driver is not guaranteed * to have any rpi regions posted to the device and * must either attempt to repost the regions or take a * fatal error. **/ int lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba) { … } /** * lpfc_sli4_post_rpi_hdr - Post an rpi header memory region to the port * @phba: pointer to lpfc hba data structure. * @rpi_page: pointer to the rpi memory region. * * This routine is invoked to post a single rpi header to the * HBA consistent with the SLI-4 interface spec. This memory region * maps up to 64 rpi context regions. * * Return codes * 0 - successful * -ENOMEM - No available memory * -EIO - The mailbox failed to complete successfully. **/ int lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) { … } /** * lpfc_sli4_alloc_rpi - Get an available rpi in the device's range * @phba: pointer to lpfc hba data structure. * * This routine is invoked to post rpi header templates to the * HBA consistent with the SLI-4 interface spec. This routine * posts a SLI4_PAGE_SIZE memory region to the port to hold up to * SLI4_PAGE_SIZE modulo 64 rpi context headers. * * Returns * A nonzero rpi defined as rpi_base <= rpi < max_rpi if successful * LPFC_RPI_ALLOC_ERROR if no rpis are available. **/ int lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) { … } /** * __lpfc_sli4_free_rpi - Release an rpi for reuse. * @phba: pointer to lpfc hba data structure. * @rpi: rpi to free * * This routine is invoked to release an rpi to the pool of * available rpis maintained by the driver. **/ static void __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) { … } /** * lpfc_sli4_free_rpi - Release an rpi for reuse. * @phba: pointer to lpfc hba data structure. * @rpi: rpi to free * * This routine is invoked to release an rpi to the pool of * available rpis maintained by the driver. **/ void lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) { … } /** * lpfc_sli4_remove_rpis - Remove the rpi bitmask region * @phba: pointer to lpfc hba data structure. * * This routine is invoked to remove the memory region that * provided rpi via a bitmask. **/ void lpfc_sli4_remove_rpis(struct lpfc_hba *phba) { … } /** * lpfc_sli4_resume_rpi - Remove the rpi bitmask region * @ndlp: pointer to lpfc nodelist data structure. * @cmpl: completion call-back. * @iocbq: data to load as mbox ctx_u information * * This routine is invoked to remove the memory region that * provided rpi via a bitmask. **/ int lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp, void (*cmpl)(struct lpfc_hba *, LPFC_MBOXQ_t *), struct lpfc_iocbq *iocbq) { … } /** * lpfc_sli4_init_vpi - Initialize a vpi with the port * @vport: Pointer to the vport for which the vpi is being initialized * * This routine is invoked to activate a vpi with the port. * * Returns: * 0 success * -Evalue otherwise **/ int lpfc_sli4_init_vpi(struct lpfc_vport *vport) { … } /** * lpfc_mbx_cmpl_add_fcf_record - add fcf mbox completion handler. * @phba: pointer to lpfc hba data structure. * @mboxq: Pointer to mailbox object. * * This routine is invoked to manually add a single FCF record. The caller * must pass a completely initialized FCF_Record. This routine takes * care of the nonembedded mailbox operations. **/ static void lpfc_mbx_cmpl_add_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { … } /** * lpfc_sli4_add_fcf_record - Manually add an FCF Record. * @phba: pointer to lpfc hba data structure. * @fcf_record: pointer to the initialized fcf record to add. * * This routine is invoked to manually add a single FCF record. The caller * must pass a completely initialized FCF_Record. This routine takes * care of the nonembedded mailbox operations. **/ int lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record) { … } /** * lpfc_sli4_build_dflt_fcf_record - Build the driver's default FCF Record. * @phba: pointer to lpfc hba data structure. * @fcf_record: pointer to the fcf record to write the default data. * @fcf_index: FCF table entry index. * * This routine is invoked to build the driver's default FCF record. The * values used are hardcoded. This routine handles memory initialization. * **/ void lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record, uint16_t fcf_index) { … } /** * lpfc_sli4_fcf_scan_read_fcf_rec - Read hba fcf record for fcf scan. * @phba: pointer to lpfc hba data structure. * @fcf_index: FCF table entry offset. * * This routine is invoked to scan the entire FCF table by reading FCF * record and processing it one at a time starting from the @fcf_index * for initial FCF discovery or fast FCF failover rediscovery. * * Return 0 if the mailbox command is submitted successfully, none 0 * otherwise. **/ int lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) { … } /** * lpfc_sli4_fcf_rr_read_fcf_rec - Read hba fcf record for roundrobin fcf. * @phba: pointer to lpfc hba data structure. * @fcf_index: FCF table entry offset. * * This routine is invoked to read an FCF record indicated by @fcf_index * and to use it for FLOGI roundrobin FCF failover. * * Return 0 if the mailbox command is submitted successfully, none 0 * otherwise. **/ int lpfc_sli4_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) { … } /** * lpfc_sli4_read_fcf_rec - Read hba fcf record for update eligible fcf bmask. * @phba: pointer to lpfc hba data structure. * @fcf_index: FCF table entry offset. * * This routine is invoked to read an FCF record indicated by @fcf_index to * determine whether it's eligible for FLOGI roundrobin failover list. * * Return 0 if the mailbox command is submitted successfully, none 0 * otherwise. **/ int lpfc_sli4_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) { … } /** * lpfc_check_next_fcf_pri_level * @phba: pointer to the lpfc_hba struct for this port. * This routine is called from the lpfc_sli4_fcf_rr_next_index_get * routine when the rr_bmask is empty. The FCF indecies are put into the * rr_bmask based on their priority level. Starting from the highest priority * to the lowest. The most likely FCF candidate will be in the highest * priority group. When this routine is called it searches the fcf_pri list for * next lowest priority group and repopulates the rr_bmask with only those * fcf_indexes. * returns: * 1=success 0=failure **/ static int lpfc_check_next_fcf_pri_level(struct lpfc_hba *phba) { … } /** * lpfc_sli4_fcf_rr_next_index_get - Get next eligible fcf record index * @phba: pointer to lpfc hba data structure. * * This routine is to get the next eligible FCF record index in a round * robin fashion. If the next eligible FCF record index equals to the * initial roundrobin FCF record index, LPFC_FCOE_FCF_NEXT_NONE (0xFFFF) * shall be returned, otherwise, the next eligible FCF record's index * shall be returned. **/ uint16_t lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) { … } /** * lpfc_sli4_fcf_rr_index_set - Set bmask with eligible fcf record index * @phba: pointer to lpfc hba data structure. * @fcf_index: index into the FCF table to 'set' * * This routine sets the FCF record index in to the eligible bmask for * roundrobin failover search. It checks to make sure that the index * does not go beyond the range of the driver allocated bmask dimension * before setting the bit. * * Returns 0 if the index bit successfully set, otherwise, it returns * -EINVAL. **/ int lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) { … } /** * lpfc_sli4_fcf_rr_index_clear - Clear bmask from eligible fcf record index * @phba: pointer to lpfc hba data structure. * @fcf_index: index into the FCF table to 'clear' * * This routine clears the FCF record index from the eligible bmask for * roundrobin failover search. It checks to make sure that the index * does not go beyond the range of the driver allocated bmask dimension * before clearing the bit. **/ void lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) { … } /** * lpfc_mbx_cmpl_redisc_fcf_table - completion routine for rediscover FCF table * @phba: pointer to lpfc hba data structure. * @mbox: An allocated pointer to type LPFC_MBOXQ_t * * This routine is the completion routine for the rediscover FCF table mailbox * command. If the mailbox command returned failure, it will try to stop the * FCF rediscover wait timer. **/ static void lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) { … } /** * lpfc_sli4_redisc_fcf_table - Request to rediscover entire FCF table by port. * @phba: pointer to lpfc hba data structure. * * This routine is invoked to request for rediscovery of the entire FCF table * by the port. **/ int lpfc_sli4_redisc_fcf_table(struct lpfc_hba *phba) { … } /** * lpfc_sli4_fcf_dead_failthrough - Failthrough routine to fcf dead event * @phba: pointer to lpfc hba data structure. * * This function is the failover routine as a last resort to the FCF DEAD * event when driver failed to perform fast FCF failover. **/ void lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *phba) { … } /** * lpfc_sli_get_config_region23 - Get sli3 port region 23 data. * @phba: pointer to lpfc hba data structure. * @rgn23_data: pointer to configure region 23 data. * * This function gets SLI3 port configure region 23 data through memory dump * mailbox command. When it successfully retrieves data, the size of the data * will be returned, otherwise, 0 will be returned. **/ static uint32_t lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) { … } /** * lpfc_sli4_get_config_region23 - Get sli4 port region 23 data. * @phba: pointer to lpfc hba data structure. * @rgn23_data: pointer to configure region 23 data. * * This function gets SLI4 port configure region 23 data through memory dump * mailbox command. When it successfully retrieves data, the size of the data * will be returned, otherwise, 0 will be returned. **/ static uint32_t lpfc_sli4_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) { … } /** * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled. * @phba: pointer to lpfc hba data structure. * * This function read region 23 and parse TLV for port status to * decide if the user disaled the port. If the TLV indicates the * port is disabled, the hba_flag is set accordingly. **/ void lpfc_sli_read_link_ste(struct lpfc_hba *phba) { … } /** * lpfc_log_fw_write_cmpl - logs firmware write completion status * @phba: pointer to lpfc hba data structure * @shdr_status: wr_object rsp's status field * @shdr_add_status: wr_object rsp's add_status field * @shdr_add_status_2: wr_object rsp's add_status_2 field * @shdr_change_status: wr_object rsp's change_status field * @shdr_csf: wr_object rsp's csf bit * * This routine is intended to be called after a firmware write completes. * It will log next action items to be performed by the user to instantiate * the newly downloaded firmware or reason for incompatibility. **/ static void lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, u32 shdr_add_status, u32 shdr_add_status_2, u32 shdr_change_status, u32 shdr_csf) { … } /** * lpfc_wr_object - write an object to the firmware * @phba: HBA structure that indicates port to create a queue on. * @dmabuf_list: list of dmabufs to write to the port. * @size: the total byte value of the objects to write to the port. * @offset: the current offset to be used to start the transfer. * * This routine will create a wr_object mailbox command to send to the port. * the mailbox command will be constructed using the dma buffers described in * @dmabuf_list to create a list of BDEs. This routine will fill in as many * BDEs that the imbedded mailbox can support. The @offset variable will be * used to indicate the starting offset of the transfer and will also return * the offset after the write object mailbox has completed. @size is used to * determine the end of the object and whether the eof bit should be set. * * Return 0 is successful and offset will contain the new offset to use * for the next write. * Return negative value for error cases. **/ int lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list, uint32_t size, uint32_t *offset) { … } /** * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. * @vport: pointer to vport data structure. * * This function iterate through the mailboxq and clean up all REG_LOGIN * and REG_VPI mailbox commands associated with the vport. This function * is called when driver want to restart discovery of the vport due to * a Clear Virtual Link event. **/ void lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) { … } /** * lpfc_drain_txq - Drain the txq * @phba: Pointer to HBA context object. * * This function attempt to submit IOCBs on the txq * to the adapter. For SLI4 adapters, the txq contains * ELS IOCBs that have been deferred because the there * are no SGLs. This congestion can occur with large * vport counts during node discovery. **/ uint32_t lpfc_drain_txq(struct lpfc_hba *phba) { … } /** * lpfc_wqe_bpl2sgl - Convert the bpl/bde to a sgl. * @phba: Pointer to HBA context object. * @pwqeq: Pointer to command WQE. * @sglq: Pointer to the scatter gather queue object. * * This routine converts the bpl or bde that is in the WQE * to a sgl list for the sli4 hardware. The physical address * of the bpl/bde is converted back to a virtual address. * If the WQE contains a BPL then the list of BDE's is * converted to sli4_sge's. If the WQE contains a single * BDE then it is converted to a single sli_sge. * The WQE is still in cpu endianness so the contents of * the bpl can be used without byte swapping. * * Returns valid XRI = Success, NO_XRI = Failure. */ static uint16_t lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeq, struct lpfc_sglq *sglq) { … } /** * lpfc_sli4_issue_wqe - Issue an SLI4 Work Queue Entry (WQE) * @phba: Pointer to HBA context object. * @qp: Pointer to HDW queue. * @pwqe: Pointer to command WQE. **/ int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, struct lpfc_iocbq *pwqe) { … } /** * lpfc_sli4_issue_abort_iotag - SLI-4 WQE init & issue for the Abort * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. * @cmpl: completion function. * * Fill the appropriate fields for the abort WQE and call * internal routine lpfc_sli4_issue_wqe to send the WQE * This function is called with hbalock held and no ring_lock held. * * RETURNS 0 - SUCCESS **/ int lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, void *cmpl) { … } #ifdef LPFC_MXP_STAT /** * lpfc_snapshot_mxp - Snapshot pbl, pvt and busy count * @phba: pointer to lpfc hba data structure. * @hwqid: belong to which HWQ. * * The purpose of this routine is to take a snapshot of pbl, pvt and busy count * 15 seconds after a test case is running. * * The user should call lpfc_debugfs_multixripools_write before running a test * case to clear stat_snapshot_taken. Then the user starts a test case. During * test case is running, stat_snapshot_taken is incremented by 1 every time when * this routine is called from heartbeat timer. When stat_snapshot_taken is * equal to LPFC_MXP_SNAPSHOT_TAKEN, a snapshot is taken. **/ void lpfc_snapshot_mxp(struct lpfc_hba *phba, u32 hwqid) { struct lpfc_sli4_hdw_queue *qp; struct lpfc_multixri_pool *multixri_pool; struct lpfc_pvt_pool *pvt_pool; struct lpfc_pbl_pool *pbl_pool; u32 txcmplq_cnt; qp = &phba->sli4_hba.hdwq[hwqid]; multixri_pool = qp->p_multixri_pool; if (!multixri_pool) return; if (multixri_pool->stat_snapshot_taken == LPFC_MXP_SNAPSHOT_TAKEN) { pvt_pool = &qp->p_multixri_pool->pvt_pool; pbl_pool = &qp->p_multixri_pool->pbl_pool; txcmplq_cnt = qp->io_wq->pring->txcmplq_cnt; multixri_pool->stat_pbl_count = pbl_pool->count; multixri_pool->stat_pvt_count = pvt_pool->count; multixri_pool->stat_busy_count = txcmplq_cnt; } multixri_pool->stat_snapshot_taken++; } #endif /** * lpfc_adjust_pvt_pool_count - Adjust private pool count * @phba: pointer to lpfc hba data structure. * @hwqid: belong to which HWQ. * * This routine moves some XRIs from private to public pool when private pool * is not busy. **/ void lpfc_adjust_pvt_pool_count(struct lpfc_hba *phba, u32 hwqid) { … } /** * lpfc_adjust_high_watermark - Adjust high watermark * @phba: pointer to lpfc hba data structure. * @hwqid: belong to which HWQ. * * This routine sets high watermark as number of outstanding XRIs, * but make sure the new value is between xri_limit/2 and xri_limit. **/ void lpfc_adjust_high_watermark(struct lpfc_hba *phba, u32 hwqid) { … } /** * lpfc_move_xri_pvt_to_pbl - Move some XRIs from private to public pool * @phba: pointer to lpfc hba data structure. * @hwqid: belong to which HWQ. * * This routine is called from hearbeat timer when pvt_pool is idle. * All free XRIs are moved from private to public pool on hwqid with 2 steps. * The first step moves (all - low_watermark) amount of XRIs. * The second step moves the rest of XRIs. **/ void lpfc_move_xri_pvt_to_pbl(struct lpfc_hba *phba, u32 hwqid) { … } /** * _lpfc_move_xri_pbl_to_pvt - Move some XRIs from public to private pool * @phba: pointer to lpfc hba data structure * @qp: pointer to HDW queue * @pbl_pool: specified public free XRI pool * @pvt_pool: specified private free XRI pool * @count: number of XRIs to move * * This routine tries to move some free common bufs from the specified pbl_pool * to the specified pvt_pool. It might move less than count XRIs if there's not * enough in public pool. * * Return: * true - if XRIs are successfully moved from the specified pbl_pool to the * specified pvt_pool * false - if the specified pbl_pool is empty or locked by someone else **/ static bool _lpfc_move_xri_pbl_to_pvt(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, struct lpfc_pbl_pool *pbl_pool, struct lpfc_pvt_pool *pvt_pool, u32 count) { … } /** * lpfc_move_xri_pbl_to_pvt - Move some XRIs from public to private pool * @phba: pointer to lpfc hba data structure. * @hwqid: belong to which HWQ. * @count: number of XRIs to move * * This routine tries to find some free common bufs in one of public pools with * Round Robin method. The search always starts from local hwqid, then the next * HWQ which was found last time (rrb_next_hwqid). Once a public pool is found, * a batch of free common bufs are moved to private pool on hwqid. * It might move less than count XRIs if there's not enough in public pool. **/ void lpfc_move_xri_pbl_to_pvt(struct lpfc_hba *phba, u32 hwqid, u32 count) { … } /** * lpfc_keep_pvt_pool_above_lowwm - Keep pvt_pool above low watermark * @phba: pointer to lpfc hba data structure. * @hwqid: belong to which HWQ. * * This routine get a batch of XRIs from pbl_pool if pvt_pool is less than * low watermark. **/ void lpfc_keep_pvt_pool_above_lowwm(struct lpfc_hba *phba, u32 hwqid) { … } /** * lpfc_release_io_buf - Return one IO buf back to free pool * @phba: pointer to lpfc hba data structure. * @lpfc_ncmd: IO buf to be returned. * @qp: belong to which HWQ. * * This routine returns one IO buf back to free pool. If this is an urgent IO, * the IO buf is returned to expedite pool. If cfg_xri_rebalancing==1, * the IO buf is returned to pbl_pool or pvt_pool based on watermark and * xri_limit. If cfg_xri_rebalancing==0, the IO buf is returned to * lpfc_io_buf_list_put. **/ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd, struct lpfc_sli4_hdw_queue *qp) { … } /** * lpfc_get_io_buf_from_private_pool - Get one free IO buf from private pool * @phba: pointer to lpfc hba data structure. * @qp: pointer to HDW queue * @pvt_pool: pointer to private pool data structure. * @ndlp: pointer to lpfc nodelist data structure. * * This routine tries to get one free IO buf from private pool. * * Return: * pointer to one free IO buf - if private pool is not empty * NULL - if private pool is empty **/ static struct lpfc_io_buf * lpfc_get_io_buf_from_private_pool(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, struct lpfc_pvt_pool *pvt_pool, struct lpfc_nodelist *ndlp) { … } /** * lpfc_get_io_buf_from_expedite_pool - Get one free IO buf from expedite pool * @phba: pointer to lpfc hba data structure. * * This routine tries to get one free IO buf from expedite pool. * * Return: * pointer to one free IO buf - if expedite pool is not empty * NULL - if expedite pool is empty **/ static struct lpfc_io_buf * lpfc_get_io_buf_from_expedite_pool(struct lpfc_hba *phba) { … } /** * lpfc_get_io_buf_from_multixri_pools - Get one free IO bufs * @phba: pointer to lpfc hba data structure. * @ndlp: pointer to lpfc nodelist data structure. * @hwqid: belong to which HWQ * @expedite: 1 means this request is urgent. * * This routine will do the following actions and then return a pointer to * one free IO buf. * * 1. If private free xri count is empty, move some XRIs from public to * private pool. * 2. Get one XRI from private free xri pool. * 3. If we fail to get one from pvt_pool and this is an expedite request, * get one free xri from expedite pool. * * Note: ndlp is only used on SCSI side for RRQ testing. * The caller should pass NULL for ndlp on NVME side. * * Return: * pointer to one free IO buf - if private pool is not empty * NULL - if private pool is empty **/ static struct lpfc_io_buf * lpfc_get_io_buf_from_multixri_pools(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int hwqid, int expedite) { … } static inline struct lpfc_io_buf * lpfc_io_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int idx) { … } /** * lpfc_get_io_buf - Get one IO buffer from free pool * @phba: The HBA for which this call is being executed. * @ndlp: pointer to lpfc nodelist data structure. * @hwqid: belong to which HWQ * @expedite: 1 means this request is urgent. * * This routine gets one IO buffer from free pool. If cfg_xri_rebalancing==1, * removes a IO buffer from multiXRI pools. If cfg_xri_rebalancing==0, removes * a IO buffer from head of @hdwq io_buf_list and returns to caller. * * Note: ndlp is only used on SCSI side for RRQ testing. * The caller should pass NULL for ndlp on NVME side. * * Return codes: * NULL - Error * Pointer to lpfc_io_buf - Success **/ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, u32 hwqid, int expedite) { … } /** * lpfc_read_object - Retrieve object data from HBA * @phba: The HBA for which this call is being executed. * @rdobject: Pathname of object data we want to read. * @datap: Pointer to where data will be copied to. * @datasz: size of data area * * This routine is limited to object sizes of LPFC_BPL_SIZE (1024) or less. * The data will be truncated if datasz is not large enough. * Version 1 is not supported with Embedded mbox cmd, so we must use version 0. * Returns the actual bytes read from the object. * * This routine is hard coded to use a poll completion. Unlike other * sli4_config mailboxes, it uses lpfc_mbuf memory which is not * cleaned up in lpfc_sli4_cmd_mbox_free. If this routine is modified * to use interrupt-based completions, code is needed to fully cleanup * the memory. */ int lpfc_read_object(struct lpfc_hba *phba, char *rdobject, uint32_t *datap, uint32_t datasz) { … } /** * lpfc_get_sgl_per_hdwq - Get one SGL chunk from hdwq's pool * @phba: The HBA for which this call is being executed. * @lpfc_buf: IO buf structure to append the SGL chunk * * This routine gets one SGL chunk buffer from hdwq's SGL chunk pool, * and will allocate an SGL chunk if the pool is empty. * * Return codes: * NULL - Error * Pointer to sli4_hybrid_sgl - Success **/ struct sli4_hybrid_sgl * lpfc_get_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf) { … } /** * lpfc_put_sgl_per_hdwq - Put one SGL chunk into hdwq pool * @phba: The HBA for which this call is being executed. * @lpfc_buf: IO buf structure with the SGL chunk * * This routine puts one SGL chunk buffer into hdwq's SGL chunk pool. * * Return codes: * 0 - Success * -EINVAL - Error **/ int lpfc_put_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf) { … } /** * lpfc_free_sgl_per_hdwq - Free all SGL chunks of hdwq pool * @phba: phba object * @hdwq: hdwq to cleanup sgl buff resources on * * This routine frees all SGL chunks of hdwq SGL chunk pool. * * Return codes: * None **/ void lpfc_free_sgl_per_hdwq(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *hdwq) { … } /** * lpfc_get_cmd_rsp_buf_per_hdwq - Get one CMD/RSP buffer from hdwq * @phba: The HBA for which this call is being executed. * @lpfc_buf: IO buf structure to attach the CMD/RSP buffer * * This routine gets one CMD/RSP buffer from hdwq's CMD/RSP pool, * and will allocate an CMD/RSP buffer if the pool is empty. * * Return codes: * NULL - Error * Pointer to fcp_cmd_rsp_buf - Success **/ struct fcp_cmd_rsp_buf * lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf) { … } /** * lpfc_put_cmd_rsp_buf_per_hdwq - Put one CMD/RSP buffer into hdwq pool * @phba: The HBA for which this call is being executed. * @lpfc_buf: IO buf structure with the CMD/RSP buf * * This routine puts one CMD/RSP buffer into executing CPU's CMD/RSP pool. * * Return codes: * 0 - Success * -EINVAL - Error **/ int lpfc_put_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_buf) { … } /** * lpfc_free_cmd_rsp_buf_per_hdwq - Free all CMD/RSP chunks of hdwq pool * @phba: phba object * @hdwq: hdwq to cleanup cmd rsp buff resources on * * This routine frees all CMD/RSP buffers of hdwq's CMD/RSP buf pool. * * Return codes: * None **/ void lpfc_free_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *hdwq) { … } /** * lpfc_sli_prep_wqe - Prepare WQE for the command to be posted * @phba: phba object * @job: job entry of the command to be posted. * * Fill the common fields of the wqe for each of the command. * * Return codes: * None **/ void lpfc_sli_prep_wqe(struct lpfc_hba *phba, struct lpfc_iocbq *job) { … }