0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/mtd/mtd.h>
0010 #include <linux/slab.h>
0011 #include <linux/rtnetlink.h>
0012
0013 #include "net_driver.h"
0014 #include "efx.h"
0015
0016 #define to_ef4_mtd_partition(mtd) \
0017 container_of(mtd, struct ef4_mtd_partition, mtd)
0018
0019
0020
0021 static int ef4_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
0022 {
0023 struct ef4_nic *efx = mtd->priv;
0024
0025 return efx->type->mtd_erase(mtd, erase->addr, erase->len);
0026 }
0027
0028 static void ef4_mtd_sync(struct mtd_info *mtd)
0029 {
0030 struct ef4_mtd_partition *part = to_ef4_mtd_partition(mtd);
0031 struct ef4_nic *efx = mtd->priv;
0032 int rc;
0033
0034 rc = efx->type->mtd_sync(mtd);
0035 if (rc)
0036 pr_err("%s: %s sync failed (%d)\n",
0037 part->name, part->dev_type_name, rc);
0038 }
0039
0040 static void ef4_mtd_remove_partition(struct ef4_mtd_partition *part)
0041 {
0042 int rc;
0043
0044 for (;;) {
0045 rc = mtd_device_unregister(&part->mtd);
0046 if (rc != -EBUSY)
0047 break;
0048 ssleep(1);
0049 }
0050 WARN_ON(rc);
0051 list_del(&part->node);
0052 }
0053
0054 int ef4_mtd_add(struct ef4_nic *efx, struct ef4_mtd_partition *parts,
0055 size_t n_parts, size_t sizeof_part)
0056 {
0057 struct ef4_mtd_partition *part;
0058 size_t i;
0059
0060 for (i = 0; i < n_parts; i++) {
0061 part = (struct ef4_mtd_partition *)((char *)parts +
0062 i * sizeof_part);
0063
0064 part->mtd.writesize = 1;
0065
0066 part->mtd.owner = THIS_MODULE;
0067 part->mtd.priv = efx;
0068 part->mtd.name = part->name;
0069 part->mtd._erase = ef4_mtd_erase;
0070 part->mtd._read = efx->type->mtd_read;
0071 part->mtd._write = efx->type->mtd_write;
0072 part->mtd._sync = ef4_mtd_sync;
0073
0074 efx->type->mtd_rename(part);
0075
0076 if (mtd_device_register(&part->mtd, NULL, 0))
0077 goto fail;
0078
0079
0080 list_add_tail(&part->node, &efx->mtd_list);
0081 }
0082
0083 return 0;
0084
0085 fail:
0086 while (i--) {
0087 part = (struct ef4_mtd_partition *)((char *)parts +
0088 i * sizeof_part);
0089 ef4_mtd_remove_partition(part);
0090 }
0091
0092 return -ENOMEM;
0093 }
0094
0095 void ef4_mtd_remove(struct ef4_nic *efx)
0096 {
0097 struct ef4_mtd_partition *parts, *part, *next;
0098
0099 WARN_ON(ef4_dev_registered(efx));
0100
0101 if (list_empty(&efx->mtd_list))
0102 return;
0103
0104 parts = list_first_entry(&efx->mtd_list, struct ef4_mtd_partition,
0105 node);
0106
0107 list_for_each_entry_safe(part, next, &efx->mtd_list, node)
0108 ef4_mtd_remove_partition(part);
0109
0110 kfree(parts);
0111 }
0112
0113 void ef4_mtd_rename(struct ef4_nic *efx)
0114 {
0115 struct ef4_mtd_partition *part;
0116
0117 ASSERT_RTNL();
0118
0119 list_for_each_entry(part, &efx->mtd_list, node)
0120 efx->type->mtd_rename(part);
0121 }