1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2017-2019 NXP */
6 static void enetc_msg_disable_mr_int(struct enetc_hw *hw)
8 u32 psiier = enetc_rd(hw, ENETC_PSIIER);
9 /* disable MR int source(s) */
10 enetc_wr(hw, ENETC_PSIIER, psiier & ~ENETC_PSIIER_MR_MASK);
13 static void enetc_msg_enable_mr_int(struct enetc_hw *hw)
15 u32 psiier = enetc_rd(hw, ENETC_PSIIER);
17 enetc_wr(hw, ENETC_PSIIER, psiier | ENETC_PSIIER_MR_MASK);
20 static irqreturn_t enetc_msg_psi_msix(int irq, void *data)
22 struct enetc_si *si = (struct enetc_si *)data;
23 struct enetc_pf *pf = enetc_si_priv(si);
25 enetc_msg_disable_mr_int(&si->hw);
26 schedule_work(&pf->msg_task);
31 static void enetc_msg_task(struct work_struct *work)
33 struct enetc_pf *pf = container_of(work, struct enetc_pf, msg_task);
34 struct enetc_hw *hw = &pf->si->hw;
35 unsigned long mr_mask;
39 mr_mask = enetc_rd(hw, ENETC_PSIMSGRR) & ENETC_PSIMSGRR_MR_MASK;
41 /* re-arm MR interrupts, w1c the IDR reg */
42 enetc_wr(hw, ENETC_PSIIDR, ENETC_PSIIER_MR_MASK);
43 enetc_msg_enable_mr_int(hw);
47 for (i = 0; i < pf->num_vfs; i++) {
51 if (!(ENETC_PSIMSGRR_MR(i) & mr_mask))
54 enetc_msg_handle_rxmsg(pf, i, &msg_code);
56 psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code);
57 psimsgrr |= ENETC_PSIMSGRR_MR(i); /* w1c */
58 enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr);
64 static int enetc_msg_alloc_mbx(struct enetc_si *si, int idx)
66 struct enetc_pf *pf = enetc_si_priv(si);
67 struct device *dev = &si->pdev->dev;
68 struct enetc_hw *hw = &si->hw;
69 struct enetc_msg_swbd *msg;
72 msg = &pf->rxmsg[idx];
73 /* allocate and set receive buffer */
74 msg->size = ENETC_DEFAULT_MSG_SIZE;
76 msg->vaddr = dma_alloc_coherent(dev, msg->size, &msg->dma,
79 dev_err(dev, "msg: fail to alloc dma buffer of size: %d\n",
84 /* set multiple of 32 bytes */
85 val = lower_32_bits(msg->dma);
86 enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), val);
87 val = upper_32_bits(msg->dma);
88 enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), val);
93 static void enetc_msg_free_mbx(struct enetc_si *si, int idx)
95 struct enetc_pf *pf = enetc_si_priv(si);
96 struct enetc_hw *hw = &si->hw;
97 struct enetc_msg_swbd *msg;
99 msg = &pf->rxmsg[idx];
100 dma_free_coherent(&si->pdev->dev, msg->size, msg->vaddr, msg->dma);
101 memset(msg, 0, sizeof(*msg));
103 enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), 0);
104 enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), 0);
107 int enetc_msg_psi_init(struct enetc_pf *pf)
109 struct enetc_si *si = pf->si;
112 /* register message passing interrupt handler */
113 snprintf(pf->msg_int_name, sizeof(pf->msg_int_name), "%s-vfmsg",
115 vector = pci_irq_vector(si->pdev, ENETC_SI_INT_IDX);
116 err = request_irq(vector, enetc_msg_psi_msix, 0, pf->msg_int_name, si);
118 dev_err(&si->pdev->dev,
119 "PSI messaging: request_irq() failed!\n");
123 /* set one IRQ entry for PSI message receive notification (SI int) */
124 enetc_wr(&si->hw, ENETC_SIMSIVR, ENETC_SI_INT_IDX);
126 /* initialize PSI mailbox */
127 INIT_WORK(&pf->msg_task, enetc_msg_task);
129 for (i = 0; i < pf->num_vfs; i++) {
130 err = enetc_msg_alloc_mbx(si, i);
135 /* enable MR interrupts */
136 enetc_msg_enable_mr_int(&si->hw);
141 for (i--; i >= 0; i--)
142 enetc_msg_free_mbx(si, i);
144 free_irq(vector, si);
149 void enetc_msg_psi_free(struct enetc_pf *pf)
151 struct enetc_si *si = pf->si;
154 cancel_work_sync(&pf->msg_task);
156 /* disable MR interrupts */
157 enetc_msg_disable_mr_int(&si->hw);
159 for (i = 0; i < pf->num_vfs; i++)
160 enetc_msg_free_mbx(si, i);
162 /* de-register message passing interrupt handler */
163 free_irq(pci_irq_vector(si->pdev, ENETC_SI_INT_IDX), si);