1baf8532aSAlex Dubov /* 2baf8532aSAlex Dubov * Sony MemoryStick Pro storage support 3baf8532aSAlex Dubov * 4baf8532aSAlex Dubov * Copyright (C) 2007 Alex Dubov <oakad@yahoo.com> 5baf8532aSAlex Dubov * 6baf8532aSAlex Dubov * This program is free software; you can redistribute it and/or modify 7baf8532aSAlex Dubov * it under the terms of the GNU General Public License version 2 as 8baf8532aSAlex Dubov * published by the Free Software Foundation. 9baf8532aSAlex Dubov * 10baf8532aSAlex Dubov * Special thanks to Carlos Corbacho for providing various MemoryStick cards 11baf8532aSAlex Dubov * that made this driver possible. 12baf8532aSAlex Dubov * 13baf8532aSAlex Dubov */ 14baf8532aSAlex Dubov 15baf8532aSAlex Dubov #include <linux/blkdev.h> 16baf8532aSAlex Dubov #include <linux/idr.h> 17baf8532aSAlex Dubov #include <linux/hdreg.h> 18baf8532aSAlex Dubov #include <linux/kthread.h> 19baf8532aSAlex Dubov #include <linux/memstick.h> 20baf8532aSAlex Dubov 21baf8532aSAlex Dubov #define DRIVER_NAME "mspro_block" 22baf8532aSAlex Dubov #define DRIVER_VERSION "0.2" 23baf8532aSAlex Dubov 24baf8532aSAlex Dubov static int major; 25baf8532aSAlex Dubov module_param(major, int, 0644); 26baf8532aSAlex Dubov 27baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_SEGS 32 28baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_PAGES ((2 << 16) - 1) 29baf8532aSAlex Dubov 30baf8532aSAlex Dubov #define MSPRO_BLOCK_SIGNATURE 0xa5c3 31baf8532aSAlex Dubov #define MSPRO_BLOCK_MAX_ATTRIBUTES 41 32baf8532aSAlex Dubov 33baf8532aSAlex Dubov enum { 34baf8532aSAlex Dubov MSPRO_BLOCK_ID_SYSINFO = 0x10, 35baf8532aSAlex Dubov MSPRO_BLOCK_ID_MODELNAME = 0x15, 36baf8532aSAlex Dubov MSPRO_BLOCK_ID_MBR = 0x20, 37baf8532aSAlex Dubov MSPRO_BLOCK_ID_PBR16 = 0x21, 38baf8532aSAlex Dubov MSPRO_BLOCK_ID_PBR32 = 0x22, 39baf8532aSAlex Dubov MSPRO_BLOCK_ID_SPECFILEVALUES1 = 0x25, 40baf8532aSAlex Dubov MSPRO_BLOCK_ID_SPECFILEVALUES2 = 0x26, 41baf8532aSAlex Dubov MSPRO_BLOCK_ID_DEVINFO = 0x30 42baf8532aSAlex Dubov }; 43baf8532aSAlex Dubov 44baf8532aSAlex Dubov struct mspro_sys_attr { 45baf8532aSAlex Dubov size_t size; 46baf8532aSAlex Dubov void *data; 47baf8532aSAlex Dubov unsigned char id; 48baf8532aSAlex Dubov char name[32]; 49baf8532aSAlex Dubov struct device_attribute dev_attr; 50baf8532aSAlex Dubov }; 51baf8532aSAlex Dubov 52baf8532aSAlex Dubov struct mspro_attr_entry { 53baf8532aSAlex Dubov unsigned int address; 54baf8532aSAlex Dubov unsigned int size; 55baf8532aSAlex Dubov unsigned char id; 56baf8532aSAlex Dubov unsigned char reserved[3]; 57baf8532aSAlex Dubov } __attribute__((packed)); 58baf8532aSAlex Dubov 59baf8532aSAlex Dubov struct mspro_attribute { 60baf8532aSAlex Dubov unsigned short signature; 61baf8532aSAlex Dubov unsigned short version; 62baf8532aSAlex Dubov unsigned char count; 63baf8532aSAlex Dubov unsigned char reserved[11]; 64baf8532aSAlex Dubov struct mspro_attr_entry entries[]; 65baf8532aSAlex Dubov } __attribute__((packed)); 66baf8532aSAlex Dubov 67baf8532aSAlex Dubov struct mspro_sys_info { 68baf8532aSAlex Dubov unsigned char class; 69baf8532aSAlex Dubov unsigned char reserved0; 70baf8532aSAlex Dubov unsigned short block_size; 71baf8532aSAlex Dubov unsigned short block_count; 72baf8532aSAlex Dubov unsigned short user_block_count; 73baf8532aSAlex Dubov unsigned short page_size; 74baf8532aSAlex Dubov unsigned char reserved1[2]; 75baf8532aSAlex Dubov unsigned char assembly_date[8]; 76baf8532aSAlex Dubov unsigned int serial_number; 77baf8532aSAlex Dubov unsigned char assembly_maker_code; 78baf8532aSAlex Dubov unsigned char assembly_model_code[3]; 79baf8532aSAlex Dubov unsigned short memory_maker_code; 80baf8532aSAlex Dubov unsigned short memory_model_code; 81baf8532aSAlex Dubov unsigned char reserved2[4]; 82baf8532aSAlex Dubov unsigned char vcc; 83baf8532aSAlex Dubov unsigned char vpp; 84baf8532aSAlex Dubov unsigned short controller_number; 85baf8532aSAlex Dubov unsigned short controller_function; 86baf8532aSAlex Dubov unsigned short start_sector; 87baf8532aSAlex Dubov unsigned short unit_size; 88baf8532aSAlex Dubov unsigned char ms_sub_class; 89baf8532aSAlex Dubov unsigned char reserved3[4]; 90baf8532aSAlex Dubov unsigned char interface_type; 91baf8532aSAlex Dubov unsigned short controller_code; 92baf8532aSAlex Dubov unsigned char format_type; 93baf8532aSAlex Dubov unsigned char reserved4; 94baf8532aSAlex Dubov unsigned char device_type; 95baf8532aSAlex Dubov unsigned char reserved5[7]; 96baf8532aSAlex Dubov unsigned char mspro_id[16]; 97baf8532aSAlex Dubov unsigned char reserved6[16]; 98baf8532aSAlex Dubov } __attribute__((packed)); 99baf8532aSAlex Dubov 100baf8532aSAlex Dubov struct mspro_mbr { 101baf8532aSAlex Dubov unsigned char boot_partition; 102baf8532aSAlex Dubov unsigned char start_head; 103baf8532aSAlex Dubov unsigned char start_sector; 104baf8532aSAlex Dubov unsigned char start_cylinder; 105baf8532aSAlex Dubov unsigned char partition_type; 106baf8532aSAlex Dubov unsigned char end_head; 107baf8532aSAlex Dubov unsigned char end_sector; 108baf8532aSAlex Dubov unsigned char end_cylinder; 109baf8532aSAlex Dubov unsigned int start_sectors; 110baf8532aSAlex Dubov unsigned int sectors_per_partition; 111baf8532aSAlex Dubov } __attribute__((packed)); 112baf8532aSAlex Dubov 113baf8532aSAlex Dubov struct mspro_devinfo { 114baf8532aSAlex Dubov unsigned short cylinders; 115baf8532aSAlex Dubov unsigned short heads; 116baf8532aSAlex Dubov unsigned short bytes_per_track; 117baf8532aSAlex Dubov unsigned short bytes_per_sector; 118baf8532aSAlex Dubov unsigned short sectors_per_track; 119baf8532aSAlex Dubov unsigned char reserved[6]; 120baf8532aSAlex Dubov } __attribute__((packed)); 121baf8532aSAlex Dubov 122baf8532aSAlex Dubov struct mspro_block_data { 123baf8532aSAlex Dubov struct memstick_dev *card; 124baf8532aSAlex Dubov unsigned int usage_count; 125baf8532aSAlex Dubov struct gendisk *disk; 126baf8532aSAlex Dubov struct request_queue *queue; 127baf8532aSAlex Dubov spinlock_t q_lock; 128baf8532aSAlex Dubov wait_queue_head_t q_wait; 129baf8532aSAlex Dubov struct task_struct *q_thread; 130baf8532aSAlex Dubov 131baf8532aSAlex Dubov unsigned short page_size; 132baf8532aSAlex Dubov unsigned short cylinders; 133baf8532aSAlex Dubov unsigned short heads; 134baf8532aSAlex Dubov unsigned short sectors_per_track; 135baf8532aSAlex Dubov 136baf8532aSAlex Dubov unsigned char system; 137baf8532aSAlex Dubov unsigned char read_only:1, 138baf8532aSAlex Dubov active:1, 139baf8532aSAlex Dubov has_request:1, 140baf8532aSAlex Dubov data_dir:1; 141baf8532aSAlex Dubov unsigned char transfer_cmd; 142baf8532aSAlex Dubov 143baf8532aSAlex Dubov int (*mrq_handler)(struct memstick_dev *card, 144baf8532aSAlex Dubov struct memstick_request **mrq); 145baf8532aSAlex Dubov 146baf8532aSAlex Dubov struct attribute_group attr_group; 147baf8532aSAlex Dubov 148baf8532aSAlex Dubov struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; 149baf8532aSAlex Dubov unsigned int seg_count; 150baf8532aSAlex Dubov unsigned int current_seg; 151baf8532aSAlex Dubov unsigned short current_page; 152baf8532aSAlex Dubov }; 153baf8532aSAlex Dubov 154baf8532aSAlex Dubov static DEFINE_IDR(mspro_block_disk_idr); 155baf8532aSAlex Dubov static DEFINE_MUTEX(mspro_block_disk_lock); 156baf8532aSAlex Dubov 157baf8532aSAlex Dubov /*** Block device ***/ 158baf8532aSAlex Dubov 159baf8532aSAlex Dubov static int mspro_block_bd_open(struct inode *inode, struct file *filp) 160baf8532aSAlex Dubov { 161baf8532aSAlex Dubov struct gendisk *disk = inode->i_bdev->bd_disk; 162baf8532aSAlex Dubov struct mspro_block_data *msb = disk->private_data; 163baf8532aSAlex Dubov int rc = -ENXIO; 164baf8532aSAlex Dubov 165baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 166baf8532aSAlex Dubov 167baf8532aSAlex Dubov if (msb && msb->card) { 168baf8532aSAlex Dubov msb->usage_count++; 169baf8532aSAlex Dubov if ((filp->f_mode & FMODE_WRITE) && msb->read_only) 170baf8532aSAlex Dubov rc = -EROFS; 171baf8532aSAlex Dubov else 172baf8532aSAlex Dubov rc = 0; 173baf8532aSAlex Dubov } 174baf8532aSAlex Dubov 175baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 176baf8532aSAlex Dubov 177baf8532aSAlex Dubov return rc; 178baf8532aSAlex Dubov } 179baf8532aSAlex Dubov 180baf8532aSAlex Dubov 181baf8532aSAlex Dubov static int mspro_block_disk_release(struct gendisk *disk) 182baf8532aSAlex Dubov { 183baf8532aSAlex Dubov struct mspro_block_data *msb = disk->private_data; 184baf8532aSAlex Dubov int disk_id = disk->first_minor >> MEMSTICK_PART_SHIFT; 185baf8532aSAlex Dubov 186baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 187baf8532aSAlex Dubov 188baf8532aSAlex Dubov if (msb->usage_count) { 189baf8532aSAlex Dubov msb->usage_count--; 190baf8532aSAlex Dubov if (!msb->usage_count) { 191baf8532aSAlex Dubov kfree(msb); 192baf8532aSAlex Dubov disk->private_data = NULL; 193baf8532aSAlex Dubov idr_remove(&mspro_block_disk_idr, disk_id); 194baf8532aSAlex Dubov put_disk(disk); 195baf8532aSAlex Dubov } 196baf8532aSAlex Dubov } 197baf8532aSAlex Dubov 198baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 199baf8532aSAlex Dubov 200baf8532aSAlex Dubov return 0; 201baf8532aSAlex Dubov } 202baf8532aSAlex Dubov 203baf8532aSAlex Dubov static int mspro_block_bd_release(struct inode *inode, struct file *filp) 204baf8532aSAlex Dubov { 205baf8532aSAlex Dubov struct gendisk *disk = inode->i_bdev->bd_disk; 206baf8532aSAlex Dubov return mspro_block_disk_release(disk); 207baf8532aSAlex Dubov } 208baf8532aSAlex Dubov 209baf8532aSAlex Dubov static int mspro_block_bd_getgeo(struct block_device *bdev, 210baf8532aSAlex Dubov struct hd_geometry *geo) 211baf8532aSAlex Dubov { 212baf8532aSAlex Dubov struct mspro_block_data *msb = bdev->bd_disk->private_data; 213baf8532aSAlex Dubov 214baf8532aSAlex Dubov geo->heads = msb->heads; 215baf8532aSAlex Dubov geo->sectors = msb->sectors_per_track; 216baf8532aSAlex Dubov geo->cylinders = msb->cylinders; 217baf8532aSAlex Dubov 218baf8532aSAlex Dubov return 0; 219baf8532aSAlex Dubov } 220baf8532aSAlex Dubov 221baf8532aSAlex Dubov static struct block_device_operations ms_block_bdops = { 222baf8532aSAlex Dubov .open = mspro_block_bd_open, 223baf8532aSAlex Dubov .release = mspro_block_bd_release, 224baf8532aSAlex Dubov .getgeo = mspro_block_bd_getgeo, 225baf8532aSAlex Dubov .owner = THIS_MODULE 226baf8532aSAlex Dubov }; 227baf8532aSAlex Dubov 228baf8532aSAlex Dubov /*** Information ***/ 229baf8532aSAlex Dubov 230baf8532aSAlex Dubov static struct mspro_sys_attr *mspro_from_sysfs_attr(struct attribute *attr) 231baf8532aSAlex Dubov { 232baf8532aSAlex Dubov struct device_attribute *dev_attr 233baf8532aSAlex Dubov = container_of(attr, struct device_attribute, attr); 234baf8532aSAlex Dubov return container_of(dev_attr, struct mspro_sys_attr, dev_attr); 235baf8532aSAlex Dubov } 236baf8532aSAlex Dubov 237baf8532aSAlex Dubov static const char *mspro_block_attr_name(unsigned char tag) 238baf8532aSAlex Dubov { 239baf8532aSAlex Dubov switch (tag) { 240baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SYSINFO: 241baf8532aSAlex Dubov return "attr_sysinfo"; 242baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MODELNAME: 243baf8532aSAlex Dubov return "attr_modelname"; 244baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MBR: 245baf8532aSAlex Dubov return "attr_mbr"; 246baf8532aSAlex Dubov case MSPRO_BLOCK_ID_PBR16: 247baf8532aSAlex Dubov return "attr_pbr16"; 248baf8532aSAlex Dubov case MSPRO_BLOCK_ID_PBR32: 249baf8532aSAlex Dubov return "attr_pbr32"; 250baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SPECFILEVALUES1: 251baf8532aSAlex Dubov return "attr_specfilevalues1"; 252baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SPECFILEVALUES2: 253baf8532aSAlex Dubov return "attr_specfilevalues2"; 254baf8532aSAlex Dubov case MSPRO_BLOCK_ID_DEVINFO: 255baf8532aSAlex Dubov return "attr_devinfo"; 256baf8532aSAlex Dubov default: 257baf8532aSAlex Dubov return NULL; 258baf8532aSAlex Dubov }; 259baf8532aSAlex Dubov } 260baf8532aSAlex Dubov 261baf8532aSAlex Dubov typedef ssize_t (*sysfs_show_t)(struct device *dev, 262baf8532aSAlex Dubov struct device_attribute *attr, 263baf8532aSAlex Dubov char *buffer); 264baf8532aSAlex Dubov 265baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_default(struct device *dev, 266baf8532aSAlex Dubov struct device_attribute *attr, 267baf8532aSAlex Dubov char *buffer) 268baf8532aSAlex Dubov { 269baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = container_of(attr, 270baf8532aSAlex Dubov struct mspro_sys_attr, 271baf8532aSAlex Dubov dev_attr); 272baf8532aSAlex Dubov 273baf8532aSAlex Dubov ssize_t cnt, rc = 0; 274baf8532aSAlex Dubov 275baf8532aSAlex Dubov for (cnt = 0; cnt < s_attr->size; cnt++) { 276baf8532aSAlex Dubov if (cnt && !(cnt % 16)) { 277baf8532aSAlex Dubov if (PAGE_SIZE - rc) 278baf8532aSAlex Dubov buffer[rc++] = '\n'; 279baf8532aSAlex Dubov } 280baf8532aSAlex Dubov 281baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "%02x ", 282baf8532aSAlex Dubov ((unsigned char *)s_attr->data)[cnt]); 283baf8532aSAlex Dubov } 284baf8532aSAlex Dubov return rc; 285baf8532aSAlex Dubov } 286baf8532aSAlex Dubov 287baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_sysinfo(struct device *dev, 288baf8532aSAlex Dubov struct device_attribute *attr, 289baf8532aSAlex Dubov char *buffer) 290baf8532aSAlex Dubov { 291baf8532aSAlex Dubov struct mspro_sys_attr *x_attr = container_of(attr, 292baf8532aSAlex Dubov struct mspro_sys_attr, 293baf8532aSAlex Dubov dev_attr); 294baf8532aSAlex Dubov struct mspro_sys_info *x_sys = x_attr->data; 295baf8532aSAlex Dubov ssize_t rc = 0; 296baf8532aSAlex Dubov 297baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n", 298baf8532aSAlex Dubov x_sys->class); 299baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block size: %x\n", 300baf8532aSAlex Dubov be16_to_cpu(x_sys->block_size)); 301baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block count: %x\n", 302baf8532aSAlex Dubov be16_to_cpu(x_sys->block_count)); 303baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "user block count: %x\n", 304baf8532aSAlex Dubov be16_to_cpu(x_sys->user_block_count)); 305baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n", 306baf8532aSAlex Dubov be16_to_cpu(x_sys->page_size)); 307baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: " 308baf8532aSAlex Dubov "%d %04u-%02u-%02u %02u:%02u:%02u\n", 309baf8532aSAlex Dubov x_sys->assembly_date[0], 310baf8532aSAlex Dubov be16_to_cpu(*(unsigned short *) 311baf8532aSAlex Dubov &x_sys->assembly_date[1]), 312baf8532aSAlex Dubov x_sys->assembly_date[3], x_sys->assembly_date[4], 313baf8532aSAlex Dubov x_sys->assembly_date[5], x_sys->assembly_date[6], 314baf8532aSAlex Dubov x_sys->assembly_date[7]); 315baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "serial number: %x\n", 316baf8532aSAlex Dubov be32_to_cpu(x_sys->serial_number)); 317baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, 318baf8532aSAlex Dubov "assembly maker code: %x\n", 319baf8532aSAlex Dubov x_sys->assembly_maker_code); 320baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly model code: " 321baf8532aSAlex Dubov "%02x%02x%02x\n", x_sys->assembly_model_code[0], 322baf8532aSAlex Dubov x_sys->assembly_model_code[1], 323baf8532aSAlex Dubov x_sys->assembly_model_code[2]); 324baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory maker code: %x\n", 325baf8532aSAlex Dubov be16_to_cpu(x_sys->memory_maker_code)); 326baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory model code: %x\n", 327baf8532aSAlex Dubov be16_to_cpu(x_sys->memory_model_code)); 328baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vcc: %x\n", 329baf8532aSAlex Dubov x_sys->vcc); 330baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vpp: %x\n", 331baf8532aSAlex Dubov x_sys->vpp); 332baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller number: %x\n", 333baf8532aSAlex Dubov be16_to_cpu(x_sys->controller_number)); 334baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, 335baf8532aSAlex Dubov "controller function: %x\n", 336baf8532aSAlex Dubov be16_to_cpu(x_sys->controller_function)); 337baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n", 338baf8532aSAlex Dubov be16_to_cpu(x_sys->start_sector)); 339baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "unit size: %x\n", 340baf8532aSAlex Dubov be16_to_cpu(x_sys->unit_size)); 341baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sub class: %x\n", 342baf8532aSAlex Dubov x_sys->ms_sub_class); 343baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "interface type: %x\n", 344baf8532aSAlex Dubov x_sys->interface_type); 345baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller code: %x\n", 346baf8532aSAlex Dubov be16_to_cpu(x_sys->controller_code)); 347baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "format type: %x\n", 348baf8532aSAlex Dubov x_sys->format_type); 349baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "device type: %x\n", 350baf8532aSAlex Dubov x_sys->device_type); 351baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "mspro id: %s\n", 352baf8532aSAlex Dubov x_sys->mspro_id); 353baf8532aSAlex Dubov return rc; 354baf8532aSAlex Dubov } 355baf8532aSAlex Dubov 356baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_modelname(struct device *dev, 357baf8532aSAlex Dubov struct device_attribute *attr, 358baf8532aSAlex Dubov char *buffer) 359baf8532aSAlex Dubov { 360baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = container_of(attr, 361baf8532aSAlex Dubov struct mspro_sys_attr, 362baf8532aSAlex Dubov dev_attr); 363baf8532aSAlex Dubov 364baf8532aSAlex Dubov return scnprintf(buffer, PAGE_SIZE, "%s", (char *)s_attr->data); 365baf8532aSAlex Dubov } 366baf8532aSAlex Dubov 367baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_mbr(struct device *dev, 368baf8532aSAlex Dubov struct device_attribute *attr, 369baf8532aSAlex Dubov char *buffer) 370baf8532aSAlex Dubov { 371baf8532aSAlex Dubov struct mspro_sys_attr *x_attr = container_of(attr, 372baf8532aSAlex Dubov struct mspro_sys_attr, 373baf8532aSAlex Dubov dev_attr); 374baf8532aSAlex Dubov struct mspro_mbr *x_mbr = x_attr->data; 375baf8532aSAlex Dubov ssize_t rc = 0; 376baf8532aSAlex Dubov 377baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "boot partition: %x\n", 378baf8532aSAlex Dubov x_mbr->boot_partition); 379baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start head: %x\n", 380baf8532aSAlex Dubov x_mbr->start_head); 381baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n", 382baf8532aSAlex Dubov x_mbr->start_sector); 383baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cylinder: %x\n", 384baf8532aSAlex Dubov x_mbr->start_cylinder); 385baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "partition type: %x\n", 386baf8532aSAlex Dubov x_mbr->partition_type); 387baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end head: %x\n", 388baf8532aSAlex Dubov x_mbr->end_head); 389baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end sector: %x\n", 390baf8532aSAlex Dubov x_mbr->end_sector); 391baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end cylinder: %x\n", 392baf8532aSAlex Dubov x_mbr->end_cylinder); 393baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sectors: %x\n", 394baf8532aSAlex Dubov x_mbr->start_sectors); 395baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, 396baf8532aSAlex Dubov "sectors per partition: %x\n", 397baf8532aSAlex Dubov x_mbr->sectors_per_partition); 398baf8532aSAlex Dubov return rc; 399baf8532aSAlex Dubov } 400baf8532aSAlex Dubov 401baf8532aSAlex Dubov static ssize_t mspro_block_attr_show_devinfo(struct device *dev, 402baf8532aSAlex Dubov struct device_attribute *attr, 403baf8532aSAlex Dubov char *buffer) 404baf8532aSAlex Dubov { 405baf8532aSAlex Dubov struct mspro_sys_attr *x_attr = container_of(attr, 406baf8532aSAlex Dubov struct mspro_sys_attr, 407baf8532aSAlex Dubov dev_attr); 408baf8532aSAlex Dubov struct mspro_devinfo *x_devinfo = x_attr->data; 409baf8532aSAlex Dubov ssize_t rc = 0; 410baf8532aSAlex Dubov 411baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "cylinders: %x\n", 412baf8532aSAlex Dubov be16_to_cpu(x_devinfo->cylinders)); 413baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "heads: %x\n", 414baf8532aSAlex Dubov be16_to_cpu(x_devinfo->heads)); 415baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per track: %x\n", 416baf8532aSAlex Dubov be16_to_cpu(x_devinfo->bytes_per_track)); 417baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per sector: %x\n", 418baf8532aSAlex Dubov be16_to_cpu(x_devinfo->bytes_per_sector)); 419baf8532aSAlex Dubov rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sectors per track: %x\n", 420baf8532aSAlex Dubov be16_to_cpu(x_devinfo->sectors_per_track)); 421baf8532aSAlex Dubov return rc; 422baf8532aSAlex Dubov } 423baf8532aSAlex Dubov 424baf8532aSAlex Dubov static sysfs_show_t mspro_block_attr_show(unsigned char tag) 425baf8532aSAlex Dubov { 426baf8532aSAlex Dubov switch (tag) { 427baf8532aSAlex Dubov case MSPRO_BLOCK_ID_SYSINFO: 428baf8532aSAlex Dubov return mspro_block_attr_show_sysinfo; 429baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MODELNAME: 430baf8532aSAlex Dubov return mspro_block_attr_show_modelname; 431baf8532aSAlex Dubov case MSPRO_BLOCK_ID_MBR: 432baf8532aSAlex Dubov return mspro_block_attr_show_mbr; 433baf8532aSAlex Dubov case MSPRO_BLOCK_ID_DEVINFO: 434baf8532aSAlex Dubov return mspro_block_attr_show_devinfo; 435baf8532aSAlex Dubov default: 436baf8532aSAlex Dubov return mspro_block_attr_show_default; 437baf8532aSAlex Dubov } 438baf8532aSAlex Dubov } 439baf8532aSAlex Dubov 440baf8532aSAlex Dubov /*** Protocol handlers ***/ 441baf8532aSAlex Dubov 442baf8532aSAlex Dubov /* 443baf8532aSAlex Dubov * Functions prefixed with "h_" are protocol callbacks. They can be called from 444baf8532aSAlex Dubov * interrupt context. Return value of 0 means that request processing is still 445baf8532aSAlex Dubov * ongoing, while special error value of -EAGAIN means that current request is 446baf8532aSAlex Dubov * finished (and request processor should come back some time later). 447baf8532aSAlex Dubov */ 448baf8532aSAlex Dubov 449baf8532aSAlex Dubov static int h_mspro_block_req_init(struct memstick_dev *card, 450baf8532aSAlex Dubov struct memstick_request **mrq) 451baf8532aSAlex Dubov { 452baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 453baf8532aSAlex Dubov 454baf8532aSAlex Dubov *mrq = &card->current_mrq; 455baf8532aSAlex Dubov card->next_request = msb->mrq_handler; 456baf8532aSAlex Dubov return 0; 457baf8532aSAlex Dubov } 458baf8532aSAlex Dubov 459baf8532aSAlex Dubov static int h_mspro_block_default(struct memstick_dev *card, 460baf8532aSAlex Dubov struct memstick_request **mrq) 461baf8532aSAlex Dubov { 462baf8532aSAlex Dubov complete(&card->mrq_complete); 463baf8532aSAlex Dubov if (!(*mrq)->error) 464baf8532aSAlex Dubov return -EAGAIN; 465baf8532aSAlex Dubov else 466baf8532aSAlex Dubov return (*mrq)->error; 467baf8532aSAlex Dubov } 468baf8532aSAlex Dubov 469baf8532aSAlex Dubov static int h_mspro_block_get_ro(struct memstick_dev *card, 470baf8532aSAlex Dubov struct memstick_request **mrq) 471baf8532aSAlex Dubov { 472baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 473baf8532aSAlex Dubov 474baf8532aSAlex Dubov if ((*mrq)->error) { 475baf8532aSAlex Dubov complete(&card->mrq_complete); 476baf8532aSAlex Dubov return (*mrq)->error; 477baf8532aSAlex Dubov } 478baf8532aSAlex Dubov 479baf8532aSAlex Dubov if ((*mrq)->data[offsetof(struct ms_status_register, status0)] 480baf8532aSAlex Dubov & MEMSTICK_STATUS0_WP) 481baf8532aSAlex Dubov msb->read_only = 1; 482baf8532aSAlex Dubov else 483baf8532aSAlex Dubov msb->read_only = 0; 484baf8532aSAlex Dubov 485baf8532aSAlex Dubov complete(&card->mrq_complete); 486baf8532aSAlex Dubov return -EAGAIN; 487baf8532aSAlex Dubov } 488baf8532aSAlex Dubov 489baf8532aSAlex Dubov static int h_mspro_block_wait_for_ced(struct memstick_dev *card, 490baf8532aSAlex Dubov struct memstick_request **mrq) 491baf8532aSAlex Dubov { 492baf8532aSAlex Dubov if ((*mrq)->error) { 493baf8532aSAlex Dubov complete(&card->mrq_complete); 494baf8532aSAlex Dubov return (*mrq)->error; 495baf8532aSAlex Dubov } 496baf8532aSAlex Dubov 497baf8532aSAlex Dubov dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]); 498baf8532aSAlex Dubov 499baf8532aSAlex Dubov if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) { 500baf8532aSAlex Dubov card->current_mrq.error = -EFAULT; 501baf8532aSAlex Dubov complete(&card->mrq_complete); 502baf8532aSAlex Dubov return card->current_mrq.error; 503baf8532aSAlex Dubov } 504baf8532aSAlex Dubov 505baf8532aSAlex Dubov if (!((*mrq)->data[0] & MEMSTICK_INT_CED)) 506baf8532aSAlex Dubov return 0; 507baf8532aSAlex Dubov else { 508baf8532aSAlex Dubov card->current_mrq.error = 0; 509baf8532aSAlex Dubov complete(&card->mrq_complete); 510baf8532aSAlex Dubov return -EAGAIN; 511baf8532aSAlex Dubov } 512baf8532aSAlex Dubov } 513baf8532aSAlex Dubov 514baf8532aSAlex Dubov static int h_mspro_block_transfer_data(struct memstick_dev *card, 515baf8532aSAlex Dubov struct memstick_request **mrq) 516baf8532aSAlex Dubov { 517baf8532aSAlex Dubov struct memstick_host *host = card->host; 518baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 519baf8532aSAlex Dubov unsigned char t_val = 0; 520baf8532aSAlex Dubov struct scatterlist t_sg = { 0 }; 521baf8532aSAlex Dubov size_t t_offset; 522baf8532aSAlex Dubov 523baf8532aSAlex Dubov if ((*mrq)->error) { 524baf8532aSAlex Dubov complete(&card->mrq_complete); 525baf8532aSAlex Dubov return (*mrq)->error; 526baf8532aSAlex Dubov } 527baf8532aSAlex Dubov 528baf8532aSAlex Dubov switch ((*mrq)->tpc) { 529baf8532aSAlex Dubov case MS_TPC_WRITE_REG: 530baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1); 531baf8532aSAlex Dubov (*mrq)->get_int_reg = 1; 532baf8532aSAlex Dubov return 0; 533baf8532aSAlex Dubov case MS_TPC_SET_CMD: 534baf8532aSAlex Dubov t_val = (*mrq)->int_reg; 535baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); 536baf8532aSAlex Dubov if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) 537baf8532aSAlex Dubov goto has_int_reg; 538baf8532aSAlex Dubov return 0; 539baf8532aSAlex Dubov case MS_TPC_GET_INT: 540baf8532aSAlex Dubov t_val = (*mrq)->data[0]; 541baf8532aSAlex Dubov has_int_reg: 542baf8532aSAlex Dubov if (t_val & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) { 543baf8532aSAlex Dubov t_val = MSPRO_CMD_STOP; 544baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_SET_CMD, &t_val, 1); 545baf8532aSAlex Dubov card->next_request = h_mspro_block_default; 546baf8532aSAlex Dubov return 0; 547baf8532aSAlex Dubov } 548baf8532aSAlex Dubov 549baf8532aSAlex Dubov if (msb->current_page 550baf8532aSAlex Dubov == (msb->req_sg[msb->current_seg].length 551baf8532aSAlex Dubov / msb->page_size)) { 552baf8532aSAlex Dubov msb->current_page = 0; 553baf8532aSAlex Dubov msb->current_seg++; 554baf8532aSAlex Dubov 555baf8532aSAlex Dubov if (msb->current_seg == msb->seg_count) { 556baf8532aSAlex Dubov if (t_val & MEMSTICK_INT_CED) { 557baf8532aSAlex Dubov complete(&card->mrq_complete); 558baf8532aSAlex Dubov return -EAGAIN; 559baf8532aSAlex Dubov } else { 560baf8532aSAlex Dubov card->next_request 561baf8532aSAlex Dubov = h_mspro_block_wait_for_ced; 562baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, 563baf8532aSAlex Dubov NULL, 1); 564baf8532aSAlex Dubov return 0; 565baf8532aSAlex Dubov } 566baf8532aSAlex Dubov } 567baf8532aSAlex Dubov } 568baf8532aSAlex Dubov 569baf8532aSAlex Dubov if (!(t_val & MEMSTICK_INT_BREQ)) { 570baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); 571baf8532aSAlex Dubov return 0; 572baf8532aSAlex Dubov } 573baf8532aSAlex Dubov 574baf8532aSAlex Dubov t_offset = msb->req_sg[msb->current_seg].offset; 575baf8532aSAlex Dubov t_offset += msb->current_page * msb->page_size; 576baf8532aSAlex Dubov 577baf8532aSAlex Dubov sg_set_page(&t_sg, 578baf8532aSAlex Dubov nth_page(sg_page(&(msb->req_sg[msb->current_seg])), 579baf8532aSAlex Dubov t_offset >> PAGE_SHIFT), 580baf8532aSAlex Dubov msb->page_size, offset_in_page(t_offset)); 581baf8532aSAlex Dubov 582baf8532aSAlex Dubov memstick_init_req_sg(*mrq, msb->data_dir == READ 583baf8532aSAlex Dubov ? MS_TPC_READ_LONG_DATA 584baf8532aSAlex Dubov : MS_TPC_WRITE_LONG_DATA, 585baf8532aSAlex Dubov &t_sg); 586baf8532aSAlex Dubov (*mrq)->get_int_reg = 1; 587baf8532aSAlex Dubov return 0; 588baf8532aSAlex Dubov case MS_TPC_READ_LONG_DATA: 589baf8532aSAlex Dubov case MS_TPC_WRITE_LONG_DATA: 590baf8532aSAlex Dubov msb->current_page++; 591baf8532aSAlex Dubov if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) { 592baf8532aSAlex Dubov t_val = (*mrq)->int_reg; 593baf8532aSAlex Dubov goto has_int_reg; 594baf8532aSAlex Dubov } else { 595baf8532aSAlex Dubov memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1); 596baf8532aSAlex Dubov return 0; 597baf8532aSAlex Dubov } 598baf8532aSAlex Dubov 599baf8532aSAlex Dubov default: 600baf8532aSAlex Dubov BUG(); 601baf8532aSAlex Dubov } 602baf8532aSAlex Dubov } 603baf8532aSAlex Dubov 604baf8532aSAlex Dubov /*** Data transfer ***/ 605baf8532aSAlex Dubov 606baf8532aSAlex Dubov static void mspro_block_process_request(struct memstick_dev *card, 607baf8532aSAlex Dubov struct request *req) 608baf8532aSAlex Dubov { 609baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 610baf8532aSAlex Dubov struct mspro_param_register param; 611baf8532aSAlex Dubov int rc, chunk, cnt; 612baf8532aSAlex Dubov unsigned short page_count; 613baf8532aSAlex Dubov sector_t t_sec; 614baf8532aSAlex Dubov unsigned long flags; 615baf8532aSAlex Dubov 616baf8532aSAlex Dubov do { 617baf8532aSAlex Dubov page_count = 0; 618baf8532aSAlex Dubov msb->current_seg = 0; 619baf8532aSAlex Dubov msb->seg_count = blk_rq_map_sg(req->q, req, msb->req_sg); 620baf8532aSAlex Dubov 621baf8532aSAlex Dubov if (msb->seg_count) { 622baf8532aSAlex Dubov msb->current_page = 0; 623baf8532aSAlex Dubov for (rc = 0; rc < msb->seg_count; rc++) 624baf8532aSAlex Dubov page_count += msb->req_sg[rc].length 625baf8532aSAlex Dubov / msb->page_size; 626baf8532aSAlex Dubov 627baf8532aSAlex Dubov t_sec = req->sector; 628baf8532aSAlex Dubov sector_div(t_sec, msb->page_size >> 9); 629baf8532aSAlex Dubov param.system = msb->system; 630baf8532aSAlex Dubov param.data_count = cpu_to_be16(page_count); 631baf8532aSAlex Dubov param.data_address = cpu_to_be32((uint32_t)t_sec); 632baf8532aSAlex Dubov param.cmd_param = 0; 633baf8532aSAlex Dubov 634baf8532aSAlex Dubov msb->data_dir = rq_data_dir(req); 635baf8532aSAlex Dubov msb->transfer_cmd = msb->data_dir == READ 636baf8532aSAlex Dubov ? MSPRO_CMD_READ_DATA 637baf8532aSAlex Dubov : MSPRO_CMD_WRITE_DATA; 638baf8532aSAlex Dubov 639baf8532aSAlex Dubov dev_dbg(&card->dev, "data transfer: cmd %x, " 640baf8532aSAlex Dubov "lba %x, count %x\n", msb->transfer_cmd, 641baf8532aSAlex Dubov be32_to_cpu(param.data_address), 642baf8532aSAlex Dubov page_count); 643baf8532aSAlex Dubov 644baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 645baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_transfer_data; 646baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, 647baf8532aSAlex Dubov ¶m, sizeof(param)); 648baf8532aSAlex Dubov memstick_new_req(card->host); 649baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 650baf8532aSAlex Dubov rc = card->current_mrq.error; 651baf8532aSAlex Dubov 652baf8532aSAlex Dubov if (rc || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { 653baf8532aSAlex Dubov for (cnt = 0; cnt < msb->current_seg; cnt++) 654baf8532aSAlex Dubov page_count += msb->req_sg[cnt].length 655baf8532aSAlex Dubov / msb->page_size; 656baf8532aSAlex Dubov 657baf8532aSAlex Dubov if (msb->current_page) 658baf8532aSAlex Dubov page_count += msb->current_page - 1; 659baf8532aSAlex Dubov 660baf8532aSAlex Dubov if (page_count && (msb->data_dir == READ)) 661baf8532aSAlex Dubov rc = msb->page_size * page_count; 662baf8532aSAlex Dubov else 663baf8532aSAlex Dubov rc = -EIO; 664baf8532aSAlex Dubov } else 665baf8532aSAlex Dubov rc = msb->page_size * page_count; 666baf8532aSAlex Dubov } else 667baf8532aSAlex Dubov rc = -EFAULT; 668baf8532aSAlex Dubov 669baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 670baf8532aSAlex Dubov if (rc >= 0) 671baf8532aSAlex Dubov chunk = __blk_end_request(req, 0, rc); 672baf8532aSAlex Dubov else 673baf8532aSAlex Dubov chunk = __blk_end_request(req, rc, 0); 674baf8532aSAlex Dubov 675baf8532aSAlex Dubov dev_dbg(&card->dev, "end chunk %d, %d\n", rc, chunk); 676baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 677baf8532aSAlex Dubov } while (chunk); 678baf8532aSAlex Dubov } 679baf8532aSAlex Dubov 680baf8532aSAlex Dubov static int mspro_block_has_request(struct mspro_block_data *msb) 681baf8532aSAlex Dubov { 682baf8532aSAlex Dubov int rc = 0; 683baf8532aSAlex Dubov unsigned long flags; 684baf8532aSAlex Dubov 685baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 686baf8532aSAlex Dubov if (kthread_should_stop() || msb->has_request) 687baf8532aSAlex Dubov rc = 1; 688baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 689baf8532aSAlex Dubov return rc; 690baf8532aSAlex Dubov } 691baf8532aSAlex Dubov 692baf8532aSAlex Dubov static int mspro_block_queue_thread(void *data) 693baf8532aSAlex Dubov { 694baf8532aSAlex Dubov struct memstick_dev *card = data; 695baf8532aSAlex Dubov struct memstick_host *host = card->host; 696baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 697baf8532aSAlex Dubov struct request *req; 698baf8532aSAlex Dubov unsigned long flags; 699baf8532aSAlex Dubov 700baf8532aSAlex Dubov while (1) { 701baf8532aSAlex Dubov wait_event(msb->q_wait, mspro_block_has_request(msb)); 702baf8532aSAlex Dubov dev_dbg(&card->dev, "thread iter\n"); 703baf8532aSAlex Dubov 704baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 705baf8532aSAlex Dubov req = elv_next_request(msb->queue); 706baf8532aSAlex Dubov dev_dbg(&card->dev, "next req %p\n", req); 707baf8532aSAlex Dubov if (!req) { 708baf8532aSAlex Dubov msb->has_request = 0; 709baf8532aSAlex Dubov if (kthread_should_stop()) { 710baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 711baf8532aSAlex Dubov break; 712baf8532aSAlex Dubov } 713baf8532aSAlex Dubov } else 714baf8532aSAlex Dubov msb->has_request = 1; 715baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 716baf8532aSAlex Dubov 717baf8532aSAlex Dubov if (req) { 718baf8532aSAlex Dubov mutex_lock(&host->lock); 719baf8532aSAlex Dubov mspro_block_process_request(card, req); 720baf8532aSAlex Dubov mutex_unlock(&host->lock); 721baf8532aSAlex Dubov } 722baf8532aSAlex Dubov } 723baf8532aSAlex Dubov dev_dbg(&card->dev, "thread finished\n"); 724baf8532aSAlex Dubov return 0; 725baf8532aSAlex Dubov } 726baf8532aSAlex Dubov 727baf8532aSAlex Dubov static void mspro_block_request(struct request_queue *q) 728baf8532aSAlex Dubov { 729baf8532aSAlex Dubov struct memstick_dev *card = q->queuedata; 730baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 731baf8532aSAlex Dubov struct request *req = NULL; 732baf8532aSAlex Dubov 733baf8532aSAlex Dubov if (msb->q_thread) { 734baf8532aSAlex Dubov msb->has_request = 1; 735baf8532aSAlex Dubov wake_up_all(&msb->q_wait); 736baf8532aSAlex Dubov } else { 737baf8532aSAlex Dubov while ((req = elv_next_request(q)) != NULL) 738baf8532aSAlex Dubov end_queued_request(req, -ENODEV); 739baf8532aSAlex Dubov } 740baf8532aSAlex Dubov } 741baf8532aSAlex Dubov 742baf8532aSAlex Dubov /*** Initialization ***/ 743baf8532aSAlex Dubov 744baf8532aSAlex Dubov static int mspro_block_wait_for_ced(struct memstick_dev *card) 745baf8532aSAlex Dubov { 746baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 747baf8532aSAlex Dubov 748baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 749baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_wait_for_ced; 750baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); 751baf8532aSAlex Dubov memstick_new_req(card->host); 752baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 753baf8532aSAlex Dubov return card->current_mrq.error; 754baf8532aSAlex Dubov } 755baf8532aSAlex Dubov 756baf8532aSAlex Dubov static int mspro_block_switch_to_parallel(struct memstick_dev *card) 757baf8532aSAlex Dubov { 758baf8532aSAlex Dubov struct memstick_host *host = card->host; 759baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 760baf8532aSAlex Dubov struct mspro_param_register param = { 761baf8532aSAlex Dubov .system = 0, 762baf8532aSAlex Dubov .data_count = 0, 763baf8532aSAlex Dubov .data_address = 0, 764baf8532aSAlex Dubov .cmd_param = 0 765baf8532aSAlex Dubov }; 766baf8532aSAlex Dubov 767baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 768baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_default; 769baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, 770baf8532aSAlex Dubov sizeof(param)); 771baf8532aSAlex Dubov memstick_new_req(host); 772baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 773baf8532aSAlex Dubov if (card->current_mrq.error) 774baf8532aSAlex Dubov return card->current_mrq.error; 775baf8532aSAlex Dubov 776baf8532aSAlex Dubov msb->system = 0; 777baf8532aSAlex Dubov host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PARALLEL); 778baf8532aSAlex Dubov 779baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 780baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_default; 781baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1); 782baf8532aSAlex Dubov memstick_new_req(card->host); 783baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 784baf8532aSAlex Dubov 785baf8532aSAlex Dubov if (card->current_mrq.error) { 786baf8532aSAlex Dubov msb->system = 0x80; 787baf8532aSAlex Dubov host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL); 788baf8532aSAlex Dubov return -EFAULT; 789baf8532aSAlex Dubov } 790baf8532aSAlex Dubov 791baf8532aSAlex Dubov return 0; 792baf8532aSAlex Dubov } 793baf8532aSAlex Dubov 794baf8532aSAlex Dubov /* Memory allocated for attributes by this function should be freed by 795baf8532aSAlex Dubov * mspro_block_data_clear, no matter if the initialization process succeded 796baf8532aSAlex Dubov * or failed. 797baf8532aSAlex Dubov */ 798baf8532aSAlex Dubov static int mspro_block_read_attributes(struct memstick_dev *card) 799baf8532aSAlex Dubov { 800baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 801baf8532aSAlex Dubov struct mspro_param_register param = { 802baf8532aSAlex Dubov .system = msb->system, 803baf8532aSAlex Dubov .data_count = cpu_to_be16(1), 804baf8532aSAlex Dubov .data_address = 0, 805baf8532aSAlex Dubov .cmd_param = 0 806baf8532aSAlex Dubov }; 807baf8532aSAlex Dubov struct mspro_attribute *attr = NULL; 808baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = NULL; 809baf8532aSAlex Dubov unsigned char *buffer = NULL; 810baf8532aSAlex Dubov int cnt, rc, attr_count; 811baf8532aSAlex Dubov unsigned int addr; 812baf8532aSAlex Dubov unsigned short page_count; 813baf8532aSAlex Dubov 814baf8532aSAlex Dubov attr = kmalloc(msb->page_size, GFP_KERNEL); 815baf8532aSAlex Dubov if (!attr) 816baf8532aSAlex Dubov return -ENOMEM; 817baf8532aSAlex Dubov 818baf8532aSAlex Dubov sg_init_one(&msb->req_sg[0], attr, msb->page_size); 819baf8532aSAlex Dubov msb->seg_count = 1; 820baf8532aSAlex Dubov msb->current_seg = 0; 821baf8532aSAlex Dubov msb->current_page = 0; 822baf8532aSAlex Dubov msb->data_dir = READ; 823baf8532aSAlex Dubov msb->transfer_cmd = MSPRO_CMD_READ_ATRB; 824baf8532aSAlex Dubov 825baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 826baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_transfer_data; 827baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, 828baf8532aSAlex Dubov sizeof(param)); 829baf8532aSAlex Dubov memstick_new_req(card->host); 830baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 831baf8532aSAlex Dubov if (card->current_mrq.error) { 832baf8532aSAlex Dubov rc = card->current_mrq.error; 833baf8532aSAlex Dubov goto out_free_attr; 834baf8532aSAlex Dubov } 835baf8532aSAlex Dubov 836baf8532aSAlex Dubov if (be16_to_cpu(attr->signature) != MSPRO_BLOCK_SIGNATURE) { 837baf8532aSAlex Dubov printk(KERN_ERR "%s: unrecognized device signature %x\n", 838baf8532aSAlex Dubov card->dev.bus_id, be16_to_cpu(attr->signature)); 839baf8532aSAlex Dubov rc = -ENODEV; 840baf8532aSAlex Dubov goto out_free_attr; 841baf8532aSAlex Dubov } 842baf8532aSAlex Dubov 843baf8532aSAlex Dubov if (attr->count > MSPRO_BLOCK_MAX_ATTRIBUTES) { 844baf8532aSAlex Dubov printk(KERN_WARNING "%s: way too many attribute entries\n", 845baf8532aSAlex Dubov card->dev.bus_id); 846baf8532aSAlex Dubov attr_count = MSPRO_BLOCK_MAX_ATTRIBUTES; 847baf8532aSAlex Dubov } else 848baf8532aSAlex Dubov attr_count = attr->count; 849baf8532aSAlex Dubov 850baf8532aSAlex Dubov msb->attr_group.attrs = kzalloc((attr_count + 1) 851baf8532aSAlex Dubov * sizeof(struct attribute), 852baf8532aSAlex Dubov GFP_KERNEL); 853baf8532aSAlex Dubov if (!msb->attr_group.attrs) { 854baf8532aSAlex Dubov rc = -ENOMEM; 855baf8532aSAlex Dubov goto out_free_attr; 856baf8532aSAlex Dubov } 857baf8532aSAlex Dubov msb->attr_group.name = "media_attributes"; 858baf8532aSAlex Dubov 859baf8532aSAlex Dubov buffer = kmalloc(msb->page_size, GFP_KERNEL); 860baf8532aSAlex Dubov if (!buffer) { 861baf8532aSAlex Dubov rc = -ENOMEM; 862baf8532aSAlex Dubov goto out_free_attr; 863baf8532aSAlex Dubov } 864baf8532aSAlex Dubov memcpy(buffer, (char *)attr, msb->page_size); 865baf8532aSAlex Dubov page_count = 1; 866baf8532aSAlex Dubov 867baf8532aSAlex Dubov for (cnt = 0; cnt < attr_count; ++cnt) { 868baf8532aSAlex Dubov s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL); 869baf8532aSAlex Dubov if (!s_attr) { 870baf8532aSAlex Dubov rc = -ENOMEM; 871baf8532aSAlex Dubov goto out_free_buffer; 872baf8532aSAlex Dubov } 873baf8532aSAlex Dubov 874baf8532aSAlex Dubov msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr; 875baf8532aSAlex Dubov addr = be32_to_cpu(attr->entries[cnt].address); 876baf8532aSAlex Dubov rc = be32_to_cpu(attr->entries[cnt].size); 877baf8532aSAlex Dubov dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, " 878baf8532aSAlex Dubov "size %x\n", cnt, attr->entries[cnt].id, addr, rc); 879baf8532aSAlex Dubov s_attr->id = attr->entries[cnt].id; 880baf8532aSAlex Dubov if (mspro_block_attr_name(s_attr->id)) 881baf8532aSAlex Dubov snprintf(s_attr->name, sizeof(s_attr->name), "%s", 882baf8532aSAlex Dubov mspro_block_attr_name(attr->entries[cnt].id)); 883baf8532aSAlex Dubov else 884baf8532aSAlex Dubov snprintf(s_attr->name, sizeof(s_attr->name), 885baf8532aSAlex Dubov "attr_x%02x", attr->entries[cnt].id); 886baf8532aSAlex Dubov 887baf8532aSAlex Dubov s_attr->dev_attr.attr.name = s_attr->name; 888baf8532aSAlex Dubov s_attr->dev_attr.attr.mode = S_IRUGO; 889baf8532aSAlex Dubov s_attr->dev_attr.attr.owner = THIS_MODULE; 890baf8532aSAlex Dubov s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); 891baf8532aSAlex Dubov 892baf8532aSAlex Dubov if (!rc) 893baf8532aSAlex Dubov continue; 894baf8532aSAlex Dubov 895baf8532aSAlex Dubov s_attr->size = rc; 896baf8532aSAlex Dubov s_attr->data = kmalloc(rc, GFP_KERNEL); 897baf8532aSAlex Dubov if (!s_attr->data) { 898baf8532aSAlex Dubov rc = -ENOMEM; 899baf8532aSAlex Dubov goto out_free_buffer; 900baf8532aSAlex Dubov } 901baf8532aSAlex Dubov 902baf8532aSAlex Dubov if (((addr / msb->page_size) 903baf8532aSAlex Dubov == be32_to_cpu(param.data_address)) 904baf8532aSAlex Dubov && (((addr + rc - 1) / msb->page_size) 905baf8532aSAlex Dubov == be32_to_cpu(param.data_address))) { 906baf8532aSAlex Dubov memcpy(s_attr->data, buffer + addr % msb->page_size, 907baf8532aSAlex Dubov rc); 908baf8532aSAlex Dubov continue; 909baf8532aSAlex Dubov } 910baf8532aSAlex Dubov 911baf8532aSAlex Dubov if (page_count <= (rc / msb->page_size)) { 912baf8532aSAlex Dubov kfree(buffer); 913baf8532aSAlex Dubov page_count = (rc / msb->page_size) + 1; 914baf8532aSAlex Dubov buffer = kmalloc(page_count * msb->page_size, 915baf8532aSAlex Dubov GFP_KERNEL); 916baf8532aSAlex Dubov if (!buffer) { 917baf8532aSAlex Dubov rc = -ENOMEM; 918baf8532aSAlex Dubov goto out_free_attr; 919baf8532aSAlex Dubov } 920baf8532aSAlex Dubov } 921baf8532aSAlex Dubov 922baf8532aSAlex Dubov param.system = msb->system; 923baf8532aSAlex Dubov param.data_count = cpu_to_be16((rc / msb->page_size) + 1); 924baf8532aSAlex Dubov param.data_address = cpu_to_be32(addr / msb->page_size); 925baf8532aSAlex Dubov param.cmd_param = 0; 926baf8532aSAlex Dubov 927baf8532aSAlex Dubov sg_init_one(&msb->req_sg[0], buffer, 928baf8532aSAlex Dubov be16_to_cpu(param.data_count) * msb->page_size); 929baf8532aSAlex Dubov msb->seg_count = 1; 930baf8532aSAlex Dubov msb->current_seg = 0; 931baf8532aSAlex Dubov msb->current_page = 0; 932baf8532aSAlex Dubov msb->data_dir = READ; 933baf8532aSAlex Dubov msb->transfer_cmd = MSPRO_CMD_READ_ATRB; 934baf8532aSAlex Dubov 935baf8532aSAlex Dubov dev_dbg(&card->dev, "reading attribute pages %x, %x\n", 936baf8532aSAlex Dubov be32_to_cpu(param.data_address), 937baf8532aSAlex Dubov be16_to_cpu(param.data_count)); 938baf8532aSAlex Dubov 939baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 940baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_transfer_data; 941baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, 942baf8532aSAlex Dubov (char *)¶m, sizeof(param)); 943baf8532aSAlex Dubov memstick_new_req(card->host); 944baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 945baf8532aSAlex Dubov if (card->current_mrq.error) { 946baf8532aSAlex Dubov rc = card->current_mrq.error; 947baf8532aSAlex Dubov goto out_free_buffer; 948baf8532aSAlex Dubov } 949baf8532aSAlex Dubov 950baf8532aSAlex Dubov memcpy(s_attr->data, buffer + addr % msb->page_size, rc); 951baf8532aSAlex Dubov } 952baf8532aSAlex Dubov 953baf8532aSAlex Dubov rc = 0; 954baf8532aSAlex Dubov out_free_buffer: 955baf8532aSAlex Dubov kfree(buffer); 956baf8532aSAlex Dubov out_free_attr: 957baf8532aSAlex Dubov kfree(attr); 958baf8532aSAlex Dubov return rc; 959baf8532aSAlex Dubov } 960baf8532aSAlex Dubov 961baf8532aSAlex Dubov static int mspro_block_init_card(struct memstick_dev *card) 962baf8532aSAlex Dubov { 963baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 964baf8532aSAlex Dubov struct memstick_host *host = card->host; 965baf8532aSAlex Dubov int rc = 0; 966baf8532aSAlex Dubov 967baf8532aSAlex Dubov msb->system = 0x80; 968baf8532aSAlex Dubov card->reg_addr.r_offset = offsetof(struct mspro_register, status); 969baf8532aSAlex Dubov card->reg_addr.r_length = sizeof(struct ms_status_register); 970baf8532aSAlex Dubov card->reg_addr.w_offset = offsetof(struct mspro_register, param); 971baf8532aSAlex Dubov card->reg_addr.w_length = sizeof(struct mspro_param_register); 972baf8532aSAlex Dubov 973baf8532aSAlex Dubov if (memstick_set_rw_addr(card)) 974baf8532aSAlex Dubov return -EIO; 975baf8532aSAlex Dubov 976baf8532aSAlex Dubov if (host->caps & MEMSTICK_CAP_PARALLEL) { 977baf8532aSAlex Dubov if (mspro_block_switch_to_parallel(card)) 978baf8532aSAlex Dubov printk(KERN_WARNING "%s: could not switch to " 979baf8532aSAlex Dubov "parallel interface\n", card->dev.bus_id); 980baf8532aSAlex Dubov } 981baf8532aSAlex Dubov 982baf8532aSAlex Dubov rc = mspro_block_wait_for_ced(card); 983baf8532aSAlex Dubov if (rc) 984baf8532aSAlex Dubov return rc; 985baf8532aSAlex Dubov dev_dbg(&card->dev, "card activated\n"); 986baf8532aSAlex Dubov 987baf8532aSAlex Dubov card->next_request = h_mspro_block_req_init; 988baf8532aSAlex Dubov msb->mrq_handler = h_mspro_block_get_ro; 989baf8532aSAlex Dubov memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL, 990baf8532aSAlex Dubov sizeof(struct ms_status_register)); 991baf8532aSAlex Dubov memstick_new_req(card->host); 992baf8532aSAlex Dubov wait_for_completion(&card->mrq_complete); 993baf8532aSAlex Dubov if (card->current_mrq.error) 994baf8532aSAlex Dubov return card->current_mrq.error; 995baf8532aSAlex Dubov 996baf8532aSAlex Dubov dev_dbg(&card->dev, "card r/w status %d\n", msb->read_only ? 0 : 1); 997baf8532aSAlex Dubov 998baf8532aSAlex Dubov msb->page_size = 512; 999baf8532aSAlex Dubov rc = mspro_block_read_attributes(card); 1000baf8532aSAlex Dubov if (rc) 1001baf8532aSAlex Dubov return rc; 1002baf8532aSAlex Dubov 1003baf8532aSAlex Dubov dev_dbg(&card->dev, "attributes loaded\n"); 1004baf8532aSAlex Dubov return 0; 1005baf8532aSAlex Dubov 1006baf8532aSAlex Dubov } 1007baf8532aSAlex Dubov 1008baf8532aSAlex Dubov static int mspro_block_init_disk(struct memstick_dev *card) 1009baf8532aSAlex Dubov { 1010baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1011baf8532aSAlex Dubov struct memstick_host *host = card->host; 1012baf8532aSAlex Dubov struct mspro_devinfo *dev_info = NULL; 1013baf8532aSAlex Dubov struct mspro_sys_info *sys_info = NULL; 1014baf8532aSAlex Dubov struct mspro_sys_attr *s_attr = NULL; 1015baf8532aSAlex Dubov int rc, disk_id; 1016baf8532aSAlex Dubov u64 limit = BLK_BOUNCE_HIGH; 1017baf8532aSAlex Dubov unsigned long capacity; 1018baf8532aSAlex Dubov 1019baf8532aSAlex Dubov if (host->cdev.dev->dma_mask && *(host->cdev.dev->dma_mask)) 1020baf8532aSAlex Dubov limit = *(host->cdev.dev->dma_mask); 1021baf8532aSAlex Dubov 1022baf8532aSAlex Dubov for (rc = 0; msb->attr_group.attrs[rc]; ++rc) { 1023baf8532aSAlex Dubov s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]); 1024baf8532aSAlex Dubov 1025baf8532aSAlex Dubov if (s_attr->id == MSPRO_BLOCK_ID_DEVINFO) 1026baf8532aSAlex Dubov dev_info = s_attr->data; 1027baf8532aSAlex Dubov else if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO) 1028baf8532aSAlex Dubov sys_info = s_attr->data; 1029baf8532aSAlex Dubov } 1030baf8532aSAlex Dubov 1031baf8532aSAlex Dubov if (!dev_info || !sys_info) 1032baf8532aSAlex Dubov return -ENODEV; 1033baf8532aSAlex Dubov 1034baf8532aSAlex Dubov msb->cylinders = be16_to_cpu(dev_info->cylinders); 1035baf8532aSAlex Dubov msb->heads = be16_to_cpu(dev_info->heads); 1036baf8532aSAlex Dubov msb->sectors_per_track = be16_to_cpu(dev_info->sectors_per_track); 1037baf8532aSAlex Dubov 1038baf8532aSAlex Dubov msb->page_size = be16_to_cpu(sys_info->unit_size); 1039baf8532aSAlex Dubov 1040baf8532aSAlex Dubov if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) 1041baf8532aSAlex Dubov return -ENOMEM; 1042baf8532aSAlex Dubov 1043baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 1044baf8532aSAlex Dubov rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id); 1045baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 1046baf8532aSAlex Dubov 1047baf8532aSAlex Dubov if (rc) 1048baf8532aSAlex Dubov return rc; 1049baf8532aSAlex Dubov 1050baf8532aSAlex Dubov if ((disk_id << MEMSTICK_PART_SHIFT) > 255) { 1051baf8532aSAlex Dubov rc = -ENOSPC; 1052baf8532aSAlex Dubov goto out_release_id; 1053baf8532aSAlex Dubov } 1054baf8532aSAlex Dubov 1055baf8532aSAlex Dubov msb->disk = alloc_disk(1 << MEMSTICK_PART_SHIFT); 1056baf8532aSAlex Dubov if (!msb->disk) { 1057baf8532aSAlex Dubov rc = -ENOMEM; 1058baf8532aSAlex Dubov goto out_release_id; 1059baf8532aSAlex Dubov } 1060baf8532aSAlex Dubov 1061baf8532aSAlex Dubov spin_lock_init(&msb->q_lock); 1062baf8532aSAlex Dubov init_waitqueue_head(&msb->q_wait); 1063baf8532aSAlex Dubov 1064baf8532aSAlex Dubov msb->queue = blk_init_queue(mspro_block_request, &msb->q_lock); 1065baf8532aSAlex Dubov if (!msb->queue) { 1066baf8532aSAlex Dubov rc = -ENOMEM; 1067baf8532aSAlex Dubov goto out_put_disk; 1068baf8532aSAlex Dubov } 1069baf8532aSAlex Dubov 1070baf8532aSAlex Dubov msb->queue->queuedata = card; 1071baf8532aSAlex Dubov 1072baf8532aSAlex Dubov blk_queue_bounce_limit(msb->queue, limit); 1073baf8532aSAlex Dubov blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES); 1074baf8532aSAlex Dubov blk_queue_max_phys_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS); 1075baf8532aSAlex Dubov blk_queue_max_hw_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS); 1076baf8532aSAlex Dubov blk_queue_max_segment_size(msb->queue, 1077baf8532aSAlex Dubov MSPRO_BLOCK_MAX_PAGES * msb->page_size); 1078baf8532aSAlex Dubov 1079baf8532aSAlex Dubov msb->disk->major = major; 1080baf8532aSAlex Dubov msb->disk->first_minor = disk_id << MEMSTICK_PART_SHIFT; 1081baf8532aSAlex Dubov msb->disk->fops = &ms_block_bdops; 1082baf8532aSAlex Dubov msb->usage_count = 1; 1083baf8532aSAlex Dubov msb->disk->private_data = msb; 1084baf8532aSAlex Dubov msb->disk->queue = msb->queue; 1085baf8532aSAlex Dubov msb->disk->driverfs_dev = &card->dev; 1086baf8532aSAlex Dubov 1087baf8532aSAlex Dubov sprintf(msb->disk->disk_name, "mspblk%d", disk_id); 1088baf8532aSAlex Dubov 1089baf8532aSAlex Dubov blk_queue_hardsect_size(msb->queue, msb->page_size); 1090baf8532aSAlex Dubov 1091baf8532aSAlex Dubov capacity = be16_to_cpu(sys_info->user_block_count); 1092baf8532aSAlex Dubov capacity *= be16_to_cpu(sys_info->block_size); 1093baf8532aSAlex Dubov capacity *= msb->page_size >> 9; 1094baf8532aSAlex Dubov set_capacity(msb->disk, capacity); 1095baf8532aSAlex Dubov dev_dbg(&card->dev, "capacity set %ld\n", capacity); 1096baf8532aSAlex Dubov msb->q_thread = kthread_run(mspro_block_queue_thread, card, 1097baf8532aSAlex Dubov DRIVER_NAME"d"); 1098baf8532aSAlex Dubov if (IS_ERR(msb->q_thread)) 1099baf8532aSAlex Dubov goto out_put_disk; 1100baf8532aSAlex Dubov 1101baf8532aSAlex Dubov mutex_unlock(&host->lock); 1102baf8532aSAlex Dubov add_disk(msb->disk); 1103baf8532aSAlex Dubov mutex_lock(&host->lock); 1104baf8532aSAlex Dubov msb->active = 1; 1105baf8532aSAlex Dubov return 0; 1106baf8532aSAlex Dubov 1107baf8532aSAlex Dubov out_put_disk: 1108baf8532aSAlex Dubov put_disk(msb->disk); 1109baf8532aSAlex Dubov out_release_id: 1110baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 1111baf8532aSAlex Dubov idr_remove(&mspro_block_disk_idr, disk_id); 1112baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 1113baf8532aSAlex Dubov return rc; 1114baf8532aSAlex Dubov } 1115baf8532aSAlex Dubov 1116baf8532aSAlex Dubov static void mspro_block_data_clear(struct mspro_block_data *msb) 1117baf8532aSAlex Dubov { 1118baf8532aSAlex Dubov int cnt; 1119baf8532aSAlex Dubov struct mspro_sys_attr *s_attr; 1120baf8532aSAlex Dubov 1121baf8532aSAlex Dubov if (msb->attr_group.attrs) { 1122baf8532aSAlex Dubov for (cnt = 0; msb->attr_group.attrs[cnt]; ++cnt) { 1123baf8532aSAlex Dubov s_attr = mspro_from_sysfs_attr(msb->attr_group 1124baf8532aSAlex Dubov .attrs[cnt]); 1125baf8532aSAlex Dubov kfree(s_attr->data); 1126baf8532aSAlex Dubov kfree(s_attr); 1127baf8532aSAlex Dubov } 1128baf8532aSAlex Dubov kfree(msb->attr_group.attrs); 1129baf8532aSAlex Dubov } 1130baf8532aSAlex Dubov 1131baf8532aSAlex Dubov msb->card = NULL; 1132baf8532aSAlex Dubov } 1133baf8532aSAlex Dubov 1134baf8532aSAlex Dubov static int mspro_block_check_card(struct memstick_dev *card) 1135baf8532aSAlex Dubov { 1136baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1137baf8532aSAlex Dubov 1138baf8532aSAlex Dubov return (msb->active == 1); 1139baf8532aSAlex Dubov } 1140baf8532aSAlex Dubov 1141baf8532aSAlex Dubov static int mspro_block_probe(struct memstick_dev *card) 1142baf8532aSAlex Dubov { 1143baf8532aSAlex Dubov struct mspro_block_data *msb; 1144baf8532aSAlex Dubov int rc = 0; 1145baf8532aSAlex Dubov 1146baf8532aSAlex Dubov msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL); 1147baf8532aSAlex Dubov if (!msb) 1148baf8532aSAlex Dubov return -ENOMEM; 1149baf8532aSAlex Dubov memstick_set_drvdata(card, msb); 1150baf8532aSAlex Dubov msb->card = card; 1151baf8532aSAlex Dubov 1152baf8532aSAlex Dubov rc = mspro_block_init_card(card); 1153baf8532aSAlex Dubov 1154baf8532aSAlex Dubov if (rc) 1155baf8532aSAlex Dubov goto out_free; 1156baf8532aSAlex Dubov 1157baf8532aSAlex Dubov rc = sysfs_create_group(&card->dev.kobj, &msb->attr_group); 1158baf8532aSAlex Dubov if (rc) 1159baf8532aSAlex Dubov goto out_free; 1160baf8532aSAlex Dubov 1161baf8532aSAlex Dubov rc = mspro_block_init_disk(card); 1162baf8532aSAlex Dubov if (!rc) { 1163baf8532aSAlex Dubov card->check = mspro_block_check_card; 1164baf8532aSAlex Dubov return 0; 1165baf8532aSAlex Dubov } 1166baf8532aSAlex Dubov 1167baf8532aSAlex Dubov sysfs_remove_group(&card->dev.kobj, &msb->attr_group); 1168baf8532aSAlex Dubov out_free: 1169baf8532aSAlex Dubov memstick_set_drvdata(card, NULL); 1170baf8532aSAlex Dubov mspro_block_data_clear(msb); 1171baf8532aSAlex Dubov kfree(msb); 1172baf8532aSAlex Dubov return rc; 1173baf8532aSAlex Dubov } 1174baf8532aSAlex Dubov 1175baf8532aSAlex Dubov static void mspro_block_remove(struct memstick_dev *card) 1176baf8532aSAlex Dubov { 1177baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1178baf8532aSAlex Dubov struct task_struct *q_thread = NULL; 1179baf8532aSAlex Dubov unsigned long flags; 1180baf8532aSAlex Dubov 1181baf8532aSAlex Dubov del_gendisk(msb->disk); 1182baf8532aSAlex Dubov dev_dbg(&card->dev, "mspro block remove\n"); 1183baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 1184baf8532aSAlex Dubov q_thread = msb->q_thread; 1185baf8532aSAlex Dubov msb->q_thread = NULL; 1186baf8532aSAlex Dubov msb->active = 0; 1187baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 1188baf8532aSAlex Dubov 1189baf8532aSAlex Dubov if (q_thread) { 1190baf8532aSAlex Dubov mutex_unlock(&card->host->lock); 1191baf8532aSAlex Dubov kthread_stop(q_thread); 1192baf8532aSAlex Dubov mutex_lock(&card->host->lock); 1193baf8532aSAlex Dubov } 1194baf8532aSAlex Dubov 1195baf8532aSAlex Dubov dev_dbg(&card->dev, "queue thread stopped\n"); 1196baf8532aSAlex Dubov 1197baf8532aSAlex Dubov blk_cleanup_queue(msb->queue); 1198baf8532aSAlex Dubov 1199baf8532aSAlex Dubov sysfs_remove_group(&card->dev.kobj, &msb->attr_group); 1200baf8532aSAlex Dubov 1201baf8532aSAlex Dubov mutex_lock(&mspro_block_disk_lock); 1202baf8532aSAlex Dubov mspro_block_data_clear(msb); 1203baf8532aSAlex Dubov mutex_unlock(&mspro_block_disk_lock); 1204baf8532aSAlex Dubov 1205baf8532aSAlex Dubov mspro_block_disk_release(msb->disk); 1206baf8532aSAlex Dubov memstick_set_drvdata(card, NULL); 1207baf8532aSAlex Dubov } 1208baf8532aSAlex Dubov 1209baf8532aSAlex Dubov #ifdef CONFIG_PM 1210baf8532aSAlex Dubov 1211baf8532aSAlex Dubov static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state) 1212baf8532aSAlex Dubov { 1213baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1214baf8532aSAlex Dubov struct task_struct *q_thread = NULL; 1215baf8532aSAlex Dubov unsigned long flags; 1216baf8532aSAlex Dubov 1217baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 1218baf8532aSAlex Dubov q_thread = msb->q_thread; 1219baf8532aSAlex Dubov msb->q_thread = NULL; 1220baf8532aSAlex Dubov msb->active = 0; 1221baf8532aSAlex Dubov blk_stop_queue(msb->queue); 1222baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 1223baf8532aSAlex Dubov 1224baf8532aSAlex Dubov if (q_thread) 1225baf8532aSAlex Dubov kthread_stop(q_thread); 1226baf8532aSAlex Dubov 1227baf8532aSAlex Dubov return 0; 1228baf8532aSAlex Dubov } 1229baf8532aSAlex Dubov 1230baf8532aSAlex Dubov static int mspro_block_resume(struct memstick_dev *card) 1231baf8532aSAlex Dubov { 1232baf8532aSAlex Dubov struct mspro_block_data *msb = memstick_get_drvdata(card); 1233baf8532aSAlex Dubov unsigned long flags; 1234baf8532aSAlex Dubov int rc = 0; 1235baf8532aSAlex Dubov 1236baf8532aSAlex Dubov #ifdef CONFIG_MEMSTICK_UNSAFE_RESUME 1237baf8532aSAlex Dubov 1238baf8532aSAlex Dubov struct mspro_block_data *new_msb; 1239baf8532aSAlex Dubov struct memstick_host *host = card->host; 1240baf8532aSAlex Dubov struct mspro_sys_attr *s_attr, *r_attr; 1241baf8532aSAlex Dubov unsigned char cnt; 1242baf8532aSAlex Dubov 1243baf8532aSAlex Dubov mutex_lock(&host->lock); 1244baf8532aSAlex Dubov new_msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL); 1245baf8532aSAlex Dubov if (!new_msb) { 1246baf8532aSAlex Dubov rc = -ENOMEM; 1247baf8532aSAlex Dubov goto out_unlock; 1248baf8532aSAlex Dubov } 1249baf8532aSAlex Dubov 1250baf8532aSAlex Dubov new_msb->card = card; 1251baf8532aSAlex Dubov memstick_set_drvdata(card, new_msb); 1252baf8532aSAlex Dubov if (mspro_block_init_card(card)) 1253baf8532aSAlex Dubov goto out_free; 1254baf8532aSAlex Dubov 1255baf8532aSAlex Dubov for (cnt = 0; new_msb->attr_group.attrs[cnt] 1256baf8532aSAlex Dubov && msb->attr_group.attrs[cnt]; ++cnt) { 1257baf8532aSAlex Dubov s_attr = mspro_from_sysfs_attr(new_msb->attr_group.attrs[cnt]); 1258baf8532aSAlex Dubov r_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[cnt]); 1259baf8532aSAlex Dubov 1260baf8532aSAlex Dubov if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO 1261baf8532aSAlex Dubov && r_attr->id == s_attr->id) { 1262baf8532aSAlex Dubov if (memcmp(s_attr->data, r_attr->data, s_attr->size)) 1263baf8532aSAlex Dubov break; 1264baf8532aSAlex Dubov 1265baf8532aSAlex Dubov memstick_set_drvdata(card, msb); 1266baf8532aSAlex Dubov msb->q_thread = kthread_run(mspro_block_queue_thread, 1267baf8532aSAlex Dubov card, DRIVER_NAME"d"); 1268baf8532aSAlex Dubov if (IS_ERR(msb->q_thread)) 1269baf8532aSAlex Dubov msb->q_thread = NULL; 1270baf8532aSAlex Dubov else 1271baf8532aSAlex Dubov msb->active = 1; 1272baf8532aSAlex Dubov 1273baf8532aSAlex Dubov break; 1274baf8532aSAlex Dubov } 1275baf8532aSAlex Dubov } 1276baf8532aSAlex Dubov 1277baf8532aSAlex Dubov out_free: 1278baf8532aSAlex Dubov memstick_set_drvdata(card, msb); 1279baf8532aSAlex Dubov mspro_block_data_clear(new_msb); 1280baf8532aSAlex Dubov kfree(new_msb); 1281baf8532aSAlex Dubov out_unlock: 1282baf8532aSAlex Dubov mutex_unlock(&host->lock); 1283baf8532aSAlex Dubov 1284baf8532aSAlex Dubov #endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */ 1285baf8532aSAlex Dubov 1286baf8532aSAlex Dubov spin_lock_irqsave(&msb->q_lock, flags); 1287baf8532aSAlex Dubov blk_start_queue(msb->queue); 1288baf8532aSAlex Dubov spin_unlock_irqrestore(&msb->q_lock, flags); 1289baf8532aSAlex Dubov return rc; 1290baf8532aSAlex Dubov } 1291baf8532aSAlex Dubov 1292baf8532aSAlex Dubov #else 1293baf8532aSAlex Dubov 1294baf8532aSAlex Dubov #define mspro_block_suspend NULL 1295baf8532aSAlex Dubov #define mspro_block_resume NULL 1296baf8532aSAlex Dubov 1297baf8532aSAlex Dubov #endif /* CONFIG_PM */ 1298baf8532aSAlex Dubov 1299baf8532aSAlex Dubov static struct memstick_device_id mspro_block_id_tbl[] = { 1300baf8532aSAlex Dubov {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO, 1301baf8532aSAlex Dubov MEMSTICK_CLASS_GENERIC_DUO}, 1302baf8532aSAlex Dubov {} 1303baf8532aSAlex Dubov }; 1304baf8532aSAlex Dubov 1305baf8532aSAlex Dubov 1306baf8532aSAlex Dubov static struct memstick_driver mspro_block_driver = { 1307baf8532aSAlex Dubov .driver = { 1308baf8532aSAlex Dubov .name = DRIVER_NAME, 1309baf8532aSAlex Dubov .owner = THIS_MODULE 1310baf8532aSAlex Dubov }, 1311baf8532aSAlex Dubov .id_table = mspro_block_id_tbl, 1312baf8532aSAlex Dubov .probe = mspro_block_probe, 1313baf8532aSAlex Dubov .remove = mspro_block_remove, 1314baf8532aSAlex Dubov .suspend = mspro_block_suspend, 1315baf8532aSAlex Dubov .resume = mspro_block_resume 1316baf8532aSAlex Dubov }; 1317baf8532aSAlex Dubov 1318baf8532aSAlex Dubov static int __init mspro_block_init(void) 1319baf8532aSAlex Dubov { 1320baf8532aSAlex Dubov int rc = -ENOMEM; 1321baf8532aSAlex Dubov 1322baf8532aSAlex Dubov rc = register_blkdev(major, DRIVER_NAME); 1323baf8532aSAlex Dubov if (rc < 0) { 1324baf8532aSAlex Dubov printk(KERN_ERR DRIVER_NAME ": failed to register " 1325baf8532aSAlex Dubov "major %d, error %d\n", major, rc); 1326baf8532aSAlex Dubov return rc; 1327baf8532aSAlex Dubov } 1328baf8532aSAlex Dubov if (!major) 1329baf8532aSAlex Dubov major = rc; 1330baf8532aSAlex Dubov 1331baf8532aSAlex Dubov rc = memstick_register_driver(&mspro_block_driver); 1332baf8532aSAlex Dubov if (rc) 1333baf8532aSAlex Dubov unregister_blkdev(major, DRIVER_NAME); 1334baf8532aSAlex Dubov return rc; 1335baf8532aSAlex Dubov } 1336baf8532aSAlex Dubov 1337baf8532aSAlex Dubov static void __exit mspro_block_exit(void) 1338baf8532aSAlex Dubov { 1339baf8532aSAlex Dubov memstick_unregister_driver(&mspro_block_driver); 1340baf8532aSAlex Dubov unregister_blkdev(major, DRIVER_NAME); 1341baf8532aSAlex Dubov idr_destroy(&mspro_block_disk_idr); 1342baf8532aSAlex Dubov } 1343baf8532aSAlex Dubov 1344baf8532aSAlex Dubov module_init(mspro_block_init); 1345baf8532aSAlex Dubov module_exit(mspro_block_exit); 1346baf8532aSAlex Dubov 1347baf8532aSAlex Dubov MODULE_LICENSE("GPL"); 1348baf8532aSAlex Dubov MODULE_AUTHOR("Alex Dubov"); 1349baf8532aSAlex Dubov MODULE_DESCRIPTION("Sony MemoryStickPro block device driver"); 1350baf8532aSAlex Dubov MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl); 1351baf8532aSAlex Dubov MODULE_VERSION(DRIVER_VERSION); 1352