2019-05-27 06:55:05 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2005-2007 Kristian Hoegsberg <krh@bitplanet.net>
|
2006-12-20 00:58:27 +00:00
|
|
|
*/
|
|
|
|
|
2009-06-04 19:09:38 +00:00
|
|
|
#include <linux/bug.h>
|
2008-05-24 14:50:22 +00:00
|
|
|
#include <linux/completion.h>
|
|
|
|
#include <linux/crc-itu-t.h>
|
2006-12-20 00:58:27 +00:00
|
|
|
#include <linux/device.h>
|
2008-05-24 14:50:22 +00:00
|
|
|
#include <linux/errno.h>
|
firewire: reorganize header files
The three header files of firewire-core, i.e.
"drivers/firewire/fw-device.h",
"drivers/firewire/fw-topology.h",
"drivers/firewire/fw-transaction.h",
are replaced by
"drivers/firewire/core.h",
"include/linux/firewire.h".
The latter includes everything which a firewire high-level driver (like
firewire-sbp2) needs besides linux/firewire-constants.h, while core.h
contains the rest which is needed by firewire-core itself and by low-
level drivers (card drivers) like firewire-ohci.
High-level drivers can now also reside outside of drivers/firewire
without having to add drivers/firewire to the header file search path in
makefiles. At least the firedtv driver will be such a driver.
I also considered to spread the contents of core.h over several files,
one for each .c file where the respective implementation resides. But
it turned out that most core .c files will end up including most of the
core .h files. Also, the combined core.h isn't unreasonably big, and it
will lose more of its contents to linux/firewire.h anyway soon when more
firewire drivers are added. (IP-over-1394, firedtv, and there are plans
for one or two more.)
Furthermore, fw-ohci.h is renamed to ohci.h. The name of core.h and
ohci.h is chosen with regard to name changes of the .c files in a
follow-up change.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2009-06-05 14:26:18 +00:00
|
|
|
#include <linux/firewire.h>
|
|
|
|
#include <linux/firewire-constants.h>
|
2009-06-04 19:09:38 +00:00
|
|
|
#include <linux/jiffies.h>
|
|
|
|
#include <linux/kernel.h>
|
2008-05-24 14:50:22 +00:00
|
|
|
#include <linux/kref.h>
|
2009-06-04 19:09:38 +00:00
|
|
|
#include <linux/list.h>
|
2008-05-24 14:50:22 +00:00
|
|
|
#include <linux/module.h>
|
2007-05-08 00:33:33 +00:00
|
|
|
#include <linux/mutex.h>
|
2009-06-04 19:09:38 +00:00
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/workqueue.h>
|
|
|
|
|
2011-07-26 23:09:06 +00:00
|
|
|
#include <linux/atomic.h>
|
2009-06-04 19:09:38 +00:00
|
|
|
#include <asm/byteorder.h>
|
2008-05-24 14:50:22 +00:00
|
|
|
|
firewire: reorganize header files
The three header files of firewire-core, i.e.
"drivers/firewire/fw-device.h",
"drivers/firewire/fw-topology.h",
"drivers/firewire/fw-transaction.h",
are replaced by
"drivers/firewire/core.h",
"include/linux/firewire.h".
The latter includes everything which a firewire high-level driver (like
firewire-sbp2) needs besides linux/firewire-constants.h, while core.h
contains the rest which is needed by firewire-core itself and by low-
level drivers (card drivers) like firewire-ohci.
High-level drivers can now also reside outside of drivers/firewire
without having to add drivers/firewire to the header file search path in
makefiles. At least the firedtv driver will be such a driver.
I also considered to spread the contents of core.h over several files,
one for each .c file where the respective implementation resides. But
it turned out that most core .c files will end up including most of the
core .h files. Also, the combined core.h isn't unreasonably big, and it
will lose more of its contents to linux/firewire.h anyway soon when more
firewire drivers are added. (IP-over-1394, firedtv, and there are plans
for one or two more.)
Furthermore, fw-ohci.h is renamed to ohci.h. The name of core.h and
ohci.h is chosen with regard to name changes of the .c files in a
follow-up change.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2009-06-05 14:26:18 +00:00
|
|
|
#include "core.h"
|
2024-05-01 07:32:36 +00:00
|
|
|
#include <trace/events/firewire.h>
|
2006-12-20 00:58:27 +00:00
|
|
|
|
firewire: core: prefix log messages with card name
Associate all log messages from firewire-core with the respective card
because some people have more than one card. E.g.
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core: created device fw0: GUID 0814438400000389, S800
firewire_core: phy config: new root=ffc1, gap_count=5
firewire_core: created device fw1: GUID 0814438400000388, S800
firewire_core: created device fw2: GUID 0001d202e06800d1, S800
turns into
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core 0000:04:00.0: created device fw0: GUID 0814438400000389, S800
firewire_core 0000:04:00.0: phy config: new root=ffc1, gap_count=5
firewire_core 0000:05:00.0: created device fw1: GUID 0814438400000388, S800
firewire_core 0000:04:00.0: created device fw2: GUID 0001d202e06800d1, S800
This increases the module size slightly; to keep this in check, turn the
former printk wrapper macros into functions. Their implementation is
largely copied from driver core's dev_printk counterparts.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2012-02-18 21:03:14 +00:00
|
|
|
#define define_fw_printk_level(func, kern_level) \
|
|
|
|
void func(const struct fw_card *card, const char *fmt, ...) \
|
|
|
|
{ \
|
|
|
|
struct va_format vaf; \
|
|
|
|
va_list args; \
|
|
|
|
\
|
|
|
|
va_start(args, fmt); \
|
|
|
|
vaf.fmt = fmt; \
|
|
|
|
vaf.va = &args; \
|
|
|
|
printk(kern_level KBUILD_MODNAME " %s: %pV", \
|
|
|
|
dev_name(card->device), &vaf); \
|
|
|
|
va_end(args); \
|
|
|
|
}
|
|
|
|
define_fw_printk_level(fw_err, KERN_ERR);
|
|
|
|
define_fw_printk_level(fw_notice, KERN_NOTICE);
|
|
|
|
|
2009-10-07 22:42:53 +00:00
|
|
|
int fw_compute_block_crc(__be32 *block)
|
2009-10-07 22:41:59 +00:00
|
|
|
{
|
|
|
|
int length;
|
|
|
|
u16 crc;
|
|
|
|
|
|
|
|
length = (be32_to_cpu(block[0]) >> 16) & 0xff;
|
|
|
|
crc = crc_itu_t(0, (u8 *)&block[1], length * 4);
|
|
|
|
*block |= cpu_to_be32(crc);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
2007-05-08 00:33:33 +00:00
|
|
|
static DEFINE_MUTEX(card_mutex);
|
2006-12-20 00:58:27 +00:00
|
|
|
static LIST_HEAD(card_list);
|
|
|
|
|
|
|
|
static LIST_HEAD(descriptor_list);
|
|
|
|
static int descriptor_count;
|
|
|
|
|
2009-10-07 22:42:27 +00:00
|
|
|
static __be32 tmp_config_rom[256];
|
2010-01-24 13:47:02 +00:00
|
|
|
/* ROM header, bus info block, root dir header, capabilities = 7 quadlets */
|
|
|
|
static size_t config_rom_length = 1 + 4 + 1 + 1;
|
2009-10-07 22:42:27 +00:00
|
|
|
|
2007-05-08 00:33:35 +00:00
|
|
|
#define BIB_CRC(v) ((v) << 0)
|
|
|
|
#define BIB_CRC_LENGTH(v) ((v) << 16)
|
|
|
|
#define BIB_INFO_LENGTH(v) ((v) << 24)
|
2010-04-14 20:30:18 +00:00
|
|
|
#define BIB_BUS_NAME 0x31333934 /* "1394" */
|
2007-05-08 00:33:35 +00:00
|
|
|
#define BIB_LINK_SPEED(v) ((v) << 0)
|
|
|
|
#define BIB_GENERATION(v) ((v) << 4)
|
|
|
|
#define BIB_MAX_ROM(v) ((v) << 8)
|
|
|
|
#define BIB_MAX_RECEIVE(v) ((v) << 12)
|
|
|
|
#define BIB_CYC_CLK_ACC(v) ((v) << 16)
|
|
|
|
#define BIB_PMC ((1) << 27)
|
|
|
|
#define BIB_BMC ((1) << 28)
|
|
|
|
#define BIB_ISC ((1) << 29)
|
|
|
|
#define BIB_CMC ((1) << 30)
|
2010-04-14 20:30:18 +00:00
|
|
|
#define BIB_IRMC ((1) << 31)
|
|
|
|
#define NODE_CAPABILITIES 0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2011-03-07 10:21:15 +00:00
|
|
|
/*
|
|
|
|
* IEEE-1394 specifies a default SPLIT_TIMEOUT value of 800 cycles (100 ms),
|
|
|
|
* but we have to make it longer because there are many devices whose firmware
|
|
|
|
* is just too slow for that.
|
|
|
|
*/
|
|
|
|
#define DEFAULT_SPLIT_TIMEOUT (2 * 8000)
|
|
|
|
|
2011-01-15 17:19:48 +00:00
|
|
|
#define CANON_OUI 0x000085
|
|
|
|
|
2010-01-24 13:47:02 +00:00
|
|
|
static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
|
|
|
struct fw_descriptor *desc;
|
2009-10-07 22:41:59 +00:00
|
|
|
int i, j, k, length;
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* Initialize contents of config rom buffer. On the OHCI
|
2007-01-21 19:44:09 +00:00
|
|
|
* controller, block reads to the config rom accesses the host
|
|
|
|
* memory, but quadlet read access the hardware bus info block
|
|
|
|
* registers. That's just crack, but it means we should make
|
2008-10-22 19:59:42 +00:00
|
|
|
* sure the contents of bus info block in host memory matches
|
2007-05-08 00:33:32 +00:00
|
|
|
* the version stored in the OHCI registers.
|
|
|
|
*/
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2009-10-07 22:41:59 +00:00
|
|
|
config_rom[0] = cpu_to_be32(
|
|
|
|
BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0));
|
2010-04-14 20:30:18 +00:00
|
|
|
config_rom[1] = cpu_to_be32(BIB_BUS_NAME);
|
2009-10-07 22:41:59 +00:00
|
|
|
config_rom[2] = cpu_to_be32(
|
2007-05-08 00:33:35 +00:00
|
|
|
BIB_LINK_SPEED(card->link_speed) |
|
|
|
|
BIB_GENERATION(card->config_rom_generation++ % 14 + 2) |
|
|
|
|
BIB_MAX_ROM(2) |
|
|
|
|
BIB_MAX_RECEIVE(card->max_receive) |
|
2010-04-14 20:30:18 +00:00
|
|
|
BIB_BMC | BIB_ISC | BIB_CMC | BIB_IRMC);
|
2009-10-07 22:41:59 +00:00
|
|
|
config_rom[3] = cpu_to_be32(card->guid >> 32);
|
|
|
|
config_rom[4] = cpu_to_be32(card->guid);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
|
|
|
/* Generate root directory. */
|
2010-04-14 20:30:18 +00:00
|
|
|
config_rom[6] = cpu_to_be32(NODE_CAPABILITIES);
|
2009-10-07 22:41:59 +00:00
|
|
|
i = 7;
|
|
|
|
j = 7 + descriptor_count;
|
2006-12-20 00:58:27 +00:00
|
|
|
|
|
|
|
/* Generate root directory entries for descriptors. */
|
|
|
|
list_for_each_entry (desc, &descriptor_list, link) {
|
2007-03-07 17:12:36 +00:00
|
|
|
if (desc->immediate > 0)
|
2009-10-07 22:41:59 +00:00
|
|
|
config_rom[i++] = cpu_to_be32(desc->immediate);
|
|
|
|
config_rom[i] = cpu_to_be32(desc->key | (j - i));
|
2006-12-20 00:58:27 +00:00
|
|
|
i++;
|
|
|
|
j += desc->length;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update root directory length. */
|
2009-10-07 22:41:59 +00:00
|
|
|
config_rom[5] = cpu_to_be32((i - 5 - 1) << 16);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
|
|
|
/* End of root directory, now copy in descriptors. */
|
|
|
|
list_for_each_entry (desc, &descriptor_list, link) {
|
2009-10-07 22:41:59 +00:00
|
|
|
for (k = 0; k < desc->length; k++)
|
|
|
|
config_rom[i + k] = cpu_to_be32(desc->data[k]);
|
2006-12-20 00:58:27 +00:00
|
|
|
i += desc->length;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate CRCs for all blocks in the config rom. This
|
|
|
|
* assumes that CRC length and info length are identical for
|
|
|
|
* the bus info block, which is always the case for this
|
|
|
|
* implementation. */
|
2007-05-08 00:33:31 +00:00
|
|
|
for (i = 0; i < j; i += length + 1)
|
2009-10-07 22:42:53 +00:00
|
|
|
length = fw_compute_block_crc(config_rom + i);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2010-01-24 13:47:02 +00:00
|
|
|
WARN_ON(j != config_rom_length);
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
static void update_config_roms(void)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
|
|
|
struct fw_card *card;
|
|
|
|
|
|
|
|
list_for_each_entry (card, &card_list, link) {
|
2010-01-24 13:47:02 +00:00
|
|
|
generate_config_rom(card, tmp_config_rom);
|
|
|
|
card->driver->set_config_rom(card, tmp_config_rom,
|
|
|
|
config_rom_length);
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-24 13:47:02 +00:00
|
|
|
static size_t required_space(struct fw_descriptor *desc)
|
|
|
|
{
|
|
|
|
/* descriptor + entry into root dir + optional immediate entry */
|
|
|
|
return desc->length + 1 + (desc->immediate > 0 ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
int fw_core_add_descriptor(struct fw_descriptor *desc)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* Check descriptor is valid; the length of all blocks in the
|
2006-12-20 00:58:27 +00:00
|
|
|
* descriptor has to add up to exactly the length of the
|
2007-05-08 00:33:32 +00:00
|
|
|
* block.
|
|
|
|
*/
|
2006-12-20 00:58:27 +00:00
|
|
|
i = 0;
|
|
|
|
while (i < desc->length)
|
|
|
|
i += (desc->data[i] >> 16) + 1;
|
|
|
|
|
|
|
|
if (i != desc->length)
|
2007-03-28 19:26:42 +00:00
|
|
|
return -EINVAL;
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2024-08-05 08:53:53 +00:00
|
|
|
guard(mutex)(&card_mutex);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2024-08-05 08:53:53 +00:00
|
|
|
if (config_rom_length + required_space(desc) > 256)
|
|
|
|
return -EBUSY;
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2024-08-05 08:53:53 +00:00
|
|
|
list_add_tail(&desc->link, &descriptor_list);
|
|
|
|
config_rom_length += required_space(desc);
|
|
|
|
descriptor_count++;
|
|
|
|
if (desc->immediate > 0)
|
|
|
|
descriptor_count++;
|
|
|
|
update_config_roms();
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2024-08-05 08:53:53 +00:00
|
|
|
return 0;
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
2009-05-18 17:08:06 +00:00
|
|
|
EXPORT_SYMBOL(fw_core_add_descriptor);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
void fw_core_remove_descriptor(struct fw_descriptor *desc)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
2024-08-05 08:53:53 +00:00
|
|
|
guard(mutex)(&card_mutex);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
|
|
|
list_del(&desc->link);
|
2010-01-24 13:47:02 +00:00
|
|
|
config_rom_length -= required_space(desc);
|
2006-12-20 00:58:27 +00:00
|
|
|
descriptor_count--;
|
2007-03-07 17:12:36 +00:00
|
|
|
if (desc->immediate > 0)
|
|
|
|
descriptor_count--;
|
2006-12-20 00:58:27 +00:00
|
|
|
update_config_roms();
|
|
|
|
}
|
2009-05-18 17:08:06 +00:00
|
|
|
EXPORT_SYMBOL(fw_core_remove_descriptor);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2010-07-08 14:09:06 +00:00
|
|
|
static int reset_bus(struct fw_card *card, bool short_reset)
|
|
|
|
{
|
|
|
|
int reg = short_reset ? 5 : 1;
|
|
|
|
int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
|
|
|
|
|
2024-06-13 13:14:39 +00:00
|
|
|
trace_bus_reset_initiate(card->index, card->generation, short_reset);
|
2024-05-01 07:32:36 +00:00
|
|
|
|
2010-07-08 14:09:06 +00:00
|
|
|
return card->driver->update_phy_reg(card, reg, 0, bit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset)
|
|
|
|
{
|
2024-06-13 13:14:39 +00:00
|
|
|
trace_bus_reset_schedule(card->index, card->generation, short_reset);
|
2024-05-01 07:32:36 +00:00
|
|
|
|
2010-07-08 14:09:06 +00:00
|
|
|
/* We don't try hard to sort out requests of long vs. short resets. */
|
|
|
|
card->br_short = short_reset;
|
|
|
|
|
|
|
|
/* Use an arbitrary short delay to combine multiple reset requests. */
|
|
|
|
fw_card_get(card);
|
firewire: sbp2: parallelize login, reconnect, logout
The struct sbp2_logical_unit.work items can all be executed in parallel
but are not reentrant. Furthermore, reconnect or re-login work must be
executed in a WQ_MEM_RECLAIM workqueue.
Hence replace the old single-threaded firewire-sbp2 workqueue by a
concurrency-managed but non-reentrant workqueue with rescuer.
firewire-core already maintains one, hence use this one.
In earlier versions of this change, I observed occasional failures of
parallel INQUIRY to an Initio INIC-2430 FireWire 800 to dual IDE bridge.
More testing indicates that parallel INQUIRY is not actually a problem,
but too quick successions of logout and login + INQUIRY, e.g. a quick
sequence of cable plugout and plugin, can result in failed INQUIRY.
This does not seem to be something that should or could be addressed by
serialization.
Another dual-LU device to which I currently have access to, an
OXUF924DSB FireWire 800 to dual SATA bridge with firmware from MacPower,
has been successfully tested with this too.
This change is beneficial to environments with two or more FireWire
storage devices, especially if they are located on the same bus.
Management tasks that should be performed as soon and as quickly as
possible, especially reconnect, are no longer held up by tasks on other
devices that may take a long time, especially login with INQUIRY and sd
or sr driver probe.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2011-05-01 18:50:31 +00:00
|
|
|
if (!queue_delayed_work(fw_workqueue, &card->br_work,
|
firewire: core: use non-reentrant workqueue with rescuer
firewire-core manages the following types of work items:
fw_card.br_work:
- resets the bus on a card and possibly sends a PHY packet before that
- does not sleep for long or not at all
- is scheduled via fw_schedule_bus_reset() by
- firewire-ohci's pci_probe method
- firewire-ohci's set_config_rom method, called by kernelspace
protocol drivers and userspace drivers which add/remove
Configuration ROM descriptors
- userspace drivers which use the bus reset ioctl
- itself if the last reset happened less than 2 seconds ago
fw_card.bm_work:
- performs bus management duties
- usually does not (but may in corner cases) sleep for long
- is scheduled via fw_schedule_bm_work() by
- firewire-ohci's self-ID-complete IRQ handler tasklet
- firewire-core's fw_device.work instances whenever the root node
device was (successfully or unsuccessfully) discovered,
refreshed, or rediscovered
- itself in case of resource allocation failures or in order to
obey the 125ms bus manager arbitration interval
fw_device.work:
- performs node probe, update, shutdown, revival, removal; including
kernel driver probe, update, shutdown and bus reset notification to
userspace drivers
- usually sleeps moderately long, in corner cases very long
- is scheduled by
- firewire-ohci's self-ID-complete IRQ handler tasklet via the
core's fw_node_event
- firewire-ohci's pci_remove method via core's fw_destroy_nodes/
fw_node_event
- itself during retries, e.g. while a node is powering up
iso_resource.work:
- accesses registers at the Isochronous Resource Manager node
- usually does not (but may in corner cases) sleep for long
- is scheduled via schedule_iso_resource() by
- the owning userspace driver at addition and removal of the
resource
- firewire-core's fw_device.work instances after bus reset
- itself in case of resource allocation if necessary to obey the
1000ms reallocation period after bus reset
fw_card.br_work instances should not, and instances of the others must
not, be executed in parallel by multiple CPUs -- but were not protected
against that. Hence allocate a non-reentrant workqueue for them.
fw_device.work may be used in the memory reclaim path in case of SBP-2
device updates. Hence we need a workqueue with rescuer and cannot use
system_nrt_wq.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Reviewed-by: Tejun Heo <tj@kernel.org>
2010-10-13 11:39:46 +00:00
|
|
|
delayed ? DIV_ROUND_UP(HZ, 100) : 0))
|
2010-07-08 14:09:06 +00:00
|
|
|
fw_card_put(card);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(fw_schedule_bus_reset);
|
|
|
|
|
|
|
|
static void br_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct fw_card *card = container_of(work, struct fw_card, br_work.work);
|
|
|
|
|
|
|
|
/* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
|
|
|
|
if (card->reset_jiffies != 0 &&
|
2011-01-22 14:05:03 +00:00
|
|
|
time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
|
2024-06-13 13:14:39 +00:00
|
|
|
trace_bus_reset_postpone(card->index, card->generation, card->br_short);
|
2024-05-01 07:32:36 +00:00
|
|
|
|
firewire: sbp2: parallelize login, reconnect, logout
The struct sbp2_logical_unit.work items can all be executed in parallel
but are not reentrant. Furthermore, reconnect or re-login work must be
executed in a WQ_MEM_RECLAIM workqueue.
Hence replace the old single-threaded firewire-sbp2 workqueue by a
concurrency-managed but non-reentrant workqueue with rescuer.
firewire-core already maintains one, hence use this one.
In earlier versions of this change, I observed occasional failures of
parallel INQUIRY to an Initio INIC-2430 FireWire 800 to dual IDE bridge.
More testing indicates that parallel INQUIRY is not actually a problem,
but too quick successions of logout and login + INQUIRY, e.g. a quick
sequence of cable plugout and plugin, can result in failed INQUIRY.
This does not seem to be something that should or could be addressed by
serialization.
Another dual-LU device to which I currently have access to, an
OXUF924DSB FireWire 800 to dual SATA bridge with firmware from MacPower,
has been successfully tested with this too.
This change is beneficial to environments with two or more FireWire
storage devices, especially if they are located on the same bus.
Management tasks that should be performed as soon and as quickly as
possible, especially reconnect, are no longer held up by tasks on other
devices that may take a long time, especially login with INQUIRY and sd
or sr driver probe.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2011-05-01 18:50:31 +00:00
|
|
|
if (!queue_delayed_work(fw_workqueue, &card->br_work, 2 * HZ))
|
2010-07-08 14:09:06 +00:00
|
|
|
fw_card_put(card);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fw_send_phy_config(card, FW_PHY_CONFIG_NO_NODE_ID, card->generation,
|
|
|
|
FW_PHY_CONFIG_CURRENT_GAP_COUNT);
|
|
|
|
reset_bus(card, card->br_short);
|
|
|
|
fw_card_put(card);
|
|
|
|
}
|
|
|
|
|
2009-03-10 20:08:37 +00:00
|
|
|
static void allocate_broadcast_channel(struct fw_card *card, int generation)
|
2009-02-23 20:59:34 +00:00
|
|
|
{
|
2009-03-10 20:08:37 +00:00
|
|
|
int channel, bandwidth = 0;
|
|
|
|
|
2010-06-10 06:40:49 +00:00
|
|
|
if (!card->broadcast_channel_allocated) {
|
|
|
|
fw_iso_resource_manage(card, generation, 1ULL << 31,
|
2011-04-22 13:13:54 +00:00
|
|
|
&channel, &bandwidth, true);
|
2010-06-10 06:40:49 +00:00
|
|
|
if (channel != 31) {
|
firewire: core: prefix log messages with card name
Associate all log messages from firewire-core with the respective card
because some people have more than one card. E.g.
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core: created device fw0: GUID 0814438400000389, S800
firewire_core: phy config: new root=ffc1, gap_count=5
firewire_core: created device fw1: GUID 0814438400000388, S800
firewire_core: created device fw2: GUID 0001d202e06800d1, S800
turns into
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core 0000:04:00.0: created device fw0: GUID 0814438400000389, S800
firewire_core 0000:04:00.0: phy config: new root=ffc1, gap_count=5
firewire_core 0000:05:00.0: created device fw1: GUID 0814438400000388, S800
firewire_core 0000:04:00.0: created device fw2: GUID 0001d202e06800d1, S800
This increases the module size slightly; to keep this in check, turn the
former printk wrapper macros into functions. Their implementation is
largely copied from driver core's dev_printk counterparts.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2012-02-18 21:03:14 +00:00
|
|
|
fw_notice(card, "failed to allocate broadcast channel\n");
|
2010-06-10 06:40:49 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-03-10 20:09:28 +00:00
|
|
|
card->broadcast_channel_allocated = true;
|
2009-02-23 20:59:34 +00:00
|
|
|
}
|
2010-06-10 06:40:49 +00:00
|
|
|
|
|
|
|
device_for_each_child(card->device, (void *)(long)generation,
|
|
|
|
fw_device_set_broadcast_channel);
|
2009-02-23 20:59:34 +00:00
|
|
|
}
|
|
|
|
|
2007-01-26 05:37:50 +00:00
|
|
|
static const char gap_count_table[] = {
|
|
|
|
63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
|
|
|
|
};
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
|
2008-11-29 16:44:57 +00:00
|
|
|
{
|
|
|
|
fw_card_get(card);
|
2010-07-08 14:09:06 +00:00
|
|
|
if (!schedule_delayed_work(&card->bm_work, delay))
|
2008-11-29 16:44:57 +00:00
|
|
|
fw_card_put(card);
|
|
|
|
}
|
|
|
|
|
2010-07-08 14:09:06 +00:00
|
|
|
static void bm_work(struct work_struct *work)
|
2006-12-20 00:58:31 +00:00
|
|
|
{
|
2010-07-08 14:09:06 +00:00
|
|
|
struct fw_card *card = container_of(work, struct fw_card, bm_work.work);
|
2010-05-30 17:43:52 +00:00
|
|
|
struct fw_device *root_device, *irm_device;
|
2009-03-10 20:08:37 +00:00
|
|
|
struct fw_node *root_node;
|
2010-06-21 21:24:35 +00:00
|
|
|
int root_id, new_root_id, irm_id, bm_id, local_id;
|
2009-03-10 20:08:37 +00:00
|
|
|
int gap_count, generation, grace, rcode;
|
2008-03-24 19:57:12 +00:00
|
|
|
bool do_reset = false;
|
2009-01-09 19:49:37 +00:00
|
|
|
bool root_device_is_running;
|
|
|
|
bool root_device_is_cmc;
|
2010-05-30 17:43:52 +00:00
|
|
|
bool irm_is_1394_1995_only;
|
2011-01-15 17:19:48 +00:00
|
|
|
bool keep_this_irm;
|
2011-04-22 13:13:54 +00:00
|
|
|
__be32 transaction_data[2];
|
2006-12-20 00:58:31 +00:00
|
|
|
|
2010-06-21 21:23:52 +00:00
|
|
|
spin_lock_irq(&card->lock);
|
2008-02-24 17:57:23 +00:00
|
|
|
|
2009-03-10 20:08:37 +00:00
|
|
|
if (card->local_node == NULL) {
|
2010-06-21 21:23:52 +00:00
|
|
|
spin_unlock_irq(&card->lock);
|
2008-11-29 16:44:57 +00:00
|
|
|
goto out_put_card;
|
2008-02-24 17:57:23 +00:00
|
|
|
}
|
2006-12-20 00:58:31 +00:00
|
|
|
|
|
|
|
generation = card->generation;
|
2010-05-30 17:43:52 +00:00
|
|
|
|
2009-03-10 20:08:37 +00:00
|
|
|
root_node = card->root_node;
|
|
|
|
fw_node_get(root_node);
|
2008-02-24 17:57:23 +00:00
|
|
|
root_device = root_node->data;
|
2009-01-09 19:49:37 +00:00
|
|
|
root_device_is_running = root_device &&
|
|
|
|
atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
|
|
|
|
root_device_is_cmc = root_device && root_device->cmc;
|
2010-05-30 17:43:52 +00:00
|
|
|
|
|
|
|
irm_device = card->irm_node->data;
|
|
|
|
irm_is_1394_1995_only = irm_device && irm_device->config_rom &&
|
|
|
|
(irm_device->config_rom[2] & 0x000000f0) == 0;
|
|
|
|
|
2011-01-15 17:19:48 +00:00
|
|
|
/* Canon MV5i works unreliably if it is not root node. */
|
|
|
|
keep_this_irm = irm_device && irm_device->config_rom &&
|
|
|
|
irm_device->config_rom[3] >> 8 == CANON_OUI;
|
|
|
|
|
2009-03-10 20:08:37 +00:00
|
|
|
root_id = root_node->node_id;
|
|
|
|
irm_id = card->irm_node->node_id;
|
|
|
|
local_id = card->local_node->node_id;
|
2009-03-10 20:07:46 +00:00
|
|
|
|
2011-01-22 14:05:03 +00:00
|
|
|
grace = time_after64(get_jiffies_64(),
|
|
|
|
card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
|
2009-03-10 20:07:46 +00:00
|
|
|
|
2010-06-10 06:37:15 +00:00
|
|
|
if ((is_next_generation(generation, card->bm_generation) &&
|
|
|
|
!card->bm_abdicate) ||
|
2007-01-26 05:38:45 +00:00
|
|
|
(card->bm_generation != generation && grace)) {
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* This first step is to figure out who is IRM and
|
2007-01-26 05:38:45 +00:00
|
|
|
* then try to become bus manager. If the IRM is not
|
|
|
|
* well defined (e.g. does not have an active link
|
|
|
|
* layer or does not responds to our lock request, we
|
|
|
|
* will have to do a little vigilante bus management.
|
|
|
|
* In that case, we do a goto into the gap count logic
|
|
|
|
* so that when we do the reset, we still optimize the
|
|
|
|
* gap count. That could well save a reset in the
|
2007-05-08 00:33:32 +00:00
|
|
|
* next generation.
|
|
|
|
*/
|
2007-01-26 05:38:45 +00:00
|
|
|
|
2009-03-10 20:08:37 +00:00
|
|
|
if (!card->irm_node->link_on) {
|
|
|
|
new_root_id = local_id;
|
firewire: core: prefix log messages with card name
Associate all log messages from firewire-core with the respective card
because some people have more than one card. E.g.
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core: created device fw0: GUID 0814438400000389, S800
firewire_core: phy config: new root=ffc1, gap_count=5
firewire_core: created device fw1: GUID 0814438400000388, S800
firewire_core: created device fw2: GUID 0001d202e06800d1, S800
turns into
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core 0000:04:00.0: created device fw0: GUID 0814438400000389, S800
firewire_core 0000:04:00.0: phy config: new root=ffc1, gap_count=5
firewire_core 0000:05:00.0: created device fw1: GUID 0814438400000388, S800
firewire_core 0000:04:00.0: created device fw2: GUID 0001d202e06800d1, S800
This increases the module size slightly; to keep this in check, turn the
former printk wrapper macros into functions. Their implementation is
largely copied from driver core's dev_printk counterparts.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2012-02-18 21:03:14 +00:00
|
|
|
fw_notice(card, "%s, making local node (%02x) root\n",
|
2010-05-30 17:43:52 +00:00
|
|
|
"IRM has link off", new_root_id);
|
|
|
|
goto pick_me;
|
|
|
|
}
|
|
|
|
|
2011-01-15 17:19:48 +00:00
|
|
|
if (irm_is_1394_1995_only && !keep_this_irm) {
|
2010-05-30 17:43:52 +00:00
|
|
|
new_root_id = local_id;
|
firewire: core: prefix log messages with card name
Associate all log messages from firewire-core with the respective card
because some people have more than one card. E.g.
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core: created device fw0: GUID 0814438400000389, S800
firewire_core: phy config: new root=ffc1, gap_count=5
firewire_core: created device fw1: GUID 0814438400000388, S800
firewire_core: created device fw2: GUID 0001d202e06800d1, S800
turns into
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core 0000:04:00.0: created device fw0: GUID 0814438400000389, S800
firewire_core 0000:04:00.0: phy config: new root=ffc1, gap_count=5
firewire_core 0000:05:00.0: created device fw1: GUID 0814438400000388, S800
firewire_core 0000:04:00.0: created device fw2: GUID 0001d202e06800d1, S800
This increases the module size slightly; to keep this in check, turn the
former printk wrapper macros into functions. Their implementation is
largely copied from driver core's dev_printk counterparts.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2012-02-18 21:03:14 +00:00
|
|
|
fw_notice(card, "%s, making local node (%02x) root\n",
|
2010-05-30 17:43:52 +00:00
|
|
|
"IRM is not 1394a compliant", new_root_id);
|
2007-01-26 05:38:45 +00:00
|
|
|
goto pick_me;
|
|
|
|
}
|
|
|
|
|
2011-04-22 13:13:54 +00:00
|
|
|
transaction_data[0] = cpu_to_be32(0x3f);
|
|
|
|
transaction_data[1] = cpu_to_be32(local_id);
|
2007-01-26 05:38:45 +00:00
|
|
|
|
2010-06-21 21:23:52 +00:00
|
|
|
spin_unlock_irq(&card->lock);
|
2007-01-26 05:38:45 +00:00
|
|
|
|
2008-07-20 12:20:53 +00:00
|
|
|
rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
|
|
|
|
irm_id, generation, SCODE_100,
|
|
|
|
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
|
2011-04-22 13:13:54 +00:00
|
|
|
transaction_data, 8);
|
2007-01-26 05:38:45 +00:00
|
|
|
|
2008-07-20 12:20:53 +00:00
|
|
|
if (rcode == RCODE_GENERATION)
|
|
|
|
/* Another bus reset, BM work has been rescheduled. */
|
2008-02-24 17:57:23 +00:00
|
|
|
goto out;
|
2007-01-26 05:38:45 +00:00
|
|
|
|
2011-04-22 13:13:54 +00:00
|
|
|
bm_id = be32_to_cpu(transaction_data[0]);
|
2009-03-10 20:08:37 +00:00
|
|
|
|
2024-08-05 08:54:05 +00:00
|
|
|
scoped_guard(spinlock_irq, &card->lock) {
|
|
|
|
if (rcode == RCODE_COMPLETE && generation == card->generation)
|
|
|
|
card->bm_node_id =
|
|
|
|
bm_id == 0x3f ? local_id : 0xffc0 | bm_id;
|
|
|
|
}
|
2009-03-10 20:08:37 +00:00
|
|
|
|
2010-06-21 21:24:35 +00:00
|
|
|
if (rcode == RCODE_COMPLETE && bm_id != 0x3f) {
|
2009-03-10 20:08:37 +00:00
|
|
|
/* Somebody else is BM. Only act as IRM. */
|
|
|
|
if (local_id == irm_id)
|
|
|
|
allocate_broadcast_channel(card, generation);
|
|
|
|
|
2008-02-24 17:57:23 +00:00
|
|
|
goto out;
|
2009-02-23 20:59:34 +00:00
|
|
|
}
|
2007-01-26 05:38:45 +00:00
|
|
|
|
2010-06-10 06:23:28 +00:00
|
|
|
if (rcode == RCODE_SEND_ERROR) {
|
|
|
|
/*
|
|
|
|
* We have been unable to send the lock request due to
|
|
|
|
* some local problem. Let's try again later and hope
|
|
|
|
* that the problem has gone away by then.
|
|
|
|
*/
|
|
|
|
fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2010-06-21 21:23:52 +00:00
|
|
|
spin_lock_irq(&card->lock);
|
2008-07-20 12:20:53 +00:00
|
|
|
|
2011-01-15 17:19:48 +00:00
|
|
|
if (rcode != RCODE_COMPLETE && !keep_this_irm) {
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* The lock request failed, maybe the IRM
|
2007-01-26 05:38:45 +00:00
|
|
|
* isn't really IRM capable after all. Let's
|
|
|
|
* do a bus reset and pick the local node as
|
2007-05-08 00:33:32 +00:00
|
|
|
* root, and thus, IRM.
|
|
|
|
*/
|
2009-03-10 20:08:37 +00:00
|
|
|
new_root_id = local_id;
|
2012-04-11 15:38:47 +00:00
|
|
|
fw_notice(card, "BM lock failed (%s), making local node (%02x) root\n",
|
|
|
|
fw_rcode_string(rcode), new_root_id);
|
2007-01-26 05:38:45 +00:00
|
|
|
goto pick_me;
|
|
|
|
}
|
|
|
|
} else if (card->bm_generation != generation) {
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
2009-03-10 20:07:46 +00:00
|
|
|
* We weren't BM in the last generation, and the last
|
|
|
|
* bus reset is less than 125ms ago. Reschedule this job.
|
2007-05-08 00:33:32 +00:00
|
|
|
*/
|
2010-06-21 21:23:52 +00:00
|
|
|
spin_unlock_irq(&card->lock);
|
2009-03-10 20:07:46 +00:00
|
|
|
fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 8));
|
2008-02-24 17:57:23 +00:00
|
|
|
goto out;
|
2007-01-26 05:38:45 +00:00
|
|
|
}
|
|
|
|
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* We're bus manager for this generation, so next step is to
|
2007-01-26 05:38:45 +00:00
|
|
|
* make sure we have an active cycle master and do gap count
|
2007-05-08 00:33:32 +00:00
|
|
|
* optimization.
|
|
|
|
*/
|
2007-01-26 05:38:45 +00:00
|
|
|
card->bm_generation = generation;
|
2006-12-20 00:58:31 +00:00
|
|
|
|
firewire: core: send bus reset promptly on gap count error
If we are bus manager and the bus has inconsistent gap counts, send a
bus reset immediately instead of trying to read the root node's config
ROM first. Otherwise, we could spend a lot of time trying to read the
config ROM but never succeeding.
This eliminates a 50+ second delay before the FireWire bus is usable after
a newly connected device is powered on in certain circumstances.
The delay occurs if a gap count inconsistency occurs, we are not the root
node, and we become bus manager. One scenario that causes this is with a TI
XIO2213B OHCI, the first time a Sony DSR-25 is powered on after being
connected to the FireWire cable. In this configuration, the Linux box will
not receive the initial PHY configuration packet sent by the DSR-25 as IRM,
resulting in the DSR-25 having a gap count of 44 while the Linux box has a
gap count of 63.
FireWire devices have a gap count parameter, which is set to 63 on power-up
and can be changed with a PHY configuration packet. This determines the
duration of the subaction and arbitration gaps. For reliable communication,
all nodes on a FireWire bus must have the same gap count.
A node may have zero or more of the following roles: root node, bus manager
(BM), isochronous resource manager (IRM), and cycle master. Unless a root
node was forced with a PHY configuration packet, any node might become root
node after a bus reset. Only the root node can become cycle master. If the
root node is not cycle master capable, the BM or IRM should force a change
of root node.
After a bus reset, each node sends a self-ID packet, which contains its
current gap count. A single bus reset does not change the gap count, but
two bus resets in a row will set the gap count to 63. Because a consistent
gap count is required for reliable communication, IEEE 1394a-2000 requires
that the bus manager generate a bus reset if it detects that the gap count
is inconsistent.
When the gap count is inconsistent, build_tree() will notice this after the
self identification process. It will set card->gap_count to the invalid
value 0. If we become bus master, this will force bm_work() to send a bus
reset when it performs gap count optimization.
After a bus reset, there is no bus manager. We will almost always try to
become bus manager. Once we become bus manager, we will first determine
whether the root node is cycle master capable. Then, we will determine if
the gap count should be changed. If either the root node or the gap count
should be changed, we will generate a bus reset.
To determine if the root node is cycle master capable, we read its
configuration ROM. bm_work() will wait until we have finished trying to
read the configuration ROM.
However, an inconsistent gap count can make this take a long time.
read_config_rom() will read the first few quadlets from the config ROM. Due
to the gap count inconsistency, eventually one of the reads will time out.
When read_config_rom() fails, fw_device_init() calls it again until
MAX_RETRIES is reached. This takes 50+ seconds.
Once we give up trying to read the configuration ROM, bm_work() will wake
up, assume that the root node is not cycle master capable, and do a bus
reset. Hopefully, this will resolve the gap count inconsistency.
This change makes bm_work() check for an inconsistent gap count before
waiting for the root node's configuration ROM. If the gap count is
inconsistent, bm_work() will immediately do a bus reset. This eliminates
the 50+ second delay and rapidly brings the bus to a working state.
I considered that if the gap count is inconsistent, a PHY configuration
packet might not be successful, so it could be desirable to skip the PHY
configuration packet before the bus reset in this case. However, IEEE
1394a-2000 and IEEE 1394-2008 say that the bus manager may transmit a PHY
configuration packet before a bus reset when correcting a gap count error.
Since the standard endorses this, I decided it's safe to retain the PHY
configuration packet transmission.
Normally, after a topology change, we will reset the bus a maximum of 5
times to change the root node and perform gap count optimization. However,
if there is a gap count inconsistency, we must always generate a bus reset.
Otherwise the gap count inconsistency will persist and communication will
be unreliable. For that reason, if there is a gap count inconstency, we
generate a bus reset even if we already reached the 5 reset limit.
Signed-off-by: Adam Goldman <adamg@pobox.com>
Reference: https://sourceforge.net/p/linux1394/mailman/message/58727806/
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
2024-02-06 23:01:17 +00:00
|
|
|
if (card->gap_count == 0) {
|
|
|
|
/*
|
|
|
|
* If self IDs have inconsistent gap counts, do a
|
|
|
|
* bus reset ASAP. The config rom read might never
|
|
|
|
* complete, so don't wait for it. However, still
|
|
|
|
* send a PHY configuration packet prior to the
|
|
|
|
* bus reset. The PHY configuration packet might
|
|
|
|
* fail, but 1394-2008 8.4.5.2 explicitly permits
|
|
|
|
* it in this case, so it should be safe to try.
|
|
|
|
*/
|
|
|
|
new_root_id = local_id;
|
|
|
|
/*
|
|
|
|
* We must always send a bus reset if the gap count
|
|
|
|
* is inconsistent, so bypass the 5-reset limit.
|
|
|
|
*/
|
|
|
|
card->bm_retries = 0;
|
|
|
|
} else if (root_device == NULL) {
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* Either link_on is false, or we failed to read the
|
|
|
|
* config rom. In either case, pick another root.
|
|
|
|
*/
|
2009-03-10 20:08:37 +00:00
|
|
|
new_root_id = local_id;
|
2009-01-09 19:49:37 +00:00
|
|
|
} else if (!root_device_is_running) {
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* If we haven't probed this device yet, bail out now
|
|
|
|
* and let's try again once that's done.
|
|
|
|
*/
|
2010-06-21 21:23:52 +00:00
|
|
|
spin_unlock_irq(&card->lock);
|
2008-02-24 17:57:23 +00:00
|
|
|
goto out;
|
2009-01-09 19:49:37 +00:00
|
|
|
} else if (root_device_is_cmc) {
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
2010-06-10 06:41:51 +00:00
|
|
|
* We will send out a force root packet for this
|
|
|
|
* node as part of the gap count optimization.
|
2007-05-08 00:33:32 +00:00
|
|
|
*/
|
2007-01-26 05:38:45 +00:00
|
|
|
new_root_id = root_id;
|
2007-01-26 05:37:50 +00:00
|
|
|
} else {
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
|
|
|
* Current root has an active link layer and we
|
2006-12-20 00:58:31 +00:00
|
|
|
* successfully read the config rom, but it's not
|
2007-05-08 00:33:32 +00:00
|
|
|
* cycle master capable.
|
|
|
|
*/
|
2009-03-10 20:08:37 +00:00
|
|
|
new_root_id = local_id;
|
2007-01-26 05:37:50 +00:00
|
|
|
}
|
|
|
|
|
2007-01-26 05:38:45 +00:00
|
|
|
pick_me:
|
2007-06-18 17:44:12 +00:00
|
|
|
/*
|
|
|
|
* Pick a gap count from 1394a table E-1. The table doesn't cover
|
|
|
|
* the typically much larger 1394b beta repeater delays though.
|
|
|
|
*/
|
|
|
|
if (!card->beta_repeaters_present &&
|
2008-02-24 17:57:23 +00:00
|
|
|
root_node->max_hops < ARRAY_SIZE(gap_count_table))
|
|
|
|
gap_count = gap_count_table[root_node->max_hops];
|
2007-01-26 05:37:50 +00:00
|
|
|
else
|
|
|
|
gap_count = 63;
|
|
|
|
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
2008-03-24 19:57:12 +00:00
|
|
|
* Finally, figure out if we should do a reset or not. If we have
|
|
|
|
* done less than 5 resets with the same physical topology and we
|
2007-05-08 00:33:32 +00:00
|
|
|
* have either a new root or a new gap count setting, let's do it.
|
|
|
|
*/
|
2006-12-20 00:58:31 +00:00
|
|
|
|
2007-01-26 05:38:45 +00:00
|
|
|
if (card->bm_retries++ < 5 &&
|
|
|
|
(card->gap_count != gap_count || new_root_id != root_id))
|
2008-03-24 19:57:12 +00:00
|
|
|
do_reset = true;
|
2006-12-20 00:58:31 +00:00
|
|
|
|
2010-06-21 21:23:52 +00:00
|
|
|
spin_unlock_irq(&card->lock);
|
2006-12-20 00:58:31 +00:00
|
|
|
|
2007-01-26 05:37:50 +00:00
|
|
|
if (do_reset) {
|
firewire: core: prefix log messages with card name
Associate all log messages from firewire-core with the respective card
because some people have more than one card. E.g.
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core: created device fw0: GUID 0814438400000389, S800
firewire_core: phy config: new root=ffc1, gap_count=5
firewire_core: created device fw1: GUID 0814438400000388, S800
firewire_core: created device fw2: GUID 0001d202e06800d1, S800
turns into
firewire_ohci 0000:04:00.0: added OHCI v1.10 device as card 0, 8 IR + 8 IT contexts, quirks 0x0
firewire_ohci 0000:05:00.0: added OHCI v1.10 device as card 1, 8 IR + 8 IT contexts, quirks 0x0
firewire_core 0000:04:00.0: created device fw0: GUID 0814438400000389, S800
firewire_core 0000:04:00.0: phy config: new root=ffc1, gap_count=5
firewire_core 0000:05:00.0: created device fw1: GUID 0814438400000388, S800
firewire_core 0000:04:00.0: created device fw2: GUID 0001d202e06800d1, S800
This increases the module size slightly; to keep this in check, turn the
former printk wrapper macros into functions. Their implementation is
largely copied from driver core's dev_printk counterparts.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
2012-02-18 21:03:14 +00:00
|
|
|
fw_notice(card, "phy config: new root=%x, gap_count=%d\n",
|
|
|
|
new_root_id, gap_count);
|
2007-01-26 05:38:45 +00:00
|
|
|
fw_send_phy_config(card, new_root_id, generation, gap_count);
|
firewire: core: use long bus reset on gap count error
When resetting the bus after a gap count error, use a long rather than
short bus reset.
IEEE 1394-1995 uses only long bus resets. IEEE 1394a adds the option of
short bus resets. When video or audio transmission is in progress and a
device is hot-plugged elsewhere on the bus, the resulting bus reset can
cause video frame drops or audio dropouts. Short bus resets reduce or
eliminate this problem. Accordingly, short bus resets are almost always
preferred.
However, on a mixed 1394/1394a bus, a short bus reset can trigger an
immediate additional bus reset. This double bus reset can be interpreted
differently by different nodes on the bus, resulting in an inconsistent gap
count after the bus reset. An inconsistent gap count will cause another bus
reset, leading to a neverending bus reset loop. This only happens for some
bus topologies, not for all mixed 1394/1394a buses.
By instead sending a long bus reset after a gap count inconsistency, we
avoid the doubled bus reset, restoring the bus to normal operation.
Signed-off-by: Adam Goldman <adamg@pobox.com>
Link: https://sourceforge.net/p/linux1394/mailman/message/58741624/
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
2024-02-29 13:17:37 +00:00
|
|
|
/*
|
|
|
|
* Where possible, use a short bus reset to minimize
|
|
|
|
* disruption to isochronous transfers. But in the event
|
|
|
|
* of a gap count inconsistency, use a long bus reset.
|
|
|
|
*
|
|
|
|
* As noted in 1394a 8.4.6.2, nodes on a mixed 1394/1394a bus
|
|
|
|
* may set different gap counts after a bus reset. On a mixed
|
|
|
|
* 1394/1394a bus, a short bus reset can get doubled. Some
|
|
|
|
* nodes may treat the double reset as one bus reset and others
|
|
|
|
* may treat it as two, causing a gap count inconsistency
|
|
|
|
* again. Using a long bus reset prevents this.
|
|
|
|
*/
|
|
|
|
reset_bus(card, card->gap_count != 0);
|
2009-03-10 20:08:37 +00:00
|
|
|
/* Will allocate broadcast channel after the reset. */
|
2010-06-10 06:41:51 +00:00
|
|
|
goto out;
|
2006-12-20 00:58:31 +00:00
|
|
|
}
|
2009-02-23 20:59:34 +00:00
|
|
|
|
2010-06-10 06:41:51 +00:00
|
|
|
if (root_device_is_cmc) {
|
|
|
|
/*
|
|
|
|
* Make sure that the cycle master sends cycle start packets.
|
|
|
|
*/
|
2011-04-22 13:13:54 +00:00
|
|
|
transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR);
|
2010-06-10 06:41:51 +00:00
|
|
|
rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,
|
|
|
|
root_id, generation, SCODE_100,
|
|
|
|
CSR_REGISTER_BASE + CSR_STATE_SET,
|
2011-04-22 13:13:54 +00:00
|
|
|
transaction_data, 4);
|
2010-06-10 06:41:51 +00:00
|
|
|
if (rcode == RCODE_GENERATION)
|
|
|
|
goto out;
|
2006-12-20 00:58:31 +00:00
|
|
|
}
|
2009-02-23 20:59:34 +00:00
|
|
|
|
2010-06-10 06:41:51 +00:00
|
|
|
if (local_id == irm_id)
|
|
|
|
allocate_broadcast_channel(card, generation);
|
|
|
|
|
2008-02-24 17:57:23 +00:00
|
|
|
out:
|
|
|
|
fw_node_put(root_node);
|
2008-11-29 16:44:57 +00:00
|
|
|
out_put_card:
|
|
|
|
fw_card_put(card);
|
2006-12-20 00:58:31 +00:00
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
void fw_card_initialize(struct fw_card *card,
|
|
|
|
const struct fw_card_driver *driver,
|
|
|
|
struct device *device)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
2007-02-06 19:49:38 +00:00
|
|
|
static atomic_t index = ATOMIC_INIT(-1);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2007-02-06 19:49:38 +00:00
|
|
|
card->index = atomic_inc_return(&index);
|
2007-01-21 19:44:09 +00:00
|
|
|
card->driver = driver;
|
2006-12-20 00:58:27 +00:00
|
|
|
card->device = device;
|
2007-01-21 19:44:09 +00:00
|
|
|
card->current_tlabel = 0;
|
|
|
|
card->tlabel_mask = 0;
|
2011-03-07 10:21:15 +00:00
|
|
|
card->split_timeout_hi = DEFAULT_SPLIT_TIMEOUT / 8000;
|
|
|
|
card->split_timeout_lo = (DEFAULT_SPLIT_TIMEOUT % 8000) << 19;
|
|
|
|
card->split_timeout_cycles = DEFAULT_SPLIT_TIMEOUT;
|
|
|
|
card->split_timeout_jiffies =
|
|
|
|
DIV_ROUND_UP(DEFAULT_SPLIT_TIMEOUT * HZ, 8000);
|
2006-12-20 00:58:27 +00:00
|
|
|
card->color = 0;
|
2008-05-24 14:41:09 +00:00
|
|
|
card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2008-05-24 14:50:22 +00:00
|
|
|
kref_init(&card->kref);
|
|
|
|
init_completion(&card->done);
|
2007-01-21 19:44:09 +00:00
|
|
|
INIT_LIST_HEAD(&card->transaction_list);
|
2010-07-16 20:25:51 +00:00
|
|
|
INIT_LIST_HEAD(&card->phy_receiver_list);
|
2006-12-20 00:58:27 +00:00
|
|
|
spin_lock_init(&card->lock);
|
|
|
|
|
|
|
|
card->local_node = NULL;
|
|
|
|
|
2010-07-08 14:09:06 +00:00
|
|
|
INIT_DELAYED_WORK(&card->br_work, br_work);
|
|
|
|
INIT_DELAYED_WORK(&card->bm_work, bm_work);
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(fw_card_initialize);
|
|
|
|
|
2024-09-04 12:51:50 +00:00
|
|
|
int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid,
|
|
|
|
unsigned int supported_isoc_contexts)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
2024-09-04 12:51:50 +00:00
|
|
|
struct workqueue_struct *isoc_wq;
|
2009-02-03 16:55:19 +00:00
|
|
|
int ret;
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2024-09-04 12:51:50 +00:00
|
|
|
// This workqueue should be:
|
|
|
|
// * != WQ_BH Sleepable.
|
|
|
|
// * == WQ_UNBOUND Any core can process data for isoc context. The
|
|
|
|
// implementation of unit protocol could consumes the core
|
|
|
|
// longer somehow.
|
|
|
|
// * != WQ_MEM_RECLAIM Not used for any backend of block device.
|
|
|
|
// * == WQ_FREEZABLE Isochronous communication is at regular interval in real
|
|
|
|
// time, thus should be drained if possible at freeze phase.
|
|
|
|
// * == WQ_HIGHPRI High priority to process semi-realtime timestamped data.
|
|
|
|
// * == WQ_SYSFS Parameters are available via sysfs.
|
|
|
|
// * max_active == n_it + n_ir A hardIRQ could notify events for multiple isochronous
|
|
|
|
// contexts if they are scheduled to the same cycle.
|
|
|
|
isoc_wq = alloc_workqueue("firewire-isoc-card%u",
|
|
|
|
WQ_UNBOUND | WQ_FREEZABLE | WQ_HIGHPRI | WQ_SYSFS,
|
|
|
|
supported_isoc_contexts, card->index);
|
|
|
|
if (!isoc_wq)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2006-12-20 00:58:27 +00:00
|
|
|
card->max_receive = max_receive;
|
|
|
|
card->link_speed = link_speed;
|
|
|
|
card->guid = guid;
|
|
|
|
|
2024-08-05 08:53:53 +00:00
|
|
|
guard(mutex)(&card_mutex);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2010-01-24 13:47:02 +00:00
|
|
|
generate_config_rom(card, tmp_config_rom);
|
|
|
|
ret = card->driver->enable(card, tmp_config_rom, config_rom_length);
|
2024-09-04 12:51:50 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
destroy_workqueue(isoc_wq);
|
2024-08-05 08:53:53 +00:00
|
|
|
return ret;
|
2024-09-04 12:51:50 +00:00
|
|
|
}
|
2009-09-06 16:50:29 +00:00
|
|
|
|
2024-09-04 12:51:50 +00:00
|
|
|
card->isoc_wq = isoc_wq;
|
2024-08-05 08:53:53 +00:00
|
|
|
list_add_tail(&card->link, &card_list);
|
2009-02-03 16:55:19 +00:00
|
|
|
|
2024-08-05 08:53:53 +00:00
|
|
|
return 0;
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(fw_card_add);
|
|
|
|
|
2007-05-08 00:33:32 +00:00
|
|
|
/*
|
2009-06-16 17:15:25 +00:00
|
|
|
* The next few functions implement a dummy driver that is used once a card
|
|
|
|
* driver shuts down an fw_card. This allows the driver to cleanly unload,
|
|
|
|
* as all IO to the card will be handled (and failed) by the dummy driver
|
|
|
|
* instead of calling into the module. Only functions for iso context
|
|
|
|
* shutdown still need to be provided by the card driver.
|
2010-08-01 10:23:14 +00:00
|
|
|
*
|
|
|
|
* .read/write_csr() should never be called anymore after the dummy driver
|
|
|
|
* was bound since they are only used within request handler context.
|
|
|
|
* .set_config_rom() is never called since the card is taken out of card_list
|
|
|
|
* before switching to the dummy driver.
|
2007-05-08 00:33:32 +00:00
|
|
|
*/
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2010-07-08 14:09:06 +00:00
|
|
|
static int dummy_read_phy_reg(struct fw_card *card, int address)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
2010-07-08 14:09:06 +00:00
|
|
|
return -ENODEV;
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
static int dummy_update_phy_reg(struct fw_card *card, int address,
|
|
|
|
int clear_bits, int set_bits)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
static void dummy_send_request(struct fw_card *card, struct fw_packet *packet)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
2010-07-18 10:44:01 +00:00
|
|
|
packet->callback(packet, card, RCODE_CANCELLED);
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
static void dummy_send_response(struct fw_card *card, struct fw_packet *packet)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
2010-07-18 10:44:01 +00:00
|
|
|
packet->callback(packet, card, RCODE_CANCELLED);
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
static int dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet)
|
2007-02-06 19:49:32 +00:00
|
|
|
{
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
static int dummy_enable_phys_dma(struct fw_card *card,
|
|
|
|
int node_id, int generation)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2010-08-01 10:23:14 +00:00
|
|
|
static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card,
|
|
|
|
int type, int channel, size_t header_size)
|
|
|
|
{
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
|
firewire: Add dummy read_csr/write_csr functions
(Hector Martin wrote)
This fixes segfaults when a card gets yanked off of the PCIe bus while
busy, e.g. with a userspace app trying to get the cycle time:
[8638860.994310] Call Trace:
[8638860.994313] ioctl_get_cycle_timer2+0x4f/0xd0 [firewire_core]
[8638860.994323] fw_device_op_ioctl+0xae/0x150 [firewire_core]
[8638860.994328] __x64_sys_ioctl+0x7d/0xb0
[8638860.994332] do_syscall_64+0x45/0x80
[8638860.994337] entry_SYSCALL_64_after_hwframe+0x44/0xae
(Takashi Sakamoto wrote)
As long as reading commit 20802224298c ("firewire: core: add forgotten
dummy driver methods, remove unused ones"), three functions are not
implemeted in dummy driver for reason; .read_csr, .write_csr, and
.set_config_rom.
In core of Linux FireWire subsystem, the callback of .set_config_rom is
under acquisition of mutual exclusive for local list of card. The
acquision is also done in process for removal of card, therefore it's
safe for missing implementation of .set_config_rom.
On the other hand, no lock primitive accompanies any call of .read_csr and
.write_csr. For userspace client, check of node shutdown is done in the
beginning of dispatch of ioctl request, while node shifts to shutdown
state in workqueue context enough after card shifts to dummy driver. It's
probable that these two functions are called for the dummy driver by the
code of userspace client. In-kernel unit driver has similar situation.
It's better to add implementation of the two functions for dummy driver.
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20220405072221.226217-2-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2022-04-05 07:22:19 +00:00
|
|
|
static u32 dummy_read_csr(struct fw_card *card, int csr_offset)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dummy_write_csr(struct fw_card *card, int csr_offset, u32 value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-08-01 10:23:14 +00:00
|
|
|
static int dummy_start_iso(struct fw_iso_context *ctx,
|
|
|
|
s32 cycle, u32 sync, u32 tags)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dummy_set_iso_channels(struct fw_iso_context *ctx, u64 *channels)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p,
|
|
|
|
struct fw_iso_buffer *buffer, unsigned long payload)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2011-05-02 07:33:56 +00:00
|
|
|
static void dummy_flush_queue_iso(struct fw_iso_context *ctx)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-03-18 18:06:39 +00:00
|
|
|
static int dummy_flush_iso_completions(struct fw_iso_context *ctx)
|
|
|
|
{
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2009-06-16 17:15:25 +00:00
|
|
|
static const struct fw_card_driver dummy_driver_template = {
|
2010-08-01 10:23:14 +00:00
|
|
|
.read_phy_reg = dummy_read_phy_reg,
|
|
|
|
.update_phy_reg = dummy_update_phy_reg,
|
|
|
|
.send_request = dummy_send_request,
|
|
|
|
.send_response = dummy_send_response,
|
|
|
|
.cancel_packet = dummy_cancel_packet,
|
|
|
|
.enable_phys_dma = dummy_enable_phys_dma,
|
firewire: Add dummy read_csr/write_csr functions
(Hector Martin wrote)
This fixes segfaults when a card gets yanked off of the PCIe bus while
busy, e.g. with a userspace app trying to get the cycle time:
[8638860.994310] Call Trace:
[8638860.994313] ioctl_get_cycle_timer2+0x4f/0xd0 [firewire_core]
[8638860.994323] fw_device_op_ioctl+0xae/0x150 [firewire_core]
[8638860.994328] __x64_sys_ioctl+0x7d/0xb0
[8638860.994332] do_syscall_64+0x45/0x80
[8638860.994337] entry_SYSCALL_64_after_hwframe+0x44/0xae
(Takashi Sakamoto wrote)
As long as reading commit 20802224298c ("firewire: core: add forgotten
dummy driver methods, remove unused ones"), three functions are not
implemeted in dummy driver for reason; .read_csr, .write_csr, and
.set_config_rom.
In core of Linux FireWire subsystem, the callback of .set_config_rom is
under acquisition of mutual exclusive for local list of card. The
acquision is also done in process for removal of card, therefore it's
safe for missing implementation of .set_config_rom.
On the other hand, no lock primitive accompanies any call of .read_csr and
.write_csr. For userspace client, check of node shutdown is done in the
beginning of dispatch of ioctl request, while node shifts to shutdown
state in workqueue context enough after card shifts to dummy driver. It's
probable that these two functions are called for the dummy driver by the
code of userspace client. In-kernel unit driver has similar situation.
It's better to add implementation of the two functions for dummy driver.
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20220405072221.226217-2-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2022-04-05 07:22:19 +00:00
|
|
|
.read_csr = dummy_read_csr,
|
|
|
|
.write_csr = dummy_write_csr,
|
2010-08-01 10:23:14 +00:00
|
|
|
.allocate_iso_context = dummy_allocate_iso_context,
|
|
|
|
.start_iso = dummy_start_iso,
|
|
|
|
.set_iso_channels = dummy_set_iso_channels,
|
|
|
|
.queue_iso = dummy_queue_iso,
|
2011-05-02 07:33:56 +00:00
|
|
|
.flush_queue_iso = dummy_flush_queue_iso,
|
2012-03-18 18:06:39 +00:00
|
|
|
.flush_iso_completions = dummy_flush_iso_completions,
|
2006-12-20 00:58:27 +00:00
|
|
|
};
|
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
void fw_card_release(struct kref *kref)
|
2008-05-24 14:50:22 +00:00
|
|
|
{
|
|
|
|
struct fw_card *card = container_of(kref, struct fw_card, kref);
|
|
|
|
|
|
|
|
complete(&card->done);
|
|
|
|
}
|
2012-02-01 22:36:02 +00:00
|
|
|
EXPORT_SYMBOL_GPL(fw_card_release);
|
2008-05-24 14:50:22 +00:00
|
|
|
|
2008-12-14 20:47:04 +00:00
|
|
|
void fw_core_remove_card(struct fw_card *card)
|
2006-12-20 00:58:27 +00:00
|
|
|
{
|
2009-06-16 17:15:25 +00:00
|
|
|
struct fw_card_driver dummy_driver = dummy_driver_template;
|
|
|
|
|
2024-09-04 12:51:50 +00:00
|
|
|
might_sleep();
|
|
|
|
|
2007-03-23 16:24:02 +00:00
|
|
|
card->driver->update_phy_reg(card, 4,
|
|
|
|
PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
|
2010-07-08 14:09:06 +00:00
|
|
|
fw_schedule_bus_reset(card, false, true);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2024-08-05 08:53:53 +00:00
|
|
|
scoped_guard(mutex, &card_mutex)
|
|
|
|
list_del_init(&card->link);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2009-06-16 17:15:25 +00:00
|
|
|
/* Switch off most of the card driver interface. */
|
|
|
|
dummy_driver.free_iso_context = card->driver->free_iso_context;
|
|
|
|
dummy_driver.stop_iso = card->driver->stop_iso;
|
2006-12-20 00:58:27 +00:00
|
|
|
card->driver = &dummy_driver;
|
2024-09-04 12:51:50 +00:00
|
|
|
drain_workqueue(card->isoc_wq);
|
2006-12-20 00:58:27 +00:00
|
|
|
|
2024-08-05 08:54:05 +00:00
|
|
|
scoped_guard(spinlock_irqsave, &card->lock)
|
|
|
|
fw_destroy_nodes(card);
|
2008-05-24 14:50:22 +00:00
|
|
|
|
|
|
|
/* Wait for all users, especially device workqueue jobs, to finish. */
|
|
|
|
fw_card_put(card);
|
|
|
|
wait_for_completion(&card->done);
|
2007-08-20 23:05:14 +00:00
|
|
|
|
2024-09-04 12:51:50 +00:00
|
|
|
destroy_workqueue(card->isoc_wq);
|
|
|
|
|
2008-07-12 12:51:18 +00:00
|
|
|
WARN_ON(!list_empty(&card->transaction_list));
|
2006-12-20 00:58:27 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(fw_core_remove_card);
|
2022-04-05 07:22:20 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_card_read_cycle_time: read from Isochronous Cycle Timer Register of 1394 OHCI in MMIO region
|
|
|
|
* for controller card.
|
|
|
|
* @card: The instance of card for 1394 OHCI controller.
|
|
|
|
* @cycle_time: The mutual reference to value of cycle time for the read operation.
|
|
|
|
*
|
|
|
|
* Read value from Isochronous Cycle Timer Register of 1394 OHCI in MMIO region for the given
|
|
|
|
* controller card. This function accesses the region without any lock primitives or IRQ mask.
|
|
|
|
* When returning successfully, the content of @value argument has value aligned to host endianness,
|
|
|
|
* formetted by CYCLE_TIME CSR Register of IEEE 1394 std.
|
|
|
|
*
|
|
|
|
* Context: Any context.
|
|
|
|
* Return:
|
|
|
|
* * 0 - Read successfully.
|
|
|
|
* * -ENODEV - The controller is unavailable due to being removed or unbound.
|
|
|
|
*/
|
|
|
|
int fw_card_read_cycle_time(struct fw_card *card, u32 *cycle_time)
|
|
|
|
{
|
|
|
|
if (card->driver->read_csr == dummy_read_csr)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
// It's possible to switch to dummy driver between the above and the below. This is the best
|
|
|
|
// effort to return -ENODEV.
|
|
|
|
*cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(fw_card_read_cycle_time);
|