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

card.c (10261B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * card.c - contains functions for managing groups of PnP devices
      4 *
      5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
      6 */
      7
      8#include <linux/module.h>
      9#include <linux/mutex.h>
     10#include <linux/ctype.h>
     11#include <linux/slab.h>
     12#include <linux/pnp.h>
     13#include <linux/dma-mapping.h>
     14#include "base.h"
     15
     16LIST_HEAD(pnp_cards);
     17static LIST_HEAD(pnp_card_drivers);
     18
     19static const struct pnp_card_device_id *match_card(struct pnp_card_driver *drv,
     20						   struct pnp_card *card)
     21{
     22	const struct pnp_card_device_id *drv_id = drv->id_table;
     23
     24	while (*drv_id->id) {
     25		if (compare_pnp_id(card->id, drv_id->id)) {
     26			int i = 0;
     27
     28			for (;;) {
     29				int found;
     30				struct pnp_dev *dev;
     31
     32				if (i == PNP_MAX_DEVICES ||
     33				    !*drv_id->devs[i].id)
     34					return drv_id;
     35				found = 0;
     36				card_for_each_dev(card, dev) {
     37					if (compare_pnp_id(dev->id,
     38						   drv_id->devs[i].id)) {
     39						found = 1;
     40						break;
     41					}
     42				}
     43				if (!found)
     44					break;
     45				i++;
     46			}
     47		}
     48		drv_id++;
     49	}
     50	return NULL;
     51}
     52
     53static void card_remove(struct pnp_dev *dev)
     54{
     55	dev->card_link = NULL;
     56}
     57
     58static void card_remove_first(struct pnp_dev *dev)
     59{
     60	struct pnp_card_driver *drv = to_pnp_card_driver(dev->driver);
     61
     62	if (!dev->card || !drv)
     63		return;
     64	if (drv->remove)
     65		drv->remove(dev->card_link);
     66	drv->link.remove = &card_remove;
     67	kfree(dev->card_link);
     68	card_remove(dev);
     69}
     70
     71static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
     72{
     73	const struct pnp_card_device_id *id;
     74	struct pnp_card_link *clink;
     75	struct pnp_dev *dev;
     76
     77	if (!drv->probe)
     78		return 0;
     79	id = match_card(drv, card);
     80	if (!id)
     81		return 0;
     82
     83	clink = kzalloc(sizeof(*clink), GFP_KERNEL);
     84	if (!clink)
     85		return 0;
     86	clink->card = card;
     87	clink->driver = drv;
     88	clink->pm_state = PMSG_ON;
     89
     90	if (drv->probe(clink, id) >= 0)
     91		return 1;
     92
     93	/* Recovery */
     94	card_for_each_dev(card, dev) {
     95		if (dev->card_link == clink)
     96			pnp_release_card_device(dev);
     97	}
     98	kfree(clink);
     99	return 0;
    100}
    101
    102/**
    103 * pnp_add_card_id - adds an EISA id to the specified card
    104 * @id: pointer to a pnp_id structure
    105 * @card: pointer to the desired card
    106 */
    107static struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id)
    108{
    109	struct pnp_id *dev_id, *ptr;
    110
    111	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
    112	if (!dev_id)
    113		return NULL;
    114
    115	dev_id->id[0] = id[0];
    116	dev_id->id[1] = id[1];
    117	dev_id->id[2] = id[2];
    118	dev_id->id[3] = tolower(id[3]);
    119	dev_id->id[4] = tolower(id[4]);
    120	dev_id->id[5] = tolower(id[5]);
    121	dev_id->id[6] = tolower(id[6]);
    122	dev_id->id[7] = '\0';
    123
    124	dev_id->next = NULL;
    125	ptr = card->id;
    126	while (ptr && ptr->next)
    127		ptr = ptr->next;
    128	if (ptr)
    129		ptr->next = dev_id;
    130	else
    131		card->id = dev_id;
    132
    133	return dev_id;
    134}
    135
    136static void pnp_free_card_ids(struct pnp_card *card)
    137{
    138	struct pnp_id *id;
    139	struct pnp_id *next;
    140
    141	id = card->id;
    142	while (id) {
    143		next = id->next;
    144		kfree(id);
    145		id = next;
    146	}
    147}
    148
    149static void pnp_release_card(struct device *dmdev)
    150{
    151	struct pnp_card *card = to_pnp_card(dmdev);
    152
    153	pnp_free_card_ids(card);
    154	kfree(card);
    155}
    156
    157struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnpid)
    158{
    159	struct pnp_card *card;
    160	struct pnp_id *dev_id;
    161
    162	card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL);
    163	if (!card)
    164		return NULL;
    165
    166	card->protocol = protocol;
    167	card->number = id;
    168
    169	card->dev.parent = &card->protocol->dev;
    170	dev_set_name(&card->dev, "%02x:%02x", card->protocol->number, card->number);
    171
    172	card->dev.coherent_dma_mask = DMA_BIT_MASK(24);
    173	card->dev.dma_mask = &card->dev.coherent_dma_mask;
    174
    175	dev_id = pnp_add_card_id(card, pnpid);
    176	if (!dev_id) {
    177		kfree(card);
    178		return NULL;
    179	}
    180
    181	return card;
    182}
    183
    184static ssize_t name_show(struct device *dmdev,
    185			 struct device_attribute *attr, char *buf)
    186{
    187	char *str = buf;
    188	struct pnp_card *card = to_pnp_card(dmdev);
    189
    190	str += sprintf(str, "%s\n", card->name);
    191	return (str - buf);
    192}
    193
    194static DEVICE_ATTR_RO(name);
    195
    196static ssize_t card_id_show(struct device *dmdev,
    197			    struct device_attribute *attr, char *buf)
    198{
    199	char *str = buf;
    200	struct pnp_card *card = to_pnp_card(dmdev);
    201	struct pnp_id *pos = card->id;
    202
    203	while (pos) {
    204		str += sprintf(str, "%s\n", pos->id);
    205		pos = pos->next;
    206	}
    207	return (str - buf);
    208}
    209
    210static DEVICE_ATTR_RO(card_id);
    211
    212static int pnp_interface_attach_card(struct pnp_card *card)
    213{
    214	int rc = device_create_file(&card->dev, &dev_attr_name);
    215
    216	if (rc)
    217		return rc;
    218
    219	rc = device_create_file(&card->dev, &dev_attr_card_id);
    220	if (rc)
    221		goto err_name;
    222
    223	return 0;
    224
    225err_name:
    226	device_remove_file(&card->dev, &dev_attr_name);
    227	return rc;
    228}
    229
    230/**
    231 * pnp_add_card - adds a PnP card to the PnP Layer
    232 * @card: pointer to the card to add
    233 */
    234int pnp_add_card(struct pnp_card *card)
    235{
    236	int error;
    237	struct list_head *pos, *temp;
    238
    239	card->dev.bus = NULL;
    240	card->dev.release = &pnp_release_card;
    241	error = device_register(&card->dev);
    242	if (error) {
    243		dev_err(&card->dev, "could not register (err=%d)\n", error);
    244		put_device(&card->dev);
    245		return error;
    246	}
    247
    248	pnp_interface_attach_card(card);
    249	mutex_lock(&pnp_lock);
    250	list_add_tail(&card->global_list, &pnp_cards);
    251	list_add_tail(&card->protocol_list, &card->protocol->cards);
    252	mutex_unlock(&pnp_lock);
    253
    254	/* we wait until now to add devices in order to ensure the drivers
    255	 * will be able to use all of the related devices on the card
    256	 * without waiting an unreasonable length of time */
    257	list_for_each(pos, &card->devices) {
    258		struct pnp_dev *dev = card_to_pnp_dev(pos);
    259		__pnp_add_device(dev);
    260	}
    261
    262	/* match with card drivers */
    263	list_for_each_safe(pos, temp, &pnp_card_drivers) {
    264		struct pnp_card_driver *drv =
    265		    list_entry(pos, struct pnp_card_driver,
    266			       global_list);
    267		card_probe(card, drv);
    268	}
    269	return 0;
    270}
    271
    272/**
    273 * pnp_remove_card - removes a PnP card from the PnP Layer
    274 * @card: pointer to the card to remove
    275 */
    276void pnp_remove_card(struct pnp_card *card)
    277{
    278	struct list_head *pos, *temp;
    279
    280	device_unregister(&card->dev);
    281	mutex_lock(&pnp_lock);
    282	list_del(&card->global_list);
    283	list_del(&card->protocol_list);
    284	mutex_unlock(&pnp_lock);
    285	list_for_each_safe(pos, temp, &card->devices) {
    286		struct pnp_dev *dev = card_to_pnp_dev(pos);
    287		pnp_remove_card_device(dev);
    288	}
    289}
    290
    291/**
    292 * pnp_add_card_device - adds a device to the specified card
    293 * @card: pointer to the card to add to
    294 * @dev: pointer to the device to add
    295 */
    296int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev)
    297{
    298	dev->dev.parent = &card->dev;
    299	dev->card_link = NULL;
    300	dev_set_name(&dev->dev, "%02x:%02x.%02x",
    301		     dev->protocol->number, card->number, dev->number);
    302	mutex_lock(&pnp_lock);
    303	dev->card = card;
    304	list_add_tail(&dev->card_list, &card->devices);
    305	mutex_unlock(&pnp_lock);
    306	return 0;
    307}
    308
    309/**
    310 * pnp_remove_card_device- removes a device from the specified card
    311 * @dev: pointer to the device to remove
    312 */
    313void pnp_remove_card_device(struct pnp_dev *dev)
    314{
    315	mutex_lock(&pnp_lock);
    316	dev->card = NULL;
    317	list_del(&dev->card_list);
    318	mutex_unlock(&pnp_lock);
    319	__pnp_remove_device(dev);
    320}
    321
    322/**
    323 * pnp_request_card_device - Searches for a PnP device under the specified card
    324 * @clink: pointer to the card link, cannot be NULL
    325 * @id: pointer to a PnP ID structure that explains the rules for finding the device
    326 * @from: Starting place to search from. If NULL it will start from the beginning.
    327 */
    328struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink,
    329					const char *id, struct pnp_dev *from)
    330{
    331	struct list_head *pos;
    332	struct pnp_dev *dev;
    333	struct pnp_card_driver *drv;
    334	struct pnp_card *card;
    335
    336	if (!clink || !id)
    337		return NULL;
    338
    339	card = clink->card;
    340	drv = clink->driver;
    341	if (!from) {
    342		pos = card->devices.next;
    343	} else {
    344		if (from->card != card)
    345			return NULL;
    346		pos = from->card_list.next;
    347	}
    348	while (pos != &card->devices) {
    349		dev = card_to_pnp_dev(pos);
    350		if ((!dev->card_link) && compare_pnp_id(dev->id, id))
    351			goto found;
    352		pos = pos->next;
    353	}
    354
    355	return NULL;
    356
    357found:
    358	dev->card_link = clink;
    359	dev->dev.driver = &drv->link.driver;
    360	if (pnp_bus_type.probe(&dev->dev))
    361		goto err_out;
    362	if (device_bind_driver(&dev->dev))
    363		goto err_out;
    364
    365	return dev;
    366
    367err_out:
    368	dev->dev.driver = NULL;
    369	dev->card_link = NULL;
    370	return NULL;
    371}
    372EXPORT_SYMBOL(pnp_request_card_device);
    373
    374/**
    375 * pnp_release_card_device - call this when the driver no longer needs the device
    376 * @dev: pointer to the PnP device structure
    377 */
    378void pnp_release_card_device(struct pnp_dev *dev)
    379{
    380	struct pnp_card_driver *drv = dev->card_link->driver;
    381
    382	drv->link.remove = &card_remove;
    383	device_release_driver(&dev->dev);
    384	drv->link.remove = &card_remove_first;
    385}
    386EXPORT_SYMBOL(pnp_release_card_device);
    387
    388/*
    389 * suspend/resume callbacks
    390 */
    391static int card_suspend(struct pnp_dev *dev, pm_message_t state)
    392{
    393	struct pnp_card_link *link = dev->card_link;
    394
    395	if (link->pm_state.event == state.event)
    396		return 0;
    397	link->pm_state = state;
    398	return link->driver->suspend(link, state);
    399}
    400
    401static int card_resume(struct pnp_dev *dev)
    402{
    403	struct pnp_card_link *link = dev->card_link;
    404
    405	if (link->pm_state.event == PM_EVENT_ON)
    406		return 0;
    407	link->pm_state = PMSG_ON;
    408	link->driver->resume(link);
    409	return 0;
    410}
    411
    412/**
    413 * pnp_register_card_driver - registers a PnP card driver with the PnP Layer
    414 * @drv: pointer to the driver to register
    415 */
    416int pnp_register_card_driver(struct pnp_card_driver *drv)
    417{
    418	int error;
    419	struct list_head *pos, *temp;
    420
    421	drv->link.name = drv->name;
    422	drv->link.id_table = NULL;	/* this will disable auto matching */
    423	drv->link.flags = drv->flags;
    424	drv->link.probe = NULL;
    425	drv->link.remove = &card_remove_first;
    426	drv->link.suspend = drv->suspend ? card_suspend : NULL;
    427	drv->link.resume = drv->resume ? card_resume : NULL;
    428
    429	error = pnp_register_driver(&drv->link);
    430	if (error < 0)
    431		return error;
    432
    433	mutex_lock(&pnp_lock);
    434	list_add_tail(&drv->global_list, &pnp_card_drivers);
    435	mutex_unlock(&pnp_lock);
    436
    437	list_for_each_safe(pos, temp, &pnp_cards) {
    438		struct pnp_card *card =
    439		    list_entry(pos, struct pnp_card, global_list);
    440		card_probe(card, drv);
    441	}
    442	return 0;
    443}
    444EXPORT_SYMBOL(pnp_register_card_driver);
    445
    446/**
    447 * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer
    448 * @drv: pointer to the driver to unregister
    449 */
    450void pnp_unregister_card_driver(struct pnp_card_driver *drv)
    451{
    452	mutex_lock(&pnp_lock);
    453	list_del(&drv->global_list);
    454	mutex_unlock(&pnp_lock);
    455	pnp_unregister_driver(&drv->link);
    456}
    457EXPORT_SYMBOL(pnp_unregister_card_driver);