mtd.c 16.7 KB
Newer Older
1 2 3
/****************************************************************************
 * Driver for Solarflare Solarstorm network controllers and boards
 * Copyright 2005-2006 Fen Systems Ltd.
Ben Hutchings's avatar
Ben Hutchings committed
4
 * Copyright 2006-2010 Solarflare Communications Inc.
5 6 7 8 9 10
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation, incorporated herein by reference.
 */

11
#include <linux/bitops.h>
12 13 14
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/delay.h>
15
#include <linux/slab.h>
16
#include <linux/rtnetlink.h>
17 18 19

#include "net_driver.h"
#include "spi.h"
20
#include "efx.h"
21
#include "nic.h"
22 23
#include "mcdi.h"
#include "mcdi_pcol.h"
24 25 26

#define EFX_SPI_VERIFY_BUF_LEN 16

27
struct efx_mtd_partition {
28
	struct mtd_info mtd;
29 30 31 32 33 34 35 36
	union {
		struct {
			bool updating;
			u8 nvram_type;
			u16 fw_subtype;
		} mcdi;
		size_t offset;
	};
37
	const char *type_name;
38 39 40
	char name[IFNAMSIZ + 20];
};

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
struct efx_mtd_ops {
	int (*read)(struct mtd_info *mtd, loff_t start, size_t len,
		    size_t *retlen, u8 *buffer);
	int (*erase)(struct mtd_info *mtd, loff_t start, size_t len);
	int (*write)(struct mtd_info *mtd, loff_t start, size_t len,
		     size_t *retlen, const u8 *buffer);
	int (*sync)(struct mtd_info *mtd);
};

struct efx_mtd {
	struct list_head node;
	struct efx_nic *efx;
	const struct efx_spi_device *spi;
	const char *name;
	const struct efx_mtd_ops *ops;
	size_t n_parts;
	struct efx_mtd_partition part[0];
};

#define efx_for_each_partition(part, efx_mtd)			\
	for ((part) = &(efx_mtd)->part[0];			\
	     (part) != &(efx_mtd)->part[(efx_mtd)->n_parts];	\
	     (part)++)

#define to_efx_mtd_partition(mtd)				\
	container_of(mtd, struct efx_mtd_partition, mtd)

static int falcon_mtd_probe(struct efx_nic *efx);
69
static int siena_mtd_probe(struct efx_nic *efx);
70

71 72
/* SPI utilities */

73 74
static int
efx_spi_slow_wait(struct efx_mtd_partition *part, bool uninterruptible)
75
{
76
	struct efx_mtd *efx_mtd = part->mtd.priv;
77
	const struct efx_spi_device *spi = efx_mtd->spi;
78
	struct efx_nic *efx = efx_mtd->efx;
79 80 81 82 83 84 85 86
	u8 status;
	int rc, i;

	/* Wait up to 4s for flash/EEPROM to finish a slow operation. */
	for (i = 0; i < 40; i++) {
		__set_current_state(uninterruptible ?
				    TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
		schedule_timeout(HZ / 10);
87
		rc = falcon_spi_cmd(efx, spi, SPI_RDSR, -1, NULL,
88 89 90 91 92 93 94 95
				    &status, sizeof(status));
		if (rc)
			return rc;
		if (!(status & SPI_STATUS_NRDY))
			return 0;
		if (signal_pending(current))
			return -EINTR;
	}
96
	pr_err("%s: timed out waiting for %s\n", part->name, efx_mtd->name);
97 98 99
	return -ETIMEDOUT;
}

100 101
static int
efx_spi_unlock(struct efx_nic *efx, const struct efx_spi_device *spi)
102 103 104 105 106 107
{
	const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 |
				SPI_STATUS_BP0);
	u8 status;
	int rc;

108 109
	rc = falcon_spi_cmd(efx, spi, SPI_RDSR, -1, NULL,
			    &status, sizeof(status));
110 111 112 113 114 115
	if (rc)
		return rc;

	if (!(status & unlock_mask))
		return 0; /* already unlocked */

116
	rc = falcon_spi_cmd(efx, spi, SPI_WREN, -1, NULL, NULL, 0);
117 118
	if (rc)
		return rc;
119
	rc = falcon_spi_cmd(efx, spi, SPI_SST_EWSR, -1, NULL, NULL, 0);
120 121 122 123
	if (rc)
		return rc;

	status &= ~unlock_mask;
124 125
	rc = falcon_spi_cmd(efx, spi, SPI_WRSR, -1, &status,
			    NULL, sizeof(status));
126 127
	if (rc)
		return rc;
128
	rc = falcon_spi_wait_write(efx, spi);
129 130 131 132 133 134
	if (rc)
		return rc;

	return 0;
}

135 136
static int
efx_spi_erase(struct efx_mtd_partition *part, loff_t start, size_t len)
137
{
138
	struct efx_mtd *efx_mtd = part->mtd.priv;
139
	const struct efx_spi_device *spi = efx_mtd->spi;
140
	struct efx_nic *efx = efx_mtd->efx;
141 142 143 144 145 146 147 148 149 150 151
	unsigned pos, block_len;
	u8 empty[EFX_SPI_VERIFY_BUF_LEN];
	u8 buffer[EFX_SPI_VERIFY_BUF_LEN];
	int rc;

	if (len != spi->erase_size)
		return -EINVAL;

	if (spi->erase_command == 0)
		return -EOPNOTSUPP;

152
	rc = efx_spi_unlock(efx, spi);
153 154
	if (rc)
		return rc;
155
	rc = falcon_spi_cmd(efx, spi, SPI_WREN, -1, NULL, NULL, 0);
156 157
	if (rc)
		return rc;
158 159
	rc = falcon_spi_cmd(efx, spi, spi->erase_command, start, NULL,
			    NULL, 0);
160 161
	if (rc)
		return rc;
162
	rc = efx_spi_slow_wait(part, false);
163 164 165 166 167

	/* Verify the entire region has been wiped */
	memset(empty, 0xff, sizeof(empty));
	for (pos = 0; pos < len; pos += block_len) {
		block_len = min(len - pos, sizeof(buffer));
168 169
		rc = falcon_spi_read(efx, spi, start + pos, block_len,
				     NULL, buffer);
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
		if (rc)
			return rc;
		if (memcmp(empty, buffer, block_len))
			return -EIO;

		/* Avoid locking up the system */
		cond_resched();
		if (signal_pending(current))
			return -EINTR;
	}

	return rc;
}

/* MTD interface */

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
{
	struct efx_mtd *efx_mtd = mtd->priv;
	int rc;

	rc = efx_mtd->ops->erase(mtd, erase->addr, erase->len);
	if (rc == 0) {
		erase->state = MTD_ERASE_DONE;
	} else {
		erase->state = MTD_ERASE_FAILED;
		erase->fail_addr = 0xffffffff;
	}
	mtd_erase_callback(erase);
	return rc;
}

static void efx_mtd_sync(struct mtd_info *mtd)
{
204
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
205 206 207 208 209
	struct efx_mtd *efx_mtd = mtd->priv;
	int rc;

	rc = efx_mtd->ops->sync(mtd);
	if (rc)
210 211
		pr_err("%s: %s sync failed (%d)\n",
		       part->name, efx_mtd->name, rc);
212 213 214 215 216 217 218
}

static void efx_mtd_remove_partition(struct efx_mtd_partition *part)
{
	int rc;

	for (;;) {
219
		rc = mtd_device_unregister(&part->mtd);
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
		if (rc != -EBUSY)
			break;
		ssleep(1);
	}
	WARN_ON(rc);
}

static void efx_mtd_remove_device(struct efx_mtd *efx_mtd)
{
	struct efx_mtd_partition *part;

	efx_for_each_partition(part, efx_mtd)
		efx_mtd_remove_partition(part);
	list_del(&efx_mtd->node);
	kfree(efx_mtd);
}

static void efx_mtd_rename_device(struct efx_mtd *efx_mtd)
{
	struct efx_mtd_partition *part;

	efx_for_each_partition(part, efx_mtd)
242 243 244 245 246 247 248 249
		if (efx_nic_rev(efx_mtd->efx) >= EFX_REV_SIENA_A0)
			snprintf(part->name, sizeof(part->name),
				 "%s %s:%02x", efx_mtd->efx->name,
				 part->type_name, part->mcdi.fw_subtype);
		else
			snprintf(part->name, sizeof(part->name),
				 "%s %s", efx_mtd->efx->name,
				 part->type_name);
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
}

static int efx_mtd_probe_device(struct efx_nic *efx, struct efx_mtd *efx_mtd)
{
	struct efx_mtd_partition *part;

	efx_mtd->efx = efx;

	efx_mtd_rename_device(efx_mtd);

	efx_for_each_partition(part, efx_mtd) {
		part->mtd.writesize = 1;

		part->mtd.owner = THIS_MODULE;
		part->mtd.priv = efx_mtd;
		part->mtd.name = part->name;
		part->mtd.erase = efx_mtd_erase;
		part->mtd.read = efx_mtd->ops->read;
		part->mtd.write = efx_mtd->ops->write;
		part->mtd.sync = efx_mtd_sync;

271
		if (mtd_device_register(&part->mtd, NULL, 0))
272 273 274 275 276 277 278 279 280 281 282
			goto fail;
	}

	list_add(&efx_mtd->node, &efx->mtd_list);
	return 0;

fail:
	while (part != &efx_mtd->part[0]) {
		--part;
		efx_mtd_remove_partition(part);
	}
283
	/* Failure is unlikely here, but probably means we're out of memory */
284 285 286 287
	return -ENOMEM;
}

void efx_mtd_remove(struct efx_nic *efx)
288
{
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
	struct efx_mtd *efx_mtd, *next;

	WARN_ON(efx_dev_registered(efx));

	list_for_each_entry_safe(efx_mtd, next, &efx->mtd_list, node)
		efx_mtd_remove_device(efx_mtd);
}

void efx_mtd_rename(struct efx_nic *efx)
{
	struct efx_mtd *efx_mtd;

	ASSERT_RTNL();

	list_for_each_entry(efx_mtd, &efx->mtd_list, node)
		efx_mtd_rename_device(efx_mtd);
}

int efx_mtd_probe(struct efx_nic *efx)
{
309 310 311 312
	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
		return siena_mtd_probe(efx);
	else
		return falcon_mtd_probe(efx);
313 314 315 316 317 318 319 320
}

/* Implementation of MTD operations for Falcon */

static int falcon_mtd_read(struct mtd_info *mtd, loff_t start,
			   size_t len, size_t *retlen, u8 *buffer)
{
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
321 322
	struct efx_mtd *efx_mtd = mtd->priv;
	const struct efx_spi_device *spi = efx_mtd->spi;
323
	struct efx_nic *efx = efx_mtd->efx;
324
	struct falcon_nic_data *nic_data = efx->nic_data;
325 326
	int rc;

327
	rc = mutex_lock_interruptible(&nic_data->spi_lock);
328 329
	if (rc)
		return rc;
330 331
	rc = falcon_spi_read(efx, spi, part->offset + start, len,
			     retlen, buffer);
332
	mutex_unlock(&nic_data->spi_lock);
333 334 335
	return rc;
}

336
static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
337
{
338
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
339
	struct efx_mtd *efx_mtd = mtd->priv;
340
	struct efx_nic *efx = efx_mtd->efx;
341
	struct falcon_nic_data *nic_data = efx->nic_data;
342 343
	int rc;

344
	rc = mutex_lock_interruptible(&nic_data->spi_lock);
345 346
	if (rc)
		return rc;
347
	rc = efx_spi_erase(part, part->offset + start, len);
348
	mutex_unlock(&nic_data->spi_lock);
349 350 351
	return rc;
}

352 353
static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
			    size_t len, size_t *retlen, const u8 *buffer)
354
{
355
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
356 357
	struct efx_mtd *efx_mtd = mtd->priv;
	const struct efx_spi_device *spi = efx_mtd->spi;
358
	struct efx_nic *efx = efx_mtd->efx;
359
	struct falcon_nic_data *nic_data = efx->nic_data;
360 361
	int rc;

362
	rc = mutex_lock_interruptible(&nic_data->spi_lock);
363 364
	if (rc)
		return rc;
365 366
	rc = falcon_spi_write(efx, spi, part->offset + start, len,
			      retlen, buffer);
367
	mutex_unlock(&nic_data->spi_lock);
368 369 370
	return rc;
}

371
static int falcon_mtd_sync(struct mtd_info *mtd)
372
{
373
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
374
	struct efx_mtd *efx_mtd = mtd->priv;
375
	struct efx_nic *efx = efx_mtd->efx;
376
	struct falcon_nic_data *nic_data = efx->nic_data;
377 378
	int rc;

379
	mutex_lock(&nic_data->spi_lock);
380
	rc = efx_spi_slow_wait(part, true);
381
	mutex_unlock(&nic_data->spi_lock);
382
	return rc;
383 384
}

385
static const struct efx_mtd_ops falcon_mtd_ops = {
386 387 388 389 390
	.read	= falcon_mtd_read,
	.erase	= falcon_mtd_erase,
	.write	= falcon_mtd_write,
	.sync	= falcon_mtd_sync,
};
391

392
static int falcon_mtd_probe(struct efx_nic *efx)
393
{
394
	struct falcon_nic_data *nic_data = efx->nic_data;
395
	struct efx_spi_device *spi;
396
	struct efx_mtd *efx_mtd;
397
	int rc = -ENODEV;
398 399

	ASSERT_RTNL();
400

401 402
	spi = &nic_data->spi_flash;
	if (efx_spi_present(spi) && spi->size > FALCON_FLASH_BOOTCODE_START) {
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
		efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]),
				  GFP_KERNEL);
		if (!efx_mtd)
			return -ENOMEM;

		efx_mtd->spi = spi;
		efx_mtd->name = "flash";
		efx_mtd->ops = &falcon_mtd_ops;

		efx_mtd->n_parts = 1;
		efx_mtd->part[0].mtd.type = MTD_NORFLASH;
		efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH;
		efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
		efx_mtd->part[0].mtd.erasesize = spi->erase_size;
		efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START;
		efx_mtd->part[0].type_name = "sfc_flash_bootrom";

		rc = efx_mtd_probe_device(efx, efx_mtd);
		if (rc) {
			kfree(efx_mtd);
			return rc;
		}
	}
426

427 428
	spi = &nic_data->spi_eeprom;
	if (efx_spi_present(spi) && spi->size > EFX_EEPROM_BOOTCONFIG_START) {
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
		efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]),
				  GFP_KERNEL);
		if (!efx_mtd)
			return -ENOMEM;

		efx_mtd->spi = spi;
		efx_mtd->name = "EEPROM";
		efx_mtd->ops = &falcon_mtd_ops;

		efx_mtd->n_parts = 1;
		efx_mtd->part[0].mtd.type = MTD_RAM;
		efx_mtd->part[0].mtd.flags = MTD_CAP_RAM;
		efx_mtd->part[0].mtd.size =
			min(spi->size, EFX_EEPROM_BOOTCONFIG_END) -
			EFX_EEPROM_BOOTCONFIG_START;
		efx_mtd->part[0].mtd.erasesize = spi->erase_size;
		efx_mtd->part[0].offset = EFX_EEPROM_BOOTCONFIG_START;
		efx_mtd->part[0].type_name = "sfc_bootconfig";

		rc = efx_mtd_probe_device(efx, efx_mtd);
		if (rc) {
			kfree(efx_mtd);
			return rc;
		}
	}
454 455

	return rc;
456
}
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471

/* Implementation of MTD operations for Siena */

static int siena_mtd_read(struct mtd_info *mtd, loff_t start,
			  size_t len, size_t *retlen, u8 *buffer)
{
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
	struct efx_mtd *efx_mtd = mtd->priv;
	struct efx_nic *efx = efx_mtd->efx;
	loff_t offset = start;
	loff_t end = min_t(loff_t, start + len, mtd->size);
	size_t chunk;
	int rc = 0;

	while (offset < end) {
472
		chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
		rc = efx_mcdi_nvram_read(efx, part->mcdi.nvram_type, offset,
					 buffer, chunk);
		if (rc)
			goto out;
		offset += chunk;
		buffer += chunk;
	}
out:
	*retlen = offset - start;
	return rc;
}

static int siena_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
{
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
	struct efx_mtd *efx_mtd = mtd->priv;
	struct efx_nic *efx = efx_mtd->efx;
	loff_t offset = start & ~((loff_t)(mtd->erasesize - 1));
	loff_t end = min_t(loff_t, start + len, mtd->size);
	size_t chunk = part->mtd.erasesize;
	int rc = 0;

	if (!part->mcdi.updating) {
		rc = efx_mcdi_nvram_update_start(efx, part->mcdi.nvram_type);
		if (rc)
			goto out;
499
		part->mcdi.updating = true;
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
	}

	/* The MCDI interface can in fact do multiple erase blocks at once;
	 * but erasing may be slow, so we make multiple calls here to avoid
	 * tripping the MCDI RPC timeout. */
	while (offset < end) {
		rc = efx_mcdi_nvram_erase(efx, part->mcdi.nvram_type, offset,
					  chunk);
		if (rc)
			goto out;
		offset += chunk;
	}
out:
	return rc;
}

static int siena_mtd_write(struct mtd_info *mtd, loff_t start,
			   size_t len, size_t *retlen, const u8 *buffer)
{
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
	struct efx_mtd *efx_mtd = mtd->priv;
	struct efx_nic *efx = efx_mtd->efx;
	loff_t offset = start;
	loff_t end = min_t(loff_t, start + len, mtd->size);
	size_t chunk;
	int rc = 0;

	if (!part->mcdi.updating) {
		rc = efx_mcdi_nvram_update_start(efx, part->mcdi.nvram_type);
		if (rc)
			goto out;
531
		part->mcdi.updating = true;
532 533 534
	}

	while (offset < end) {
535
		chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
		rc = efx_mcdi_nvram_write(efx, part->mcdi.nvram_type, offset,
					  buffer, chunk);
		if (rc)
			goto out;
		offset += chunk;
		buffer += chunk;
	}
out:
	*retlen = offset - start;
	return rc;
}

static int siena_mtd_sync(struct mtd_info *mtd)
{
	struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
	struct efx_mtd *efx_mtd = mtd->priv;
	struct efx_nic *efx = efx_mtd->efx;
	int rc = 0;

	if (part->mcdi.updating) {
556
		part->mcdi.updating = false;
557 558 559 560 561 562
		rc = efx_mcdi_nvram_update_finish(efx, part->mcdi.nvram_type);
	}

	return rc;
}

563
static const struct efx_mtd_ops siena_mtd_ops = {
564 565 566 567 568 569 570 571 572 573 574
	.read	= siena_mtd_read,
	.erase	= siena_mtd_erase,
	.write	= siena_mtd_write,
	.sync	= siena_mtd_sync,
};

struct siena_nvram_type_info {
	int port;
	const char *name;
};

575
static const struct siena_nvram_type_info siena_nvram_types[] = {
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
	[MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO]	= { 0, "sfc_dummy_phy" },
	[MC_CMD_NVRAM_TYPE_MC_FW]		= { 0, "sfc_mcfw" },
	[MC_CMD_NVRAM_TYPE_MC_FW_BACKUP]	= { 0, "sfc_mcfw_backup" },
	[MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0]	= { 0, "sfc_static_cfg" },
	[MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1]	= { 1, "sfc_static_cfg" },
	[MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0]	= { 0, "sfc_dynamic_cfg" },
	[MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1]	= { 1, "sfc_dynamic_cfg" },
	[MC_CMD_NVRAM_TYPE_EXP_ROM]		= { 0, "sfc_exp_rom" },
	[MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0]	= { 0, "sfc_exp_rom_cfg" },
	[MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1]	= { 1, "sfc_exp_rom_cfg" },
	[MC_CMD_NVRAM_TYPE_PHY_PORT0]		= { 0, "sfc_phy_fw" },
	[MC_CMD_NVRAM_TYPE_PHY_PORT1]		= { 1, "sfc_phy_fw" },
};

static int siena_mtd_probe_partition(struct efx_nic *efx,
				     struct efx_mtd *efx_mtd,
				     unsigned int part_id,
				     unsigned int type)
{
	struct efx_mtd_partition *part = &efx_mtd->part[part_id];
596
	const struct siena_nvram_type_info *info;
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
	size_t size, erase_size;
	bool protected;
	int rc;

	if (type >= ARRAY_SIZE(siena_nvram_types))
		return -ENODEV;

	info = &siena_nvram_types[type];

	if (info->port != efx_port_num(efx))
		return -ENODEV;

	rc = efx_mcdi_nvram_info(efx, type, &size, &erase_size, &protected);
	if (rc)
		return rc;
	if (protected)
		return -ENODEV; /* hide it */

	part->mcdi.nvram_type = type;
	part->type_name = info->name;

	part->mtd.type = MTD_NORFLASH;
	part->mtd.flags = MTD_CAP_NORFLASH;
	part->mtd.size = size;
	part->mtd.erasesize = erase_size;

	return 0;
}

static int siena_mtd_get_fw_subtypes(struct efx_nic *efx,
				     struct efx_mtd *efx_mtd)
{
	struct efx_mtd_partition *part;
630
	uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM];
631 632
	int rc;

633
	rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list, NULL);
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
	if (rc)
		return rc;

	efx_for_each_partition(part, efx_mtd)
		part->mcdi.fw_subtype = fw_subtype_list[part->mcdi.nvram_type];

	return 0;
}

static int siena_mtd_probe(struct efx_nic *efx)
{
	struct efx_mtd *efx_mtd;
	int rc = -ENODEV;
	u32 nvram_types;
	unsigned int type;

	ASSERT_RTNL();

	rc = efx_mcdi_nvram_types(efx, &nvram_types);
	if (rc)
		return rc;

	efx_mtd = kzalloc(sizeof(*efx_mtd) +
			  hweight32(nvram_types) * sizeof(efx_mtd->part[0]),
			  GFP_KERNEL);
	if (!efx_mtd)
		return -ENOMEM;

	efx_mtd->name = "Siena NVRAM manager";

	efx_mtd->ops = &siena_mtd_ops;

	type = 0;
	efx_mtd->n_parts = 0;

	while (nvram_types != 0) {
		if (nvram_types & 1) {
			rc = siena_mtd_probe_partition(efx, efx_mtd,
						       efx_mtd->n_parts, type);
			if (rc == 0)
				efx_mtd->n_parts++;
			else if (rc != -ENODEV)
				goto fail;
		}
		type++;
		nvram_types >>= 1;
	}

	rc = siena_mtd_get_fw_subtypes(efx, efx_mtd);
	if (rc)
		goto fail;

	rc = efx_mtd_probe_device(efx, efx_mtd);
fail:
	if (rc)
		kfree(efx_mtd);
	return rc;
}