mtd/drivers/mtd/maps pcmciamtd.c,1.36,1.37
spse at infradead.org
spse at infradead.org
Sun Oct 27 11:07:12 EST 2002
Update of /home/cvs/mtd/drivers/mtd/maps
In directory phoenix.infradead.org:/tmp/cvs-serv21471
Modified Files:
pcmciamtd.c
Log Message:
Remove struct list_head and use dev_link_t already in struct pcmciamtd_dev
Add dev_node_t into pcmciamtd_dev and set dev_name correctly
Remove cardsize from pcmciamtd_dev, use mtd_info->size instead
Clear DEV_PRESENT when card is removed so read/write functions can silently
fail and then the chip driver can time out appropiately
When card is removed unexpectedly, call del_mtd_device outside of
pcmciamtd_release so it is not called from inside a timer
Dont destory_map / free device struct until the module is removed so
any holders still have a vaild mtd_info struct
Index: pcmciamtd.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/maps/pcmciamtd.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- pcmciamtd.c 14 Oct 2002 18:49:12 -0000 1.36
+++ pcmciamtd.c 27 Oct 2002 16:07:10 -0000 1.37
@@ -41,9 +41,9 @@
static const int debug = 0;
#endif
-#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg)
+#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg)
#define DRIVER_DESC "PCMCIA Flash memory card driver"
@@ -53,21 +53,20 @@
#define MAX_PCMCIA_ADDR 0x4000000
struct pcmciamtd_dev {
- struct list_head list;
dev_link_t link; /* PCMCIA link */
+ dev_node_t node; /* device node */
caddr_t win_base; /* ioremapped address of PCMCIA window */
unsigned int win_size; /* size of window */
- unsigned int cardsize; /* size of whole card */
unsigned int offset; /* offset into card the window currently points at */
struct map_info pcmcia_map;
struct mtd_info *mtd_info;
- u8 vpp;
+ int vpp;
char mtd_name[sizeof(struct cistpl_vers_1_t)];
};
static dev_info_t dev_info = "pcmciamtd";
-static LIST_HEAD(dev_list);
+static dev_link_t *dev_list;
/* Module parameters */
@@ -123,6 +122,11 @@
memreq_t mrq;
int ret;
+ if(!(dev->link.state & DEV_PRESENT)) {
+ DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
+ return 0;
+ }
+
mrq.CardOffset = to & ~(dev->win_size-1);
if(mrq.CardOffset != dev->offset) {
DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
@@ -245,11 +249,16 @@
/* read/write{8,16} copy_{from,to} routines with direct access */
+#define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
+
static u8 pcmcia_read8(struct map_info *map, unsigned long ofs)
{
caddr_t win_base = (caddr_t)map->map_priv_2;
u8 d;
+ if(DEV_REMOVED(map))
+ return 0;
+
d = readb(win_base + ofs);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d);
return d;
@@ -261,6 +270,9 @@
caddr_t win_base = (caddr_t)map->map_priv_2;
u16 d;
+ if(DEV_REMOVED(map))
+ return 0;
+
d = readw(win_base + ofs);
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d);
return d;
@@ -271,6 +283,9 @@
{
caddr_t win_base = (caddr_t)map->map_priv_2;
+ if(DEV_REMOVED(map))
+ return;
+
DEBUG(3, "to = %p from = %lu len = %u", to, from, len);
memcpy_fromio(to, win_base + from, len);
}
@@ -280,6 +295,9 @@
{
caddr_t win_base = (caddr_t)map->map_priv_2;
+ if(DEV_REMOVED(map))
+ return;
+
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, win_base + adr, d);
writeb(d, win_base + adr);
}
@@ -289,6 +307,9 @@
{
caddr_t win_base = (caddr_t)map->map_priv_2;
+ if(DEV_REMOVED(map))
+ return;
+
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, win_base + adr, d);
writew(d, win_base + adr);
}
@@ -298,6 +319,9 @@
{
caddr_t win_base = (caddr_t)map->map_priv_2;
+ if(DEV_REMOVED(map))
+ return;
+
DEBUG(3, "to = %lu from = %p len = %u", to, from, len);
memcpy_toio(win_base + to, from, len);
}
@@ -330,40 +354,18 @@
static void pcmciamtd_release(u_long arg)
{
dev_link_t *link = (dev_link_t *)arg;
- struct pcmciamtd_dev *dev = NULL;
- int ret;
- struct list_head *temp1, *temp2;
+ struct pcmciamtd_dev *dev = link->priv;
DEBUG(3, "link = 0x%p", link);
- /* Find device in list */
- list_for_each_safe(temp1, temp2, &dev_list) {
- dev = list_entry(temp1, struct pcmciamtd_dev, list);
- if(link == &dev->link)
- break;
- }
- if(link != &dev->link) {
- DEBUG(1, "Cant find %p in dev_list", link);
- return;
- }
- if(dev) {
- if(dev->mtd_info) {
- del_mtd_device(dev->mtd_info);
- dev->mtd_info = NULL;
- MOD_DEC_USE_COUNT;
- }
- if (link->win) {
- if(dev->win_base) {
- iounmap(dev->win_base);
- dev->win_base = NULL;
- }
- CardServices(ReleaseWindow, link->win);
+ if (link->win) {
+ if(dev->win_base) {
+ iounmap(dev->win_base);
+ dev->win_base = NULL;
}
- ret = CardServices(ReleaseConfiguration, link->handle);
- if(ret != CS_SUCCESS)
- cs_error(link->handle, ReleaseConfiguration, ret);
-
+ CardServices(ReleaseWindow, link->win);
}
+ CardServices(ReleaseConfiguration, link->handle);
link->state &= ~DEV_CONFIG;
}
@@ -472,7 +474,6 @@
if(force_size) {
dev->pcmcia_map.size = force_size << 20;
DEBUG(2, "size forced to %dM", force_size);
-
}
if(buswidth) {
@@ -586,9 +587,8 @@
}
DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
dev, req.Base, dev->win_base, req.Size);
- dev->cardsize = 0;
- dev->offset = 0;
+ dev->offset = 0;
dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
@@ -620,9 +620,6 @@
cs_error(link->handle, RequestConfiguration, ret);
}
- link->dev = NULL;
- link->state &= ~DEV_CONFIG_PENDING;
-
if(mem_type == 1) {
mtd = do_map_probe("map_ram", &dev->pcmcia_map);
} else if(mem_type == 2) {
@@ -646,7 +643,6 @@
dev->mtd_info = mtd;
mtd->module = THIS_MODULE;
- dev->cardsize = mtd->size;
if(new_name) {
int size = 0;
@@ -655,19 +651,19 @@
size */
if(mtd->size < 1048576) { /* <1MB in size, show size in K */
size = mtd->size >> 10;
- unit = 'K';
+ unit = 'K';
} else {
size = mtd->size >> 20;
unit = 'M';
}
- sprintf(mtd->name, "%d%cB %s", size, unit, "PCMCIA Memory card");
+ snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%cB %s", size, unit, "PCMCIA Memory card");
}
/* If the memory found is fits completely into the mapped PCMCIA window,
use the faster non-remapping read/write functions */
- if(dev->cardsize <= dev->win_size) {
+ if(mtd->size <= dev->win_size) {
DEBUG(1, "Using non remapping memory functions");
-
+ dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
dev->pcmcia_map.read8 = pcmcia_read8;
dev->pcmcia_map.read16 = pcmcia_read16;
@@ -677,16 +673,17 @@
dev->pcmcia_map.copy_to = pcmcia_copy_to;
}
- MOD_INC_USE_COUNT;
if(add_mtd_device(mtd)) {
+ map_destroy(mtd);
dev->mtd_info = NULL;
- MOD_DEC_USE_COUNT;
err("Couldnt register MTD device");
pcmciamtd_release((u_long)link);
return;
}
- DEBUG(1, "mtd added @ %p mtd->priv = %p", mtd, mtd->priv);
-
+ snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
+ info("mtd%d: %s", mtd->index, mtd->name);
+ link->state &= ~DEV_CONFIG_PENDING;
+ link->dev = &dev->node;
return;
cs_failed:
@@ -713,8 +710,14 @@
case CS_EVENT_CARD_REMOVAL:
DEBUG(2, "EVENT_CARD_REMOVAL");
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
+ if (link->state & DEV_CONFIG) {
+ struct pcmciamtd_dev *dev = link->priv;
+ if(dev->mtd_info) {
+ del_mtd_device(dev->mtd_info);
+ info("mtd%d: Removed", dev->mtd_info->index);
+ }
mod_timer(&link->release, jiffies + HZ/20);
+ }
break;
case CS_EVENT_CARD_INSERTION:
DEBUG(2, "EVENT_CARD_INSERTION");
@@ -752,47 +755,23 @@
static void pcmciamtd_detach(dev_link_t *link)
{
- int ret;
- struct pcmciamtd_dev *dev = NULL;
- struct list_head *temp1, *temp2;
-
DEBUG(3, "link=0x%p", link);
- /* Find device in list */
- list_for_each_safe(temp1, temp2, &dev_list) {
- dev = list_entry(temp1, struct pcmciamtd_dev, list);
- if(link == &dev->link)
- break;
- }
- if(link != &dev->link) {
- DEBUG(1, "Cant find %p in dev_list", link);
- return;
- }
-
del_timer(&link->release);
- if(!dev) {
- DEBUG(3, "dev is NULL");
- return;
- }
-
- if (link->state & DEV_CONFIG) {
- //pcmciamtd_release((u_long)link);
- DEBUG(3, "DEV_CONFIG set");
- link->state |= DEV_STALE_LINK;
- return;
+ if(link->state & DEV_CONFIG) {
+ pcmciamtd_release((u_long)link);
}
if (link->handle) {
+ int ret;
DEBUG(2, "Deregistering with card services");
ret = CardServices(DeregisterClient, link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
}
- DEBUG(3, "Freeing dev (%p)", dev);
- list_del(&dev->list);
- link->priv = NULL;
- kfree(dev);
+
+ link->state |= DEV_STALE_LINK;
}
@@ -814,7 +793,8 @@
DEBUG(1, "dev=0x%p", dev);
memset(dev, 0, sizeof(*dev));
- link = &dev->link; link->priv = dev;
+ link = &dev->link;
+ link->priv = dev;
link->release.function = &pcmciamtd_release;
link->release.data = (u_long)link;
@@ -822,7 +802,8 @@
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY;
- list_add(&dev->list, &dev_list);
+ link->next = dev_list;
+ dev_list = link;
/* Register with Card Services */
client_reg.dev_info = &dev_info;
@@ -841,7 +822,7 @@
pcmciamtd_detach(link);
return NULL;
}
-
+ DEBUG(2, "link = %p", link);
return link;
}
@@ -876,15 +857,35 @@
static void __exit exit_pcmciamtd(void)
{
- struct list_head *temp1, *temp2;
-
DEBUG(1, DRIVER_DESC " unloading");
unregister_pccard_driver(&dev_info);
- list_for_each_safe(temp1, temp2, &dev_list) {
- dev_link_t *link = &list_entry(temp1, struct pcmciamtd_dev, list)->link;
- if (link && (link->state & DEV_CONFIG)) {
- pcmciamtd_release((u_long)link);
- pcmciamtd_detach(link);
+
+ while(dev_list) {
+ dev_link_t *link = dev_list;
+
+ dev_list = link->next;
+ if (link) {
+ struct pcmciamtd_dev *dev = link->priv;
+
+ if(dev) {
+ if(link->state & DEV_PRESENT) {
+ if (!(link->state & DEV_STALE_LINK)) {
+ pcmciamtd_detach(link);
+ }
+ link->state &= ~DEV_PRESENT;
+ if(dev->mtd_info) {
+ del_mtd_device(dev->mtd_info);
+ info("mtd%d: Removed",
+ dev->mtd_info->index);
+ }
+ }
+ if(dev->mtd_info) {
+ DEBUG(2, "Destroying map for mtd%d",
+ dev->mtd_info->index);
+ map_destroy(dev->mtd_info);
+ }
+ kfree(dev);
+ }
}
}
}
More information about the linux-mtd-cvs
mailing list