799 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */3 4#include <linux/printk.h>5#include <linux/dynamic_debug.h>6#include <linux/module.h>7#include <linux/netdevice.h>8#include <linux/utsname.h>9#include <generated/utsrelease.h>10#include <linux/ctype.h>11 12#include "ionic.h"13#include "ionic_bus.h"14#include "ionic_lif.h"15#include "ionic_debugfs.h"16 17MODULE_DESCRIPTION(IONIC_DRV_DESCRIPTION);18MODULE_AUTHOR("Shannon Nelson <shannon.nelson@amd.com>");19MODULE_LICENSE("GPL");20 21static const char *ionic_error_to_str(enum ionic_status_code code)22{23 switch (code) {24 case IONIC_RC_SUCCESS:25 return "IONIC_RC_SUCCESS";26 case IONIC_RC_EVERSION:27 return "IONIC_RC_EVERSION";28 case IONIC_RC_EOPCODE:29 return "IONIC_RC_EOPCODE";30 case IONIC_RC_EIO:31 return "IONIC_RC_EIO";32 case IONIC_RC_EPERM:33 return "IONIC_RC_EPERM";34 case IONIC_RC_EQID:35 return "IONIC_RC_EQID";36 case IONIC_RC_EQTYPE:37 return "IONIC_RC_EQTYPE";38 case IONIC_RC_ENOENT:39 return "IONIC_RC_ENOENT";40 case IONIC_RC_EINTR:41 return "IONIC_RC_EINTR";42 case IONIC_RC_EAGAIN:43 return "IONIC_RC_EAGAIN";44 case IONIC_RC_ENOMEM:45 return "IONIC_RC_ENOMEM";46 case IONIC_RC_EFAULT:47 return "IONIC_RC_EFAULT";48 case IONIC_RC_EBUSY:49 return "IONIC_RC_EBUSY";50 case IONIC_RC_EEXIST:51 return "IONIC_RC_EEXIST";52 case IONIC_RC_EINVAL:53 return "IONIC_RC_EINVAL";54 case IONIC_RC_ENOSPC:55 return "IONIC_RC_ENOSPC";56 case IONIC_RC_ERANGE:57 return "IONIC_RC_ERANGE";58 case IONIC_RC_BAD_ADDR:59 return "IONIC_RC_BAD_ADDR";60 case IONIC_RC_DEV_CMD:61 return "IONIC_RC_DEV_CMD";62 case IONIC_RC_ENOSUPP:63 return "IONIC_RC_ENOSUPP";64 case IONIC_RC_ERROR:65 return "IONIC_RC_ERROR";66 case IONIC_RC_ERDMA:67 return "IONIC_RC_ERDMA";68 case IONIC_RC_EBAD_FW:69 return "IONIC_RC_EBAD_FW";70 default:71 return "IONIC_RC_UNKNOWN";72 }73}74 75static int ionic_error_to_errno(enum ionic_status_code code)76{77 switch (code) {78 case IONIC_RC_SUCCESS:79 return 0;80 case IONIC_RC_EVERSION:81 case IONIC_RC_EQTYPE:82 case IONIC_RC_EQID:83 case IONIC_RC_EINVAL:84 case IONIC_RC_ENOSUPP:85 return -EINVAL;86 case IONIC_RC_EPERM:87 return -EPERM;88 case IONIC_RC_ENOENT:89 return -ENOENT;90 case IONIC_RC_EAGAIN:91 return -EAGAIN;92 case IONIC_RC_ENOMEM:93 return -ENOMEM;94 case IONIC_RC_EFAULT:95 return -EFAULT;96 case IONIC_RC_EBUSY:97 return -EBUSY;98 case IONIC_RC_EEXIST:99 return -EEXIST;100 case IONIC_RC_ENOSPC:101 return -ENOSPC;102 case IONIC_RC_ERANGE:103 return -ERANGE;104 case IONIC_RC_BAD_ADDR:105 return -EFAULT;106 case IONIC_RC_EOPCODE:107 case IONIC_RC_EINTR:108 case IONIC_RC_DEV_CMD:109 case IONIC_RC_ERROR:110 case IONIC_RC_ERDMA:111 case IONIC_RC_EIO:112 default:113 return -EIO;114 }115}116 117static const char *ionic_opcode_to_str(enum ionic_cmd_opcode opcode)118{119 switch (opcode) {120 case IONIC_CMD_NOP:121 return "IONIC_CMD_NOP";122 case IONIC_CMD_INIT:123 return "IONIC_CMD_INIT";124 case IONIC_CMD_RESET:125 return "IONIC_CMD_RESET";126 case IONIC_CMD_IDENTIFY:127 return "IONIC_CMD_IDENTIFY";128 case IONIC_CMD_GETATTR:129 return "IONIC_CMD_GETATTR";130 case IONIC_CMD_SETATTR:131 return "IONIC_CMD_SETATTR";132 case IONIC_CMD_PORT_IDENTIFY:133 return "IONIC_CMD_PORT_IDENTIFY";134 case IONIC_CMD_PORT_INIT:135 return "IONIC_CMD_PORT_INIT";136 case IONIC_CMD_PORT_RESET:137 return "IONIC_CMD_PORT_RESET";138 case IONIC_CMD_PORT_GETATTR:139 return "IONIC_CMD_PORT_GETATTR";140 case IONIC_CMD_PORT_SETATTR:141 return "IONIC_CMD_PORT_SETATTR";142 case IONIC_CMD_LIF_INIT:143 return "IONIC_CMD_LIF_INIT";144 case IONIC_CMD_LIF_RESET:145 return "IONIC_CMD_LIF_RESET";146 case IONIC_CMD_LIF_IDENTIFY:147 return "IONIC_CMD_LIF_IDENTIFY";148 case IONIC_CMD_LIF_SETATTR:149 return "IONIC_CMD_LIF_SETATTR";150 case IONIC_CMD_LIF_GETATTR:151 return "IONIC_CMD_LIF_GETATTR";152 case IONIC_CMD_LIF_SETPHC:153 return "IONIC_CMD_LIF_SETPHC";154 case IONIC_CMD_RX_MODE_SET:155 return "IONIC_CMD_RX_MODE_SET";156 case IONIC_CMD_RX_FILTER_ADD:157 return "IONIC_CMD_RX_FILTER_ADD";158 case IONIC_CMD_RX_FILTER_DEL:159 return "IONIC_CMD_RX_FILTER_DEL";160 case IONIC_CMD_Q_IDENTIFY:161 return "IONIC_CMD_Q_IDENTIFY";162 case IONIC_CMD_Q_INIT:163 return "IONIC_CMD_Q_INIT";164 case IONIC_CMD_Q_CONTROL:165 return "IONIC_CMD_Q_CONTROL";166 case IONIC_CMD_RDMA_RESET_LIF:167 return "IONIC_CMD_RDMA_RESET_LIF";168 case IONIC_CMD_RDMA_CREATE_EQ:169 return "IONIC_CMD_RDMA_CREATE_EQ";170 case IONIC_CMD_RDMA_CREATE_CQ:171 return "IONIC_CMD_RDMA_CREATE_CQ";172 case IONIC_CMD_RDMA_CREATE_ADMINQ:173 return "IONIC_CMD_RDMA_CREATE_ADMINQ";174 case IONIC_CMD_FW_DOWNLOAD:175 return "IONIC_CMD_FW_DOWNLOAD";176 case IONIC_CMD_FW_CONTROL:177 return "IONIC_CMD_FW_CONTROL";178 case IONIC_CMD_FW_DOWNLOAD_V1:179 return "IONIC_CMD_FW_DOWNLOAD_V1";180 case IONIC_CMD_FW_CONTROL_V1:181 return "IONIC_CMD_FW_CONTROL_V1";182 case IONIC_CMD_VF_GETATTR:183 return "IONIC_CMD_VF_GETATTR";184 case IONIC_CMD_VF_SETATTR:185 return "IONIC_CMD_VF_SETATTR";186 default:187 return "DEVCMD_UNKNOWN";188 }189}190 191static void ionic_adminq_flush(struct ionic_lif *lif)192{193 struct ionic_admin_desc_info *desc_info;194 struct ionic_admin_cmd *desc;195 unsigned long irqflags;196 struct ionic_queue *q;197 198 spin_lock_irqsave(&lif->adminq_lock, irqflags);199 if (!lif->adminqcq) {200 spin_unlock_irqrestore(&lif->adminq_lock, irqflags);201 return;202 }203 204 q = &lif->adminqcq->q;205 206 while (q->tail_idx != q->head_idx) {207 desc = &q->adminq[q->tail_idx];208 desc_info = &q->admin_info[q->tail_idx];209 memset(desc, 0, sizeof(union ionic_adminq_cmd));210 desc_info->ctx = NULL;211 q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);212 }213 spin_unlock_irqrestore(&lif->adminq_lock, irqflags);214}215 216void ionic_adminq_netdev_err_print(struct ionic_lif *lif, u8 opcode,217 u8 status, int err)218{219 const char *stat_str;220 221 stat_str = (err == -ETIMEDOUT) ? "TIMEOUT" :222 ionic_error_to_str(status);223 224 netdev_err(lif->netdev, "%s (%d) failed: %s (%d)\n",225 ionic_opcode_to_str(opcode), opcode, stat_str, err);226}227 228static int ionic_adminq_check_err(struct ionic_lif *lif,229 struct ionic_admin_ctx *ctx,230 const bool timeout,231 const bool do_msg)232{233 int err = 0;234 235 if (ctx->comp.comp.status || timeout) {236 err = timeout ? -ETIMEDOUT :237 ionic_error_to_errno(ctx->comp.comp.status);238 239 if (do_msg)240 ionic_adminq_netdev_err_print(lif, ctx->cmd.cmd.opcode,241 ctx->comp.comp.status, err);242 243 if (timeout)244 ionic_adminq_flush(lif);245 }246 247 return err;248}249 250bool ionic_notifyq_service(struct ionic_cq *cq)251{252 struct ionic_deferred_work *work;253 union ionic_notifyq_comp *comp;254 struct net_device *netdev;255 struct ionic_queue *q;256 struct ionic_lif *lif;257 u64 eid;258 259 comp = &((union ionic_notifyq_comp *)cq->base)[cq->tail_idx];260 261 q = cq->bound_q;262 lif = q->admin_info[0].ctx;263 netdev = lif->netdev;264 eid = le64_to_cpu(comp->event.eid);265 266 /* Have we run out of new completions to process? */267 if ((s64)(eid - lif->last_eid) <= 0)268 return false;269 270 lif->last_eid = eid;271 272 dev_dbg(lif->ionic->dev, "notifyq event:\n");273 dynamic_hex_dump("event ", DUMP_PREFIX_OFFSET, 16, 1,274 comp, sizeof(*comp), true);275 276 switch (le16_to_cpu(comp->event.ecode)) {277 case IONIC_EVENT_LINK_CHANGE:278 ionic_link_status_check_request(lif, CAN_NOT_SLEEP);279 break;280 case IONIC_EVENT_RESET:281 if (lif->ionic->idev.fw_status_ready &&282 !test_bit(IONIC_LIF_F_FW_RESET, lif->state) &&283 !test_and_set_bit(IONIC_LIF_F_FW_STOPPING, lif->state)) {284 work = kzalloc(sizeof(*work), GFP_ATOMIC);285 if (!work) {286 netdev_err(lif->netdev, "Reset event dropped\n");287 clear_bit(IONIC_LIF_F_FW_STOPPING, lif->state);288 } else {289 work->type = IONIC_DW_TYPE_LIF_RESET;290 ionic_lif_deferred_enqueue(lif, work);291 }292 }293 break;294 default:295 netdev_warn(netdev, "Notifyq event ecode=%d eid=%lld\n",296 comp->event.ecode, eid);297 break;298 }299 300 return true;301}302 303bool ionic_adminq_service(struct ionic_cq *cq)304{305 struct ionic_admin_desc_info *desc_info;306 struct ionic_queue *q = cq->bound_q;307 struct ionic_admin_comp *comp;308 u16 index;309 310 comp = &((struct ionic_admin_comp *)cq->base)[cq->tail_idx];311 312 if (!color_match(comp->color, cq->done_color))313 return false;314 315 /* check for empty queue */316 if (q->tail_idx == q->head_idx)317 return false;318 319 do {320 desc_info = &q->admin_info[q->tail_idx];321 index = q->tail_idx;322 q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);323 if (likely(desc_info->ctx)) {324 struct ionic_admin_ctx *ctx = desc_info->ctx;325 326 memcpy(&ctx->comp, comp, sizeof(*comp));327 328 dev_dbg(q->dev, "comp admin queue command:\n");329 dynamic_hex_dump("comp ", DUMP_PREFIX_OFFSET, 16, 1,330 &ctx->comp, sizeof(ctx->comp), true);331 complete_all(&ctx->work);332 desc_info->ctx = NULL;333 }334 } while (index != le16_to_cpu(comp->comp_index));335 336 return true;337}338 339bool ionic_adminq_poke_doorbell(struct ionic_queue *q)340{341 struct ionic_lif *lif = q->lif;342 unsigned long now, then, dif;343 unsigned long irqflags;344 345 spin_lock_irqsave(&lif->adminq_lock, irqflags);346 347 if (q->tail_idx == q->head_idx) {348 spin_unlock_irqrestore(&lif->adminq_lock, irqflags);349 return false;350 }351 352 now = READ_ONCE(jiffies);353 then = q->dbell_jiffies;354 dif = now - then;355 356 if (dif > q->dbell_deadline) {357 ionic_dbell_ring(q->lif->kern_dbpage, q->hw_type,358 q->dbval | q->head_idx);359 360 q->dbell_jiffies = now;361 }362 363 spin_unlock_irqrestore(&lif->adminq_lock, irqflags);364 365 return true;366}367 368int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)369{370 struct ionic_admin_desc_info *desc_info;371 struct ionic_admin_cmd *desc;372 unsigned long irqflags;373 struct ionic_queue *q;374 int err = 0;375 376 spin_lock_irqsave(&lif->adminq_lock, irqflags);377 if (!lif->adminqcq) {378 spin_unlock_irqrestore(&lif->adminq_lock, irqflags);379 return -EIO;380 }381 382 q = &lif->adminqcq->q;383 384 if (!ionic_q_has_space(q, 1)) {385 err = -ENOSPC;386 goto err_out;387 }388 389 err = ionic_heartbeat_check(lif->ionic);390 if (err)391 goto err_out;392 393 desc_info = &q->admin_info[q->head_idx];394 desc_info->ctx = ctx;395 396 desc = &q->adminq[q->head_idx];397 memcpy(desc, &ctx->cmd, sizeof(ctx->cmd));398 399 dev_dbg(&lif->netdev->dev, "post admin queue command:\n");400 dynamic_hex_dump("cmd ", DUMP_PREFIX_OFFSET, 16, 1,401 &ctx->cmd, sizeof(ctx->cmd), true);402 403 ionic_q_post(q, true);404 405err_out:406 spin_unlock_irqrestore(&lif->adminq_lock, irqflags);407 408 return err;409}410 411int ionic_adminq_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx,412 const int err, const bool do_msg)413{414 struct net_device *netdev = lif->netdev;415 unsigned long time_limit;416 unsigned long time_start;417 unsigned long time_done;418 unsigned long remaining;419 const char *name;420 421 name = ionic_opcode_to_str(ctx->cmd.cmd.opcode);422 423 if (err) {424 if (do_msg && !test_bit(IONIC_LIF_F_FW_RESET, lif->state))425 netdev_err(netdev, "Posting of %s (%d) failed: %d\n",426 name, ctx->cmd.cmd.opcode, err);427 ctx->comp.comp.status = IONIC_RC_ERROR;428 return err;429 }430 431 time_start = jiffies;432 time_limit = time_start + HZ * (ulong)DEVCMD_TIMEOUT;433 do {434 remaining = wait_for_completion_timeout(&ctx->work,435 IONIC_ADMINQ_TIME_SLICE);436 437 /* check for done */438 if (remaining)439 break;440 441 /* force a check of FW status and break out if FW reset */442 ionic_heartbeat_check(lif->ionic);443 if ((test_bit(IONIC_LIF_F_FW_RESET, lif->state) &&444 !lif->ionic->idev.fw_status_ready) ||445 test_bit(IONIC_LIF_F_FW_STOPPING, lif->state)) {446 if (do_msg)447 netdev_warn(netdev, "%s (%d) interrupted, FW in reset\n",448 name, ctx->cmd.cmd.opcode);449 ctx->comp.comp.status = IONIC_RC_ERROR;450 return -ENXIO;451 }452 453 } while (time_before(jiffies, time_limit));454 time_done = jiffies;455 456 dev_dbg(lif->ionic->dev, "%s: elapsed %d msecs\n",457 __func__, jiffies_to_msecs(time_done - time_start));458 459 return ionic_adminq_check_err(lif, ctx,460 time_after_eq(time_done, time_limit),461 do_msg);462}463 464static int __ionic_adminq_post_wait(struct ionic_lif *lif,465 struct ionic_admin_ctx *ctx,466 const bool do_msg)467{468 int err;469 470 if (!ionic_is_fw_running(&lif->ionic->idev))471 return 0;472 473 err = ionic_adminq_post(lif, ctx);474 475 return ionic_adminq_wait(lif, ctx, err, do_msg);476}477 478int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)479{480 return __ionic_adminq_post_wait(lif, ctx, true);481}482 483int ionic_adminq_post_wait_nomsg(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)484{485 return __ionic_adminq_post_wait(lif, ctx, false);486}487 488static void ionic_dev_cmd_clean(struct ionic *ionic)489{490 struct ionic_dev *idev = &ionic->idev;491 492 if (!idev->dev_cmd_regs)493 return;494 495 iowrite32(0, &idev->dev_cmd_regs->doorbell);496 memset_io(&idev->dev_cmd_regs->cmd, 0, sizeof(idev->dev_cmd_regs->cmd));497}498 499void ionic_dev_cmd_dev_err_print(struct ionic *ionic, u8 opcode, u8 status,500 int err)501{502 const char *stat_str;503 504 stat_str = (err == -ETIMEDOUT) ? "TIMEOUT" :505 ionic_error_to_str(status);506 507 dev_err(ionic->dev, "DEV_CMD %s (%d) error, %s (%d) failed\n",508 ionic_opcode_to_str(opcode), opcode, stat_str, err);509}510 511static int __ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds,512 const bool do_msg)513{514 struct ionic_dev *idev = &ionic->idev;515 unsigned long start_time;516 unsigned long max_wait;517 unsigned long duration;518 int done = 0;519 bool fw_up;520 int opcode;521 int err;522 523 /* Wait for dev cmd to complete, retrying if we get EAGAIN,524 * but don't wait any longer than max_seconds.525 */526 max_wait = jiffies + (max_seconds * HZ);527try_again:528 opcode = idev->opcode;529 start_time = jiffies;530 for (fw_up = ionic_is_fw_running(idev);531 !done && fw_up && time_before(jiffies, max_wait);532 fw_up = ionic_is_fw_running(idev)) {533 done = ionic_dev_cmd_done(idev);534 if (done)535 break;536 usleep_range(100, 200);537 }538 duration = jiffies - start_time;539 540 dev_dbg(ionic->dev, "DEVCMD %s (%d) done=%d took %ld secs (%ld jiffies)\n",541 ionic_opcode_to_str(opcode), opcode,542 done, duration / HZ, duration);543 544 if (!done && !fw_up) {545 ionic_dev_cmd_clean(ionic);546 dev_warn(ionic->dev, "DEVCMD %s (%d) interrupted - FW is down\n",547 ionic_opcode_to_str(opcode), opcode);548 return -ENXIO;549 }550 551 if (!done && !time_before(jiffies, max_wait)) {552 ionic_dev_cmd_clean(ionic);553 dev_warn(ionic->dev, "DEVCMD %s (%d) timeout after %ld secs\n",554 ionic_opcode_to_str(opcode), opcode, max_seconds);555 return -ETIMEDOUT;556 }557 558 err = ionic_dev_cmd_status(&ionic->idev);559 if (err) {560 if (err == IONIC_RC_EAGAIN &&561 time_before(jiffies, (max_wait - HZ))) {562 dev_dbg(ionic->dev, "DEV_CMD %s (%d), %s (%d) retrying...\n",563 ionic_opcode_to_str(opcode), opcode,564 ionic_error_to_str(err), err);565 566 iowrite32(0, &idev->dev_cmd_regs->done);567 msleep(1000);568 iowrite32(1, &idev->dev_cmd_regs->doorbell);569 goto try_again;570 }571 572 if (!(opcode == IONIC_CMD_FW_CONTROL && err == IONIC_RC_EAGAIN))573 if (do_msg)574 ionic_dev_cmd_dev_err_print(ionic, opcode, err,575 ionic_error_to_errno(err));576 577 return ionic_error_to_errno(err);578 }579 580 ionic_dev_cmd_clean(ionic);581 582 return 0;583}584 585int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)586{587 return __ionic_dev_cmd_wait(ionic, max_seconds, true);588}589 590int ionic_dev_cmd_wait_nomsg(struct ionic *ionic, unsigned long max_seconds)591{592 return __ionic_dev_cmd_wait(ionic, max_seconds, false);593}594 595int ionic_setup(struct ionic *ionic)596{597 int err;598 599 err = ionic_dev_setup(ionic);600 if (err)601 return err;602 ionic_reset(ionic);603 604 return 0;605}606 607int ionic_identify(struct ionic *ionic)608{609 struct ionic_identity *ident = &ionic->ident;610 struct ionic_dev *idev = &ionic->idev;611 size_t sz;612 int err;613 614 memset(ident, 0, sizeof(*ident));615 616 ident->drv.os_type = cpu_to_le32(IONIC_OS_TYPE_LINUX);617 strscpy(ident->drv.driver_ver_str, UTS_RELEASE,618 sizeof(ident->drv.driver_ver_str));619 620 mutex_lock(&ionic->dev_cmd_lock);621 622 sz = min(sizeof(ident->drv), sizeof(idev->dev_cmd_regs->data));623 memcpy_toio(&idev->dev_cmd_regs->data, &ident->drv, sz);624 625 ionic_dev_cmd_identify(idev, IONIC_DEV_IDENTITY_VERSION_2);626 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);627 if (!err) {628 sz = min(sizeof(ident->dev), sizeof(idev->dev_cmd_regs->data));629 memcpy_fromio(&ident->dev, &idev->dev_cmd_regs->data, sz);630 }631 mutex_unlock(&ionic->dev_cmd_lock);632 633 if (err) {634 dev_err(ionic->dev, "Cannot identify ionic: %d\n", err);635 goto err_out;636 }637 638 if (isprint(idev->dev_info.fw_version[0]) &&639 isascii(idev->dev_info.fw_version[0]))640 dev_info(ionic->dev, "FW: %.*s\n",641 (int)(sizeof(idev->dev_info.fw_version) - 1),642 idev->dev_info.fw_version);643 else644 dev_info(ionic->dev, "FW: (invalid string) 0x%02x 0x%02x 0x%02x 0x%02x ...\n",645 (u8)idev->dev_info.fw_version[0],646 (u8)idev->dev_info.fw_version[1],647 (u8)idev->dev_info.fw_version[2],648 (u8)idev->dev_info.fw_version[3]);649 650 err = ionic_lif_identify(ionic, IONIC_LIF_TYPE_CLASSIC,651 &ionic->ident.lif);652 if (err) {653 dev_err(ionic->dev, "Cannot identify LIFs: %d\n", err);654 goto err_out;655 }656 657 return 0;658 659err_out:660 return err;661}662 663int ionic_init(struct ionic *ionic)664{665 struct ionic_dev *idev = &ionic->idev;666 int err;667 668 mutex_lock(&ionic->dev_cmd_lock);669 ionic_dev_cmd_init(idev);670 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);671 mutex_unlock(&ionic->dev_cmd_lock);672 673 return err;674}675 676int ionic_reset(struct ionic *ionic)677{678 struct ionic_dev *idev = &ionic->idev;679 int err;680 681 if (!ionic_is_fw_running(idev))682 return 0;683 684 mutex_lock(&ionic->dev_cmd_lock);685 ionic_dev_cmd_reset(idev);686 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);687 mutex_unlock(&ionic->dev_cmd_lock);688 689 return err;690}691 692int ionic_port_identify(struct ionic *ionic)693{694 struct ionic_identity *ident = &ionic->ident;695 struct ionic_dev *idev = &ionic->idev;696 size_t sz;697 int err;698 699 mutex_lock(&ionic->dev_cmd_lock);700 701 ionic_dev_cmd_port_identify(idev);702 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);703 if (!err) {704 sz = min(sizeof(ident->port), sizeof(idev->dev_cmd_regs->data));705 memcpy_fromio(&ident->port, &idev->dev_cmd_regs->data, sz);706 }707 708 mutex_unlock(&ionic->dev_cmd_lock);709 710 return err;711}712 713int ionic_port_init(struct ionic *ionic)714{715 struct ionic_identity *ident = &ionic->ident;716 struct ionic_dev *idev = &ionic->idev;717 size_t sz;718 int err;719 720 if (!idev->port_info) {721 idev->port_info_sz = ALIGN(sizeof(*idev->port_info), PAGE_SIZE);722 idev->port_info = dma_alloc_coherent(ionic->dev,723 idev->port_info_sz,724 &idev->port_info_pa,725 GFP_KERNEL);726 if (!idev->port_info)727 return -ENOMEM;728 }729 730 sz = min(sizeof(ident->port.config), sizeof(idev->dev_cmd_regs->data));731 732 mutex_lock(&ionic->dev_cmd_lock);733 734 memcpy_toio(&idev->dev_cmd_regs->data, &ident->port.config, sz);735 ionic_dev_cmd_port_init(idev);736 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);737 738 ionic_dev_cmd_port_state(&ionic->idev, IONIC_PORT_ADMIN_STATE_UP);739 ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);740 741 mutex_unlock(&ionic->dev_cmd_lock);742 if (err) {743 dev_err(ionic->dev, "Failed to init port\n");744 dma_free_coherent(ionic->dev, idev->port_info_sz,745 idev->port_info, idev->port_info_pa);746 idev->port_info = NULL;747 idev->port_info_pa = 0;748 }749 750 return err;751}752 753int ionic_port_reset(struct ionic *ionic)754{755 struct ionic_dev *idev = &ionic->idev;756 int err = 0;757 758 if (!idev->port_info)759 return 0;760 761 if (ionic_is_fw_running(idev)) {762 mutex_lock(&ionic->dev_cmd_lock);763 ionic_dev_cmd_port_reset(idev);764 err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);765 mutex_unlock(&ionic->dev_cmd_lock);766 }767 768 dma_free_coherent(ionic->dev, idev->port_info_sz,769 idev->port_info, idev->port_info_pa);770 771 idev->port_info = NULL;772 idev->port_info_pa = 0;773 774 return err;775}776 777static int __init ionic_init_module(void)778{779 int ret;780 781 ionic_debugfs_create();782 ret = ionic_bus_register_driver();783 if (ret)784 ionic_debugfs_destroy();785 786 return ret;787}788 789static void __exit ionic_cleanup_module(void)790{791 ionic_bus_unregister_driver();792 ionic_debugfs_destroy();793 794 pr_info("%s removed\n", IONIC_DRV_NAME);795}796 797module_init(ionic_init_module);798module_exit(ionic_cleanup_module);799