linux/net/ncsi/ncsi-rsp.c
<<
>>
Prefs
   1/*
   2 * Copyright Gavin Shan, IBM Corporation 2016.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <linux/netdevice.h>
  14#include <linux/skbuff.h>
  15
  16#include <net/ncsi.h>
  17#include <net/net_namespace.h>
  18#include <net/sock.h>
  19
  20#include "internal.h"
  21#include "ncsi-pkt.h"
  22
  23static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
  24                                 unsigned short payload)
  25{
  26        struct ncsi_rsp_pkt_hdr *h;
  27        u32 checksum;
  28        __be32 *pchecksum;
  29
  30        /* Check NCSI packet header. We don't need validate
  31         * the packet type, which should have been checked
  32         * before calling this function.
  33         */
  34        h = (struct ncsi_rsp_pkt_hdr *)skb_network_header(nr->rsp);
  35        if (h->common.revision != NCSI_PKT_REVISION)
  36                return -EINVAL;
  37        if (ntohs(h->common.length) != payload)
  38                return -EINVAL;
  39
  40        /* Check on code and reason */
  41        if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED ||
  42            ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR)
  43                return -EINVAL;
  44
  45        /* Validate checksum, which might be zeroes if the
  46         * sender doesn't support checksum according to NCSI
  47         * specification.
  48         */
  49        pchecksum = (__be32 *)((void *)(h + 1) + payload - 4);
  50        if (ntohl(*pchecksum) == 0)
  51                return 0;
  52
  53        checksum = ncsi_calculate_checksum((unsigned char *)h,
  54                                           sizeof(*h) + payload - 4);
  55        if (*pchecksum != htonl(checksum))
  56                return -EINVAL;
  57
  58        return 0;
  59}
  60
  61static int ncsi_rsp_handler_cis(struct ncsi_request *nr)
  62{
  63        struct ncsi_rsp_pkt *rsp;
  64        struct ncsi_dev_priv *ndp = nr->ndp;
  65        struct ncsi_package *np;
  66        struct ncsi_channel *nc;
  67        unsigned char id;
  68
  69        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
  70        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel, &np, &nc);
  71        if (!nc) {
  72                if (ndp->flags & NCSI_DEV_PROBED)
  73                        return -ENXIO;
  74
  75                id = NCSI_CHANNEL_INDEX(rsp->rsp.common.channel);
  76                nc = ncsi_add_channel(np, id);
  77        }
  78
  79        return nc ? 0 : -ENODEV;
  80}
  81
  82static int ncsi_rsp_handler_sp(struct ncsi_request *nr)
  83{
  84        struct ncsi_rsp_pkt *rsp;
  85        struct ncsi_dev_priv *ndp = nr->ndp;
  86        struct ncsi_package *np;
  87        unsigned char id;
  88
  89        /* Add the package if it's not existing. Otherwise,
  90         * to change the state of its child channels.
  91         */
  92        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
  93        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
  94                                      &np, NULL);
  95        if (!np) {
  96                if (ndp->flags & NCSI_DEV_PROBED)
  97                        return -ENXIO;
  98
  99                id = NCSI_PACKAGE_INDEX(rsp->rsp.common.channel);
 100                np = ncsi_add_package(ndp, id);
 101                if (!np)
 102                        return -ENODEV;
 103        }
 104
 105        return 0;
 106}
 107
 108static int ncsi_rsp_handler_dp(struct ncsi_request *nr)
 109{
 110        struct ncsi_rsp_pkt *rsp;
 111        struct ncsi_dev_priv *ndp = nr->ndp;
 112        struct ncsi_package *np;
 113        struct ncsi_channel *nc;
 114        unsigned long flags;
 115
 116        /* Find the package */
 117        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 118        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 119                                      &np, NULL);
 120        if (!np)
 121                return -ENODEV;
 122
 123        /* Change state of all channels attached to the package */
 124        NCSI_FOR_EACH_CHANNEL(np, nc) {
 125                spin_lock_irqsave(&nc->lock, flags);
 126                nc->state = NCSI_CHANNEL_INACTIVE;
 127                spin_unlock_irqrestore(&nc->lock, flags);
 128        }
 129
 130        return 0;
 131}
 132
 133static int ncsi_rsp_handler_ec(struct ncsi_request *nr)
 134{
 135        struct ncsi_rsp_pkt *rsp;
 136        struct ncsi_dev_priv *ndp = nr->ndp;
 137        struct ncsi_channel *nc;
 138        struct ncsi_channel_mode *ncm;
 139
 140        /* Find the package and channel */
 141        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 142        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 143                                      NULL, &nc);
 144        if (!nc)
 145                return -ENODEV;
 146
 147        ncm = &nc->modes[NCSI_MODE_ENABLE];
 148        if (ncm->enable)
 149                return -EBUSY;
 150
 151        ncm->enable = 1;
 152        return 0;
 153}
 154
 155static int ncsi_rsp_handler_dc(struct ncsi_request *nr)
 156{
 157        struct ncsi_rsp_pkt *rsp;
 158        struct ncsi_dev_priv *ndp = nr->ndp;
 159        struct ncsi_channel *nc;
 160        struct ncsi_channel_mode *ncm;
 161        int ret;
 162
 163        ret = ncsi_validate_rsp_pkt(nr, 4);
 164        if (ret)
 165                return ret;
 166
 167        /* Find the package and channel */
 168        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 169        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 170                                      NULL, &nc);
 171        if (!nc)
 172                return -ENODEV;
 173
 174        ncm = &nc->modes[NCSI_MODE_ENABLE];
 175        if (!ncm->enable)
 176                return -EBUSY;
 177
 178        ncm->enable = 0;
 179        return 0;
 180}
 181
 182static int ncsi_rsp_handler_rc(struct ncsi_request *nr)
 183{
 184        struct ncsi_rsp_pkt *rsp;
 185        struct ncsi_dev_priv *ndp = nr->ndp;
 186        struct ncsi_channel *nc;
 187        unsigned long flags;
 188
 189        /* Find the package and channel */
 190        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 191        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 192                                      NULL, &nc);
 193        if (!nc)
 194                return -ENODEV;
 195
 196        /* Update state for the specified channel */
 197        spin_lock_irqsave(&nc->lock, flags);
 198        nc->state = NCSI_CHANNEL_INACTIVE;
 199        spin_unlock_irqrestore(&nc->lock, flags);
 200
 201        return 0;
 202}
 203
 204static int ncsi_rsp_handler_ecnt(struct ncsi_request *nr)
 205{
 206        struct ncsi_rsp_pkt *rsp;
 207        struct ncsi_dev_priv *ndp = nr->ndp;
 208        struct ncsi_channel *nc;
 209        struct ncsi_channel_mode *ncm;
 210
 211        /* Find the package and channel */
 212        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 213        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 214                                      NULL, &nc);
 215        if (!nc)
 216                return -ENODEV;
 217
 218        ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
 219        if (ncm->enable)
 220                return -EBUSY;
 221
 222        ncm->enable = 1;
 223        return 0;
 224}
 225
 226static int ncsi_rsp_handler_dcnt(struct ncsi_request *nr)
 227{
 228        struct ncsi_rsp_pkt *rsp;
 229        struct ncsi_dev_priv *ndp = nr->ndp;
 230        struct ncsi_channel *nc;
 231        struct ncsi_channel_mode *ncm;
 232
 233        /* Find the package and channel */
 234        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 235        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 236                                      NULL, &nc);
 237        if (!nc)
 238                return -ENODEV;
 239
 240        ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
 241        if (!ncm->enable)
 242                return -EBUSY;
 243
 244        ncm->enable = 1;
 245        return 0;
 246}
 247
 248static int ncsi_rsp_handler_ae(struct ncsi_request *nr)
 249{
 250        struct ncsi_cmd_ae_pkt *cmd;
 251        struct ncsi_rsp_pkt *rsp;
 252        struct ncsi_dev_priv *ndp = nr->ndp;
 253        struct ncsi_channel *nc;
 254        struct ncsi_channel_mode *ncm;
 255
 256        /* Find the package and channel */
 257        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 258        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 259                                      NULL, &nc);
 260        if (!nc)
 261                return -ENODEV;
 262
 263        /* Check if the AEN has been enabled */
 264        ncm = &nc->modes[NCSI_MODE_AEN];
 265        if (ncm->enable)
 266                return -EBUSY;
 267
 268        /* Update to AEN configuration */
 269        cmd = (struct ncsi_cmd_ae_pkt *)skb_network_header(nr->cmd);
 270        ncm->enable = 1;
 271        ncm->data[0] = cmd->mc_id;
 272        ncm->data[1] = ntohl(cmd->mode);
 273
 274        return 0;
 275}
 276
 277static int ncsi_rsp_handler_sl(struct ncsi_request *nr)
 278{
 279        struct ncsi_cmd_sl_pkt *cmd;
 280        struct ncsi_rsp_pkt *rsp;
 281        struct ncsi_dev_priv *ndp = nr->ndp;
 282        struct ncsi_channel *nc;
 283        struct ncsi_channel_mode *ncm;
 284
 285        /* Find the package and channel */
 286        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 287        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 288                                      NULL, &nc);
 289        if (!nc)
 290                return -ENODEV;
 291
 292        cmd = (struct ncsi_cmd_sl_pkt *)skb_network_header(nr->cmd);
 293        ncm = &nc->modes[NCSI_MODE_LINK];
 294        ncm->data[0] = ntohl(cmd->mode);
 295        ncm->data[1] = ntohl(cmd->oem_mode);
 296
 297        return 0;
 298}
 299
 300static int ncsi_rsp_handler_gls(struct ncsi_request *nr)
 301{
 302        struct ncsi_rsp_gls_pkt *rsp;
 303        struct ncsi_dev_priv *ndp = nr->ndp;
 304        struct ncsi_channel *nc;
 305        struct ncsi_channel_mode *ncm;
 306        unsigned long flags;
 307
 308        /* Find the package and channel */
 309        rsp = (struct ncsi_rsp_gls_pkt *)skb_network_header(nr->rsp);
 310        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 311                                      NULL, &nc);
 312        if (!nc)
 313                return -ENODEV;
 314
 315        ncm = &nc->modes[NCSI_MODE_LINK];
 316        ncm->data[2] = ntohl(rsp->status);
 317        ncm->data[3] = ntohl(rsp->other);
 318        ncm->data[4] = ntohl(rsp->oem_status);
 319
 320        if (nr->flags & NCSI_REQ_FLAG_EVENT_DRIVEN)
 321                return 0;
 322
 323        /* Reset the channel monitor if it has been enabled */
 324        spin_lock_irqsave(&nc->lock, flags);
 325        nc->monitor.state = NCSI_CHANNEL_MONITOR_START;
 326        spin_unlock_irqrestore(&nc->lock, flags);
 327
 328        return 0;
 329}
 330
 331static int ncsi_rsp_handler_svf(struct ncsi_request *nr)
 332{
 333        struct ncsi_cmd_svf_pkt *cmd;
 334        struct ncsi_rsp_pkt *rsp;
 335        struct ncsi_dev_priv *ndp = nr->ndp;
 336        struct ncsi_channel *nc;
 337        struct ncsi_channel_filter *ncf;
 338        unsigned short vlan;
 339        int ret;
 340
 341        /* Find the package and channel */
 342        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 343        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 344                                      NULL, &nc);
 345        if (!nc)
 346                return -ENODEV;
 347
 348        cmd = (struct ncsi_cmd_svf_pkt *)skb_network_header(nr->cmd);
 349        ncf = nc->filters[NCSI_FILTER_VLAN];
 350        if (!ncf)
 351                return -ENOENT;
 352        if (cmd->index >= ncf->total)
 353                return -ERANGE;
 354
 355        /* Add or remove the VLAN filter */
 356        if (!(cmd->enable & 0x1)) {
 357                ret = ncsi_remove_filter(nc, NCSI_FILTER_VLAN, cmd->index);
 358        } else {
 359                vlan = ntohs(cmd->vlan);
 360                ret = ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
 361        }
 362
 363        return ret;
 364}
 365
 366static int ncsi_rsp_handler_ev(struct ncsi_request *nr)
 367{
 368        struct ncsi_cmd_ev_pkt *cmd;
 369        struct ncsi_rsp_pkt *rsp;
 370        struct ncsi_dev_priv *ndp = nr->ndp;
 371        struct ncsi_channel *nc;
 372        struct ncsi_channel_mode *ncm;
 373
 374        /* Find the package and channel */
 375        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 376        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 377                                      NULL, &nc);
 378        if (!nc)
 379                return -ENODEV;
 380
 381        /* Check if VLAN mode has been enabled */
 382        ncm = &nc->modes[NCSI_MODE_VLAN];
 383        if (ncm->enable)
 384                return -EBUSY;
 385
 386        /* Update to VLAN mode */
 387        cmd = (struct ncsi_cmd_ev_pkt *)skb_network_header(nr->cmd);
 388        ncm->enable = 1;
 389        ncm->data[0] = ntohl(cmd->mode);
 390
 391        return 0;
 392}
 393
 394static int ncsi_rsp_handler_dv(struct ncsi_request *nr)
 395{
 396        struct ncsi_rsp_pkt *rsp;
 397        struct ncsi_dev_priv *ndp = nr->ndp;
 398        struct ncsi_channel *nc;
 399        struct ncsi_channel_mode *ncm;
 400
 401        /* Find the package and channel */
 402        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 403        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 404                                      NULL, &nc);
 405        if (!nc)
 406                return -ENODEV;
 407
 408        /* Check if VLAN mode has been enabled */
 409        ncm = &nc->modes[NCSI_MODE_VLAN];
 410        if (!ncm->enable)
 411                return -EBUSY;
 412
 413        /* Update to VLAN mode */
 414        ncm->enable = 0;
 415        return 0;
 416}
 417
 418static int ncsi_rsp_handler_sma(struct ncsi_request *nr)
 419{
 420        struct ncsi_cmd_sma_pkt *cmd;
 421        struct ncsi_rsp_pkt *rsp;
 422        struct ncsi_dev_priv *ndp = nr->ndp;
 423        struct ncsi_channel *nc;
 424        struct ncsi_channel_filter *ncf;
 425        void *bitmap;
 426
 427        /* Find the package and channel */
 428        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 429        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 430                                      NULL, &nc);
 431        if (!nc)
 432                return -ENODEV;
 433
 434        /* According to NCSI spec 1.01, the mixed filter table
 435         * isn't supported yet.
 436         */
 437        cmd = (struct ncsi_cmd_sma_pkt *)skb_network_header(nr->cmd);
 438        switch (cmd->at_e >> 5) {
 439        case 0x0:       /* UC address */
 440                ncf = nc->filters[NCSI_FILTER_UC];
 441                break;
 442        case 0x1:       /* MC address */
 443                ncf = nc->filters[NCSI_FILTER_MC];
 444                break;
 445        default:
 446                return -EINVAL;
 447        }
 448
 449        /* Sanity check on the filter */
 450        if (!ncf)
 451                return -ENOENT;
 452        else if (cmd->index >= ncf->total)
 453                return -ERANGE;
 454
 455        bitmap = &ncf->bitmap;
 456        if (cmd->at_e & 0x1) {
 457                if (test_and_set_bit(cmd->index, bitmap))
 458                        return -EBUSY;
 459                memcpy(ncf->data + 6 * cmd->index, cmd->mac, 6);
 460        } else {
 461                if (!test_and_clear_bit(cmd->index, bitmap))
 462                        return -EBUSY;
 463
 464                memset(ncf->data + 6 * cmd->index, 0, 6);
 465        }
 466
 467        return 0;
 468}
 469
 470static int ncsi_rsp_handler_ebf(struct ncsi_request *nr)
 471{
 472        struct ncsi_cmd_ebf_pkt *cmd;
 473        struct ncsi_rsp_pkt *rsp;
 474        struct ncsi_dev_priv *ndp = nr->ndp;
 475        struct ncsi_channel *nc;
 476        struct ncsi_channel_mode *ncm;
 477
 478        /* Find the package and channel */
 479        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 480        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel, NULL, &nc);
 481        if (!nc)
 482                return -ENODEV;
 483
 484        /* Check if broadcast filter has been enabled */
 485        ncm = &nc->modes[NCSI_MODE_BC];
 486        if (ncm->enable)
 487                return -EBUSY;
 488
 489        /* Update to broadcast filter mode */
 490        cmd = (struct ncsi_cmd_ebf_pkt *)skb_network_header(nr->cmd);
 491        ncm->enable = 1;
 492        ncm->data[0] = ntohl(cmd->mode);
 493
 494        return 0;
 495}
 496
 497static int ncsi_rsp_handler_dbf(struct ncsi_request *nr)
 498{
 499        struct ncsi_rsp_pkt *rsp;
 500        struct ncsi_dev_priv *ndp = nr->ndp;
 501        struct ncsi_channel *nc;
 502        struct ncsi_channel_mode *ncm;
 503
 504        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 505        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 506                                      NULL, &nc);
 507        if (!nc)
 508                return -ENODEV;
 509
 510        /* Check if broadcast filter isn't enabled */
 511        ncm = &nc->modes[NCSI_MODE_BC];
 512        if (!ncm->enable)
 513                return -EBUSY;
 514
 515        /* Update to broadcast filter mode */
 516        ncm->enable = 0;
 517        ncm->data[0] = 0;
 518
 519        return 0;
 520}
 521
 522static int ncsi_rsp_handler_egmf(struct ncsi_request *nr)
 523{
 524        struct ncsi_cmd_egmf_pkt *cmd;
 525        struct ncsi_rsp_pkt *rsp;
 526        struct ncsi_dev_priv *ndp = nr->ndp;
 527        struct ncsi_channel *nc;
 528        struct ncsi_channel_mode *ncm;
 529
 530        /* Find the channel */
 531        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 532        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 533                                      NULL, &nc);
 534        if (!nc)
 535                return -ENODEV;
 536
 537        /* Check if multicast filter has been enabled */
 538        ncm = &nc->modes[NCSI_MODE_MC];
 539        if (ncm->enable)
 540                return -EBUSY;
 541
 542        /* Update to multicast filter mode */
 543        cmd = (struct ncsi_cmd_egmf_pkt *)skb_network_header(nr->cmd);
 544        ncm->enable = 1;
 545        ncm->data[0] = ntohl(cmd->mode);
 546
 547        return 0;
 548}
 549
 550static int ncsi_rsp_handler_dgmf(struct ncsi_request *nr)
 551{
 552        struct ncsi_rsp_pkt *rsp;
 553        struct ncsi_dev_priv *ndp = nr->ndp;
 554        struct ncsi_channel *nc;
 555        struct ncsi_channel_mode *ncm;
 556
 557        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 558        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 559                                      NULL, &nc);
 560        if (!nc)
 561                return -ENODEV;
 562
 563        /* Check if multicast filter has been enabled */
 564        ncm = &nc->modes[NCSI_MODE_MC];
 565        if (!ncm->enable)
 566                return -EBUSY;
 567
 568        /* Update to multicast filter mode */
 569        ncm->enable = 0;
 570        ncm->data[0] = 0;
 571
 572        return 0;
 573}
 574
 575static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
 576{
 577        struct ncsi_cmd_snfc_pkt *cmd;
 578        struct ncsi_rsp_pkt *rsp;
 579        struct ncsi_dev_priv *ndp = nr->ndp;
 580        struct ncsi_channel *nc;
 581        struct ncsi_channel_mode *ncm;
 582
 583        /* Find the channel */
 584        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 585        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 586                                      NULL, &nc);
 587        if (!nc)
 588                return -ENODEV;
 589
 590        /* Check if flow control has been enabled */
 591        ncm = &nc->modes[NCSI_MODE_FC];
 592        if (ncm->enable)
 593                return -EBUSY;
 594
 595        /* Update to flow control mode */
 596        cmd = (struct ncsi_cmd_snfc_pkt *)skb_network_header(nr->cmd);
 597        ncm->enable = 1;
 598        ncm->data[0] = cmd->mode;
 599
 600        return 0;
 601}
 602
 603static int ncsi_rsp_handler_gvi(struct ncsi_request *nr)
 604{
 605        struct ncsi_rsp_gvi_pkt *rsp;
 606        struct ncsi_dev_priv *ndp = nr->ndp;
 607        struct ncsi_channel *nc;
 608        struct ncsi_channel_version *ncv;
 609        int i;
 610
 611        /* Find the channel */
 612        rsp = (struct ncsi_rsp_gvi_pkt *)skb_network_header(nr->rsp);
 613        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 614                                      NULL, &nc);
 615        if (!nc)
 616                return -ENODEV;
 617
 618        /* Update to channel's version info */
 619        ncv = &nc->version;
 620        ncv->version = ntohl(rsp->ncsi_version);
 621        ncv->alpha2 = rsp->alpha2;
 622        memcpy(ncv->fw_name, rsp->fw_name, 12);
 623        ncv->fw_version = ntohl(rsp->fw_version);
 624        for (i = 0; i < ARRAY_SIZE(ncv->pci_ids); i++)
 625                ncv->pci_ids[i] = ntohs(rsp->pci_ids[i]);
 626        ncv->mf_id = ntohl(rsp->mf_id);
 627
 628        return 0;
 629}
 630
 631static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
 632{
 633        struct ncsi_rsp_gc_pkt *rsp;
 634        struct ncsi_dev_priv *ndp = nr->ndp;
 635        struct ncsi_channel *nc;
 636        struct ncsi_channel_filter *ncf;
 637        size_t size, entry_size;
 638        int cnt, i;
 639
 640        /* Find the channel */
 641        rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header(nr->rsp);
 642        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 643                                      NULL, &nc);
 644        if (!nc)
 645                return -ENODEV;
 646
 647        /* Update channel's capabilities */
 648        nc->caps[NCSI_CAP_GENERIC].cap = ntohl(rsp->cap) &
 649                                         NCSI_CAP_GENERIC_MASK;
 650        nc->caps[NCSI_CAP_BC].cap = ntohl(rsp->bc_cap) &
 651                                    NCSI_CAP_BC_MASK;
 652        nc->caps[NCSI_CAP_MC].cap = ntohl(rsp->mc_cap) &
 653                                    NCSI_CAP_MC_MASK;
 654        nc->caps[NCSI_CAP_BUFFER].cap = ntohl(rsp->buf_cap);
 655        nc->caps[NCSI_CAP_AEN].cap = ntohl(rsp->aen_cap) &
 656                                     NCSI_CAP_AEN_MASK;
 657        nc->caps[NCSI_CAP_VLAN].cap = rsp->vlan_mode &
 658                                      NCSI_CAP_VLAN_MASK;
 659
 660        /* Build filters */
 661        for (i = 0; i < NCSI_FILTER_MAX; i++) {
 662                switch (i) {
 663                case NCSI_FILTER_VLAN:
 664                        cnt = rsp->vlan_cnt;
 665                        entry_size = 2;
 666                        break;
 667                case NCSI_FILTER_MIXED:
 668                        cnt = rsp->mixed_cnt;
 669                        entry_size = 6;
 670                        break;
 671                case NCSI_FILTER_MC:
 672                        cnt = rsp->mc_cnt;
 673                        entry_size = 6;
 674                        break;
 675                case NCSI_FILTER_UC:
 676                        cnt = rsp->uc_cnt;
 677                        entry_size = 6;
 678                        break;
 679                default:
 680                        continue;
 681                }
 682
 683                if (!cnt || nc->filters[i])
 684                        continue;
 685
 686                size = sizeof(*ncf) + cnt * entry_size;
 687                ncf = kzalloc(size, GFP_ATOMIC);
 688                if (!ncf) {
 689                        pr_warn("%s: Cannot alloc filter table (%d)\n",
 690                                __func__, i);
 691                        return -ENOMEM;
 692                }
 693
 694                ncf->index = i;
 695                ncf->total = cnt;
 696                ncf->bitmap = 0x0ul;
 697                nc->filters[i] = ncf;
 698        }
 699
 700        return 0;
 701}
 702
 703static int ncsi_rsp_handler_gp(struct ncsi_request *nr)
 704{
 705        struct ncsi_rsp_gp_pkt *rsp;
 706        struct ncsi_dev_priv *ndp = nr->ndp;
 707        struct ncsi_channel *nc;
 708        unsigned short enable, vlan;
 709        unsigned char *pdata;
 710        int table, i;
 711
 712        /* Find the channel */
 713        rsp = (struct ncsi_rsp_gp_pkt *)skb_network_header(nr->rsp);
 714        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 715                                      NULL, &nc);
 716        if (!nc)
 717                return -ENODEV;
 718
 719        /* Modes with explicit enabled indications */
 720        if (ntohl(rsp->valid_modes) & 0x1) {    /* BC filter mode */
 721                nc->modes[NCSI_MODE_BC].enable = 1;
 722                nc->modes[NCSI_MODE_BC].data[0] = ntohl(rsp->bc_mode);
 723        }
 724        if (ntohl(rsp->valid_modes) & 0x2)      /* Channel enabled */
 725                nc->modes[NCSI_MODE_ENABLE].enable = 1;
 726        if (ntohl(rsp->valid_modes) & 0x4)      /* Channel Tx enabled */
 727                nc->modes[NCSI_MODE_TX_ENABLE].enable = 1;
 728        if (ntohl(rsp->valid_modes) & 0x8)      /* MC filter mode */
 729                nc->modes[NCSI_MODE_MC].enable = 1;
 730
 731        /* Modes without explicit enabled indications */
 732        nc->modes[NCSI_MODE_LINK].enable = 1;
 733        nc->modes[NCSI_MODE_LINK].data[0] = ntohl(rsp->link_mode);
 734        nc->modes[NCSI_MODE_VLAN].enable = 1;
 735        nc->modes[NCSI_MODE_VLAN].data[0] = rsp->vlan_mode;
 736        nc->modes[NCSI_MODE_FC].enable = 1;
 737        nc->modes[NCSI_MODE_FC].data[0] = rsp->fc_mode;
 738        nc->modes[NCSI_MODE_AEN].enable = 1;
 739        nc->modes[NCSI_MODE_AEN].data[0] = ntohl(rsp->aen_mode);
 740
 741        /* MAC addresses filter table */
 742        pdata = (unsigned char *)rsp + 48;
 743        enable = rsp->mac_enable;
 744        for (i = 0; i < rsp->mac_cnt; i++, pdata += 6) {
 745                if (i >= (nc->filters[NCSI_FILTER_UC]->total +
 746                          nc->filters[NCSI_FILTER_MC]->total))
 747                        table = NCSI_FILTER_MIXED;
 748                else if (i >= nc->filters[NCSI_FILTER_UC]->total)
 749                        table = NCSI_FILTER_MC;
 750                else
 751                        table = NCSI_FILTER_UC;
 752
 753                if (!(enable & (0x1 << i)))
 754                        continue;
 755
 756                if (ncsi_find_filter(nc, table, pdata) >= 0)
 757                        continue;
 758
 759                ncsi_add_filter(nc, table, pdata);
 760        }
 761
 762        /* VLAN filter table */
 763        enable = ntohs(rsp->vlan_enable);
 764        for (i = 0; i < rsp->vlan_cnt; i++, pdata += 2) {
 765                if (!(enable & (0x1 << i)))
 766                        continue;
 767
 768                vlan = ntohs(*(__be16 *)pdata);
 769                if (ncsi_find_filter(nc, NCSI_FILTER_VLAN, &vlan) >= 0)
 770                        continue;
 771
 772                ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
 773        }
 774
 775        return 0;
 776}
 777
 778static int ncsi_rsp_handler_gcps(struct ncsi_request *nr)
 779{
 780        struct ncsi_rsp_gcps_pkt *rsp;
 781        struct ncsi_dev_priv *ndp = nr->ndp;
 782        struct ncsi_channel *nc;
 783        struct ncsi_channel_stats *ncs;
 784
 785        /* Find the channel */
 786        rsp = (struct ncsi_rsp_gcps_pkt *)skb_network_header(nr->rsp);
 787        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 788                                      NULL, &nc);
 789        if (!nc)
 790                return -ENODEV;
 791
 792        /* Update HNC's statistics */
 793        ncs = &nc->stats;
 794        ncs->hnc_cnt_hi         = ntohl(rsp->cnt_hi);
 795        ncs->hnc_cnt_lo         = ntohl(rsp->cnt_lo);
 796        ncs->hnc_rx_bytes       = ntohl(rsp->rx_bytes);
 797        ncs->hnc_tx_bytes       = ntohl(rsp->tx_bytes);
 798        ncs->hnc_rx_uc_pkts     = ntohl(rsp->rx_uc_pkts);
 799        ncs->hnc_rx_mc_pkts     = ntohl(rsp->rx_mc_pkts);
 800        ncs->hnc_rx_bc_pkts     = ntohl(rsp->rx_bc_pkts);
 801        ncs->hnc_tx_uc_pkts     = ntohl(rsp->tx_uc_pkts);
 802        ncs->hnc_tx_mc_pkts     = ntohl(rsp->tx_mc_pkts);
 803        ncs->hnc_tx_bc_pkts     = ntohl(rsp->tx_bc_pkts);
 804        ncs->hnc_fcs_err        = ntohl(rsp->fcs_err);
 805        ncs->hnc_align_err      = ntohl(rsp->align_err);
 806        ncs->hnc_false_carrier  = ntohl(rsp->false_carrier);
 807        ncs->hnc_runt_pkts      = ntohl(rsp->runt_pkts);
 808        ncs->hnc_jabber_pkts    = ntohl(rsp->jabber_pkts);
 809        ncs->hnc_rx_pause_xon   = ntohl(rsp->rx_pause_xon);
 810        ncs->hnc_rx_pause_xoff  = ntohl(rsp->rx_pause_xoff);
 811        ncs->hnc_tx_pause_xon   = ntohl(rsp->tx_pause_xon);
 812        ncs->hnc_tx_pause_xoff  = ntohl(rsp->tx_pause_xoff);
 813        ncs->hnc_tx_s_collision = ntohl(rsp->tx_s_collision);
 814        ncs->hnc_tx_m_collision = ntohl(rsp->tx_m_collision);
 815        ncs->hnc_l_collision    = ntohl(rsp->l_collision);
 816        ncs->hnc_e_collision    = ntohl(rsp->e_collision);
 817        ncs->hnc_rx_ctl_frames  = ntohl(rsp->rx_ctl_frames);
 818        ncs->hnc_rx_64_frames   = ntohl(rsp->rx_64_frames);
 819        ncs->hnc_rx_127_frames  = ntohl(rsp->rx_127_frames);
 820        ncs->hnc_rx_255_frames  = ntohl(rsp->rx_255_frames);
 821        ncs->hnc_rx_511_frames  = ntohl(rsp->rx_511_frames);
 822        ncs->hnc_rx_1023_frames = ntohl(rsp->rx_1023_frames);
 823        ncs->hnc_rx_1522_frames = ntohl(rsp->rx_1522_frames);
 824        ncs->hnc_rx_9022_frames = ntohl(rsp->rx_9022_frames);
 825        ncs->hnc_tx_64_frames   = ntohl(rsp->tx_64_frames);
 826        ncs->hnc_tx_127_frames  = ntohl(rsp->tx_127_frames);
 827        ncs->hnc_tx_255_frames  = ntohl(rsp->tx_255_frames);
 828        ncs->hnc_tx_511_frames  = ntohl(rsp->tx_511_frames);
 829        ncs->hnc_tx_1023_frames = ntohl(rsp->tx_1023_frames);
 830        ncs->hnc_tx_1522_frames = ntohl(rsp->tx_1522_frames);
 831        ncs->hnc_tx_9022_frames = ntohl(rsp->tx_9022_frames);
 832        ncs->hnc_rx_valid_bytes = ntohl(rsp->rx_valid_bytes);
 833        ncs->hnc_rx_runt_pkts   = ntohl(rsp->rx_runt_pkts);
 834        ncs->hnc_rx_jabber_pkts = ntohl(rsp->rx_jabber_pkts);
 835
 836        return 0;
 837}
 838
 839static int ncsi_rsp_handler_gns(struct ncsi_request *nr)
 840{
 841        struct ncsi_rsp_gns_pkt *rsp;
 842        struct ncsi_dev_priv *ndp = nr->ndp;
 843        struct ncsi_channel *nc;
 844        struct ncsi_channel_stats *ncs;
 845
 846        /* Find the channel */
 847        rsp = (struct ncsi_rsp_gns_pkt *)skb_network_header(nr->rsp);
 848        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 849                                      NULL, &nc);
 850        if (!nc)
 851                return -ENODEV;
 852
 853        /* Update HNC's statistics */
 854        ncs = &nc->stats;
 855        ncs->ncsi_rx_cmds       = ntohl(rsp->rx_cmds);
 856        ncs->ncsi_dropped_cmds  = ntohl(rsp->dropped_cmds);
 857        ncs->ncsi_cmd_type_errs = ntohl(rsp->cmd_type_errs);
 858        ncs->ncsi_cmd_csum_errs = ntohl(rsp->cmd_csum_errs);
 859        ncs->ncsi_rx_pkts       = ntohl(rsp->rx_pkts);
 860        ncs->ncsi_tx_pkts       = ntohl(rsp->tx_pkts);
 861        ncs->ncsi_tx_aen_pkts   = ntohl(rsp->tx_aen_pkts);
 862
 863        return 0;
 864}
 865
 866static int ncsi_rsp_handler_gnpts(struct ncsi_request *nr)
 867{
 868        struct ncsi_rsp_gnpts_pkt *rsp;
 869        struct ncsi_dev_priv *ndp = nr->ndp;
 870        struct ncsi_channel *nc;
 871        struct ncsi_channel_stats *ncs;
 872
 873        /* Find the channel */
 874        rsp = (struct ncsi_rsp_gnpts_pkt *)skb_network_header(nr->rsp);
 875        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 876                                      NULL, &nc);
 877        if (!nc)
 878                return -ENODEV;
 879
 880        /* Update HNC's statistics */
 881        ncs = &nc->stats;
 882        ncs->pt_tx_pkts        = ntohl(rsp->tx_pkts);
 883        ncs->pt_tx_dropped     = ntohl(rsp->tx_dropped);
 884        ncs->pt_tx_channel_err = ntohl(rsp->tx_channel_err);
 885        ncs->pt_tx_us_err      = ntohl(rsp->tx_us_err);
 886        ncs->pt_rx_pkts        = ntohl(rsp->rx_pkts);
 887        ncs->pt_rx_dropped     = ntohl(rsp->rx_dropped);
 888        ncs->pt_rx_channel_err = ntohl(rsp->rx_channel_err);
 889        ncs->pt_rx_us_err      = ntohl(rsp->rx_us_err);
 890        ncs->pt_rx_os_err      = ntohl(rsp->rx_os_err);
 891
 892        return 0;
 893}
 894
 895static int ncsi_rsp_handler_gps(struct ncsi_request *nr)
 896{
 897        struct ncsi_rsp_gps_pkt *rsp;
 898        struct ncsi_dev_priv *ndp = nr->ndp;
 899        struct ncsi_package *np;
 900
 901        /* Find the package */
 902        rsp = (struct ncsi_rsp_gps_pkt *)skb_network_header(nr->rsp);
 903        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 904                                      &np, NULL);
 905        if (!np)
 906                return -ENODEV;
 907
 908        return 0;
 909}
 910
 911static int ncsi_rsp_handler_gpuuid(struct ncsi_request *nr)
 912{
 913        struct ncsi_rsp_gpuuid_pkt *rsp;
 914        struct ncsi_dev_priv *ndp = nr->ndp;
 915        struct ncsi_package *np;
 916
 917        /* Find the package */
 918        rsp = (struct ncsi_rsp_gpuuid_pkt *)skb_network_header(nr->rsp);
 919        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 920                                      &np, NULL);
 921        if (!np)
 922                return -ENODEV;
 923
 924        memcpy(np->uuid, rsp->uuid, sizeof(rsp->uuid));
 925
 926        return 0;
 927}
 928
 929static struct ncsi_rsp_handler {
 930        unsigned char   type;
 931        int             payload;
 932        int             (*handler)(struct ncsi_request *nr);
 933} ncsi_rsp_handlers[] = {
 934        { NCSI_PKT_RSP_CIS,     4, ncsi_rsp_handler_cis     },
 935        { NCSI_PKT_RSP_SP,      4, ncsi_rsp_handler_sp      },
 936        { NCSI_PKT_RSP_DP,      4, ncsi_rsp_handler_dp      },
 937        { NCSI_PKT_RSP_EC,      4, ncsi_rsp_handler_ec      },
 938        { NCSI_PKT_RSP_DC,      4, ncsi_rsp_handler_dc      },
 939        { NCSI_PKT_RSP_RC,      4, ncsi_rsp_handler_rc      },
 940        { NCSI_PKT_RSP_ECNT,    4, ncsi_rsp_handler_ecnt    },
 941        { NCSI_PKT_RSP_DCNT,    4, ncsi_rsp_handler_dcnt    },
 942        { NCSI_PKT_RSP_AE,      4, ncsi_rsp_handler_ae      },
 943        { NCSI_PKT_RSP_SL,      4, ncsi_rsp_handler_sl      },
 944        { NCSI_PKT_RSP_GLS,    16, ncsi_rsp_handler_gls     },
 945        { NCSI_PKT_RSP_SVF,     4, ncsi_rsp_handler_svf     },
 946        { NCSI_PKT_RSP_EV,      4, ncsi_rsp_handler_ev      },
 947        { NCSI_PKT_RSP_DV,      4, ncsi_rsp_handler_dv      },
 948        { NCSI_PKT_RSP_SMA,     4, ncsi_rsp_handler_sma     },
 949        { NCSI_PKT_RSP_EBF,     4, ncsi_rsp_handler_ebf     },
 950        { NCSI_PKT_RSP_DBF,     4, ncsi_rsp_handler_dbf     },
 951        { NCSI_PKT_RSP_EGMF,    4, ncsi_rsp_handler_egmf    },
 952        { NCSI_PKT_RSP_DGMF,    4, ncsi_rsp_handler_dgmf    },
 953        { NCSI_PKT_RSP_SNFC,    4, ncsi_rsp_handler_snfc    },
 954        { NCSI_PKT_RSP_GVI,    36, ncsi_rsp_handler_gvi     },
 955        { NCSI_PKT_RSP_GC,     32, ncsi_rsp_handler_gc      },
 956        { NCSI_PKT_RSP_GP,     -1, ncsi_rsp_handler_gp      },
 957        { NCSI_PKT_RSP_GCPS,  172, ncsi_rsp_handler_gcps    },
 958        { NCSI_PKT_RSP_GNS,   172, ncsi_rsp_handler_gns     },
 959        { NCSI_PKT_RSP_GNPTS, 172, ncsi_rsp_handler_gnpts   },
 960        { NCSI_PKT_RSP_GPS,     8, ncsi_rsp_handler_gps     },
 961        { NCSI_PKT_RSP_OEM,     0, NULL                     },
 962        { NCSI_PKT_RSP_PLDM,    0, NULL                     },
 963        { NCSI_PKT_RSP_GPUUID, 20, ncsi_rsp_handler_gpuuid  }
 964};
 965
 966int ncsi_rcv_rsp(struct sk_buff *skb, struct net_device *dev,
 967                 struct packet_type *pt, struct net_device *orig_dev)
 968{
 969        struct ncsi_rsp_handler *nrh = NULL;
 970        struct ncsi_dev *nd;
 971        struct ncsi_dev_priv *ndp;
 972        struct ncsi_request *nr;
 973        struct ncsi_pkt_hdr *hdr;
 974        unsigned long flags;
 975        int payload, i, ret;
 976
 977        /* Find the NCSI device */
 978        nd = ncsi_find_dev(dev);
 979        ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
 980        if (!ndp)
 981                return -ENODEV;
 982
 983        /* Check if it is AEN packet */
 984        hdr = (struct ncsi_pkt_hdr *)skb_network_header(skb);
 985        if (hdr->type == NCSI_PKT_AEN)
 986                return ncsi_aen_handler(ndp, skb);
 987
 988        /* Find the handler */
 989        for (i = 0; i < ARRAY_SIZE(ncsi_rsp_handlers); i++) {
 990                if (ncsi_rsp_handlers[i].type == hdr->type) {
 991                        if (ncsi_rsp_handlers[i].handler)
 992                                nrh = &ncsi_rsp_handlers[i];
 993                        else
 994                                nrh = NULL;
 995
 996                        break;
 997                }
 998        }
 999
1000        if (!nrh) {
1001                netdev_err(nd->dev, "Received unrecognized packet (0x%x)\n",
1002                           hdr->type);
1003                return -ENOENT;
1004        }
1005
1006        /* Associate with the request */
1007        spin_lock_irqsave(&ndp->lock, flags);
1008        nr = &ndp->requests[hdr->id];
1009        if (!nr->used) {
1010                spin_unlock_irqrestore(&ndp->lock, flags);
1011                return -ENODEV;
1012        }
1013
1014        nr->rsp = skb;
1015        if (!nr->enabled) {
1016                spin_unlock_irqrestore(&ndp->lock, flags);
1017                ret = -ENOENT;
1018                goto out;
1019        }
1020
1021        /* Validate the packet */
1022        spin_unlock_irqrestore(&ndp->lock, flags);
1023        payload = nrh->payload;
1024        if (payload < 0)
1025                payload = ntohs(hdr->length);
1026        ret = ncsi_validate_rsp_pkt(nr, payload);
1027        if (ret)
1028                goto out;
1029
1030        /* Process the packet */
1031        ret = nrh->handler(nr);
1032out:
1033        ncsi_free_request(nr);
1034        return ret;
1035}
1036