linux/drivers/net/ethernet/huawei/hinic/hinic_devlink.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Huawei HiNIC PCI Express Linux driver
   3 * Copyright(c) 2017 Huawei Technologies Co., Ltd
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12 * for more details.
  13 *
  14 */
  15#include <linux/netlink.h>
  16#include <net/devlink.h>
  17#include <linux/firmware.h>
  18
  19#include "hinic_port.h"
  20#include "hinic_devlink.h"
  21#include "hinic_hw_dev.h"
  22
  23static bool check_image_valid(struct hinic_devlink_priv *priv, const u8 *buf,
  24                              u32 image_size, struct host_image_st *host_image)
  25{
  26        struct fw_image_st *fw_image = NULL;
  27        u32 len = 0;
  28        u32 i;
  29
  30        fw_image = (struct fw_image_st *)buf;
  31
  32        if (fw_image->fw_magic != HINIC_MAGIC_NUM) {
  33                dev_err(&priv->hwdev->hwif->pdev->dev, "Wrong fw_magic read from file, fw_magic: 0x%x\n",
  34                        fw_image->fw_magic);
  35                return false;
  36        }
  37
  38        if (fw_image->fw_info.fw_section_cnt > MAX_FW_TYPE_NUM) {
  39                dev_err(&priv->hwdev->hwif->pdev->dev, "Wrong fw_type_num read from file, fw_type_num: 0x%x\n",
  40                        fw_image->fw_info.fw_section_cnt);
  41                return false;
  42        }
  43
  44        for (i = 0; i < fw_image->fw_info.fw_section_cnt; i++) {
  45                len += fw_image->fw_section_info[i].fw_section_len;
  46                memcpy(&host_image->image_section_info[i],
  47                       &fw_image->fw_section_info[i],
  48                       sizeof(struct fw_section_info_st));
  49        }
  50
  51        if (len != fw_image->fw_len ||
  52            (fw_image->fw_len + UPDATEFW_IMAGE_HEAD_SIZE) != image_size) {
  53                dev_err(&priv->hwdev->hwif->pdev->dev, "Wrong data size read from file\n");
  54                return false;
  55        }
  56
  57        host_image->image_info.up_total_len = fw_image->fw_len;
  58        host_image->image_info.fw_version = fw_image->fw_version;
  59        host_image->section_type_num = fw_image->fw_info.fw_section_cnt;
  60        host_image->device_id = fw_image->device_id;
  61
  62        return true;
  63}
  64
  65static bool check_image_integrity(struct hinic_devlink_priv *priv,
  66                                  struct host_image_st *host_image,
  67                                  u32 update_type)
  68{
  69        u32 collect_section_type = 0;
  70        u32 i, type;
  71
  72        for (i = 0; i < host_image->section_type_num; i++) {
  73                type = host_image->image_section_info[i].fw_section_type;
  74                if (collect_section_type & (1U << type)) {
  75                        dev_err(&priv->hwdev->hwif->pdev->dev, "Duplicate section type: %u\n",
  76                                type);
  77                        return false;
  78                }
  79                collect_section_type |= (1U << type);
  80        }
  81
  82        if (update_type == FW_UPDATE_COLD &&
  83            (((collect_section_type & _IMAGE_COLD_SUB_MODULES_MUST_IN) ==
  84               _IMAGE_COLD_SUB_MODULES_MUST_IN) ||
  85              collect_section_type == _IMAGE_CFG_SUB_MODULES_MUST_IN))
  86                return true;
  87
  88        if (update_type == FW_UPDATE_HOT &&
  89            (collect_section_type & _IMAGE_HOT_SUB_MODULES_MUST_IN) ==
  90            _IMAGE_HOT_SUB_MODULES_MUST_IN)
  91                return true;
  92
  93        if (update_type == FW_UPDATE_COLD)
  94                dev_err(&priv->hwdev->hwif->pdev->dev, "Check file integrity failed, valid: 0x%x or 0x%lx, current: 0x%x\n",
  95                        _IMAGE_COLD_SUB_MODULES_MUST_IN,
  96                        _IMAGE_CFG_SUB_MODULES_MUST_IN, collect_section_type);
  97        else
  98                dev_err(&priv->hwdev->hwif->pdev->dev, "Check file integrity failed, valid:0x%x, current: 0x%x\n",
  99                        _IMAGE_HOT_SUB_MODULES_MUST_IN, collect_section_type);
 100
 101        return false;
 102}
 103
 104static int check_image_device_type(struct hinic_devlink_priv *priv,
 105                                   u32 image_device_type)
 106{
 107        struct hinic_comm_board_info board_info = {0};
 108
 109        if (hinic_get_board_info(priv->hwdev, &board_info)) {
 110                dev_err(&priv->hwdev->hwif->pdev->dev, "Get board info failed\n");
 111                return false;
 112        }
 113
 114        if (image_device_type == board_info.info.board_type)
 115                return true;
 116
 117        dev_err(&priv->hwdev->hwif->pdev->dev, "The device type of upgrade file doesn't match the device type of current firmware, please check the upgrade file\n");
 118        dev_err(&priv->hwdev->hwif->pdev->dev, "The image device type: 0x%x, firmware device type: 0x%x\n",
 119                image_device_type, board_info.info.board_type);
 120
 121        return false;
 122}
 123
 124static int hinic_flash_fw(struct hinic_devlink_priv *priv, const u8 *data,
 125                          struct host_image_st *host_image)
 126{
 127        u32 section_remain_send_len, send_fragment_len, send_pos, up_total_len;
 128        struct hinic_cmd_update_fw *fw_update_msg = NULL;
 129        u32 section_type, section_crc, section_version;
 130        u32 i, len, section_len, section_offset;
 131        u16 out_size = sizeof(*fw_update_msg);
 132        int total_len_flag = 0;
 133        int err;
 134
 135        fw_update_msg = kzalloc(sizeof(*fw_update_msg), GFP_KERNEL);
 136        if (!fw_update_msg)
 137                return -ENOMEM;
 138
 139        up_total_len = host_image->image_info.up_total_len;
 140
 141        for (i = 0; i < host_image->section_type_num; i++) {
 142                len = host_image->image_section_info[i].fw_section_len;
 143                if (host_image->image_section_info[i].fw_section_type ==
 144                    UP_FW_UPDATE_BOOT) {
 145                        up_total_len = up_total_len - len;
 146                        break;
 147                }
 148        }
 149
 150        for (i = 0; i < host_image->section_type_num; i++) {
 151                section_len =
 152                        host_image->image_section_info[i].fw_section_len;
 153                section_offset =
 154                        host_image->image_section_info[i].fw_section_offset;
 155                section_remain_send_len = section_len;
 156                section_type =
 157                        host_image->image_section_info[i].fw_section_type;
 158                section_crc = host_image->image_section_info[i].fw_section_crc;
 159                section_version =
 160                        host_image->image_section_info[i].fw_section_version;
 161
 162                if (section_type == UP_FW_UPDATE_BOOT)
 163                        continue;
 164
 165                send_fragment_len = 0;
 166                send_pos = 0;
 167
 168                while (section_remain_send_len > 0) {
 169                        if (!total_len_flag) {
 170                                fw_update_msg->total_len = up_total_len;
 171                                total_len_flag = 1;
 172                        } else {
 173                                fw_update_msg->total_len = 0;
 174                        }
 175
 176                        memset(fw_update_msg->data, 0, MAX_FW_FRAGMENT_LEN);
 177
 178                        fw_update_msg->ctl_info.SF =
 179                                (section_remain_send_len == section_len) ?
 180                                true : false;
 181                        fw_update_msg->section_info.FW_section_CRC = section_crc;
 182                        fw_update_msg->fw_section_version = section_version;
 183                        fw_update_msg->ctl_info.flag = UP_TYPE_A;
 184
 185                        if (section_type <= UP_FW_UPDATE_UP_DATA_B) {
 186                                fw_update_msg->section_info.FW_section_type =
 187                                        (section_type % 2) ?
 188                                        UP_FW_UPDATE_UP_DATA :
 189                                        UP_FW_UPDATE_UP_TEXT;
 190
 191                                fw_update_msg->ctl_info.flag = UP_TYPE_B;
 192                                if (section_type <= UP_FW_UPDATE_UP_DATA_A)
 193                                        fw_update_msg->ctl_info.flag = UP_TYPE_A;
 194                        } else {
 195                                fw_update_msg->section_info.FW_section_type =
 196                                        section_type - 0x2;
 197                        }
 198
 199                        fw_update_msg->setion_total_len = section_len;
 200                        fw_update_msg->section_offset = send_pos;
 201
 202                        if (section_remain_send_len <= MAX_FW_FRAGMENT_LEN) {
 203                                fw_update_msg->ctl_info.SL = true;
 204                                fw_update_msg->ctl_info.fragment_len =
 205                                        section_remain_send_len;
 206                                send_fragment_len += section_remain_send_len;
 207                        } else {
 208                                fw_update_msg->ctl_info.SL = false;
 209                                fw_update_msg->ctl_info.fragment_len =
 210                                        MAX_FW_FRAGMENT_LEN;
 211                                send_fragment_len += MAX_FW_FRAGMENT_LEN;
 212                        }
 213
 214                        memcpy(fw_update_msg->data,
 215                               data + UPDATEFW_IMAGE_HEAD_SIZE +
 216                               section_offset + send_pos,
 217                               fw_update_msg->ctl_info.fragment_len);
 218
 219                        err = hinic_port_msg_cmd(priv->hwdev,
 220                                                 HINIC_PORT_CMD_UPDATE_FW,
 221                                                 fw_update_msg,
 222                                                 sizeof(*fw_update_msg),
 223                                                 fw_update_msg, &out_size);
 224                        if (err || !out_size || fw_update_msg->status) {
 225                                dev_err(&priv->hwdev->hwif->pdev->dev, "Failed to update firmware, err: %d, status: 0x%x, out size: 0x%x\n",
 226                                        err, fw_update_msg->status, out_size);
 227                                err = fw_update_msg->status ?
 228                                        fw_update_msg->status : -EIO;
 229                                kfree(fw_update_msg);
 230                                return err;
 231                        }
 232
 233                        send_pos = send_fragment_len;
 234                        section_remain_send_len = section_len -
 235                                                  send_fragment_len;
 236                }
 237        }
 238
 239        kfree(fw_update_msg);
 240
 241        return 0;
 242}
 243
 244static int hinic_firmware_update(struct hinic_devlink_priv *priv,
 245                                 const struct firmware *fw,
 246                                 struct netlink_ext_ack *extack)
 247{
 248        struct host_image_st host_image;
 249        int err;
 250
 251        memset(&host_image, 0, sizeof(struct host_image_st));
 252
 253        if (!check_image_valid(priv, fw->data, fw->size, &host_image) ||
 254            !check_image_integrity(priv, &host_image, FW_UPDATE_COLD) ||
 255            !check_image_device_type(priv, host_image.device_id)) {
 256                NL_SET_ERR_MSG_MOD(extack, "Check image failed");
 257                return -EINVAL;
 258        }
 259
 260        dev_info(&priv->hwdev->hwif->pdev->dev, "Flash firmware begin\n");
 261
 262        err = hinic_flash_fw(priv, fw->data, &host_image);
 263        if (err) {
 264                if (err == HINIC_FW_DISMATCH_ERROR) {
 265                        dev_err(&priv->hwdev->hwif->pdev->dev, "Firmware image doesn't match this card, please use newer image, err: %d\n",
 266                                err);
 267                        NL_SET_ERR_MSG_MOD(extack,
 268                                           "Firmware image doesn't match this card, please use newer image");
 269                } else {
 270                        dev_err(&priv->hwdev->hwif->pdev->dev, "Send firmware image data failed, err: %d\n",
 271                                err);
 272                        NL_SET_ERR_MSG_MOD(extack, "Send firmware image data failed");
 273                }
 274
 275                return err;
 276        }
 277
 278        dev_info(&priv->hwdev->hwif->pdev->dev, "Flash firmware end\n");
 279
 280        return 0;
 281}
 282
 283static int hinic_devlink_flash_update(struct devlink *devlink,
 284                                      struct devlink_flash_update_params *params,
 285                                      struct netlink_ext_ack *extack)
 286{
 287        struct hinic_devlink_priv *priv = devlink_priv(devlink);
 288
 289        return hinic_firmware_update(priv, params->fw, extack);
 290}
 291
 292static const struct devlink_ops hinic_devlink_ops = {
 293        .flash_update = hinic_devlink_flash_update,
 294};
 295
 296struct devlink *hinic_devlink_alloc(void)
 297{
 298        return devlink_alloc(&hinic_devlink_ops, sizeof(struct hinic_dev));
 299}
 300
 301void hinic_devlink_free(struct devlink *devlink)
 302{
 303        devlink_free(devlink);
 304}
 305
 306int hinic_devlink_register(struct hinic_devlink_priv *priv, struct device *dev)
 307{
 308        struct devlink *devlink = priv_to_devlink(priv);
 309
 310        return devlink_register(devlink, dev);
 311}
 312
 313void hinic_devlink_unregister(struct hinic_devlink_priv *priv)
 314{
 315        struct devlink *devlink = priv_to_devlink(priv);
 316
 317        devlink_unregister(devlink);
 318}
 319
 320static int chip_fault_show(struct devlink_fmsg *fmsg,
 321                           struct hinic_fault_event *event)
 322{
 323        const char * const level_str[FAULT_LEVEL_MAX + 1] = {
 324                "fatal", "reset", "flr", "general", "suggestion", "Unknown"};
 325        u8 fault_level;
 326        int err;
 327
 328        fault_level = (event->event.chip.err_level < FAULT_LEVEL_MAX) ?
 329                event->event.chip.err_level : FAULT_LEVEL_MAX;
 330        if (fault_level == FAULT_LEVEL_SERIOUS_FLR) {
 331                err = devlink_fmsg_u32_pair_put(fmsg, "Function level err func_id",
 332                                                (u32)event->event.chip.func_id);
 333                if (err)
 334                        return err;
 335        }
 336
 337        err = devlink_fmsg_u8_pair_put(fmsg, "module_id", event->event.chip.node_id);
 338        if (err)
 339                return err;
 340
 341        err = devlink_fmsg_u32_pair_put(fmsg, "err_type", (u32)event->event.chip.err_type);
 342        if (err)
 343                return err;
 344
 345        err = devlink_fmsg_string_pair_put(fmsg, "err_level", level_str[fault_level]);
 346        if (err)
 347                return err;
 348
 349        err = devlink_fmsg_u32_pair_put(fmsg, "err_csr_addr",
 350                                        event->event.chip.err_csr_addr);
 351        if (err)
 352                return err;
 353
 354        err = devlink_fmsg_u32_pair_put(fmsg, "err_csr_value",
 355                                        event->event.chip.err_csr_value);
 356        if (err)
 357                return err;
 358
 359        return 0;
 360}
 361
 362static int fault_report_show(struct devlink_fmsg *fmsg,
 363                             struct hinic_fault_event *event)
 364{
 365        const char * const type_str[FAULT_TYPE_MAX + 1] = {
 366                "chip", "ucode", "mem rd timeout", "mem wr timeout",
 367                "reg rd timeout", "reg wr timeout", "phy fault", "Unknown"};
 368        u8 fault_type;
 369        int err;
 370
 371        fault_type = (event->type < FAULT_TYPE_MAX) ? event->type : FAULT_TYPE_MAX;
 372
 373        err = devlink_fmsg_string_pair_put(fmsg, "Fault type", type_str[fault_type]);
 374        if (err)
 375                return err;
 376
 377        err = devlink_fmsg_binary_pair_put(fmsg, "Fault raw data",
 378                                           event->event.val, sizeof(event->event.val));
 379        if (err)
 380                return err;
 381
 382        switch (event->type) {
 383        case FAULT_TYPE_CHIP:
 384                err = chip_fault_show(fmsg, event);
 385                if (err)
 386                        return err;
 387                break;
 388        case FAULT_TYPE_UCODE:
 389                err = devlink_fmsg_u8_pair_put(fmsg, "Cause_id", event->event.ucode.cause_id);
 390                if (err)
 391                        return err;
 392                err = devlink_fmsg_u8_pair_put(fmsg, "core_id", event->event.ucode.core_id);
 393                if (err)
 394                        return err;
 395                err = devlink_fmsg_u8_pair_put(fmsg, "c_id", event->event.ucode.c_id);
 396                if (err)
 397                        return err;
 398                err = devlink_fmsg_u8_pair_put(fmsg, "epc", event->event.ucode.epc);
 399                if (err)
 400                        return err;
 401                break;
 402        case FAULT_TYPE_MEM_RD_TIMEOUT:
 403        case FAULT_TYPE_MEM_WR_TIMEOUT:
 404                err = devlink_fmsg_u32_pair_put(fmsg, "Err_csr_ctrl",
 405                                                event->event.mem_timeout.err_csr_ctrl);
 406                if (err)
 407                        return err;
 408                err = devlink_fmsg_u32_pair_put(fmsg, "err_csr_data",
 409                                                event->event.mem_timeout.err_csr_data);
 410                if (err)
 411                        return err;
 412                err = devlink_fmsg_u32_pair_put(fmsg, "ctrl_tab",
 413                                                event->event.mem_timeout.ctrl_tab);
 414                if (err)
 415                        return err;
 416                err = devlink_fmsg_u32_pair_put(fmsg, "mem_index",
 417                                                event->event.mem_timeout.mem_index);
 418                if (err)
 419                        return err;
 420                break;
 421        case FAULT_TYPE_REG_RD_TIMEOUT:
 422        case FAULT_TYPE_REG_WR_TIMEOUT:
 423                err = devlink_fmsg_u32_pair_put(fmsg, "Err_csr", event->event.reg_timeout.err_csr);
 424                if (err)
 425                        return err;
 426                break;
 427        case FAULT_TYPE_PHY_FAULT:
 428                err = devlink_fmsg_u8_pair_put(fmsg, "Op_type", event->event.phy_fault.op_type);
 429                if (err)
 430                        return err;
 431                err = devlink_fmsg_u8_pair_put(fmsg, "port_id", event->event.phy_fault.port_id);
 432                if (err)
 433                        return err;
 434                err = devlink_fmsg_u8_pair_put(fmsg, "dev_ad", event->event.phy_fault.dev_ad);
 435                if (err)
 436                        return err;
 437
 438                err = devlink_fmsg_u32_pair_put(fmsg, "csr_addr", event->event.phy_fault.csr_addr);
 439                if (err)
 440                        return err;
 441                err = devlink_fmsg_u32_pair_put(fmsg, "op_data", event->event.phy_fault.op_data);
 442                if (err)
 443                        return err;
 444                break;
 445        default:
 446                break;
 447        }
 448
 449        return 0;
 450}
 451
 452static int hinic_hw_reporter_dump(struct devlink_health_reporter *reporter,
 453                                  struct devlink_fmsg *fmsg, void *priv_ctx,
 454                                  struct netlink_ext_ack *extack)
 455{
 456        if (priv_ctx)
 457                return fault_report_show(fmsg, priv_ctx);
 458
 459        return 0;
 460}
 461
 462static int mgmt_watchdog_report_show(struct devlink_fmsg *fmsg,
 463                                     struct hinic_mgmt_watchdog_info *watchdog_info)
 464{
 465        int err;
 466
 467        err = devlink_fmsg_u32_pair_put(fmsg, "Mgmt deadloop time_h", watchdog_info->curr_time_h);
 468        if (err)
 469                return err;
 470
 471        err = devlink_fmsg_u32_pair_put(fmsg, "time_l", watchdog_info->curr_time_l);
 472        if (err)
 473                return err;
 474
 475        err = devlink_fmsg_u32_pair_put(fmsg, "task_id", watchdog_info->task_id);
 476        if (err)
 477                return err;
 478
 479        err = devlink_fmsg_u32_pair_put(fmsg, "sp", watchdog_info->sp);
 480        if (err)
 481                return err;
 482
 483        err = devlink_fmsg_u32_pair_put(fmsg, "stack_current_used", watchdog_info->curr_used);
 484        if (err)
 485                return err;
 486
 487        err = devlink_fmsg_u32_pair_put(fmsg, "peak_used", watchdog_info->peak_used);
 488        if (err)
 489                return err;
 490
 491        err = devlink_fmsg_u32_pair_put(fmsg, "\n Overflow_flag", watchdog_info->is_overflow);
 492        if (err)
 493                return err;
 494
 495        err = devlink_fmsg_u32_pair_put(fmsg, "stack_top", watchdog_info->stack_top);
 496        if (err)
 497                return err;
 498
 499        err = devlink_fmsg_u32_pair_put(fmsg, "stack_bottom", watchdog_info->stack_bottom);
 500        if (err)
 501                return err;
 502
 503        err = devlink_fmsg_u32_pair_put(fmsg, "mgmt_pc", watchdog_info->pc);
 504        if (err)
 505                return err;
 506
 507        err = devlink_fmsg_u32_pair_put(fmsg, "lr", watchdog_info->lr);
 508        if (err)
 509                return err;
 510
 511        err = devlink_fmsg_u32_pair_put(fmsg, "cpsr", watchdog_info->cpsr);
 512        if (err)
 513                return err;
 514
 515        err = devlink_fmsg_binary_pair_put(fmsg, "Mgmt register info",
 516                                           watchdog_info->reg, sizeof(watchdog_info->reg));
 517        if (err)
 518                return err;
 519
 520        err = devlink_fmsg_binary_pair_put(fmsg, "Mgmt dump stack(start from sp)",
 521                                           watchdog_info->data, sizeof(watchdog_info->data));
 522        if (err)
 523                return err;
 524
 525        return 0;
 526}
 527
 528static int hinic_fw_reporter_dump(struct devlink_health_reporter *reporter,
 529                                  struct devlink_fmsg *fmsg, void *priv_ctx,
 530                                  struct netlink_ext_ack *extack)
 531{
 532        if (priv_ctx)
 533                return mgmt_watchdog_report_show(fmsg, priv_ctx);
 534
 535        return 0;
 536}
 537
 538static const struct devlink_health_reporter_ops hinic_hw_fault_reporter_ops = {
 539        .name = "hw",
 540        .dump = hinic_hw_reporter_dump,
 541};
 542
 543static const struct devlink_health_reporter_ops hinic_fw_fault_reporter_ops = {
 544        .name = "fw",
 545        .dump = hinic_fw_reporter_dump,
 546};
 547
 548int hinic_health_reporters_create(struct hinic_devlink_priv *priv)
 549{
 550        struct devlink *devlink = priv_to_devlink(priv);
 551
 552        priv->hw_fault_reporter =
 553                devlink_health_reporter_create(devlink, &hinic_hw_fault_reporter_ops,
 554                                               0, priv);
 555        if (IS_ERR(priv->hw_fault_reporter)) {
 556                dev_warn(&priv->hwdev->hwif->pdev->dev, "Failed to create hw fault reporter, err: %ld\n",
 557                         PTR_ERR(priv->hw_fault_reporter));
 558                return PTR_ERR(priv->hw_fault_reporter);
 559        }
 560
 561        priv->fw_fault_reporter =
 562                devlink_health_reporter_create(devlink, &hinic_fw_fault_reporter_ops,
 563                                               0, priv);
 564        if (IS_ERR(priv->fw_fault_reporter)) {
 565                dev_warn(&priv->hwdev->hwif->pdev->dev, "Failed to create fw fault reporter, err: %ld\n",
 566                         PTR_ERR(priv->fw_fault_reporter));
 567                devlink_health_reporter_destroy(priv->hw_fault_reporter);
 568                priv->hw_fault_reporter = NULL;
 569                return PTR_ERR(priv->fw_fault_reporter);
 570        }
 571
 572        return 0;
 573}
 574
 575void hinic_health_reporters_destroy(struct hinic_devlink_priv *priv)
 576{
 577        if (!IS_ERR_OR_NULL(priv->fw_fault_reporter)) {
 578                devlink_health_reporter_destroy(priv->fw_fault_reporter);
 579                priv->fw_fault_reporter = NULL;
 580        }
 581
 582        if (!IS_ERR_OR_NULL(priv->hw_fault_reporter)) {
 583                devlink_health_reporter_destroy(priv->hw_fault_reporter);
 584                priv->hw_fault_reporter = NULL;
 585        }
 586}
 587