Path: blob/master/drivers/memstick/core/memstick.c
15111 views
/*1* Sony MemoryStick support2*3* Copyright (C) 2007 Alex Dubov <[email protected]>4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License version 2 as7* published by the Free Software Foundation.8*9* Special thanks to Carlos Corbacho for providing various MemoryStick cards10* that made this driver possible.11*12*/1314#include <linux/memstick.h>15#include <linux/idr.h>16#include <linux/fs.h>17#include <linux/delay.h>18#include <linux/slab.h>1920#define DRIVER_NAME "memstick"2122static unsigned int cmd_retries = 3;23module_param(cmd_retries, uint, 0644);2425static struct workqueue_struct *workqueue;26static DEFINE_IDR(memstick_host_idr);27static DEFINE_SPINLOCK(memstick_host_lock);2829static int memstick_dev_match(struct memstick_dev *card,30struct memstick_device_id *id)31{32if (id->match_flags & MEMSTICK_MATCH_ALL) {33if ((id->type == card->id.type)34&& (id->category == card->id.category)35&& (id->class == card->id.class))36return 1;37}3839return 0;40}4142static int memstick_bus_match(struct device *dev, struct device_driver *drv)43{44struct memstick_dev *card = container_of(dev, struct memstick_dev,45dev);46struct memstick_driver *ms_drv = container_of(drv,47struct memstick_driver,48driver);49struct memstick_device_id *ids = ms_drv->id_table;5051if (ids) {52while (ids->match_flags) {53if (memstick_dev_match(card, ids))54return 1;55++ids;56}57}58return 0;59}6061static int memstick_uevent(struct device *dev, struct kobj_uevent_env *env)62{63struct memstick_dev *card = container_of(dev, struct memstick_dev,64dev);6566if (add_uevent_var(env, "MEMSTICK_TYPE=%02X", card->id.type))67return -ENOMEM;6869if (add_uevent_var(env, "MEMSTICK_CATEGORY=%02X", card->id.category))70return -ENOMEM;7172if (add_uevent_var(env, "MEMSTICK_CLASS=%02X", card->id.class))73return -ENOMEM;7475return 0;76}7778static int memstick_device_probe(struct device *dev)79{80struct memstick_dev *card = container_of(dev, struct memstick_dev,81dev);82struct memstick_driver *drv = container_of(dev->driver,83struct memstick_driver,84driver);85int rc = -ENODEV;8687if (dev->driver && drv->probe) {88rc = drv->probe(card);89if (!rc)90get_device(dev);91}92return rc;93}9495static int memstick_device_remove(struct device *dev)96{97struct memstick_dev *card = container_of(dev, struct memstick_dev,98dev);99struct memstick_driver *drv = container_of(dev->driver,100struct memstick_driver,101driver);102103if (dev->driver && drv->remove) {104drv->remove(card);105card->dev.driver = NULL;106}107108put_device(dev);109return 0;110}111112#ifdef CONFIG_PM113114static int memstick_device_suspend(struct device *dev, pm_message_t state)115{116struct memstick_dev *card = container_of(dev, struct memstick_dev,117dev);118struct memstick_driver *drv = container_of(dev->driver,119struct memstick_driver,120driver);121122if (dev->driver && drv->suspend)123return drv->suspend(card, state);124return 0;125}126127static int memstick_device_resume(struct device *dev)128{129struct memstick_dev *card = container_of(dev, struct memstick_dev,130dev);131struct memstick_driver *drv = container_of(dev->driver,132struct memstick_driver,133driver);134135if (dev->driver && drv->resume)136return drv->resume(card);137return 0;138}139140#else141142#define memstick_device_suspend NULL143#define memstick_device_resume NULL144145#endif /* CONFIG_PM */146147#define MEMSTICK_ATTR(name, format) \148static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \149char *buf) \150{ \151struct memstick_dev *card = container_of(dev, struct memstick_dev, \152dev); \153return sprintf(buf, format, card->id.name); \154}155156MEMSTICK_ATTR(type, "%02X");157MEMSTICK_ATTR(category, "%02X");158MEMSTICK_ATTR(class, "%02X");159160#define MEMSTICK_ATTR_RO(name) __ATTR(name, S_IRUGO, name##_show, NULL)161162static struct device_attribute memstick_dev_attrs[] = {163MEMSTICK_ATTR_RO(type),164MEMSTICK_ATTR_RO(category),165MEMSTICK_ATTR_RO(class),166__ATTR_NULL167};168169static struct bus_type memstick_bus_type = {170.name = "memstick",171.dev_attrs = memstick_dev_attrs,172.match = memstick_bus_match,173.uevent = memstick_uevent,174.probe = memstick_device_probe,175.remove = memstick_device_remove,176.suspend = memstick_device_suspend,177.resume = memstick_device_resume178};179180static void memstick_free(struct device *dev)181{182struct memstick_host *host = container_of(dev, struct memstick_host,183dev);184kfree(host);185}186187static struct class memstick_host_class = {188.name = "memstick_host",189.dev_release = memstick_free190};191192static void memstick_free_card(struct device *dev)193{194struct memstick_dev *card = container_of(dev, struct memstick_dev,195dev);196kfree(card);197}198199static int memstick_dummy_check(struct memstick_dev *card)200{201return 0;202}203204/**205* memstick_detect_change - schedule media detection on memstick host206* @host - host to use207*/208void memstick_detect_change(struct memstick_host *host)209{210queue_work(workqueue, &host->media_checker);211}212EXPORT_SYMBOL(memstick_detect_change);213214/**215* memstick_next_req - called by host driver to obtain next request to process216* @host - host to use217* @mrq - pointer to stick the request to218*219* Host calls this function from idle state (*mrq == NULL) or after finishing220* previous request (*mrq should point to it). If previous request was221* unsuccessful, it is retried for predetermined number of times. Return value222* of 0 means that new request was assigned to the host.223*/224int memstick_next_req(struct memstick_host *host, struct memstick_request **mrq)225{226int rc = -ENXIO;227228if ((*mrq) && (*mrq)->error && host->retries) {229(*mrq)->error = rc;230host->retries--;231return 0;232}233234if (host->card && host->card->next_request)235rc = host->card->next_request(host->card, mrq);236237if (!rc)238host->retries = cmd_retries > 1 ? cmd_retries - 1 : 1;239else240*mrq = NULL;241242return rc;243}244EXPORT_SYMBOL(memstick_next_req);245246/**247* memstick_new_req - notify the host that some requests are pending248* @host - host to use249*/250void memstick_new_req(struct memstick_host *host)251{252if (host->card) {253host->retries = cmd_retries;254INIT_COMPLETION(host->card->mrq_complete);255host->request(host);256}257}258EXPORT_SYMBOL(memstick_new_req);259260/**261* memstick_init_req_sg - set request fields needed for bulk data transfer262* @mrq - request to use263* @tpc - memstick Transport Protocol Command264* @sg - TPC argument265*/266void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,267const struct scatterlist *sg)268{269mrq->tpc = tpc;270if (tpc & 8)271mrq->data_dir = WRITE;272else273mrq->data_dir = READ;274275mrq->sg = *sg;276mrq->long_data = 1;277278if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)279mrq->need_card_int = 1;280else281mrq->need_card_int = 0;282}283EXPORT_SYMBOL(memstick_init_req_sg);284285/**286* memstick_init_req - set request fields needed for short data transfer287* @mrq - request to use288* @tpc - memstick Transport Protocol Command289* @buf - TPC argument buffer290* @length - TPC argument size291*292* The intended use of this function (transfer of data items several bytes293* in size) allows us to just copy the value between request structure and294* user supplied buffer.295*/296void memstick_init_req(struct memstick_request *mrq, unsigned char tpc,297const void *buf, size_t length)298{299mrq->tpc = tpc;300if (tpc & 8)301mrq->data_dir = WRITE;302else303mrq->data_dir = READ;304305mrq->data_len = length > sizeof(mrq->data) ? sizeof(mrq->data) : length;306if (mrq->data_dir == WRITE)307memcpy(mrq->data, buf, mrq->data_len);308309mrq->long_data = 0;310311if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)312mrq->need_card_int = 1;313else314mrq->need_card_int = 0;315}316EXPORT_SYMBOL(memstick_init_req);317318/*319* Functions prefixed with "h_" are protocol callbacks. They can be called from320* interrupt context. Return value of 0 means that request processing is still321* ongoing, while special error value of -EAGAIN means that current request is322* finished (and request processor should come back some time later).323*/324325static int h_memstick_read_dev_id(struct memstick_dev *card,326struct memstick_request **mrq)327{328struct ms_id_register id_reg;329330if (!(*mrq)) {331memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL,332sizeof(struct ms_id_register));333*mrq = &card->current_mrq;334return 0;335} else {336if (!(*mrq)->error) {337memcpy(&id_reg, (*mrq)->data, sizeof(id_reg));338card->id.match_flags = MEMSTICK_MATCH_ALL;339card->id.type = id_reg.type;340card->id.category = id_reg.category;341card->id.class = id_reg.class;342dev_dbg(&card->dev, "if_mode = %02x\n", id_reg.if_mode);343}344complete(&card->mrq_complete);345return -EAGAIN;346}347}348349static int h_memstick_set_rw_addr(struct memstick_dev *card,350struct memstick_request **mrq)351{352if (!(*mrq)) {353memstick_init_req(&card->current_mrq, MS_TPC_SET_RW_REG_ADRS,354(char *)&card->reg_addr,355sizeof(card->reg_addr));356*mrq = &card->current_mrq;357return 0;358} else {359complete(&card->mrq_complete);360return -EAGAIN;361}362}363364/**365* memstick_set_rw_addr - issue SET_RW_REG_ADDR request and wait for it to366* complete367* @card - media device to use368*/369int memstick_set_rw_addr(struct memstick_dev *card)370{371card->next_request = h_memstick_set_rw_addr;372memstick_new_req(card->host);373wait_for_completion(&card->mrq_complete);374375return card->current_mrq.error;376}377EXPORT_SYMBOL(memstick_set_rw_addr);378379static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)380{381struct memstick_dev *card = kzalloc(sizeof(struct memstick_dev),382GFP_KERNEL);383struct memstick_dev *old_card = host->card;384struct ms_id_register id_reg;385386if (card) {387card->host = host;388dev_set_name(&card->dev, "%s", dev_name(&host->dev));389card->dev.parent = &host->dev;390card->dev.bus = &memstick_bus_type;391card->dev.release = memstick_free_card;392card->check = memstick_dummy_check;393394card->reg_addr.r_offset = offsetof(struct ms_register, id);395card->reg_addr.r_length = sizeof(id_reg);396card->reg_addr.w_offset = offsetof(struct ms_register, id);397card->reg_addr.w_length = sizeof(id_reg);398399init_completion(&card->mrq_complete);400401host->card = card;402if (memstick_set_rw_addr(card))403goto err_out;404405card->next_request = h_memstick_read_dev_id;406memstick_new_req(host);407wait_for_completion(&card->mrq_complete);408409if (card->current_mrq.error)410goto err_out;411}412host->card = old_card;413return card;414err_out:415host->card = old_card;416kfree(card);417return NULL;418}419420static int memstick_power_on(struct memstick_host *host)421{422int rc = host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);423424if (!rc)425rc = host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);426427return rc;428}429430static void memstick_check(struct work_struct *work)431{432struct memstick_host *host = container_of(work, struct memstick_host,433media_checker);434struct memstick_dev *card;435436dev_dbg(&host->dev, "memstick_check started\n");437mutex_lock(&host->lock);438if (!host->card) {439if (memstick_power_on(host))440goto out_power_off;441} else if (host->card->stop)442host->card->stop(host->card);443444card = memstick_alloc_card(host);445446if (!card) {447if (host->card) {448device_unregister(&host->card->dev);449host->card = NULL;450}451} else {452dev_dbg(&host->dev, "new card %02x, %02x, %02x\n",453card->id.type, card->id.category, card->id.class);454if (host->card) {455if (memstick_set_rw_addr(host->card)456|| !memstick_dev_match(host->card, &card->id)457|| !(host->card->check(host->card))) {458device_unregister(&host->card->dev);459host->card = NULL;460} else if (host->card->start)461host->card->start(host->card);462}463464if (!host->card) {465host->card = card;466if (device_register(&card->dev)) {467put_device(&card->dev);468kfree(host->card);469host->card = NULL;470}471} else472kfree(card);473}474475out_power_off:476if (!host->card)477host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);478479mutex_unlock(&host->lock);480dev_dbg(&host->dev, "memstick_check finished\n");481}482483/**484* memstick_alloc_host - allocate a memstick_host structure485* @extra: size of the user private data to allocate486* @dev: parent device of the host487*/488struct memstick_host *memstick_alloc_host(unsigned int extra,489struct device *dev)490{491struct memstick_host *host;492493host = kzalloc(sizeof(struct memstick_host) + extra, GFP_KERNEL);494if (host) {495mutex_init(&host->lock);496INIT_WORK(&host->media_checker, memstick_check);497host->dev.class = &memstick_host_class;498host->dev.parent = dev;499device_initialize(&host->dev);500}501return host;502}503EXPORT_SYMBOL(memstick_alloc_host);504505/**506* memstick_add_host - start request processing on memstick host507* @host - host to use508*/509int memstick_add_host(struct memstick_host *host)510{511int rc;512513while (1) {514if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL))515return -ENOMEM;516517spin_lock(&memstick_host_lock);518rc = idr_get_new(&memstick_host_idr, host, &host->id);519spin_unlock(&memstick_host_lock);520if (!rc)521break;522else if (rc != -EAGAIN)523return rc;524}525526dev_set_name(&host->dev, "memstick%u", host->id);527528rc = device_add(&host->dev);529if (rc) {530spin_lock(&memstick_host_lock);531idr_remove(&memstick_host_idr, host->id);532spin_unlock(&memstick_host_lock);533return rc;534}535536host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);537memstick_detect_change(host);538return 0;539}540EXPORT_SYMBOL(memstick_add_host);541542/**543* memstick_remove_host - stop request processing on memstick host544* @host - host to use545*/546void memstick_remove_host(struct memstick_host *host)547{548flush_workqueue(workqueue);549mutex_lock(&host->lock);550if (host->card)551device_unregister(&host->card->dev);552host->card = NULL;553host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);554mutex_unlock(&host->lock);555556spin_lock(&memstick_host_lock);557idr_remove(&memstick_host_idr, host->id);558spin_unlock(&memstick_host_lock);559device_del(&host->dev);560}561EXPORT_SYMBOL(memstick_remove_host);562563/**564* memstick_free_host - free memstick host565* @host - host to use566*/567void memstick_free_host(struct memstick_host *host)568{569mutex_destroy(&host->lock);570put_device(&host->dev);571}572EXPORT_SYMBOL(memstick_free_host);573574/**575* memstick_suspend_host - notify bus driver of host suspension576* @host - host to use577*/578void memstick_suspend_host(struct memstick_host *host)579{580mutex_lock(&host->lock);581host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);582mutex_unlock(&host->lock);583}584EXPORT_SYMBOL(memstick_suspend_host);585586/**587* memstick_resume_host - notify bus driver of host resumption588* @host - host to use589*/590void memstick_resume_host(struct memstick_host *host)591{592int rc = 0;593594mutex_lock(&host->lock);595if (host->card)596rc = memstick_power_on(host);597mutex_unlock(&host->lock);598599if (!rc)600memstick_detect_change(host);601}602EXPORT_SYMBOL(memstick_resume_host);603604int memstick_register_driver(struct memstick_driver *drv)605{606drv->driver.bus = &memstick_bus_type;607608return driver_register(&drv->driver);609}610EXPORT_SYMBOL(memstick_register_driver);611612void memstick_unregister_driver(struct memstick_driver *drv)613{614driver_unregister(&drv->driver);615}616EXPORT_SYMBOL(memstick_unregister_driver);617618619static int __init memstick_init(void)620{621int rc;622623workqueue = create_freezable_workqueue("kmemstick");624if (!workqueue)625return -ENOMEM;626627rc = bus_register(&memstick_bus_type);628if (!rc)629rc = class_register(&memstick_host_class);630631if (!rc)632return 0;633634bus_unregister(&memstick_bus_type);635destroy_workqueue(workqueue);636637return rc;638}639640static void __exit memstick_exit(void)641{642class_unregister(&memstick_host_class);643bus_unregister(&memstick_bus_type);644destroy_workqueue(workqueue);645idr_destroy(&memstick_host_idr);646}647648module_init(memstick_init);649module_exit(memstick_exit);650651MODULE_AUTHOR("Alex Dubov");652MODULE_LICENSE("GPL");653MODULE_DESCRIPTION("Sony MemoryStick core driver");654655656