brintos

brintos / linux-shallow public Read only

0
0
Text · 19.1 KiB · 0f817c3 Raw
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