linux/drivers/firewire/ohci.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Driver for OHCI 1394 controllers
 *
 * Copyright (C) 2003-2006 Kristian Hoegsberg <[email protected]>
 */

#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>

#include <asm/byteorder.h>
#include <asm/page.h>

#ifdef CONFIG_PPC_PMAC
#include <asm/pmac_feature.h>
#endif

#include "core.h"
#include "ohci.h"
#include "packet-header-definitions.h"
#include "phy-packet-definitions.h"

#include <trace/events/firewire.h>

static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk);

#define CREATE_TRACE_POINTS
#include <trace/events/firewire_ohci.h>

#define ohci_info(ohci, f, args...)
#define ohci_notice(ohci, f, args...)
#define ohci_err(ohci, f, args...)

#define DESCRIPTOR_OUTPUT_MORE
#define DESCRIPTOR_OUTPUT_LAST
#define DESCRIPTOR_INPUT_MORE
#define DESCRIPTOR_INPUT_LAST
#define DESCRIPTOR_STATUS
#define DESCRIPTOR_KEY_IMMEDIATE
#define DESCRIPTOR_PING
#define DESCRIPTOR_YY
#define DESCRIPTOR_NO_IRQ
#define DESCRIPTOR_IRQ_ERROR
#define DESCRIPTOR_IRQ_ALWAYS
#define DESCRIPTOR_BRANCH_ALWAYS
#define DESCRIPTOR_WAIT

#define DESCRIPTOR_CMD

struct descriptor {} __attribute__((aligned));

#define CONTROL_SET(regs)
#define CONTROL_CLEAR(regs)
#define COMMAND_PTR(regs)
#define CONTEXT_MATCH(regs)

#define AR_BUFFER_SIZE
#define AR_BUFFERS_MIN
/* we need at least two pages for proper list management */
#define AR_BUFFERS

#define MAX_ASYNC_PAYLOAD
#define MAX_AR_PACKET_SIZE
#define AR_WRAPAROUND_PAGES

struct ar_context {};

struct context;

descriptor_callback_t;

/*
 * A buffer that contains a block of DMA-able coherent memory used for
 * storing a portion of a DMA descriptor program.
 */
struct descriptor_buffer {};

struct context {};

#define IT_HEADER_SY(v)
#define IT_HEADER_TCODE(v)
#define IT_HEADER_CHANNEL(v)
#define IT_HEADER_TAG(v)
#define IT_HEADER_SPEED(v)
#define IT_HEADER_DATA_LENGTH(v)

struct iso_context {};

#define CONFIG_ROM_SIZE

struct fw_ohci {};

static struct workqueue_struct *selfid_workqueue;

static inline struct fw_ohci *fw_ohci(struct fw_card *card)
{}

#define IT_CONTEXT_CYCLE_MATCH_ENABLE
#define IR_CONTEXT_BUFFER_FILL
#define IR_CONTEXT_ISOCH_HEADER
#define IR_CONTEXT_CYCLE_MATCH_ENABLE
#define IR_CONTEXT_MULTI_CHANNEL_MODE
#define IR_CONTEXT_DUAL_BUFFER_MODE

#define CONTEXT_RUN
#define CONTEXT_WAKE
#define CONTEXT_DEAD
#define CONTEXT_ACTIVE

#define OHCI1394_MAX_AT_REQ_RETRIES
#define OHCI1394_MAX_AT_RESP_RETRIES
#define OHCI1394_MAX_PHYS_RESP_RETRIES

#define OHCI1394_REGISTER_SIZE
#define OHCI1394_PCI_HCI_Control
#define SELF_ID_BUF_SIZE
#define OHCI_TCODE_PHY_PACKET
#define OHCI_VERSION_1_1

static char ohci_driver_name[] =;

#define PCI_VENDOR_ID_PINNACLE_SYSTEMS
#define PCI_DEVICE_ID_AGERE_FW643
#define PCI_DEVICE_ID_CREATIVE_SB1394
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW
#define PCI_DEVICE_ID_TI_TSB12LV22
#define PCI_DEVICE_ID_TI_TSB12LV26
#define PCI_DEVICE_ID_TI_TSB82AA2
#define PCI_DEVICE_ID_VIA_VT630X
#define PCI_REV_ID_VIA_VT6306
#define PCI_DEVICE_ID_VIA_VT6315

#define QUIRK_CYCLE_TIMER
#define QUIRK_RESET_PACKET
#define QUIRK_BE_HEADERS
#define QUIRK_NO_1394A
#define QUIRK_NO_MSI
#define QUIRK_TI_SLLZ059
#define QUIRK_IR_WAKE

// On PCI Express Root Complex in any type of AMD Ryzen machine, VIA VT6306/6307/6308 with Asmedia
// ASM1083/1085 brings an inconvenience that the read accesses to 'Isochronous Cycle Timer' register
// (at offset 0xf0 in PCI I/O space) often causes unexpected system reboot. The mechanism is not
// clear, since the read access to the other registers is enough safe; e.g. 'Node ID' register,
// while it is probable due to detection of any type of PCIe error.
#define QUIRK_REBOOT_BY_CYCLE_TIMER_READ

#if IS_ENABLED(CONFIG_X86)

static bool has_reboot_by_cycle_timer_read_quirk(const struct fw_ohci *ohci)
{}

#define PCI_DEVICE_ID_ASMEDIA_ASM108X

static bool detect_vt630x_with_asm1083_on_amd_ryzen_machine(const struct pci_dev *pdev)
{}

#else
#define has_reboot_by_cycle_timer_read_quirk
#define detect_vt630x_with_asm1083_on_amd_ryzen_machine
#endif

/* In case of multiple matches in ohci_quirks[], only the first one is used. */
static const struct {} ohci_quirks[] =;

/* This overrides anything that was found in ohci_quirks[]. */
static int param_quirks;
module_param_named(quirks, param_quirks, int, 0644);
MODULE_PARM_DESC();

#define OHCI_PARAM_DEBUG_AT_AR
#define OHCI_PARAM_DEBUG_SELFIDS
#define OHCI_PARAM_DEBUG_IRQS

static int param_debug;
module_param_named(debug, param_debug, int, 0644);
MODULE_PARM_DESC();

static bool param_remote_dma;
module_param_named(remote_dma, param_remote_dma, bool, 0444);
MODULE_PARM_DESC();

static void log_irqs(struct fw_ohci *ohci, u32 evt)
{}

static void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count)
{}

static const char *evts[] =;
static const char *tcodes[] =;

static void log_ar_at_event(struct fw_ohci *ohci,
			    char dir, int speed, u32 *header, int evt)
{}

static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
{}

static inline u32 reg_read(const struct fw_ohci *ohci, int offset)
{}

static inline void flush_writes(const struct fw_ohci *ohci)
{}

/*
 * Beware!  read_phy_reg(), write_phy_reg(), update_phy_reg(), and
 * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex.
 * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg()
 * directly.  Exceptions are intrinsically serialized contexts like pci_probe.
 */
static int read_phy_reg(struct fw_ohci *ohci, int addr)
{}

static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
{}

static int update_phy_reg(struct fw_ohci *ohci, int addr,
			  int clear_bits, int set_bits)
{}

static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr)
{}

static int ohci_read_phy_reg(struct fw_card *card, int addr)
{}

static int ohci_update_phy_reg(struct fw_card *card, int addr,
			       int clear_bits, int set_bits)
{}

static inline dma_addr_t ar_buffer_bus(struct ar_context *ctx, unsigned int i)
{}

static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
{}

static void ar_context_release(struct ar_context *ctx)
{}

static void ar_context_abort(struct ar_context *ctx, const char *error_msg)
{}

static inline unsigned int ar_next_buffer_index(unsigned int index)
{}

static inline unsigned int ar_first_buffer_index(struct ar_context *ctx)
{}

/*
 * We search for the buffer that contains the last AR packet DMA data written
 * by the controller.
 */
static unsigned int ar_search_last_active_buffer(struct ar_context *ctx,
						 unsigned int *buffer_offset)
{}

static void ar_sync_buffers_for_cpu(struct ar_context *ctx,
				    unsigned int end_buffer_index,
				    unsigned int end_buffer_offset)
{}

#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk)
{
	return has_be_header_quirk ? (__force __u32)value : le32_to_cpu(value);
}

static bool has_be_header_quirk(const struct fw_ohci *ohci)
{
	return !!(ohci->quirks & QUIRK_BE_HEADERS);
}
#else
static u32 cond_le32_to_cpu(__le32 value, bool has_be_header_quirk __maybe_unused)
{}

static bool has_be_header_quirk(const struct fw_ohci *ohci)
{}
#endif

static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
{}

static void *handle_ar_packets(struct ar_context *ctx, void *p, void *end)
{}

static void ar_recycle_buffers(struct ar_context *ctx, unsigned int end_buffer)
{}

static void ar_context_tasklet(unsigned long data)
{}

static int ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci,
			   unsigned int descriptors_offset, u32 regs)
{}

static void ar_context_run(struct ar_context *ctx)
{}

static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
{}

static void context_tasklet(unsigned long data)
{}

/*
 * Allocate a new buffer and add it to the list of free buffers for this
 * context.  Must be called with ohci->lock held.
 */
static int context_add_buffer(struct context *ctx)
{}

static int context_init(struct context *ctx, struct fw_ohci *ohci,
			u32 regs, descriptor_callback_t callback)
{}

static void context_release(struct context *ctx)
{}

/* Must be called with ohci->lock held */
static struct descriptor *context_get_descriptors(struct context *ctx,
						  int z, dma_addr_t *d_bus)
{}

static void context_run(struct context *ctx, u32 extra)
{}

static void context_append(struct context *ctx,
			   struct descriptor *d, int z, int extra)
{}

static void context_stop(struct context *ctx)
{}

struct driver_data {};

/*
 * This function apppends a packet to the DMA queue for transmission.
 * Must always be called with the ochi->lock held to ensure proper
 * generation handling and locking around packet queue manipulation.
 */
static int at_context_queue_packet(struct context *ctx,
				   struct fw_packet *packet)
{}

static void at_context_flush(struct context *ctx)
{}

static int handle_at_packet(struct context *context,
			    struct descriptor *d,
			    struct descriptor *last)
{}

static u32 get_cycle_time(struct fw_ohci *ohci);

static void handle_local_rom(struct fw_ohci *ohci,
			     struct fw_packet *packet, u32 csr)
{}

static void handle_local_lock(struct fw_ohci *ohci,
			      struct fw_packet *packet, u32 csr)
{}

static void handle_local_request(struct context *ctx, struct fw_packet *packet)
{}

static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
{}

static void detect_dead_context(struct fw_ohci *ohci,
				const char *name, unsigned int regs)
{}

static void handle_dead_contexts(struct fw_ohci *ohci)
{}

static u32 cycle_timer_ticks(u32 cycle_timer)
{}

/*
 * Some controllers exhibit one or more of the following bugs when updating the
 * iso cycle timer register:
 *  - When the lowest six bits are wrapping around to zero, a read that happens
 *    at the same time will return garbage in the lowest ten bits.
 *  - When the cycleOffset field wraps around to zero, the cycleCount field is
 *    not incremented for about 60 ns.
 *  - Occasionally, the entire register reads zero.
 *
 * To catch these, we read the register three times and ensure that the
 * difference between each two consecutive reads is approximately the same, i.e.
 * less than twice the other.  Furthermore, any negative difference indicates an
 * error.  (A PCI read should take at least 20 ticks of the 24.576 MHz timer to
 * execute, so we have enough precision to compute the ratio of the differences.)
 */
static u32 get_cycle_time(struct fw_ohci *ohci)
{}

/*
 * This function has to be called at least every 64 seconds.  The bus_time
 * field stores not only the upper 25 bits of the BUS_TIME register but also
 * the most significant bit of the cycle timer in bit 6 so that we can detect
 * changes in this bit.
 */
static u32 update_bus_time(struct fw_ohci *ohci)
{}

static int get_status_for_port(struct fw_ohci *ohci, int port_index,
			       enum phy_packet_self_id_port_status *status)
{}

static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
	int self_id_count)
{}

static bool initiated_reset(struct fw_ohci *ohci)
{}

/*
 * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
 * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
 * Construct the selfID from phy register contents.
 */
static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
{}

static void bus_reset_work(struct work_struct *work)
{}

static irqreturn_t irq_handler(int irq, void *data)
{}

static int software_reset(struct fw_ohci *ohci)
{}

static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length)
{}

static int configure_1394a_enhancements(struct fw_ohci *ohci)
{}

static int probe_tsb41ba3d(struct fw_ohci *ohci)
{}

static int ohci_enable(struct fw_card *card,
		       const __be32 *config_rom, size_t length)
{}

static int ohci_set_config_rom(struct fw_card *card,
			       const __be32 *config_rom, size_t length)
{}

static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
{}

static void ohci_send_response(struct fw_card *card, struct fw_packet *packet)
{}

static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
{}

static int ohci_enable_phys_dma(struct fw_card *card,
				int node_id, int generation)
{}

static u32 ohci_read_csr(struct fw_card *card, int csr_offset)
{}

static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value)
{}

static void flush_iso_completions(struct iso_context *ctx, enum fw_iso_context_completions_cause cause)
{}

static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr)
{}

static int handle_ir_packet_per_buffer(struct context *context,
				       struct descriptor *d,
				       struct descriptor *last)
{}

/* d == last because each descriptor block is only a single descriptor. */
static int handle_ir_buffer_fill(struct context *context,
				 struct descriptor *d,
				 struct descriptor *last)
{}

static void flush_ir_buffer_fill(struct iso_context *ctx)
{}

static inline void sync_it_packet_for_cpu(struct context *context,
					  struct descriptor *pd)
{}

static int handle_it_packet(struct context *context,
			    struct descriptor *d,
			    struct descriptor *last)
{}

static void set_multichannel_mask(struct fw_ohci *ohci, u64 channels)
{}

static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
				int type, int channel, size_t header_size)
{}

static int ohci_start_iso(struct fw_iso_context *base,
			  s32 cycle, u32 sync, u32 tags)
{}

static int ohci_stop_iso(struct fw_iso_context *base)
{}

static void ohci_free_iso_context(struct fw_iso_context *base)
{}

static int ohci_set_iso_channels(struct fw_iso_context *base, u64 *channels)
{}

#ifdef CONFIG_PM
static void ohci_resume_iso_dma(struct fw_ohci *ohci)
{}
#endif

static int queue_iso_transmit(struct iso_context *ctx,
			      struct fw_iso_packet *packet,
			      struct fw_iso_buffer *buffer,
			      unsigned long payload)
{}

static int queue_iso_packet_per_buffer(struct iso_context *ctx,
				       struct fw_iso_packet *packet,
				       struct fw_iso_buffer *buffer,
				       unsigned long payload)
{}

static int queue_iso_buffer_fill(struct iso_context *ctx,
				 struct fw_iso_packet *packet,
				 struct fw_iso_buffer *buffer,
				 unsigned long payload)
{}

static int ohci_queue_iso(struct fw_iso_context *base,
			  struct fw_iso_packet *packet,
			  struct fw_iso_buffer *buffer,
			  unsigned long payload)
{}

static void ohci_flush_queue_iso(struct fw_iso_context *base)
{}

static int ohci_flush_iso_completions(struct fw_iso_context *base)
{}

static const struct fw_card_driver ohci_driver =;

#ifdef CONFIG_PPC_PMAC
static void pmac_ohci_on(struct pci_dev *dev)
{
	if (machine_is(powermac)) {
		struct device_node *ofn = pci_device_to_OF_node(dev);

		if (ofn) {
			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
		}
	}
}

static void pmac_ohci_off(struct pci_dev *dev)
{
	if (machine_is(powermac)) {
		struct device_node *ofn = pci_device_to_OF_node(dev);

		if (ofn) {
			pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
		}
	}
}
#else
static inline void pmac_ohci_on(struct pci_dev *dev) {}
static inline void pmac_ohci_off(struct pci_dev *dev) {}
#endif /* CONFIG_PPC_PMAC */

static void release_ohci(struct device *dev, void *data)
{}

static int pci_probe(struct pci_dev *dev,
			       const struct pci_device_id *ent)
{}

static void pci_remove(struct pci_dev *dev)
{}

#ifdef CONFIG_PM
static int pci_suspend(struct pci_dev *dev, pm_message_t state)
{}

static int pci_resume(struct pci_dev *dev)
{}
#endif

static const struct pci_device_id pci_table[] =;

MODULE_DEVICE_TABLE(pci, pci_table);

static struct pci_driver fw_ohci_pci_driver =;

static int __init fw_ohci_init(void)
{}

static void __exit fw_ohci_cleanup(void)
{}

module_init();
module_exit(fw_ohci_cleanup);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

/* Provide a module alias so root-on-sbp2 initrds don't break. */
MODULE_ALIAS();