cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tifm_core.c (8269B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  tifm_core.c - TI FlashMedia driver
      4 *
      5 *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
      6 */
      7
      8#include <linux/tifm.h>
      9#include <linux/slab.h>
     10#include <linux/init.h>
     11#include <linux/idr.h>
     12#include <linux/module.h>
     13
     14#define DRIVER_NAME "tifm_core"
     15#define DRIVER_VERSION "0.8"
     16
     17static struct workqueue_struct *workqueue;
     18static DEFINE_IDR(tifm_adapter_idr);
     19static DEFINE_SPINLOCK(tifm_adapter_lock);
     20
     21static const char *tifm_media_type_name(unsigned char type, unsigned char nt)
     22{
     23	const char *card_type_name[3][3] = {
     24		{ "SmartMedia/xD", "MemoryStick", "MMC/SD" },
     25		{ "XD", "MS", "SD"},
     26		{ "xd", "ms", "sd"}
     27	};
     28
     29	if (nt > 2 || type < 1 || type > 3)
     30		return NULL;
     31	return card_type_name[nt][type - 1];
     32}
     33
     34static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id)
     35{
     36	if (sock->type == id->type)
     37		return 1;
     38	return 0;
     39}
     40
     41static int tifm_bus_match(struct device *dev, struct device_driver *drv)
     42{
     43	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
     44	struct tifm_driver *fm_drv = container_of(drv, struct tifm_driver,
     45						  driver);
     46	struct tifm_device_id *ids = fm_drv->id_table;
     47
     48	if (ids) {
     49		while (ids->type) {
     50			if (tifm_dev_match(sock, ids))
     51				return 1;
     52			++ids;
     53		}
     54	}
     55	return 0;
     56}
     57
     58static int tifm_uevent(struct device *dev, struct kobj_uevent_env *env)
     59{
     60	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
     61
     62	if (add_uevent_var(env, "TIFM_CARD_TYPE=%s", tifm_media_type_name(sock->type, 1)))
     63		return -ENOMEM;
     64
     65	return 0;
     66}
     67
     68static int tifm_device_probe(struct device *dev)
     69{
     70	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
     71	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
     72					       driver);
     73	int rc = -ENODEV;
     74
     75	get_device(dev);
     76	if (dev->driver && drv->probe) {
     77		rc = drv->probe(sock);
     78		if (!rc)
     79			return 0;
     80	}
     81	put_device(dev);
     82	return rc;
     83}
     84
     85static void tifm_dummy_event(struct tifm_dev *sock)
     86{
     87	return;
     88}
     89
     90static void tifm_device_remove(struct device *dev)
     91{
     92	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
     93	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
     94					       driver);
     95
     96	if (dev->driver && drv->remove) {
     97		sock->card_event = tifm_dummy_event;
     98		sock->data_event = tifm_dummy_event;
     99		drv->remove(sock);
    100		sock->dev.driver = NULL;
    101	}
    102
    103	put_device(dev);
    104}
    105
    106#ifdef CONFIG_PM
    107
    108static int tifm_device_suspend(struct device *dev, pm_message_t state)
    109{
    110	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
    111	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
    112					       driver);
    113
    114	if (dev->driver && drv->suspend)
    115		return drv->suspend(sock, state);
    116	return 0;
    117}
    118
    119static int tifm_device_resume(struct device *dev)
    120{
    121	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
    122	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
    123					       driver);
    124
    125	if (dev->driver && drv->resume)
    126		return drv->resume(sock);
    127	return 0;
    128}
    129
    130#else
    131
    132#define tifm_device_suspend NULL
    133#define tifm_device_resume NULL
    134
    135#endif /* CONFIG_PM */
    136
    137static ssize_t type_show(struct device *dev, struct device_attribute *attr,
    138			 char *buf)
    139{
    140	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
    141	return sprintf(buf, "%x", sock->type);
    142}
    143static DEVICE_ATTR_RO(type);
    144
    145static struct attribute *tifm_dev_attrs[] = {
    146	&dev_attr_type.attr,
    147	NULL,
    148};
    149ATTRIBUTE_GROUPS(tifm_dev);
    150
    151static struct bus_type tifm_bus_type = {
    152	.name      = "tifm",
    153	.dev_groups = tifm_dev_groups,
    154	.match     = tifm_bus_match,
    155	.uevent    = tifm_uevent,
    156	.probe     = tifm_device_probe,
    157	.remove    = tifm_device_remove,
    158	.suspend   = tifm_device_suspend,
    159	.resume    = tifm_device_resume
    160};
    161
    162static void tifm_free(struct device *dev)
    163{
    164	struct tifm_adapter *fm = container_of(dev, struct tifm_adapter, dev);
    165
    166	kfree(fm);
    167}
    168
    169static struct class tifm_adapter_class = {
    170	.name    = "tifm_adapter",
    171	.dev_release = tifm_free
    172};
    173
    174struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
    175					struct device *dev)
    176{
    177	struct tifm_adapter *fm;
    178
    179	fm = kzalloc(struct_size(fm, sockets, num_sockets), GFP_KERNEL);
    180	if (fm) {
    181		fm->dev.class = &tifm_adapter_class;
    182		fm->dev.parent = dev;
    183		device_initialize(&fm->dev);
    184		spin_lock_init(&fm->lock);
    185		fm->num_sockets = num_sockets;
    186	}
    187	return fm;
    188}
    189EXPORT_SYMBOL(tifm_alloc_adapter);
    190
    191int tifm_add_adapter(struct tifm_adapter *fm)
    192{
    193	int rc;
    194
    195	idr_preload(GFP_KERNEL);
    196	spin_lock(&tifm_adapter_lock);
    197	rc = idr_alloc(&tifm_adapter_idr, fm, 0, 0, GFP_NOWAIT);
    198	if (rc >= 0)
    199		fm->id = rc;
    200	spin_unlock(&tifm_adapter_lock);
    201	idr_preload_end();
    202	if (rc < 0)
    203		return rc;
    204
    205	dev_set_name(&fm->dev, "tifm%u", fm->id);
    206	rc = device_add(&fm->dev);
    207	if (rc) {
    208		spin_lock(&tifm_adapter_lock);
    209		idr_remove(&tifm_adapter_idr, fm->id);
    210		spin_unlock(&tifm_adapter_lock);
    211	}
    212
    213	return rc;
    214}
    215EXPORT_SYMBOL(tifm_add_adapter);
    216
    217void tifm_remove_adapter(struct tifm_adapter *fm)
    218{
    219	unsigned int cnt;
    220
    221	flush_workqueue(workqueue);
    222	for (cnt = 0; cnt < fm->num_sockets; ++cnt) {
    223		if (fm->sockets[cnt])
    224			device_unregister(&fm->sockets[cnt]->dev);
    225	}
    226
    227	spin_lock(&tifm_adapter_lock);
    228	idr_remove(&tifm_adapter_idr, fm->id);
    229	spin_unlock(&tifm_adapter_lock);
    230	device_del(&fm->dev);
    231}
    232EXPORT_SYMBOL(tifm_remove_adapter);
    233
    234void tifm_free_adapter(struct tifm_adapter *fm)
    235{
    236	put_device(&fm->dev);
    237}
    238EXPORT_SYMBOL(tifm_free_adapter);
    239
    240void tifm_free_device(struct device *dev)
    241{
    242	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
    243	kfree(sock);
    244}
    245EXPORT_SYMBOL(tifm_free_device);
    246
    247struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
    248				   unsigned char type)
    249{
    250	struct tifm_dev *sock = NULL;
    251
    252	if (!tifm_media_type_name(type, 0))
    253		return sock;
    254
    255	sock = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
    256	if (sock) {
    257		spin_lock_init(&sock->lock);
    258		sock->type = type;
    259		sock->socket_id = id;
    260		sock->card_event = tifm_dummy_event;
    261		sock->data_event = tifm_dummy_event;
    262
    263		sock->dev.parent = fm->dev.parent;
    264		sock->dev.bus = &tifm_bus_type;
    265		sock->dev.dma_mask = fm->dev.parent->dma_mask;
    266		sock->dev.release = tifm_free_device;
    267
    268		dev_set_name(&sock->dev, "tifm_%s%u:%u",
    269			     tifm_media_type_name(type, 2), fm->id, id);
    270		printk(KERN_INFO DRIVER_NAME
    271		       ": %s card detected in socket %u:%u\n",
    272		       tifm_media_type_name(type, 0), fm->id, id);
    273	}
    274	return sock;
    275}
    276EXPORT_SYMBOL(tifm_alloc_device);
    277
    278void tifm_eject(struct tifm_dev *sock)
    279{
    280	struct tifm_adapter *fm = dev_get_drvdata(sock->dev.parent);
    281	fm->eject(fm, sock);
    282}
    283EXPORT_SYMBOL(tifm_eject);
    284
    285int tifm_has_ms_pif(struct tifm_dev *sock)
    286{
    287	struct tifm_adapter *fm = dev_get_drvdata(sock->dev.parent);
    288	return fm->has_ms_pif(fm, sock);
    289}
    290EXPORT_SYMBOL(tifm_has_ms_pif);
    291
    292int tifm_map_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
    293		int direction)
    294{
    295	return dma_map_sg(&to_pci_dev(sock->dev.parent)->dev, sg, nents,
    296			  direction);
    297}
    298EXPORT_SYMBOL(tifm_map_sg);
    299
    300void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
    301		   int direction)
    302{
    303	dma_unmap_sg(&to_pci_dev(sock->dev.parent)->dev, sg, nents, direction);
    304}
    305EXPORT_SYMBOL(tifm_unmap_sg);
    306
    307void tifm_queue_work(struct work_struct *work)
    308{
    309	queue_work(workqueue, work);
    310}
    311EXPORT_SYMBOL(tifm_queue_work);
    312
    313int tifm_register_driver(struct tifm_driver *drv)
    314{
    315	drv->driver.bus = &tifm_bus_type;
    316
    317	return driver_register(&drv->driver);
    318}
    319EXPORT_SYMBOL(tifm_register_driver);
    320
    321void tifm_unregister_driver(struct tifm_driver *drv)
    322{
    323	driver_unregister(&drv->driver);
    324}
    325EXPORT_SYMBOL(tifm_unregister_driver);
    326
    327static int __init tifm_init(void)
    328{
    329	int rc;
    330
    331	workqueue = create_freezable_workqueue("tifm");
    332	if (!workqueue)
    333		return -ENOMEM;
    334
    335	rc = bus_register(&tifm_bus_type);
    336
    337	if (rc)
    338		goto err_out_wq;
    339
    340	rc = class_register(&tifm_adapter_class);
    341	if (!rc)
    342		return 0;
    343
    344	bus_unregister(&tifm_bus_type);
    345
    346err_out_wq:
    347	destroy_workqueue(workqueue);
    348
    349	return rc;
    350}
    351
    352static void __exit tifm_exit(void)
    353{
    354	class_unregister(&tifm_adapter_class);
    355	bus_unregister(&tifm_bus_type);
    356	destroy_workqueue(workqueue);
    357}
    358
    359subsys_initcall(tifm_init);
    360module_exit(tifm_exit);
    361
    362MODULE_LICENSE("GPL");
    363MODULE_AUTHOR("Alex Dubov");
    364MODULE_DESCRIPTION("TI FlashMedia core driver");
    365MODULE_LICENSE("GPL");
    366MODULE_VERSION(DRIVER_VERSION);