root/drivers/net/ethernet/freescale/enetc/enetc_msg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. enetc_msg_disable_mr_int
  2. enetc_msg_enable_mr_int
  3. enetc_msg_psi_msix
  4. enetc_msg_task
  5. enetc_msg_alloc_mbx
  6. enetc_msg_free_mbx
  7. enetc_msg_psi_init
  8. enetc_msg_psi_free

   1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
   2 /* Copyright 2017-2019 NXP */
   3 
   4 #include "enetc_pf.h"
   5 
   6 static void enetc_msg_disable_mr_int(struct enetc_hw *hw)
   7 {
   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);
  11 }
  12 
  13 static void enetc_msg_enable_mr_int(struct enetc_hw *hw)
  14 {
  15         u32 psiier = enetc_rd(hw, ENETC_PSIIER);
  16 
  17         enetc_wr(hw, ENETC_PSIIER, psiier | ENETC_PSIIER_MR_MASK);
  18 }
  19 
  20 static irqreturn_t enetc_msg_psi_msix(int irq, void *data)
  21 {
  22         struct enetc_si *si = (struct enetc_si *)data;
  23         struct enetc_pf *pf = enetc_si_priv(si);
  24 
  25         enetc_msg_disable_mr_int(&si->hw);
  26         schedule_work(&pf->msg_task);
  27 
  28         return IRQ_HANDLED;
  29 }
  30 
  31 static void enetc_msg_task(struct work_struct *work)
  32 {
  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;
  36         int i;
  37 
  38         for (;;) {
  39                 mr_mask = enetc_rd(hw, ENETC_PSIMSGRR) & ENETC_PSIMSGRR_MR_MASK;
  40                 if (!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);
  44                         return;
  45                 }
  46 
  47                 for (i = 0; i < pf->num_vfs; i++) {
  48                         u32 psimsgrr;
  49                         u16 msg_code;
  50 
  51                         if (!(ENETC_PSIMSGRR_MR(i) & mr_mask))
  52                                 continue;
  53 
  54                         enetc_msg_handle_rxmsg(pf, i, &msg_code);
  55 
  56                         psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code);
  57                         psimsgrr |= ENETC_PSIMSGRR_MR(i); /* w1c */
  58                         enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr);
  59                 }
  60         }
  61 }
  62 
  63 /* Init */
  64 static int enetc_msg_alloc_mbx(struct enetc_si *si, int idx)
  65 {
  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;
  70         u32 val;
  71 
  72         msg = &pf->rxmsg[idx];
  73         /* allocate and set receive buffer */
  74         msg->size = ENETC_DEFAULT_MSG_SIZE;
  75 
  76         msg->vaddr = dma_alloc_coherent(dev, msg->size, &msg->dma,
  77                                         GFP_KERNEL);
  78         if (!msg->vaddr) {
  79                 dev_err(dev, "msg: fail to alloc dma buffer of size: %d\n",
  80                         msg->size);
  81                 return -ENOMEM;
  82         }
  83 
  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);
  89 
  90         return 0;
  91 }
  92 
  93 static void enetc_msg_free_mbx(struct enetc_si *si, int idx)
  94 {
  95         struct enetc_pf *pf = enetc_si_priv(si);
  96         struct enetc_hw *hw = &si->hw;
  97         struct enetc_msg_swbd *msg;
  98 
  99         msg = &pf->rxmsg[idx];
 100         dma_free_coherent(&si->pdev->dev, msg->size, msg->vaddr, msg->dma);
 101         memset(msg, 0, sizeof(*msg));
 102 
 103         enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), 0);
 104         enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), 0);
 105 }
 106 
 107 int enetc_msg_psi_init(struct enetc_pf *pf)
 108 {
 109         struct enetc_si *si = pf->si;
 110         int vector, i, err;
 111 
 112         /* register message passing interrupt handler */
 113         snprintf(pf->msg_int_name, sizeof(pf->msg_int_name), "%s-vfmsg",
 114                  si->ndev->name);
 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);
 117         if (err) {
 118                 dev_err(&si->pdev->dev,
 119                         "PSI messaging: request_irq() failed!\n");
 120                 return err;
 121         }
 122 
 123         /* set one IRQ entry for PSI message receive notification (SI int) */
 124         enetc_wr(&si->hw, ENETC_SIMSIVR, ENETC_SI_INT_IDX);
 125 
 126         /* initialize PSI mailbox */
 127         INIT_WORK(&pf->msg_task, enetc_msg_task);
 128 
 129         for (i = 0; i < pf->num_vfs; i++) {
 130                 err = enetc_msg_alloc_mbx(si, i);
 131                 if (err)
 132                         goto err_init_mbx;
 133         }
 134 
 135         /* enable MR interrupts */
 136         enetc_msg_enable_mr_int(&si->hw);
 137 
 138         return 0;
 139 
 140 err_init_mbx:
 141         for (i--; i >= 0; i--)
 142                 enetc_msg_free_mbx(si, i);
 143 
 144         free_irq(vector, si);
 145 
 146         return err;
 147 }
 148 
 149 void enetc_msg_psi_free(struct enetc_pf *pf)
 150 {
 151         struct enetc_si *si = pf->si;
 152         int i;
 153 
 154         cancel_work_sync(&pf->msg_task);
 155 
 156         /* disable MR interrupts */
 157         enetc_msg_disable_mr_int(&si->hw);
 158 
 159         for (i = 0; i < pf->num_vfs; i++)
 160                 enetc_msg_free_mbx(si, i);
 161 
 162         /* de-register message passing interrupt handler */
 163         free_irq(pci_irq_vector(si->pdev, ENETC_SI_INT_IDX), si);
 164 }

/* [<][>][^][v][top][bottom][index][help] */