root/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c

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

DEFINITIONS

This source file includes following definitions.
  1. octeon_mbox_read
  2. octeon_mbox_write
  3. get_vf_stats
  4. octeon_mbox_process_cmd
  5. octeon_mbox_process_message
  6. octeon_mbox_cancel

   1 /**********************************************************************
   2  * Author: Cavium, Inc.
   3  *
   4  * Contact: support@cavium.com
   5  *          Please include "LiquidIO" in the subject.
   6  *
   7  * Copyright (c) 2003-2016 Cavium, Inc.
   8  *
   9  * This file is free software; you can redistribute it and/or modify
  10  * it under the terms of the GNU General Public License, Version 2, as
  11  * published by the Free Software Foundation.
  12  *
  13  * This file is distributed in the hope that it will be useful, but
  14  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
  15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  16  * NONINFRINGEMENT.  See the GNU General Public License for more details.
  17  ***********************************************************************/
  18 #include <linux/pci.h>
  19 #include <linux/netdevice.h>
  20 #include "liquidio_common.h"
  21 #include "octeon_droq.h"
  22 #include "octeon_iq.h"
  23 #include "response_manager.h"
  24 #include "octeon_device.h"
  25 #include "octeon_main.h"
  26 #include "octeon_mailbox.h"
  27 #include "cn23xx_pf_device.h"
  28 
  29 /**
  30  * octeon_mbox_read:
  31  * @oct: Pointer mailbox
  32  *
  33  * Reads the 8-bytes of data from the mbox register
  34  * Writes back the acknowldgement inidcating completion of read
  35  */
  36 int octeon_mbox_read(struct octeon_mbox *mbox)
  37 {
  38         union octeon_mbox_message msg;
  39         int ret = 0;
  40 
  41         spin_lock(&mbox->lock);
  42 
  43         msg.u64 = readq(mbox->mbox_read_reg);
  44 
  45         if ((msg.u64 == OCTEON_PFVFACK) || (msg.u64 == OCTEON_PFVFSIG)) {
  46                 spin_unlock(&mbox->lock);
  47                 return 0;
  48         }
  49 
  50         if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
  51                 mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = msg.u64;
  52                 mbox->mbox_req.recv_len++;
  53         } else {
  54                 if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
  55                         mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
  56                                 msg.u64;
  57                         mbox->mbox_resp.recv_len++;
  58                 } else {
  59                         if ((mbox->state & OCTEON_MBOX_STATE_IDLE) &&
  60                             (msg.s.type == OCTEON_MBOX_REQUEST)) {
  61                                 mbox->state &= ~OCTEON_MBOX_STATE_IDLE;
  62                                 mbox->state |=
  63                                     OCTEON_MBOX_STATE_REQUEST_RECEIVING;
  64                                 mbox->mbox_req.msg.u64 = msg.u64;
  65                                 mbox->mbox_req.q_no = mbox->q_no;
  66                                 mbox->mbox_req.recv_len = 1;
  67                         } else {
  68                                 if ((mbox->state &
  69                                      OCTEON_MBOX_STATE_RESPONSE_PENDING) &&
  70                                     (msg.s.type == OCTEON_MBOX_RESPONSE)) {
  71                                         mbox->state &=
  72                                             ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
  73                                         mbox->state |=
  74                                             OCTEON_MBOX_STATE_RESPONSE_RECEIVING
  75                                             ;
  76                                         mbox->mbox_resp.msg.u64 = msg.u64;
  77                                         mbox->mbox_resp.q_no = mbox->q_no;
  78                                         mbox->mbox_resp.recv_len = 1;
  79                                 } else {
  80                                         writeq(OCTEON_PFVFERR,
  81                                                mbox->mbox_read_reg);
  82                                         mbox->state |= OCTEON_MBOX_STATE_ERROR;
  83                                         spin_unlock(&mbox->lock);
  84                                         return 1;
  85                                 }
  86                         }
  87                 }
  88         }
  89 
  90         if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
  91                 if (mbox->mbox_req.recv_len < mbox->mbox_req.msg.s.len) {
  92                         ret = 0;
  93                 } else {
  94                         mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVING;
  95                         mbox->state |= OCTEON_MBOX_STATE_REQUEST_RECEIVED;
  96                         ret = 1;
  97                 }
  98         } else {
  99                 if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
 100                         if (mbox->mbox_resp.recv_len <
 101                             mbox->mbox_resp.msg.s.len) {
 102                                 ret = 0;
 103                         } else {
 104                                 mbox->state &=
 105                                     ~OCTEON_MBOX_STATE_RESPONSE_RECEIVING;
 106                                 mbox->state |=
 107                                     OCTEON_MBOX_STATE_RESPONSE_RECEIVED;
 108                                 ret = 1;
 109                         }
 110                 } else {
 111                         WARN_ON(1);
 112                 }
 113         }
 114 
 115         writeq(OCTEON_PFVFACK, mbox->mbox_read_reg);
 116 
 117         spin_unlock(&mbox->lock);
 118 
 119         return ret;
 120 }
 121 
 122 /**
 123  * octeon_mbox_write:
 124  * @oct: Pointer Octeon Device
 125  * @mbox_cmd: Cmd to send to mailbox.
 126  *
 127  * Populates the queue specific mbox structure
 128  * with cmd information.
 129  * Write the cmd to mbox register
 130  */
 131 int octeon_mbox_write(struct octeon_device *oct,
 132                       struct octeon_mbox_cmd *mbox_cmd)
 133 {
 134         struct octeon_mbox *mbox = oct->mbox[mbox_cmd->q_no];
 135         u32 count, i, ret = OCTEON_MBOX_STATUS_SUCCESS;
 136         long timeout = LIO_MBOX_WRITE_WAIT_TIME;
 137         unsigned long flags;
 138 
 139         spin_lock_irqsave(&mbox->lock, flags);
 140 
 141         if ((mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) &&
 142             !(mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED)) {
 143                 spin_unlock_irqrestore(&mbox->lock, flags);
 144                 return OCTEON_MBOX_STATUS_FAILED;
 145         }
 146 
 147         if ((mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) &&
 148             !(mbox->state & OCTEON_MBOX_STATE_IDLE)) {
 149                 spin_unlock_irqrestore(&mbox->lock, flags);
 150                 return OCTEON_MBOX_STATUS_BUSY;
 151         }
 152 
 153         if (mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) {
 154                 memcpy(&mbox->mbox_resp, mbox_cmd,
 155                        sizeof(struct octeon_mbox_cmd));
 156                 mbox->state = OCTEON_MBOX_STATE_RESPONSE_PENDING;
 157         }
 158 
 159         spin_unlock_irqrestore(&mbox->lock, flags);
 160 
 161         count = 0;
 162 
 163         while (readq(mbox->mbox_write_reg) != OCTEON_PFVFSIG) {
 164                 schedule_timeout_uninterruptible(timeout);
 165                 if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
 166                         ret = OCTEON_MBOX_STATUS_FAILED;
 167                         break;
 168                 }
 169         }
 170 
 171         if (ret == OCTEON_MBOX_STATUS_SUCCESS) {
 172                 writeq(mbox_cmd->msg.u64, mbox->mbox_write_reg);
 173                 for (i = 0; i < (u32)(mbox_cmd->msg.s.len - 1); i++) {
 174                         count = 0;
 175                         while (readq(mbox->mbox_write_reg) !=
 176                                OCTEON_PFVFACK) {
 177                                 schedule_timeout_uninterruptible(timeout);
 178                                 if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
 179                                         ret = OCTEON_MBOX_STATUS_FAILED;
 180                                         break;
 181                                 }
 182                         }
 183                         if (ret == OCTEON_MBOX_STATUS_SUCCESS)
 184                                 writeq(mbox_cmd->data[i], mbox->mbox_write_reg);
 185                         else
 186                                 break;
 187                 }
 188         }
 189 
 190         spin_lock_irqsave(&mbox->lock, flags);
 191         if (mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) {
 192                 mbox->state = OCTEON_MBOX_STATE_IDLE;
 193                 writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
 194         } else {
 195                 if ((!mbox_cmd->msg.s.resp_needed) ||
 196                     (ret == OCTEON_MBOX_STATUS_FAILED)) {
 197                         mbox->state &= ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
 198                         if (!(mbox->state &
 199                               (OCTEON_MBOX_STATE_REQUEST_RECEIVING |
 200                                OCTEON_MBOX_STATE_REQUEST_RECEIVED)))
 201                                 mbox->state = OCTEON_MBOX_STATE_IDLE;
 202                 }
 203         }
 204         spin_unlock_irqrestore(&mbox->lock, flags);
 205 
 206         return ret;
 207 }
 208 
 209 static void get_vf_stats(struct octeon_device *oct,
 210                          struct oct_vf_stats *stats)
 211 {
 212         int i;
 213 
 214         for (i = 0; i < oct->num_iqs; i++) {
 215                 if (!oct->instr_queue[i])
 216                         continue;
 217                 stats->tx_packets += oct->instr_queue[i]->stats.tx_done;
 218                 stats->tx_bytes += oct->instr_queue[i]->stats.tx_tot_bytes;
 219         }
 220 
 221         for (i = 0; i < oct->num_oqs; i++) {
 222                 if (!oct->droq[i])
 223                         continue;
 224                 stats->rx_packets += oct->droq[i]->stats.rx_pkts_received;
 225                 stats->rx_bytes += oct->droq[i]->stats.rx_bytes_received;
 226         }
 227 }
 228 
 229 /**
 230  * octeon_mbox_process_cmd:
 231  * @mbox: Pointer mailbox
 232  * @mbox_cmd: Pointer to command received
 233  *
 234  * Process the cmd received in mbox
 235  */
 236 static int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
 237                                    struct octeon_mbox_cmd *mbox_cmd)
 238 {
 239         struct octeon_device *oct = mbox->oct_dev;
 240 
 241         switch (mbox_cmd->msg.s.cmd) {
 242         case OCTEON_VF_ACTIVE:
 243                 dev_dbg(&oct->pci_dev->dev, "got vfactive sending data back\n");
 244                 mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
 245                 mbox_cmd->msg.s.resp_needed = 1;
 246                 mbox_cmd->msg.s.len = 2;
 247                 mbox_cmd->data[0] = 0; /* VF version is in mbox_cmd->data[0] */
 248                 ((struct lio_version *)&mbox_cmd->data[0])->major =
 249                         LIQUIDIO_BASE_MAJOR_VERSION;
 250                 ((struct lio_version *)&mbox_cmd->data[0])->minor =
 251                         LIQUIDIO_BASE_MINOR_VERSION;
 252                 ((struct lio_version *)&mbox_cmd->data[0])->micro =
 253                         LIQUIDIO_BASE_MICRO_VERSION;
 254                 memcpy(mbox_cmd->msg.s.params, (uint8_t *)&oct->pfvf_hsword, 6);
 255                 /* Sending core cofig info to the corresponding active VF.*/
 256                 octeon_mbox_write(oct, mbox_cmd);
 257                 break;
 258 
 259         case OCTEON_VF_FLR_REQUEST:
 260                 dev_info(&oct->pci_dev->dev,
 261                          "got a request for FLR from VF that owns DPI ring %u\n",
 262                          mbox->q_no);
 263                 pcie_flr(oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no]);
 264                 break;
 265 
 266         case OCTEON_PF_CHANGED_VF_MACADDR:
 267                 if (OCTEON_CN23XX_VF(oct))
 268                         octeon_pf_changed_vf_macaddr(oct,
 269                                                      mbox_cmd->msg.s.params);
 270                 break;
 271 
 272         case OCTEON_GET_VF_STATS:
 273                 dev_dbg(&oct->pci_dev->dev, "Got VF stats request. Sending data back\n");
 274                 mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
 275                 mbox_cmd->msg.s.resp_needed = 1;
 276                 mbox_cmd->msg.s.len = 1 +
 277                         sizeof(struct oct_vf_stats) / sizeof(u64);
 278                 get_vf_stats(oct, (struct oct_vf_stats *)mbox_cmd->data);
 279                 octeon_mbox_write(oct, mbox_cmd);
 280                 break;
 281         default:
 282                 break;
 283         }
 284         return 0;
 285 }
 286 
 287 /**
 288  *octeon_mbox_process_message:
 289  *
 290  * Process the received mbox message.
 291  */
 292 int octeon_mbox_process_message(struct octeon_mbox *mbox)
 293 {
 294         struct octeon_mbox_cmd mbox_cmd;
 295         unsigned long flags;
 296 
 297         spin_lock_irqsave(&mbox->lock, flags);
 298 
 299         if (mbox->state & OCTEON_MBOX_STATE_ERROR) {
 300                 if (mbox->state & (OCTEON_MBOX_STATE_RESPONSE_PENDING |
 301                                    OCTEON_MBOX_STATE_RESPONSE_RECEIVING)) {
 302                         memcpy(&mbox_cmd, &mbox->mbox_resp,
 303                                sizeof(struct octeon_mbox_cmd));
 304                         mbox->state = OCTEON_MBOX_STATE_IDLE;
 305                         writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
 306                         spin_unlock_irqrestore(&mbox->lock, flags);
 307                         mbox_cmd.recv_status = 1;
 308                         if (mbox_cmd.fn)
 309                                 mbox_cmd.fn(mbox->oct_dev, &mbox_cmd,
 310                                             mbox_cmd.fn_arg);
 311                         return 0;
 312                 }
 313 
 314                 mbox->state = OCTEON_MBOX_STATE_IDLE;
 315                 writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
 316                 spin_unlock_irqrestore(&mbox->lock, flags);
 317                 return 0;
 318         }
 319 
 320         if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVED) {
 321                 memcpy(&mbox_cmd, &mbox->mbox_resp,
 322                        sizeof(struct octeon_mbox_cmd));
 323                 mbox->state = OCTEON_MBOX_STATE_IDLE;
 324                 writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
 325                 spin_unlock_irqrestore(&mbox->lock, flags);
 326                 mbox_cmd.recv_status = 0;
 327                 if (mbox_cmd.fn)
 328                         mbox_cmd.fn(mbox->oct_dev, &mbox_cmd, mbox_cmd.fn_arg);
 329                 return 0;
 330         }
 331 
 332         if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED) {
 333                 memcpy(&mbox_cmd, &mbox->mbox_req,
 334                        sizeof(struct octeon_mbox_cmd));
 335                 if (!mbox_cmd.msg.s.resp_needed) {
 336                         mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVED;
 337                         if (!(mbox->state &
 338                               OCTEON_MBOX_STATE_RESPONSE_PENDING))
 339                                 mbox->state = OCTEON_MBOX_STATE_IDLE;
 340                         writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
 341                 }
 342 
 343                 spin_unlock_irqrestore(&mbox->lock, flags);
 344                 octeon_mbox_process_cmd(mbox, &mbox_cmd);
 345                 return 0;
 346         }
 347 
 348         spin_unlock_irqrestore(&mbox->lock, flags);
 349         WARN_ON(1);
 350 
 351         return 0;
 352 }
 353 
 354 int octeon_mbox_cancel(struct octeon_device *oct, int q_no)
 355 {
 356         struct octeon_mbox *mbox = oct->mbox[q_no];
 357         struct octeon_mbox_cmd *mbox_cmd;
 358         unsigned long flags = 0;
 359 
 360         spin_lock_irqsave(&mbox->lock, flags);
 361         mbox_cmd = &mbox->mbox_resp;
 362 
 363         if (!(mbox->state & OCTEON_MBOX_STATE_RESPONSE_PENDING)) {
 364                 spin_unlock_irqrestore(&mbox->lock, flags);
 365                 return 1;
 366         }
 367 
 368         mbox->state = OCTEON_MBOX_STATE_IDLE;
 369         memset(mbox_cmd, 0, sizeof(*mbox_cmd));
 370         writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
 371         spin_unlock_irqrestore(&mbox->lock, flags);
 372 
 373         return 0;
 374 }

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