1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
277c9a5daSStefan Richter #ifndef _LINUX_FIREWIRE_H
377c9a5daSStefan Richter #define _LINUX_FIREWIRE_H
477c9a5daSStefan Richter
577c9a5daSStefan Richter #include <linux/completion.h>
6f68c56b7SPaul Gortmaker #include <linux/device.h>
7c76acec6SJay Fenlason #include <linux/dma-mapping.h>
877c9a5daSStefan Richter #include <linux/kernel.h>
977c9a5daSStefan Richter #include <linux/kref.h>
1077c9a5daSStefan Richter #include <linux/list.h>
1177c9a5daSStefan Richter #include <linux/mutex.h>
1277c9a5daSStefan Richter #include <linux/spinlock.h>
1377c9a5daSStefan Richter #include <linux/sysfs.h>
1477c9a5daSStefan Richter #include <linux/timer.h>
1577c9a5daSStefan Richter #include <linux/types.h>
1677c9a5daSStefan Richter #include <linux/workqueue.h>
1777c9a5daSStefan Richter
1860063497SArun Sharma #include <linux/atomic.h>
1977c9a5daSStefan Richter #include <asm/byteorder.h>
2077c9a5daSStefan Richter
2177c9a5daSStefan Richter #define CSR_REGISTER_BASE 0xfffff0000000ULL
2277c9a5daSStefan Richter
2377c9a5daSStefan Richter /* register offsets are relative to CSR_REGISTER_BASE */
2477c9a5daSStefan Richter #define CSR_STATE_CLEAR 0x0
2577c9a5daSStefan Richter #define CSR_STATE_SET 0x4
2677c9a5daSStefan Richter #define CSR_NODE_IDS 0x8
2777c9a5daSStefan Richter #define CSR_RESET_START 0xc
2877c9a5daSStefan Richter #define CSR_SPLIT_TIMEOUT_HI 0x18
2977c9a5daSStefan Richter #define CSR_SPLIT_TIMEOUT_LO 0x1c
3077c9a5daSStefan Richter #define CSR_CYCLE_TIME 0x200
3177c9a5daSStefan Richter #define CSR_BUS_TIME 0x204
3277c9a5daSStefan Richter #define CSR_BUSY_TIMEOUT 0x210
33a1a1132bSClemens Ladisch #define CSR_PRIORITY_BUDGET 0x218
3477c9a5daSStefan Richter #define CSR_BUS_MANAGER_ID 0x21c
3577c9a5daSStefan Richter #define CSR_BANDWIDTH_AVAILABLE 0x220
3677c9a5daSStefan Richter #define CSR_CHANNELS_AVAILABLE 0x224
3777c9a5daSStefan Richter #define CSR_CHANNELS_AVAILABLE_HI 0x224
3877c9a5daSStefan Richter #define CSR_CHANNELS_AVAILABLE_LO 0x228
393d1f46ebSClemens Ladisch #define CSR_MAINT_UTILITY 0x230
4077c9a5daSStefan Richter #define CSR_BROADCAST_CHANNEL 0x234
4177c9a5daSStefan Richter #define CSR_CONFIG_ROM 0x400
4277c9a5daSStefan Richter #define CSR_CONFIG_ROM_END 0x800
4331ef9134SClemens Ladisch #define CSR_OMPR 0x900
4431ef9134SClemens Ladisch #define CSR_OPCR(i) (0x904 + (i) * 4)
4531ef9134SClemens Ladisch #define CSR_IMPR 0x980
4631ef9134SClemens Ladisch #define CSR_IPCR(i) (0x984 + (i) * 4)
4777c9a5daSStefan Richter #define CSR_FCP_COMMAND 0xB00
4877c9a5daSStefan Richter #define CSR_FCP_RESPONSE 0xD00
4977c9a5daSStefan Richter #define CSR_FCP_END 0xF00
5077c9a5daSStefan Richter #define CSR_TOPOLOGY_MAP 0x1000
5177c9a5daSStefan Richter #define CSR_TOPOLOGY_MAP_END 0x1400
5277c9a5daSStefan Richter #define CSR_SPEED_MAP 0x2000
5377c9a5daSStefan Richter #define CSR_SPEED_MAP_END 0x3000
5477c9a5daSStefan Richter
5577c9a5daSStefan Richter #define CSR_OFFSET 0x40
5677c9a5daSStefan Richter #define CSR_LEAF 0x80
5777c9a5daSStefan Richter #define CSR_DIRECTORY 0xc0
5877c9a5daSStefan Richter
5977c9a5daSStefan Richter #define CSR_DESCRIPTOR 0x01
6077c9a5daSStefan Richter #define CSR_VENDOR 0x03
6177c9a5daSStefan Richter #define CSR_HARDWARE_VERSION 0x04
6277c9a5daSStefan Richter #define CSR_UNIT 0x11
6377c9a5daSStefan Richter #define CSR_SPECIFIER_ID 0x12
6477c9a5daSStefan Richter #define CSR_VERSION 0x13
6577c9a5daSStefan Richter #define CSR_DEPENDENT_INFO 0x14
6677c9a5daSStefan Richter #define CSR_MODEL 0x17
6777c9a5daSStefan Richter #define CSR_DIRECTORY_ID 0x20
6877c9a5daSStefan Richter
6977c9a5daSStefan Richter struct fw_csr_iterator {
7013b302d0SStefan Richter const u32 *p;
7113b302d0SStefan Richter const u32 *end;
7277c9a5daSStefan Richter };
7377c9a5daSStefan Richter
7413b302d0SStefan Richter void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p);
7577c9a5daSStefan Richter int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value);
7613b302d0SStefan Richter int fw_csr_string(const u32 *directory, int key, char *buf, size_t size);
771f8fef7bSClemens Ladisch
7810416a35SGreg Kroah-Hartman extern const struct bus_type fw_bus_type;
7977c9a5daSStefan Richter
8077c9a5daSStefan Richter struct fw_card_driver;
8177c9a5daSStefan Richter struct fw_node;
8277c9a5daSStefan Richter
8377c9a5daSStefan Richter struct fw_card {
8477c9a5daSStefan Richter const struct fw_card_driver *driver;
8577c9a5daSStefan Richter struct device *device;
8677c9a5daSStefan Richter struct kref kref;
8777c9a5daSStefan Richter struct completion done;
8877c9a5daSStefan Richter
8977c9a5daSStefan Richter int node_id;
9077c9a5daSStefan Richter int generation;
911e626fdcSStefan Richter int current_tlabel;
921e626fdcSStefan Richter u64 tlabel_mask;
9377c9a5daSStefan Richter struct list_head transaction_list;
94e71084afSClemens Ladisch u64 reset_jiffies;
9577c9a5daSStefan Richter
968e4b50f9SClemens Ladisch u32 split_timeout_hi;
978e4b50f9SClemens Ladisch u32 split_timeout_lo;
988e4b50f9SClemens Ladisch unsigned int split_timeout_cycles;
998e4b50f9SClemens Ladisch unsigned int split_timeout_jiffies;
1008e4b50f9SClemens Ladisch
10177c9a5daSStefan Richter unsigned long long guid;
10277c9a5daSStefan Richter unsigned max_receive;
10377c9a5daSStefan Richter int link_speed;
10477c9a5daSStefan Richter int config_rom_generation;
10577c9a5daSStefan Richter
10677c9a5daSStefan Richter spinlock_t lock; /* Take this lock when handling the lists in
10777c9a5daSStefan Richter * this struct. */
10877c9a5daSStefan Richter struct fw_node *local_node;
10977c9a5daSStefan Richter struct fw_node *root_node;
11077c9a5daSStefan Richter struct fw_node *irm_node;
11177c9a5daSStefan Richter u8 color; /* must be u8 to match the definition in struct fw_node */
11277c9a5daSStefan Richter int gap_count;
11377c9a5daSStefan Richter bool beta_repeaters_present;
11477c9a5daSStefan Richter
11577c9a5daSStefan Richter int index;
11677c9a5daSStefan Richter struct list_head link;
11777c9a5daSStefan Richter
118bf54e146SStefan Richter struct list_head phy_receiver_list;
119bf54e146SStefan Richter
12002d37bedSStefan Richter struct delayed_work br_work; /* bus reset job */
12102d37bedSStefan Richter bool br_short;
12202d37bedSStefan Richter
12302d37bedSStefan Richter struct delayed_work bm_work; /* bus manager job */
12477c9a5daSStefan Richter int bm_retries;
12577c9a5daSStefan Richter int bm_generation;
126250b2b6dSStefan Richter int bm_node_id;
127c8a94dedSStefan Richter bool bm_abdicate;
12877c9a5daSStefan Richter
129db3c9cc1SStefan Richter bool priority_budget_implemented; /* controller feature */
130db3c9cc1SStefan Richter bool broadcast_channel_auto_allocated; /* controller feature */
131db3c9cc1SStefan Richter
13277c9a5daSStefan Richter bool broadcast_channel_allocated;
13377c9a5daSStefan Richter u32 broadcast_channel;
134cb7c96daSStefan Richter __be32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];
1353d1f46ebSClemens Ladisch
1363d1f46ebSClemens Ladisch __be32 maint_utility_register;
137c6fb88a5STakashi Sakamoto
138c6fb88a5STakashi Sakamoto struct workqueue_struct *isoc_wq;
13977c9a5daSStefan Richter };
14077c9a5daSStefan Richter
fw_card_get(struct fw_card * card)141fc5f80b1SChris Boot static inline struct fw_card *fw_card_get(struct fw_card *card)
142fc5f80b1SChris Boot {
143fc5f80b1SChris Boot kref_get(&card->kref);
144fc5f80b1SChris Boot
145fc5f80b1SChris Boot return card;
146fc5f80b1SChris Boot }
147fc5f80b1SChris Boot
148fc5f80b1SChris Boot void fw_card_release(struct kref *kref);
149fc5f80b1SChris Boot
fw_card_put(struct fw_card * card)150fc5f80b1SChris Boot static inline void fw_card_put(struct fw_card *card)
151fc5f80b1SChris Boot {
152fc5f80b1SChris Boot kref_put(&card->kref, fw_card_release);
153fc5f80b1SChris Boot }
154fc5f80b1SChris Boot
155baa914cdSTakashi Sakamoto int fw_card_read_cycle_time(struct fw_card *card, u32 *cycle_time);
156baa914cdSTakashi Sakamoto
15777c9a5daSStefan Richter struct fw_attribute_group {
15877c9a5daSStefan Richter struct attribute_group *groups[2];
15977c9a5daSStefan Richter struct attribute_group group;
160baedee17SClemens Ladisch struct attribute *attrs[13];
16177c9a5daSStefan Richter };
16277c9a5daSStefan Richter
16377c9a5daSStefan Richter enum fw_device_state {
16477c9a5daSStefan Richter FW_DEVICE_INITIALIZING,
16577c9a5daSStefan Richter FW_DEVICE_RUNNING,
16677c9a5daSStefan Richter FW_DEVICE_GONE,
16777c9a5daSStefan Richter FW_DEVICE_SHUTDOWN,
16877c9a5daSStefan Richter };
16977c9a5daSStefan Richter
17077c9a5daSStefan Richter /*
17177c9a5daSStefan Richter * Note, fw_device.generation always has to be read before fw_device.node_id.
17277c9a5daSStefan Richter * Use SMP memory barriers to ensure this. Otherwise requests will be sent
17377c9a5daSStefan Richter * to an outdated node_id if the generation was updated in the meantime due
17477c9a5daSStefan Richter * to a bus reset.
17577c9a5daSStefan Richter *
17677c9a5daSStefan Richter * Likewise, fw-core will take care to update .node_id before .generation so
17777c9a5daSStefan Richter * that whenever fw_device.generation is current WRT the actual bus generation,
17877c9a5daSStefan Richter * fw_device.node_id is guaranteed to be current too.
17977c9a5daSStefan Richter *
18077c9a5daSStefan Richter * The same applies to fw_device.card->node_id vs. fw_device.generation.
18177c9a5daSStefan Richter *
18277c9a5daSStefan Richter * fw_device.config_rom and fw_device.config_rom_length may be accessed during
18377c9a5daSStefan Richter * the lifetime of any fw_unit belonging to the fw_device, before device_del()
18477c9a5daSStefan Richter * was called on the last fw_unit. Alternatively, they may be accessed while
18577c9a5daSStefan Richter * holding fw_device_rwsem.
18677c9a5daSStefan Richter */
18777c9a5daSStefan Richter struct fw_device {
18877c9a5daSStefan Richter atomic_t state;
18977c9a5daSStefan Richter struct fw_node *node;
19077c9a5daSStefan Richter int node_id;
19177c9a5daSStefan Richter int generation;
19277c9a5daSStefan Richter unsigned max_speed;
19377c9a5daSStefan Richter struct fw_card *card;
19477c9a5daSStefan Richter struct device device;
19577c9a5daSStefan Richter
19677c9a5daSStefan Richter struct mutex client_list_mutex;
19777c9a5daSStefan Richter struct list_head client_list;
19877c9a5daSStefan Richter
19913b302d0SStefan Richter const u32 *config_rom;
20077c9a5daSStefan Richter size_t config_rom_length;
20177c9a5daSStefan Richter int config_rom_retries;
20277c9a5daSStefan Richter unsigned is_local:1;
203837ec787SStefan Richter unsigned max_rec:4;
20477c9a5daSStefan Richter unsigned cmc:1;
205837ec787SStefan Richter unsigned irmc:1;
20677c9a5daSStefan Richter unsigned bc_implemented:2;
20777c9a5daSStefan Richter
20870044d71STejun Heo work_func_t workfn;
20977c9a5daSStefan Richter struct delayed_work work;
21077c9a5daSStefan Richter struct fw_attribute_group attribute_group;
21177c9a5daSStefan Richter };
21277c9a5daSStefan Richter
21349b7fc1cSGreg Kroah-Hartman #define fw_device(dev) container_of_const(dev, struct fw_device, device)
21477c9a5daSStefan Richter
fw_device_is_shutdown(struct fw_device * device)21577c9a5daSStefan Richter static inline int fw_device_is_shutdown(struct fw_device *device)
21677c9a5daSStefan Richter {
21777c9a5daSStefan Richter return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
21877c9a5daSStefan Richter }
21977c9a5daSStefan Richter
22077c9a5daSStefan Richter int fw_device_enable_phys_dma(struct fw_device *device);
22177c9a5daSStefan Richter
22277c9a5daSStefan Richter /*
22377c9a5daSStefan Richter * fw_unit.directory must not be accessed after device_del(&fw_unit.device).
22477c9a5daSStefan Richter */
22577c9a5daSStefan Richter struct fw_unit {
22677c9a5daSStefan Richter struct device device;
22713b302d0SStefan Richter const u32 *directory;
22877c9a5daSStefan Richter struct fw_attribute_group attribute_group;
22977c9a5daSStefan Richter };
23077c9a5daSStefan Richter
23149b7fc1cSGreg Kroah-Hartman #define fw_unit(dev) container_of_const(dev, struct fw_unit, device)
23277c9a5daSStefan Richter
fw_unit_get(struct fw_unit * unit)23377c9a5daSStefan Richter static inline struct fw_unit *fw_unit_get(struct fw_unit *unit)
23477c9a5daSStefan Richter {
23577c9a5daSStefan Richter get_device(&unit->device);
23677c9a5daSStefan Richter
23777c9a5daSStefan Richter return unit;
23877c9a5daSStefan Richter }
23977c9a5daSStefan Richter
fw_unit_put(struct fw_unit * unit)24077c9a5daSStefan Richter static inline void fw_unit_put(struct fw_unit *unit)
24177c9a5daSStefan Richter {
24277c9a5daSStefan Richter put_device(&unit->device);
24377c9a5daSStefan Richter }
24477c9a5daSStefan Richter
24549b7fc1cSGreg Kroah-Hartman #define fw_parent_device(unit) fw_device(unit->device.parent)
246e5110d01SStefan Richter
24777c9a5daSStefan Richter struct ieee1394_device_id;
24877c9a5daSStefan Richter
24977c9a5daSStefan Richter struct fw_driver {
25077c9a5daSStefan Richter struct device_driver driver;
25194a87157SStefan Richter int (*probe)(struct fw_unit *unit, const struct ieee1394_device_id *id);
25277c9a5daSStefan Richter /* Called when the parent device sits through a bus reset. */
25377c9a5daSStefan Richter void (*update)(struct fw_unit *unit);
25494a87157SStefan Richter void (*remove)(struct fw_unit *unit);
25577c9a5daSStefan Richter const struct ieee1394_device_id *id_table;
25677c9a5daSStefan Richter };
25777c9a5daSStefan Richter
25877c9a5daSStefan Richter struct fw_packet;
25977c9a5daSStefan Richter struct fw_request;
26077c9a5daSStefan Richter
26177c9a5daSStefan Richter typedef void (*fw_packet_callback_t)(struct fw_packet *packet,
26277c9a5daSStefan Richter struct fw_card *card, int status);
26377c9a5daSStefan Richter typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode,
26477c9a5daSStefan Richter void *data, size_t length,
26577c9a5daSStefan Richter void *callback_data);
266dcadfd7fSTakashi Sakamoto typedef void (*fw_transaction_callback_with_tstamp_t)(struct fw_card *card, int rcode,
267dcadfd7fSTakashi Sakamoto u32 request_tstamp, u32 response_tstamp, void *data,
268dcadfd7fSTakashi Sakamoto size_t length, void *callback_data);
269dcadfd7fSTakashi Sakamoto
270dcadfd7fSTakashi Sakamoto union fw_transaction_callback {
271dcadfd7fSTakashi Sakamoto fw_transaction_callback_t without_tstamp;
272dcadfd7fSTakashi Sakamoto fw_transaction_callback_with_tstamp_t with_tstamp;
273dcadfd7fSTakashi Sakamoto };
274dcadfd7fSTakashi Sakamoto
27577c9a5daSStefan Richter /*
2764d50c443SStefan Richter * This callback handles an inbound request subaction. It is called in
2774d50c443SStefan Richter * RCU read-side context, therefore must not sleep.
2784d50c443SStefan Richter *
2794d50c443SStefan Richter * The callback should not initiate outbound request subactions directly.
2804d50c443SStefan Richter * Otherwise there is a danger of recursion of inbound and outbound
2814d50c443SStefan Richter * transactions from and to the local node.
2824d50c443SStefan Richter *
283e6996002STakashi Sakamoto * The callback is responsible that fw_send_response() is called on the @request, except for FCP
284e6996002STakashi Sakamoto * registers for which the core takes care of that.
28577c9a5daSStefan Richter */
28677c9a5daSStefan Richter typedef void (*fw_address_callback_t)(struct fw_card *card,
28777c9a5daSStefan Richter struct fw_request *request,
28877c9a5daSStefan Richter int tcode, int destination, int source,
28933e553feSStefan Richter int generation,
29077c9a5daSStefan Richter unsigned long long offset,
29177c9a5daSStefan Richter void *data, size_t length,
29277c9a5daSStefan Richter void *callback_data);
29377c9a5daSStefan Richter
29477c9a5daSStefan Richter struct fw_packet {
29577c9a5daSStefan Richter int speed;
29677c9a5daSStefan Richter int generation;
29777c9a5daSStefan Richter u32 header[4];
29877c9a5daSStefan Richter size_t header_length;
29977c9a5daSStefan Richter void *payload;
30077c9a5daSStefan Richter size_t payload_length;
30177c9a5daSStefan Richter dma_addr_t payload_bus;
30219593ffdSStefan Richter bool payload_mapped;
30377c9a5daSStefan Richter u32 timestamp;
30477c9a5daSStefan Richter
30577c9a5daSStefan Richter /*
30618d0cdfdSStefan Richter * This callback is called when the packet transmission has completed.
30718d0cdfdSStefan Richter * For successful transmission, the status code is the ack received
30818d0cdfdSStefan Richter * from the destination. Otherwise it is one of the juju-specific
30918d0cdfdSStefan Richter * rcodes: RCODE_SEND_ERROR, _CANCELLED, _BUSY, _GENERATION, _NO_ACK.
31077c9a5daSStefan Richter * The callback can be called from tasklet context and thus
31177c9a5daSStefan Richter * must never block.
31277c9a5daSStefan Richter */
31377c9a5daSStefan Richter fw_packet_callback_t callback;
31477c9a5daSStefan Richter int ack;
31577c9a5daSStefan Richter struct list_head link;
31677c9a5daSStefan Richter void *driver_data;
31777c9a5daSStefan Richter };
31877c9a5daSStefan Richter
31977c9a5daSStefan Richter struct fw_transaction {
32077c9a5daSStefan Richter int node_id; /* The generation is implied; it is always the current. */
32177c9a5daSStefan Richter int tlabel;
32277c9a5daSStefan Richter struct list_head link;
3235c40cbfeSClemens Ladisch struct fw_card *card;
324410cf2bdSClemens Ladisch bool is_split_transaction;
3255c40cbfeSClemens Ladisch struct timer_list split_timeout_timer;
326dcadfd7fSTakashi Sakamoto u32 split_timeout_cycle;
32777c9a5daSStefan Richter
32877c9a5daSStefan Richter struct fw_packet packet;
32977c9a5daSStefan Richter
33077c9a5daSStefan Richter /*
33177c9a5daSStefan Richter * The data passed to the callback is valid only during the
33277c9a5daSStefan Richter * callback.
33377c9a5daSStefan Richter */
334dcadfd7fSTakashi Sakamoto union fw_transaction_callback callback;
335dcadfd7fSTakashi Sakamoto bool with_tstamp;
33677c9a5daSStefan Richter void *callback_data;
33777c9a5daSStefan Richter };
33877c9a5daSStefan Richter
33977c9a5daSStefan Richter struct fw_address_handler {
34077c9a5daSStefan Richter u64 offset;
341188726ecSClemens Ladisch u64 length;
34277c9a5daSStefan Richter fw_address_callback_t address_callback;
34377c9a5daSStefan Richter void *callback_data;
34477c9a5daSStefan Richter struct list_head link;
34577c9a5daSStefan Richter };
34677c9a5daSStefan Richter
34777c9a5daSStefan Richter struct fw_address_region {
34877c9a5daSStefan Richter u64 start;
34977c9a5daSStefan Richter u64 end;
35077c9a5daSStefan Richter };
35177c9a5daSStefan Richter
35277c9a5daSStefan Richter extern const struct fw_address_region fw_high_memory_region;
35377c9a5daSStefan Richter
35477c9a5daSStefan Richter int fw_core_add_address_handler(struct fw_address_handler *handler,
35577c9a5daSStefan Richter const struct fw_address_region *region);
35677c9a5daSStefan Richter void fw_core_remove_address_handler(struct fw_address_handler *handler);
35777c9a5daSStefan Richter void fw_send_response(struct fw_card *card,
35877c9a5daSStefan Richter struct fw_request *request, int rcode);
359253d9237SChris Boot int fw_get_request_speed(struct fw_request *request);
360b2405aa9STakashi Sakamoto u32 fw_request_get_timestamp(const struct fw_request *request);
36139ce342cSTakashi Sakamoto
36239ce342cSTakashi Sakamoto void __fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
36339ce342cSTakashi Sakamoto int destination_id, int generation, int speed, unsigned long long offset,
36439ce342cSTakashi Sakamoto void *payload, size_t length, union fw_transaction_callback callback,
36539ce342cSTakashi Sakamoto bool with_tstamp, void *callback_data);
36639ce342cSTakashi Sakamoto
36739ce342cSTakashi Sakamoto /**
36839ce342cSTakashi Sakamoto * fw_send_request() - submit a request packet for transmission to generate callback for response
36939ce342cSTakashi Sakamoto * subaction without time stamp.
37039ce342cSTakashi Sakamoto * @card: interface to send the request at
37139ce342cSTakashi Sakamoto * @t: transaction instance to which the request belongs
37239ce342cSTakashi Sakamoto * @tcode: transaction code
37339ce342cSTakashi Sakamoto * @destination_id: destination node ID, consisting of bus_ID and phy_ID
37439ce342cSTakashi Sakamoto * @generation: bus generation in which request and response are valid
37539ce342cSTakashi Sakamoto * @speed: transmission speed
37639ce342cSTakashi Sakamoto * @offset: 48bit wide offset into destination's address space
37739ce342cSTakashi Sakamoto * @payload: data payload for the request subaction
37839ce342cSTakashi Sakamoto * @length: length of the payload, in bytes
37939ce342cSTakashi Sakamoto * @callback: function to be called when the transaction is completed
38039ce342cSTakashi Sakamoto * @callback_data: data to be passed to the transaction completion callback
38139ce342cSTakashi Sakamoto *
38239ce342cSTakashi Sakamoto * A variation of __fw_send_request() to generate callback for response subaction without time
38339ce342cSTakashi Sakamoto * stamp.
38439ce342cSTakashi Sakamoto */
fw_send_request(struct fw_card * card,struct fw_transaction * t,int tcode,int destination_id,int generation,int speed,unsigned long long offset,void * payload,size_t length,fw_transaction_callback_t callback,void * callback_data)38539ce342cSTakashi Sakamoto static inline void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
38639ce342cSTakashi Sakamoto int destination_id, int generation, int speed,
38777c9a5daSStefan Richter unsigned long long offset, void *payload, size_t length,
38839ce342cSTakashi Sakamoto fw_transaction_callback_t callback, void *callback_data)
38939ce342cSTakashi Sakamoto {
39039ce342cSTakashi Sakamoto union fw_transaction_callback cb = {
39139ce342cSTakashi Sakamoto .without_tstamp = callback,
39239ce342cSTakashi Sakamoto };
39339ce342cSTakashi Sakamoto __fw_send_request(card, t, tcode, destination_id, generation, speed, offset, payload,
39439ce342cSTakashi Sakamoto length, cb, false, callback_data);
39539ce342cSTakashi Sakamoto }
39639ce342cSTakashi Sakamoto
39739ce342cSTakashi Sakamoto /**
39839ce342cSTakashi Sakamoto * fw_send_request_with_tstamp() - submit a request packet for transmission to generate callback for
39939ce342cSTakashi Sakamoto * response with time stamp.
40039ce342cSTakashi Sakamoto * @card: interface to send the request at
40139ce342cSTakashi Sakamoto * @t: transaction instance to which the request belongs
40239ce342cSTakashi Sakamoto * @tcode: transaction code
40339ce342cSTakashi Sakamoto * @destination_id: destination node ID, consisting of bus_ID and phy_ID
40439ce342cSTakashi Sakamoto * @generation: bus generation in which request and response are valid
40539ce342cSTakashi Sakamoto * @speed: transmission speed
40639ce342cSTakashi Sakamoto * @offset: 48bit wide offset into destination's address space
40739ce342cSTakashi Sakamoto * @payload: data payload for the request subaction
40839ce342cSTakashi Sakamoto * @length: length of the payload, in bytes
40939ce342cSTakashi Sakamoto * @callback: function to be called when the transaction is completed
41039ce342cSTakashi Sakamoto * @callback_data: data to be passed to the transaction completion callback
41139ce342cSTakashi Sakamoto *
41239ce342cSTakashi Sakamoto * A variation of __fw_send_request() to generate callback for response subaction with time stamp.
41339ce342cSTakashi Sakamoto */
fw_send_request_with_tstamp(struct fw_card * card,struct fw_transaction * t,int tcode,int destination_id,int generation,int speed,unsigned long long offset,void * payload,size_t length,fw_transaction_callback_with_tstamp_t callback,void * callback_data)41439ce342cSTakashi Sakamoto static inline void fw_send_request_with_tstamp(struct fw_card *card, struct fw_transaction *t,
41539ce342cSTakashi Sakamoto int tcode, int destination_id, int generation, int speed, unsigned long long offset,
41639ce342cSTakashi Sakamoto void *payload, size_t length, fw_transaction_callback_with_tstamp_t callback,
41739ce342cSTakashi Sakamoto void *callback_data)
41839ce342cSTakashi Sakamoto {
41939ce342cSTakashi Sakamoto union fw_transaction_callback cb = {
42039ce342cSTakashi Sakamoto .with_tstamp = callback,
42139ce342cSTakashi Sakamoto };
42239ce342cSTakashi Sakamoto __fw_send_request(card, t, tcode, destination_id, generation, speed, offset, payload,
42339ce342cSTakashi Sakamoto length, cb, true, callback_data);
42439ce342cSTakashi Sakamoto }
42539ce342cSTakashi Sakamoto
42677c9a5daSStefan Richter int fw_cancel_transaction(struct fw_card *card,
42777c9a5daSStefan Richter struct fw_transaction *transaction);
42877c9a5daSStefan Richter int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
42977c9a5daSStefan Richter int generation, int speed, unsigned long long offset,
43077c9a5daSStefan Richter void *payload, size_t length);
4317bdbff67SClemens Ladisch const char *fw_rcode_string(int rcode);
43277c9a5daSStefan Richter
fw_stream_packet_destination_id(int tag,int channel,int sy)433c76acec6SJay Fenlason static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
434c76acec6SJay Fenlason {
435c76acec6SJay Fenlason return tag << 14 | channel << 8 | sy;
436c76acec6SJay Fenlason }
437c76acec6SJay Fenlason
4389b1ee0b2STakashi Sakamoto void fw_schedule_bus_reset(struct fw_card *card, bool delayed,
4399b1ee0b2STakashi Sakamoto bool short_reset);
4409b1ee0b2STakashi Sakamoto
441c76acec6SJay Fenlason struct fw_descriptor {
442c76acec6SJay Fenlason struct list_head link;
443c76acec6SJay Fenlason size_t length;
444c76acec6SJay Fenlason u32 immediate;
445c76acec6SJay Fenlason u32 key;
446c76acec6SJay Fenlason const u32 *data;
447c76acec6SJay Fenlason };
448c76acec6SJay Fenlason
449c76acec6SJay Fenlason int fw_core_add_descriptor(struct fw_descriptor *desc);
450c76acec6SJay Fenlason void fw_core_remove_descriptor(struct fw_descriptor *desc);
451c76acec6SJay Fenlason
452c76acec6SJay Fenlason /*
453c76acec6SJay Fenlason * The iso packet format allows for an immediate header/payload part
454c76acec6SJay Fenlason * stored in 'header' immediately after the packet info plus an
455c76acec6SJay Fenlason * indirect payload part that is pointer to by the 'payload' field.
456c76acec6SJay Fenlason * Applications can use one or the other or both to implement simple
457c76acec6SJay Fenlason * low-bandwidth streaming (e.g. audio) or more advanced
458c76acec6SJay Fenlason * scatter-gather streaming (e.g. assembling video frame automatically).
459c76acec6SJay Fenlason */
460c76acec6SJay Fenlason struct fw_iso_packet {
461872e330eSStefan Richter u16 payload_length; /* Length of indirect payload */
462c76acec6SJay Fenlason u32 interrupt:1; /* Generate interrupt on this packet */
463872e330eSStefan Richter u32 skip:1; /* tx: Set to not send packet at all */
464872e330eSStefan Richter /* rx: Sync bit, wait for matching sy */
465872e330eSStefan Richter u32 tag:2; /* tx: Tag in packet header */
466872e330eSStefan Richter u32 sy:4; /* tx: Sy in packet header */
46700e3913bSTakashi Sakamoto u32 header_length:8; /* Size of immediate header */
46800e3913bSTakashi Sakamoto u32 header[]; /* tx: Top of 1394 isoch. data_block */
469c76acec6SJay Fenlason };
470c76acec6SJay Fenlason
471c76acec6SJay Fenlason #define FW_ISO_CONTEXT_TRANSMIT 0
472c76acec6SJay Fenlason #define FW_ISO_CONTEXT_RECEIVE 1
473872e330eSStefan Richter #define FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2
474c76acec6SJay Fenlason
475c76acec6SJay Fenlason #define FW_ISO_CONTEXT_MATCH_TAG0 1
476c76acec6SJay Fenlason #define FW_ISO_CONTEXT_MATCH_TAG1 2
477c76acec6SJay Fenlason #define FW_ISO_CONTEXT_MATCH_TAG2 4
478c76acec6SJay Fenlason #define FW_ISO_CONTEXT_MATCH_TAG3 8
479c76acec6SJay Fenlason #define FW_ISO_CONTEXT_MATCH_ALL_TAGS 15
480c76acec6SJay Fenlason
481c76acec6SJay Fenlason /*
482c76acec6SJay Fenlason * An iso buffer is just a set of pages mapped for DMA in the
483c76acec6SJay Fenlason * specified direction. Since the pages are to be used for DMA, they
484c76acec6SJay Fenlason * are not mapped into the kernel virtual address space. We store the
485c76acec6SJay Fenlason * DMA address in the page private. The helper function
486c76acec6SJay Fenlason * fw_iso_buffer_map() will map the pages into a given vma.
487c76acec6SJay Fenlason */
488c76acec6SJay Fenlason struct fw_iso_buffer {
489c76acec6SJay Fenlason enum dma_data_direction direction;
490c76acec6SJay Fenlason struct page **pages;
491c76acec6SJay Fenlason int page_count;
4920b6c4857SStefan Richter int page_count_mapped;
493c76acec6SJay Fenlason };
494c76acec6SJay Fenlason
495c76acec6SJay Fenlason int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
496c76acec6SJay Fenlason int page_count, enum dma_data_direction direction);
497c76acec6SJay Fenlason void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
498872e330eSStefan Richter size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed);
499c76acec6SJay Fenlason
500c76acec6SJay Fenlason struct fw_iso_context;
501c76acec6SJay Fenlason typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,
502c76acec6SJay Fenlason u32 cycle, size_t header_length,
503c76acec6SJay Fenlason void *header, void *data);
504872e330eSStefan Richter typedef void (*fw_iso_mc_callback_t)(struct fw_iso_context *context,
505872e330eSStefan Richter dma_addr_t completed, void *data);
506ebe4560eSOscar Carter
507ebe4560eSOscar Carter union fw_iso_callback {
508ebe4560eSOscar Carter fw_iso_callback_t sc;
509ebe4560eSOscar Carter fw_iso_mc_callback_t mc;
510ebe4560eSOscar Carter };
511ebe4560eSOscar Carter
512c76acec6SJay Fenlason struct fw_iso_context {
513c76acec6SJay Fenlason struct fw_card *card;
5144f55ad75STakashi Sakamoto struct work_struct work;
515c76acec6SJay Fenlason int type;
516c76acec6SJay Fenlason int channel;
517c76acec6SJay Fenlason int speed;
5180699a73aSClemens Ladisch bool drop_overflow_headers;
519c76acec6SJay Fenlason size_t header_size;
520ebe4560eSOscar Carter union fw_iso_callback callback;
521c76acec6SJay Fenlason void *callback_data;
522c76acec6SJay Fenlason };
523c76acec6SJay Fenlason
524c76acec6SJay Fenlason struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
525c76acec6SJay Fenlason int type, int channel, int speed, size_t header_size,
526c76acec6SJay Fenlason fw_iso_callback_t callback, void *callback_data);
527872e330eSStefan Richter int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels);
528c76acec6SJay Fenlason int fw_iso_context_queue(struct fw_iso_context *ctx,
529c76acec6SJay Fenlason struct fw_iso_packet *packet,
530c76acec6SJay Fenlason struct fw_iso_buffer *buffer,
531c76acec6SJay Fenlason unsigned long payload);
53213882a82SClemens Ladisch void fw_iso_context_queue_flush(struct fw_iso_context *ctx);
533d1bbd209SClemens Ladisch int fw_iso_context_flush_completions(struct fw_iso_context *ctx);
534446216bdSTakashi Sakamoto
535446216bdSTakashi Sakamoto /**
536446216bdSTakashi Sakamoto * fw_iso_context_schedule_flush_completions() - schedule work item to process isochronous context.
537446216bdSTakashi Sakamoto * @ctx: the isochronous context
538446216bdSTakashi Sakamoto *
539446216bdSTakashi Sakamoto * Schedule a work item on workqueue to process the isochronous context. The registered callback
540*4010cb1eSTakashi Sakamoto * function is called by the worker when a queued packet buffer with the interrupt flag is
541*4010cb1eSTakashi Sakamoto * completed, either after transmission in the IT context or after being filled in the IR context.
542*4010cb1eSTakashi Sakamoto * The callback function is also called when the header buffer in the context becomes full, If it
543*4010cb1eSTakashi Sakamoto * is required to process the context in the current context, fw_iso_context_flush_completions() is
544*4010cb1eSTakashi Sakamoto * available instead.
545446216bdSTakashi Sakamoto *
546446216bdSTakashi Sakamoto * Context: Any context.
547446216bdSTakashi Sakamoto */
fw_iso_context_schedule_flush_completions(struct fw_iso_context * ctx)548446216bdSTakashi Sakamoto static inline void fw_iso_context_schedule_flush_completions(struct fw_iso_context *ctx)
549446216bdSTakashi Sakamoto {
550446216bdSTakashi Sakamoto queue_work(ctx->card->isoc_wq, &ctx->work);
551446216bdSTakashi Sakamoto }
552446216bdSTakashi Sakamoto
553c76acec6SJay Fenlason int fw_iso_context_start(struct fw_iso_context *ctx,
554c76acec6SJay Fenlason int cycle, int sync, int tags);
555c76acec6SJay Fenlason int fw_iso_context_stop(struct fw_iso_context *ctx);
556c76acec6SJay Fenlason void fw_iso_context_destroy(struct fw_iso_context *ctx);
55731ef9134SClemens Ladisch void fw_iso_resource_manage(struct fw_card *card, int generation,
55831ef9134SClemens Ladisch u64 channels_mask, int *channel, int *bandwidth,
559f30e6d3eSStefan Richter bool allocate);
560c76acec6SJay Fenlason
561105e53f8SStefan Richter extern struct workqueue_struct *fw_workqueue;
562105e53f8SStefan Richter
56377c9a5daSStefan Richter #endif /* _LINUX_FIREWIRE_H */
564