aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2012-11-27 23:38:10 -0500
committerBen Hutchings <bhutchings@solarflare.com>2013-08-22 14:26:04 -0400
commitb766630b351c68c0383831dba9b81a905e5e84c6 (patch)
treea76241779bfa03c7eabf0c9712d30cf0e23fb5e5
parentecd0a6f0f2c70a3b713bc77d8a32d6b4ad5ad49b (diff)
sfc: Eliminate struct efx_mtd
Currently we use struct efx_mtd to represent a physical NVRAM device and struct efx_mtd_partition to represent a partition on that device. But this only really makes sense for Falcon, as we don't know or care whether MC-managed NVRAM partitions are on one or more physical devices. It complicates iteration and provides little benefit. Therefore: - Replace the pointer to efx_mtd in mtd_info::priv with a pointer to efx_nic - Move the falcon_spi_device pointer into the union in struct efx_mtd_partition - Move the device name to efx_mtd_partition::dev_type_name - Move the efx_mtd_ops pointer to efx_nic::mtd_ops - Make efx_nic::mtd_list a list of partitions Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r--drivers/net/ethernet/sfc/mtd.c279
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h1
2 files changed, 120 insertions, 160 deletions
diff --git a/drivers/net/ethernet/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c
index e4b35c61e90b..ba6c87a73d86 100644
--- a/drivers/net/ethernet/sfc/mtd.c
+++ b/drivers/net/ethernet/sfc/mtd.c
@@ -25,6 +25,7 @@
25#define FALCON_SPI_VERIFY_BUF_LEN 16 25#define FALCON_SPI_VERIFY_BUF_LEN 16
26 26
27struct efx_mtd_partition { 27struct efx_mtd_partition {
28 struct list_head node;
28 struct mtd_info mtd; 29 struct mtd_info mtd;
29 union { 30 union {
30 struct { 31 struct {
@@ -32,8 +33,12 @@ struct efx_mtd_partition {
32 u8 nvram_type; 33 u8 nvram_type;
33 u16 fw_subtype; 34 u16 fw_subtype;
34 } mcdi; 35 } mcdi;
35 size_t offset; 36 struct {
37 const struct falcon_spi_device *spi;
38 size_t offset;
39 } falcon;
36 }; 40 };
41 const char *dev_type_name;
37 const char *type_name; 42 const char *type_name;
38 char name[IFNAMSIZ + 20]; 43 char name[IFNAMSIZ + 20];
39}; 44};
@@ -47,21 +52,6 @@ struct efx_mtd_ops {
47 int (*sync)(struct mtd_info *mtd); 52 int (*sync)(struct mtd_info *mtd);
48}; 53};
49 54
50struct efx_mtd {
51 struct list_head node;
52 struct efx_nic *efx;
53 const struct falcon_spi_device *spi;
54 const char *name;
55 const struct efx_mtd_ops *ops;
56 size_t n_parts;
57 struct efx_mtd_partition part[0];
58};
59
60#define efx_for_each_partition(part, efx_mtd) \
61 for ((part) = &(efx_mtd)->part[0]; \
62 (part) != &(efx_mtd)->part[(efx_mtd)->n_parts]; \
63 (part)++)
64
65#define to_efx_mtd_partition(mtd) \ 55#define to_efx_mtd_partition(mtd) \
66 container_of(mtd, struct efx_mtd_partition, mtd) 56 container_of(mtd, struct efx_mtd_partition, mtd)
67 57
@@ -73,9 +63,8 @@ static int siena_mtd_probe(struct efx_nic *efx);
73static int 63static int
74falcon_spi_slow_wait(struct efx_mtd_partition *part, bool uninterruptible) 64falcon_spi_slow_wait(struct efx_mtd_partition *part, bool uninterruptible)
75{ 65{
76 struct efx_mtd *efx_mtd = part->mtd.priv; 66 const struct falcon_spi_device *spi = part->falcon.spi;
77 const struct falcon_spi_device *spi = efx_mtd->spi; 67 struct efx_nic *efx = part->mtd.priv;
78 struct efx_nic *efx = efx_mtd->efx;
79 u8 status; 68 u8 status;
80 int rc, i; 69 int rc, i;
81 70
@@ -93,7 +82,8 @@ falcon_spi_slow_wait(struct efx_mtd_partition *part, bool uninterruptible)
93 if (signal_pending(current)) 82 if (signal_pending(current))
94 return -EINTR; 83 return -EINTR;
95 } 84 }
96 pr_err("%s: timed out waiting for %s\n", part->name, efx_mtd->name); 85 pr_err("%s: timed out waiting for %s\n",
86 part->name, part->dev_type_name);
97 return -ETIMEDOUT; 87 return -ETIMEDOUT;
98} 88}
99 89
@@ -135,9 +125,8 @@ falcon_spi_unlock(struct efx_nic *efx, const struct falcon_spi_device *spi)
135static int 125static int
136falcon_spi_erase(struct efx_mtd_partition *part, loff_t start, size_t len) 126falcon_spi_erase(struct efx_mtd_partition *part, loff_t start, size_t len)
137{ 127{
138 struct efx_mtd *efx_mtd = part->mtd.priv; 128 const struct falcon_spi_device *spi = part->falcon.spi;
139 const struct falcon_spi_device *spi = efx_mtd->spi; 129 struct efx_nic *efx = part->mtd.priv;
140 struct efx_nic *efx = efx_mtd->efx;
141 unsigned pos, block_len; 130 unsigned pos, block_len;
142 u8 empty[FALCON_SPI_VERIFY_BUF_LEN]; 131 u8 empty[FALCON_SPI_VERIFY_BUF_LEN];
143 u8 buffer[FALCON_SPI_VERIFY_BUF_LEN]; 132 u8 buffer[FALCON_SPI_VERIFY_BUF_LEN];
@@ -185,10 +174,10 @@ falcon_spi_erase(struct efx_mtd_partition *part, loff_t start, size_t len)
185 174
186static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) 175static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
187{ 176{
188 struct efx_mtd *efx_mtd = mtd->priv; 177 struct efx_nic *efx = mtd->priv;
189 int rc; 178 int rc;
190 179
191 rc = efx_mtd->ops->erase(mtd, erase->addr, erase->len); 180 rc = efx->mtd_ops->erase(mtd, erase->addr, erase->len);
192 if (rc == 0) { 181 if (rc == 0) {
193 erase->state = MTD_ERASE_DONE; 182 erase->state = MTD_ERASE_DONE;
194 } else { 183 } else {
@@ -202,13 +191,13 @@ static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
202static void efx_mtd_sync(struct mtd_info *mtd) 191static void efx_mtd_sync(struct mtd_info *mtd)
203{ 192{
204 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 193 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
205 struct efx_mtd *efx_mtd = mtd->priv; 194 struct efx_nic *efx = mtd->priv;
206 int rc; 195 int rc;
207 196
208 rc = efx_mtd->ops->sync(mtd); 197 rc = efx->mtd_ops->sync(mtd);
209 if (rc) 198 if (rc)
210 pr_err("%s: %s sync failed (%d)\n", 199 pr_err("%s: %s sync failed (%d)\n",
211 part->name, efx_mtd->name, rc); 200 part->name, part->dev_type_name, rc);
212} 201}
213 202
214static void efx_mtd_remove_partition(struct efx_mtd_partition *part) 203static void efx_mtd_remove_partition(struct efx_mtd_partition *part)
@@ -222,86 +211,84 @@ static void efx_mtd_remove_partition(struct efx_mtd_partition *part)
222 ssleep(1); 211 ssleep(1);
223 } 212 }
224 WARN_ON(rc); 213 WARN_ON(rc);
214 list_del(&part->node);
225} 215}
226 216
227static void efx_mtd_remove_device(struct efx_mtd *efx_mtd) 217static void efx_mtd_rename_partition(struct efx_mtd_partition *part)
228{
229 struct efx_mtd_partition *part;
230
231 efx_for_each_partition(part, efx_mtd)
232 efx_mtd_remove_partition(part);
233 list_del(&efx_mtd->node);
234 kfree(efx_mtd);
235}
236
237static void efx_mtd_rename_device(struct efx_mtd *efx_mtd)
238{ 218{
239 struct efx_mtd_partition *part; 219 struct efx_nic *efx = part->mtd.priv;
240 220
241 efx_for_each_partition(part, efx_mtd) 221 if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
242 if (efx_nic_rev(efx_mtd->efx) >= EFX_REV_SIENA_A0) 222 snprintf(part->name, sizeof(part->name), "%s %s:%02x",
243 snprintf(part->name, sizeof(part->name), 223 efx->name, part->type_name, part->mcdi.fw_subtype);
244 "%s %s:%02x", efx_mtd->efx->name, 224 else
245 part->type_name, part->mcdi.fw_subtype); 225 snprintf(part->name, sizeof(part->name), "%s %s",
246 else 226 efx->name, part->type_name);
247 snprintf(part->name, sizeof(part->name),
248 "%s %s", efx_mtd->efx->name,
249 part->type_name);
250} 227}
251 228
252static int efx_mtd_probe_device(struct efx_nic *efx, struct efx_mtd *efx_mtd) 229static int efx_mtd_add(struct efx_nic *efx,
230 struct efx_mtd_partition *parts, size_t n_parts)
253{ 231{
254 struct efx_mtd_partition *part; 232 struct efx_mtd_partition *part;
233 size_t i;
255 234
256 efx_mtd->efx = efx; 235 for (i = 0; i < n_parts; i++) {
236 part = &parts[i];
257 237
258 efx_mtd_rename_device(efx_mtd);
259
260 efx_for_each_partition(part, efx_mtd) {
261 part->mtd.writesize = 1; 238 part->mtd.writesize = 1;
262 239
263 part->mtd.owner = THIS_MODULE; 240 part->mtd.owner = THIS_MODULE;
264 part->mtd.priv = efx_mtd; 241 part->mtd.priv = efx;
265 part->mtd.name = part->name; 242 part->mtd.name = part->name;
266 part->mtd._erase = efx_mtd_erase; 243 part->mtd._erase = efx_mtd_erase;
267 part->mtd._read = efx_mtd->ops->read; 244 part->mtd._read = efx->mtd_ops->read;
268 part->mtd._write = efx_mtd->ops->write; 245 part->mtd._write = efx->mtd_ops->write;
269 part->mtd._sync = efx_mtd_sync; 246 part->mtd._sync = efx_mtd_sync;
270 247
248 efx_mtd_rename_partition(part);
249
271 if (mtd_device_register(&part->mtd, NULL, 0)) 250 if (mtd_device_register(&part->mtd, NULL, 0))
272 goto fail; 251 goto fail;
252
253 /* Add to list in order - efx_mtd_remove() depends on this */
254 list_add_tail(&part->node, &efx->mtd_list);
273 } 255 }
274 256
275 list_add(&efx_mtd->node, &efx->mtd_list);
276 return 0; 257 return 0;
277 258
278fail: 259fail:
279 while (part != &efx_mtd->part[0]) { 260 while (i--)
280 --part; 261 efx_mtd_remove_partition(&parts[i]);
281 efx_mtd_remove_partition(part);
282 }
283 /* Failure is unlikely here, but probably means we're out of memory */ 262 /* Failure is unlikely here, but probably means we're out of memory */
284 return -ENOMEM; 263 return -ENOMEM;
285} 264}
286 265
287void efx_mtd_remove(struct efx_nic *efx) 266void efx_mtd_remove(struct efx_nic *efx)
288{ 267{
289 struct efx_mtd *efx_mtd, *next; 268 struct efx_mtd_partition *parts, *part, *next;
290 269
291 WARN_ON(efx_dev_registered(efx)); 270 WARN_ON(efx_dev_registered(efx));
292 271
293 list_for_each_entry_safe(efx_mtd, next, &efx->mtd_list, node) 272 if (list_empty(&efx->mtd_list))
294 efx_mtd_remove_device(efx_mtd); 273 return;
274
275 parts = list_first_entry(&efx->mtd_list, struct efx_mtd_partition,
276 node);
277
278 list_for_each_entry_safe(part, next, &efx->mtd_list, node)
279 efx_mtd_remove_partition(part);
280
281 kfree(parts);
295} 282}
296 283
297void efx_mtd_rename(struct efx_nic *efx) 284void efx_mtd_rename(struct efx_nic *efx)
298{ 285{
299 struct efx_mtd *efx_mtd; 286 struct efx_mtd_partition *part;
300 287
301 ASSERT_RTNL(); 288 ASSERT_RTNL();
302 289
303 list_for_each_entry(efx_mtd, &efx->mtd_list, node) 290 list_for_each_entry(part, &efx->mtd_list, node)
304 efx_mtd_rename_device(efx_mtd); 291 efx_mtd_rename_partition(part);
305} 292}
306 293
307int efx_mtd_probe(struct efx_nic *efx) 294int efx_mtd_probe(struct efx_nic *efx)
@@ -318,17 +305,15 @@ static int falcon_mtd_read(struct mtd_info *mtd, loff_t start,
318 size_t len, size_t *retlen, u8 *buffer) 305 size_t len, size_t *retlen, u8 *buffer)
319{ 306{
320 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 307 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
321 struct efx_mtd *efx_mtd = mtd->priv; 308 struct efx_nic *efx = mtd->priv;
322 const struct falcon_spi_device *spi = efx_mtd->spi;
323 struct efx_nic *efx = efx_mtd->efx;
324 struct falcon_nic_data *nic_data = efx->nic_data; 309 struct falcon_nic_data *nic_data = efx->nic_data;
325 int rc; 310 int rc;
326 311
327 rc = mutex_lock_interruptible(&nic_data->spi_lock); 312 rc = mutex_lock_interruptible(&nic_data->spi_lock);
328 if (rc) 313 if (rc)
329 return rc; 314 return rc;
330 rc = falcon_spi_read(efx, spi, part->offset + start, len, 315 rc = falcon_spi_read(efx, part->falcon.spi, part->falcon.offset + start,
331 retlen, buffer); 316 len, retlen, buffer);
332 mutex_unlock(&nic_data->spi_lock); 317 mutex_unlock(&nic_data->spi_lock);
333 return rc; 318 return rc;
334} 319}
@@ -336,15 +321,14 @@ static int falcon_mtd_read(struct mtd_info *mtd, loff_t start,
336static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len) 321static int falcon_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
337{ 322{
338 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 323 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
339 struct efx_mtd *efx_mtd = mtd->priv; 324 struct efx_nic *efx = mtd->priv;
340 struct efx_nic *efx = efx_mtd->efx;
341 struct falcon_nic_data *nic_data = efx->nic_data; 325 struct falcon_nic_data *nic_data = efx->nic_data;
342 int rc; 326 int rc;
343 327
344 rc = mutex_lock_interruptible(&nic_data->spi_lock); 328 rc = mutex_lock_interruptible(&nic_data->spi_lock);
345 if (rc) 329 if (rc)
346 return rc; 330 return rc;
347 rc = falcon_spi_erase(part, part->offset + start, len); 331 rc = falcon_spi_erase(part, part->falcon.offset + start, len);
348 mutex_unlock(&nic_data->spi_lock); 332 mutex_unlock(&nic_data->spi_lock);
349 return rc; 333 return rc;
350} 334}
@@ -353,17 +337,15 @@ static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
353 size_t len, size_t *retlen, const u8 *buffer) 337 size_t len, size_t *retlen, const u8 *buffer)
354{ 338{
355 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 339 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
356 struct efx_mtd *efx_mtd = mtd->priv; 340 struct efx_nic *efx = mtd->priv;
357 const struct falcon_spi_device *spi = efx_mtd->spi;
358 struct efx_nic *efx = efx_mtd->efx;
359 struct falcon_nic_data *nic_data = efx->nic_data; 341 struct falcon_nic_data *nic_data = efx->nic_data;
360 int rc; 342 int rc;
361 343
362 rc = mutex_lock_interruptible(&nic_data->spi_lock); 344 rc = mutex_lock_interruptible(&nic_data->spi_lock);
363 if (rc) 345 if (rc)
364 return rc; 346 return rc;
365 rc = falcon_spi_write(efx, spi, part->offset + start, len, 347 rc = falcon_spi_write(efx, part->falcon.spi,
366 retlen, buffer); 348 part->falcon.offset + start, len, retlen, buffer);
367 mutex_unlock(&nic_data->spi_lock); 349 mutex_unlock(&nic_data->spi_lock);
368 return rc; 350 return rc;
369} 351}
@@ -371,8 +353,7 @@ static int falcon_mtd_write(struct mtd_info *mtd, loff_t start,
371static int falcon_mtd_sync(struct mtd_info *mtd) 353static int falcon_mtd_sync(struct mtd_info *mtd)
372{ 354{
373 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 355 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
374 struct efx_mtd *efx_mtd = mtd->priv; 356 struct efx_nic *efx = mtd->priv;
375 struct efx_nic *efx = efx_mtd->efx;
376 struct falcon_nic_data *nic_data = efx->nic_data; 357 struct falcon_nic_data *nic_data = efx->nic_data;
377 int rc; 358 int rc;
378 359
@@ -392,66 +373,50 @@ static const struct efx_mtd_ops falcon_mtd_ops = {
392static int falcon_mtd_probe(struct efx_nic *efx) 373static int falcon_mtd_probe(struct efx_nic *efx)
393{ 374{
394 struct falcon_nic_data *nic_data = efx->nic_data; 375 struct falcon_nic_data *nic_data = efx->nic_data;
376 struct efx_mtd_partition *parts;
395 struct falcon_spi_device *spi; 377 struct falcon_spi_device *spi;
396 struct efx_mtd *efx_mtd; 378 size_t n_parts;
397 int rc = -ENODEV; 379 int rc = -ENODEV;
398 380
399 ASSERT_RTNL(); 381 ASSERT_RTNL();
400 382
383 efx->mtd_ops = &falcon_mtd_ops;
384
385 /* Allocate space for maximum number of partitions */
386 parts = kcalloc(2, sizeof(*parts), GFP_KERNEL);
387 n_parts = 0;
388
401 spi = &nic_data->spi_flash; 389 spi = &nic_data->spi_flash;
402 if (falcon_spi_present(spi) && spi->size > FALCON_FLASH_BOOTCODE_START) { 390 if (falcon_spi_present(spi) && spi->size > FALCON_FLASH_BOOTCODE_START) {
403 efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), 391 parts[n_parts].falcon.spi = spi;
404 GFP_KERNEL); 392 parts[n_parts].falcon.offset = FALCON_FLASH_BOOTCODE_START;
405 if (!efx_mtd) 393 parts[n_parts].dev_type_name = "flash";
406 return -ENOMEM; 394 parts[n_parts].type_name = "sfc_flash_bootrom";
407 395 parts[n_parts].mtd.type = MTD_NORFLASH;
408 efx_mtd->spi = spi; 396 parts[n_parts].mtd.flags = MTD_CAP_NORFLASH;
409 efx_mtd->name = "flash"; 397 parts[n_parts].mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
410 efx_mtd->ops = &falcon_mtd_ops; 398 parts[n_parts].mtd.erasesize = spi->erase_size;
411 399 n_parts++;
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 } 400 }
426 401
427 spi = &nic_data->spi_eeprom; 402 spi = &nic_data->spi_eeprom;
428 if (falcon_spi_present(spi) && spi->size > FALCON_EEPROM_BOOTCONFIG_START) { 403 if (falcon_spi_present(spi) && spi->size > FALCON_EEPROM_BOOTCONFIG_START) {
429 efx_mtd = kzalloc(sizeof(*efx_mtd) + sizeof(efx_mtd->part[0]), 404 parts[n_parts].falcon.spi = spi;
430 GFP_KERNEL); 405 parts[n_parts].falcon.offset = FALCON_EEPROM_BOOTCONFIG_START;
431 if (!efx_mtd) 406 parts[n_parts].dev_type_name = "EEPROM";
432 return -ENOMEM; 407 parts[n_parts].type_name = "sfc_bootconfig";
433 408 parts[n_parts].mtd.type = MTD_RAM;
434 efx_mtd->spi = spi; 409 parts[n_parts].mtd.flags = MTD_CAP_RAM;
435 efx_mtd->name = "EEPROM"; 410 parts[n_parts].mtd.size =
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, FALCON_EEPROM_BOOTCONFIG_END) - 411 min(spi->size, FALCON_EEPROM_BOOTCONFIG_END) -
443 FALCON_EEPROM_BOOTCONFIG_START; 412 FALCON_EEPROM_BOOTCONFIG_START;
444 efx_mtd->part[0].mtd.erasesize = spi->erase_size; 413 parts[n_parts].mtd.erasesize = spi->erase_size;
445 efx_mtd->part[0].offset = FALCON_EEPROM_BOOTCONFIG_START; 414 n_parts++;
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
417 rc = efx_mtd_add(efx, parts, n_parts);
418 if (rc)
419 kfree(parts);
455 return rc; 420 return rc;
456} 421}
457 422
@@ -461,8 +426,7 @@ static int siena_mtd_read(struct mtd_info *mtd, loff_t start,
461 size_t len, size_t *retlen, u8 *buffer) 426 size_t len, size_t *retlen, u8 *buffer)
462{ 427{
463 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 428 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
464 struct efx_mtd *efx_mtd = mtd->priv; 429 struct efx_nic *efx = mtd->priv;
465 struct efx_nic *efx = efx_mtd->efx;
466 loff_t offset = start; 430 loff_t offset = start;
467 loff_t end = min_t(loff_t, start + len, mtd->size); 431 loff_t end = min_t(loff_t, start + len, mtd->size);
468 size_t chunk; 432 size_t chunk;
@@ -485,8 +449,7 @@ out:
485static int siena_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len) 449static int siena_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
486{ 450{
487 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 451 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
488 struct efx_mtd *efx_mtd = mtd->priv; 452 struct efx_nic *efx = mtd->priv;
489 struct efx_nic *efx = efx_mtd->efx;
490 loff_t offset = start & ~((loff_t)(mtd->erasesize - 1)); 453 loff_t offset = start & ~((loff_t)(mtd->erasesize - 1));
491 loff_t end = min_t(loff_t, start + len, mtd->size); 454 loff_t end = min_t(loff_t, start + len, mtd->size);
492 size_t chunk = part->mtd.erasesize; 455 size_t chunk = part->mtd.erasesize;
@@ -517,8 +480,7 @@ static int siena_mtd_write(struct mtd_info *mtd, loff_t start,
517 size_t len, size_t *retlen, const u8 *buffer) 480 size_t len, size_t *retlen, const u8 *buffer)
518{ 481{
519 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 482 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
520 struct efx_mtd *efx_mtd = mtd->priv; 483 struct efx_nic *efx = mtd->priv;
521 struct efx_nic *efx = efx_mtd->efx;
522 loff_t offset = start; 484 loff_t offset = start;
523 loff_t end = min_t(loff_t, start + len, mtd->size); 485 loff_t end = min_t(loff_t, start + len, mtd->size);
524 size_t chunk; 486 size_t chunk;
@@ -548,8 +510,7 @@ out:
548static int siena_mtd_sync(struct mtd_info *mtd) 510static int siena_mtd_sync(struct mtd_info *mtd)
549{ 511{
550 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd); 512 struct efx_mtd_partition *part = to_efx_mtd_partition(mtd);
551 struct efx_mtd *efx_mtd = mtd->priv; 513 struct efx_nic *efx = mtd->priv;
552 struct efx_nic *efx = efx_mtd->efx;
553 int rc = 0; 514 int rc = 0;
554 515
555 if (part->mcdi.updating) { 516 if (part->mcdi.updating) {
@@ -589,11 +550,9 @@ static const struct siena_nvram_type_info siena_nvram_types[] = {
589}; 550};
590 551
591static int siena_mtd_probe_partition(struct efx_nic *efx, 552static int siena_mtd_probe_partition(struct efx_nic *efx,
592 struct efx_mtd *efx_mtd, 553 struct efx_mtd_partition *part,
593 unsigned int part_id,
594 unsigned int type) 554 unsigned int type)
595{ 555{
596 struct efx_mtd_partition *part = &efx_mtd->part[part_id];
597 const struct siena_nvram_type_info *info; 556 const struct siena_nvram_type_info *info;
598 size_t size, erase_size; 557 size_t size, erase_size;
599 bool protected; 558 bool protected;
@@ -615,6 +574,7 @@ static int siena_mtd_probe_partition(struct efx_nic *efx,
615 return -ENODEV; /* hide it */ 574 return -ENODEV; /* hide it */
616 575
617 part->mcdi.nvram_type = type; 576 part->mcdi.nvram_type = type;
577 part->dev_type_name = "Siena NVRAM manager";
618 part->type_name = info->name; 578 part->type_name = info->name;
619 579
620 part->mtd.type = MTD_NORFLASH; 580 part->mtd.type = MTD_NORFLASH;
@@ -626,55 +586,54 @@ static int siena_mtd_probe_partition(struct efx_nic *efx,
626} 586}
627 587
628static int siena_mtd_get_fw_subtypes(struct efx_nic *efx, 588static int siena_mtd_get_fw_subtypes(struct efx_nic *efx,
629 struct efx_mtd *efx_mtd) 589 struct efx_mtd_partition *parts,
590 size_t n_parts)
630{ 591{
631 struct efx_mtd_partition *part;
632 uint16_t fw_subtype_list[ 592 uint16_t fw_subtype_list[
633 MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM]; 593 MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM];
594 size_t i;
634 int rc; 595 int rc;
635 596
636 rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list, NULL); 597 rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list, NULL);
637 if (rc) 598 if (rc)
638 return rc; 599 return rc;
639 600
640 efx_for_each_partition(part, efx_mtd) 601 for (i = 0; i < n_parts; i++)
641 part->mcdi.fw_subtype = fw_subtype_list[part->mcdi.nvram_type]; 602 parts[i].mcdi.fw_subtype =
603 fw_subtype_list[parts[i].mcdi.nvram_type];
642 604
643 return 0; 605 return 0;
644} 606}
645 607
646static int siena_mtd_probe(struct efx_nic *efx) 608static int siena_mtd_probe(struct efx_nic *efx)
647{ 609{
648 struct efx_mtd *efx_mtd; 610 struct efx_mtd_partition *parts;
649 int rc = -ENODEV;
650 u32 nvram_types; 611 u32 nvram_types;
651 unsigned int type; 612 unsigned int type;
613 size_t n_parts;
614 int rc;
652 615
653 ASSERT_RTNL(); 616 ASSERT_RTNL();
654 617
618 efx->mtd_ops = &siena_mtd_ops;
619
655 rc = efx_mcdi_nvram_types(efx, &nvram_types); 620 rc = efx_mcdi_nvram_types(efx, &nvram_types);
656 if (rc) 621 if (rc)
657 return rc; 622 return rc;
658 623
659 efx_mtd = kzalloc(sizeof(*efx_mtd) + 624 parts = kcalloc(hweight32(nvram_types), sizeof(*parts), GFP_KERNEL);
660 hweight32(nvram_types) * sizeof(efx_mtd->part[0]), 625 if (!parts)
661 GFP_KERNEL);
662 if (!efx_mtd)
663 return -ENOMEM; 626 return -ENOMEM;
664 627
665 efx_mtd->name = "Siena NVRAM manager";
666
667 efx_mtd->ops = &siena_mtd_ops;
668
669 type = 0; 628 type = 0;
670 efx_mtd->n_parts = 0; 629 n_parts = 0;
671 630
672 while (nvram_types != 0) { 631 while (nvram_types != 0) {
673 if (nvram_types & 1) { 632 if (nvram_types & 1) {
674 rc = siena_mtd_probe_partition(efx, efx_mtd, 633 rc = siena_mtd_probe_partition(efx, &parts[n_parts],
675 efx_mtd->n_parts, type); 634 type);
676 if (rc == 0) 635 if (rc == 0)
677 efx_mtd->n_parts++; 636 n_parts++;
678 else if (rc != -ENODEV) 637 else if (rc != -ENODEV)
679 goto fail; 638 goto fail;
680 } 639 }
@@ -682,14 +641,14 @@ static int siena_mtd_probe(struct efx_nic *efx)
682 nvram_types >>= 1; 641 nvram_types >>= 1;
683 } 642 }
684 643
685 rc = siena_mtd_get_fw_subtypes(efx, efx_mtd); 644 rc = siena_mtd_get_fw_subtypes(efx, parts, n_parts);
686 if (rc) 645 if (rc)
687 goto fail; 646 goto fail;
688 647
689 rc = efx_mtd_probe_device(efx, efx_mtd); 648 rc = efx_mtd_add(efx, parts, n_parts);
690fail: 649fail:
691 if (rc) 650 if (rc)
692 kfree(efx_mtd); 651 kfree(parts);
693 return rc; 652 return rc;
694} 653}
695 654
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 555dd013bda7..958ede16077a 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -868,6 +868,7 @@ struct efx_nic {
868 struct delayed_work selftest_work; 868 struct delayed_work selftest_work;
869 869
870#ifdef CONFIG_SFC_MTD 870#ifdef CONFIG_SFC_MTD
871 const struct efx_mtd_ops *mtd_ops;
871 struct list_head mtd_list; 872 struct list_head mtd_list;
872#endif 873#endif
873 874