diff options
Diffstat (limited to 'drivers/net/sfc/mtd.c')
-rw-r--r-- | drivers/net/sfc/mtd.c | 106 |
1 files changed, 71 insertions, 35 deletions
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c index 02e54b4f701f..b6304486f244 100644 --- a/drivers/net/sfc/mtd.c +++ b/drivers/net/sfc/mtd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2005-2006 Fen Systems Ltd. | 3 | * Copyright 2005-2006 Fen Systems Ltd. |
4 | * Copyright 2006-2009 Solarflare Communications Inc. | 4 | * Copyright 2006-2010 Solarflare Communications Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
@@ -216,7 +216,7 @@ static void efx_mtd_remove_partition(struct efx_mtd_partition *part) | |||
216 | int rc; | 216 | int rc; |
217 | 217 | ||
218 | for (;;) { | 218 | for (;;) { |
219 | rc = del_mtd_device(&part->mtd); | 219 | rc = mtd_device_unregister(&part->mtd); |
220 | if (rc != -EBUSY) | 220 | if (rc != -EBUSY) |
221 | break; | 221 | break; |
222 | ssleep(1); | 222 | ssleep(1); |
@@ -268,7 +268,7 @@ static int efx_mtd_probe_device(struct efx_nic *efx, struct efx_mtd *efx_mtd) | |||
268 | part->mtd.write = efx_mtd->ops->write; | 268 | part->mtd.write = efx_mtd->ops->write; |
269 | part->mtd.sync = efx_mtd_sync; | 269 | part->mtd.sync = efx_mtd_sync; |
270 | 270 | ||
271 | if (add_mtd_device(&part->mtd)) | 271 | if (mtd_device_register(&part->mtd, NULL, 0)) |
272 | goto fail; | 272 | goto fail; |
273 | } | 273 | } |
274 | 274 | ||
@@ -280,7 +280,7 @@ fail: | |||
280 | --part; | 280 | --part; |
281 | efx_mtd_remove_partition(part); | 281 | efx_mtd_remove_partition(part); |
282 | } | 282 | } |
283 | /* add_mtd_device() returns 1 if the MTD table is full */ | 283 | /* mtd_device_register() returns 1 if the MTD table is full */ |
284 | return -ENOMEM; | 284 | return -ENOMEM; |
285 | } | 285 | } |
286 | 286 | ||
@@ -321,14 +321,15 @@ static int falcon_mtd_read(struct mtd_info *mtd, loff_t start, | |||
321 | struct efx_mtd *efx_mtd = mtd->priv; | 321 | struct efx_mtd *efx_mtd = mtd->priv; |
322 | const struct efx_spi_device *spi = efx_mtd->spi; | 322 | const struct efx_spi_device *spi = efx_mtd->spi; |
323 | struct efx_nic *efx = efx_mtd->efx; | 323 | struct efx_nic *efx = efx_mtd->efx; |
324 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
324 | int rc; | 325 | int rc; |
325 | 326 | ||
326 | rc = mutex_lock_interruptible(&efx->spi_lock); | 327 | rc = mutex_lock_interruptible(&nic_data->spi_lock); |
327 | if (rc) | 328 | if (rc) |
328 | return rc; | 329 | return rc; |
329 | rc = falcon_spi_read(efx, spi, part->offset + start, len, | 330 | rc = falcon_spi_read(efx, spi, part->offset + start, len, |
330 | retlen, buffer); | 331 | retlen, buffer); |
331 | mutex_unlock(&efx->spi_lock); | 332 | mutex_unlock(&nic_data->spi_lock); |
332 | return rc; | 333 | return rc; |
333 | } | 334 | } |
334 | 335 | ||
@@ -337,13 +338,14 @@ static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len) | |||
337 | struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); | 338 | struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); |
338 | struct efx_mtd *efx_mtd = mtd->priv; | 339 | struct efx_mtd *efx_mtd = mtd->priv; |
339 | struct efx_nic *efx = efx_mtd->efx; | 340 | struct efx_nic *efx = efx_mtd->efx; |
341 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
340 | int rc; | 342 | int rc; |
341 | 343 | ||
342 | rc = mutex_lock_interruptible(&efx->spi_lock); | 344 | rc = mutex_lock_interruptible(&nic_data->spi_lock); |
343 | if (rc) | 345 | if (rc) |
344 | return rc; | 346 | return rc; |
345 | rc = efx_spi_erase(part, part->offset + start, len); | 347 | rc = efx_spi_erase(part, part->offset + start, len); |
346 | mutex_unlock(&efx->spi_lock); | 348 | mutex_unlock(&nic_data->spi_lock); |
347 | return rc; | 349 | return rc; |
348 | } | 350 | } |
349 | 351 | ||
@@ -354,14 +356,15 @@ static int falcon_mtd_write(struct mtd_info *mtd, loff_t start, | |||
354 | struct efx_mtd *efx_mtd = mtd->priv; | 356 | struct efx_mtd *efx_mtd = mtd->priv; |
355 | const struct efx_spi_device *spi = efx_mtd->spi; | 357 | const struct efx_spi_device *spi = efx_mtd->spi; |
356 | struct efx_nic *efx = efx_mtd->efx; | 358 | struct efx_nic *efx = efx_mtd->efx; |
359 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
357 | int rc; | 360 | int rc; |
358 | 361 | ||
359 | rc = mutex_lock_interruptible(&efx->spi_lock); | 362 | rc = mutex_lock_interruptible(&nic_data->spi_lock); |
360 | if (rc) | 363 | if (rc) |
361 | return rc; | 364 | return rc; |
362 | rc = falcon_spi_write(efx, spi, part->offset + start, len, | 365 | rc = falcon_spi_write(efx, spi, part->offset + start, len, |
363 | retlen, buffer); | 366 | retlen, buffer); |
364 | mutex_unlock(&efx->spi_lock); | 367 | mutex_unlock(&nic_data->spi_lock); |
365 | return rc; | 368 | return rc; |
366 | } | 369 | } |
367 | 370 | ||
@@ -370,11 +373,12 @@ static int falcon_mtd_sync(struct mtd_info *mtd) | |||
370 | struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); | 373 | struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); |
371 | struct efx_mtd *efx_mtd = mtd->priv; | 374 | struct efx_mtd *efx_mtd = mtd->priv; |
372 | struct efx_nic *efx = efx_mtd->efx; | 375 | struct efx_nic *efx = efx_mtd->efx; |
376 | struct falcon_nic_data *nic_data = efx->nic_data; | ||
373 | int rc; | 377 | int rc; |
374 | 378 | ||
375 | mutex_lock(&efx->spi_lock); | 379 | mutex_lock(&nic_data->spi_lock); |
376 | rc = efx_spi_slow_wait(part, true); | 380 | rc = efx_spi_slow_wait(part, true); |
377 | mutex_unlock(&efx->spi_lock); | 381 | mutex_unlock(&nic_data->spi_lock); |
378 | return rc; | 382 | return rc; |
379 | } | 383 | } |
380 | 384 | ||
@@ -387,35 +391,67 @@ static struct efx_mtd_ops falcon_mtd_ops = { | |||
387 | 391 | ||
388 | static int falcon_mtd_probe(struct efx_nic *efx) | 392 | static int falcon_mtd_probe(struct efx_nic *efx) |
389 | { | 393 | { |
390 | struct efx_spi_device *spi = efx->spi_flash; | 394 | struct falcon_nic_data *nic_data = efx->nic_data; |
395 | struct efx_spi_device *spi; | ||
391 | struct efx_mtd *efx_mtd; | 396 | struct efx_mtd *efx_mtd; |
392 | int rc; | 397 | int rc = -ENODEV; |
393 | 398 | ||
394 | ASSERT_RTNL(); | 399 | ASSERT_RTNL(); |
395 | 400 | ||
396 | if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START) | 401 | spi = &nic_data->spi_flash; |
397 | return -ENODEV; | 402 | if (efx_spi_present(spi) && spi->size > FALCON_FLASH_BOOTCODE_START) { |
398 | 403 | efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), | |
399 | efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), | 404 | GFP_KERNEL); |
400 | GFP_KERNEL); | 405 | if (!efx_mtd) |
401 | if (!efx_mtd) | 406 | return -ENOMEM; |
402 | return -ENOMEM; | 407 | |
403 | 408 | efx_mtd->spi = spi; | |
404 | efx_mtd->spi = spi; | 409 | efx_mtd->name = "flash"; |
405 | efx_mtd->name = "flash"; | 410 | efx_mtd->ops = &falcon_mtd_ops; |
406 | efx_mtd->ops = &falcon_mtd_ops; | 411 | |
412 | efx_mtd->n_parts = 1; | ||
413 | efx_mtd->part[0].mtd.type = MTD_NORFLASH; | ||
414 | efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH; | ||
415 | efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START; | ||
416 | efx_mtd->part[0].mtd.erasesize = spi->erase_size; | ||
417 | efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START; | ||
418 | efx_mtd->part[0].type_name = "sfc_flash_bootrom"; | ||
419 | |||
420 | rc = efx_mtd_probe_device(efx, efx_mtd); | ||
421 | if (rc) { | ||
422 | kfree(efx_mtd); | ||
423 | return rc; | ||
424 | } | ||
425 | } | ||
407 | 426 | ||
408 | efx_mtd->n_parts = 1; | 427 | spi = &nic_data->spi_eeprom; |
409 | efx_mtd->part[0].mtd.type = MTD_NORFLASH; | 428 | if (efx_spi_present(spi) && spi->size > EFX_EEPROM_BOOTCONFIG_START) { |
410 | efx_mtd->part[0].mtd.flags = MTD_CAP_NORFLASH; | 429 | efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), |
411 | efx_mtd->part[0].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START; | 430 | GFP_KERNEL); |
412 | efx_mtd->part[0].mtd.erasesize = spi->erase_size; | 431 | if (!efx_mtd) |
413 | efx_mtd->part[0].offset = FALCON_FLASH_BOOTCODE_START; | 432 | return -ENOMEM; |
414 | efx_mtd->part[0].type_name = "sfc_flash_bootrom"; | 433 | |
434 | efx_mtd->spi = spi; | ||
435 | efx_mtd->name = "EEPROM"; | ||
436 | efx_mtd->ops = &falcon_mtd_ops; | ||
437 | |||
438 | efx_mtd->n_parts = 1; | ||
439 | efx_mtd->part[0].mtd.type = MTD_RAM; | ||
440 | efx_mtd->part[0].mtd.flags = MTD_CAP_RAM; | ||
441 | efx_mtd->part[0].mtd.size = | ||
442 | min(spi->size, EFX_EEPROM_BOOTCONFIG_END) - | ||
443 | EFX_EEPROM_BOOTCONFIG_START; | ||
444 | efx_mtd->part[0].mtd.erasesize = spi->erase_size; | ||
445 | efx_mtd->part[0].offset = EFX_EEPROM_BOOTCONFIG_START; | ||
446 | efx_mtd->part[0].type_name = "sfc_bootconfig"; | ||
447 | |||
448 | rc = efx_mtd_probe_device(efx, efx_mtd); | ||
449 | if (rc) { | ||
450 | kfree(efx_mtd); | ||
451 | return rc; | ||
452 | } | ||
453 | } | ||
415 | 454 | ||
416 | rc = efx_mtd_probe_device(efx, efx_mtd); | ||
417 | if (rc) | ||
418 | kfree(efx_mtd); | ||
419 | return rc; | 455 | return rc; |
420 | } | 456 | } |
421 | 457 | ||