18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/bug.h> 78c2ecf20Sopenharmony_ci#include <linux/completion.h> 88c2ecf20Sopenharmony_ci#include <linux/crc-itu-t.h> 98c2ecf20Sopenharmony_ci#include <linux/device.h> 108c2ecf20Sopenharmony_ci#include <linux/errno.h> 118c2ecf20Sopenharmony_ci#include <linux/firewire.h> 128c2ecf20Sopenharmony_ci#include <linux/firewire-constants.h> 138c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/kref.h> 168c2ecf20Sopenharmony_ci#include <linux/list.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/mutex.h> 198c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 208c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <linux/atomic.h> 238c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "core.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define define_fw_printk_level(func, kern_level) \ 288c2ecf20Sopenharmony_civoid func(const struct fw_card *card, const char *fmt, ...) \ 298c2ecf20Sopenharmony_ci{ \ 308c2ecf20Sopenharmony_ci struct va_format vaf; \ 318c2ecf20Sopenharmony_ci va_list args; \ 328c2ecf20Sopenharmony_ci \ 338c2ecf20Sopenharmony_ci va_start(args, fmt); \ 348c2ecf20Sopenharmony_ci vaf.fmt = fmt; \ 358c2ecf20Sopenharmony_ci vaf.va = &args; \ 368c2ecf20Sopenharmony_ci printk(kern_level KBUILD_MODNAME " %s: %pV", \ 378c2ecf20Sopenharmony_ci dev_name(card->device), &vaf); \ 388c2ecf20Sopenharmony_ci va_end(args); \ 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_cidefine_fw_printk_level(fw_err, KERN_ERR); 418c2ecf20Sopenharmony_cidefine_fw_printk_level(fw_notice, KERN_NOTICE); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciint fw_compute_block_crc(__be32 *block) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci int length; 468c2ecf20Sopenharmony_ci u16 crc; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci length = (be32_to_cpu(block[0]) >> 16) & 0xff; 498c2ecf20Sopenharmony_ci crc = crc_itu_t(0, (u8 *)&block[1], length * 4); 508c2ecf20Sopenharmony_ci *block |= cpu_to_be32(crc); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci return length; 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(card_mutex); 568c2ecf20Sopenharmony_cistatic LIST_HEAD(card_list); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic LIST_HEAD(descriptor_list); 598c2ecf20Sopenharmony_cistatic int descriptor_count; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic __be32 tmp_config_rom[256]; 628c2ecf20Sopenharmony_ci/* ROM header, bus info block, root dir header, capabilities = 7 quadlets */ 638c2ecf20Sopenharmony_cistatic size_t config_rom_length = 1 + 4 + 1 + 1; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define BIB_CRC(v) ((v) << 0) 668c2ecf20Sopenharmony_ci#define BIB_CRC_LENGTH(v) ((v) << 16) 678c2ecf20Sopenharmony_ci#define BIB_INFO_LENGTH(v) ((v) << 24) 688c2ecf20Sopenharmony_ci#define BIB_BUS_NAME 0x31333934 /* "1394" */ 698c2ecf20Sopenharmony_ci#define BIB_LINK_SPEED(v) ((v) << 0) 708c2ecf20Sopenharmony_ci#define BIB_GENERATION(v) ((v) << 4) 718c2ecf20Sopenharmony_ci#define BIB_MAX_ROM(v) ((v) << 8) 728c2ecf20Sopenharmony_ci#define BIB_MAX_RECEIVE(v) ((v) << 12) 738c2ecf20Sopenharmony_ci#define BIB_CYC_CLK_ACC(v) ((v) << 16) 748c2ecf20Sopenharmony_ci#define BIB_PMC ((1) << 27) 758c2ecf20Sopenharmony_ci#define BIB_BMC ((1) << 28) 768c2ecf20Sopenharmony_ci#define BIB_ISC ((1) << 29) 778c2ecf20Sopenharmony_ci#define BIB_CMC ((1) << 30) 788c2ecf20Sopenharmony_ci#define BIB_IRMC ((1) << 31) 798c2ecf20Sopenharmony_ci#define NODE_CAPABILITIES 0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* 828c2ecf20Sopenharmony_ci * IEEE-1394 specifies a default SPLIT_TIMEOUT value of 800 cycles (100 ms), 838c2ecf20Sopenharmony_ci * but we have to make it longer because there are many devices whose firmware 848c2ecf20Sopenharmony_ci * is just too slow for that. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci#define DEFAULT_SPLIT_TIMEOUT (2 * 8000) 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define CANON_OUI 0x000085 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic void generate_config_rom(struct fw_card *card, __be32 *config_rom) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct fw_descriptor *desc; 938c2ecf20Sopenharmony_ci int i, j, k, length; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* 968c2ecf20Sopenharmony_ci * Initialize contents of config rom buffer. On the OHCI 978c2ecf20Sopenharmony_ci * controller, block reads to the config rom accesses the host 988c2ecf20Sopenharmony_ci * memory, but quadlet read access the hardware bus info block 998c2ecf20Sopenharmony_ci * registers. That's just crack, but it means we should make 1008c2ecf20Sopenharmony_ci * sure the contents of bus info block in host memory matches 1018c2ecf20Sopenharmony_ci * the version stored in the OHCI registers. 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci config_rom[0] = cpu_to_be32( 1058c2ecf20Sopenharmony_ci BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0)); 1068c2ecf20Sopenharmony_ci config_rom[1] = cpu_to_be32(BIB_BUS_NAME); 1078c2ecf20Sopenharmony_ci config_rom[2] = cpu_to_be32( 1088c2ecf20Sopenharmony_ci BIB_LINK_SPEED(card->link_speed) | 1098c2ecf20Sopenharmony_ci BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | 1108c2ecf20Sopenharmony_ci BIB_MAX_ROM(2) | 1118c2ecf20Sopenharmony_ci BIB_MAX_RECEIVE(card->max_receive) | 1128c2ecf20Sopenharmony_ci BIB_BMC | BIB_ISC | BIB_CMC | BIB_IRMC); 1138c2ecf20Sopenharmony_ci config_rom[3] = cpu_to_be32(card->guid >> 32); 1148c2ecf20Sopenharmony_ci config_rom[4] = cpu_to_be32(card->guid); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* Generate root directory. */ 1178c2ecf20Sopenharmony_ci config_rom[6] = cpu_to_be32(NODE_CAPABILITIES); 1188c2ecf20Sopenharmony_ci i = 7; 1198c2ecf20Sopenharmony_ci j = 7 + descriptor_count; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* Generate root directory entries for descriptors. */ 1228c2ecf20Sopenharmony_ci list_for_each_entry (desc, &descriptor_list, link) { 1238c2ecf20Sopenharmony_ci if (desc->immediate > 0) 1248c2ecf20Sopenharmony_ci config_rom[i++] = cpu_to_be32(desc->immediate); 1258c2ecf20Sopenharmony_ci config_rom[i] = cpu_to_be32(desc->key | (j - i)); 1268c2ecf20Sopenharmony_ci i++; 1278c2ecf20Sopenharmony_ci j += desc->length; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* Update root directory length. */ 1318c2ecf20Sopenharmony_ci config_rom[5] = cpu_to_be32((i - 5 - 1) << 16); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* End of root directory, now copy in descriptors. */ 1348c2ecf20Sopenharmony_ci list_for_each_entry (desc, &descriptor_list, link) { 1358c2ecf20Sopenharmony_ci for (k = 0; k < desc->length; k++) 1368c2ecf20Sopenharmony_ci config_rom[i + k] = cpu_to_be32(desc->data[k]); 1378c2ecf20Sopenharmony_ci i += desc->length; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Calculate CRCs for all blocks in the config rom. This 1418c2ecf20Sopenharmony_ci * assumes that CRC length and info length are identical for 1428c2ecf20Sopenharmony_ci * the bus info block, which is always the case for this 1438c2ecf20Sopenharmony_ci * implementation. */ 1448c2ecf20Sopenharmony_ci for (i = 0; i < j; i += length + 1) 1458c2ecf20Sopenharmony_ci length = fw_compute_block_crc(config_rom + i); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci WARN_ON(j != config_rom_length); 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic void update_config_roms(void) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci struct fw_card *card; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci list_for_each_entry (card, &card_list, link) { 1558c2ecf20Sopenharmony_ci generate_config_rom(card, tmp_config_rom); 1568c2ecf20Sopenharmony_ci card->driver->set_config_rom(card, tmp_config_rom, 1578c2ecf20Sopenharmony_ci config_rom_length); 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic size_t required_space(struct fw_descriptor *desc) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci /* descriptor + entry into root dir + optional immediate entry */ 1648c2ecf20Sopenharmony_ci return desc->length + 1 + (desc->immediate > 0 ? 1 : 0); 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ciint fw_core_add_descriptor(struct fw_descriptor *desc) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci size_t i; 1708c2ecf20Sopenharmony_ci int ret; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* 1738c2ecf20Sopenharmony_ci * Check descriptor is valid; the length of all blocks in the 1748c2ecf20Sopenharmony_ci * descriptor has to add up to exactly the length of the 1758c2ecf20Sopenharmony_ci * block. 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci i = 0; 1788c2ecf20Sopenharmony_ci while (i < desc->length) 1798c2ecf20Sopenharmony_ci i += (desc->data[i] >> 16) + 1; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if (i != desc->length) 1828c2ecf20Sopenharmony_ci return -EINVAL; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci mutex_lock(&card_mutex); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (config_rom_length + required_space(desc) > 256) { 1878c2ecf20Sopenharmony_ci ret = -EBUSY; 1888c2ecf20Sopenharmony_ci } else { 1898c2ecf20Sopenharmony_ci list_add_tail(&desc->link, &descriptor_list); 1908c2ecf20Sopenharmony_ci config_rom_length += required_space(desc); 1918c2ecf20Sopenharmony_ci descriptor_count++; 1928c2ecf20Sopenharmony_ci if (desc->immediate > 0) 1938c2ecf20Sopenharmony_ci descriptor_count++; 1948c2ecf20Sopenharmony_ci update_config_roms(); 1958c2ecf20Sopenharmony_ci ret = 0; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci mutex_unlock(&card_mutex); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci return ret; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fw_core_add_descriptor); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_civoid fw_core_remove_descriptor(struct fw_descriptor *desc) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci mutex_lock(&card_mutex); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci list_del(&desc->link); 2098c2ecf20Sopenharmony_ci config_rom_length -= required_space(desc); 2108c2ecf20Sopenharmony_ci descriptor_count--; 2118c2ecf20Sopenharmony_ci if (desc->immediate > 0) 2128c2ecf20Sopenharmony_ci descriptor_count--; 2138c2ecf20Sopenharmony_ci update_config_roms(); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci mutex_unlock(&card_mutex); 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fw_core_remove_descriptor); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic int reset_bus(struct fw_card *card, bool short_reset) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci int reg = short_reset ? 5 : 1; 2228c2ecf20Sopenharmony_ci int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci return card->driver->update_phy_reg(card, reg, 0, bit); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_civoid fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci /* We don't try hard to sort out requests of long vs. short resets. */ 2308c2ecf20Sopenharmony_ci card->br_short = short_reset; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* Use an arbitrary short delay to combine multiple reset requests. */ 2338c2ecf20Sopenharmony_ci fw_card_get(card); 2348c2ecf20Sopenharmony_ci if (!queue_delayed_work(fw_workqueue, &card->br_work, 2358c2ecf20Sopenharmony_ci delayed ? DIV_ROUND_UP(HZ, 100) : 0)) 2368c2ecf20Sopenharmony_ci fw_card_put(card); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fw_schedule_bus_reset); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic void br_work(struct work_struct *work) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci struct fw_card *card = container_of(work, struct fw_card, br_work.work); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ 2458c2ecf20Sopenharmony_ci if (card->reset_jiffies != 0 && 2468c2ecf20Sopenharmony_ci time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) { 2478c2ecf20Sopenharmony_ci if (!queue_delayed_work(fw_workqueue, &card->br_work, 2 * HZ)) 2488c2ecf20Sopenharmony_ci fw_card_put(card); 2498c2ecf20Sopenharmony_ci return; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci fw_send_phy_config(card, FW_PHY_CONFIG_NO_NODE_ID, card->generation, 2538c2ecf20Sopenharmony_ci FW_PHY_CONFIG_CURRENT_GAP_COUNT); 2548c2ecf20Sopenharmony_ci reset_bus(card, card->br_short); 2558c2ecf20Sopenharmony_ci fw_card_put(card); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic void allocate_broadcast_channel(struct fw_card *card, int generation) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci int channel, bandwidth = 0; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (!card->broadcast_channel_allocated) { 2638c2ecf20Sopenharmony_ci fw_iso_resource_manage(card, generation, 1ULL << 31, 2648c2ecf20Sopenharmony_ci &channel, &bandwidth, true); 2658c2ecf20Sopenharmony_ci if (channel != 31) { 2668c2ecf20Sopenharmony_ci fw_notice(card, "failed to allocate broadcast channel\n"); 2678c2ecf20Sopenharmony_ci return; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci card->broadcast_channel_allocated = true; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci device_for_each_child(card->device, (void *)(long)generation, 2738c2ecf20Sopenharmony_ci fw_device_set_broadcast_channel); 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic const char gap_count_table[] = { 2778c2ecf20Sopenharmony_ci 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 2788c2ecf20Sopenharmony_ci}; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_civoid fw_schedule_bm_work(struct fw_card *card, unsigned long delay) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci fw_card_get(card); 2838c2ecf20Sopenharmony_ci if (!schedule_delayed_work(&card->bm_work, delay)) 2848c2ecf20Sopenharmony_ci fw_card_put(card); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic void bm_work(struct work_struct *work) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct fw_card *card = container_of(work, struct fw_card, bm_work.work); 2908c2ecf20Sopenharmony_ci struct fw_device *root_device, *irm_device; 2918c2ecf20Sopenharmony_ci struct fw_node *root_node; 2928c2ecf20Sopenharmony_ci int root_id, new_root_id, irm_id, bm_id, local_id; 2938c2ecf20Sopenharmony_ci int gap_count, generation, grace, rcode; 2948c2ecf20Sopenharmony_ci bool do_reset = false; 2958c2ecf20Sopenharmony_ci bool root_device_is_running; 2968c2ecf20Sopenharmony_ci bool root_device_is_cmc; 2978c2ecf20Sopenharmony_ci bool irm_is_1394_1995_only; 2988c2ecf20Sopenharmony_ci bool keep_this_irm; 2998c2ecf20Sopenharmony_ci __be32 transaction_data[2]; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci spin_lock_irq(&card->lock); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci if (card->local_node == NULL) { 3048c2ecf20Sopenharmony_ci spin_unlock_irq(&card->lock); 3058c2ecf20Sopenharmony_ci goto out_put_card; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci generation = card->generation; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci root_node = card->root_node; 3118c2ecf20Sopenharmony_ci fw_node_get(root_node); 3128c2ecf20Sopenharmony_ci root_device = root_node->data; 3138c2ecf20Sopenharmony_ci root_device_is_running = root_device && 3148c2ecf20Sopenharmony_ci atomic_read(&root_device->state) == FW_DEVICE_RUNNING; 3158c2ecf20Sopenharmony_ci root_device_is_cmc = root_device && root_device->cmc; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci irm_device = card->irm_node->data; 3188c2ecf20Sopenharmony_ci irm_is_1394_1995_only = irm_device && irm_device->config_rom && 3198c2ecf20Sopenharmony_ci (irm_device->config_rom[2] & 0x000000f0) == 0; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Canon MV5i works unreliably if it is not root node. */ 3228c2ecf20Sopenharmony_ci keep_this_irm = irm_device && irm_device->config_rom && 3238c2ecf20Sopenharmony_ci irm_device->config_rom[3] >> 8 == CANON_OUI; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci root_id = root_node->node_id; 3268c2ecf20Sopenharmony_ci irm_id = card->irm_node->node_id; 3278c2ecf20Sopenharmony_ci local_id = card->local_node->node_id; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci grace = time_after64(get_jiffies_64(), 3308c2ecf20Sopenharmony_ci card->reset_jiffies + DIV_ROUND_UP(HZ, 8)); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci if ((is_next_generation(generation, card->bm_generation) && 3338c2ecf20Sopenharmony_ci !card->bm_abdicate) || 3348c2ecf20Sopenharmony_ci (card->bm_generation != generation && grace)) { 3358c2ecf20Sopenharmony_ci /* 3368c2ecf20Sopenharmony_ci * This first step is to figure out who is IRM and 3378c2ecf20Sopenharmony_ci * then try to become bus manager. If the IRM is not 3388c2ecf20Sopenharmony_ci * well defined (e.g. does not have an active link 3398c2ecf20Sopenharmony_ci * layer or does not responds to our lock request, we 3408c2ecf20Sopenharmony_ci * will have to do a little vigilante bus management. 3418c2ecf20Sopenharmony_ci * In that case, we do a goto into the gap count logic 3428c2ecf20Sopenharmony_ci * so that when we do the reset, we still optimize the 3438c2ecf20Sopenharmony_ci * gap count. That could well save a reset in the 3448c2ecf20Sopenharmony_ci * next generation. 3458c2ecf20Sopenharmony_ci */ 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (!card->irm_node->link_on) { 3488c2ecf20Sopenharmony_ci new_root_id = local_id; 3498c2ecf20Sopenharmony_ci fw_notice(card, "%s, making local node (%02x) root\n", 3508c2ecf20Sopenharmony_ci "IRM has link off", new_root_id); 3518c2ecf20Sopenharmony_ci goto pick_me; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci if (irm_is_1394_1995_only && !keep_this_irm) { 3558c2ecf20Sopenharmony_ci new_root_id = local_id; 3568c2ecf20Sopenharmony_ci fw_notice(card, "%s, making local node (%02x) root\n", 3578c2ecf20Sopenharmony_ci "IRM is not 1394a compliant", new_root_id); 3588c2ecf20Sopenharmony_ci goto pick_me; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci transaction_data[0] = cpu_to_be32(0x3f); 3628c2ecf20Sopenharmony_ci transaction_data[1] = cpu_to_be32(local_id); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci spin_unlock_irq(&card->lock); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, 3678c2ecf20Sopenharmony_ci irm_id, generation, SCODE_100, 3688c2ecf20Sopenharmony_ci CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, 3698c2ecf20Sopenharmony_ci transaction_data, 8); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci if (rcode == RCODE_GENERATION) 3728c2ecf20Sopenharmony_ci /* Another bus reset, BM work has been rescheduled. */ 3738c2ecf20Sopenharmony_ci goto out; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci bm_id = be32_to_cpu(transaction_data[0]); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci spin_lock_irq(&card->lock); 3788c2ecf20Sopenharmony_ci if (rcode == RCODE_COMPLETE && generation == card->generation) 3798c2ecf20Sopenharmony_ci card->bm_node_id = 3808c2ecf20Sopenharmony_ci bm_id == 0x3f ? local_id : 0xffc0 | bm_id; 3818c2ecf20Sopenharmony_ci spin_unlock_irq(&card->lock); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci if (rcode == RCODE_COMPLETE && bm_id != 0x3f) { 3848c2ecf20Sopenharmony_ci /* Somebody else is BM. Only act as IRM. */ 3858c2ecf20Sopenharmony_ci if (local_id == irm_id) 3868c2ecf20Sopenharmony_ci allocate_broadcast_channel(card, generation); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci goto out; 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci if (rcode == RCODE_SEND_ERROR) { 3928c2ecf20Sopenharmony_ci /* 3938c2ecf20Sopenharmony_ci * We have been unable to send the lock request due to 3948c2ecf20Sopenharmony_ci * some local problem. Let's try again later and hope 3958c2ecf20Sopenharmony_ci * that the problem has gone away by then. 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_ci fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8)); 3988c2ecf20Sopenharmony_ci goto out; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci spin_lock_irq(&card->lock); 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci if (rcode != RCODE_COMPLETE && !keep_this_irm) { 4048c2ecf20Sopenharmony_ci /* 4058c2ecf20Sopenharmony_ci * The lock request failed, maybe the IRM 4068c2ecf20Sopenharmony_ci * isn't really IRM capable after all. Let's 4078c2ecf20Sopenharmony_ci * do a bus reset and pick the local node as 4088c2ecf20Sopenharmony_ci * root, and thus, IRM. 4098c2ecf20Sopenharmony_ci */ 4108c2ecf20Sopenharmony_ci new_root_id = local_id; 4118c2ecf20Sopenharmony_ci fw_notice(card, "BM lock failed (%s), making local node (%02x) root\n", 4128c2ecf20Sopenharmony_ci fw_rcode_string(rcode), new_root_id); 4138c2ecf20Sopenharmony_ci goto pick_me; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci } else if (card->bm_generation != generation) { 4168c2ecf20Sopenharmony_ci /* 4178c2ecf20Sopenharmony_ci * We weren't BM in the last generation, and the last 4188c2ecf20Sopenharmony_ci * bus reset is less than 125ms ago. Reschedule this job. 4198c2ecf20Sopenharmony_ci */ 4208c2ecf20Sopenharmony_ci spin_unlock_irq(&card->lock); 4218c2ecf20Sopenharmony_ci fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8)); 4228c2ecf20Sopenharmony_ci goto out; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* 4268c2ecf20Sopenharmony_ci * We're bus manager for this generation, so next step is to 4278c2ecf20Sopenharmony_ci * make sure we have an active cycle master and do gap count 4288c2ecf20Sopenharmony_ci * optimization. 4298c2ecf20Sopenharmony_ci */ 4308c2ecf20Sopenharmony_ci card->bm_generation = generation; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci if (root_device == NULL) { 4338c2ecf20Sopenharmony_ci /* 4348c2ecf20Sopenharmony_ci * Either link_on is false, or we failed to read the 4358c2ecf20Sopenharmony_ci * config rom. In either case, pick another root. 4368c2ecf20Sopenharmony_ci */ 4378c2ecf20Sopenharmony_ci new_root_id = local_id; 4388c2ecf20Sopenharmony_ci } else if (!root_device_is_running) { 4398c2ecf20Sopenharmony_ci /* 4408c2ecf20Sopenharmony_ci * If we haven't probed this device yet, bail out now 4418c2ecf20Sopenharmony_ci * and let's try again once that's done. 4428c2ecf20Sopenharmony_ci */ 4438c2ecf20Sopenharmony_ci spin_unlock_irq(&card->lock); 4448c2ecf20Sopenharmony_ci goto out; 4458c2ecf20Sopenharmony_ci } else if (root_device_is_cmc) { 4468c2ecf20Sopenharmony_ci /* 4478c2ecf20Sopenharmony_ci * We will send out a force root packet for this 4488c2ecf20Sopenharmony_ci * node as part of the gap count optimization. 4498c2ecf20Sopenharmony_ci */ 4508c2ecf20Sopenharmony_ci new_root_id = root_id; 4518c2ecf20Sopenharmony_ci } else { 4528c2ecf20Sopenharmony_ci /* 4538c2ecf20Sopenharmony_ci * Current root has an active link layer and we 4548c2ecf20Sopenharmony_ci * successfully read the config rom, but it's not 4558c2ecf20Sopenharmony_ci * cycle master capable. 4568c2ecf20Sopenharmony_ci */ 4578c2ecf20Sopenharmony_ci new_root_id = local_id; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci pick_me: 4618c2ecf20Sopenharmony_ci /* 4628c2ecf20Sopenharmony_ci * Pick a gap count from 1394a table E-1. The table doesn't cover 4638c2ecf20Sopenharmony_ci * the typically much larger 1394b beta repeater delays though. 4648c2ecf20Sopenharmony_ci */ 4658c2ecf20Sopenharmony_ci if (!card->beta_repeaters_present && 4668c2ecf20Sopenharmony_ci root_node->max_hops < ARRAY_SIZE(gap_count_table)) 4678c2ecf20Sopenharmony_ci gap_count = gap_count_table[root_node->max_hops]; 4688c2ecf20Sopenharmony_ci else 4698c2ecf20Sopenharmony_ci gap_count = 63; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* 4728c2ecf20Sopenharmony_ci * Finally, figure out if we should do a reset or not. If we have 4738c2ecf20Sopenharmony_ci * done less than 5 resets with the same physical topology and we 4748c2ecf20Sopenharmony_ci * have either a new root or a new gap count setting, let's do it. 4758c2ecf20Sopenharmony_ci */ 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (card->bm_retries++ < 5 && 4788c2ecf20Sopenharmony_ci (card->gap_count != gap_count || new_root_id != root_id)) 4798c2ecf20Sopenharmony_ci do_reset = true; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci spin_unlock_irq(&card->lock); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci if (do_reset) { 4848c2ecf20Sopenharmony_ci fw_notice(card, "phy config: new root=%x, gap_count=%d\n", 4858c2ecf20Sopenharmony_ci new_root_id, gap_count); 4868c2ecf20Sopenharmony_ci fw_send_phy_config(card, new_root_id, generation, gap_count); 4878c2ecf20Sopenharmony_ci reset_bus(card, true); 4888c2ecf20Sopenharmony_ci /* Will allocate broadcast channel after the reset. */ 4898c2ecf20Sopenharmony_ci goto out; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci if (root_device_is_cmc) { 4938c2ecf20Sopenharmony_ci /* 4948c2ecf20Sopenharmony_ci * Make sure that the cycle master sends cycle start packets. 4958c2ecf20Sopenharmony_ci */ 4968c2ecf20Sopenharmony_ci transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR); 4978c2ecf20Sopenharmony_ci rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, 4988c2ecf20Sopenharmony_ci root_id, generation, SCODE_100, 4998c2ecf20Sopenharmony_ci CSR_REGISTER_BASE + CSR_STATE_SET, 5008c2ecf20Sopenharmony_ci transaction_data, 4); 5018c2ecf20Sopenharmony_ci if (rcode == RCODE_GENERATION) 5028c2ecf20Sopenharmony_ci goto out; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (local_id == irm_id) 5068c2ecf20Sopenharmony_ci allocate_broadcast_channel(card, generation); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci out: 5098c2ecf20Sopenharmony_ci fw_node_put(root_node); 5108c2ecf20Sopenharmony_ci out_put_card: 5118c2ecf20Sopenharmony_ci fw_card_put(card); 5128c2ecf20Sopenharmony_ci} 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_civoid fw_card_initialize(struct fw_card *card, 5158c2ecf20Sopenharmony_ci const struct fw_card_driver *driver, 5168c2ecf20Sopenharmony_ci struct device *device) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci static atomic_t index = ATOMIC_INIT(-1); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci card->index = atomic_inc_return(&index); 5218c2ecf20Sopenharmony_ci card->driver = driver; 5228c2ecf20Sopenharmony_ci card->device = device; 5238c2ecf20Sopenharmony_ci card->current_tlabel = 0; 5248c2ecf20Sopenharmony_ci card->tlabel_mask = 0; 5258c2ecf20Sopenharmony_ci card->split_timeout_hi = DEFAULT_SPLIT_TIMEOUT / 8000; 5268c2ecf20Sopenharmony_ci card->split_timeout_lo = (DEFAULT_SPLIT_TIMEOUT % 8000) << 19; 5278c2ecf20Sopenharmony_ci card->split_timeout_cycles = DEFAULT_SPLIT_TIMEOUT; 5288c2ecf20Sopenharmony_ci card->split_timeout_jiffies = 5298c2ecf20Sopenharmony_ci DIV_ROUND_UP(DEFAULT_SPLIT_TIMEOUT * HZ, 8000); 5308c2ecf20Sopenharmony_ci card->color = 0; 5318c2ecf20Sopenharmony_ci card->broadcast_channel = BROADCAST_CHANNEL_INITIAL; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci kref_init(&card->kref); 5348c2ecf20Sopenharmony_ci init_completion(&card->done); 5358c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&card->transaction_list); 5368c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&card->phy_receiver_list); 5378c2ecf20Sopenharmony_ci spin_lock_init(&card->lock); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci card->local_node = NULL; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&card->br_work, br_work); 5428c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&card->bm_work, bm_work); 5438c2ecf20Sopenharmony_ci} 5448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fw_card_initialize); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ciint fw_card_add(struct fw_card *card, 5478c2ecf20Sopenharmony_ci u32 max_receive, u32 link_speed, u64 guid) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci int ret; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci card->max_receive = max_receive; 5528c2ecf20Sopenharmony_ci card->link_speed = link_speed; 5538c2ecf20Sopenharmony_ci card->guid = guid; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci mutex_lock(&card_mutex); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci generate_config_rom(card, tmp_config_rom); 5588c2ecf20Sopenharmony_ci ret = card->driver->enable(card, tmp_config_rom, config_rom_length); 5598c2ecf20Sopenharmony_ci if (ret == 0) 5608c2ecf20Sopenharmony_ci list_add_tail(&card->link, &card_list); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci mutex_unlock(&card_mutex); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci return ret; 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fw_card_add); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci/* 5698c2ecf20Sopenharmony_ci * The next few functions implement a dummy driver that is used once a card 5708c2ecf20Sopenharmony_ci * driver shuts down an fw_card. This allows the driver to cleanly unload, 5718c2ecf20Sopenharmony_ci * as all IO to the card will be handled (and failed) by the dummy driver 5728c2ecf20Sopenharmony_ci * instead of calling into the module. Only functions for iso context 5738c2ecf20Sopenharmony_ci * shutdown still need to be provided by the card driver. 5748c2ecf20Sopenharmony_ci * 5758c2ecf20Sopenharmony_ci * .read/write_csr() should never be called anymore after the dummy driver 5768c2ecf20Sopenharmony_ci * was bound since they are only used within request handler context. 5778c2ecf20Sopenharmony_ci * .set_config_rom() is never called since the card is taken out of card_list 5788c2ecf20Sopenharmony_ci * before switching to the dummy driver. 5798c2ecf20Sopenharmony_ci */ 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_cistatic int dummy_read_phy_reg(struct fw_card *card, int address) 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci return -ENODEV; 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic int dummy_update_phy_reg(struct fw_card *card, int address, 5878c2ecf20Sopenharmony_ci int clear_bits, int set_bits) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci return -ENODEV; 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_cistatic void dummy_send_request(struct fw_card *card, struct fw_packet *packet) 5938c2ecf20Sopenharmony_ci{ 5948c2ecf20Sopenharmony_ci packet->callback(packet, card, RCODE_CANCELLED); 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic void dummy_send_response(struct fw_card *card, struct fw_packet *packet) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci packet->callback(packet, card, RCODE_CANCELLED); 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci return -ENOENT; 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic int dummy_enable_phys_dma(struct fw_card *card, 6088c2ecf20Sopenharmony_ci int node_id, int generation) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci return -ENODEV; 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cistatic struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card, 6148c2ecf20Sopenharmony_ci int type, int channel, size_t header_size) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci return ERR_PTR(-ENODEV); 6178c2ecf20Sopenharmony_ci} 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_cistatic int dummy_start_iso(struct fw_iso_context *ctx, 6208c2ecf20Sopenharmony_ci s32 cycle, u32 sync, u32 tags) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci return -ENODEV; 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cistatic int dummy_set_iso_channels(struct fw_iso_context *ctx, u64 *channels) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci return -ENODEV; 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_cistatic int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p, 6318c2ecf20Sopenharmony_ci struct fw_iso_buffer *buffer, unsigned long payload) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci return -ENODEV; 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic void dummy_flush_queue_iso(struct fw_iso_context *ctx) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_cistatic int dummy_flush_iso_completions(struct fw_iso_context *ctx) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci return -ENODEV; 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic const struct fw_card_driver dummy_driver_template = { 6468c2ecf20Sopenharmony_ci .read_phy_reg = dummy_read_phy_reg, 6478c2ecf20Sopenharmony_ci .update_phy_reg = dummy_update_phy_reg, 6488c2ecf20Sopenharmony_ci .send_request = dummy_send_request, 6498c2ecf20Sopenharmony_ci .send_response = dummy_send_response, 6508c2ecf20Sopenharmony_ci .cancel_packet = dummy_cancel_packet, 6518c2ecf20Sopenharmony_ci .enable_phys_dma = dummy_enable_phys_dma, 6528c2ecf20Sopenharmony_ci .allocate_iso_context = dummy_allocate_iso_context, 6538c2ecf20Sopenharmony_ci .start_iso = dummy_start_iso, 6548c2ecf20Sopenharmony_ci .set_iso_channels = dummy_set_iso_channels, 6558c2ecf20Sopenharmony_ci .queue_iso = dummy_queue_iso, 6568c2ecf20Sopenharmony_ci .flush_queue_iso = dummy_flush_queue_iso, 6578c2ecf20Sopenharmony_ci .flush_iso_completions = dummy_flush_iso_completions, 6588c2ecf20Sopenharmony_ci}; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_civoid fw_card_release(struct kref *kref) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci struct fw_card *card = container_of(kref, struct fw_card, kref); 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci complete(&card->done); 6658c2ecf20Sopenharmony_ci} 6668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fw_card_release); 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_civoid fw_core_remove_card(struct fw_card *card) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci struct fw_card_driver dummy_driver = dummy_driver_template; 6718c2ecf20Sopenharmony_ci unsigned long flags; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci card->driver->update_phy_reg(card, 4, 6748c2ecf20Sopenharmony_ci PHY_LINK_ACTIVE | PHY_CONTENDER, 0); 6758c2ecf20Sopenharmony_ci fw_schedule_bus_reset(card, false, true); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci mutex_lock(&card_mutex); 6788c2ecf20Sopenharmony_ci list_del_init(&card->link); 6798c2ecf20Sopenharmony_ci mutex_unlock(&card_mutex); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci /* Switch off most of the card driver interface. */ 6828c2ecf20Sopenharmony_ci dummy_driver.free_iso_context = card->driver->free_iso_context; 6838c2ecf20Sopenharmony_ci dummy_driver.stop_iso = card->driver->stop_iso; 6848c2ecf20Sopenharmony_ci card->driver = &dummy_driver; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci spin_lock_irqsave(&card->lock, flags); 6878c2ecf20Sopenharmony_ci fw_destroy_nodes(card); 6888c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&card->lock, flags); 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci /* Wait for all users, especially device workqueue jobs, to finish. */ 6918c2ecf20Sopenharmony_ci fw_card_put(card); 6928c2ecf20Sopenharmony_ci wait_for_completion(&card->done); 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci WARN_ON(!list_empty(&card->transaction_list)); 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fw_core_remove_card); 697