]> err.no Git - linux-2.6/blobdiff - drivers/memstick/core/mspro_block.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
[linux-2.6] / drivers / memstick / core / mspro_block.c
index 1d637e4561d36bea56267d431a2bf9c7db2928ec..477d0fb6e5883dafcaca0d273e79893c10c4173f 100644 (file)
@@ -133,6 +133,7 @@ struct mspro_devinfo {
 struct mspro_block_data {
        struct memstick_dev   *card;
        unsigned int          usage_count;
+       unsigned int          caps;
        struct gendisk        *disk;
        struct request_queue  *queue;
        spinlock_t            q_lock;
@@ -577,7 +578,6 @@ static int h_mspro_block_wait_for_ced(struct memstick_dev *card,
 static int h_mspro_block_transfer_data(struct memstick_dev *card,
                                       struct memstick_request **mrq)
 {
-       struct memstick_host *host = card->host;
        struct mspro_block_data *msb = memstick_get_drvdata(card);
        unsigned char t_val = 0;
        struct scatterlist t_sg = { 0 };
@@ -591,12 +591,12 @@ static int h_mspro_block_transfer_data(struct memstick_dev *card,
        switch ((*mrq)->tpc) {
        case MS_TPC_WRITE_REG:
                memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1);
-               (*mrq)->get_int_reg = 1;
+               (*mrq)->need_card_int = 1;
                return 0;
        case MS_TPC_SET_CMD:
                t_val = (*mrq)->int_reg;
                memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
-               if (host->caps & MEMSTICK_CAP_AUTO_GET_INT)
+               if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT)
                        goto has_int_reg;
                return 0;
        case MS_TPC_GET_INT:
@@ -646,12 +646,12 @@ has_int_reg:
                                           ? MS_TPC_READ_LONG_DATA
                                           : MS_TPC_WRITE_LONG_DATA,
                                     &t_sg);
-               (*mrq)->get_int_reg = 1;
+               (*mrq)->need_card_int = 1;
                return 0;
        case MS_TPC_READ_LONG_DATA:
        case MS_TPC_WRITE_LONG_DATA:
                msb->current_page++;
-               if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) {
+               if (msb->caps & MEMSTICK_CAP_AUTO_GET_INT) {
                        t_val = (*mrq)->int_reg;
                        goto has_int_reg;
                } else {
@@ -816,12 +816,13 @@ static int mspro_block_wait_for_ced(struct memstick_dev *card)
        return card->current_mrq.error;
 }
 
-static int mspro_block_switch_to_parallel(struct memstick_dev *card)
+static int mspro_block_set_interface(struct memstick_dev *card,
+                                    unsigned char sys_reg)
 {
        struct memstick_host *host = card->host;
        struct mspro_block_data *msb = memstick_get_drvdata(card);
        struct mspro_param_register param = {
-               .system = MEMSTICK_SYS_PAR4,
+               .system = sys_reg,
                .data_count = 0,
                .data_address = 0,
                .tpc_param = 0
@@ -833,41 +834,70 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
                          sizeof(param));
        memstick_new_req(host);
        wait_for_completion(&card->mrq_complete);
-       if (card->current_mrq.error)
-               return card->current_mrq.error;
+       return card->current_mrq.error;
+}
+
+static int mspro_block_switch_interface(struct memstick_dev *card)
+{
+       struct memstick_host *host = card->host;
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       int rc = 0;
+
+       if (msb->caps & MEMSTICK_CAP_PAR4)
+               rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4);
+       else
+               return 0;
+
+       if (rc) {
+               printk(KERN_WARNING
+                      "%s: could not switch to 4-bit mode, error %d\n",
+                      card->dev.bus_id, rc);
+               return 0;
+       }
 
        msb->system = MEMSTICK_SYS_PAR4;
        host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
+       printk(KERN_INFO "%s: switching to 4-bit parallel mode\n",
+              card->dev.bus_id);
+
+       if (msb->caps & MEMSTICK_CAP_PAR8) {
+               rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8);
+
+               if (!rc) {
+                       msb->system = MEMSTICK_SYS_PAR8;
+                       host->set_param(host, MEMSTICK_INTERFACE,
+                                       MEMSTICK_PAR8);
+                       printk(KERN_INFO
+                              "%s: switching to 8-bit parallel mode\n",
+                              card->dev.bus_id);
+               } else
+                       printk(KERN_WARNING
+                              "%s: could not switch to 8-bit mode, error %d\n",
+                              card->dev.bus_id, rc);
+       }
 
        card->next_request = h_mspro_block_req_init;
        msb->mrq_handler = h_mspro_block_default;
        memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
        memstick_new_req(card->host);
        wait_for_completion(&card->mrq_complete);
+       rc = card->current_mrq.error;
 
-       if (card->current_mrq.error) {
+       if (rc) {
+               printk(KERN_WARNING
+                      "%s: interface error, trying to fall back to serial\n",
+                      card->dev.bus_id);
                msb->system = MEMSTICK_SYS_SERIAL;
                host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
-               msleep(1000);
+               msleep(10);
                host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
                host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
 
-               if (memstick_set_rw_addr(card))
-                       return card->current_mrq.error;
-
-               param.system = msb->system;
-
-               card->next_request = h_mspro_block_req_init;
-               msb->mrq_handler = h_mspro_block_default;
-               memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
-                                 sizeof(param));
-               memstick_new_req(host);
-               wait_for_completion(&card->mrq_complete);
-
-               return -EFAULT;
+               rc = memstick_set_rw_addr(card);
+               if (!rc)
+                       rc = mspro_block_set_interface(card, msb->system);
        }
-
-       return 0;
+       return rc;
 }
 
 /* Memory allocated for attributes by this function should be freed by
@@ -1052,16 +1082,18 @@ static int mspro_block_init_card(struct memstick_dev *card)
        if (memstick_set_rw_addr(card))
                return -EIO;
 
-       if (host->caps & MEMSTICK_CAP_PAR4) {
-               if (mspro_block_switch_to_parallel(card))
-                       printk(KERN_WARNING "%s: could not switch to "
-                              "parallel interface\n", card->dev.bus_id);
-       }
+       msb->caps = host->caps;
+       rc = mspro_block_switch_interface(card);
+       if (rc)
+               return rc;
 
+       msleep(200);
        rc = mspro_block_wait_for_ced(card);
        if (rc)
                return rc;
        dev_dbg(&card->dev, "card activated\n");
+       if (msb->system != MEMSTICK_SYS_SERIAL)
+               msb->caps |= MEMSTICK_CAP_AUTO_GET_INT;
 
        card->next_request = h_mspro_block_req_init;
        msb->mrq_handler = h_mspro_block_get_ro;
@@ -1095,8 +1127,8 @@ static int mspro_block_init_disk(struct memstick_dev *card)
        u64 limit = BLK_BOUNCE_HIGH;
        unsigned long capacity;
 
-       if (host->cdev.dev->dma_mask && *(host->cdev.dev->dma_mask))
-               limit = *(host->cdev.dev->dma_mask);
+       if (host->dev.dma_mask && *(host->dev.dma_mask))
+               limit = *(host->dev.dma_mask);
 
        for (rc = 0; msb->attr_group.attrs[rc]; ++rc) {
                s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]);