X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fmemstick%2Fcore%2Fmspro_block.c;h=a41634699f846e95f1dbd8f8f2d185b215c8679a;hb=40cbbb781d3eba5d6ac0860db078af490e5c7c6b;hp=423ad8cf4bb9902e605cd000e3506ccf2fbd1a88;hpb=baf8532a147d5b76681ce040e2c8f25a3f0e718d;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 423ad8c..a416346 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -16,10 +16,10 @@ #include #include #include +#include #include #define DRIVER_NAME "mspro_block" -#define DRIVER_VERSION "0.2" static int major; module_param(major, int, 0644); @@ -30,6 +30,8 @@ module_param(major, int, 0644); #define MSPRO_BLOCK_SIGNATURE 0xa5c3 #define MSPRO_BLOCK_MAX_ATTRIBUTES 41 +#define MSPRO_BLOCK_PART_SHIFT 3 + enum { MSPRO_BLOCK_ID_SYSINFO = 0x10, MSPRO_BLOCK_ID_MODELNAME = 0x15, @@ -50,14 +52,14 @@ struct mspro_sys_attr { }; struct mspro_attr_entry { - unsigned int address; - unsigned int size; + __be32 address; + __be32 size; unsigned char id; unsigned char reserved[3]; } __attribute__((packed)); struct mspro_attribute { - unsigned short signature; + __be16 signature; unsigned short version; unsigned char count; unsigned char reserved[11]; @@ -67,28 +69,28 @@ struct mspro_attribute { struct mspro_sys_info { unsigned char class; unsigned char reserved0; - unsigned short block_size; - unsigned short block_count; - unsigned short user_block_count; - unsigned short page_size; + __be16 block_size; + __be16 block_count; + __be16 user_block_count; + __be16 page_size; unsigned char reserved1[2]; unsigned char assembly_date[8]; - unsigned int serial_number; + __be32 serial_number; unsigned char assembly_maker_code; unsigned char assembly_model_code[3]; - unsigned short memory_maker_code; - unsigned short memory_model_code; + __be16 memory_maker_code; + __be16 memory_model_code; unsigned char reserved2[4]; unsigned char vcc; unsigned char vpp; - unsigned short controller_number; - unsigned short controller_function; - unsigned short start_sector; - unsigned short unit_size; + __be16 controller_number; + __be16 controller_function; + __be16 start_sector; + __be16 unit_size; unsigned char ms_sub_class; unsigned char reserved3[4]; unsigned char interface_type; - unsigned short controller_code; + __be16 controller_code; unsigned char format_type; unsigned char reserved4; unsigned char device_type; @@ -110,23 +112,34 @@ struct mspro_mbr { unsigned int sectors_per_partition; } __attribute__((packed)); +struct mspro_specfile { + char name[8]; + char ext[3]; + unsigned char attr; + unsigned char reserved[10]; + unsigned short time; + unsigned short date; + unsigned short cluster; + unsigned int size; +} __attribute__((packed)); + struct mspro_devinfo { - unsigned short cylinders; - unsigned short heads; - unsigned short bytes_per_track; - unsigned short bytes_per_sector; - unsigned short sectors_per_track; + __be16 cylinders; + __be16 heads; + __be16 bytes_per_track; + __be16 bytes_per_sector; + __be16 sectors_per_track; unsigned char reserved[6]; } __attribute__((packed)); struct mspro_block_data { struct memstick_dev *card; unsigned int usage_count; + unsigned int caps; struct gendisk *disk; struct request_queue *queue; + struct request *block_req; spinlock_t q_lock; - wait_queue_head_t q_wait; - struct task_struct *q_thread; unsigned short page_size; unsigned short cylinders; @@ -135,9 +148,10 @@ struct mspro_block_data { unsigned char system; unsigned char read_only:1, - active:1, + eject:1, has_request:1, - data_dir:1; + data_dir:1, + active:1; unsigned char transfer_cmd; int (*mrq_handler)(struct memstick_dev *card, @@ -148,17 +162,19 @@ struct mspro_block_data { struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; unsigned int seg_count; unsigned int current_seg; - unsigned short current_page; + unsigned int current_page; }; static DEFINE_IDR(mspro_block_disk_idr); static DEFINE_MUTEX(mspro_block_disk_lock); +static int mspro_block_complete_req(struct memstick_dev *card, int error); + /*** Block device ***/ -static int mspro_block_bd_open(struct inode *inode, struct file *filp) +static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) { - struct gendisk *disk = inode->i_bdev->bd_disk; + struct gendisk *disk = bdev->bd_disk; struct mspro_block_data *msb = disk->private_data; int rc = -ENXIO; @@ -166,7 +182,7 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp) if (msb && msb->card) { msb->usage_count++; - if ((filp->f_mode & FMODE_WRITE) && msb->read_only) + if ((mode & FMODE_WRITE) && msb->read_only) rc = -EROFS; else rc = 0; @@ -181,12 +197,14 @@ static int mspro_block_bd_open(struct inode *inode, struct file *filp) static int mspro_block_disk_release(struct gendisk *disk) { struct mspro_block_data *msb = disk->private_data; - int disk_id = disk->first_minor >> MEMSTICK_PART_SHIFT; + int disk_id = MINOR(disk_devt(disk)) >> MSPRO_BLOCK_PART_SHIFT; mutex_lock(&mspro_block_disk_lock); - if (msb->usage_count) { - msb->usage_count--; + if (msb) { + if (msb->usage_count) + msb->usage_count--; + if (!msb->usage_count) { kfree(msb); disk->private_data = NULL; @@ -200,9 +218,8 @@ static int mspro_block_disk_release(struct gendisk *disk) return 0; } -static int mspro_block_bd_release(struct inode *inode, struct file *filp) +static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode) { - struct gendisk *disk = inode->i_bdev->bd_disk; return mspro_block_disk_release(disk); } @@ -293,6 +310,20 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev, dev_attr); struct mspro_sys_info *x_sys = x_attr->data; ssize_t rc = 0; + int date_tz = 0, date_tz_f = 0; + + if (x_sys->assembly_date[0] > 0x80U) { + date_tz = (~x_sys->assembly_date[0]) + 1; + date_tz_f = date_tz & 3; + date_tz >>= 2; + date_tz = -date_tz; + date_tz_f *= 15; + } else if (x_sys->assembly_date[0] < 0x80U) { + date_tz = x_sys->assembly_date[0]; + date_tz_f = date_tz & 3; + date_tz >>= 2; + date_tz_f *= 15; + } rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n", x_sys->class); @@ -305,10 +336,9 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev, rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n", be16_to_cpu(x_sys->page_size)); rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: " - "%d %04u-%02u-%02u %02u:%02u:%02u\n", - x_sys->assembly_date[0], - be16_to_cpu(*(unsigned short *) - &x_sys->assembly_date[1]), + "GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n", + date_tz, date_tz_f, + be16_to_cpup((__be16 *)&x_sys->assembly_date[1]), x_sys->assembly_date[3], x_sys->assembly_date[4], x_sys->assembly_date[5], x_sys->assembly_date[6], x_sys->assembly_date[7]); @@ -398,6 +428,41 @@ static ssize_t mspro_block_attr_show_mbr(struct device *dev, return rc; } +static ssize_t mspro_block_attr_show_specfile(struct device *dev, + struct device_attribute *attr, + char *buffer) +{ + struct mspro_sys_attr *x_attr = container_of(attr, + struct mspro_sys_attr, + dev_attr); + struct mspro_specfile *x_spfile = x_attr->data; + char name[9], ext[4]; + ssize_t rc = 0; + + memcpy(name, x_spfile->name, 8); + name[8] = 0; + memcpy(ext, x_spfile->ext, 3); + ext[3] = 0; + + rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "name: %s\n", name); + rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "ext: %s\n", ext); + rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "attribute: %x\n", + x_spfile->attr); + rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "time: %d:%d:%d\n", + x_spfile->time >> 11, + (x_spfile->time >> 5) & 0x3f, + (x_spfile->time & 0x1f) * 2); + rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "date: %d-%d-%d\n", + (x_spfile->date >> 9) + 1980, + (x_spfile->date >> 5) & 0xf, + x_spfile->date & 0x1f); + rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cluster: %x\n", + x_spfile->cluster); + rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "size: %x\n", + x_spfile->size); + return rc; +} + static ssize_t mspro_block_attr_show_devinfo(struct device *dev, struct device_attribute *attr, char *buffer) @@ -430,6 +495,9 @@ static sysfs_show_t mspro_block_attr_show(unsigned char tag) return mspro_block_attr_show_modelname; case MSPRO_BLOCK_ID_MBR: return mspro_block_attr_show_mbr; + case MSPRO_BLOCK_ID_SPECFILEVALUES1: + case MSPRO_BLOCK_ID_SPECFILEVALUES2: + return mspro_block_attr_show_specfile; case MSPRO_BLOCK_ID_DEVINFO: return mspro_block_attr_show_devinfo; default: @@ -459,11 +527,13 @@ static int h_mspro_block_req_init(struct memstick_dev *card, static int h_mspro_block_default(struct memstick_dev *card, struct memstick_request **mrq) { - complete(&card->mrq_complete); - if (!(*mrq)->error) - return -EAGAIN; - else - return (*mrq)->error; + return mspro_block_complete_req(card, (*mrq)->error); +} + +static int h_mspro_block_default_bad(struct memstick_dev *card, + struct memstick_request **mrq) +{ + return -ENXIO; } static int h_mspro_block_get_ro(struct memstick_dev *card, @@ -471,69 +541,52 @@ static int h_mspro_block_get_ro(struct memstick_dev *card, { struct mspro_block_data *msb = memstick_get_drvdata(card); - if ((*mrq)->error) { - complete(&card->mrq_complete); - return (*mrq)->error; + if (!(*mrq)->error) { + if ((*mrq)->data[offsetof(struct ms_status_register, status0)] + & MEMSTICK_STATUS0_WP) + msb->read_only = 1; + else + msb->read_only = 0; } - if ((*mrq)->data[offsetof(struct ms_status_register, status0)] - & MEMSTICK_STATUS0_WP) - msb->read_only = 1; - else - msb->read_only = 0; - - complete(&card->mrq_complete); - return -EAGAIN; + return mspro_block_complete_req(card, (*mrq)->error); } static int h_mspro_block_wait_for_ced(struct memstick_dev *card, struct memstick_request **mrq) { - if ((*mrq)->error) { - complete(&card->mrq_complete); - return (*mrq)->error; - } - dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]); - if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) { - card->current_mrq.error = -EFAULT; - complete(&card->mrq_complete); - return card->current_mrq.error; + if (!(*mrq)->error) { + if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) + (*mrq)->error = -EFAULT; + else if (!((*mrq)->data[0] & MEMSTICK_INT_CED)) + return 0; } - if (!((*mrq)->data[0] & MEMSTICK_INT_CED)) - return 0; - else { - card->current_mrq.error = 0; - complete(&card->mrq_complete); - return -EAGAIN; - } + return mspro_block_complete_req(card, (*mrq)->error); } 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 }; size_t t_offset; - if ((*mrq)->error) { - complete(&card->mrq_complete); - return (*mrq)->error; - } + if ((*mrq)->error) + return mspro_block_complete_req(card, (*mrq)->error); 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: @@ -554,8 +607,8 @@ has_int_reg: if (msb->current_seg == msb->seg_count) { if (t_val & MEMSTICK_INT_CED) { - complete(&card->mrq_complete); - return -EAGAIN; + return mspro_block_complete_req(card, + 0); } else { card->next_request = h_mspro_block_wait_for_ced; @@ -583,12 +636,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 { @@ -603,140 +656,184 @@ has_int_reg: /*** Data transfer ***/ -static void mspro_block_process_request(struct memstick_dev *card, - struct request *req) +static int mspro_block_issue_req(struct memstick_dev *card, int chunk) { struct mspro_block_data *msb = memstick_get_drvdata(card); - struct mspro_param_register param; - int rc, chunk, cnt; - unsigned short page_count; sector_t t_sec; - unsigned long flags; + unsigned int count; + struct mspro_param_register param; - do { - page_count = 0; +try_again: + while (chunk) { + msb->current_page = 0; msb->current_seg = 0; - msb->seg_count = blk_rq_map_sg(req->q, req, msb->req_sg); + msb->seg_count = blk_rq_map_sg(msb->block_req->q, + msb->block_req, + msb->req_sg); - if (msb->seg_count) { - msb->current_page = 0; - for (rc = 0; rc < msb->seg_count; rc++) - page_count += msb->req_sg[rc].length - / msb->page_size; - - t_sec = req->sector; - sector_div(t_sec, msb->page_size >> 9); - param.system = msb->system; - param.data_count = cpu_to_be16(page_count); - param.data_address = cpu_to_be32((uint32_t)t_sec); - param.cmd_param = 0; - - msb->data_dir = rq_data_dir(req); - msb->transfer_cmd = msb->data_dir == READ - ? MSPRO_CMD_READ_DATA - : MSPRO_CMD_WRITE_DATA; - - dev_dbg(&card->dev, "data transfer: cmd %x, " - "lba %x, count %x\n", msb->transfer_cmd, - be32_to_cpu(param.data_address), - page_count); - - card->next_request = h_mspro_block_req_init; - msb->mrq_handler = h_mspro_block_transfer_data; - memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, - ¶m, sizeof(param)); - memstick_new_req(card->host); - wait_for_completion(&card->mrq_complete); - rc = card->current_mrq.error; + if (!msb->seg_count) { + chunk = __blk_end_request(msb->block_req, -ENOMEM, + blk_rq_cur_bytes(msb->block_req)); + continue; + } - if (rc || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { - for (cnt = 0; cnt < msb->current_seg; cnt++) - page_count += msb->req_sg[cnt].length - / msb->page_size; - - if (msb->current_page) - page_count += msb->current_page - 1; - - if (page_count && (msb->data_dir == READ)) - rc = msb->page_size * page_count; - else - rc = -EIO; - } else - rc = msb->page_size * page_count; - } else - rc = -EFAULT; + t_sec = msb->block_req->sector << 9; + sector_div(t_sec, msb->page_size); - spin_lock_irqsave(&msb->q_lock, flags); - if (rc >= 0) - chunk = __blk_end_request(req, 0, rc); - else - chunk = __blk_end_request(req, rc, 0); + count = msb->block_req->nr_sectors << 9; + count /= msb->page_size; - dev_dbg(&card->dev, "end chunk %d, %d\n", rc, chunk); - spin_unlock_irqrestore(&msb->q_lock, flags); - } while (chunk); + param.system = msb->system; + param.data_count = cpu_to_be16(count); + param.data_address = cpu_to_be32((uint32_t)t_sec); + param.tpc_param = 0; + + msb->data_dir = rq_data_dir(msb->block_req); + msb->transfer_cmd = msb->data_dir == READ + ? MSPRO_CMD_READ_DATA + : MSPRO_CMD_WRITE_DATA; + + dev_dbg(&card->dev, "data transfer: cmd %x, " + "lba %x, count %x\n", msb->transfer_cmd, + be32_to_cpu(param.data_address), count); + + card->next_request = h_mspro_block_req_init; + msb->mrq_handler = h_mspro_block_transfer_data; + memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, + ¶m, sizeof(param)); + memstick_new_req(card->host); + return 0; + } + + dev_dbg(&card->dev, "elv_next\n"); + msb->block_req = elv_next_request(msb->queue); + if (!msb->block_req) { + dev_dbg(&card->dev, "issue end\n"); + return -EAGAIN; + } + + dev_dbg(&card->dev, "trying again\n"); + chunk = 1; + goto try_again; } -static int mspro_block_has_request(struct mspro_block_data *msb) +static int mspro_block_complete_req(struct memstick_dev *card, int error) { - int rc = 0; + struct mspro_block_data *msb = memstick_get_drvdata(card); + int chunk, cnt; + unsigned int t_len = 0; unsigned long flags; spin_lock_irqsave(&msb->q_lock, flags); - if (kthread_should_stop() || msb->has_request) - rc = 1; + dev_dbg(&card->dev, "complete %d, %d\n", msb->has_request ? 1 : 0, + error); + + if (msb->has_request) { + /* Nothing to do - not really an error */ + if (error == -EAGAIN) + error = 0; + + if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { + if (msb->data_dir == READ) { + for (cnt = 0; cnt < msb->current_seg; cnt++) + t_len += msb->req_sg[cnt].length + / msb->page_size; + + if (msb->current_page) + t_len += msb->current_page - 1; + + t_len *= msb->page_size; + } + } else + t_len = msb->block_req->nr_sectors << 9; + + dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error); + + if (error && !t_len) + t_len = blk_rq_cur_bytes(msb->block_req); + + chunk = __blk_end_request(msb->block_req, error, t_len); + + error = mspro_block_issue_req(card, chunk); + + if (!error) + goto out; + else + msb->has_request = 0; + } else { + if (!error) + error = -EAGAIN; + } + + card->next_request = h_mspro_block_default_bad; + complete_all(&card->mrq_complete); +out: spin_unlock_irqrestore(&msb->q_lock, flags); - return rc; + return error; } -static int mspro_block_queue_thread(void *data) +static void mspro_block_stop(struct memstick_dev *card) { - struct memstick_dev *card = data; - struct memstick_host *host = card->host; struct mspro_block_data *msb = memstick_get_drvdata(card); - struct request *req; + int rc = 0; unsigned long flags; while (1) { - wait_event(msb->q_wait, mspro_block_has_request(msb)); - dev_dbg(&card->dev, "thread iter\n"); - spin_lock_irqsave(&msb->q_lock, flags); - req = elv_next_request(msb->queue); - dev_dbg(&card->dev, "next req %p\n", req); - if (!req) { - msb->has_request = 0; - if (kthread_should_stop()) { - spin_unlock_irqrestore(&msb->q_lock, flags); - break; - } - } else - msb->has_request = 1; + if (!msb->has_request) { + blk_stop_queue(msb->queue); + rc = 1; + } spin_unlock_irqrestore(&msb->q_lock, flags); - if (req) { - mutex_lock(&host->lock); - mspro_block_process_request(card, req); - mutex_unlock(&host->lock); - } + if (rc) + break; + + wait_for_completion(&card->mrq_complete); } - dev_dbg(&card->dev, "thread finished\n"); - return 0; } -static void mspro_block_request(struct request_queue *q) +static void mspro_block_start(struct memstick_dev *card) +{ + struct mspro_block_data *msb = memstick_get_drvdata(card); + unsigned long flags; + + spin_lock_irqsave(&msb->q_lock, flags); + blk_start_queue(msb->queue); + spin_unlock_irqrestore(&msb->q_lock, flags); +} + +static int mspro_block_prepare_req(struct request_queue *q, struct request *req) +{ + if (!blk_fs_request(req) && !blk_pc_request(req)) { + blk_dump_rq_flags(req, "MSPro unsupported request"); + return BLKPREP_KILL; + } + + req->cmd_flags |= REQ_DONTPREP; + + return BLKPREP_OK; +} + +static void mspro_block_submit_req(struct request_queue *q) { struct memstick_dev *card = q->queuedata; struct mspro_block_data *msb = memstick_get_drvdata(card); struct request *req = NULL; - if (msb->q_thread) { - msb->has_request = 1; - wake_up_all(&msb->q_wait); - } else { + if (msb->has_request) + return; + + if (msb->eject) { while ((req = elv_next_request(q)) != NULL) - end_queued_request(req, -ENODEV); + __blk_end_request_all(req, -ENODEV); + + return; } + + msb->has_request = 1; + if (mspro_block_issue_req(card, 0)) + msb->has_request = 0; } /*** Initialization ***/ @@ -753,15 +850,16 @@ 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 = 0, + .system = sys_reg, .data_count = 0, .data_address = 0, - .cmd_param = 0 + .tpc_param = 0 }; card->next_request = h_mspro_block_req_init; @@ -770,25 +868,83 @@ 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; +} - msb->system = 0; - host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PARALLEL); +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; + +try_again: + 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", + dev_name(&card->dev), 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", + dev_name(&card->dev)); + + 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", + dev_name(&card->dev)); + } else + printk(KERN_WARNING + "%s: could not switch to 8-bit mode, error %d\n", + dev_name(&card->dev), 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); - - if (card->current_mrq.error) { - msb->system = 0x80; + rc = card->current_mrq.error; + + if (rc) { + printk(KERN_WARNING + "%s: interface error, trying to fall back to serial\n", + dev_name(&card->dev)); + msb->system = MEMSTICK_SYS_SERIAL; + host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF); + msleep(10); + host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON); host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); - return -EFAULT; - } - return 0; + rc = memstick_set_rw_addr(card); + if (!rc) + rc = mspro_block_set_interface(card, msb->system); + + if (!rc) { + msleep(150); + rc = mspro_block_wait_for_ced(card); + if (rc) + return rc; + + if (msb->caps & MEMSTICK_CAP_PAR8) { + msb->caps &= ~MEMSTICK_CAP_PAR8; + goto try_again; + } + } + } + return rc; } /* Memory allocated for attributes by this function should be freed by @@ -802,7 +958,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) .system = msb->system, .data_count = cpu_to_be16(1), .data_address = 0, - .cmd_param = 0 + .tpc_param = 0 }; struct mspro_attribute *attr = NULL; struct mspro_sys_attr *s_attr = NULL; @@ -835,14 +991,14 @@ static int mspro_block_read_attributes(struct memstick_dev *card) if (be16_to_cpu(attr->signature) != MSPRO_BLOCK_SIGNATURE) { printk(KERN_ERR "%s: unrecognized device signature %x\n", - card->dev.bus_id, be16_to_cpu(attr->signature)); + dev_name(&card->dev), be16_to_cpu(attr->signature)); rc = -ENODEV; goto out_free_attr; } if (attr->count > MSPRO_BLOCK_MAX_ATTRIBUTES) { printk(KERN_WARNING "%s: way too many attribute entries\n", - card->dev.bus_id); + dev_name(&card->dev)); attr_count = MSPRO_BLOCK_MAX_ATTRIBUTES; } else attr_count = attr->count; @@ -886,7 +1042,6 @@ static int mspro_block_read_attributes(struct memstick_dev *card) s_attr->dev_attr.attr.name = s_attr->name; s_attr->dev_attr.attr.mode = S_IRUGO; - s_attr->dev_attr.attr.owner = THIS_MODULE; s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); if (!rc) @@ -922,7 +1077,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card) param.system = msb->system; param.data_count = cpu_to_be16((rc / msb->page_size) + 1); param.data_address = cpu_to_be32(addr / msb->page_size); - param.cmd_param = 0; + param.tpc_param = 0; sg_init_one(&msb->req_sg[0], buffer, be16_to_cpu(param.data_count) * msb->page_size); @@ -964,7 +1119,7 @@ static int mspro_block_init_card(struct memstick_dev *card) struct memstick_host *host = card->host; int rc = 0; - msb->system = 0x80; + msb->system = MEMSTICK_SYS_SERIAL; card->reg_addr.r_offset = offsetof(struct mspro_register, status); card->reg_addr.r_length = sizeof(struct ms_status_register); card->reg_addr.w_offset = offsetof(struct mspro_register, param); @@ -973,16 +1128,20 @@ static int mspro_block_init_card(struct memstick_dev *card) if (memstick_set_rw_addr(card)) return -EIO; - if (host->caps & MEMSTICK_CAP_PARALLEL) { - 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; + msleep(150); rc = mspro_block_wait_for_ced(card); if (rc) return rc; + + rc = mspro_block_switch_interface(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; @@ -1016,8 +1175,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]); @@ -1047,27 +1206,25 @@ static int mspro_block_init_disk(struct memstick_dev *card) if (rc) return rc; - if ((disk_id << MEMSTICK_PART_SHIFT) > 255) { + if ((disk_id << MSPRO_BLOCK_PART_SHIFT) > 255) { rc = -ENOSPC; goto out_release_id; } - msb->disk = alloc_disk(1 << MEMSTICK_PART_SHIFT); + msb->disk = alloc_disk(1 << MSPRO_BLOCK_PART_SHIFT); if (!msb->disk) { rc = -ENOMEM; goto out_release_id; } - spin_lock_init(&msb->q_lock); - init_waitqueue_head(&msb->q_wait); - - msb->queue = blk_init_queue(mspro_block_request, &msb->q_lock); + msb->queue = blk_init_queue(mspro_block_submit_req, &msb->q_lock); if (!msb->queue) { rc = -ENOMEM; goto out_put_disk; } msb->queue->queuedata = card; + blk_queue_prep_rq(msb->queue, mspro_block_prepare_req); blk_queue_bounce_limit(msb->queue, limit); blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); @@ -1077,7 +1234,7 @@ static int mspro_block_init_disk(struct memstick_dev *card) MSPRO_BLOCK_MAX_PAGES * msb->page_size); msb->disk->major = major; - msb->disk->first_minor = disk_id << MEMSTICK_PART_SHIFT; + msb->disk->first_minor = disk_id << MSPRO_BLOCK_PART_SHIFT; msb->disk->fops = &ms_block_bdops; msb->usage_count = 1; msb->disk->private_data = msb; @@ -1093,14 +1250,8 @@ static int mspro_block_init_disk(struct memstick_dev *card) capacity *= msb->page_size >> 9; set_capacity(msb->disk, capacity); dev_dbg(&card->dev, "capacity set %ld\n", capacity); - msb->q_thread = kthread_run(mspro_block_queue_thread, card, - DRIVER_NAME"d"); - if (IS_ERR(msb->q_thread)) - goto out_put_disk; - mutex_unlock(&host->lock); add_disk(msb->disk); - mutex_lock(&host->lock); msb->active = 1; return 0; @@ -1148,6 +1299,7 @@ static int mspro_block_probe(struct memstick_dev *card) return -ENOMEM; memstick_set_drvdata(card, msb); msb->card = card; + spin_lock_init(&msb->q_lock); rc = mspro_block_init_card(card); @@ -1161,6 +1313,8 @@ static int mspro_block_probe(struct memstick_dev *card) rc = mspro_block_init_disk(card); if (!rc) { card->check = mspro_block_check_card; + card->stop = mspro_block_stop; + card->start = mspro_block_start; return 0; } @@ -1175,26 +1329,17 @@ out_free: static void mspro_block_remove(struct memstick_dev *card) { struct mspro_block_data *msb = memstick_get_drvdata(card); - struct task_struct *q_thread = NULL; unsigned long flags; del_gendisk(msb->disk); dev_dbg(&card->dev, "mspro block remove\n"); spin_lock_irqsave(&msb->q_lock, flags); - q_thread = msb->q_thread; - msb->q_thread = NULL; - msb->active = 0; + msb->eject = 1; + blk_start_queue(msb->queue); spin_unlock_irqrestore(&msb->q_lock, flags); - if (q_thread) { - mutex_unlock(&card->host->lock); - kthread_stop(q_thread); - mutex_lock(&card->host->lock); - } - - dev_dbg(&card->dev, "queue thread stopped\n"); - blk_cleanup_queue(msb->queue); + msb->queue = NULL; sysfs_remove_group(&card->dev.kobj, &msb->attr_group); @@ -1211,19 +1356,13 @@ static void mspro_block_remove(struct memstick_dev *card) static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) { struct mspro_block_data *msb = memstick_get_drvdata(card); - struct task_struct *q_thread = NULL; unsigned long flags; spin_lock_irqsave(&msb->q_lock, flags); - q_thread = msb->q_thread; - msb->q_thread = NULL; - msb->active = 0; blk_stop_queue(msb->queue); + msb->active = 0; spin_unlock_irqrestore(&msb->q_lock, flags); - if (q_thread) - kthread_stop(q_thread); - return 0; } @@ -1262,14 +1401,7 @@ static int mspro_block_resume(struct memstick_dev *card) if (memcmp(s_attr->data, r_attr->data, s_attr->size)) break; - memstick_set_drvdata(card, msb); - msb->q_thread = kthread_run(mspro_block_queue_thread, - card, DRIVER_NAME"d"); - if (IS_ERR(msb->q_thread)) - msb->q_thread = NULL; - else - msb->active = 1; - + msb->active = 1; break; } } @@ -1298,7 +1430,7 @@ out_unlock: static struct memstick_device_id mspro_block_id_tbl[] = { {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO, - MEMSTICK_CLASS_GENERIC_DUO}, + MEMSTICK_CLASS_DUO}, {} }; @@ -1348,4 +1480,3 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alex Dubov"); MODULE_DESCRIPTION("Sony MemoryStickPro block device driver"); MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl); -MODULE_VERSION(DRIVER_VERSION);