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 0;
 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 0;
 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 0;
 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 0;
 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 0;
 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                /* HW indexes from 1 */
 358                ret = ncsi_remove_filter(nc, NCSI_FILTER_VLAN, cmd->index - 1);
 359        } else {
 360                vlan = ntohs(cmd->vlan);
 361                ret = ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
 362        }
 363
 364        return ret;
 365}
 366
 367static int ncsi_rsp_handler_ev(struct ncsi_request *nr)
 368{
 369        struct ncsi_cmd_ev_pkt *cmd;
 370        struct ncsi_rsp_pkt *rsp;
 371        struct ncsi_dev_priv *ndp = nr->ndp;
 372        struct ncsi_channel *nc;
 373        struct ncsi_channel_mode *ncm;
 374
 375        /* Find the package and channel */
 376        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 377        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 378                                      NULL, &nc);
 379        if (!nc)
 380                return -ENODEV;
 381
 382        /* Check if VLAN mode has been enabled */
 383        ncm = &nc->modes[NCSI_MODE_VLAN];
 384        if (ncm->enable)
 385                return 0;
 386
 387        /* Update to VLAN mode */
 388        cmd = (struct ncsi_cmd_ev_pkt *)skb_network_header(nr->cmd);
 389        ncm->enable = 1;
 390        ncm->data[0] = ntohl(cmd->mode);
 391
 392        return 0;
 393}
 394
 395static int ncsi_rsp_handler_dv(struct ncsi_request *nr)
 396{
 397        struct ncsi_rsp_pkt *rsp;
 398        struct ncsi_dev_priv *ndp = nr->ndp;
 399        struct ncsi_channel *nc;
 400        struct ncsi_channel_mode *ncm;
 401
 402        /* Find the package and channel */
 403        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 404        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 405                                      NULL, &nc);
 406        if (!nc)
 407                return -ENODEV;
 408
 409        /* Check if VLAN mode has been enabled */
 410        ncm = &nc->modes[NCSI_MODE_VLAN];
 411        if (!ncm->enable)
 412                return 0;
 413
 414        /* Update to VLAN mode */
 415        ncm->enable = 0;
 416        return 0;
 417}
 418
 419static int ncsi_rsp_handler_sma(struct ncsi_request *nr)
 420{
 421        struct ncsi_cmd_sma_pkt *cmd;
 422        struct ncsi_rsp_pkt *rsp;
 423        struct ncsi_dev_priv *ndp = nr->ndp;
 424        struct ncsi_channel *nc;
 425        struct ncsi_channel_filter *ncf;
 426        void *bitmap;
 427
 428        /* Find the package and channel */
 429        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 430        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 431                                      NULL, &nc);
 432        if (!nc)
 433                return -ENODEV;
 434
 435        /* According to NCSI spec 1.01, the mixed filter table
 436         * isn't supported yet.
 437         */
 438        cmd = (struct ncsi_cmd_sma_pkt *)skb_network_header(nr->cmd);
 439        switch (cmd->at_e >> 5) {
 440        case 0x0:       /* UC address */
 441                ncf = nc->filters[NCSI_FILTER_UC];
 442                break;
 443        case 0x1:       /* MC address */
 444                ncf = nc->filters[NCSI_FILTER_MC];
 445                break;
 446        default:
 447                return -EINVAL;
 448        }
 449
 450        /* Sanity check on the filter */
 451        if (!ncf)
 452                return -ENOENT;
 453        else if (cmd->index >= ncf->total)
 454                return -ERANGE;
 455
 456        bitmap = &ncf->bitmap;
 457        if (cmd->at_e & 0x1) {
 458                set_bit(cmd->index, bitmap);
 459                memcpy(ncf->data + 6 * cmd->index, cmd->mac, 6);
 460        } else {
 461                clear_bit(cmd->index, bitmap);
 462                memset(ncf->data + 6 * cmd->index, 0, 6);
 463        }
 464
 465        return 0;
 466}
 467
 468static int ncsi_rsp_handler_ebf(struct ncsi_request *nr)
 469{
 470        struct ncsi_cmd_ebf_pkt *cmd;
 471        struct ncsi_rsp_pkt *rsp;
 472        struct ncsi_dev_priv *ndp = nr->ndp;
 473        struct ncsi_channel *nc;
 474        struct ncsi_channel_mode *ncm;
 475
 476        /* Find the package and channel */
 477        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 478        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel, NULL, &nc);
 479        if (!nc)
 480                return -ENODEV;
 481
 482        /* Check if broadcast filter has been enabled */
 483        ncm = &nc->modes[NCSI_MODE_BC];
 484        if (ncm->enable)
 485                return 0;
 486
 487        /* Update to broadcast filter mode */
 488        cmd = (struct ncsi_cmd_ebf_pkt *)skb_network_header(nr->cmd);
 489        ncm->enable = 1;
 490        ncm->data[0] = ntohl(cmd->mode);
 491
 492        return 0;
 493}
 494
 495static int ncsi_rsp_handler_dbf(struct ncsi_request *nr)
 496{
 497        struct ncsi_rsp_pkt *rsp;
 498        struct ncsi_dev_priv *ndp = nr->ndp;
 499        struct ncsi_channel *nc;
 500        struct ncsi_channel_mode *ncm;
 501
 502        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 503        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 504                                      NULL, &nc);
 505        if (!nc)
 506                return -ENODEV;
 507
 508        /* Check if broadcast filter isn't enabled */
 509        ncm = &nc->modes[NCSI_MODE_BC];
 510        if (!ncm->enable)
 511                return 0;
 512
 513        /* Update to broadcast filter mode */
 514        ncm->enable = 0;
 515        ncm->data[0] = 0;
 516
 517        return 0;
 518}
 519
 520static int ncsi_rsp_handler_egmf(struct ncsi_request *nr)
 521{
 522        struct ncsi_cmd_egmf_pkt *cmd;
 523        struct ncsi_rsp_pkt *rsp;
 524        struct ncsi_dev_priv *ndp = nr->ndp;
 525        struct ncsi_channel *nc;
 526        struct ncsi_channel_mode *ncm;
 527
 528        /* Find the channel */
 529        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 530        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 531                                      NULL, &nc);
 532        if (!nc)
 533                return -ENODEV;
 534
 535        /* Check if multicast filter has been enabled */
 536        ncm = &nc->modes[NCSI_MODE_MC];
 537        if (ncm->enable)
 538                return 0;
 539
 540        /* Update to multicast filter mode */
 541        cmd = (struct ncsi_cmd_egmf_pkt *)skb_network_header(nr->cmd);
 542        ncm->enable = 1;
 543        ncm->data[0] = ntohl(cmd->mode);
 544
 545        return 0;
 546}
 547
 548static int ncsi_rsp_handler_dgmf(struct ncsi_request *nr)
 549{
 550        struct ncsi_rsp_pkt *rsp;
 551        struct ncsi_dev_priv *ndp = nr->ndp;
 552        struct ncsi_channel *nc;
 553        struct ncsi_channel_mode *ncm;
 554
 555        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 556        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 557                                      NULL, &nc);
 558        if (!nc)
 559                return -ENODEV;
 560
 561        /* Check if multicast filter has been enabled */
 562        ncm = &nc->modes[NCSI_MODE_MC];
 563        if (!ncm->enable)
 564                return 0;
 565
 566        /* Update to multicast filter mode */
 567        ncm->enable = 0;
 568        ncm->data[0] = 0;
 569
 570        return 0;
 571}
 572
 573static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
 574{
 575        struct ncsi_cmd_snfc_pkt *cmd;
 576        struct ncsi_rsp_pkt *rsp;
 577        struct ncsi_dev_priv *ndp = nr->ndp;
 578        struct ncsi_channel *nc;
 579        struct ncsi_channel_mode *ncm;
 580
 581        /* Find the channel */
 582        rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
 583        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 584                                      NULL, &nc);
 585        if (!nc)
 586                return -ENODEV;
 587
 588        /* Check if flow control has been enabled */
 589        ncm = &nc->modes[NCSI_MODE_FC];
 590        if (ncm->enable)
 591                return 0;
 592
 593        /* Update to flow control mode */
 594        cmd = (struct ncsi_cmd_snfc_pkt *)skb_network_header(nr->cmd);
 595        ncm->enable = 1;
 596        ncm->data[0] = cmd->mode;
 597
 598        return 0;
 599}
 600
 601static int ncsi_rsp_handler_gvi(struct ncsi_request *nr)
 602{
 603        struct ncsi_rsp_gvi_pkt *rsp;
 604        struct ncsi_dev_priv *ndp = nr->ndp;
 605        struct ncsi_channel *nc;
 606        struct ncsi_channel_version *ncv;
 607        int i;
 608
 609        /* Find the channel */
 610        rsp = (struct ncsi_rsp_gvi_pkt *)skb_network_header(nr->rsp);
 611        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 612                                      NULL, &nc);
 613        if (!nc)
 614                return -ENODEV;
 615
 616        /* Update to channel's version info */
 617        ncv = &nc->version;
 618        ncv->version = ntohl(rsp->ncsi_version);
 619        ncv->alpha2 = rsp->alpha2;
 620        memcpy(ncv->fw_name, rsp->fw_name, 12);
 621        ncv->fw_version = ntohl(rsp->fw_version);
 622        for (i = 0; i < ARRAY_SIZE(ncv->pci_ids); i++)
 623                ncv->pci_ids[i] = ntohs(rsp->pci_ids[i]);
 624        ncv->mf_id = ntohl(rsp->mf_id);
 625
 626        return 0;
 627}
 628
 629static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
 630{
 631        struct ncsi_rsp_gc_pkt *rsp;
 632        struct ncsi_dev_priv *ndp = nr->ndp;
 633        struct ncsi_channel *nc;
 634        struct ncsi_channel_filter *ncf;
 635        size_t size, entry_size;
 636        int cnt, i;
 637
 638        /* Find the channel */
 639        rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header(nr->rsp);
 640        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 641                                      NULL, &nc);
 642        if (!nc)
 643                return -ENODEV;
 644
 645        /* Update channel's capabilities */
 646        nc->caps[NCSI_CAP_GENERIC].cap = ntohl(rsp->cap) &
 647                                         NCSI_CAP_GENERIC_MASK;
 648        nc->caps[NCSI_CAP_BC].cap = ntohl(rsp->bc_cap) &
 649                                    NCSI_CAP_BC_MASK;
 650        nc->caps[NCSI_CAP_MC].cap = ntohl(rsp->mc_cap) &
 651                                    NCSI_CAP_MC_MASK;
 652        nc->caps[NCSI_CAP_BUFFER].cap = ntohl(rsp->buf_cap);
 653        nc->caps[NCSI_CAP_AEN].cap = ntohl(rsp->aen_cap) &
 654                                     NCSI_CAP_AEN_MASK;
 655        nc->caps[NCSI_CAP_VLAN].cap = rsp->vlan_mode &
 656                                      NCSI_CAP_VLAN_MASK;
 657
 658        /* Build filters */
 659        for (i = 0; i < NCSI_FILTER_MAX; i++) {
 660                switch (i) {
 661                case NCSI_FILTER_VLAN:
 662                        cnt = rsp->vlan_cnt;
 663                        entry_size = 2;
 664                        break;
 665                case NCSI_FILTER_MIXED:
 666                        cnt = rsp->mixed_cnt;
 667                        entry_size = 6;
 668                        break;
 669                case NCSI_FILTER_MC:
 670                        cnt = rsp->mc_cnt;
 671                        entry_size = 6;
 672                        break;
 673                case NCSI_FILTER_UC:
 674                        cnt = rsp->uc_cnt;
 675                        entry_size = 6;
 676                        break;
 677                default:
 678                        continue;
 679                }
 680
 681                if (!cnt || nc->filters[i])
 682                        continue;
 683
 684                size = sizeof(*ncf) + cnt * entry_size;
 685                ncf = kzalloc(size, GFP_ATOMIC);
 686                if (!ncf) {
 687                        pr_warn("%s: Cannot alloc filter table (%d)\n",
 688                                __func__, i);
 689                        return -ENOMEM;
 690                }
 691
 692                ncf->index = i;
 693                ncf->total = cnt;
 694                if (i == NCSI_FILTER_VLAN) {
 695                        /* Set VLAN filters active so they are cleared in
 696                         * first configuration state
 697                         */
 698                        ncf->bitmap = U64_MAX;
 699                } else {
 700                        ncf->bitmap = 0x0ul;
 701                }
 702                nc->filters[i] = ncf;
 703        }
 704
 705        return 0;
 706}
 707
 708static int ncsi_rsp_handler_gp(struct ncsi_request *nr)
 709{
 710        struct ncsi_rsp_gp_pkt *rsp;
 711        struct ncsi_dev_priv *ndp = nr->ndp;
 712        struct ncsi_channel *nc;
 713        unsigned short enable, vlan;
 714        unsigned char *pdata;
 715        int table, i;
 716
 717        /* Find the channel */
 718        rsp = (struct ncsi_rsp_gp_pkt *)skb_network_header(nr->rsp);
 719        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 720                                      NULL, &nc);
 721        if (!nc)
 722                return -ENODEV;
 723
 724        /* Modes with explicit enabled indications */
 725        if (ntohl(rsp->valid_modes) & 0x1) {    /* BC filter mode */
 726                nc->modes[NCSI_MODE_BC].enable = 1;
 727                nc->modes[NCSI_MODE_BC].data[0] = ntohl(rsp->bc_mode);
 728        }
 729        if (ntohl(rsp->valid_modes) & 0x2)      /* Channel enabled */
 730                nc->modes[NCSI_MODE_ENABLE].enable = 1;
 731        if (ntohl(rsp->valid_modes) & 0x4)      /* Channel Tx enabled */
 732                nc->modes[NCSI_MODE_TX_ENABLE].enable = 1;
 733        if (ntohl(rsp->valid_modes) & 0x8)      /* MC filter mode */
 734                nc->modes[NCSI_MODE_MC].enable = 1;
 735
 736        /* Modes without explicit enabled indications */
 737        nc->modes[NCSI_MODE_LINK].enable = 1;
 738        nc->modes[NCSI_MODE_LINK].data[0] = ntohl(rsp->link_mode);
 739        nc->modes[NCSI_MODE_VLAN].enable = 1;
 740        nc->modes[NCSI_MODE_VLAN].data[0] = rsp->vlan_mode;
 741        nc->modes[NCSI_MODE_FC].enable = 1;
 742        nc->modes[NCSI_MODE_FC].data[0] = rsp->fc_mode;
 743        nc->modes[NCSI_MODE_AEN].enable = 1;
 744        nc->modes[NCSI_MODE_AEN].data[0] = ntohl(rsp->aen_mode);
 745
 746        /* MAC addresses filter table */
 747        pdata = (unsigned char *)rsp + 48;
 748        enable = rsp->mac_enable;
 749        for (i = 0; i < rsp->mac_cnt; i++, pdata += 6) {
 750                if (i >= (nc->filters[NCSI_FILTER_UC]->total +
 751                          nc->filters[NCSI_FILTER_MC]->total))
 752                        table = NCSI_FILTER_MIXED;
 753                else if (i >= nc->filters[NCSI_FILTER_UC]->total)
 754                        table = NCSI_FILTER_MC;
 755                else
 756                        table = NCSI_FILTER_UC;
 757
 758                if (!(enable & (0x1 << i)))
 759                        continue;
 760
 761                if (ncsi_find_filter(nc, table, pdata) >= 0)
 762                        continue;
 763
 764                ncsi_add_filter(nc, table, pdata);
 765        }
 766
 767        /* VLAN filter table */
 768        enable = ntohs(rsp->vlan_enable);
 769        for (i = 0; i < rsp->vlan_cnt; i++, pdata += 2) {
 770                if (!(enable & (0x1 << i)))
 771                        continue;
 772
 773                vlan = ntohs(*(__be16 *)pdata);
 774                if (ncsi_find_filter(nc, NCSI_FILTER_VLAN, &vlan) >= 0)
 775                        continue;
 776
 777                ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
 778        }
 779
 780        return 0;
 781}
 782
 783static int ncsi_rsp_handler_gcps(struct ncsi_request *nr)
 784{
 785        struct ncsi_rsp_gcps_pkt *rsp;
 786        struct ncsi_dev_priv *ndp = nr->ndp;
 787        struct ncsi_channel *nc;
 788        struct ncsi_channel_stats *ncs;
 789
 790        /* Find the channel */
 791        rsp = (struct ncsi_rsp_gcps_pkt *)skb_network_header(nr->rsp);
 792        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 793                                      NULL, &nc);
 794        if (!nc)
 795                return -ENODEV;
 796
 797        /* Update HNC's statistics */
 798        ncs = &nc->stats;
 799        ncs->hnc_cnt_hi         = ntohl(rsp->cnt_hi);
 800        ncs->hnc_cnt_lo         = ntohl(rsp->cnt_lo);
 801        ncs->hnc_rx_bytes       = ntohl(rsp->rx_bytes);
 802        ncs->hnc_tx_bytes       = ntohl(rsp->tx_bytes);
 803        ncs->hnc_rx_uc_pkts     = ntohl(rsp->rx_uc_pkts);
 804        ncs->hnc_rx_mc_pkts     = ntohl(rsp->rx_mc_pkts);
 805        ncs->hnc_rx_bc_pkts     = ntohl(rsp->rx_bc_pkts);
 806        ncs->hnc_tx_uc_pkts     = ntohl(rsp->tx_uc_pkts);
 807        ncs->hnc_tx_mc_pkts     = ntohl(rsp->tx_mc_pkts);
 808        ncs->hnc_tx_bc_pkts     = ntohl(rsp->tx_bc_pkts);
 809        ncs->hnc_fcs_err        = ntohl(rsp->fcs_err);
 810        ncs->hnc_align_err      = ntohl(rsp->align_err);
 811        ncs->hnc_false_carrier  = ntohl(rsp->false_carrier);
 812        ncs->hnc_runt_pkts      = ntohl(rsp->runt_pkts);
 813        ncs->hnc_jabber_pkts    = ntohl(rsp->jabber_pkts);
 814        ncs->hnc_rx_pause_xon   = ntohl(rsp->rx_pause_xon);
 815        ncs->hnc_rx_pause_xoff  = ntohl(rsp->rx_pause_xoff);
 816        ncs->hnc_tx_pause_xon   = ntohl(rsp->tx_pause_xon);
 817        ncs->hnc_tx_pause_xoff  = ntohl(rsp->tx_pause_xoff);
 818        ncs->hnc_tx_s_collision = ntohl(rsp->tx_s_collision);
 819        ncs->hnc_tx_m_collision = ntohl(rsp->tx_m_collision);
 820        ncs->hnc_l_collision    = ntohl(rsp->l_collision);
 821        ncs->hnc_e_collision    = ntohl(rsp->e_collision);
 822        ncs->hnc_rx_ctl_frames  = ntohl(rsp->rx_ctl_frames);
 823        ncs->hnc_rx_64_frames   = ntohl(rsp->rx_64_frames);
 824        ncs->hnc_rx_127_frames  = ntohl(rsp->rx_127_frames);
 825        ncs->hnc_rx_255_frames  = ntohl(rsp->rx_255_frames);
 826        ncs->hnc_rx_511_frames  = ntohl(rsp->rx_511_frames);
 827        ncs->hnc_rx_1023_frames = ntohl(rsp->rx_1023_frames);
 828        ncs->hnc_rx_1522_frames = ntohl(rsp->rx_1522_frames);
 829        ncs->hnc_rx_9022_frames = ntohl(rsp->rx_9022_frames);
 830        ncs->hnc_tx_64_frames   = ntohl(rsp->tx_64_frames);
 831        ncs->hnc_tx_127_frames  = ntohl(rsp->tx_127_frames);
 832        ncs->hnc_tx_255_frames  = ntohl(rsp->tx_255_frames);
 833        ncs->hnc_tx_511_frames  = ntohl(rsp->tx_511_frames);
 834        ncs->hnc_tx_1023_frames = ntohl(rsp->tx_1023_frames);
 835        ncs->hnc_tx_1522_frames = ntohl(rsp->tx_1522_frames);
 836        ncs->hnc_tx_9022_frames = ntohl(rsp->tx_9022_frames);
 837        ncs->hnc_rx_valid_bytes = ntohl(rsp->rx_valid_bytes);
 838        ncs->hnc_rx_runt_pkts   = ntohl(rsp->rx_runt_pkts);
 839        ncs->hnc_rx_jabber_pkts = ntohl(rsp->rx_jabber_pkts);
 840
 841        return 0;
 842}
 843
 844static int ncsi_rsp_handler_gns(struct ncsi_request *nr)
 845{
 846        struct ncsi_rsp_gns_pkt *rsp;
 847        struct ncsi_dev_priv *ndp = nr->ndp;
 848        struct ncsi_channel *nc;
 849        struct ncsi_channel_stats *ncs;
 850
 851        /* Find the channel */
 852        rsp = (struct ncsi_rsp_gns_pkt *)skb_network_header(nr->rsp);
 853        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 854                                      NULL, &nc);
 855        if (!nc)
 856                return -ENODEV;
 857
 858        /* Update HNC's statistics */
 859        ncs = &nc->stats;
 860        ncs->ncsi_rx_cmds       = ntohl(rsp->rx_cmds);
 861        ncs->ncsi_dropped_cmds  = ntohl(rsp->dropped_cmds);
 862        ncs->ncsi_cmd_type_errs = ntohl(rsp->cmd_type_errs);
 863        ncs->ncsi_cmd_csum_errs = ntohl(rsp->cmd_csum_errs);
 864        ncs->ncsi_rx_pkts       = ntohl(rsp->rx_pkts);
 865        ncs->ncsi_tx_pkts       = ntohl(rsp->tx_pkts);
 866        ncs->ncsi_tx_aen_pkts   = ntohl(rsp->tx_aen_pkts);
 867
 868        return 0;
 869}
 870
 871static int ncsi_rsp_handler_gnpts(struct ncsi_request *nr)
 872{
 873        struct ncsi_rsp_gnpts_pkt *rsp;
 874        struct ncsi_dev_priv *ndp = nr->ndp;
 875        struct ncsi_channel *nc;
 876        struct ncsi_channel_stats *ncs;
 877
 878        /* Find the channel */
 879        rsp = (struct ncsi_rsp_gnpts_pkt *)skb_network_header(nr->rsp);
 880        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 881                                      NULL, &nc);
 882        if (!nc)
 883                return -ENODEV;
 884
 885        /* Update HNC's statistics */
 886        ncs = &nc->stats;
 887        ncs->pt_tx_pkts        = ntohl(rsp->tx_pkts);
 888        ncs->pt_tx_dropped     = ntohl(rsp->tx_dropped);
 889        ncs->pt_tx_channel_err = ntohl(rsp->tx_channel_err);
 890        ncs->pt_tx_us_err      = ntohl(rsp->tx_us_err);
 891        ncs->pt_rx_pkts        = ntohl(rsp->rx_pkts);
 892        ncs->pt_rx_dropped     = ntohl(rsp->rx_dropped);
 893        ncs->pt_rx_channel_err = ntohl(rsp->rx_channel_err);
 894        ncs->pt_rx_us_err      = ntohl(rsp->rx_us_err);
 895        ncs->pt_rx_os_err      = ntohl(rsp->rx_os_err);
 896
 897        return 0;
 898}
 899
 900static int ncsi_rsp_handler_gps(struct ncsi_request *nr)
 901{
 902        struct ncsi_rsp_gps_pkt *rsp;
 903        struct ncsi_dev_priv *ndp = nr->ndp;
 904        struct ncsi_package *np;
 905
 906        /* Find the package */
 907        rsp = (struct ncsi_rsp_gps_pkt *)skb_network_header(nr->rsp);
 908        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 909                                      &np, NULL);
 910        if (!np)
 911                return -ENODEV;
 912
 913        return 0;
 914}
 915
 916static int ncsi_rsp_handler_gpuuid(struct ncsi_request *nr)
 917{
 918        struct ncsi_rsp_gpuuid_pkt *rsp;
 919        struct ncsi_dev_priv *ndp = nr->ndp;
 920        struct ncsi_package *np;
 921
 922        /* Find the package */
 923        rsp = (struct ncsi_rsp_gpuuid_pkt *)skb_network_header(nr->rsp);
 924        ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
 925                                      &np, NULL);
 926        if (!np)
 927                return -ENODEV;
 928
 929        memcpy(np->uuid, rsp->uuid, sizeof(rsp->uuid));
 930
 931        return 0;
 932}
 933
 934static struct ncsi_rsp_handler {
 935        unsigned char   type;
 936        int             payload;
 937        int             (*handler)(struct ncsi_request *nr);
 938} ncsi_rsp_handlers[] = {
 939        { NCSI_PKT_RSP_CIS,     4, ncsi_rsp_handler_cis     },
 940        { NCSI_PKT_RSP_SP,      4, ncsi_rsp_handler_sp      },
 941        { NCSI_PKT_RSP_DP,      4, ncsi_rsp_handler_dp      },
 942        { NCSI_PKT_RSP_EC,      4, ncsi_rsp_handler_ec      },
 943        { NCSI_PKT_RSP_DC,      4, ncsi_rsp_handler_dc      },
 944        { NCSI_PKT_RSP_RC,      4, ncsi_rsp_handler_rc      },
 945        { NCSI_PKT_RSP_ECNT,    4, ncsi_rsp_handler_ecnt    },
 946        { NCSI_PKT_RSP_DCNT,    4, ncsi_rsp_handler_dcnt    },
 947        { NCSI_PKT_RSP_AE,      4, ncsi_rsp_handler_ae      },
 948        { NCSI_PKT_RSP_SL,      4, ncsi_rsp_handler_sl      },
 949        { NCSI_PKT_RSP_GLS,    16, ncsi_rsp_handler_gls     },
 950        { NCSI_PKT_RSP_SVF,     4, ncsi_rsp_handler_svf     },
 951        { NCSI_PKT_RSP_EV,      4, ncsi_rsp_handler_ev      },
 952        { NCSI_PKT_RSP_DV,      4, ncsi_rsp_handler_dv      },
 953        { NCSI_PKT_RSP_SMA,     4, ncsi_rsp_handler_sma     },
 954        { NCSI_PKT_RSP_EBF,     4, ncsi_rsp_handler_ebf     },
 955        { NCSI_PKT_RSP_DBF,     4, ncsi_rsp_handler_dbf     },
 956        { NCSI_PKT_RSP_EGMF,    4, ncsi_rsp_handler_egmf    },
 957        { NCSI_PKT_RSP_DGMF,    4, ncsi_rsp_handler_dgmf    },
 958        { NCSI_PKT_RSP_SNFC,    4, ncsi_rsp_handler_snfc    },
 959        { NCSI_PKT_RSP_GVI,    40, ncsi_rsp_handler_gvi     },
 960        { NCSI_PKT_RSP_GC,     32, ncsi_rsp_handler_gc      },
 961        { NCSI_PKT_RSP_GP,     -1, ncsi_rsp_handler_gp      },
 962        { NCSI_PKT_RSP_GCPS,  172, ncsi_rsp_handler_gcps    },
 963        { NCSI_PKT_RSP_GNS,   172, ncsi_rsp_handler_gns     },
 964        { NCSI_PKT_RSP_GNPTS, 172, ncsi_rsp_handler_gnpts   },
 965        { NCSI_PKT_RSP_GPS,     8, ncsi_rsp_handler_gps     },
 966        { NCSI_PKT_RSP_OEM,     0, NULL                     },
 967        { NCSI_PKT_RSP_PLDM,    0, NULL                     },
 968        { NCSI_PKT_RSP_GPUUID, 20, ncsi_rsp_handler_gpuuid  }
 969};
 970
 971int ncsi_rcv_rsp(struct sk_buff *skb, struct net_device *dev,
 972                 struct packet_type *pt, struct net_device *orig_dev)
 973{
 974        struct ncsi_rsp_handler *nrh = NULL;
 975        struct ncsi_dev *nd;
 976        struct ncsi_dev_priv *ndp;
 977        struct ncsi_request *nr;
 978        struct ncsi_pkt_hdr *hdr;
 979        unsigned long flags;
 980        int payload, i, ret;
 981
 982        /* Find the NCSI device */
 983        nd = ncsi_find_dev(dev);
 984        ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
 985        if (!ndp)
 986                return -ENODEV;
 987
 988        /* Check if it is AEN packet */
 989        hdr = (struct ncsi_pkt_hdr *)skb_network_header(skb);
 990        if (hdr->type == NCSI_PKT_AEN)
 991                return ncsi_aen_handler(ndp, skb);
 992
 993        /* Find the handler */
 994        for (i = 0; i < ARRAY_SIZE(ncsi_rsp_handlers); i++) {
 995                if (ncsi_rsp_handlers[i].type == hdr->type) {
 996                        if (ncsi_rsp_handlers[i].handler)
 997                                nrh = &ncsi_rsp_handlers[i];
 998                        else
 999                                nrh = NULL;
1000
1001                        break;
1002                }
1003        }
1004
1005        if (!nrh) {
1006                netdev_err(nd->dev, "Received unrecognized packet (0x%x)\n",
1007                           hdr->type);
1008                return -ENOENT;
1009        }
1010
1011        /* Associate with the request */
1012        spin_lock_irqsave(&ndp->lock, flags);
1013        nr = &ndp->requests[hdr->id];
1014        if (!nr->used) {
1015                spin_unlock_irqrestore(&ndp->lock, flags);
1016                return -ENODEV;
1017        }
1018
1019        nr->rsp = skb;
1020        if (!nr->enabled) {
1021                spin_unlock_irqrestore(&ndp->lock, flags);
1022                ret = -ENOENT;
1023                goto out;
1024        }
1025
1026        /* Validate the packet */
1027        spin_unlock_irqrestore(&ndp->lock, flags);
1028        payload = nrh->payload;
1029        if (payload < 0)
1030                payload = ntohs(hdr->length);
1031        ret = ncsi_validate_rsp_pkt(nr, payload);
1032        if (ret) {
1033                netdev_warn(ndp->ndev.dev,
1034                            "NCSI: 'bad' packet ignored for type 0x%x\n",
1035                            hdr->type);
1036                goto out;
1037        }
1038
1039        /* Process the packet */
1040        ret = nrh->handler(nr);
1041        if (ret)
1042                netdev_err(ndp->ndev.dev,
1043                           "NCSI: Handler for packet type 0x%x returned %d\n",
1044                           hdr->type, ret);
1045out:
1046        ncsi_free_request(nr);
1047        return ret;
1048}
1049