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 = dma_alloc_coherent(&vdev->pdev->dev,
 229                        ring->size_unaligned, &ring->base_addr_unaligned,
 230                        GFP_KERNEL);
 231        if (!ring->descs_unaligned) {
 232                pr_err("Failed to allocate ring (size=%d), aborting\n",
 233                        (int)ring->size);
 234
 235                return -ENOMEM;
 236        }
 237
 238        ring->base_addr = ALIGN(ring->base_addr_unaligned,
 239                ring->base_align);
 240        ring->descs = (u8 *)ring->descs_unaligned +
 241                (ring->base_addr - ring->base_addr_unaligned);
 242
 243        svnic_dev_clear_desc_ring(ring);
 244
 245        ring->desc_avail = ring->desc_count - 1;
 246
 247        return 0;
 248}
 249
 250void svnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
 251{
 252        if (ring->descs) {
 253                dma_free_coherent(&vdev->pdev->dev,
 254                        ring->size_unaligned,
 255                        ring->descs_unaligned,
 256                        ring->base_addr_unaligned);
 257                ring->descs = NULL;
 258        }
 259}
 260
 261static int _svnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
 262        int wait)
 263{
 264        struct devcmd2_controller *dc2c = vdev->devcmd2;
 265        struct devcmd2_result *result = NULL;
 266        unsigned int i;
 267        int delay;
 268        int err;
 269        u32 posted;
 270        u32 fetch_idx;
 271        u32 new_posted;
 272        u8 color;
 273
 274        fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index);
 275        if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone  */
 276                /* Hardware surprise removal: return error */
 277                return -ENODEV;
 278        }
 279
 280        posted = ioread32(&dc2c->wq_ctrl->posted_index);
 281
 282        if (posted == 0xFFFFFFFF) { /* check for hardware gone  */
 283                /* Hardware surprise removal: return error */
 284                return -ENODEV;
 285        }
 286
 287        new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
 288        if (new_posted == fetch_idx) {
 289                pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n",
 290                        pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted);
 291
 292                return -EBUSY;
 293        }
 294
 295        dc2c->cmd_ring[posted].cmd = cmd;
 296        dc2c->cmd_ring[posted].flags = 0;
 297
 298        if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
 299                dc2c->cmd_ring[posted].flags |= DEVCMD2_FNORESULT;
 300
 301        if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
 302                for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
 303                        dc2c->cmd_ring[posted].args[i] = vdev->args[i];
 304        }
 305        /* Adding write memory barrier prevents compiler and/or CPU
 306         * reordering, thus avoiding descriptor posting before
 307         * descriptor is initialized. Otherwise, hardware can read
 308         * stale descriptor fields.
 309         */
 310        wmb();
 311        iowrite32(new_posted, &dc2c->wq_ctrl->posted_index);
 312
 313        if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
 314                return 0;
 315
 316        result = dc2c->result + dc2c->next_result;
 317        color = dc2c->color;
 318
 319        /*
 320         * Increment next_result, after posting the devcmd, irrespective of
 321         * devcmd result, and it should be done only once.
 322         */
 323        dc2c->next_result++;
 324        if (dc2c->next_result == dc2c->result_size) {
 325                dc2c->next_result = 0;
 326                dc2c->color = dc2c->color ? 0 : 1;
 327        }
 328
 329        for (delay = 0; delay < wait; delay++) {
 330                udelay(100);
 331                if (result->color == color) {
 332                        if (result->error) {
 333                                err = (int) result->error;
 334                                if (err != ERR_ECMDUNKNOWN ||
 335                                    cmd != CMD_CAPABILITY)
 336                                        pr_err("Error %d devcmd %d\n",
 337                                                err, _CMD_N(cmd));
 338
 339                                return err;
 340                        }
 341                        if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
 342                                for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
 343                                        vdev->args[i] = result->results[i];
 344                        }
 345
 346                        return 0;
 347                }
 348        }
 349
 350        pr_err("Timed out devcmd %d\n", _CMD_N(cmd));
 351
 352        return -ETIMEDOUT;
 353}
 354
 355static int svnic_dev_init_devcmd2(struct vnic_dev *vdev)
 356{
 357        struct devcmd2_controller *dc2c = NULL;
 358        unsigned int fetch_idx;
 359        int ret;
 360        void __iomem *p;
 361
 362        if (vdev->devcmd2)
 363                return 0;
 364
 365        p = svnic_dev_get_res(vdev, RES_TYPE_DEVCMD2, 0);
 366        if (!p)
 367                return -ENODEV;
 368
 369        dc2c = kzalloc(sizeof(*dc2c), GFP_ATOMIC);
 370        if (!dc2c)
 371                return -ENOMEM;
 372
 373        vdev->devcmd2 = dc2c;
 374
 375        dc2c->color = 1;
 376        dc2c->result_size = DEVCMD2_RING_SIZE;
 377
 378        ret  = vnic_wq_devcmd2_alloc(vdev,
 379                                     &dc2c->wq,
 380                                     DEVCMD2_RING_SIZE,
 381                                     DEVCMD2_DESC_SIZE);
 382        if (ret)
 383                goto err_free_devcmd2;
 384
 385        fetch_idx = ioread32(&dc2c->wq.ctrl->fetch_index);
 386        if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone  */
 387                /* Hardware surprise removal: reset fetch_index */
 388                fetch_idx = 0;
 389        }
 390
 391        /*
 392         * Don't change fetch_index ever and
 393         * set posted_index same as fetch_index
 394         * when setting up the WQ for devcmd2.
 395         */
 396        vnic_wq_init_start(&dc2c->wq, 0, fetch_idx, fetch_idx, 0, 0);
 397        svnic_wq_enable(&dc2c->wq);
 398        ret = svnic_dev_alloc_desc_ring(vdev,
 399                                        &dc2c->results_ring,
 400                                        DEVCMD2_RING_SIZE,
 401                                        DEVCMD2_DESC_SIZE);
 402        if (ret)
 403                goto err_free_wq;
 404
 405        dc2c->result = (struct devcmd2_result *) dc2c->results_ring.descs;
 406        dc2c->cmd_ring = (struct vnic_devcmd2 *) dc2c->wq.ring.descs;
 407        dc2c->wq_ctrl = dc2c->wq.ctrl;
 408        vdev->args[0] = (u64) dc2c->results_ring.base_addr | VNIC_PADDR_TARGET;
 409        vdev->args[1] = DEVCMD2_RING_SIZE;
 410
 411        ret = _svnic_dev_cmd2(vdev, CMD_INITIALIZE_DEVCMD2, VNIC_DVCMD_TMO);
 412        if (ret < 0)
 413                goto err_free_desc_ring;
 414
 415        vdev->devcmd_rtn = &_svnic_dev_cmd2;
 416        pr_info("DEVCMD2 Initialized.\n");
 417
 418        return ret;
 419
 420err_free_desc_ring:
 421        svnic_dev_free_desc_ring(vdev, &dc2c->results_ring);
 422
 423err_free_wq:
 424        svnic_wq_disable(&dc2c->wq);
 425        svnic_wq_free(&dc2c->wq);
 426
 427err_free_devcmd2:
 428        kfree(dc2c);
 429        vdev->devcmd2 = NULL;
 430
 431        return ret;
 432} /* end of svnic_dev_init_devcmd2 */
 433
 434static void vnic_dev_deinit_devcmd2(struct vnic_dev *vdev)
 435{
 436        struct devcmd2_controller *dc2c = vdev->devcmd2;
 437
 438        vdev->devcmd2 = NULL;
 439        vdev->devcmd_rtn = NULL;
 440
 441        svnic_dev_free_desc_ring(vdev, &dc2c->results_ring);
 442        svnic_wq_disable(&dc2c->wq);
 443        svnic_wq_free(&dc2c->wq);
 444        kfree(dc2c);
 445}
 446
 447int svnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
 448        u64 *a0, u64 *a1, int wait)
 449{
 450        int err;
 451
 452        memset(vdev->args, 0, sizeof(vdev->args));
 453        vdev->args[0] = *a0;
 454        vdev->args[1] = *a1;
 455
 456        err = (*vdev->devcmd_rtn)(vdev, cmd, wait);
 457
 458        *a0 = vdev->args[0];
 459        *a1 = vdev->args[1];
 460
 461        return  err;
 462}
 463
 464int svnic_dev_fw_info(struct vnic_dev *vdev,
 465        struct vnic_devcmd_fw_info **fw_info)
 466{
 467        u64 a0, a1 = 0;
 468        int wait = VNIC_DVCMD_TMO;
 469        int err = 0;
 470
 471        if (!vdev->fw_info) {
 472                vdev->fw_info = dma_alloc_coherent(&vdev->pdev->dev,
 473                        sizeof(struct vnic_devcmd_fw_info),
 474                        &vdev->fw_info_pa, GFP_KERNEL);
 475                if (!vdev->fw_info)
 476                        return -ENOMEM;
 477
 478                a0 = vdev->fw_info_pa;
 479
 480                /* only get fw_info once and cache it */
 481                err = svnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait);
 482        }
 483
 484        *fw_info = vdev->fw_info;
 485
 486        return err;
 487}
 488
 489int svnic_dev_spec(struct vnic_dev *vdev, unsigned int offset,
 490        unsigned int size, void *value)
 491{
 492        u64 a0, a1;
 493        int wait = VNIC_DVCMD_TMO;
 494        int err;
 495
 496        a0 = offset;
 497        a1 = size;
 498
 499        err = svnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait);
 500
 501        switch (size) {
 502        case 1:
 503                *(u8 *)value = (u8)a0;
 504                break;
 505        case 2:
 506                *(u16 *)value = (u16)a0;
 507                break;
 508        case 4:
 509                *(u32 *)value = (u32)a0;
 510                break;
 511        case 8:
 512                *(u64 *)value = a0;
 513                break;
 514        default:
 515                BUG();
 516                break;
 517        }
 518
 519        return err;
 520}
 521
 522int svnic_dev_stats_clear(struct vnic_dev *vdev)
 523{
 524        u64 a0 = 0, a1 = 0;
 525        int wait = VNIC_DVCMD_TMO;
 526
 527        return svnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait);
 528}
 529
 530int svnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
 531{
 532        u64 a0, a1;
 533        int wait = VNIC_DVCMD_TMO;
 534
 535        if (!vdev->stats) {
 536                vdev->stats = dma_alloc_coherent(&vdev->pdev->dev,
 537                        sizeof(struct vnic_stats), &vdev->stats_pa, GFP_KERNEL);
 538                if (!vdev->stats)
 539                        return -ENOMEM;
 540        }
 541
 542        *stats = vdev->stats;
 543        a0 = vdev->stats_pa;
 544        a1 = sizeof(struct vnic_stats);
 545
 546        return svnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
 547}
 548
 549int svnic_dev_close(struct vnic_dev *vdev)
 550{
 551        u64 a0 = 0, a1 = 0;
 552        int wait = VNIC_DVCMD_TMO;
 553
 554        return svnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
 555}
 556
 557int svnic_dev_enable_wait(struct vnic_dev *vdev)
 558{
 559        u64 a0 = 0, a1 = 0;
 560        int wait = VNIC_DVCMD_TMO;
 561        int err = 0;
 562
 563        err = svnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
 564        if (err == ERR_ECMDUNKNOWN)
 565                return svnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
 566
 567        return err;
 568}
 569
 570int svnic_dev_disable(struct vnic_dev *vdev)
 571{
 572        u64 a0 = 0, a1 = 0;
 573        int wait = VNIC_DVCMD_TMO;
 574
 575        return svnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait);
 576}
 577
 578int svnic_dev_open(struct vnic_dev *vdev, int arg)
 579{
 580        u64 a0 = (u32)arg, a1 = 0;
 581        int wait = VNIC_DVCMD_TMO;
 582
 583        return svnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait);
 584}
 585
 586int svnic_dev_open_done(struct vnic_dev *vdev, int *done)
 587{
 588        u64 a0 = 0, a1 = 0;
 589        int wait = VNIC_DVCMD_TMO;
 590        int err;
 591
 592        *done = 0;
 593
 594        err = svnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
 595        if (err)
 596                return err;
 597
 598        *done = (a0 == 0);
 599
 600        return 0;
 601}
 602
 603int svnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
 604{
 605        u64 a0, a1;
 606        int wait = VNIC_DVCMD_TMO;
 607
 608        if (!vdev->notify) {
 609                vdev->notify = dma_alloc_coherent(&vdev->pdev->dev,
 610                        sizeof(struct vnic_devcmd_notify),
 611                        &vdev->notify_pa, GFP_KERNEL);
 612                if (!vdev->notify)
 613                        return -ENOMEM;
 614        }
 615
 616        a0 = vdev->notify_pa;
 617        a1 = ((u64)intr << 32) & VNIC_NOTIFY_INTR_MASK;
 618        a1 += sizeof(struct vnic_devcmd_notify);
 619
 620        return svnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
 621}
 622
 623void svnic_dev_notify_unset(struct vnic_dev *vdev)
 624{
 625        u64 a0, a1;
 626        int wait = VNIC_DVCMD_TMO;
 627
 628        a0 = 0;  /* paddr = 0 to unset notify buffer */
 629        a1 = VNIC_NOTIFY_INTR_MASK; /* intr num = -1 to unreg for intr */
 630        a1 += sizeof(struct vnic_devcmd_notify);
 631
 632        svnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
 633}
 634
 635static int vnic_dev_notify_ready(struct vnic_dev *vdev)
 636{
 637        u32 *words;
 638        unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4;
 639        unsigned int i;
 640        u32 csum;
 641
 642        if (!vdev->notify)
 643                return 0;
 644
 645        do {
 646                csum = 0;
 647                memcpy(&vdev->notify_copy, vdev->notify,
 648                        sizeof(struct vnic_devcmd_notify));
 649                words = (u32 *)&vdev->notify_copy;
 650                for (i = 1; i < nwords; i++)
 651                        csum += words[i];
 652        } while (csum != words[0]);
 653
 654        return 1;
 655}
 656
 657int svnic_dev_init(struct vnic_dev *vdev, int arg)
 658{
 659        u64 a0 = (u32)arg, a1 = 0;
 660        int wait = VNIC_DVCMD_TMO;
 661
 662        return svnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
 663}
 664
 665int svnic_dev_link_status(struct vnic_dev *vdev)
 666{
 667        if (vdev->linkstatus)
 668                return *vdev->linkstatus;
 669
 670        if (!vnic_dev_notify_ready(vdev))
 671                return 0;
 672
 673        return vdev->notify_copy.link_state;
 674}
 675
 676u32 svnic_dev_link_down_cnt(struct vnic_dev *vdev)
 677{
 678        if (!vnic_dev_notify_ready(vdev))
 679                return 0;
 680
 681        return vdev->notify_copy.link_down_cnt;
 682}
 683
 684void svnic_dev_set_intr_mode(struct vnic_dev *vdev,
 685        enum vnic_dev_intr_mode intr_mode)
 686{
 687        vdev->intr_mode = intr_mode;
 688}
 689
 690enum vnic_dev_intr_mode svnic_dev_get_intr_mode(struct vnic_dev *vdev)
 691{
 692        return vdev->intr_mode;
 693}
 694
 695void svnic_dev_unregister(struct vnic_dev *vdev)
 696{
 697        if (vdev) {
 698                if (vdev->notify)
 699                        dma_free_coherent(&vdev->pdev->dev,
 700                                sizeof(struct vnic_devcmd_notify),
 701                                vdev->notify,
 702                                vdev->notify_pa);
 703                if (vdev->linkstatus)
 704                        dma_free_coherent(&vdev->pdev->dev,
 705                                sizeof(u32),
 706                                vdev->linkstatus,
 707                                vdev->linkstatus_pa);
 708                if (vdev->stats)
 709                        dma_free_coherent(&vdev->pdev->dev,
 710                                sizeof(struct vnic_stats),
 711                                vdev->stats, vdev->stats_pa);
 712                if (vdev->fw_info)
 713                        dma_free_coherent(&vdev->pdev->dev,
 714                                sizeof(struct vnic_devcmd_fw_info),
 715                                vdev->fw_info, vdev->fw_info_pa);
 716                if (vdev->devcmd2)
 717                        vnic_dev_deinit_devcmd2(vdev);
 718                kfree(vdev);
 719        }
 720}
 721
 722struct vnic_dev *svnic_dev_alloc_discover(struct vnic_dev *vdev,
 723                                          void *priv,
 724                                          struct pci_dev *pdev,
 725                                          struct vnic_dev_bar *bar,
 726                                          unsigned int num_bars)
 727{
 728        if (!vdev) {
 729                vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC);
 730                if (!vdev)
 731                        return NULL;
 732        }
 733
 734        vdev->priv = priv;
 735        vdev->pdev = pdev;
 736
 737        if (vnic_dev_discover_res(vdev, bar, num_bars))
 738                goto err_out;
 739
 740        return vdev;
 741
 742err_out:
 743        svnic_dev_unregister(vdev);
 744
 745        return NULL;
 746} /* end of svnic_dev_alloc_discover */
 747
 748/*
 749 * fallback option is left to keep the interface common for other vnics.
 750 */
 751int svnic_dev_cmd_init(struct vnic_dev *vdev, int fallback)
 752{
 753        int err = -ENODEV;
 754        void __iomem *p;
 755
 756        p = svnic_dev_get_res(vdev, RES_TYPE_DEVCMD2, 0);
 757        if (p)
 758                err = svnic_dev_init_devcmd2(vdev);
 759        else
 760                pr_err("DEVCMD2 resource not found.\n");
 761
 762        return err;
 763} /* end of svnic_dev_cmd_init */
 764
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.