@@ -1768,6 +1768,184 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
17681768 return cmd_iocb;
17691769}
17701770
1771+ /**
1772+ * lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl
1773+ * @phba: Pointer to HBA context object.
1774+ * @cmdiocb: Pointer to driver command iocb object.
1775+ * @cmf_cmpl: Pointer to completed WCQE.
1776+ *
1777+ * This routine will inform the driver of any BW adjustments we need
1778+ * to make. These changes will be picked up during the next CMF
1779+ * timer interrupt. In addition, any BW changes will be logged
1780+ * with LOG_CGN_MGMT.
1781+ **/
1782+ static void
1783+ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1784+ struct lpfc_wcqe_complete *cmf_cmpl)
1785+ {
1786+ union lpfc_wqe128 *wqe;
1787+ uint32_t status, info;
1788+ uint64_t bw;
1789+ int asig, afpin, sigcnt, fpincnt;
1790+ int cg, tdp;
1791+
1792+ /* First check for error */
1793+ status = bf_get(lpfc_wcqe_c_status, cmf_cmpl);
1794+ if (status) {
1795+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1796+ "6211 CMF_SYNC_WQE Error "
1797+ "req_tag x%x status x%x hwstatus x%x "
1798+ "tdatap x%x parm x%x\n",
1799+ bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl),
1800+ bf_get(lpfc_wcqe_c_status, cmf_cmpl),
1801+ bf_get(lpfc_wcqe_c_hw_status, cmf_cmpl),
1802+ cmf_cmpl->total_data_placed,
1803+ cmf_cmpl->parameter);
1804+ goto out;
1805+ }
1806+
1807+ /* Gather congestion information on a successful cmpl */
1808+ info = cmf_cmpl->parameter;
1809+ tdp = bf_get(lpfc_wcqe_c_cmf_bw, cmf_cmpl);
1810+ cg = bf_get(lpfc_wcqe_c_cmf_cg, cmf_cmpl);
1811+
1812+ /* Get BW requirement from firmware */
1813+ bw = (uint64_t)tdp * LPFC_CMF_BLK_SIZE;
1814+ if (!bw) {
1815+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1816+ "6212 CMF_SYNC_WQE x%x: NULL bw\n",
1817+ bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl));
1818+ goto out;
1819+ }
1820+
1821+ /* Gather information needed for logging if a BW change is required */
1822+ wqe = &cmdiocb->wqe;
1823+ asig = bf_get(cmf_sync_asig, &wqe->cmf_sync);
1824+ afpin = bf_get(cmf_sync_afpin, &wqe->cmf_sync);
1825+ fpincnt = bf_get(cmf_sync_wfpincnt, &wqe->cmf_sync);
1826+ sigcnt = bf_get(cmf_sync_wsigcnt, &wqe->cmf_sync);
1827+
1828+ out:
1829+ lpfc_sli_release_iocbq(phba, cmdiocb);
1830+ }
1831+
1832+ /**
1833+ * lpfc_issue_cmf_sync_wqe - Issue a CMF_SYNC_WQE
1834+ * @phba: Pointer to HBA context object.
1835+ * @ms: ms to set in WQE interval, 0 means use init op
1836+ * @total: Total rcv bytes for this interval
1837+ *
1838+ * This routine is called every CMF timer interrupt. Its purpose is
1839+ * to issue a CMF_SYNC_WQE to the firmware to inform it of any events
1840+ * that may indicate we have congestion (FPINs or Signals). Upon
1841+ * completion, the firmware will indicate any BW restrictions the
1842+ * driver may need to take.
1843+ **/
1844+ int
1845+ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
1846+ {
1847+ union lpfc_wqe128 *wqe;
1848+ struct lpfc_iocbq *sync_buf;
1849+ unsigned long iflags;
1850+ u32 ret_val;
1851+ u32 atot, wtot, max;
1852+
1853+ /* First address any alarm / warning activity */
1854+ atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0);
1855+ wtot = atomic_xchg(&phba->cgn_sync_warn_cnt, 0);
1856+
1857+ /* ONLY Managed mode will send the CMF_SYNC_WQE to the HBA */
1858+ if (phba->cmf_active_mode != LPFC_CFG_MANAGED ||
1859+ phba->link_state == LPFC_LINK_DOWN)
1860+ return 0;
1861+
1862+ spin_lock_irqsave(&phba->hbalock, iflags);
1863+ sync_buf = __lpfc_sli_get_iocbq(phba);
1864+ if (!sync_buf) {
1865+ lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
1866+ "6213 No available WQEs for CMF_SYNC_WQE\n");
1867+ ret_val = ENOMEM;
1868+ goto out_unlock;
1869+ }
1870+
1871+ wqe = &sync_buf->wqe;
1872+
1873+ /* WQEs are reused. Clear stale data and set key fields to zero */
1874+ memset(wqe, 0, sizeof(*wqe));
1875+
1876+ /* If this is the very first CMF_SYNC_WQE, issue an init operation */
1877+ if (!ms) {
1878+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1879+ "6441 CMF Init %d - CMF_SYNC_WQE\n",
1880+ phba->fc_eventTag);
1881+ bf_set(cmf_sync_op, &wqe->cmf_sync, 1); /* 1=init */
1882+ bf_set(cmf_sync_interval, &wqe->cmf_sync, LPFC_CMF_INTERVAL);
1883+ goto initpath;
1884+ }
1885+
1886+ bf_set(cmf_sync_op, &wqe->cmf_sync, 0); /* 0=recalc */
1887+ bf_set(cmf_sync_interval, &wqe->cmf_sync, ms);
1888+
1889+ /* Check for alarms / warnings */
1890+ if (atot) {
1891+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
1892+ /* We hit an Signal alarm condition */
1893+ bf_set(cmf_sync_asig, &wqe->cmf_sync, 1);
1894+ } else {
1895+ /* We hit a FPIN alarm condition */
1896+ bf_set(cmf_sync_afpin, &wqe->cmf_sync, 1);
1897+ }
1898+ } else if (wtot) {
1899+ if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY ||
1900+ phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
1901+ /* We hit an Signal warning condition */
1902+ max = LPFC_SEC_TO_MSEC / lpfc_fabric_cgn_frequency *
1903+ lpfc_acqe_cgn_frequency;
1904+ bf_set(cmf_sync_wsigmax, &wqe->cmf_sync, max);
1905+ bf_set(cmf_sync_wsigcnt, &wqe->cmf_sync, wtot);
1906+ } else {
1907+ /* We hit a FPIN warning condition */
1908+ bf_set(cmf_sync_wfpinmax, &wqe->cmf_sync, 1);
1909+ bf_set(cmf_sync_wfpincnt, &wqe->cmf_sync, 1);
1910+ }
1911+ }
1912+
1913+ /* Update total read blocks during previous timer interval */
1914+ wqe->cmf_sync.read_bytes = (u32)(total / LPFC_CMF_BLK_SIZE);
1915+
1916+ initpath:
1917+ bf_set(cmf_sync_ver, &wqe->cmf_sync, LPFC_CMF_SYNC_VER);
1918+ wqe->cmf_sync.event_tag = phba->fc_eventTag;
1919+ bf_set(cmf_sync_cmnd, &wqe->cmf_sync, CMD_CMF_SYNC_WQE);
1920+
1921+ /* Setup reqtag to match the wqe completion. */
1922+ bf_set(cmf_sync_reqtag, &wqe->cmf_sync, sync_buf->iotag);
1923+
1924+ bf_set(cmf_sync_qosd, &wqe->cmf_sync, 1);
1925+
1926+ bf_set(cmf_sync_cmd_type, &wqe->cmf_sync, CMF_SYNC_COMMAND);
1927+ bf_set(cmf_sync_wqec, &wqe->cmf_sync, 1);
1928+ bf_set(cmf_sync_cqid, &wqe->cmf_sync, LPFC_WQE_CQ_ID_DEFAULT);
1929+
1930+ sync_buf->vport = phba->pport;
1931+ sync_buf->wqe_cmpl = lpfc_cmf_sync_cmpl;
1932+ sync_buf->iocb_cmpl = NULL;
1933+ sync_buf->context1 = NULL;
1934+ sync_buf->context2 = NULL;
1935+ sync_buf->context3 = NULL;
1936+ sync_buf->sli4_xritag = NO_XRI;
1937+
1938+ sync_buf->iocb_flag |= LPFC_IO_CMF;
1939+ ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf);
1940+ if (ret_val)
1941+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1942+ "6214 Cannot issue CMF_SYNC_WQE: x%x\n",
1943+ ret_val);
1944+ out_unlock:
1945+ spin_unlock_irqrestore(&phba->hbalock, iflags);
1946+ return ret_val;
1947+ }
1948+
17711949/**
17721950 * lpfc_sli_next_iocb_slot - Get next iocb slot in the ring
17731951 * @phba: Pointer to HBA context object.
0 commit comments