linux/drivers/scsi/snic/vnic_dev.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 Cisco Systems, Inc.  All rights reserved.
   3 *
   4 * This program is free software; you may redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; version 2 of the License.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  15 * SOFTWARE.
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/errno.h>
  20#include <linux/types.h>
  21#include <linux/pci.h>
  22#include <linux/delay.h>
  23#include <linux/if_ether.h>
  24#include <linux/slab.h>
  25#include "vnic_resource.h"
  26#include "vnic_devcmd.h"
  27#include "vnic_dev.h"
  28#include "vnic_stats.h"
  29#include "vnic_wq.h"
  30
  31#define VNIC_DVCMD_TMO  10000   /* Devcmd Timeout value */
  32#define VNIC_NOTIFY_INTR_MASK 0x0000ffff00000000ULL
  33
  34struct devcmd2_controller {
  35        struct vnic_wq_ctrl __iomem *wq_ctrl;
  36        struct vnic_dev_ring results_ring;
  37        struct vnic_wq wq;
  38        struct vnic_devcmd2 *cmd_ring;
  39        struct devcmd2_result *result;
  40        u16 next_result;
  41        u16 result_size;
  42        int color;
  43};
  44
  45struct vnic_res {
  46        void __iomem *vaddr;
  47        unsigned int count;
  48};
  49
  50struct vnic_dev {
  51        void *priv;
  52        struct pci_dev *pdev;
  53        struct vnic_res res[RES_TYPE_MAX];
  54        enum vnic_dev_intr_mode intr_mode;
  55        struct vnic_devcmd __iomem *devcmd;
  56        struct vnic_devcmd_notify *notify;
  57        struct vnic_devcmd_notify notify_copy;
  58        dma_addr_t notify_pa;
  59        u32 *linkstatus;
  60        dma_addr_t linkstatus_pa;
  61        struct vnic_stats *stats;
  62        dma_addr_t stats_pa;
  63        struct vnic_devcmd_fw_info *fw_info;
  64        dma_addr_t fw_info_pa;
  65        u64 args[VNIC_DEVCMD_NARGS];
  66        struct devcmd2_controller *devcmd2;
  67
  68        int (*devcmd_rtn)(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
  69                          int wait);
  70};
  71
  72#define VNIC_MAX_RES_HDR_SIZE \
  73        (sizeof(struct vnic_resource_header) + \
  74        sizeof(struct vnic_resource) * RES_TYPE_MAX)
  75#define VNIC_RES_STRIDE 128
  76
  77void *svnic_dev_priv(struct vnic_dev *vdev)
  78{
  79        return vdev->priv;
  80}
  81
  82static int vnic_dev_discover_res(struct vnic_dev *vdev,
  83        struct vnic_dev_bar *bar, unsigned int num_bars)
  84{
  85        struct vnic_resource_header __iomem *rh;
  86        struct vnic_resource __iomem *r;
  87        u8 type;
  88
  89        if (num_bars == 0)
  90                return -EINVAL;
  91
  92        if (bar->len < VNIC_MAX_RES_HDR_SIZE) {
  93                pr_err("vNIC BAR0 res hdr length error\n");
  94
  95                return -EINVAL;
  96        }
  97
  98        rh = bar->vaddr;
  99        if (!rh) {
 100                pr_err("vNIC BAR0 res hdr not mem-mapped\n");
 101
 102                return -EINVAL;
 103        }
 104
 105        if (ioread32(&rh->magic) != VNIC_RES_MAGIC ||
 106            ioread32(&rh->version) != VNIC_RES_VERSION) {
 107                pr_err("vNIC BAR0 res magic/version error exp (%lx/%lx) curr (%x/%x)\n",
 108                        VNIC_RES_MAGIC, VNIC_RES_VERSION,
 109                        ioread32(&rh->magic), ioread32(&rh->version));
 110
 111                return -EINVAL;
 112        }
 113
 114        r = (struct vnic_resource __iomem *)(rh + 1);
 115
 116        while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
 117
 118                u8 bar_num = ioread8(&r->bar);
 119                u32 bar_offset = ioread32(&r->bar_offset);
 120                u32 count = ioread32(&r->count);
 121                u32 len;
 122
 123                r++;
 124
 125                if (bar_num >= num_bars)
 126                        continue;
 127
 128                if (!bar[bar_num].len || !bar[bar_num].vaddr)
 129                        continue;
 130
 131                switch (type) {
 132                case RES_TYPE_WQ:
 133                case RES_TYPE_RQ:
 134                case RES_TYPE_CQ:
 135                case RES_TYPE_INTR_CTRL:
 136                        /* each count is stride bytes long */
 137                        len = count * VNIC_RES_STRIDE;
 138                        if (len + bar_offset > bar->len) {
 139                                pr_err("vNIC BAR0 resource %d out-of-bounds, offset 0x%x + size 0x%x > bar len 0x%lx\n",
 140                                        type, bar_offset,
 141                                        len,
 142                                        bar->len);
 143
 144                                return -EINVAL;
 145                        }
 146                        break;
 147
 148                case RES_TYPE_INTR_PBA_LEGACY:
 149                case RES_TYPE_DEVCMD:
 150                case RES_TYPE_DEVCMD2:
 151                        len = count;
 152                        break;
 153
 154                default:
 155                        continue;
 156                }
 157
 158                vdev->res[type].count = count;
 159                vdev->res[type].vaddr = (char __iomem *)bar->vaddr + bar_offset;
 160        }
 161
 162        return 0;
 163}
 164
 165unsigned int svnic_dev_get_res_count(struct vnic_dev *vdev,
 166        enum vnic_res_type type)
 167{
 168        return vdev->res[type].count;
 169}
 170
 171void __iomem *svnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
 172        unsigned int index)
 173{
 174        if (!vdev->res[type].vaddr)
 175                return NULL;
 176
 177        switch (type) {
 178        case RES_TYPE_WQ:
 179        case RES_TYPE_RQ:
 180        case RES_TYPE_CQ:
 181        case RES_TYPE_INTR_CTRL:
 182                return (char __iomem *)vdev->res[type].vaddr +
 183                                        index * VNIC_RES_STRIDE;
 184
 185        default:
 186                return (char __iomem *)vdev->res[type].vaddr;
 187        }
 188}
 189
 190unsigned int svnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
 191                                      unsigned int desc_count,
 192                                      unsigned int desc_size)
 193{
 194        /* The base address of the desc rings must be 512 byte aligned.
 195         * Descriptor count is aligned to groups of 32 descriptors.  A
 196         * count of 0 means the maximum 4096 descriptors.  Descriptor
 197         * size is aligned to 16 bytes.
 198         */
 199
 200        unsigned int count_align = 32;
 201        unsigned int desc_align = 16;
 202
 203        ring->base_align = 512;
 204
 205        if (desc_count == 0)
 206                desc_count = 4096;
 207
 208        ring->desc_count = ALIGN(desc_count, count_align);
 209
 210        ring->desc_size = ALIGN(desc_size, desc_align);
 211
 212        ring->size = ring->desc_count * ring->desc_size;
 213        ring->size_unaligned = ring->size + ring->base_align;
 214
 215        return ring->size_unaligned;
 216}
 217
 218void svnic_dev_clear_desc_ring(struct vnic_dev_ring *ring)
 219{
 220        memset(ring->descs, 0, ring->size);
 221}
 222
 223int svnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
 224        unsigned int desc_count, unsigned int desc_size)
 225{
 226        svnic_dev_desc_ring_size(ring, desc_count, desc_size);
 227
 228        ring->descs_unaligned = pci_alloc_consistent(vdev->pdev,
 229                ring->size_unaligned,
 230                &ring->base_addr_unaligned);
 231
 232        if (!ring->descs_unaligned) {
 233                pr_err("Failed to allocate ring (size=%d), aborting\n",
 234                        (int)ring->size);
 235
 236                return -ENOMEM;
 237        }
 238
 239        ring->base_addr = ALIGN(ring->base_addr_unaligned,
 240                ring->base_align);
 241        ring->descs = (u8 *)ring->descs_unaligned +
 242                (ring->base_addr - ring->base_addr_unaligned);
 243
 244        svnic_dev_clear_desc_ring(ring);
 245
 246        ring->desc_avail = ring->desc_count - 1;
 247
 248        return 0;
 249}
 250
 251void svnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
 252{
 253        if (ring->descs) {
 254                pci_free_consistent(vdev->pdev,
 255                        ring->size_unaligned,
 256                        ring->descs_unaligned,
 257                        ring->base_addr_unaligned);
 258                ring->descs = NULL;
 259        }
 260}
 261
 262static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
 263        int wait)
 264{
 265        struct devcmd2_controller *dc2c = vdev->devcmd2;
 266        struct devcmd2_result *result = NULL;
 267        unsigned int i;
 268        int delay;
 269        int err;
 270        u32 posted;
 271        u32 fetch_idx;
 272        u32 new_posted;
 273        u8 color;
 274
 275        fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index);
 276        if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone  */
 277                /* Hardware surprise removal: return error */
 278                return -ENODEV;
 279        }
 280
 281        posted = ioread32(&dc2c->wq_ctrl->posted_index);
 282
 283        if (posted == 0xFFFFFFFF) { /* check for hardware gone  */
 284                /* Hardware surprise removal: return error */
 285                return -ENODEV;
 286        }
 287
 288        new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
 289        if (new_posted == fetch_idx) {
 290                pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n",
 291                        pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted);
 292
 293                return -EBUSY;
 294        }
 295
 296        dc2c->cmd_ring[posted].cmd = cmd;
 297        dc2c->cmd_ring[posted].flags = 0;
 298
 299        if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
 300                dc2c->cmd_ring[posted].flags |= DEVCMD2_FNORESULT;
 301
 302        if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
 303                for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
 304                        dc2c->cmd_ring[posted].args[i] = vdev->args[i];
 305        }
 306        /* Adding write memory barrier prevents compiler and/or CPU
 307         * reordering, thus avoiding descriptor posting before
 308         * descriptor is initialized. Otherwise, hardware can read
 309         * stale descriptor fields.
 310         */
 311        wmb();
 312        iowrite32(new_posted, &dc2c->wq_ctrl->posted_index);
 313
 314        if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
 315                return 0;
 316
 317        result = dc2c->result + dc2c->next_result;
 318        color = dc2c->color;
 319
 320        /*
 321         * Increment next_result, after posting the devcmd, irrespective of
 322         * devcmd result, and it should be done only once.
 323         */
 324        dc2c->next_result++;
 325        if (dc2c->next_result == dc2c->result_size) {
 326                dc2c->next_result = 0;
 327                dc2c->color = dc2c->color ? 0 : 1;
 328        }
 329
 330        for (delay = 0; delay < wait; delay++) {
 331                udelay(100);
 332                if (result->color == color) {
 333                        if (result->error) {
 334                                err = (int) result->error;
 335                                if (err != ERR_ECMDUNKNOWN ||
 336                                    cmd != CMD_CAPABILITY)
 337                                        pr_err("Error %d devcmd %d\n",
 338                                                err, _CMD_N(cmd));
 339
 340                                return err;
 341                        }
 342                        if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
 343                                for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
 344                                        vdev->args[i] = result->results[i];
 345                        }
 346
 347                        return 0;
 348                }
 349        }
 350
 351        pr_err("Timed out devcmd %d\n", _CMD_N(cmd));
 352
 353        return -ETIMEDOUT;
 354}
 355
 356static int svnic_dev_init_devcmd2(struct vnic_dev *vdev)
 357{
 358        struct devcmd2_controller *dc2c = NULL;
 359        unsigned int fetch_idx;
 360        int ret;
 361        void __iomem *p;
 362
 363        if (vdev->devcmd2)
 364                return 0;
 365
 366        p = svnic_dev_get_res(vdev, RES_TYPE_DEVCMD2, 0);
 367        if (!p)
 368                return -ENODEV;
 369
 370        dc2c = kzalloc(sizeof(*dc2c), GFP_ATOMIC);
 371        if (!dc2c)
 372                return -ENOMEM;
 373
 374        vdev->devcmd2 = dc2c;
 375
 376        dc2c->color = 1;
 377        dc2c->result_size = DEVCMD2_RING_SIZE;
 378
 379        ret  = vnic_wq_devcmd2_alloc(vdev,
 380                                     &dc2c->wq,
 381                                     DEVCMD2_RING_SIZE,
 382                                     DEVCMD2_DESC_SIZE);
 383        if (ret)
 384                goto err_free_devcmd2;
 385
 386        fetch_idx = ioread32(&dc2c->wq.ctrl->fetch_index);
 387        if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone  */
 388                /* Hardware surprise removal: reset fetch_index */
 389                fetch_idx = 0;
 390        }
 391
 392        /*
 393         * Don't change fetch_index ever and
 394         * set posted_index same as fetch_index
 395         * when setting up the WQ for devcmd2.
 396         */
 397        vnic_wq_init_start(&dc2c->wq, 0, fetch_idx, fetch_idx, 0, 0);
 398        svnic_wq_enable(&dc2c->wq);
 399        ret = svnic_dev_alloc_desc_ring(vdev,
 400                                        &dc2c->results_ring,
 401                                        DEVCMD2_RING_SIZE,
 402                                        DEVCMD2_DESC_SIZE);
 403        if (ret)
 404                goto err_free_wq;
 405
 406        dc2c->result = (struct devcmd2_result *) dc2c->results_ring.descs;
 407        dc2c->cmd_ring = (struct vnic_devcmd2 *) dc2c->wq.ring.descs;
 408        dc2c->wq_ctrl = dc2c->wq.ctrl;
 409        vdev->args[0] = (u64) dc2c->results_ring.base_addr | VNIC_PADDR_TARGET;
 410        vdev->args[1] = DEVCMD2_RING_SIZE;
 411
 412        ret = _svnic_dev_cmd2(vdev, CMD_INITIALIZE_DEVCMD2, VNIC_DVCMD_TMO);
 413        if (ret < 0)
 414                goto err_free_desc_ring;
 415
 416        vdev->devcmd_rtn = &_svnic_dev_cmd2;
 417        pr_info("DEVCMD2 Initialized.\n");
 418
 419        return ret;
 420
 421err_free_desc_ring:
 422        svnic_dev_free_desc_ring(vdev, &dc2c->results_ring);
 423
 424err_free_wq:
 425        svnic_wq_disable(&dc2c->wq);
 426        svnic_wq_free(&dc2c->wq);
 427
 428err_free_devcmd2:
 429        kfree(dc2c);
 430        vdev->devcmd2 = NULL;
 431
 432        return ret;
 433} /* end of svnic_dev_init_devcmd2 */
 434
 435static void vnic_dev_deinit_devcmd2(struct vnic_dev *vdev)
 436{
 437        struct devcmd2_controller *dc2c = vdev->devcmd2;
 438
 439        vdev->devcmd2 = NULL;
 440        vdev->devcmd_rtn = NULL;
 441
 442        svnic_dev_free_desc_ring(vdev, &dc2c->results_ring);
 443        svnic_wq_disable(&dc2c->wq);
 444        svnic_wq_free(&dc2c->wq);
 445        kfree(dc2c);
 446}
 447
 448int svnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
 449        u64 *a0, u64 *a1, int wait)
 450{
 451        int err;
 452
 453        memset(vdev->args, 0, sizeof(vdev->args));
 454        vdev->args[0] = *a0;
 455        vdev->args[1] = *a1;
 456
 457        err = (*vdev->devcmd_rtn)(vdev, cmd, wait);
 458
 459        *a0 = vdev->args[0];
 460        *a1 = vdev->args[1];
 461
 462        return  err;
 463}
 464
 465int svnic_dev_fw_info(struct vnic_dev *vdev,
 466        struct vnic_devcmd_fw_info **fw_info)
 467{
 468        u64 a0, a1 = 0;
 469        int wait = VNIC_DVCMD_TMO;
 470        int err = 0;
 471
 472        if (!vdev->fw_info) {
 473                vdev->fw_info = pci_alloc_consistent(vdev->pdev,
 474                        sizeof(struct vnic_devcmd_fw_info),
 475                        &vdev->fw_info_pa);
 476                if (!vdev->fw_info)
 477                        return -ENOMEM;
 478
 479                a0 = vdev->fw_info_pa;
 480
 481                /* only get fw_info once and cache it */
 482                err = svnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait);
 483        }
 484
 485        *fw_info = vdev->fw_info;
 486
 487        return err;
 488}
 489
 490int svnic_dev_spec(struct vnic_dev *vdev, unsigned int offset,
 491        unsigned int size, void *value)
 492{
 493        u64 a0, a1;
 494        int wait = VNIC_DVCMD_TMO;
 495        int err;
 496
 497        a0 = offset;
 498        a1 = size;
 499
 500        err = svnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait);
 501
 502        switch (size) {
 503        case 1:
 504                *(u8 *)value = (u8)a0;
 505                break;
 506        case 2:
 507                *(u16 *)value = (u16)a0;
 508                break;
 509        case 4:
 510                *(u32 *)value = (u32)a0;
 511                break;
 512        case 8:
 513                *(u64 *)value = a0;
 514                break;
 515        default:
 516                BUG();
 517                break;
 518        }
 519
 520        return err;
 521}
 522
 523int svnic_dev_stats_clear(struct vnic_dev *vdev)
 524{
 525        u64 a0 = 0, a1 = 0;
 526        int wait = VNIC_DVCMD_TMO;
 527
 528        return svnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait);
 529}
 530
 531int svnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
 532{
 533        u64 a0, a1;
 534        int wait = VNIC_DVCMD_TMO;
 535
 536        if (!vdev->stats) {
 537                vdev->stats = pci_alloc_consistent(vdev->pdev,
 538                        sizeof(struct vnic_stats), &vdev->stats_pa);
 539                if (!vdev->stats)
 540                        return -ENOMEM;
 541        }
 542
 543        *stats = vdev->stats;
 544        a0 = vdev->stats_pa;
 545        a1 = sizeof(struct vnic_stats);
 546
 547        return svnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
 548}
 549
 550int svnic_dev_close(struct vnic_dev *vdev)
 551{
 552        u64 a0 = 0, a1 = 0;
 553        int wait = VNIC_DVCMD_TMO;
 554
 555        return svnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
 556}
 557
 558int svnic_dev_enable_wait(struct vnic_dev *vdev)
 559{
 560        u64 a0 = 0, a1 = 0;
 561        int wait = VNIC_DVCMD_TMO;
 562        int err = 0;
 563
 564        err = svnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
 565        if (err == ERR_ECMDUNKNOWN)
 566                return svnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
 567
 568        return err;
 569}
 570
 571int svnic_dev_disable(struct vnic_dev *vdev)
 572{
 573        u64 a0 = 0, a1 = 0;
 574        int wait = VNIC_DVCMD_TMO;
 575
 576        return svnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait);
 577}
 578
 579int svnic_dev_open(struct vnic_dev *vdev, int arg)
 580{
 581        u64 a0 = (u32)arg, a1 = 0;
 582        int wait = VNIC_DVCMD_TMO;
 583
 584        return svnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait);
 585}
 586
 587int svnic_dev_open_done(struct vnic_dev *vdev, int *done)
 588{
 589        u64 a0 = 0, a1 = 0;
 590        int wait = VNIC_DVCMD_TMO;
 591        int err;
 592
 593        *done = 0;
 594
 595        err = svnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
 596        if (err)
 597                return err;
 598
 599        *done = (a0 == 0);
 600
 601        return 0;
 602}
 603
 604int svnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
 605{
 606        u64 a0, a1;
 607        int wait = VNIC_DVCMD_TMO;
 608
 609        if (!vdev->notify) {
 610                vdev->notify = pci_alloc_consistent(vdev->pdev,
 611                        sizeof(struct vnic_devcmd_notify),
 612                        &vdev->notify_pa);
 613                if (!vdev->notify)
 614                        return -ENOMEM;
 615        }
 616
 617        a0 = vdev->notify_pa;
 618        a1 = ((u64)intr << 32) & VNIC_NOTIFY_INTR_MASK;
 619        a1 += sizeof(struct vnic_devcmd_notify);
 620
 621        return svnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
 622}
 623
 624void svnic_dev_notify_unset(struct vnic_dev *vdev)
 625{
 626        u64 a0, a1;
 627        int wait = VNIC_DVCMD_TMO;
 628
 629        a0 = 0;  /* paddr = 0 to unset notify buffer */
 630        a1 = VNIC_NOTIFY_INTR_MASK; /* intr num = -1 to unreg for intr */
 631        a1 += sizeof(struct vnic_devcmd_notify);
 632
 633        svnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
 634}
 635
 636static int vnic_dev_notify_ready(struct vnic_dev *vdev)
 637{
 638        u32 *words;
 639        unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4;
 640        unsigned int i;
 641        u32 csum;
 642
 643        if (!vdev->notify)
 644                return 0;
 645
 646        do {
 647                csum = 0;
 648                memcpy(&vdev->notify_copy, vdev->notify,
 649                        sizeof(struct vnic_devcmd_notify));
 650                words = (u32 *)&vdev->notify_copy;
 651                for (i = 1; i < nwords; i++)
 652                        csum += words[i];
 653        } while (csum != words[0]);
 654
 655        return 1;
 656}
 657
 658int svnic_dev_init(struct vnic_dev *vdev, int arg)
 659{
 660        u64 a0 = (u32)arg, a1 = 0;
 661        int wait = VNIC_DVCMD_TMO;
 662
 663        return svnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
 664}
 665
 666int svnic_dev_link_status(struct vnic_dev *vdev)
 667{
 668        if (vdev->linkstatus)
 669                return *vdev->linkstatus;
 670
 671        if (!vnic_dev_notify_ready(vdev))
 672                return 0;
 673
 674        return vdev->notify_copy.link_state;
 675}
 676
 677u32 svnic_dev_link_down_cnt(struct vnic_dev *vdev)
 678{
 679        if (!vnic_dev_notify_ready(vdev))
 680                return 0;
 681
 682        return vdev->notify_copy.link_down_cnt;
 683}
 684
 685void svnic_dev_set_intr_mode(struct vnic_dev *vdev,
 686        enum vnic_dev_intr_mode intr_mode)
 687{
 688        vdev->intr_mode = intr_mode;
 689}
 690
 691enum vnic_dev_intr_mode svnic_dev_get_intr_mode(struct vnic_dev *vdev)
 692{
 693        return vdev->intr_mode;
 694}
 695
 696void svnic_dev_unregister(struct vnic_dev *vdev)
 697{
 698        if (vdev) {
 699                if (vdev->notify)
 700                        pci_free_consistent(vdev->pdev,
 701                                sizeof(struct vnic_devcmd_notify),
 702                                vdev->notify,
 703                                vdev->notify_pa);
 704                if (vdev->linkstatus)
 705                        pci_free_consistent(vdev->pdev,
 706                                sizeof(u32),
 707                                vdev->linkstatus,
 708                                vdev->linkstatus_pa);
 709                if (vdev->stats)
 710                        pci_free_consistent(vdev->pdev,
 711                                sizeof(struct vnic_stats),
 712                                vdev->stats, vdev->stats_pa);
 713                if (vdev->fw_info)
 714                        pci_free_consistent(vdev->pdev,
 715                                sizeof(struct vnic_devcmd_fw_info),
 716                                vdev->fw_info, vdev->fw_info_pa);
 717                if (vdev->devcmd2)
 718                        vnic_dev_deinit_devcmd2(vdev);
 719                kfree(vdev);
 720        }
 721}
 722
 723struct vnic_dev *svnic_dev_alloc_discover(struct vnic_dev *vdev,
 724                                          void *priv,
 725                                          struct pci_dev *pdev,
 726                                          struct vnic_dev_bar *bar,
 727                                          unsigned int num_bars)
 728{
 729        if (!vdev) {
 730                vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC);
 731                if (!vdev)
 732                        return NULL;
 733        }
 734
 735        vdev->priv = priv;
 736        vdev->pdev = pdev;
 737
 738        if (vnic_dev_discover_res(vdev, bar, num_bars))
 739                goto err_out;
 740
 741        return vdev;
 742
 743err_out:
 744        svnic_dev_unregister(vdev);
 745
 746        return NULL;
 747} /* end of svnic_dev_alloc_discover */
 748
 749/*
 750 * fallback option is left to keep the interface common for other vnics.
 751 */
 752int svnic_dev_cmd_init(struct vnic_dev *vdev, int fallback)
 753{
 754        int err = -ENODEV;
 755        void __iomem *p;
 756
 757        p = svnic_dev_get_res(vdev, RES_TYPE_DEVCMD2, 0);
 758        if (p)
 759                err = svnic_dev_init_devcmd2(vdev);
 760        else
 761                pr_err("DEVCMD2 resource not found.\n");
 762
 763        return err;
 764} /* end of svnic_dev_cmd_init */
 765