summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-04-08 20:10:21 +0200
committerDominik Brodowski <linux@dominikbrodowski.net>2010-04-11 14:38:31 +0200
commitb1095afe6fd6ea4c0d9e75489b955f898d6617d9 (patch)
tree65777d0feebe7e5710fdfa4419ce52d493992cf8
parent509b0865fbd8ab6c820397706dde980c1c285538 (diff)
downloadlinux-3.10-b1095afe6fd6ea4c0d9e75489b955f898d6617d9.tar.gz
linux-3.10-b1095afe6fd6ea4c0d9e75489b955f898d6617d9.tar.bz2
linux-3.10-b1095afe6fd6ea4c0d9e75489b955f898d6617d9.zip
pcmcia: re-start on MFC override
If there are changes to the number of socket devices, we need to start over in all cases: else pcmcia_request_configuration() might get confused. Reported-by: Alexander Kurz <linux@kbdbabel.org> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--drivers/pcmcia/ds.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index cb6036d89e5..4014cf8e4a2 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -687,12 +687,10 @@ static void pcmcia_requery(struct pcmcia_socket *s)
new_funcs = mfc.nfn;
else
new_funcs = 1;
- if (old_funcs > new_funcs) {
+ if (old_funcs != new_funcs) {
+ /* we need to re-start */
pcmcia_card_remove(s, NULL);
pcmcia_card_add(s);
- } else if (new_funcs > old_funcs) {
- s->functions = new_funcs;
- pcmcia_device_add(s, 1);
}
}
@@ -728,6 +726,8 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
struct pcmcia_socket *s = dev->socket;
const struct firmware *fw;
int ret = -ENOMEM;
+ cistpl_longlink_mfc_t mfc;
+ int old_funcs, new_funcs = 1;
if (!filename)
return -EINVAL;
@@ -750,6 +750,14 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
goto release;
}
+ /* we need to re-start if the number of functions changed */
+ old_funcs = s->functions;
+ if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC,
+ &mfc))
+ new_funcs = mfc.nfn;
+
+ if (old_funcs != new_funcs)
+ ret = -EBUSY;
/* update information */
pcmcia_device_query(dev);
@@ -858,10 +866,8 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
dev_dbg(&dev->dev, "device needs a fake CIS\n");
if (!dev->socket->fake_cis)
- pcmcia_load_firmware(dev, did->cisfile);
-
- if (!dev->socket->fake_cis)
- return 0;
+ if (pcmcia_load_firmware(dev, did->cisfile))
+ return 0;
}
if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {