From 3038e353cfaf548eb94f02b172b9dbe412abd24c Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Tue, 19 Dec 2006 19:58:27 -0500 Subject: firewire: Add core firewire stack. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-transaction.h | 422 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 drivers/firewire/fw-transaction.h (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h new file mode 100644 index 00000000000..149ef1652ac --- /dev/null +++ b/drivers/firewire/fw-transaction.h @@ -0,0 +1,422 @@ +/* -*- c-basic-offset: 8 -*- + * + * fw-transaction.h - Header for IEEE1394 transaction logic + * + * Copyright (C) 2003-2006 Kristian Hoegsberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __fw_core_h +#define __fw_core_h + +#include +#include +#include +#include +#include + +#define TCODE_WRITE_QUADLET_REQUEST 0 +#define TCODE_WRITE_BLOCK_REQUEST 1 +#define TCODE_WRITE_RESPONSE 2 +#define TCODE_READ_QUADLET_REQUEST 4 +#define TCODE_READ_BLOCK_REQUEST 5 +#define TCODE_READ_QUADLET_RESPONSE 6 +#define TCODE_READ_BLOCK_RESPONSE 7 +#define TCODE_CYCLE_START 8 +#define TCODE_LOCK_REQUEST 9 +#define TCODE_STREAM_DATA 10 +#define TCODE_LOCK_RESPONSE 11 + +#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) +#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0) +#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0) +#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4) +#define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0) + +/* Juju specific tcodes */ +#define TCODE_DEALLOCATE 0x10 +#define TCODE_LOCK_MASK_SWAP 0x11 +#define TCODE_LOCK_COMPARE_SWAP 0x12 +#define TCODE_LOCK_FETCH_ADD 0x13 +#define TCODE_LOCK_LITTLE_ADD 0x14 +#define TCODE_LOCK_BOUNDED_ADD 0x15 +#define TCODE_LOCK_WRAP_ADD 0x16 +#define TCODE_LOCK_VENDOR_SPECIFIC 0x17 + +#define SCODE_100 0x0 +#define SCODE_200 0x1 +#define SCODE_400 0x2 +#define SCODE_BETA 0x3 + +#define EXTCODE_MASK_SWAP 0x1 +#define EXTCODE_COMPARE_SWAP 0x2 +#define EXTCODE_FETCH_ADD 0x3 +#define EXTCODE_LITTLE_ADD 0x4 +#define EXTCODE_BOUNDED_ADD 0x5 +#define EXTCODE_WRAP_ADD 0x6 + +#define ACK_COMPLETE 0x1 +#define ACK_PENDING 0x2 +#define ACK_BUSY_X 0x4 +#define ACK_BUSY_A 0x5 +#define ACK_BUSY_B 0x6 +#define ACK_DATA_ERROR 0xd +#define ACK_TYPE_ERROR 0xe + +#define RCODE_COMPLETE 0x0 +#define RCODE_CONFLICT_ERROR 0x4 +#define RCODE_DATA_ERROR 0x5 +#define RCODE_TYPE_ERROR 0x6 +#define RCODE_ADDRESS_ERROR 0x7 + +/* Juju specific rcodes */ +#define RCODE_SEND_ERROR 0x10 +#define RCODE_CANCELLED 0x11 +#define RCODE_BUSY 0x12 + +#define RETRY_1 0x00 +#define RETRY_X 0x01 +#define RETRY_A 0x02 +#define RETRY_B 0x03 + +#define LOCAL_BUS 0xffc0 + +#define SELFID_PORT_CHILD 0x3 +#define SELFID_PORT_PARENT 0x2 +#define SELFID_PORT_NCONN 0x1 +#define SELFID_PORT_NONE 0x0 + +#define PHY_PACKET_CONFIG 0x0 +#define PHY_PACKET_LINK_ON 0x1 +#define PHY_PACKET_SELF_ID 0x2 + +#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) +#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) +#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args) + +static inline void +fw_memcpy_from_be32(void *_dst, void *_src, size_t size) +{ + u32 *dst = _dst; + u32 *src = _src; + int i; + + for (i = 0; i < size / 4; i++) + dst[i] = cpu_to_be32(src[i]); +} + +static inline void +fw_memcpy_to_be32(void *_dst, void *_src, size_t size) +{ + fw_memcpy_from_be32(_dst, _src, size); +} + +struct fw_card; +struct fw_packet; +struct fw_node; +struct fw_request; + +struct fw_descriptor { + struct list_head link; + size_t length; + u32 key; + u32 *data; +}; + +int fw_core_add_descriptor (struct fw_descriptor *desc); +void fw_core_remove_descriptor (struct fw_descriptor *desc); + +typedef void (*fw_packet_callback_t) (struct fw_packet *packet, + struct fw_card *card, int status); + +typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, + void *data, + size_t length, + void *callback_data); + +typedef void (*fw_address_callback_t)(struct fw_card *card, + struct fw_request *request, + int tcode, int destination, int source, + int generation, int speed, + unsigned long long offset, + void *data, size_t length, + void *callback_data); + +typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle, + int node_id, int generation, + u32 *self_ids, + int self_id_count, + void *callback_data); + +struct fw_packet { + int speed; + int generation; + u32 header[4]; + size_t header_length; + void *payload; + size_t payload_length; + u32 timestamp; + + dma_addr_t payload_bus; + + /* This callback is called when the packet transmission has + * completed; for successful transmission, the status code is + * the ack received from the destination, otherwise it's a + * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO. + * The callback can be called from tasklet context and thus + * must never block. + */ + fw_packet_callback_t callback; + int status; + struct list_head link; +}; + +struct fw_transaction { + int node_id; /* The generation is implied; it is always the current. */ + int tlabel; + int timestamp; + struct list_head link; + + struct fw_packet packet; + + /* The data passed to the callback is valid only during the + * callback. */ + fw_transaction_callback_t callback; + void *callback_data; +}; + +extern inline struct fw_packet * +fw_packet(struct list_head *l) +{ + return list_entry (l, struct fw_packet, link); +} + +struct fw_address_handler { + u64 offset; + size_t length; + fw_address_callback_t address_callback; + void *callback_data; + struct list_head link; +}; + + +struct fw_address_region { + u64 start; + u64 end; +}; + +extern struct fw_address_region fw_low_memory_region; +extern struct fw_address_region fw_high_memory_region; +extern struct fw_address_region fw_private_region; +extern struct fw_address_region fw_csr_region; +extern struct fw_address_region fw_unit_space_region; + +int fw_core_add_address_handler(struct fw_address_handler *handler, + struct fw_address_region *region); +void fw_core_remove_address_handler(struct fw_address_handler *handler); +void fw_send_response(struct fw_card *card, + struct fw_request *request, int rcode); + +extern struct bus_type fw_bus_type; + +struct fw_card { + struct fw_card_driver *driver; + struct device *device; + + int node_id; + int generation; + /* This is the generation used for timestamping incoming requests. */ + int request_generation; + int current_tlabel, tlabel_mask; + struct list_head transaction_list; + struct timer_list flush_timer; + + unsigned long long guid; + int max_receive; + int link_speed; + int config_rom_generation; + + /* We need to store up to 4 self ID for a maximum of 63 devices. */ + int self_id_count; + u32 self_ids[252]; + + spinlock_t lock; /* Take this lock when handling the lists in + * this struct. */ + struct fw_node *local_node; + struct fw_node *root_node; + struct fw_node *irm_node; + int color; + + int index; + + struct device card_device; + + struct list_head link; +}; + +struct fw_card *fw_card_get(struct fw_card *card); +void fw_card_put(struct fw_card *card); + +/* The iso packet format allows for an immediate header/payload part + * stored in 'header' immediately after the packet info plus an + * indirect payload part that is pointer to by the 'payload' field. + * Applications can use one or the other or both to implement simple + * low-bandwidth streaming (e.g. audio) or more advanced + * scatter-gather streaming (e.g. assembling video frame automatically). */ + +struct fw_iso_packet { + u16 payload_length; /* Length of indirect payload. */ + u32 interrupt : 1; /* Generate interrupt on this packet */ + u32 skip : 1; /* Set to not send packet at all. */ + u32 tag : 2; + u32 sy : 4; + u32 header_length : 8; /* Length of immediate header. */ + u32 header[0]; +}; + +#define FW_ISO_CONTEXT_TRANSMIT 0 +#define FW_ISO_CONTEXT_RECEIVE 1 + +struct fw_iso_context; + +typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, + int status, u32 cycle, void *data); + +struct fw_iso_context { + struct fw_card *card; + int type; + int channel; + int speed; + fw_iso_callback_t callback; + void *callback_data; + + void *buffer; + size_t buffer_size; + dma_addr_t *pages; + int page_count; +}; + +struct fw_iso_context * +fw_iso_context_create(struct fw_card *card, int type, + size_t buffer_size, + fw_iso_callback_t callback, + void *callback_data); + +void +fw_iso_context_destroy(struct fw_iso_context *ctx); + +void +fw_iso_context_start(struct fw_iso_context *ctx, + int channel, int speed, int cycle); + +int +fw_iso_context_queue(struct fw_iso_context *ctx, + struct fw_iso_packet *packet, void *payload); + +int +fw_iso_context_send(struct fw_iso_context *ctx, + int channel, int speed, int cycle); + +struct fw_card_driver { + const char *name; + + /* Enable the given card with the given initial config rom. + * This function is expected to activate the card, and either + * enable the PHY or set the link_on bit and initiate a bus + * reset. */ + int (*enable) (struct fw_card *card, u32 *config_rom, size_t length); + + int (*update_phy_reg) (struct fw_card *card, int address, + int clear_bits, int set_bits); + + /* Update the config rom for an enabled card. This function + * should change the config rom that is presented on the bus + * an initiate a bus reset. */ + int (*set_config_rom) (struct fw_card *card, + u32 *config_rom, size_t length); + + void (*send_request) (struct fw_card *card, struct fw_packet *packet); + void (*send_response) (struct fw_card *card, struct fw_packet *packet); + + /* Allow the specified node ID to do direct DMA out and in of + * host memory. The card will disable this for all node when + * a bus reset happens, so driver need to reenable this after + * bus reset. Returns 0 on success, -ENODEV if the card + * doesn't support this, -ESTALE if the generation doesn't + * match. */ + int (*enable_phys_dma) (struct fw_card *card, + int node_id, int generation); + + struct fw_iso_context * + (*allocate_iso_context)(struct fw_card *card, int type); + void (*free_iso_context)(struct fw_iso_context *ctx); + + int (*send_iso)(struct fw_iso_context *ctx, s32 cycle); + + int (*queue_iso)(struct fw_iso_context *ctx, + struct fw_iso_packet *packet, void *payload); +}; + +int +fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); + +void +fw_send_request(struct fw_card *card, struct fw_transaction *t, + int tcode, int node_id, int generation, int speed, + unsigned long long offset, + void *data, size_t length, + fw_transaction_callback_t callback, void *callback_data); + +void fw_flush_transactions(struct fw_card *card); + +void +fw_send_force_root(struct fw_card *card, int node_id, int generation); + +/* Called by the topology code to inform the device code of node + * activity; found, lost, or updated nodes */ +void +fw_node_event(struct fw_card *card, struct fw_node *node, int event); + +/* API used by card level drivers */ + +/* Do we need phy speed here also? If we add more args, maybe we + should go back to struct fw_card_info. */ +void +fw_card_initialize(struct fw_card *card, struct fw_card_driver *driver, + struct device *device); +int +fw_card_add(struct fw_card *card, + u32 max_receive, u32 link_speed, u64 guid); + +void +fw_core_remove_card(struct fw_card *card); + +void +fw_core_handle_bus_reset(struct fw_card *card, + int node_id, int generation, + int self_id_count, u32 *self_ids); +void +fw_core_handle_request(struct fw_card *card, + int speed, int ack, int timestamp, + int generation, + u32 length, u32 *payload); +void +fw_core_handle_response(struct fw_card *card, + int speed, int ack, int timestamp, + u32 length, u32 *payload); + + +#endif /* __fw_core_h */ -- cgit v1.2.3-70-g09d2 From 19a15b937b26638933307bb02f7b1801310d6eb2 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Tue, 19 Dec 2006 19:58:31 -0500 Subject: firewire: Add device probing and sysfs integration. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/Makefile | 3 +- drivers/firewire/fw-card.c | 56 ++++ drivers/firewire/fw-device-cdev.c | 617 ++++++++++++++++++++++++++++++++++++++ drivers/firewire/fw-device-cdev.h | 146 +++++++++ drivers/firewire/fw-device.c | 613 +++++++++++++++++++++++++++++++++++++ drivers/firewire/fw-device.h | 127 ++++++++ drivers/firewire/fw-iso.c | 1 + drivers/firewire/fw-topology.c | 10 +- drivers/firewire/fw-transaction.c | 5 +- drivers/firewire/fw-transaction.h | 4 + 10 files changed, 1573 insertions(+), 9 deletions(-) create mode 100644 drivers/firewire/fw-device-cdev.c create mode 100644 drivers/firewire/fw-device-cdev.h create mode 100644 drivers/firewire/fw-device.c create mode 100644 drivers/firewire/fw-device.h (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile index db7020dd02a..da77bc0501e 100644 --- a/drivers/firewire/Makefile +++ b/drivers/firewire/Makefile @@ -2,6 +2,7 @@ # Makefile for the Linux IEEE 1394 implementation # -fw-core-objs := fw-card.o fw-topology.o fw-transaction.o fw-iso.o +fw-core-objs := fw-card.o fw-topology.o fw-transaction.o fw-iso.o \ + fw-device.o fw-device-cdev.o obj-$(CONFIG_FW) += fw-core.o diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index d8abd70ce84..79773907e10 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -24,6 +24,7 @@ #include #include "fw-transaction.h" #include "fw-topology.h" +#include "fw-device.h" /* The lib/crc16.c implementation uses the standard (0x8005) * polynomial, but we need the ITU-T (or CCITT) polynomial (0x1021). @@ -185,6 +186,59 @@ fw_core_remove_descriptor (struct fw_descriptor *desc) } EXPORT_SYMBOL(fw_core_remove_descriptor); +static void +fw_card_irm_work(struct work_struct *work) +{ + struct fw_card *card = + container_of(work, struct fw_card, work.work); + struct fw_device *root; + unsigned long flags; + int new_irm_id, generation; + + /* FIXME: This simple bus management unconditionally picks a + * cycle master if the current root can't do it. We need to + * not do this if there is a bus manager already. Also, some + * hubs set the contender bit, which is bogus, so we should + * probably do a little sanity check on the IRM (like, read + * the bandwidth register) if it's not us. */ + + spin_lock_irqsave(&card->lock, flags); + + generation = card->generation; + root = card->root_node->data; + + if (root == NULL) + /* Either link_on is false, or we failed to read the + * config rom. In either case, pick another root. */ + new_irm_id = card->local_node->node_id; + else if (root->state != FW_DEVICE_RUNNING) + /* If we haven't probed this device yet, bail out now + * and let's try again once that's done. */ + new_irm_id = -1; + else if (root->config_rom[2] & bib_cmc) + /* FIXME: I suppose we should set the cmstr bit in the + * STATE_CLEAR register of this node, as described in + * 1394-1995, 8.4.2.6. Also, send out a force root + * packet for this node. */ + new_irm_id = -1; + else + /* Current root has an active link layer and we + * successfully read the config rom, but it's not + * cycle master capable. */ + new_irm_id = card->local_node->node_id; + + if (card->irm_retries++ > 5) + new_irm_id = -1; + + spin_unlock_irqrestore(&card->lock, flags); + + if (new_irm_id > 0) { + fw_notify("Trying to become root (card %d)\n", card->index); + fw_send_force_root(card, new_irm_id, generation); + fw_core_initiate_bus_reset(card, 1); + } +} + static void release_card(struct device *device) { @@ -222,6 +276,8 @@ fw_card_initialize(struct fw_card *card, struct fw_card_driver *driver, card->local_node = NULL; + INIT_DELAYED_WORK(&card->work, fw_card_irm_work); + card->card_device.bus = &fw_bus_type; card->card_device.release = release_card; card->card_device.parent = card->device; diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c new file mode 100644 index 00000000000..c10e3326abf --- /dev/null +++ b/drivers/firewire/fw-device-cdev.c @@ -0,0 +1,617 @@ +/* -*- c-basic-offset: 8 -*- + * + * fw-device-cdev.c - Char device for device raw access + * + * Copyright (C) 2005-2006 Kristian Hoegsberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fw-transaction.h" +#include "fw-topology.h" +#include "fw-device.h" +#include "fw-device-cdev.h" + +/* + * todo + * + * - bus resets sends a new packet with new generation and node id + * + */ + +/* dequeue_event() just kfree()'s the event, so the event has to be + * the first field in the struct. */ + +struct event { + struct { void *data; size_t size; } v[2]; + struct list_head link; +}; + +struct response { + struct event event; + struct fw_transaction transaction; + struct client *client; + struct fw_cdev_event_response response; +}; + +struct iso_interrupt { + struct event event; + struct fw_cdev_event_iso_interrupt interrupt; +}; + +struct client { + struct fw_device *device; + spinlock_t lock; + struct list_head handler_list; + struct list_head request_list; + u32 request_serial; + struct list_head event_list; + struct semaphore event_list_sem; + wait_queue_head_t wait; + unsigned long vm_start; + struct fw_iso_context *iso_context; +}; + +static inline void __user * +u64_to_uptr(__u64 value) +{ + return (void __user *)(unsigned long)value; +} + +static inline __u64 +uptr_to_u64(void __user *ptr) +{ + return (__u64)(unsigned long)ptr; +} + +static int fw_device_op_open(struct inode *inode, struct file *file) +{ + struct fw_device *device; + struct client *client; + + device = container_of(inode->i_cdev, struct fw_device, cdev); + + client = kzalloc(sizeof *client, GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + + client->device = fw_device_get(device); + INIT_LIST_HEAD(&client->event_list); + sema_init(&client->event_list_sem, 0); + INIT_LIST_HEAD(&client->handler_list); + INIT_LIST_HEAD(&client->request_list); + spin_lock_init(&client->lock); + init_waitqueue_head(&client->wait); + + file->private_data = client; + + return 0; +} + +static void queue_event(struct client *client, struct event *event, + void *data0, size_t size0, void *data1, size_t size1) +{ + unsigned long flags; + + event->v[0].data = data0; + event->v[0].size = size0; + event->v[1].data = data1; + event->v[1].size = size1; + + spin_lock_irqsave(&client->lock, flags); + + list_add_tail(&event->link, &client->event_list); + + up(&client->event_list_sem); + wake_up_interruptible(&client->wait); + + spin_unlock_irqrestore(&client->lock, flags); +} + +static int dequeue_event(struct client *client, char __user *buffer, size_t count) +{ + unsigned long flags; + struct event *event; + size_t size, total; + int i, retval = -EFAULT; + + if (down_interruptible(&client->event_list_sem) < 0) + return -EINTR; + + spin_lock_irqsave(&client->lock, flags); + + event = container_of(client->event_list.next, struct event, link); + list_del(&event->link); + + spin_unlock_irqrestore(&client->lock, flags); + + if (buffer == NULL) + goto out; + + total = 0; + for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { + size = min(event->v[i].size, count - total); + if (copy_to_user(buffer + total, event->v[i].data, size)) + goto out; + total += size; + } + retval = total; + + out: + kfree(event); + + return retval; +} + +static ssize_t +fw_device_op_read(struct file *file, + char __user *buffer, size_t count, loff_t *offset) +{ + struct client *client = file->private_data; + + return dequeue_event(client, buffer, count); +} + +static int ioctl_config_rom(struct client *client, void __user *arg) +{ + struct fw_cdev_get_config_rom rom; + + rom.length = client->device->config_rom_length; + memcpy(rom.data, client->device->config_rom, rom.length * 4); + if (copy_to_user(arg, &rom, + (char *)&rom.data[rom.length] - (char *)&rom)) + return -EFAULT; + + return 0; +} + +static void +complete_transaction(struct fw_card *card, int rcode, + void *payload, size_t length, void *data) +{ + struct response *response = data; + struct client *client = response->client; + + if (length < response->response.length) + response->response.length = length; + if (rcode == RCODE_COMPLETE) + memcpy(response->response.data, payload, + response->response.length); + + response->response.type = FW_CDEV_EVENT_RESPONSE; + response->response.rcode = rcode; + queue_event(client, &response->event, + &response->response, sizeof response->response, + response->response.data, response->response.length); +} + +static ssize_t ioctl_send_request(struct client *client, void __user *arg) +{ + struct fw_device *device = client->device; + struct fw_cdev_send_request request; + struct response *response; + + if (copy_from_user(&request, arg, sizeof request)) + return -EFAULT; + + /* What is the biggest size we'll accept, really? */ + if (request.length > 4096) + return -EINVAL; + + response = kmalloc(sizeof *response + request.length, GFP_KERNEL); + if (response == NULL) + return -ENOMEM; + + response->client = client; + response->response.length = request.length; + response->response.closure = request.closure; + + if (request.data && + copy_from_user(response->response.data, + u64_to_uptr(request.data), request.length)) { + kfree(response); + return -EFAULT; + } + + fw_send_request(device->card, &response->transaction, + request.tcode, + device->node->node_id | LOCAL_BUS, + device->card->generation, + device->node->max_speed, + request.offset, + response->response.data, request.length, + complete_transaction, response); + + if (request.data) + return sizeof request + request.length; + else + return sizeof request; +} + +struct address_handler { + struct fw_address_handler handler; + __u64 closure; + struct client *client; + struct list_head link; +}; + +struct request { + struct fw_request *request; + void *data; + size_t length; + u32 serial; + struct list_head link; +}; + +struct request_event { + struct event event; + struct fw_cdev_event_request request; +}; + +static void +handle_request(struct fw_card *card, struct fw_request *r, + int tcode, int destination, int source, + int generation, int speed, + unsigned long long offset, + void *payload, size_t length, void *callback_data) +{ + struct address_handler *handler = callback_data; + struct request *request; + struct request_event *e; + unsigned long flags; + struct client *client = handler->client; + + request = kmalloc(sizeof *request, GFP_ATOMIC); + e = kmalloc(sizeof *e, GFP_ATOMIC); + if (request == NULL || e == NULL) { + kfree(request); + kfree(e); + fw_send_response(card, r, RCODE_CONFLICT_ERROR); + return; + } + + request->request = r; + request->data = payload; + request->length = length; + + spin_lock_irqsave(&client->lock, flags); + request->serial = client->request_serial++; + list_add_tail(&request->link, &client->request_list); + spin_unlock_irqrestore(&client->lock, flags); + + e->request.type = FW_CDEV_EVENT_REQUEST; + e->request.tcode = tcode; + e->request.offset = offset; + e->request.length = length; + e->request.serial = request->serial; + e->request.closure = handler->closure; + + queue_event(client, &e->event, + &e->request, sizeof e->request, payload, length); +} + +static int ioctl_allocate(struct client *client, void __user *arg) +{ + struct fw_cdev_allocate request; + struct address_handler *handler; + unsigned long flags; + struct fw_address_region region; + + if (copy_from_user(&request, arg, sizeof request)) + return -EFAULT; + + handler = kmalloc(sizeof *handler, GFP_KERNEL); + if (handler == NULL) + return -ENOMEM; + + region.start = request.offset; + region.end = request.offset + request.length; + handler->handler.length = request.length; + handler->handler.address_callback = handle_request; + handler->handler.callback_data = handler; + handler->closure = request.closure; + handler->client = client; + + if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { + kfree(handler); + return -EBUSY; + } + + spin_lock_irqsave(&client->lock, flags); + list_add_tail(&handler->link, &client->handler_list); + spin_unlock_irqrestore(&client->lock, flags); + + return 0; +} + +static int ioctl_send_response(struct client *client, void __user *arg) +{ + struct fw_cdev_send_response request; + struct request *r; + unsigned long flags; + + if (copy_from_user(&request, arg, sizeof request)) + return -EFAULT; + + spin_lock_irqsave(&client->lock, flags); + list_for_each_entry(r, &client->request_list, link) { + if (r->serial == request.serial) { + list_del(&r->link); + break; + } + } + spin_unlock_irqrestore(&client->lock, flags); + + if (&r->link == &client->request_list) + return -EINVAL; + + if (request.length < r->length) + r->length = request.length; + if (copy_from_user(r->data, u64_to_uptr(request.data), r->length)) + return -EFAULT; + + fw_send_response(client->device->card, r->request, request.rcode); + + kfree(r); + + return 0; +} + +static void +iso_callback(struct fw_iso_context *context, int status, u32 cycle, void *data) +{ + struct client *client = data; + struct iso_interrupt *interrupt; + + interrupt = kzalloc(sizeof *interrupt, GFP_ATOMIC); + if (interrupt == NULL) + return; + + interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; + interrupt->interrupt.closure = 0; + interrupt->interrupt.cycle = cycle; + queue_event(client, &interrupt->event, + &interrupt->interrupt, sizeof interrupt->interrupt, NULL, 0); +} + +static int ioctl_create_iso_context(struct client *client, void __user *arg) +{ + struct fw_cdev_create_iso_context request; + + if (copy_from_user(&request, arg, sizeof request)) + return -EFAULT; + + client->iso_context = fw_iso_context_create(client->device->card, + FW_ISO_CONTEXT_TRANSMIT, + request.buffer_size, + iso_callback, client); + if (IS_ERR(client->iso_context)) + return PTR_ERR(client->iso_context); + + return 0; +} + +static int ioctl_queue_iso(struct client *client, void __user *arg) +{ + struct fw_cdev_queue_iso request; + struct fw_cdev_iso_packet __user *p, *end, *next; + void *payload, *payload_end; + unsigned long index; + int count; + struct { + struct fw_iso_packet packet; + u8 header[256]; + } u; + + if (client->iso_context == NULL) + return -EINVAL; + if (copy_from_user(&request, arg, sizeof request)) + return -EFAULT; + + /* If the user passes a non-NULL data pointer, has mmap()'ed + * the iso buffer, and the pointer points inside the buffer, + * we setup the payload pointers accordingly. Otherwise we + * set them both to NULL, which will still let packets with + * payload_length == 0 through. In other words, if no packets + * use the indirect payload, the iso buffer need not be mapped + * and the request.data pointer is ignored.*/ + + index = (unsigned long)request.data - client->vm_start; + if (request.data != 0 && client->vm_start != 0 && + index <= client->iso_context->buffer_size) { + payload = client->iso_context->buffer + index; + payload_end = client->iso_context->buffer + + client->iso_context->buffer_size; + } else { + payload = NULL; + payload_end = NULL; + } + + if (!access_ok(VERIFY_READ, request.packets, request.size)) + return -EFAULT; + + p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request.packets); + end = (void __user *)p + request.size; + count = 0; + while (p < end) { + if (__copy_from_user(&u.packet, p, sizeof *p)) + return -EFAULT; + next = (struct fw_cdev_iso_packet __user *) + &p->header[u.packet.header_length / 4]; + if (next > end) + return -EINVAL; + if (__copy_from_user + (u.packet.header, p->header, u.packet.header_length)) + return -EFAULT; + if (u.packet.skip && + u.packet.header_length + u.packet.payload_length > 0) + return -EINVAL; + if (payload + u.packet.payload_length > payload_end) + return -EINVAL; + + if (fw_iso_context_queue(client->iso_context, + &u.packet, payload)) + break; + + p = next; + payload += u.packet.payload_length; + count++; + } + + request.size -= uptr_to_u64(p) - request.packets; + request.packets = uptr_to_u64(p); + request.data = + client->vm_start + (payload - client->iso_context->buffer); + + if (copy_to_user(arg, &request, sizeof request)) + return -EFAULT; + + return count; +} + +static int ioctl_send_iso(struct client *client, void __user *arg) +{ + struct fw_cdev_send_iso request; + + if (copy_from_user(&request, arg, sizeof request)) + return -EFAULT; + + return fw_iso_context_send(client->iso_context, request.channel, + request.speed, request.cycle); +} + +static int +dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) +{ + switch (cmd) { + case FW_CDEV_IOC_GET_CONFIG_ROM: + return ioctl_config_rom(client, arg); + case FW_CDEV_IOC_SEND_REQUEST: + return ioctl_send_request(client, arg); + case FW_CDEV_IOC_ALLOCATE: + return ioctl_allocate(client, arg); + case FW_CDEV_IOC_SEND_RESPONSE: + return ioctl_send_response(client, arg); + case FW_CDEV_IOC_CREATE_ISO_CONTEXT: + return ioctl_create_iso_context(client, arg); + case FW_CDEV_IOC_QUEUE_ISO: + return ioctl_queue_iso(client, arg); + case FW_CDEV_IOC_SEND_ISO: + return ioctl_send_iso(client, arg); + default: + return -EINVAL; + } +} + +static long +fw_device_op_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct client *client = file->private_data; + + return dispatch_ioctl(client, cmd, (void __user *) arg); +} + +#ifdef CONFIG_COMPAT +static long +fw_device_op_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct client *client = file->private_data; + + return dispatch_ioctl(client, cmd, compat_ptr(arg)); +} +#endif + +static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct client *client = file->private_data; + + if (client->iso_context->buffer == NULL) + return -EINVAL; + + client->vm_start = vma->vm_start; + + return remap_vmalloc_range(vma, client->iso_context->buffer, 0); +} + +static int fw_device_op_release(struct inode *inode, struct file *file) +{ + struct client *client = file->private_data; + struct address_handler *h, *next; + struct request *r, *next_r; + + if (client->iso_context) + fw_iso_context_destroy(client->iso_context); + + list_for_each_entry_safe(h, next, &client->handler_list, link) { + fw_core_remove_address_handler(&h->handler); + kfree(h); + } + + list_for_each_entry_safe(r, next_r, &client->request_list, link) { + fw_send_response(client->device->card, r->request, + RCODE_CONFLICT_ERROR); + kfree(r); + } + + /* TODO: wait for all transactions to finish so + * complete_transaction doesn't try to queue up responses + * after we free client. */ + while (!list_empty(&client->event_list)) + dequeue_event(client, NULL, 0); + + fw_device_put(client->device); + kfree(client); + + return 0; +} + +static unsigned int fw_device_op_poll(struct file *file, poll_table * pt) +{ + struct client *client = file->private_data; + + poll_wait(file, &client->wait, pt); + + if (!list_empty(&client->event_list)) + return POLLIN | POLLRDNORM; + else + return 0; +} + +struct file_operations fw_device_ops = { + .owner = THIS_MODULE, + .open = fw_device_op_open, + .read = fw_device_op_read, + .unlocked_ioctl = fw_device_op_ioctl, + .poll = fw_device_op_poll, + .release = fw_device_op_release, + .mmap = fw_device_op_mmap, + +#ifdef CONFIG_COMPAT + .compat_ioctl = fw_device_op_compat_ioctl +#endif +}; diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h new file mode 100644 index 00000000000..18b20c28a40 --- /dev/null +++ b/drivers/firewire/fw-device-cdev.h @@ -0,0 +1,146 @@ +/* -*- c-basic-offset: 8 -*- + * + * fw-device-cdev.h -- Char device interface. + * + * Copyright (C) 2005-2006 Kristian Hoegsberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __fw_cdev_h +#define __fw_cdev_h + +#include +#include + +#define TCODE_WRITE_QUADLET_REQUEST 0 +#define TCODE_WRITE_BLOCK_REQUEST 1 +#define TCODE_WRITE_RESPONSE 2 +#define TCODE_READ_QUADLET_REQUEST 4 +#define TCODE_READ_BLOCK_REQUEST 5 +#define TCODE_READ_QUADLET_RESPONSE 6 +#define TCODE_READ_BLOCK_RESPONSE 7 +#define TCODE_CYCLE_START 8 +#define TCODE_LOCK_REQUEST 9 +#define TCODE_STREAM_DATA 10 +#define TCODE_LOCK_RESPONSE 11 + +#define RCODE_COMPLETE 0x0 +#define RCODE_CONFLICT_ERROR 0x4 +#define RCODE_DATA_ERROR 0x5 +#define RCODE_TYPE_ERROR 0x6 +#define RCODE_ADDRESS_ERROR 0x7 + +#define SCODE_100 0x0 +#define SCODE_200 0x1 +#define SCODE_400 0x2 +#define SCODE_800 0x3 +#define SCODE_1600 0x4 +#define SCODE_3200 0x5 + +#define FW_CDEV_EVENT_RESPONSE 0x00 +#define FW_CDEV_EVENT_REQUEST 0x01 +#define FW_CDEV_EVENT_ISO_INTERRUPT 0x02 + +/* The 'closure' fields are for user space to use. Data passed in the + * 'closure' field for a request will be returned in the corresponding + * event. It's a 64-bit type so that it's a fixed size type big + * enough to hold a pointer on all platforms. */ + +struct fw_cdev_event_response { + __u32 type; + __u32 rcode; + __u64 closure; + __u32 length; + __u32 data[0]; +}; + +struct fw_cdev_event_request { + __u32 type; + __u32 tcode; + __u64 offset; + __u64 closure; + __u32 serial; + __u32 length; + __u32 data[0]; +}; + +struct fw_cdev_event_iso_interrupt { + __u32 type; + __u32 cycle; + __u64 closure; +}; + +#define FW_CDEV_IOC_GET_CONFIG_ROM _IOR('#', 0x00, struct fw_cdev_get_config_rom) +#define FW_CDEV_IOC_SEND_REQUEST _IO('#', 0x01) +#define FW_CDEV_IOC_ALLOCATE _IO('#', 0x02) +#define FW_CDEV_IOC_SEND_RESPONSE _IO('#', 0x03) +#define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04) +#define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05) +#define FW_CDEV_IOC_SEND_ISO _IO('#', 0x06) + +struct fw_cdev_get_config_rom { + __u32 length; + __u32 data[256]; +}; + +struct fw_cdev_send_request { + __u32 tcode; + __u32 length; + __u64 offset; + __u64 closure; + __u64 data; +}; + +struct fw_cdev_send_response { + __u32 rcode; + __u32 length; + __u64 data; + __u32 serial; +}; + +struct fw_cdev_allocate { + __u64 offset; + __u64 closure; + __u32 length; +}; + +struct fw_cdev_create_iso_context { + __u32 buffer_size; +}; + +struct fw_cdev_iso_packet { + __u16 payload_length; /* Length of indirect payload. */ + __u32 interrupt : 1; /* Generate interrupt on this packet */ + __u32 skip : 1; /* Set to not send packet at all. */ + __u32 tag : 2; + __u32 sy : 4; + __u32 header_length : 8; /* Length of immediate header. */ + __u32 header[0]; +}; + +struct fw_cdev_queue_iso { + __u32 size; + __u64 packets; + __u64 data; +}; + +struct fw_cdev_send_iso { + __u32 channel; + __u32 speed; + __s32 cycle; +}; + +#endif diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c new file mode 100644 index 00000000000..ec1cb7fc8e9 --- /dev/null +++ b/drivers/firewire/fw-device.c @@ -0,0 +1,613 @@ +/* -*- c-basic-offset: 8 -*- + * + * fw-device.c - Device probing and sysfs code. + * + * Copyright (C) 2005-2006 Kristian Hoegsberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include "fw-transaction.h" +#include "fw-topology.h" +#include "fw-device.h" + +void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) +{ + ci->p = p + 1; + ci->end = ci->p + (p[0] >> 16); +} + +EXPORT_SYMBOL(fw_csr_iterator_init); + +int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value) +{ + *key = *ci->p >> 24; + *value = *ci->p & 0xffffff; + + return ci->p++ < ci->end; +} + +EXPORT_SYMBOL(fw_csr_iterator_next); + +static int is_fw_unit(struct device *dev); + +static int match_unit_directory(u32 * directory, struct fw_device_id *id) +{ + struct fw_csr_iterator ci; + int key, value, match; + + match = 0; + fw_csr_iterator_init(&ci, directory); + while (fw_csr_iterator_next(&ci, &key, &value)) { + if (key == CSR_VENDOR && value == id->vendor) + match |= FW_MATCH_VENDOR; + if (key == CSR_MODEL && value == id->model) + match |= FW_MATCH_MODEL; + if (key == CSR_SPECIFIER_ID && value == id->specifier_id) + match |= FW_MATCH_SPECIFIER_ID; + if (key == CSR_VERSION && value == id->version) + match |= FW_MATCH_VERSION; + } + + return (match & id->match_flags) == id->match_flags; +} + +static int fw_unit_match(struct device *dev, struct device_driver *drv) +{ + struct fw_unit *unit = fw_unit(dev); + struct fw_driver *driver = fw_driver(drv); + int i; + + /* We only allow binding to fw_units. */ + if (!is_fw_unit(dev)) + return 0; + + for (i = 0; driver->id_table[i].match_flags != 0; i++) { + if (match_unit_directory(unit->directory, &driver->id_table[i])) + return 1; + } + + return 0; +} + +static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) +{ + struct fw_device *device = fw_device(unit->device.parent); + struct fw_csr_iterator ci; + + int key, value; + int vendor = 0; + int model = 0; + int specifier_id = 0; + int version = 0; + + fw_csr_iterator_init(&ci, &device->config_rom[5]); + while (fw_csr_iterator_next(&ci, &key, &value)) { + switch (key) { + case CSR_VENDOR: + vendor = value; + break; + case CSR_MODEL: + model = value; + break; + } + } + + fw_csr_iterator_init(&ci, unit->directory); + while (fw_csr_iterator_next(&ci, &key, &value)) { + switch (key) { + case CSR_SPECIFIER_ID: + specifier_id = value; + break; + case CSR_VERSION: + version = value; + break; + } + } + + return snprintf(buffer, buffer_size, + "ieee1394:ven%08Xmo%08Xsp%08Xver%08X", + vendor, model, specifier_id, version); +} + +static int +fw_unit_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct fw_unit *unit = fw_unit(dev); + char modalias[64]; + int length = 0; + int i = 0; + + if (!is_fw_unit(dev)) + goto out; + + get_modalias(unit, modalias, sizeof modalias); + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MODALIAS=%s", modalias)) + return -ENOMEM; + + out: + envp[i] = NULL; + + return 0; +} + +struct bus_type fw_bus_type = { + .name = "fw", + .match = fw_unit_match, + .uevent = fw_unit_uevent +}; + +EXPORT_SYMBOL(fw_bus_type); + +extern struct fw_device *fw_device_get(struct fw_device *device) +{ + get_device(&device->device); + + return device; +} + +extern void fw_device_put(struct fw_device *device) +{ + put_device(&device->device); +} + +static void fw_device_release(struct device *dev) +{ + struct fw_device *device = fw_device(dev); + unsigned long flags; + + /* Take the card lock so we don't set this to NULL while a + * FW_NODE_UPDATED callback is being handled. */ + spin_lock_irqsave(&device->card->lock, flags); + device->node->data = NULL; + spin_unlock_irqrestore(&device->card->lock, flags); + + fw_node_put(device->node); + fw_card_put(device->card); + kfree(device->config_rom); + kfree(device); +} + +int fw_device_enable_phys_dma(struct fw_device *device) +{ + return device->card->driver->enable_phys_dma(device->card, + device->node_id, + device->generation); +} + +EXPORT_SYMBOL(fw_device_enable_phys_dma); + +static ssize_t +show_modalias_attribute(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fw_unit *unit = fw_unit(dev); + int length; + + length = get_modalias(unit, buf, PAGE_SIZE); + strcpy(buf + length, "\n"); + + return length + 1; +} + +static struct device_attribute modalias_attribute = { + .attr = {.name = "modalias",.mode = S_IRUGO}, + .show = show_modalias_attribute +}; + +static ssize_t +show_config_rom_attribute(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fw_device *device = fw_device(dev); + + memcpy(buf, device->config_rom, device->config_rom_length * 4); + + return device->config_rom_length * 4; +} + +static struct device_attribute config_rom_attribute = { + .attr = {.name = "config_rom",.mode = S_IRUGO}, + .show = show_config_rom_attribute, +}; + +struct read_quadlet_callback_data { + struct completion done; + int rcode; + u32 data; +}; + +static void +complete_transaction(struct fw_card *card, int rcode, + void *payload, size_t length, void *data) +{ + struct read_quadlet_callback_data *callback_data = data; + + if (rcode == RCODE_COMPLETE) + callback_data->data = be32_to_cpu(*(__be32 *)payload); + callback_data->rcode = rcode; + complete(&callback_data->done); +} + +static int read_rom(struct fw_device *device, int index, u32 * data) +{ + struct read_quadlet_callback_data callback_data; + struct fw_transaction t; + u64 offset; + + init_completion(&callback_data.done); + + offset = 0xfffff0000400ULL + index * 4; + fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST, + device->node_id | LOCAL_BUS, + device->generation, SCODE_100, + offset, NULL, 4, complete_transaction, &callback_data); + + wait_for_completion(&callback_data.done); + + *data = callback_data.data; + + return callback_data.rcode; +} + +static int read_bus_info_block(struct fw_device *device) +{ + static u32 rom[256]; + u32 stack[16], sp, key; + int i, end, length; + + /* First read the bus info block. */ + for (i = 0; i < 5; i++) { + if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) + return -1; + /* As per IEEE1212 7.2, during power-up, devices can + * reply with a 0 for the first quadlet of the config + * rom to indicate that they are booting (for example, + * if the firmware is on the disk of a external + * harddisk). In that case we just fail, and the + * retry mechanism will try again later. */ + if (i == 0 && rom[i] == 0) + return -1; + } + + /* Now parse the config rom. The config rom is a recursive + * directory structure so we parse it using a stack of + * references to the blocks that make up the structure. We + * push a reference to the root directory on the stack to + * start things off. */ + length = i; + sp = 0; + stack[sp++] = 0xc0000005; + while (sp > 0) { + /* Pop the next block reference of the stack. The + * lower 24 bits is the offset into the config rom, + * the upper 8 bits are the type of the reference the + * block. */ + key = stack[--sp]; + i = key & 0xffffff; + if (i >= ARRAY_SIZE(rom)) + /* The reference points outside the standard + * config rom area, something's fishy. */ + return -1; + + /* Read header quadlet for the block to get the length. */ + if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) + return -1; + end = i + (rom[i] >> 16) + 1; + i++; + if (end > ARRAY_SIZE(rom)) + /* This block extends outside standard config + * area (and the array we're reading it + * into). That's broken, so ignore this + * device. */ + return -1; + + /* Now read in the block. If this is a directory + * block, check the entries as we read them to see if + * it references another block, and push it in that case. */ + while (i < end) { + if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) + return -1; + if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && + sp < ARRAY_SIZE(stack)) + stack[sp++] = i + rom[i]; + i++; + } + if (length < i) + length = i; + } + + device->config_rom = kmalloc(length * 4, GFP_KERNEL); + if (device->config_rom == NULL) + return -1; + memcpy(device->config_rom, rom, length * 4); + device->config_rom_length = length; + + return 0; +} + +static void fw_unit_release(struct device *dev) +{ + struct fw_unit *unit = fw_unit(dev); + + kfree(unit); +} + +static int is_fw_unit(struct device *dev) +{ + return dev->release == fw_unit_release; +} + +static void create_units(struct fw_device *device) +{ + struct fw_csr_iterator ci; + struct fw_unit *unit; + int key, value, i; + + i = 0; + fw_csr_iterator_init(&ci, &device->config_rom[5]); + while (fw_csr_iterator_next(&ci, &key, &value)) { + if (key != (CSR_UNIT | CSR_DIRECTORY)) + continue; + + /* Get the address of the unit directory and try to + * match the drivers id_tables against it. */ + unit = kzalloc(sizeof *unit, GFP_KERNEL); + if (unit == NULL) { + fw_error("failed to allocate memory for unit\n"); + continue; + } + + unit->directory = ci.p + value - 1; + unit->device.bus = &fw_bus_type; + unit->device.release = fw_unit_release; + unit->device.parent = &device->device; + snprintf(unit->device.bus_id, sizeof unit->device.bus_id, + "%s.%d", device->device.bus_id, i++); + + if (device_register(&unit->device) < 0) { + kfree(unit); + continue; + } + + if (device_create_file(&unit->device, &modalias_attribute) < 0) { + device_unregister(&unit->device); + kfree(unit); + } + } +} + +static int shutdown_unit(struct device *device, void *data) +{ + struct fw_unit *unit = fw_unit(device); + + if (is_fw_unit(device)) { + device_remove_file(&unit->device, &modalias_attribute); + device_unregister(&unit->device); + } + + return 0; +} + +static void fw_device_shutdown(struct work_struct *work) +{ + struct fw_device *device = + container_of(work, struct fw_device, work.work); + + device_remove_file(&device->device, &config_rom_attribute); + cdev_del(&device->cdev); + unregister_chrdev_region(device->device.devt, 1); + device_for_each_child(&device->device, NULL, shutdown_unit); + device_unregister(&device->device); +} + +/* These defines control the retry behavior for reading the config + * rom. It shouldn't be necessary to tweak these; if the device + * doesn't respond to a config rom read within 10 seconds, it's not + * going to respond at all. As for the initial delay, a lot of + * devices will be able to respond within half a second after bus + * reset. On the other hand, it's not really worth being more + * aggressive than that, since it scales pretty well; if 10 devices + * are plugged in, they're all getting read within one second. */ + +#define MAX_RETRIES 5 +#define RETRY_DELAY (2 * HZ) +#define INITIAL_DELAY (HZ / 2) + +static void fw_device_init(struct work_struct *work) +{ + static int serial; + struct fw_device *device = + container_of(work, struct fw_device, work.work); + + /* All failure paths here set node->data to NULL, so that we + * don't try to do device_for_each_child() on a kfree()'d + * device. */ + + if (read_bus_info_block(device) < 0) { + if (device->config_rom_retries < MAX_RETRIES) { + device->config_rom_retries++; + schedule_delayed_work(&device->work, RETRY_DELAY); + } else { + fw_notify("giving up on config rom for node id %d\n", + device->node_id); + fw_device_release(&device->device); + } + return; + } + + device->device.bus = &fw_bus_type; + device->device.release = fw_device_release; + device->device.parent = device->card->device; + snprintf(device->device.bus_id, sizeof device->device.bus_id, + "fw%d", serial++); + + if (alloc_chrdev_region(&device->device.devt, 0, 1, "fw")) { + fw_error("Failed to register char device region.\n"); + goto error; + } + + cdev_init(&device->cdev, &fw_device_ops); + device->cdev.owner = THIS_MODULE; + kobject_set_name(&device->cdev.kobj, device->device.bus_id); + if (cdev_add(&device->cdev, device->device.devt, 1)) { + fw_error("Failed to register char device.\n"); + goto error; + } + + if (device_add(&device->device)) { + fw_error("Failed to add device.\n"); + goto error; + } + + if (device_create_file(&device->device, &config_rom_attribute) < 0) { + fw_error("Failed to create config rom file.\n"); + goto error_with_device; + } + + create_units(device); + + /* Transition the device to running state. If it got pulled + * out from under us while we did the intialization work, we + * have to shut down the device again here. Normally, though, + * fw_node_event will be responsible for shutting it down when + * necessary. We have to use the atomic cmpxchg here to avoid + * racing with the FW_NODE_DESTROYED case in + * fw_node_event(). */ + if (cmpxchg(&device->state, + FW_DEVICE_INITIALIZING, + FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) + fw_device_shutdown(&device->work.work); + else + fw_notify("created new fw device %s (%d config rom retries)\n", + device->device.bus_id, device->config_rom_retries); + + /* Reschedule the IRM work if we just finished reading the + * root node config rom. If this races with a bus reset we + * just end up running the IRM work a couple of extra times - + * pretty harmless. */ + if (device->node == device->card->root_node) + schedule_delayed_work(&device->card->work, 0); + + return; + + error_with_device: + device_del(&device->device); + error: + cdev_del(&device->cdev); + unregister_chrdev_region(device->device.devt, 1); + put_device(&device->device); +} + +static int update_unit(struct device *dev, void *data) +{ + struct fw_unit *unit = fw_unit(dev); + struct fw_driver *driver = (struct fw_driver *)dev->driver; + + if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) + driver->update(unit); + + return 0; +} + +void fw_node_event(struct fw_card *card, struct fw_node *node, int event) +{ + struct fw_device *device; + + /* Ignore events for the local node (i.e. the node that + * corresponds to the ieee1394 controller in this linux box). */ + if (node == card->local_node) + return; + + switch (event) { + case FW_NODE_CREATED: + case FW_NODE_LINK_ON: + if (!node->link_on) + break; + + device = kzalloc(sizeof(*device), GFP_ATOMIC); + if (device == NULL) + break; + + /* Do minimal intialization of the device here, the + * rest will happen in fw_device_init(). We need the + * card and node so we can read the config rom and we + * need to do device_initialize() now so + * device_for_each_child() in FW_NODE_UPDATED is + * doesn't freak out. */ + device_initialize(&device->device); + device->state = FW_DEVICE_INITIALIZING; + device->card = fw_card_get(card); + device->node = fw_node_get(node); + device->node_id = node->node_id; + device->generation = card->generation; + + /* Set the node data to point back to this device so + * FW_NODE_UPDATED callbacks can update the node_id + * and generation for the device. */ + node->data = device; + + /* Many devices are slow to respond after bus resets, + * especially if they are bus powered and go through + * power-up after getting plugged in. We schedule the + * first config rom scan half a second after bus reset. */ + INIT_DELAYED_WORK(&device->work, fw_device_init); + schedule_delayed_work(&device->work, INITIAL_DELAY); + break; + + case FW_NODE_UPDATED: + if (!node->link_on || node->data == NULL) + break; + + device = node->data; + device->node_id = node->node_id; + device->generation = card->generation; + device_for_each_child(&device->device, NULL, update_unit); + break; + + case FW_NODE_DESTROYED: + case FW_NODE_LINK_OFF: + if (!node->data) + break; + + /* Destroy the device associated with the node. There + * are two cases here: either the device is fully + * initialized (FW_DEVICE_RUNNING) or we're in the + * process of reading its config rom + * (FW_DEVICE_INITIALIZING). If it is fully + * initialized we can reuse device->work to schedule a + * full fw_device_shutdown(). If not, there's work + * scheduled to read it's config rom, and we just put + * the device in shutdown state to have that code fail + * to create the device. */ + device = node->data; + if (xchg(&device->state, + FW_DEVICE_SHUTDOWN) == FW_DEVICE_RUNNING) { + INIT_DELAYED_WORK(&device->work, fw_device_shutdown); + schedule_delayed_work(&device->work, 0); + } + break; + } +} diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h new file mode 100644 index 00000000000..84cd5e7e2fc --- /dev/null +++ b/drivers/firewire/fw-device.h @@ -0,0 +1,127 @@ +/* -*- c-basic-offset: 8 -*- + * + * fw-device.h - Device probing and sysfs code. + * + * Copyright (C) 2005-2006 Kristian Hoegsberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __fw_device_h +#define __fw_device_h + +#include +#include + +enum fw_device_state { + FW_DEVICE_INITIALIZING, + FW_DEVICE_RUNNING, + FW_DEVICE_SHUTDOWN +}; + +struct fw_device { + int state; + struct fw_node *node; + int node_id; + int generation; + struct fw_card *card; + struct device device; + struct cdev cdev; + __be32 *config_rom; + size_t config_rom_length; + int config_rom_retries; + struct delayed_work work; +}; + +static inline struct fw_device * +fw_device(struct device *dev) +{ + return container_of(dev, struct fw_device, device); +} + +struct fw_device *fw_device_get(struct fw_device *device); +void fw_device_put(struct fw_device *device); +int fw_device_enable_phys_dma(struct fw_device *device); + +struct fw_unit { + struct device device; + u32 *directory; +}; + +static inline struct fw_unit * +fw_unit(struct device *dev) +{ + return container_of(dev, struct fw_unit, device); +} + +#define CSR_OFFSET 0x40 +#define CSR_LEAF 0x80 +#define CSR_DIRECTORY 0xc0 + +#define CSR_DESCRIPTOR 0x01 +#define CSR_VENDOR 0x03 +#define CSR_HARDWARE_VERSION 0x04 +#define CSR_NODE_CAPABILITIES 0x0c +#define CSR_UNIT 0x11 +#define CSR_SPECIFIER_ID 0x12 +#define CSR_VERSION 0x13 +#define CSR_DEPENDENT_INFO 0x14 +#define CSR_MODEL 0x17 +#define CSR_INSTANCE 0x18 + +#define SBP2_COMMAND_SET_SPECIFIER 0x38 +#define SBP2_COMMAND_SET 0x39 +#define SBP2_COMMAND_SET_REVISION 0x3b +#define SBP2_FIRMWARE_REVISION 0x3c + +struct fw_csr_iterator { + u32 *p; + u32 *end; +}; + +void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p); +int fw_csr_iterator_next(struct fw_csr_iterator *ci, + int *key, int *value); + +#define FW_MATCH_VENDOR 0x0001 +#define FW_MATCH_MODEL 0x0002 +#define FW_MATCH_SPECIFIER_ID 0x0004 +#define FW_MATCH_VERSION 0x0008 + +struct fw_device_id { + u32 match_flags; + u32 vendor; + u32 model; + u32 specifier_id; + u32 version; + void *driver_data; +}; + +struct fw_driver { + struct device_driver driver; + /* Called when the parent device sits through a bus reset. */ + void (*update) (struct fw_unit *unit); + struct fw_device_id *id_table; +}; + +static inline struct fw_driver * +fw_driver(struct device_driver *drv) +{ + return container_of(drv, struct fw_driver, driver); +} + +extern struct file_operations fw_device_ops; + +#endif diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 61548c4d18e..6b638568c2c 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -26,6 +26,7 @@ #include "fw-transaction.h" #include "fw-topology.h" +#include "fw-device.h" static int setup_iso_buffer(struct fw_iso_context *ctx, size_t size, diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 2778aa3da8e..e475025aae9 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -434,13 +434,15 @@ fw_core_handle_bus_reset(struct fw_card *card, for_each_fw_node(card, local_node, report_found_node); } else { update_tree(card, local_node, &changed); + if (changed) + card->irm_retries = 0; } + /* If we're not the root node, we may have to do some IRM work. */ + if (card->local_node != card->root_node) + schedule_delayed_work(&card->work, 0); + spin_unlock_irqrestore(&card->lock, flags); } EXPORT_SYMBOL(fw_core_handle_bus_reset); - -void fw_node_event(struct fw_card *card, struct fw_node *node, int event) -{ -} diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index c3acf743127..affd42014a6 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -33,6 +33,7 @@ #include "fw-transaction.h" #include "fw-topology.h" +#include "fw-device.h" #define header_pri(pri) ((pri) << 0) #define header_tcode(tcode) ((tcode) << 4) @@ -702,10 +703,6 @@ static struct fw_descriptor vendor_textual_descriptor = { .data = vendor_textual_descriptor_data }; -struct bus_type fw_bus_type = { - .name = "fw", -}; - static int __init fw_core_init(void) { int retval; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 149ef1652ac..7f618f2373a 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -265,6 +265,10 @@ struct fw_card { struct device card_device; struct list_head link; + + /* Work struct for IRM duties. */ + struct delayed_work work; + int irm_retries; }; struct fw_card *fw_card_get(struct fw_card *card); -- cgit v1.2.3-70-g09d2 From 687198bbd2679cb72cf381da070082d3d9f57edf Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 28 Dec 2006 16:20:00 +0100 Subject: firewire: consistent ifndef blocks in header files Replace __fw_core_h by __fw_transaction_h to match the file name. Add comments to the final #endif in header files. Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.h | 2 +- drivers/firewire/fw-device.h | 2 +- drivers/firewire/fw-topology.h | 2 +- drivers/firewire/fw-transaction.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 18b20c28a40..e2ae93361a5 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -143,4 +143,4 @@ struct fw_cdev_send_iso { __s32 cycle; }; -#endif +#endif /* __fw_cdev_h */ diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 84cd5e7e2fc..731abbe5330 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -124,4 +124,4 @@ fw_driver(struct device_driver *drv) extern struct file_operations fw_device_ops; -#endif +#endif /* __fw_device_h */ diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index 7582d6e16cb..32ea7cdb9e1 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -81,4 +81,4 @@ fw_node_put(struct fw_node *node) void fw_destroy_nodes(struct fw_card *card); -#endif +#endif /* __fw_topology_h */ diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 7f618f2373a..292add50910 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -19,8 +19,8 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __fw_core_h -#define __fw_core_h +#ifndef __fw_transaction_h +#define __fw_transaction_h #include #include @@ -423,4 +423,4 @@ fw_core_handle_response(struct fw_card *card, u32 length, u32 *payload); -#endif /* __fw_core_h */ +#endif /* __fw_transaction_h */ -- cgit v1.2.3-70-g09d2 From 21ebcd1224d05c8673053e1e93ab9ec7ef3e0b84 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 14 Jan 2007 15:29:07 +0100 Subject: firewire: mark some structs const Instances of struct file_operations and struct fw_card_driver can be qualified as "const". Ditto with struct fw_descriptor.data, struct fw_device_id, and predefined instances of struct fw_address_region, at least in the current implementation. Data qualified as const is placed into the .rodata section which won't be mixed with dirty data. Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 2 +- drivers/firewire/fw-device-cdev.c | 2 +- drivers/firewire/fw-device.c | 2 +- drivers/firewire/fw-device.h | 4 ++-- drivers/firewire/fw-ohci.c | 2 +- drivers/firewire/fw-sbp2.c | 2 +- drivers/firewire/fw-transaction.c | 14 +++++++------- drivers/firewire/fw-transaction.h | 18 +++++++++--------- 8 files changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 79773907e10..82a92432bcb 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -257,7 +257,7 @@ flush_timer_callback(unsigned long data) } void -fw_card_initialize(struct fw_card *card, struct fw_card_driver *driver, +fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, struct device *device) { static int index; diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index c10e3326abf..117bc6db54a 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -602,7 +602,7 @@ static unsigned int fw_device_op_poll(struct file *file, poll_table * pt) return 0; } -struct file_operations fw_device_ops = { +const struct file_operations fw_device_ops = { .owner = THIS_MODULE, .open = fw_device_op_open, .read = fw_device_op_read, diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index ec1cb7fc8e9..e541daade0c 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -49,7 +49,7 @@ EXPORT_SYMBOL(fw_csr_iterator_next); static int is_fw_unit(struct device *dev); -static int match_unit_directory(u32 * directory, struct fw_device_id *id) +static int match_unit_directory(u32 * directory, const struct fw_device_id *id) { struct fw_csr_iterator ci; int key, value, match; diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 731abbe5330..f39cf6ae625 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -113,7 +113,7 @@ struct fw_driver { struct device_driver driver; /* Called when the parent device sits through a bus reset. */ void (*update) (struct fw_unit *unit); - struct fw_device_id *id_table; + const struct fw_device_id *id_table; }; static inline struct fw_driver * @@ -122,6 +122,6 @@ fw_driver(struct device_driver *drv) return container_of(drv, struct fw_driver, driver); } -extern struct file_operations fw_device_ops; +extern const struct file_operations fw_device_ops; #endif /* __fw_device_h */ diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 5d42d18bd45..d3750a2692e 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1146,7 +1146,7 @@ ohci_queue_iso(struct fw_iso_context *base, return 0; } -static struct fw_card_driver ohci_driver = { +static const struct fw_card_driver ohci_driver = { .name = ohci_driver_name, .enable = ohci_enable, .update_phy_reg = ohci_update_phy_reg, diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index ce9c41ff076..28acae8b01b 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -681,7 +681,7 @@ static void sbp2_update(struct fw_unit *unit) #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e #define SBP2_SW_VERSION_ENTRY 0x00010483 -static struct fw_device_id sbp2_id_table[] = { +static const struct fw_device_id sbp2_id_table[] = { { .match_flags = FW_MATCH_SPECIFIER_ID | FW_MATCH_VERSION, .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY, diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index affd42014a6..a72f50288c0 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -331,15 +331,15 @@ lookup_enclosing_address_handler(struct list_head *list, static DEFINE_SPINLOCK(address_handler_lock); static LIST_HEAD(address_handler_list); -struct fw_address_region fw_low_memory_region = +const struct fw_address_region fw_low_memory_region = { 0x000000000000ull, 0x000100000000ull }; -struct fw_address_region fw_high_memory_region = +const struct fw_address_region fw_high_memory_region = { 0x000100000000ull, 0xffffe0000000ull }; -struct fw_address_region fw_private_region = +const struct fw_address_region fw_private_region = { 0xffffe0000000ull, 0xfffff0000000ull }; -struct fw_address_region fw_csr_region = +const struct fw_address_region fw_csr_region = { 0xfffff0000000ULL, 0xfffff0000800ull }; -struct fw_address_region fw_unit_space_region = +const struct fw_address_region fw_unit_space_region = { 0xfffff0000900ull, 0x1000000000000ull }; EXPORT_SYMBOL(fw_low_memory_region); @@ -358,7 +358,7 @@ EXPORT_SYMBOL(fw_unit_space_region); int fw_core_add_address_handler(struct fw_address_handler *handler, - struct fw_address_region *region) + const struct fw_address_region *region) { struct fw_address_handler *other; unsigned long flags; @@ -684,7 +684,7 @@ MODULE_AUTHOR("Kristian Hoegsberg "); MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); MODULE_LICENSE("GPL"); -static u32 vendor_textual_descriptor_data[] = { +static const u32 vendor_textual_descriptor_data[] = { /* textual descriptor leaf () */ 0x00080000, 0x00000000, diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 292add50910..2f849c813a4 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -133,7 +133,7 @@ struct fw_descriptor { struct list_head link; size_t length; u32 key; - u32 *data; + const u32 *data; }; int fw_core_add_descriptor (struct fw_descriptor *desc); @@ -218,14 +218,14 @@ struct fw_address_region { u64 end; }; -extern struct fw_address_region fw_low_memory_region; -extern struct fw_address_region fw_high_memory_region; -extern struct fw_address_region fw_private_region; -extern struct fw_address_region fw_csr_region; -extern struct fw_address_region fw_unit_space_region; +extern const struct fw_address_region fw_low_memory_region; +extern const struct fw_address_region fw_high_memory_region; +extern const struct fw_address_region fw_private_region; +extern const struct fw_address_region fw_csr_region; +extern const struct fw_address_region fw_unit_space_region; int fw_core_add_address_handler(struct fw_address_handler *handler, - struct fw_address_region *region); + const struct fw_address_region *region); void fw_core_remove_address_handler(struct fw_address_handler *handler); void fw_send_response(struct fw_card *card, struct fw_request *request, int rcode); @@ -233,7 +233,7 @@ void fw_send_response(struct fw_card *card, extern struct bus_type fw_bus_type; struct fw_card { - struct fw_card_driver *driver; + const struct fw_card_driver *driver; struct device *device; int node_id; @@ -399,7 +399,7 @@ fw_node_event(struct fw_card *card, struct fw_node *node, int event); /* Do we need phy speed here also? If we add more args, maybe we should go back to struct fw_card_info. */ void -fw_card_initialize(struct fw_card *card, struct fw_card_driver *driver, +fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, struct device *device); int fw_card_add(struct fw_card *card, -- cgit v1.2.3-70-g09d2 From 95688e97cdf7453cde22eaa73cc2ab6b113c1853 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 22 Jan 2007 19:17:37 +0100 Subject: firewire: cleanups This patch contains the following cleanups: - "extern inline" -> "static inline" - fw-topology.c: make struct fw_node_create static Signed-off-by: Adrian Bunk Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 8 ++++---- drivers/firewire/fw-topology.c | 2 +- drivers/firewire/fw-topology.h | 6 +++--- drivers/firewire/fw-transaction.c | 2 +- drivers/firewire/fw-transaction.h | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index d3750a2692e..6eff7996c1a 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -147,7 +147,7 @@ struct fw_ohci { struct iso_context *ir_context_list; }; -extern inline struct fw_ohci *fw_ohci(struct fw_card *card) +static inline struct fw_ohci *fw_ohci(struct fw_card *card) { return container_of(card, struct fw_ohci, card); } @@ -174,17 +174,17 @@ extern inline struct fw_ohci *fw_ohci(struct fw_card *card) static char ohci_driver_name[] = KBUILD_MODNAME; -extern inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data) +static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data) { writel(data, ohci->registers + offset); } -extern inline u32 reg_read(const struct fw_ohci *ohci, int offset) +static inline u32 reg_read(const struct fw_ohci *ohci, int offset) { return readl(ohci->registers + offset); } -extern inline void flush_writes(const struct fw_ohci *ohci) +static inline void flush_writes(const struct fw_ohci *ohci) { /* Do a dummy read to flush writes. */ reg_read(ohci, OHCI1394_Version); diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index e475025aae9..e111687f559 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -92,7 +92,7 @@ static int get_port_type(u32 *sid, int port_index) return (sid[index] >> shift) & 0x03; } -struct fw_node *fw_node_create(u32 sid, int port_count, int color) +static struct fw_node *fw_node_create(u32 sid, int port_count, int color) { struct fw_node *node; diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index 32ea7cdb9e1..a78c9516ed0 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -57,13 +57,13 @@ struct fw_node { struct fw_port ports[0]; }; -extern inline struct fw_node * +static inline struct fw_node * fw_node(struct list_head *l) { return list_entry (l, struct fw_node, link); } -extern inline struct fw_node * +static inline struct fw_node * fw_node_get(struct fw_node *node) { atomic_inc(&node->ref_count); @@ -71,7 +71,7 @@ fw_node_get(struct fw_node *node) return node; } -extern inline void +static inline void fw_node_put(struct fw_node *node) { if (atomic_dec_and_test(&node->ref_count)) diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index a72f50288c0..c2473a82431 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -106,7 +106,7 @@ transmit_complete_callback(struct fw_packet *packet, } } -void +static void fw_fill_packet(struct fw_packet *packet, int tcode, int tlabel, int node_id, int generation, int speed, unsigned long long offset, void *payload, size_t length) diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 2f849c813a4..a664fc3380c 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -198,7 +198,7 @@ struct fw_transaction { void *callback_data; }; -extern inline struct fw_packet * +static inline struct fw_packet * fw_packet(struct list_head *l) { return list_entry (l, struct fw_packet, link); -- cgit v1.2.3-70-g09d2 From 5e20c282184fd5794661b6688883231ff5348abc Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 21 Jan 2007 20:44:09 +0100 Subject: firewire: whitespace adjustments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Richter Signed-off-by: Kristian Høgsberg --- drivers/firewire/fw-card.c | 41 ++++----- drivers/firewire/fw-device-cdev.h | 18 ++-- drivers/firewire/fw-device.c | 4 - drivers/firewire/fw-device.h | 6 +- drivers/firewire/fw-iso.c | 4 - drivers/firewire/fw-ohci.c | 5 +- drivers/firewire/fw-ohci.h | 44 +++++----- drivers/firewire/fw-topology.c | 1 - drivers/firewire/fw-topology.h | 8 +- drivers/firewire/fw-transaction.c | 8 -- drivers/firewire/fw-transaction.h | 174 +++++++++++++++++++------------------- 11 files changed, 144 insertions(+), 169 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 82a92432bcb..c560fd5e74f 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -76,12 +76,12 @@ generate_config_rom (struct fw_card *card, size_t *config_rom_length) static u32 config_rom[256]; int i, j, length; - /* Initialize contents of config rom buffer. On the OHCI - * 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 - * sure the contents of bus info block in host memory mathces - * the version stored in the OHCI registers. */ + /* Initialize contents of config rom buffer. On the OHCI + * 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 + * sure the contents of bus info block in host memory mathces + * the version stored in the OHCI registers. */ memset(config_rom, 0, sizeof config_rom); config_rom[0] = bib_crc_length(4) | bib_info_length(4) | bib_crc(0); @@ -263,13 +263,13 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, static int index; card->index = index++; - card->driver = driver; + card->driver = driver; card->device = device; - card->current_tlabel = 0; - card->tlabel_mask = 0; + card->current_tlabel = 0; + card->tlabel_mask = 0; card->color = 0; - INIT_LIST_HEAD(&card->transaction_list); + INIT_LIST_HEAD(&card->transaction_list); spin_lock_init(&card->lock); setup_timer(&card->flush_timer, flush_timer_callback, (unsigned long)card); @@ -307,7 +307,7 @@ fw_card_add(struct fw_card *card, retval = device_add(&card->card_device); if (retval < 0) { - fw_error("Failed to register card device."); + fw_error("Failed to register card device."); return retval; } @@ -358,13 +358,13 @@ dummy_set_config_rom(struct fw_card *card, static void dummy_send_request(struct fw_card *card, struct fw_packet *packet) { - packet->callback(packet, card, -ENODEV); + packet->callback(packet, card, -ENODEV); } static void dummy_send_response(struct fw_card *card, struct fw_packet *packet) { - packet->callback(packet, card, -ENODEV); + packet->callback(packet, card, -ENODEV); } static int @@ -375,12 +375,12 @@ dummy_enable_phys_dma(struct fw_card *card, } static struct fw_card_driver dummy_driver = { - .name = "dummy", + .name = "dummy", .enable = dummy_enable, .update_phy_reg = dummy_update_phy_reg, .set_config_rom = dummy_set_config_rom, - .send_request = dummy_send_request, - .send_response = dummy_send_response, + .send_request = dummy_send_request, + .send_response = dummy_send_response, .enable_phys_dma = dummy_enable_phys_dma }; @@ -428,13 +428,6 @@ EXPORT_SYMBOL(fw_card_put); int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) { - u32 address; - - if (short_reset) - address = 5; - else - address = 1; - - return card->driver->update_phy_reg(card, address, 0, 0x40); + return card->driver->update_phy_reg(card, short_reset ? 5 : 1, 0, 0x40); } EXPORT_SYMBOL(fw_core_initiate_bus_reset); diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index e2ae93361a5..b934272913e 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -33,15 +33,15 @@ #define TCODE_READ_QUADLET_RESPONSE 6 #define TCODE_READ_BLOCK_RESPONSE 7 #define TCODE_CYCLE_START 8 -#define TCODE_LOCK_REQUEST 9 -#define TCODE_STREAM_DATA 10 -#define TCODE_LOCK_RESPONSE 11 +#define TCODE_LOCK_REQUEST 9 +#define TCODE_STREAM_DATA 10 +#define TCODE_LOCK_RESPONSE 11 #define RCODE_COMPLETE 0x0 -#define RCODE_CONFLICT_ERROR 0x4 -#define RCODE_DATA_ERROR 0x5 -#define RCODE_TYPE_ERROR 0x6 -#define RCODE_ADDRESS_ERROR 0x7 +#define RCODE_CONFLICT_ERROR 0x4 +#define RCODE_DATA_ERROR 0x5 +#define RCODE_TYPE_ERROR 0x6 +#define RCODE_ADDRESS_ERROR 0x7 #define SCODE_100 0x0 #define SCODE_200 0x1 @@ -122,13 +122,13 @@ struct fw_cdev_create_iso_context { }; struct fw_cdev_iso_packet { - __u16 payload_length; /* Length of indirect payload. */ + __u16 payload_length; /* Length of indirect payload. */ __u32 interrupt : 1; /* Generate interrupt on this packet */ __u32 skip : 1; /* Set to not send packet at all. */ __u32 tag : 2; __u32 sy : 4; __u32 header_length : 8; /* Length of immediate header. */ - __u32 header[0]; + __u32 header[0]; }; struct fw_cdev_queue_iso { diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index e541daade0c..559b9340e8f 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -34,7 +34,6 @@ void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) ci->p = p + 1; ci->end = ci->p + (p[0] >> 16); } - EXPORT_SYMBOL(fw_csr_iterator_init); int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value) @@ -44,7 +43,6 @@ int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value) return ci->p++ < ci->end; } - EXPORT_SYMBOL(fw_csr_iterator_next); static int is_fw_unit(struct device *dev); @@ -158,7 +156,6 @@ struct bus_type fw_bus_type = { .match = fw_unit_match, .uevent = fw_unit_uevent }; - EXPORT_SYMBOL(fw_bus_type); extern struct fw_device *fw_device_get(struct fw_device *device) @@ -196,7 +193,6 @@ int fw_device_enable_phys_dma(struct fw_device *device) device->node_id, device->generation); } - EXPORT_SYMBOL(fw_device_enable_phys_dma); static ssize_t diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index f39cf6ae625..b150adb4253 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -48,7 +48,7 @@ struct fw_device { static inline struct fw_device * fw_device(struct device *dev) { - return container_of(dev, struct fw_device, device); + return container_of(dev, struct fw_device, device); } struct fw_device *fw_device_get(struct fw_device *device); @@ -63,7 +63,7 @@ struct fw_unit { static inline struct fw_unit * fw_unit(struct device *dev) { - return container_of(dev, struct fw_unit, device); + return container_of(dev, struct fw_unit, device); } #define CSR_OFFSET 0x40 @@ -119,7 +119,7 @@ struct fw_driver { static inline struct fw_driver * fw_driver(struct device_driver *drv) { - return container_of(drv, struct fw_driver, driver); + return container_of(drv, struct fw_driver, driver); } extern const struct file_operations fw_device_ops; diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 6b638568c2c..024fab4ef99 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -99,7 +99,6 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type, return ctx; } - EXPORT_SYMBOL(fw_iso_context_create); void fw_iso_context_destroy(struct fw_iso_context *ctx) @@ -110,7 +109,6 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx) card->driver->free_iso_context(ctx); } - EXPORT_SYMBOL(fw_iso_context_destroy); int @@ -122,7 +120,6 @@ fw_iso_context_send(struct fw_iso_context *ctx, return ctx->card->driver->send_iso(ctx, cycle); } - EXPORT_SYMBOL(fw_iso_context_send); int @@ -133,5 +130,4 @@ fw_iso_context_queue(struct fw_iso_context *ctx, return card->driver->queue_iso(ctx, packet, payload); } - EXPORT_SYMBOL(fw_iso_context_queue); diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 6eff7996c1a..1f34bdd95c8 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -963,9 +963,8 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, * element so that head == tail means buffer full. */ memset(ctx->head_descriptor, 0, sizeof *ctx->head_descriptor); - ctx->head_descriptor->control = - cpu_to_le16(descriptor_output_last); - ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011); + ctx->head_descriptor->control = cpu_to_le16(descriptor_output_last); + ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011); ctx->head_descriptor++; return &ctx->base; diff --git a/drivers/firewire/fw-ohci.h b/drivers/firewire/fw-ohci.h index 35e2a759e01..a562305078b 100644 --- a/drivers/firewire/fw-ohci.h +++ b/drivers/firewire/fw-ohci.h @@ -63,7 +63,7 @@ #define OHCI1394_PhyControl_Read(addr) (((addr) << 8) | 0x00008000) #define OHCI1394_PhyControl_ReadDone 0x80000000 #define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) -#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) +#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) #define OHCI1394_PhyControl_WriteDone 0x00004000 #define OHCI1394_IsochronousCycleTimer 0x0F0 #define OHCI1394_AsReqFilterHiSet 0x100 @@ -109,27 +109,27 @@ #define OHCI1394_IsoRcvContextMatch(n) (0x410 + 32 * (n)) /* Interrupts Mask/Events */ -#define OHCI1394_reqTxComplete 0x00000001 -#define OHCI1394_respTxComplete 0x00000002 -#define OHCI1394_ARRQ 0x00000004 -#define OHCI1394_ARRS 0x00000008 -#define OHCI1394_RQPkt 0x00000010 -#define OHCI1394_RSPkt 0x00000020 -#define OHCI1394_isochTx 0x00000040 -#define OHCI1394_isochRx 0x00000080 -#define OHCI1394_postedWriteErr 0x00000100 -#define OHCI1394_lockRespErr 0x00000200 -#define OHCI1394_selfIDComplete 0x00010000 -#define OHCI1394_busReset 0x00020000 -#define OHCI1394_phy 0x00080000 -#define OHCI1394_cycleSynch 0x00100000 -#define OHCI1394_cycle64Seconds 0x00200000 -#define OHCI1394_cycleLost 0x00400000 -#define OHCI1394_cycleInconsistent 0x00800000 -#define OHCI1394_unrecoverableError 0x01000000 -#define OHCI1394_cycleTooLong 0x02000000 -#define OHCI1394_phyRegRcvd 0x04000000 -#define OHCI1394_masterIntEnable 0x80000000 +#define OHCI1394_reqTxComplete 0x00000001 +#define OHCI1394_respTxComplete 0x00000002 +#define OHCI1394_ARRQ 0x00000004 +#define OHCI1394_ARRS 0x00000008 +#define OHCI1394_RQPkt 0x00000010 +#define OHCI1394_RSPkt 0x00000020 +#define OHCI1394_isochTx 0x00000040 +#define OHCI1394_isochRx 0x00000080 +#define OHCI1394_postedWriteErr 0x00000100 +#define OHCI1394_lockRespErr 0x00000200 +#define OHCI1394_selfIDComplete 0x00010000 +#define OHCI1394_busReset 0x00020000 +#define OHCI1394_phy 0x00080000 +#define OHCI1394_cycleSynch 0x00100000 +#define OHCI1394_cycle64Seconds 0x00200000 +#define OHCI1394_cycleLost 0x00400000 +#define OHCI1394_cycleInconsistent 0x00800000 +#define OHCI1394_unrecoverableError 0x01000000 +#define OHCI1394_cycleTooLong 0x02000000 +#define OHCI1394_phyRegRcvd 0x04000000 +#define OHCI1394_masterIntEnable 0x80000000 #define OHCI1394_evt_no_status 0x0 #define OHCI1394_evt_long_packet 0x2 diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index e111687f559..1938f36cfaa 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -444,5 +444,4 @@ fw_core_handle_bus_reset(struct fw_card *card, spin_unlock_irqrestore(&card->lock, flags); } - EXPORT_SYMBOL(fw_core_handle_bus_reset); diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index a78c9516ed0..4311d9f890d 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -37,7 +37,7 @@ struct fw_port { struct fw_node { u16 node_id; - u8 color; + u8 color; u8 port_count; unsigned link_on : 1; unsigned initiated_reset : 1; @@ -48,19 +48,19 @@ struct fw_node { atomic_t ref_count; - /* For serializing node topology into a list. */ + /* For serializing node topology into a list. */ struct list_head link; /* Upper layer specific data. */ void *data; - struct fw_port ports[0]; + struct fw_port ports[0]; }; static inline struct fw_node * fw_node(struct list_head *l) { - return list_entry (l, struct fw_node, link); + return list_entry (l, struct fw_node, link); } static inline struct fw_node * diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index c2473a82431..79563b2848f 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -341,7 +341,6 @@ const struct fw_address_region fw_csr_region = { 0xfffff0000000ULL, 0xfffff0000800ull }; const struct fw_address_region fw_unit_space_region = { 0xfffff0000900ull, 0x1000000000000ull }; - EXPORT_SYMBOL(fw_low_memory_region); EXPORT_SYMBOL(fw_high_memory_region); EXPORT_SYMBOL(fw_private_region); @@ -355,7 +354,6 @@ EXPORT_SYMBOL(fw_unit_space_region); * parameters passed to the callback give the details of the * particular request */ - int fw_core_add_address_handler(struct fw_address_handler *handler, const struct fw_address_region *region) @@ -385,7 +383,6 @@ fw_core_add_address_handler(struct fw_address_handler *handler, return ret; } - EXPORT_SYMBOL(fw_core_add_address_handler); /** @@ -396,7 +393,6 @@ EXPORT_SYMBOL(fw_core_add_address_handler); * length are set to the start and the length respectively for the * deallocated region, payload is set to NULL. */ - void fw_core_remove_address_handler(struct fw_address_handler *handler) { unsigned long flags; @@ -405,7 +401,6 @@ void fw_core_remove_address_handler(struct fw_address_handler *handler) list_del(&handler->link); spin_unlock_irqrestore(&address_handler_lock, flags); } - EXPORT_SYMBOL(fw_core_remove_address_handler); struct fw_request { @@ -552,7 +547,6 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) card->driver->send_response(card, &request->response); } - EXPORT_SYMBOL(fw_send_response); void @@ -613,7 +607,6 @@ fw_core_handle_request(struct fw_card *card, request->data, request->length, handler->callback_data); } - EXPORT_SYMBOL(fw_core_handle_request); void @@ -677,7 +670,6 @@ fw_core_handle_response(struct fw_card *card, t->callback(card, rcode, data, data_length, t->callback_data); } - EXPORT_SYMBOL(fw_core_handle_response); MODULE_AUTHOR("Kristian Hoegsberg "); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index a664fc3380c..22d2871131b 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -36,9 +36,9 @@ #define TCODE_READ_QUADLET_RESPONSE 6 #define TCODE_READ_BLOCK_RESPONSE 7 #define TCODE_CYCLE_START 8 -#define TCODE_LOCK_REQUEST 9 -#define TCODE_STREAM_DATA 10 -#define TCODE_LOCK_RESPONSE 11 +#define TCODE_LOCK_REQUEST 9 +#define TCODE_STREAM_DATA 10 +#define TCODE_LOCK_RESPONSE 11 #define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) #define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0) @@ -61,26 +61,26 @@ #define SCODE_400 0x2 #define SCODE_BETA 0x3 -#define EXTCODE_MASK_SWAP 0x1 -#define EXTCODE_COMPARE_SWAP 0x2 -#define EXTCODE_FETCH_ADD 0x3 -#define EXTCODE_LITTLE_ADD 0x4 -#define EXTCODE_BOUNDED_ADD 0x5 -#define EXTCODE_WRAP_ADD 0x6 - -#define ACK_COMPLETE 0x1 -#define ACK_PENDING 0x2 -#define ACK_BUSY_X 0x4 -#define ACK_BUSY_A 0x5 -#define ACK_BUSY_B 0x6 -#define ACK_DATA_ERROR 0xd -#define ACK_TYPE_ERROR 0xe - -#define RCODE_COMPLETE 0x0 -#define RCODE_CONFLICT_ERROR 0x4 -#define RCODE_DATA_ERROR 0x5 -#define RCODE_TYPE_ERROR 0x6 -#define RCODE_ADDRESS_ERROR 0x7 +#define EXTCODE_MASK_SWAP 0x1 +#define EXTCODE_COMPARE_SWAP 0x2 +#define EXTCODE_FETCH_ADD 0x3 +#define EXTCODE_LITTLE_ADD 0x4 +#define EXTCODE_BOUNDED_ADD 0x5 +#define EXTCODE_WRAP_ADD 0x6 + +#define ACK_COMPLETE 0x1 +#define ACK_PENDING 0x2 +#define ACK_BUSY_X 0x4 +#define ACK_BUSY_A 0x5 +#define ACK_BUSY_B 0x6 +#define ACK_DATA_ERROR 0xd +#define ACK_TYPE_ERROR 0xe + +#define RCODE_COMPLETE 0x0 +#define RCODE_CONFLICT_ERROR 0x4 +#define RCODE_DATA_ERROR 0x5 +#define RCODE_TYPE_ERROR 0x6 +#define RCODE_ADDRESS_ERROR 0x7 /* Juju specific rcodes */ #define RCODE_SEND_ERROR 0x10 @@ -94,10 +94,10 @@ #define LOCAL_BUS 0xffc0 -#define SELFID_PORT_CHILD 0x3 -#define SELFID_PORT_PARENT 0x2 -#define SELFID_PORT_NCONN 0x1 -#define SELFID_PORT_NONE 0x0 +#define SELFID_PORT_CHILD 0x3 +#define SELFID_PORT_PARENT 0x2 +#define SELFID_PORT_NCONN 0x1 +#define SELFID_PORT_NONE 0x0 #define PHY_PACKET_CONFIG 0x0 #define PHY_PACKET_LINK_ON 0x1 @@ -162,54 +162,54 @@ typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle, void *callback_data); struct fw_packet { - int speed; - int generation; - u32 header[4]; - size_t header_length; - void *payload; - size_t payload_length; - u32 timestamp; - - dma_addr_t payload_bus; - - /* This callback is called when the packet transmission has - * completed; for successful transmission, the status code is - * the ack received from the destination, otherwise it's a - * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO. - * The callback can be called from tasklet context and thus - * must never block. - */ - fw_packet_callback_t callback; + int speed; + int generation; + u32 header[4]; + size_t header_length; + void *payload; + size_t payload_length; + u32 timestamp; + + dma_addr_t payload_bus; + + /* This callback is called when the packet transmission has + * completed; for successful transmission, the status code is + * the ack received from the destination, otherwise it's a + * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO. + * The callback can be called from tasklet context and thus + * must never block. + */ + fw_packet_callback_t callback; int status; - struct list_head link; + struct list_head link; }; struct fw_transaction { - int node_id; /* The generation is implied; it is always the current. */ - int tlabel; - int timestamp; - struct list_head link; + int node_id; /* The generation is implied; it is always the current. */ + int tlabel; + int timestamp; + struct list_head link; - struct fw_packet packet; + struct fw_packet packet; /* The data passed to the callback is valid only during the * callback. */ - fw_transaction_callback_t callback; - void *callback_data; + fw_transaction_callback_t callback; + void *callback_data; }; static inline struct fw_packet * fw_packet(struct list_head *l) { - return list_entry (l, struct fw_packet, link); + return list_entry (l, struct fw_packet, link); } struct fw_address_handler { - u64 offset; - size_t length; - fw_address_callback_t address_callback; - void *callback_data; - struct list_head link; + u64 offset; + size_t length; + fw_address_callback_t address_callback; + void *callback_data; + struct list_head link; }; @@ -236,22 +236,22 @@ struct fw_card { const struct fw_card_driver *driver; struct device *device; - int node_id; - int generation; - /* This is the generation used for timestamping incoming requests. */ - int request_generation; - int current_tlabel, tlabel_mask; - struct list_head transaction_list; + int node_id; + int generation; + /* This is the generation used for timestamping incoming requests. */ + int request_generation; + int current_tlabel, tlabel_mask; + struct list_head transaction_list; struct timer_list flush_timer; - unsigned long long guid; + unsigned long long guid; int max_receive; int link_speed; int config_rom_generation; - /* We need to store up to 4 self ID for a maximum of 63 devices. */ - int self_id_count; - u32 self_ids[252]; + /* We need to store up to 4 self ID for a maximum of 63 devices. */ + int self_id_count; + u32 self_ids[252]; spinlock_t lock; /* Take this lock when handling the lists in * this struct. */ @@ -282,13 +282,13 @@ void fw_card_put(struct fw_card *card); * scatter-gather streaming (e.g. assembling video frame automatically). */ struct fw_iso_packet { - u16 payload_length; /* Length of indirect payload. */ + u16 payload_length; /* Length of indirect payload. */ u32 interrupt : 1; /* Generate interrupt on this packet */ u32 skip : 1; /* Set to not send packet at all. */ u32 tag : 2; u32 sy : 4; u32 header_length : 8; /* Length of immediate header. */ - u32 header[0]; + u32 header[0]; }; #define FW_ISO_CONTEXT_TRANSMIT 0 @@ -335,25 +335,25 @@ fw_iso_context_send(struct fw_iso_context *ctx, int channel, int speed, int cycle); struct fw_card_driver { - const char *name; + const char *name; - /* Enable the given card with the given initial config rom. - * This function is expected to activate the card, and either - * enable the PHY or set the link_on bit and initiate a bus - * reset. */ - int (*enable) (struct fw_card *card, u32 *config_rom, size_t length); + /* Enable the given card with the given initial config rom. + * This function is expected to activate the card, and either + * enable the PHY or set the link_on bit and initiate a bus + * reset. */ + int (*enable) (struct fw_card *card, u32 *config_rom, size_t length); - int (*update_phy_reg) (struct fw_card *card, int address, - int clear_bits, int set_bits); + int (*update_phy_reg) (struct fw_card *card, int address, + int clear_bits, int set_bits); - /* Update the config rom for an enabled card. This function - * should change the config rom that is presented on the bus - * an initiate a bus reset. */ - int (*set_config_rom) (struct fw_card *card, + /* Update the config rom for an enabled card. This function + * should change the config rom that is presented on the bus + * an initiate a bus reset. */ + int (*set_config_rom) (struct fw_card *card, u32 *config_rom, size_t length); - void (*send_request) (struct fw_card *card, struct fw_packet *packet); - void (*send_response) (struct fw_card *card, struct fw_packet *packet); + void (*send_request) (struct fw_card *card, struct fw_packet *packet); + void (*send_response) (struct fw_card *card, struct fw_packet *packet); /* Allow the specified node ID to do direct DMA out and in of * host memory. The card will disable this for all node when @@ -419,8 +419,8 @@ fw_core_handle_request(struct fw_card *card, u32 length, u32 *payload); void fw_core_handle_response(struct fw_card *card, - int speed, int ack, int timestamp, - u32 length, u32 *payload); + int speed, int ack, int timestamp, + u32 length, u32 *payload); #endif /* __fw_transaction_h */ -- cgit v1.2.3-70-g09d2 From 83db801ce8c644edee49f4364c7ebdfef1657762 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 26 Jan 2007 00:37:50 -0500 Subject: firewire: Implement gap count optimization. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 46 ++++++++++++++++-------- drivers/firewire/fw-topology.c | 76 ++++++++++++++++++++++++++++++++++----- drivers/firewire/fw-topology.h | 15 +++++--- drivers/firewire/fw-transaction.c | 8 +++-- drivers/firewire/fw-transaction.h | 6 ++-- 5 files changed, 120 insertions(+), 31 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index c8b7d695c81..307c8b85138 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -186,14 +186,17 @@ fw_core_remove_descriptor (struct fw_descriptor *desc) } EXPORT_SYMBOL(fw_core_remove_descriptor); +static const char gap_count_table[] = { + 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 +}; + static void fw_card_irm_work(struct work_struct *work) { - struct fw_card *card = - container_of(work, struct fw_card, work.work); + struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_device *root; unsigned long flags; - int new_irm_id, generation; + int root_id, new_irm_id, gap_count, generation, do_reset = 0; /* FIXME: This simple bus management unconditionally picks a * cycle master if the current root can't do it. We need to @@ -206,35 +209,50 @@ fw_card_irm_work(struct work_struct *work) generation = card->generation; root = card->root_node->data; + root_id = card->root_node->node_id; - if (root == NULL) + if (root == NULL) { /* Either link_on is false, or we failed to read the * config rom. In either case, pick another root. */ new_irm_id = card->local_node->node_id; - else if (root->state != FW_DEVICE_RUNNING) + } else if (root->state != FW_DEVICE_RUNNING) { /* If we haven't probed this device yet, bail out now * and let's try again once that's done. */ - new_irm_id = -1; - else if (root->config_rom[2] & bib_cmc) + new_irm_id = root_id; + } else if (root->config_rom[2] & bib_cmc) { /* FIXME: I suppose we should set the cmstr bit in the * STATE_CLEAR register of this node, as described in * 1394-1995, 8.4.2.6. Also, send out a force root * packet for this node. */ - new_irm_id = -1; - else + new_irm_id = root_id; + } else { /* Current root has an active link layer and we * successfully read the config rom, but it's not * cycle master capable. */ new_irm_id = card->local_node->node_id; + } + + /* Now figure out what gap count to set. */ + if (card->topology_type == FW_TOPOLOGY_A && + card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) + gap_count = gap_count_table[card->root_node->max_hops]; + else + gap_count = 63; + + /* Finally, figure out if we should do a reset or not. If we've + * done less that 5 resets with the same physical topology and we + * have either a new root or a new gap count setting, let's do it. */ - if (card->irm_retries++ > 5) - new_irm_id = -1; + if (card->irm_retries++ < 5 && + (card->gap_count != gap_count || new_irm_id != root_id)) + do_reset = 1; spin_unlock_irqrestore(&card->lock, flags); - if (new_irm_id > 0) { - fw_notify("Trying to become root (card %d)\n", card->index); - fw_send_force_root(card, new_irm_id, generation); + if (do_reset) { + fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", + card->index, new_irm_id, gap_count); + fw_send_phy_config(card, new_irm_id, generation, gap_count); fw_core_initiate_bus_reset(card, 1); } } diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 684d87d9977..d3131e7d52f 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -113,6 +113,44 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color) return node; } +/* Compute the maximum hop count for this node and it's children. The + * maximum hop count is the maximum number of connections between any + * two nodes in the subtree rooted at this node. We need this for + * setting the gap count. As we build the tree bottom up in + * build_tree() below, this is fairly easy to do: for each node we + * maintain the max hop count and the max depth, ie the number of hops + * to the furthest leaf. Computing the max hop count breaks down into + * two cases: either the path goes through this node, in which case + * the hop count is the sum of the two biggest child depths plus 2. + * Or it could be the case that the max hop path is entirely + * containted in a child tree, in which case the max hop count is just + * the max hop count of this child. + */ +static void update_hop_count(struct fw_node *node) +{ + int depths[2] = { -1, -1 }; + int max_child_hops = 0; + int i; + + for (i = 0; i < node->port_count; i++) { + if (node->ports[i].node == NULL) + continue; + + if (node->ports[i].node->max_hops > max_child_hops) + max_child_hops = node->ports[i].node->max_hops; + + if (node->ports[i].node->max_depth > depths[0]) { + depths[1] = depths[0]; + depths[0] = node->ports[i].node->max_depth; + } else if (node->ports[i].node->max_depth > depths[1]) + depths[1] = node->ports[i].node->max_depth; + } + + node->max_depth = depths[0] + 1; + node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2); +} + + /** * build_tree - Build the tree representation of the topology * @self_ids: array of self IDs to create the tree from @@ -131,6 +169,7 @@ static struct fw_node *build_tree(struct fw_card *card) struct list_head stack, *h; u32 *sid, *next_sid, *end, q; int i, port_count, child_port_count, phy_id, parent_count, stack_depth; + int gap_count, topology_type; local_node = NULL; node = NULL; @@ -140,6 +179,8 @@ static struct fw_node *build_tree(struct fw_card *card) end = sid + card->self_id_count; phy_id = 0; card->irm_node = NULL; + gap_count = self_id_gap_count(*sid); + topology_type = 0; while (sid < end) { next_sid = count_ports(sid, &port_count, &child_port_count); @@ -179,6 +220,11 @@ static struct fw_node *build_tree(struct fw_card *card) if (self_id_contender(q)) card->irm_node = node; + if (node->phy_speed == SCODE_BETA) + topology_type |= FW_TOPOLOGY_B; + else + topology_type |= FW_TOPOLOGY_A; + parent_count = 0; for (i = 0; i < port_count; i++) { @@ -223,11 +269,21 @@ static struct fw_node *build_tree(struct fw_card *card) list_add_tail(&node->link, &stack); stack_depth += 1 - child_port_count; + /* If all PHYs does not report the same gap count + * setting, we fall back to 63 which will force a gap + * count reconfiguration and a reset. */ + if (self_id_gap_count(q) != gap_count) + gap_count = 63; + + update_hop_count(node); + sid = next_sid; phy_id++; } card->root_node = node; + card->gap_count = gap_count; + card->topology_type = topology_type; return local_node; } @@ -286,7 +342,8 @@ report_found_node(struct fw_card *card, int b_path = (node->phy_speed == SCODE_BETA); if (parent != NULL) { - node->max_speed = min(parent->max_speed, node->phy_speed); + node->max_speed = min((u8)parent->max_speed, + (u8)node->phy_speed); node->b_path = parent->b_path && b_path; } else { node->max_speed = node->phy_speed; @@ -329,7 +386,7 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) * as we go. */ static void -update_tree(struct fw_card *card, struct fw_node *root, int *changed) +update_tree(struct fw_card *card, struct fw_node *root) { struct list_head list0, list1; struct fw_node *node0, *node1; @@ -342,7 +399,6 @@ update_tree(struct fw_card *card, struct fw_node *root, int *changed) node0 = fw_node(list0.next); node1 = fw_node(list1.next); - *changed = 0; while (&node0->link != &list0) { @@ -358,6 +414,7 @@ update_tree(struct fw_card *card, struct fw_node *root, int *changed) node0->color = card->color; node0->link_on = node1->link_on; node0->initiated_reset = node1->initiated_reset; + node0->max_hops = node1->max_hops; node1->color = card->color; fw_node_event(card, node0, event); @@ -386,7 +443,6 @@ update_tree(struct fw_card *card, struct fw_node *root, int *changed) for_each_fw_node(card, node0->ports[i].node, report_lost_node); node0->ports[i].node = NULL; - *changed = 1; } else if (node1->ports[i].node) { /* One or more node were connected to * this port. Move the new nodes into @@ -395,7 +451,6 @@ update_tree(struct fw_card *card, struct fw_node *root, int *changed) move_tree(node0, node1, i); for_each_fw_node(card, node0->ports[i].node, report_found_node); - *changed = 1; } } @@ -411,12 +466,17 @@ fw_core_handle_bus_reset(struct fw_card *card, { struct fw_node *local_node; unsigned long flags; - int changed; fw_flush_transactions(card); spin_lock_irqsave(&card->lock, flags); + /* If the new topology has a different self_id_count the topology + * changed, either nodes were added or removed. In that case we + * reset the IRM reset counter. */ + if (card->self_id_count != self_id_count) + card->irm_retries = 0; + card->node_id = node_id; card->self_id_count = self_id_count; card->generation = generation; @@ -433,9 +493,7 @@ fw_core_handle_bus_reset(struct fw_card *card, card->local_node = local_node; for_each_fw_node(card, local_node, report_found_node); } else { - update_tree(card, local_node, &changed); - if (changed) - card->irm_retries = 0; + update_tree(card, local_node); } /* If we're not the root node, we may have to do some IRM work. */ diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index ab03059a0da..f2a575e05ae 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -22,6 +22,12 @@ #ifndef __fw_topology_h #define __fw_topology_h +enum { + FW_TOPOLOGY_A = 0x01, + FW_TOPOLOGY_B = 0x02, + FW_TOPOLOGY_MIXED = 0x03, +}; + enum { FW_NODE_CREATED = 0x00, FW_NODE_UPDATED = 0x01, @@ -42,10 +48,11 @@ struct fw_node { unsigned link_on : 1; unsigned initiated_reset : 1; unsigned b_path : 1; - u8 phy_speed; /* As in the self ID packet. */ - u8 max_speed; /* Minimum of all phy-speeds and port speeds on - * the path from the local node to this node. */ - + u8 phy_speed : 3; /* As in the self ID packet. */ + u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on + * the path from the local node to this node. */ + u8 max_depth : 4; /* Maximum depth to any leaf node */ + u8 max_hops : 4; /* Max hops in this sub tree */ atomic_t ref_count; /* For serializing node topology into a list. */ diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 439a3e3ee2f..57ecf95e527 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -274,11 +274,15 @@ static void send_phy_packet(struct fw_card *card, u32 data, int generation) card->driver->send_request(card, packet); } -void fw_send_force_root(struct fw_card *card, int node_id, int generation) +void fw_send_phy_config(struct fw_card *card, + int node_id, int generation, int gap_count) { u32 q; - q = phy_identifier(PHY_PACKET_CONFIG) | phy_config_root_id(node_id); + q = phy_identifier(PHY_PACKET_CONFIG) | + phy_config_root_id(node_id) | + phy_config_gap_count(gap_count); + send_phy_packet(card, q, generation); } diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 22d2871131b..df652452bdb 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -259,6 +259,8 @@ struct fw_card { struct fw_node *root_node; struct fw_node *irm_node; int color; + int gap_count; + int topology_type; int index; @@ -386,8 +388,8 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, void fw_flush_transactions(struct fw_card *card); -void -fw_send_force_root(struct fw_card *card, int node_id, int generation); +void fw_send_phy_config(struct fw_card *card, + int node_id, int generation, int gap_count); /* Called by the topology code to inform the device code of node * activity; found, lost, or updated nodes */ -- cgit v1.2.3-70-g09d2 From 2639a6fb268e1f2a7700fe3d31cbca9b39aa3ad9 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 26 Jan 2007 00:37:57 -0500 Subject: firewire: Use struct fw_packet for incoming packets too in controller interface. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 61 ++++++++++++++++-------- drivers/firewire/fw-transaction.c | 99 +++++++++++++++++++-------------------- drivers/firewire/fw-transaction.h | 13 ++--- 3 files changed, 92 insertions(+), 81 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index d6f0644b05d..8dc872aedce 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -221,24 +221,48 @@ static void ar_context_tasklet(unsigned long data) { struct ar_context *ctx = (struct ar_context *)data; struct fw_ohci *ohci = ctx->ohci; - u32 status; - int length, speed, ack, timestamp, tcode; + struct fw_packet p; + u32 status, length, tcode; /* FIXME: What to do about evt_* errors? */ length = le16_to_cpu(ctx->descriptor.req_count) - le16_to_cpu(ctx->descriptor.res_count) - 4; status = le32_to_cpu(ctx->buffer[length / 4]); - ack = ((status >> 16) & 0x1f) - 16; - speed = (status >> 21) & 0x7; - timestamp = status & 0xffff; - ctx->buffer[0] = le32_to_cpu(ctx->buffer[0]); - ctx->buffer[1] = le32_to_cpu(ctx->buffer[1]); - ctx->buffer[2] = le32_to_cpu(ctx->buffer[2]); + p.ack = ((status >> 16) & 0x1f) - 16; + p.speed = (status >> 21) & 0x7; + p.timestamp = status & 0xffff; + p.generation = ohci->request_generation; + + p.header[0] = le32_to_cpu(ctx->buffer[0]); + p.header[1] = le32_to_cpu(ctx->buffer[1]); + p.header[2] = le32_to_cpu(ctx->buffer[2]); + + tcode = (p.header[0] >> 4) & 0x0f; + switch (tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_READ_QUADLET_RESPONSE: + p.header[3] = ctx->buffer[3]; + p.header_length = 16; + break; + + case TCODE_WRITE_BLOCK_REQUEST: + case TCODE_READ_BLOCK_REQUEST : + case TCODE_READ_BLOCK_RESPONSE: + case TCODE_LOCK_REQUEST: + case TCODE_LOCK_RESPONSE: + p.header[3] = le32_to_cpu(ctx->buffer[3]); + p.header_length = 16; + break; + + case TCODE_WRITE_RESPONSE: + case TCODE_READ_QUADLET_REQUEST: + p.header_length = 12; + break; + } - tcode = (ctx->buffer[0] >> 4) & 0x0f; - if (TCODE_IS_BLOCK_PACKET(tcode)) - ctx->buffer[3] = le32_to_cpu(ctx->buffer[3]); + p.payload = (void *) ctx->buffer + p.header_length; + p.payload_length = length - p.header_length; /* The OHCI bus reset handler synthesizes a phy packet with * the new generation number when a bus reset happens (see @@ -248,15 +272,12 @@ static void ar_context_tasklet(unsigned long data) * we use the unique tlabel for finding the matching * request. */ - if (ack + 16 == 0x09) + if (p.ack + 16 == 0x09) ohci->request_generation = (ctx->buffer[2] >> 16) & 0xff; else if (ctx == &ohci->ar_request_ctx) - fw_core_handle_request(&ohci->card, speed, ack, timestamp, - ohci->request_generation, - length, ctx->buffer); + fw_core_handle_request(&ohci->card, &p); else - fw_core_handle_response(&ohci->card, speed, ack, timestamp, - length, ctx->buffer); + fw_core_handle_response(&ohci->card, &p); ctx->descriptor.data_address = cpu_to_le32(ctx->buffer_bus); ctx->descriptor.req_count = cpu_to_le16(sizeof ctx->buffer); @@ -323,15 +344,15 @@ do_packet_callbacks(struct fw_ohci *ohci, struct list_head *list) struct fw_packet *p, *next; list_for_each_entry_safe(p, next, list, link) - p->callback(p, &ohci->card, p->status); + p->callback(p, &ohci->card, p->ack); } static void complete_transmission(struct fw_packet *packet, - int status, struct list_head *list) + int ack, struct list_head *list) { list_move_tail(&packet->link, list); - packet->status = status; + packet->ack = ack; } /* This function prepares the first packet in the context queue for diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 57ecf95e527..4ca39f09f58 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -426,15 +426,15 @@ free_response_callback(struct fw_packet *packet, static void fw_fill_response(struct fw_packet *response, - u32 *request, u32 *data, size_t length) + struct fw_packet *request, void *data) { int tcode, tlabel, extended_tcode, source, destination; - tcode = header_get_tcode(request[0]); - tlabel = header_get_tlabel(request[0]); - source = header_get_destination(request[0]); - destination = header_get_source(request[1]); - extended_tcode = header_get_extended_tcode(request[3]); + tcode = header_get_tcode(request->header[0]); + tlabel = header_get_tlabel(request->header[0]); + source = header_get_destination(request->header[0]); + destination = header_get_source(request->header[1]); + extended_tcode = header_get_extended_tcode(request->header[3]); response->header[0] = header_retry(RETRY_1) | @@ -463,11 +463,11 @@ fw_fill_response(struct fw_packet *response, case TCODE_LOCK_REQUEST: response->header[0] |= header_tcode(tcode + 2); response->header[3] = - header_data_length(length) | + header_data_length(request->payload_length) | header_extended_tcode(extended_tcode); response->header_length = 16; response->payload = data; - response->payload_length = length; + response->payload_length = request->payload_length; break; default: @@ -477,24 +477,23 @@ fw_fill_response(struct fw_packet *response, } static struct fw_request * -allocate_request(u32 *header, int ack, - int speed, int timestamp, int generation) +allocate_request(struct fw_packet *p) { struct fw_request *request; u32 *data, length; - int request_tcode; + int request_tcode, t; - request_tcode = header_get_tcode(header[0]); + request_tcode = header_get_tcode(p->header[0]); switch (request_tcode) { case TCODE_WRITE_QUADLET_REQUEST: - data = &header[3]; + data = &p->header[3]; length = 4; break; case TCODE_WRITE_BLOCK_REQUEST: case TCODE_LOCK_REQUEST: - data = &header[4]; - length = header_get_data_length(header[3]); + data = p->payload; + length = header_get_data_length(p->header[3]); break; case TCODE_READ_QUADLET_REQUEST: @@ -504,7 +503,7 @@ allocate_request(u32 *header, int ack, case TCODE_READ_BLOCK_REQUEST: data = NULL; - length = header_get_data_length(header[3]); + length = header_get_data_length(p->header[3]); break; default: @@ -516,16 +515,22 @@ allocate_request(u32 *header, int ack, if (request == NULL) return NULL; - request->response.speed = speed; - request->response.timestamp = timestamp; - request->response.generation = generation; + t = (p->timestamp & 0x1fff) + 4000; + if (t >= 8000) + t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000; + else + t = (p->timestamp & ~0x1fff) + t; + + request->response.speed = p->speed; + request->response.timestamp = t; + request->response.generation = p->generation; request->response.callback = free_response_callback; - request->ack = ack; - request->length = length; + request->ack = p->ack; + request->length = p->payload_length; if (data) - memcpy(request->data, data, length); + memcpy(request->data, p->payload, p->payload_length); - fw_fill_response(&request->response, header, request->data, length); + fw_fill_response(&request->response, p, request->data); return request; } @@ -554,31 +559,23 @@ fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) EXPORT_SYMBOL(fw_send_response); void -fw_core_handle_request(struct fw_card *card, - int speed, int ack, int timestamp, - int generation, u32 length, u32 *header) +fw_core_handle_request(struct fw_card *card, struct fw_packet *p) { struct fw_address_handler *handler; struct fw_request *request; unsigned long long offset; unsigned long flags; - int tcode, destination, source, t; + int tcode, destination, source; - if (length > 2048) { + if (p->payload_length > 2048) { /* FIXME: send error response. */ return; } - if (ack != ACK_PENDING && ack != ACK_COMPLETE) + if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) return; - t = (timestamp & 0x1fff) + 4000; - if (t >= 8000) - t = (timestamp & ~0x1fff) + 0x2000 + t - 8000; - else - t = (timestamp & ~0x1fff) + t; - - request = allocate_request(header, ack, speed, t, generation); + request = allocate_request(p); if (request == NULL) { /* FIXME: send statically allocated busy packet. */ return; @@ -586,10 +583,10 @@ fw_core_handle_request(struct fw_card *card, offset = ((unsigned long long) - header_get_offset_high(header[1]) << 32) | header[2]; - tcode = header_get_tcode(header[0]); - destination = header_get_destination(header[0]); - source = header_get_source(header[0]); + header_get_offset_high(p->header[1]) << 32) | p->header[2]; + tcode = header_get_tcode(p->header[0]); + destination = header_get_destination(p->header[0]); + source = header_get_source(p->header[0]); spin_lock_irqsave(&address_handler_lock, flags); handler = lookup_enclosing_address_handler(&address_handler_list, @@ -607,16 +604,14 @@ fw_core_handle_request(struct fw_card *card, else handler->address_callback(card, request, tcode, destination, source, - generation, speed, offset, + p->generation, p->speed, offset, request->data, request->length, handler->callback_data); } EXPORT_SYMBOL(fw_core_handle_request); void -fw_core_handle_response(struct fw_card *card, - int speed, int ack, int timestamp, - u32 length, u32 *header) +fw_core_handle_response(struct fw_card *card, struct fw_packet *p) { struct fw_transaction *t; unsigned long flags; @@ -624,11 +619,11 @@ fw_core_handle_response(struct fw_card *card, size_t data_length; int tcode, tlabel, destination, source, rcode; - tcode = header_get_tcode(header[0]); - tlabel = header_get_tlabel(header[0]); - destination = header_get_destination(header[0]); - source = header_get_source(header[1]); - rcode = header_get_rcode(header[1]); + tcode = header_get_tcode(p->header[0]); + tlabel = header_get_tlabel(p->header[0]); + destination = header_get_destination(p->header[0]); + source = header_get_source(p->header[1]); + rcode = header_get_rcode(p->header[1]); spin_lock_irqsave(&card->lock, flags); list_for_each_entry(t, &card->transaction_list, link) { @@ -650,7 +645,7 @@ fw_core_handle_response(struct fw_card *card, switch (tcode) { case TCODE_READ_QUADLET_RESPONSE: - data = (u32 *) &header[3]; + data = (u32 *) &p->header[3]; data_length = 4; break; @@ -661,8 +656,8 @@ fw_core_handle_response(struct fw_card *card, case TCODE_READ_BLOCK_RESPONSE: case TCODE_LOCK_RESPONSE: - data = &header[4]; - data_length = header_get_data_length(header[3]); + data = &p->header[4]; + data_length = header_get_data_length(p->header[3]); break; default: diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index df652452bdb..903235b142f 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -180,7 +180,7 @@ struct fw_packet { * must never block. */ fw_packet_callback_t callback; - int status; + int ack; struct list_head link; }; @@ -415,14 +415,9 @@ fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, int self_id_count, u32 *self_ids); void -fw_core_handle_request(struct fw_card *card, - int speed, int ack, int timestamp, - int generation, - u32 length, u32 *payload); -void -fw_core_handle_response(struct fw_card *card, - int speed, int ack, int timestamp, - u32 length, u32 *payload); +fw_core_handle_request(struct fw_card *card, struct fw_packet *request); +void +fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); #endif /* __fw_transaction_h */ -- cgit v1.2.3-70-g09d2 From 93c4cceb963ebb133531e5e3f4f6e2da0d222656 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 26 Jan 2007 00:38:26 -0500 Subject: firewire: Handle access to CSR resources on local node. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 130 +++++++++++++++++++++++++++++++++----- drivers/firewire/fw-transaction.c | 14 ++-- drivers/firewire/fw-transaction.h | 31 +++++++++ 3 files changed, 154 insertions(+), 21 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 5156329a865..ac6c018de0d 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -540,38 +540,136 @@ at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 control_set) } #define header_get_destination(q) (((q) >> 16) & 0xffff) +#define header_get_tcode(q) (((q) >> 4) & 0x0f) +#define header_get_offset_high(q) (((q) >> 0) & 0xffff) +#define header_get_data_length(q) (((q) >> 16) & 0xffff) +#define header_get_extended_tcode(q) (((q) >> 0) & 0xffff) + +static void +handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) +{ + struct fw_packet response; + int tcode, length, i; + + tcode = header_get_tcode(packet->header[0]); + if (TCODE_IS_BLOCK_PACKET(tcode)) + length = header_get_data_length(packet->header[3]); + else + length = 4; + + i = csr - CSR_CONFIG_ROM; + if (i + length > CONFIG_ROM_SIZE) { + fw_fill_response(&response, packet->header, + RCODE_ADDRESS_ERROR, NULL, 0); + } else if (!TCODE_IS_READ_REQUEST(tcode)) { + fw_fill_response(&response, packet->header, + RCODE_TYPE_ERROR, NULL, 0); + } else { + fw_fill_response(&response, packet->header, RCODE_COMPLETE, + (void *) ohci->config_rom + i, length); + } + + fw_core_handle_response(&ohci->card, &response); +} + +static void +handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) +{ + struct fw_packet response; + int tcode, length, ext_tcode, sel; + __be32 *payload, lock_old; + u32 lock_arg, lock_data; + + tcode = header_get_tcode(packet->header[0]); + length = header_get_data_length(packet->header[3]); + payload = packet->payload; + ext_tcode = header_get_extended_tcode(packet->header[3]); + + if (tcode == TCODE_LOCK_REQUEST && + ext_tcode == EXTCODE_COMPARE_SWAP && length == 8) { + lock_arg = be32_to_cpu(payload[0]); + lock_data = be32_to_cpu(payload[1]); + } else if (tcode == TCODE_READ_QUADLET_REQUEST) { + lock_arg = 0; + lock_data = 0; + } else { + fw_fill_response(&response, packet->header, + RCODE_TYPE_ERROR, NULL, 0); + goto out; + } + + sel = (csr - CSR_BUS_MANAGER_ID) / 4; + reg_write(ohci, OHCI1394_CSRData, lock_data); + reg_write(ohci, OHCI1394_CSRCompareData, lock_arg); + reg_write(ohci, OHCI1394_CSRControl, sel); + + if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) + lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData)); + else + fw_notify("swap not done yet\n"); + + fw_fill_response(&response, packet->header, + RCODE_COMPLETE, &lock_old, sizeof lock_old); + out: + fw_core_handle_response(&ohci->card, &response); +} + +static void +handle_local_request(struct at_context *ctx, struct fw_packet *packet) +{ + u64 offset; + u32 csr; + + packet->ack = ACK_PENDING; + packet->callback(packet, &ctx->ohci->card, packet->ack); + + offset = + ((unsigned long long) + header_get_offset_high(packet->header[1]) << 32) | + packet->header[2]; + csr = offset - CSR_REGISTER_BASE; + + /* Handle config rom reads. */ + if (csr >= CSR_CONFIG_ROM && csr < CSR_CONFIG_ROM_END) + handle_local_rom(ctx->ohci, packet, csr); + else switch (csr) { + case CSR_BUS_MANAGER_ID: + case CSR_BANDWIDTH_AVAILABLE: + case CSR_CHANNELS_AVAILABLE_HI: + case CSR_CHANNELS_AVAILABLE_LO: + handle_local_lock(ctx->ohci, packet, csr); + break; + default: + if (ctx == &ctx->ohci->at_request_ctx) + fw_core_handle_request(&ctx->ohci->card, packet); + else + fw_core_handle_response(&ctx->ohci->card, packet); + break; + } +} static void at_context_transmit(struct at_context *ctx, struct fw_packet *packet) { LIST_HEAD(list); unsigned long flags; - int local; spin_lock_irqsave(&ctx->ohci->lock, flags); if (header_get_destination(packet->header[0]) == ctx->ohci->node_id && ctx->ohci->generation == packet->generation) { - local = 1; - } else { - list_add_tail(&packet->link, &ctx->list); - if (ctx->list.next == &packet->link) - at_context_setup_packet(ctx, &list); - local = 0; + spin_unlock_irqrestore(&ctx->ohci->lock, flags); + handle_local_request(ctx, packet); + return; } + list_add_tail(&packet->link, &ctx->list); + if (ctx->list.next == &packet->link) + at_context_setup_packet(ctx, &list); + spin_unlock_irqrestore(&ctx->ohci->lock, flags); do_packet_callbacks(ctx->ohci, &list); - - if (local) { - packet->ack = ACK_PENDING; - packet->callback(packet, &ctx->ohci->card, packet->ack); - if (ctx == &ctx->ohci->at_request_ctx) - fw_core_handle_request(&ctx->ohci->card, packet); - else - fw_core_handle_response(&ctx->ohci->card, packet); - } } static void bus_reset_tasklet(unsigned long data) diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index a116ffa9bf4..780ed2b4498 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -425,7 +425,7 @@ free_response_callback(struct fw_packet *packet, kfree(request); } -static void +void fw_fill_response(struct fw_packet *response, u32 *request_header, int rcode, void *payload, size_t length) { @@ -457,7 +457,10 @@ fw_fill_response(struct fw_packet *response, u32 *request_header, case TCODE_READ_QUADLET_REQUEST: response->header[0] |= header_tcode(TCODE_READ_QUADLET_RESPONSE); - response->header[3] = *(u32 *)payload; + if (payload != NULL) + response->header[3] = *(u32 *)payload; + else + response->header[3] = 0; response->header_length = 16; response->payload_length = 0; break; @@ -478,6 +481,7 @@ fw_fill_response(struct fw_packet *response, u32 *request_header, return; } } +EXPORT_SYMBOL(fw_fill_response); static struct fw_request * allocate_request(struct fw_packet *p) @@ -529,9 +533,9 @@ allocate_request(struct fw_packet *p) request->response.generation = p->generation; request->response.callback = free_response_callback; request->ack = p->ack; - request->length = p->payload_length; + request->length = length; if (data) - memcpy(request->data, p->payload, p->payload_length); + memcpy(request->data, p->payload, length); memcpy(request->request_header, p->header, sizeof p->header); @@ -656,7 +660,7 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p) case TCODE_READ_BLOCK_RESPONSE: case TCODE_LOCK_RESPONSE: - data = &p->header[4]; + data = p->payload; data_length = header_get_data_length(p->header[3]); break; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 903235b142f..fb46ef78a32 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -40,6 +40,7 @@ #define TCODE_STREAM_DATA 10 #define TCODE_LOCK_RESPONSE 11 +#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) #define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) #define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0) #define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0) @@ -103,6 +104,34 @@ #define PHY_PACKET_LINK_ON 0x1 #define PHY_PACKET_SELF_ID 0x2 +#define CSR_REGISTER_BASE 0xfffff0000000ULL + +/* register offsets relative to CSR_REGISTER_BASE */ +#define CSR_STATE_CLEAR 0x0 +#define CSR_STATE_SET 0x4 +#define CSR_NODE_IDS 0x8 +#define CSR_RESET_START 0xc +#define CSR_SPLIT_TIMEOUT_HI 0x18 +#define CSR_SPLIT_TIMEOUT_LO 0x1c +#define CSR_CYCLE_TIME 0x200 +#define CSR_BUS_TIME 0x204 +#define CSR_BUSY_TIMEOUT 0x210 +#define CSR_BUS_MANAGER_ID 0x21c +#define CSR_BANDWIDTH_AVAILABLE 0x220 +#define CSR_CHANNELS_AVAILABLE 0x224 +#define CSR_CHANNELS_AVAILABLE_HI 0x224 +#define CSR_CHANNELS_AVAILABLE_LO 0x228 +#define CSR_BROADCAST_CHANNEL 0x234 +#define CSR_CONFIG_ROM 0x400 +#define CSR_CONFIG_ROM_END 0x800 +#define CSR_FCP_COMMAND 0xB00 +#define CSR_FCP_RESPONSE 0xD00 +#define CSR_FCP_END 0xF00 +#define CSR_TOPOLOGY_MAP 0x1000 +#define CSR_TOPOLOGY_MAP_END 0x1400 +#define CSR_SPEED_MAP 0x2000 +#define CSR_SPEED_MAP_END 0x3000 + #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) #define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args) @@ -227,6 +256,8 @@ extern const struct fw_address_region fw_unit_space_region; int fw_core_add_address_handler(struct fw_address_handler *handler, const struct fw_address_region *region); void fw_core_remove_address_handler(struct fw_address_handler *handler); +void fw_fill_response(struct fw_packet *response, u32 *request_header, + int rcode, void *payload, size_t length); void fw_send_response(struct fw_card *card, struct fw_request *request, int rcode); -- cgit v1.2.3-70-g09d2 From e5f49c3b837ff90c8aec2c6c66c4966080aced06 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 26 Jan 2007 00:38:34 -0500 Subject: firewire: Sanitize send error codes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the negative errnos and use RCODEs for all error codes in the complete transaction callback. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 20 ++++++++++---------- drivers/firewire/fw-transaction.c | 12 ++++++------ drivers/firewire/fw-transaction.h | 2 ++ 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index ac6c018de0d..58bc85dd791 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -376,7 +376,7 @@ at_context_setup_packet(struct at_context *ctx, struct list_head *list) packet->payload_length, DMA_TO_DEVICE); if (packet->payload_bus == 0) { - complete_transmission(packet, -ENOMEM, list); + complete_transmission(packet, RCODE_SEND_ERROR, list); return; } @@ -438,7 +438,7 @@ at_context_setup_packet(struct at_context *ctx, struct list_head *list) /* We dont return error codes from this function; all * transmission errors are reported through the * callback. */ - complete_transmission(packet, -ESTALE, list); + complete_transmission(packet, RCODE_GENERATION, list); } } @@ -484,26 +484,26 @@ static void at_context_tasklet(unsigned long data) switch (evt) { case OHCI1394_evt_timeout: /* Async response transmit timed out. */ - complete_transmission(packet, -ETIMEDOUT, &list); + complete_transmission(packet, RCODE_CANCELLED, &list); break; case OHCI1394_evt_flushed: /* The packet was flushed should give same * error as when we try to use a stale * generation count. */ - complete_transmission(packet, -ESTALE, &list); + complete_transmission(packet, + RCODE_GENERATION, &list); break; case OHCI1394_evt_missing_ack: - /* This would be a higher level software - * error, it is using a valid (current) - * generation count, but the node is not on - * the bus. */ - complete_transmission(packet, -ENODEV, &list); + /* Using a valid (current) generation count, + * but the node is not on the bus or not + * sending acks. */ + complete_transmission(packet, RCODE_NO_ACK, &list); break; default: - complete_transmission(packet, -EIO, &list); + complete_transmission(packet, RCODE_SEND_ERROR, &list); break; } } else diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 780ed2b4498..8387c8ea673 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -93,15 +93,15 @@ transmit_complete_callback(struct fw_packet *packet, close_transaction(t, card, RCODE_BUSY, NULL, 0); break; case ACK_DATA_ERROR: + close_transaction(t, card, RCODE_DATA_ERROR, NULL, 0); + break; case ACK_TYPE_ERROR: - close_transaction(t, card, RCODE_SEND_ERROR, NULL, 0); + close_transaction(t, card, RCODE_TYPE_ERROR, NULL, 0); break; default: - /* FIXME: In this case, status is a negative errno, - * corresponding to an OHCI specific transmit error - * code. We should map that to an RCODE instead of - * just the generic RCODE_SEND_ERROR. */ - close_transaction(t, card, RCODE_SEND_ERROR, NULL, 0); + /* In this case the ack is really a juju specific + * rcode, so just forward that to the callback. */ + close_transaction(t, card, status, NULL, 0); break; } } diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index fb46ef78a32..ad7ba32755e 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -87,6 +87,8 @@ #define RCODE_SEND_ERROR 0x10 #define RCODE_CANCELLED 0x11 #define RCODE_BUSY 0x12 +#define RCODE_GENERATION 0x13 +#define RCODE_NO_ACK 0x14 #define RETRY_1 0x00 #define RETRY_X 0x01 -- cgit v1.2.3-70-g09d2 From 931c4834c8d1e1bf0dcc256b89449a01711f970d Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 26 Jan 2007 00:38:45 -0500 Subject: firewire: Implement compliant bus management. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 127 ++++++++++++++++++++++++++++++++------ drivers/firewire/fw-device.c | 2 + drivers/firewire/fw-topology.c | 7 +-- drivers/firewire/fw-transaction.h | 6 +- 4 files changed, 117 insertions(+), 25 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 307c8b85138..f94874ce58a 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -92,7 +92,7 @@ generate_config_rom (struct fw_card *card, size_t *config_rom_length) bib_generation(card->config_rom_generation++ % 14 + 2) | bib_max_rom(2) | bib_max_receive(card->max_receive) | - bib_isc | bib_cmc | bib_imc; + bib_bmc | bib_isc | bib_cmc | bib_imc; config_rom[3] = card->guid >> 32; config_rom[4] = card->guid; @@ -190,48 +190,137 @@ static const char gap_count_table[] = { 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 }; +struct bm_data { + struct fw_transaction t; + struct { + __be32 arg; + __be32 data; + } lock; + u32 old; + int rcode; + struct completion done; +}; + static void -fw_card_irm_work(struct work_struct *work) +complete_bm_lock(struct fw_card *card, int rcode, + void *payload, size_t length, void *data) +{ + struct bm_data *bmd = data; + + if (rcode == RCODE_COMPLETE) + bmd->old = be32_to_cpu(*(__be32 *) payload); + bmd->rcode = rcode; + complete(&bmd->done); +} + +static void +fw_card_bm_work(struct work_struct *work) { struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_device *root; + struct bm_data bmd; unsigned long flags; - int root_id, new_irm_id, gap_count, generation, do_reset = 0; - - /* FIXME: This simple bus management unconditionally picks a - * cycle master if the current root can't do it. We need to - * not do this if there is a bus manager already. Also, some - * hubs set the contender bit, which is bogus, so we should - * probably do a little sanity check on the IRM (like, read - * the bandwidth register) if it's not us. */ + int root_id, new_root_id, irm_id, gap_count, generation, grace; + int do_reset = 0; spin_lock_irqsave(&card->lock, flags); generation = card->generation; root = card->root_node->data; root_id = card->root_node->node_id; + grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); + + if (card->bm_generation + 1 == generation || + (card->bm_generation != generation && grace)) { + /* This first step is to figure out who is IRM and + * 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 + * next generation. */ + + irm_id = card->irm_node->node_id; + if (!card->irm_node->link_on) { + new_root_id = card->local_node->node_id; + fw_notify("IRM has link off, making local node (%02x) root.\n", + new_root_id); + goto pick_me; + } + + bmd.lock.arg = cpu_to_be32(0x3f); + bmd.lock.data = cpu_to_be32(card->local_node->node_id); + + spin_unlock_irqrestore(&card->lock, flags); + + init_completion(&bmd.done); + fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP, + irm_id, generation, + SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, + &bmd.lock, sizeof bmd.lock, + complete_bm_lock, &bmd); + wait_for_completion(&bmd.done); + + if (bmd.rcode == RCODE_GENERATION) { + /* Another bus reset happened. Just return, + * the BM work has been rescheduled. */ + return; + } + + if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) + /* Somebody else is BM, let them do the work. */ + return; + + spin_lock_irqsave(&card->lock, flags); + if (bmd.rcode != RCODE_COMPLETE) { + /* The lock request failed, maybe the IRM + * isn't really IRM capable after all. Let's + * do a bus reset and pick the local node as + * root, and thus, IRM. */ + new_root_id = card->local_node->node_id; + fw_notify("BM lock failed, making local node (%02x) root.\n", + new_root_id); + goto pick_me; + } + } else if (card->bm_generation != generation) { + /* OK, we weren't BM in the last generation, and it's + * less than 100ms since last bus reset. Reschedule + * this task 100ms from now. */ + spin_unlock_irqrestore(&card->lock, flags); + schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); + return; + } + + /* We're bus manager for this generation, so next step is to + * make sure we have an active cycle master and do gap count + * optimization. */ + card->bm_generation = generation; if (root == NULL) { /* Either link_on is false, or we failed to read the * config rom. In either case, pick another root. */ - new_irm_id = card->local_node->node_id; + new_root_id = card->local_node->node_id; } else if (root->state != FW_DEVICE_RUNNING) { /* If we haven't probed this device yet, bail out now * and let's try again once that's done. */ - new_irm_id = root_id; + spin_unlock_irqrestore(&card->lock, flags); + return; } else if (root->config_rom[2] & bib_cmc) { /* FIXME: I suppose we should set the cmstr bit in the * STATE_CLEAR register of this node, as described in * 1394-1995, 8.4.2.6. Also, send out a force root * packet for this node. */ - new_irm_id = root_id; + new_root_id = root_id; } else { /* Current root has an active link layer and we * successfully read the config rom, but it's not * cycle master capable. */ - new_irm_id = card->local_node->node_id; + new_root_id = card->local_node->node_id; } + pick_me: /* Now figure out what gap count to set. */ if (card->topology_type == FW_TOPOLOGY_A && card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) @@ -243,16 +332,16 @@ fw_card_irm_work(struct work_struct *work) * done less that 5 resets with the same physical topology and we * have either a new root or a new gap count setting, let's do it. */ - if (card->irm_retries++ < 5 && - (card->gap_count != gap_count || new_irm_id != root_id)) + if (card->bm_retries++ < 5 && + (card->gap_count != gap_count || new_root_id != root_id)) do_reset = 1; spin_unlock_irqrestore(&card->lock, flags); if (do_reset) { fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", - card->index, new_irm_id, gap_count); - fw_send_phy_config(card, new_irm_id, generation, gap_count); + card->index, new_root_id, gap_count); + fw_send_phy_config(card, new_root_id, generation, gap_count); fw_core_initiate_bus_reset(card, 1); } } @@ -294,7 +383,7 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, card->local_node = NULL; - INIT_DELAYED_WORK(&card->work, fw_card_irm_work); + INIT_DELAYED_WORK(&card->work, fw_card_bm_work); card->card_device.bus = &fw_bus_type; card->card_device.release = release_card; diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index d71824bb61c..4ea8d4d08a6 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -449,6 +449,8 @@ static void fw_device_init(struct work_struct *work) } else { fw_notify("giving up on config rom for node id %x\n", device->node_id); + if (device->node == device->card->root_node) + schedule_delayed_work(&device->card->work, 0); fw_device_release(&device->device); } return; diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index fc8f1e7d3b0..27c6cb9c836 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -476,12 +476,13 @@ fw_core_handle_bus_reset(struct fw_card *card, * changed, either nodes were added or removed. In that case we * reset the IRM reset counter. */ if (card->self_id_count != self_id_count) - card->irm_retries = 0; + card->bm_retries = 0; card->node_id = node_id; card->self_id_count = self_id_count; card->generation = generation; memcpy(card->self_ids, self_ids, self_id_count * 4); + card->reset_jiffies = jiffies; local_node = build_tree(card); @@ -497,9 +498,7 @@ fw_core_handle_bus_reset(struct fw_card *card, update_tree(card, local_node); } - /* If we're not the root node, we may have to do some IRM work. */ - if (card->local_node != card->root_node) - schedule_delayed_work(&card->work, 0); + schedule_delayed_work(&card->work, 0); spin_unlock_irqrestore(&card->lock, flags); } diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index ad7ba32755e..50ec2c683a3 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -276,6 +276,7 @@ struct fw_card { int current_tlabel, tlabel_mask; struct list_head transaction_list; struct timer_list flush_timer; + unsigned long reset_jiffies; unsigned long long guid; int max_receive; @@ -301,9 +302,10 @@ struct fw_card { struct list_head link; - /* Work struct for IRM duties. */ + /* Work struct for BM duties. */ struct delayed_work work; - int irm_retries; + int bm_retries; + int bm_generation; }; struct fw_card *fw_card_get(struct fw_card *card); -- cgit v1.2.3-70-g09d2 From 730c32f58ba81b3a4fe6d19c7d9e9829dd96d363 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Tue, 6 Feb 2007 14:49:32 -0500 Subject: firewire: Implement proper transaction cancelation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers such as fw-sbp2 had no way to properly cancel in-progress transactions, which could leave a pending transaction or an unset packet in the low-level queues after kfree'ing the containing structure. fw_cancel_transaction() lets drivers cancel a submitted transaction. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 7 +++++ drivers/firewire/fw-ohci.c | 33 ++++++++++++++++++++++++ drivers/firewire/fw-sbp2.c | 3 +++ drivers/firewire/fw-transaction.c | 54 ++++++++++++++++++++++++++++++++++----- drivers/firewire/fw-transaction.h | 5 ++++ 5 files changed, 95 insertions(+), 7 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 7f5dc43ec13..f785b100528 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -474,6 +474,12 @@ dummy_send_response(struct fw_card *card, struct fw_packet *packet) packet->callback(packet, card, -ENODEV); } +static int +dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) +{ + return -ENOENT; +} + static int dummy_enable_phys_dma(struct fw_card *card, int node_id, int generation) @@ -487,6 +493,7 @@ static struct fw_card_driver dummy_driver = { .update_phy_reg = dummy_update_phy_reg, .set_config_rom = dummy_set_config_rom, .send_request = dummy_send_request, + .cancel_packet = dummy_cancel_packet, .send_response = dummy_send_response, .enable_phys_dma = dummy_enable_phys_dma, }; diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 02b2b69c874..e6fa3496183 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -79,6 +79,7 @@ struct at_context { struct fw_ohci *ohci; dma_addr_t descriptor_bus; dma_addr_t buffer_bus; + struct fw_packet *current_packet; struct list_head list; @@ -489,6 +490,7 @@ at_context_setup_packet(struct at_context *ctx, struct list_head *list) ctx->descriptor_bus | z); reg_write(ctx->ohci, control_set(ctx->regs), CONTEXT_RUN | CONTEXT_WAKE); + ctx->current_packet = packet; } else { /* We dont return error codes from this function; all * transmission errors are reported through the @@ -524,6 +526,12 @@ static void at_context_tasklet(unsigned long data) at_context_stop(ctx); + /* If the head of the list isn't the packet that just got + * transmitted, the packet got cancelled before we finished + * transmitting it. */ + if (ctx->current_packet != packet) + goto skip_to_next; + if (packet->payload_length > 0) { dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); @@ -564,6 +572,7 @@ static void at_context_tasklet(unsigned long data) } else complete_transmission(packet, evt - 16, &list); + skip_to_next: /* If more packets are queued, set up the next one. */ if (!list_empty(&ctx->list)) at_context_setup_packet(ctx, &list); @@ -1012,6 +1021,29 @@ static void ohci_send_response(struct fw_card *card, struct fw_packet *packet) at_context_transmit(&ohci->at_response_ctx, packet); } +static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) +{ + struct fw_ohci *ohci = fw_ohci(card); + LIST_HEAD(list); + unsigned long flags; + + spin_lock_irqsave(&ohci->lock, flags); + + if (packet->ack == 0) { + fw_notify("cancelling packet %p (header[0]=%08x)\n", + packet, packet->header[0]); + + complete_transmission(packet, RCODE_CANCELLED, &list); + } + + spin_unlock_irqrestore(&ohci->lock, flags); + + do_packet_callbacks(ohci, &list); + + /* Return success if we actually cancelled something. */ + return list_empty(&list) ? -ENOENT : 0; +} + static int ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) { @@ -1339,6 +1371,7 @@ static const struct fw_card_driver ohci_driver = { .set_config_rom = ohci_set_config_rom, .send_request = ohci_send_request, .send_response = ohci_send_response, + .cancel_packet = ohci_cancel_packet, .enable_phys_dma = ohci_enable_phys_dma, .allocate_iso_context = ohci_allocate_iso_context, diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 54cad3a5dfb..bb133398fee 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -348,6 +348,9 @@ static void sbp2_cancel_orbs(struct fw_unit *unit) spin_unlock_irqrestore(&device->card->lock, flags); list_for_each_entry_safe(orb, next, &list, link) { + if (fw_cancel_transaction(device->card, &orb->t) == 0) + continue; + orb->rcode = RCODE_CANCELLED; orb->callback(orb, NULL); } diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index fb3b77e1bb2..5394569a1c8 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -59,20 +59,52 @@ #define phy_config_root_id(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) #define phy_identifier(id) ((id) << 30) -static void -close_transaction(struct fw_transaction *t, struct fw_card *card, int rcode, - u32 * payload, size_t length) +static int +close_transaction(struct fw_transaction *transaction, + struct fw_card *card, int rcode, + u32 *payload, size_t length) { + struct fw_transaction *t; unsigned long flags; spin_lock_irqsave(&card->lock, flags); - card->tlabel_mask &= ~(1 << t->tlabel); - list_del(&t->link); + list_for_each_entry(t, &card->transaction_list, link) { + if (t == transaction) { + list_del(&t->link); + card->tlabel_mask &= ~(1 << t->tlabel); + break; + } + } spin_unlock_irqrestore(&card->lock, flags); - t->callback(card, rcode, payload, length, t->callback_data); + if (&t->link != &card->transaction_list) { + t->callback(card, rcode, payload, length, t->callback_data); + return 0; + } + + return -ENOENT; } +/* Only valid for transactions that are potentially pending (ie have + * been sent). */ +int +fw_cancel_transaction(struct fw_card *card, + struct fw_transaction *transaction) +{ + /* Cancel the packet transmission if it's still queued. That + * will call the packet transmission callback which cancels + * the transaction. */ + + if (card->driver->cancel_packet(card, &transaction->packet) == 0) + return 0; + + /* If the request packet has already been sent, we need to see + * if the transaction is still pending and remove it in that case. */ + + return close_transaction(transaction, card, RCODE_CANCELLED, NULL, 0); +} +EXPORT_SYMBOL(fw_cancel_transaction); + static void transmit_complete_callback(struct fw_packet *packet, struct fw_card *card, int status) @@ -162,6 +194,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, packet->speed = speed; packet->generation = generation; + packet->ack = 0; } /** @@ -298,8 +331,14 @@ void fw_flush_transactions(struct fw_card *card) card->tlabel_mask = 0; spin_unlock_irqrestore(&card->lock, flags); - list_for_each_entry_safe(t, next, &list, link) + list_for_each_entry_safe(t, next, &list, link) { + card->driver->cancel_packet(card, &t->packet); + + /* At this point cancel_packet will never call the + * transaction callback, since we just took all the + * transactions out of the list. So do it here.*/ t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data); + } } static struct fw_address_handler * @@ -531,6 +570,7 @@ allocate_request(struct fw_packet *p) request->response.speed = p->speed; request->response.timestamp = t; request->response.generation = p->generation; + request->response.ack = 0; request->response.callback = free_response_callback; request->ack = p->ack; request->length = length; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 50ec2c683a3..8f0283cf1a7 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -391,6 +391,8 @@ struct fw_card_driver { void (*send_request) (struct fw_card *card, struct fw_packet *packet); void (*send_response) (struct fw_card *card, struct fw_packet *packet); + /* Calling cancel is valid once a packet has been submitted. */ + int (*cancel_packet) (struct fw_card *card, struct fw_packet *packet); /* Allow the specified node ID to do direct DMA out and in of * host memory. The card will disable this for all node when @@ -421,6 +423,9 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, void *data, size_t length, fw_transaction_callback_t callback, void *callback_data); +int fw_cancel_transaction(struct fw_card *card, + struct fw_transaction *transaction); + void fw_flush_transactions(struct fw_card *card); void fw_send_phy_config(struct fw_card *card, -- cgit v1.2.3-70-g09d2 From 9aad8125389a7a2990dee72d7892e22330a945eb Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:38 -0500 Subject: firewire: Split the iso buffer out from fw_iso_context and avoid vmalloc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch splits out the iso buffer so we can initialize it at mmap time with the size provided in the mmap call. Furthermore, allocate the backing pages using alloc_page to avoid setting up kernel side virtual memory mappings for the pages. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 65 +++++++++++++++------ drivers/firewire/fw-device-cdev.h | 2 +- drivers/firewire/fw-iso.c | 118 +++++++++++++++++++++----------------- drivers/firewire/fw-ohci.c | 12 ++-- drivers/firewire/fw-transaction.h | 38 +++++++++--- 5 files changed, 151 insertions(+), 84 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 1b9e5f7c012..6284375c639 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -71,8 +71,10 @@ struct client { struct list_head event_list; struct semaphore event_list_sem; wait_queue_head_t wait; - unsigned long vm_start; + struct fw_iso_context *iso_context; + struct fw_iso_buffer buffer; + unsigned long vm_start; }; static inline void __user * @@ -406,7 +408,6 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) client->iso_context = fw_iso_context_create(client->device->card, FW_ISO_CONTEXT_TRANSMIT, - request.buffer_size, iso_callback, client); if (IS_ERR(client->iso_context)) return PTR_ERR(client->iso_context); @@ -418,8 +419,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) { struct fw_cdev_queue_iso request; struct fw_cdev_iso_packet __user *p, *end, *next; - void *payload, *payload_end; - unsigned long index; + unsigned long payload, payload_end; int count; struct { struct fw_iso_packet packet; @@ -434,20 +434,17 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) /* If the user passes a non-NULL data pointer, has mmap()'ed * the iso buffer, and the pointer points inside the buffer, * we setup the payload pointers accordingly. Otherwise we - * set them both to NULL, which will still let packets with + * set them both to 0, which will still let packets with * payload_length == 0 through. In other words, if no packets * use the indirect payload, the iso buffer need not be mapped * and the request.data pointer is ignored.*/ - index = (unsigned long)request.data - client->vm_start; - if (request.data != 0 && client->vm_start != 0 && - index <= client->iso_context->buffer_size) { - payload = client->iso_context->buffer + index; - payload_end = client->iso_context->buffer + - client->iso_context->buffer_size; - } else { - payload = NULL; - payload_end = NULL; + payload = (unsigned long)request.data - client->vm_start; + payload_end = payload + (client->buffer.page_count << PAGE_SHIFT); + if (request.data == 0 || client->buffer.pages == NULL || + payload >= payload_end) { + payload = 0; + payload_end = 0; } if (!access_ok(VERIFY_READ, request.packets, request.size)) @@ -473,7 +470,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) return -EINVAL; if (fw_iso_context_queue(client->iso_context, - &u.packet, payload)) + &u.packet, &client->buffer, payload)) break; p = next; @@ -483,8 +480,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) request.size -= uptr_to_u64(p) - request.packets; request.packets = uptr_to_u64(p); - request.data = - client->vm_start + (payload - client->iso_context->buffer); + request.data = client->vm_start + payload; if (copy_to_user(arg, &request, sizeof request)) return -EFAULT; @@ -549,13 +545,41 @@ fw_device_op_compat_ioctl(struct file *file, static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) { struct client *client = file->private_data; + enum dma_data_direction direction; + unsigned long size; + int page_count, retval; + + /* FIXME: We could support multiple buffers, but we don't. */ + if (client->buffer.pages != NULL) + return -EBUSY; + + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; - if (client->iso_context->buffer == NULL) + if (vma->vm_start & ~PAGE_MASK) return -EINVAL; client->vm_start = vma->vm_start; + size = vma->vm_end - vma->vm_start; + page_count = size >> PAGE_SHIFT; + if (size & ~PAGE_MASK) + return -EINVAL; + + if (vma->vm_flags & VM_WRITE) + direction = DMA_TO_DEVICE; + else + direction = DMA_FROM_DEVICE; + + retval = fw_iso_buffer_init(&client->buffer, client->device->card, + page_count, direction); + if (retval < 0) + return retval; - return remap_vmalloc_range(vma, client->iso_context->buffer, 0); + retval = fw_iso_buffer_map(&client->buffer, vma); + if (retval < 0) + fw_iso_buffer_destroy(&client->buffer, client->device->card); + + return retval; } static int fw_device_op_release(struct inode *inode, struct file *file) @@ -564,6 +588,9 @@ static int fw_device_op_release(struct inode *inode, struct file *file) struct address_handler *h, *next; struct request *r, *next_r; + if (client->buffer.pages) + fw_iso_buffer_destroy(&client->buffer, client->device->card); + if (client->iso_context) fw_iso_context_destroy(client->iso_context); diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index ddbae43ca1a..003cc669551 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -126,7 +126,7 @@ struct fw_cdev_allocate { }; struct fw_cdev_create_iso_context { - __u32 buffer_size; + __u32 handle; }; struct fw_cdev_iso_packet { diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 6481e3df2c9..4e7ba867292 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -28,68 +28,88 @@ #include "fw-topology.h" #include "fw-device.h" -static int -setup_iso_buffer(struct fw_iso_context *ctx, size_t size, - enum dma_data_direction direction) +int +fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, + int page_count, enum dma_data_direction direction) { - struct page *page; - int i, j; - void *p; - - ctx->buffer_size = PAGE_ALIGN(size); - if (size == 0) - return 0; - - ctx->buffer = vmalloc_32_user(ctx->buffer_size); - if (ctx->buffer == NULL) - goto fail_buffer_alloc; - - ctx->page_count = ctx->buffer_size >> PAGE_SHIFT; - ctx->pages = - kzalloc(ctx->page_count * sizeof(ctx->pages[0]), GFP_KERNEL); - if (ctx->pages == NULL) - goto fail_pages_alloc; - - p = ctx->buffer; - for (i = 0; i < ctx->page_count; i++, p += PAGE_SIZE) { - page = vmalloc_to_page(p); - ctx->pages[i] = dma_map_page(ctx->card->device, - page, 0, PAGE_SIZE, direction); - if (dma_mapping_error(ctx->pages[i])) - goto fail_mapping; + int i, j, retval = -ENOMEM; + dma_addr_t address; + + buffer->page_count = page_count; + buffer->direction = direction; + + buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]), + GFP_KERNEL); + if (buffer->pages == NULL) + goto out; + + for (i = 0; i < buffer->page_count; i++) { + buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32); + if (buffer->pages[i] == NULL) + goto out_pages; + + address = dma_map_page(card->device, buffer->pages[i], + 0, PAGE_SIZE, direction); + if (dma_mapping_error(address)) { + __free_page(buffer->pages[i]); + goto out_pages; + } + set_page_private(buffer->pages[i], address); } return 0; - fail_mapping: - for (j = 0; j < i; j++) - dma_unmap_page(ctx->card->device, ctx->pages[j], + out_pages: + for (j = 0; j < i; j++) { + address = page_private(buffer->pages[j]); + dma_unmap_page(card->device, address, PAGE_SIZE, DMA_TO_DEVICE); - fail_pages_alloc: - vfree(ctx->buffer); - fail_buffer_alloc: - return -ENOMEM; + __free_page(buffer->pages[j]); + } + kfree(buffer->pages); + out: + buffer->pages = NULL; + return retval; +} + +int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) +{ + unsigned long uaddr; + int i, retval; + + uaddr = vma->vm_start; + for (i = 0; i < buffer->page_count; i++) { + retval = vm_insert_page(vma, uaddr, buffer->pages[i]); + if (retval) + return retval; + uaddr += PAGE_SIZE; + } + + return 0; } -static void destroy_iso_buffer(struct fw_iso_context *ctx) +void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, + struct fw_card *card) { int i; + dma_addr_t address; - for (i = 0; i < ctx->page_count; i++) - dma_unmap_page(ctx->card->device, ctx->pages[i], + for (i = 0; i < buffer->page_count; i++) { + address = page_private(buffer->pages[i]); + dma_unmap_page(card->device, address, PAGE_SIZE, DMA_TO_DEVICE); + __free_page(buffer->pages[i]); + } - kfree(ctx->pages); - vfree(ctx->buffer); + kfree(buffer->pages); + buffer->pages = NULL; } struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type, - size_t buffer_size, fw_iso_callback_t callback, void *callback_data) { struct fw_iso_context *ctx; - int retval; ctx = card->driver->allocate_iso_context(card, type); if (IS_ERR(ctx)) @@ -100,12 +120,6 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type, ctx->callback = callback; ctx->callback_data = callback_data; - retval = setup_iso_buffer(ctx, buffer_size, DMA_TO_DEVICE); - if (retval < 0) { - card->driver->free_iso_context(ctx); - return ERR_PTR(retval); - } - return ctx; } EXPORT_SYMBOL(fw_iso_context_create); @@ -114,8 +128,6 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx) { struct fw_card *card = ctx->card; - destroy_iso_buffer(ctx); - card->driver->free_iso_context(ctx); } EXPORT_SYMBOL(fw_iso_context_destroy); @@ -133,10 +145,12 @@ EXPORT_SYMBOL(fw_iso_context_send); int fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, void *payload) + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct fw_card *card = ctx->card; - return card->driver->queue_iso(ctx, packet, payload); + return card->driver->queue_iso(ctx, packet, buffer, payload); } EXPORT_SYMBOL(fw_iso_context_queue); diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 72f80361fc4..8499d70bf9e 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1251,14 +1251,16 @@ static void ohci_free_iso_context(struct fw_iso_context *base) static int ohci_queue_iso(struct fw_iso_context *base, - struct fw_iso_packet *packet, void *payload) + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct iso_context *ctx = (struct iso_context *)base; struct fw_ohci *ohci = fw_ohci(ctx->base.card); struct descriptor *d, *end, *last, *tail, *pd; struct fw_iso_packet *p; __le32 *header; - dma_addr_t d_bus; + dma_addr_t d_bus, page_bus; u32 z, header_z, payload_z, irq; u32 payload_index, payload_end_index, next_page_index; int index, page, end_page, i, length, offset; @@ -1267,7 +1269,7 @@ ohci_queue_iso(struct fw_iso_context *base, * packet, retransmit or terminate.. */ p = packet; - payload_index = payload - ctx->base.buffer; + payload_index = payload; d = ctx->head_descriptor; tail = ctx->tail_descriptor; end = ctx->buffer + ISO_BUFFER_SIZE / sizeof(struct descriptor); @@ -1337,7 +1339,9 @@ ohci_queue_iso(struct fw_iso_context *base, length = min(next_page_index, payload_end_index) - payload_index; pd[i].req_count = cpu_to_le16(length); - pd[i].data_address = cpu_to_le32(ctx->base.pages[page] + offset); + + page_bus = page_private(buffer->pages[page]); + pd[i].data_address = cpu_to_le32(page_bus + offset); payload_index += length; } diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 8f0283cf1a7..89c6dda2793 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -27,6 +27,7 @@ #include #include #include +#include #define TCODE_WRITE_QUADLET_REQUEST 0 #define TCODE_WRITE_BLOCK_REQUEST 1 @@ -336,6 +337,18 @@ struct fw_iso_context; typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, int status, u32 cycle, void *data); +/* An iso buffer is just a set of pages mapped for DMA in the + * specified direction. Since the pages are to be used for DMA, they + * are not mapped into the kernel virtual address space. We store the + * DMA address in the page private. The helper function + * fw_iso_buffer_map() will map the pages into a given vma. */ + +struct fw_iso_buffer { + enum dma_data_direction direction; + struct page **pages; + int page_count; +}; + struct fw_iso_context { struct fw_card *card; int type; @@ -343,19 +356,24 @@ struct fw_iso_context { int speed; fw_iso_callback_t callback; void *callback_data; - - void *buffer; - size_t buffer_size; - dma_addr_t *pages; - int page_count; }; +int +fw_iso_buffer_init(struct fw_iso_buffer *buffer, + struct fw_card *card, + int page_count, + enum dma_data_direction direction); +int +fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); +void +fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); + struct fw_iso_context * fw_iso_context_create(struct fw_card *card, int type, - size_t buffer_size, fw_iso_callback_t callback, void *callback_data); + void fw_iso_context_destroy(struct fw_iso_context *ctx); @@ -365,7 +383,9 @@ fw_iso_context_start(struct fw_iso_context *ctx, int fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, void *payload); + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload); int fw_iso_context_send(struct fw_iso_context *ctx, @@ -410,7 +430,9 @@ struct fw_card_driver { int (*send_iso)(struct fw_iso_context *ctx, s32 cycle); int (*queue_iso)(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, void *payload); + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload); }; int -- cgit v1.2.3-70-g09d2 From 295e3feb92e5073ec32a3c626302d4b92c4c8a95 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:40 -0500 Subject: firewire: Implement basic isochronous receive functionality. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 23 +++++- drivers/firewire/fw-device-cdev.h | 5 ++ drivers/firewire/fw-iso.c | 7 +- drivers/firewire/fw-ohci.c | 168 +++++++++++++++++++++++++++++++++----- drivers/firewire/fw-ohci.h | 1 + drivers/firewire/fw-transaction.h | 7 +- 6 files changed, 181 insertions(+), 30 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 6284375c639..1101ccd9b9c 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -406,8 +406,12 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) if (copy_from_user(&request, arg, sizeof request)) return -EFAULT; + if (request.type > FW_ISO_CONTEXT_RECEIVE) + return -EINVAL; + client->iso_context = fw_iso_context_create(client->device->card, - FW_ISO_CONTEXT_TRANSMIT, + request.type, + request.header_size, iso_callback, client); if (IS_ERR(client->iso_context)) return PTR_ERR(client->iso_context); @@ -419,7 +423,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) { struct fw_cdev_queue_iso request; struct fw_cdev_iso_packet __user *p, *end, *next; - unsigned long payload, payload_end; + unsigned long payload, payload_end, header_length; int count; struct { struct fw_iso_packet packet; @@ -456,12 +460,23 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) while (p < end) { if (__copy_from_user(&u.packet, p, sizeof *p)) return -EFAULT; + + if (client->iso_context->type == FW_ISO_CONTEXT_TRANSMIT) { + header_length = u.packet.header_length; + } else { + /* We require that header_length is a multiple of + * the fixed header size, ctx->header_size */ + if (u.packet.header_length % client->iso_context->header_size != 0) + return -EINVAL; + header_length = 0; + } + next = (struct fw_cdev_iso_packet __user *) - &p->header[u.packet.header_length / 4]; + &p->header[header_length / 4]; if (next > end) return -EINVAL; if (__copy_from_user - (u.packet.header, p->header, u.packet.header_length)) + (u.packet.header, p->header, header_length)) return -EFAULT; if (u.packet.skip && u.packet.header_length + u.packet.payload_length > 0) diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 003cc669551..4e766ec6cd3 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -125,7 +125,12 @@ struct fw_cdev_allocate { __u32 length; }; +#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 +#define FW_CDEV_ISO_CONTEXT_RECEIVE 1 + struct fw_cdev_create_iso_context { + __u32 type; + __u32 header_size; __u32 handle; }; diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 4e7ba867292..4c6dc99a1ff 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -105,9 +105,9 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, buffer->pages = NULL; } -struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type, - fw_iso_callback_t callback, - void *callback_data) +struct fw_iso_context * +fw_iso_context_create(struct fw_card *card, int type, size_t header_size, + fw_iso_callback_t callback, void *callback_data) { struct fw_iso_context *ctx; @@ -117,6 +117,7 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type, ctx->card = card; ctx->type = type; + ctx->header_size = header_size; ctx->callback = callback; ctx->callback_data = callback_data; diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 86fe55cff28..90db5a4f3ae 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -45,6 +45,7 @@ #define descriptor_irq_error (1 << 4) #define descriptor_irq_always (3 << 4) #define descriptor_branch_always (3 << 2) +#define descriptor_wait (3 << 0) struct descriptor { __le16 req_count; @@ -55,6 +56,20 @@ struct descriptor { __le16 transfer_status; } __attribute__((aligned(16))); +struct db_descriptor { + __le16 first_size; + __le16 control; + __le16 second_req_count; + __le16 first_req_count; + __le32 branch_address; + __le16 second_res_count; + __le16 first_res_count; + __le32 reserved0; + __le32 first_buffer; + __le32 second_buffer; + __le32 reserved1; +} __attribute__((aligned(16))); + #define control_set(regs) (regs) #define control_clear(regs) ((regs) + 4) #define command_ptr(regs) ((regs) + 12) @@ -171,7 +186,12 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) return container_of(card, struct fw_ohci, card); } -#define CONTEXT_CYCLE_MATCH_ENABLE 0x80000000 +#define IT_CONTEXT_CYCLE_MATCH_ENABLE 0x80000000 +#define IR_CONTEXT_BUFFER_FILL 0x80000000 +#define IR_CONTEXT_ISOCH_HEADER 0x40000000 +#define IR_CONTEXT_CYCLE_MATCH_ENABLE 0x20000000 +#define IR_CONTEXT_MULTI_CHANNEL_MODE 0x10000000 +#define IR_CONTEXT_DUAL_BUFFER_MODE 0x08000000 #define CONTEXT_RUN 0x8000 #define CONTEXT_WAKE 0x1000 @@ -518,14 +538,14 @@ context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus) return d; } -static void context_run(struct context *ctx, u32 cycle_match) +static void context_run(struct context *ctx, u32 extra) { struct fw_ohci *ohci = ctx->ohci; reg_write(ohci, command_ptr(ctx->regs), le32_to_cpu(ctx->tail_descriptor_last->branch_address)); reg_write(ohci, control_clear(ctx->regs), ~0); - reg_write(ohci, control_set(ctx->regs), CONTEXT_RUN | cycle_match); + reg_write(ohci, control_set(ctx->regs), CONTEXT_RUN | extra); flush_writes(ohci); } @@ -1240,11 +1260,25 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) return retval; } -static void ir_context_tasklet(unsigned long data) +static int handle_ir_packet(struct context *context, + struct descriptor *d, + struct descriptor *last) { - struct iso_context *ctx = (struct iso_context *)data; + struct iso_context *ctx = + container_of(context, struct iso_context, context); + struct db_descriptor *db = (struct db_descriptor *) d; + + if (db->first_res_count > 0 && db->second_res_count > 0) + /* This descriptor isn't done yet, stop iteration. */ + return 0; + + if (le16_to_cpu(db->control) & descriptor_irq_always) + /* FIXME: we should pass payload address here. */ + ctx->base.callback(&ctx->base, + 0, 0, + ctx->base.callback_data); - (void)ctx; + return 1; } #define ISO_BUFFER_SIZE (64 * 1024) @@ -1274,7 +1308,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type) struct fw_ohci *ohci = fw_ohci(card); struct iso_context *ctx, *list; descriptor_callback_t callback; - u32 *mask; + u32 *mask, regs; unsigned long flags; int index, retval; @@ -1283,7 +1317,9 @@ ohci_allocate_iso_context(struct fw_card *card, int type) list = ohci->it_context_list; callback = handle_it_packet; } else { - return ERR_PTR(-EINVAL); + mask = &ohci->ir_context_mask; + list = ohci->ir_context_list; + callback = handle_ir_packet; } spin_lock_irqsave(&ohci->lock, flags); @@ -1295,10 +1331,15 @@ ohci_allocate_iso_context(struct fw_card *card, int type) if (index < 0) return ERR_PTR(-EBUSY); + if (type == FW_ISO_CONTEXT_TRANSMIT) + regs = OHCI1394_IsoXmitContextBase(index); + else + regs = OHCI1394_IsoRcvContextBase(index); + ctx = &list[index]; memset(ctx, 0, sizeof *ctx); retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE, - OHCI1394_IsoXmitContextBase(index), callback); + regs, callback); if (retval < 0) { spin_lock_irqsave(&ohci->lock, flags); *mask |= 1 << index; @@ -1316,13 +1357,24 @@ static int ohci_send_iso(struct fw_iso_context *base, s32 cycle) u32 cycle_match = 0; int index; - index = ctx - ohci->it_context_list; - if (cycle > 0) - cycle_match = CONTEXT_CYCLE_MATCH_ENABLE | - (cycle & 0x7fff) << 16; + if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { + index = ctx - ohci->it_context_list; + if (cycle > 0) + cycle_match = IT_CONTEXT_CYCLE_MATCH_ENABLE | + (cycle & 0x7fff) << 16; + + reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index); + reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index); + context_run(&ctx->context, cycle_match); + } else { + index = ctx - ohci->ir_context_list; - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index); - context_run(&ctx->context, cycle_match); + reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); + reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); + reg_write(ohci, context_match(ctx->context.regs), + 0xf0000000 | ctx->base.channel); + context_run(&ctx->context, IR_CONTEXT_DUAL_BUFFER_MODE); + } return 0; } @@ -1355,10 +1407,10 @@ static void ohci_free_iso_context(struct fw_iso_context *base) } static int -ohci_queue_iso(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) +ohci_queue_iso_transmit(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct descriptor *d, *last, *pd; @@ -1451,6 +1503,84 @@ ohci_queue_iso(struct fw_iso_context *base, return 0; } +static int +ohci_queue_iso_receive(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) +{ + struct iso_context *ctx = container_of(base, struct iso_context, base); + struct db_descriptor *db = NULL; + struct descriptor *d; + struct fw_iso_packet *p; + dma_addr_t d_bus, page_bus; + u32 z, header_z, length, rest; + int page, offset; + + /* FIXME: Cycle lost behavior should be configurable: lose + * packet, retransmit or terminate.. */ + + p = packet; + z = 2; + + /* Get header size in number of descriptors. */ + header_z = DIV_ROUND_UP(p->header_length, sizeof *d); + page = payload >> PAGE_SHIFT; + offset = payload & ~PAGE_MASK; + rest = p->payload_length; + + /* FIXME: OHCI 1.0 doesn't support dual buffer receive */ + /* FIXME: handle descriptor_wait */ + /* FIXME: make packet-per-buffer/dual-buffer a context option */ + while (rest > 0) { + d = context_get_descriptors(&ctx->context, + z + header_z, &d_bus); + if (d == NULL) + return -ENOMEM; + + db = (struct db_descriptor *) d; + db->control = cpu_to_le16(descriptor_status | + descriptor_branch_always); + db->first_size = cpu_to_le16(ctx->base.header_size); + db->first_req_count = cpu_to_le16(p->header_length); + db->second_req_count = cpu_to_le16(p->payload_length); + db->first_res_count = cpu_to_le16(db->first_req_count); + db->second_res_count = cpu_to_le16(db->second_req_count); + + db->first_buffer = cpu_to_le32(d_bus + sizeof *db); + + if (offset + rest < PAGE_SIZE) + length = rest; + else + length = PAGE_SIZE - offset; + + page_bus = page_private(buffer->pages[page]); + db->second_buffer = cpu_to_le32(page_bus + offset); + + context_append(&ctx->context, d, z, header_z); + offset = (offset + length) & ~PAGE_MASK; + rest -= length; + page++; + } + + if (p->interrupt) + db->control |= cpu_to_le16(descriptor_irq_always); + + return 0; + } + +static int +ohci_queue_iso(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) +{ + if (base->type == FW_ISO_CONTEXT_TRANSMIT) + return ohci_queue_iso_transmit(base, packet, buffer, payload); + else + return ohci_queue_iso_receive(base, packet, buffer, payload); +} + static const struct fw_card_driver ohci_driver = { .name = ohci_driver_name, .enable = ohci_enable, diff --git a/drivers/firewire/fw-ohci.h b/drivers/firewire/fw-ohci.h index a562305078b..fa15706397d 100644 --- a/drivers/firewire/fw-ohci.h +++ b/drivers/firewire/fw-ohci.h @@ -103,6 +103,7 @@ #define OHCI1394_IsoXmitCommandPtr(n) (0x20C + 16 * (n)) /* Isochronous receive registers */ +#define OHCI1394_IsoRcvContextBase(n) (0x400 + 32 * (n)) #define OHCI1394_IsoRcvContextControlSet(n) (0x400 + 32 * (n)) #define OHCI1394_IsoRcvContextControlClear(n) (0x404 + 32 * (n)) #define OHCI1394_IsoRcvCommandPtr(n) (0x40C + 32 * (n)) diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 89c6dda2793..9e92edad68d 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -354,6 +354,7 @@ struct fw_iso_context { int type; int channel; int speed; + size_t header_size; fw_iso_callback_t callback; void *callback_data; }; @@ -369,10 +370,8 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, - fw_iso_callback_t callback, - void *callback_data); - +fw_iso_context_create(struct fw_card *card, int type, size_t header_size, + fw_iso_callback_t callback, void *callback_data); void fw_iso_context_destroy(struct fw_iso_context *ctx); -- cgit v1.2.3-70-g09d2 From 69cdb7268ca2e644665dae8ea26e35ce4e96679c Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:41 -0500 Subject: firewire: Rename 'send_iso' to 'start_iso'. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 12 ++++++------ drivers/firewire/fw-device-cdev.h | 4 ++-- drivers/firewire/fw-iso.c | 8 ++++---- drivers/firewire/fw-ohci.c | 4 ++-- drivers/firewire/fw-transaction.h | 8 ++------ 5 files changed, 16 insertions(+), 20 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 1101ccd9b9c..b738c997ef3 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -503,15 +503,15 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) return count; } -static int ioctl_send_iso(struct client *client, void __user *arg) +static int ioctl_start_iso(struct client *client, void __user *arg) { - struct fw_cdev_send_iso request; + struct fw_cdev_start_iso request; if (copy_from_user(&request, arg, sizeof request)) return -EFAULT; - return fw_iso_context_send(client->iso_context, request.channel, - request.speed, request.cycle); + return fw_iso_context_start(client->iso_context, request.channel, + request.speed, request.cycle); } static int @@ -530,8 +530,8 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) return ioctl_create_iso_context(client, arg); case FW_CDEV_IOC_QUEUE_ISO: return ioctl_queue_iso(client, arg); - case FW_CDEV_IOC_SEND_ISO: - return ioctl_send_iso(client, arg); + case FW_CDEV_IOC_START_ISO: + return ioctl_start_iso(client, arg); default: return -EINVAL; } diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 4e766ec6cd3..ac91ce501bf 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -97,7 +97,7 @@ struct fw_cdev_event_iso_interrupt { #define FW_CDEV_IOC_SEND_RESPONSE _IO('#', 0x03) #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04) #define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05) -#define FW_CDEV_IOC_SEND_ISO _IO('#', 0x06) +#define FW_CDEV_IOC_START_ISO _IO('#', 0x06) struct fw_cdev_get_config_rom { __u32 length; @@ -150,7 +150,7 @@ struct fw_cdev_queue_iso { __u64 data; }; -struct fw_cdev_send_iso { +struct fw_cdev_start_iso { __u32 channel; __u32 speed; __s32 cycle; diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 4c6dc99a1ff..d84792fe619 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -134,15 +134,15 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx) EXPORT_SYMBOL(fw_iso_context_destroy); int -fw_iso_context_send(struct fw_iso_context *ctx, - int channel, int speed, int cycle) +fw_iso_context_start(struct fw_iso_context *ctx, + int channel, int speed, int cycle) { ctx->channel = channel; ctx->speed = speed; - return ctx->card->driver->send_iso(ctx, cycle); + return ctx->card->driver->start_iso(ctx, cycle); } -EXPORT_SYMBOL(fw_iso_context_send); +EXPORT_SYMBOL(fw_iso_context_start); int fw_iso_context_queue(struct fw_iso_context *ctx, diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 90db5a4f3ae..faa384426a1 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1350,7 +1350,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type) return &ctx->base; } -static int ohci_send_iso(struct fw_iso_context *base, s32 cycle) +static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct fw_ohci *ohci = ctx->context.ohci; @@ -1594,7 +1594,7 @@ static const struct fw_card_driver ohci_driver = { .allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, .queue_iso = ohci_queue_iso, - .send_iso = ohci_send_iso, + .start_iso = ohci_start_iso, }; static int software_reset(struct fw_ohci *ohci) diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 9e92edad68d..9ccbed80ceb 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -376,10 +376,6 @@ fw_iso_context_create(struct fw_card *card, int type, size_t header_size, void fw_iso_context_destroy(struct fw_iso_context *ctx); -void -fw_iso_context_start(struct fw_iso_context *ctx, - int channel, int speed, int cycle); - int fw_iso_context_queue(struct fw_iso_context *ctx, struct fw_iso_packet *packet, @@ -387,7 +383,7 @@ fw_iso_context_queue(struct fw_iso_context *ctx, unsigned long payload); int -fw_iso_context_send(struct fw_iso_context *ctx, +fw_iso_context_start(struct fw_iso_context *ctx, int channel, int speed, int cycle); struct fw_card_driver { @@ -426,7 +422,7 @@ struct fw_card_driver { (*allocate_iso_context)(struct fw_card *card, int type); void (*free_iso_context)(struct fw_iso_context *ctx); - int (*send_iso)(struct fw_iso_context *ctx, s32 cycle); + int (*start_iso)(struct fw_iso_context *ctx, s32 cycle); int (*queue_iso)(struct fw_iso_context *ctx, struct fw_iso_packet *packet, -- cgit v1.2.3-70-g09d2 From b82956685aab4a9d333714300eb8a86fed6c9ab3 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:42 -0500 Subject: firewire: Implement functionality to stop isochronous DMA contexts. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 7 +++++++ drivers/firewire/fw-device-cdev.h | 1 + drivers/firewire/fw-iso.c | 7 +++++++ drivers/firewire/fw-ohci.c | 44 +++++++++++++++++++++++++++++---------- drivers/firewire/fw-transaction.h | 5 +++++ 5 files changed, 53 insertions(+), 11 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index b738c997ef3..1ce33d4f91a 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -514,6 +514,11 @@ static int ioctl_start_iso(struct client *client, void __user *arg) request.speed, request.cycle); } +static int ioctl_stop_iso(struct client *client, void __user *arg) +{ + return fw_iso_context_stop(client->iso_context); +} + static int dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) { @@ -532,6 +537,8 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) return ioctl_queue_iso(client, arg); case FW_CDEV_IOC_START_ISO: return ioctl_start_iso(client, arg); + case FW_CDEV_IOC_STOP_ISO: + return ioctl_stop_iso(client, arg); default: return -EINVAL; } diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index ac91ce501bf..257dc872f46 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -98,6 +98,7 @@ struct fw_cdev_event_iso_interrupt { #define FW_CDEV_IOC_CREATE_ISO_CONTEXT _IO('#', 0x04) #define FW_CDEV_IOC_QUEUE_ISO _IO('#', 0x05) #define FW_CDEV_IOC_START_ISO _IO('#', 0x06) +#define FW_CDEV_IOC_STOP_ISO _IO('#', 0x07) struct fw_cdev_get_config_rom { __u32 length; diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index d84792fe619..1605e115723 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -155,3 +155,10 @@ fw_iso_context_queue(struct fw_iso_context *ctx, return card->driver->queue_iso(ctx, packet, buffer, payload); } EXPORT_SYMBOL(fw_iso_context_queue); + +int +fw_iso_context_stop(struct fw_iso_context *ctx) +{ + return ctx->card->driver->stop_iso(ctx); +} +EXPORT_SYMBOL(fw_iso_context_stop); diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index faa384426a1..c0ab868b9fe 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -570,13 +570,19 @@ static void context_append(struct context *ctx, static void context_stop(struct context *ctx) { u32 reg; + int i; reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN); + flush_writes(ctx->ohci); - reg = reg_read(ctx->ohci, control_set(ctx->regs)); - if (reg & CONTEXT_ACTIVE) - fw_notify("Tried to stop context, but it is still active " - "(0x%08x).\n", reg); + for (i = 0; i < 10; i++) { + reg = reg_read(ctx->ohci, control_set(ctx->regs)); + if ((reg & CONTEXT_ACTIVE) == 0) + break; + + fw_notify("context_stop: still active (0x%08x)\n", reg); + msleep(1); + } } static void @@ -1379,6 +1385,25 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) return 0; } +static int ohci_stop_iso(struct fw_iso_context *base) +{ + struct fw_ohci *ohci = fw_ohci(base->card); + struct iso_context *ctx = container_of(base, struct iso_context, base); + int index; + + if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { + index = ctx - ohci->it_context_list; + reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index); + } else { + index = ctx - ohci->ir_context_list; + reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index); + } + flush_writes(ohci); + context_stop(&ctx->context); + + return 0; +} + static void ohci_free_iso_context(struct fw_iso_context *base) { struct fw_ohci *ohci = fw_ohci(base->card); @@ -1386,22 +1411,18 @@ static void ohci_free_iso_context(struct fw_iso_context *base) unsigned long flags; int index; + ohci_stop_iso(base); + context_release(&ctx->context); + spin_lock_irqsave(&ohci->lock, flags); if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { index = ctx - ohci->it_context_list; - reg_write(ohci, OHCI1394_IsoXmitContextControlClear(index), ~0); - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index); ohci->it_context_mask |= 1 << index; } else { index = ctx - ohci->ir_context_list; - reg_write(ohci, OHCI1394_IsoRcvContextControlClear(index), ~0); - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index); ohci->ir_context_mask |= 1 << index; } - flush_writes(ohci); - - context_release(&ctx->context); spin_unlock_irqrestore(&ohci->lock, flags); } @@ -1595,6 +1616,7 @@ static const struct fw_card_driver ohci_driver = { .free_iso_context = ohci_free_iso_context, .queue_iso = ohci_queue_iso, .start_iso = ohci_start_iso, + .stop_iso = ohci_stop_iso, }; static int software_reset(struct fw_ohci *ohci) diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 9ccbed80ceb..b2a0a030c0f 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -386,6 +386,9 @@ int fw_iso_context_start(struct fw_iso_context *ctx, int channel, int speed, int cycle); +int +fw_iso_context_stop(struct fw_iso_context *ctx); + struct fw_card_driver { const char *name; @@ -428,6 +431,8 @@ struct fw_card_driver { struct fw_iso_packet *packet, struct fw_iso_buffer *buffer, unsigned long payload); + + int (*stop_iso)(struct fw_iso_context *ctx); }; int -- cgit v1.2.3-70-g09d2 From 9b32d5f3074e9b1afaa39a360a59fd77a2214783 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:44 -0500 Subject: firewire: Acummulate received iso headers and send them back to user space. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 25 +++++++++++++------- drivers/firewire/fw-device-cdev.h | 2 ++ drivers/firewire/fw-ohci.c | 49 +++++++++++++++++++++++++++------------ drivers/firewire/fw-transaction.h | 5 +++- 4 files changed, 57 insertions(+), 24 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 1ce33d4f91a..6545fb8214d 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -383,20 +383,24 @@ static int ioctl_send_response(struct client *client, void __user *arg) } static void -iso_callback(struct fw_iso_context *context, int status, u32 cycle, void *data) +iso_callback(struct fw_iso_context *context, u32 cycle, + size_t header_length, void *header, void *data) { struct client *client = data; struct iso_interrupt *interrupt; - interrupt = kzalloc(sizeof *interrupt, GFP_ATOMIC); + interrupt = kzalloc(sizeof *interrupt + header_length, GFP_ATOMIC); if (interrupt == NULL) return; interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; interrupt->interrupt.closure = 0; interrupt->interrupt.cycle = cycle; + interrupt->interrupt.header_length = header_length; + memcpy(interrupt->interrupt.header, header, header_length); queue_event(client, &interrupt->event, - &interrupt->interrupt, sizeof interrupt->interrupt, NULL, 0); + &interrupt->interrupt, + sizeof interrupt->interrupt + header_length, NULL, 0); } static int ioctl_create_iso_context(struct client *client, void __user *arg) @@ -423,6 +427,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) { struct fw_cdev_queue_iso request; struct fw_cdev_iso_packet __user *p, *end, *next; + struct fw_iso_context *ctx = client->iso_context; unsigned long payload, payload_end, header_length; int count; struct { @@ -430,7 +435,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) u8 header[256]; } u; - if (client->iso_context == NULL) + if (ctx == NULL) return -EINVAL; if (copy_from_user(&request, arg, sizeof request)) return -EFAULT; @@ -461,13 +466,17 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) if (__copy_from_user(&u.packet, p, sizeof *p)) return -EFAULT; - if (client->iso_context->type == FW_ISO_CONTEXT_TRANSMIT) { + if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { header_length = u.packet.header_length; } else { /* We require that header_length is a multiple of * the fixed header size, ctx->header_size */ - if (u.packet.header_length % client->iso_context->header_size != 0) + if (ctx->header_size == 0) { + if (u.packet.header_length > 0) + return -EINVAL; + } else if (u.packet.header_length % ctx->header_size != 0) { return -EINVAL; + } header_length = 0; } @@ -484,8 +493,8 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) if (payload + u.packet.payload_length > payload_end) return -EINVAL; - if (fw_iso_context_queue(client->iso_context, - &u.packet, &client->buffer, payload)) + if (fw_iso_context_queue(ctx, &u.packet, + &client->buffer, payload)) break; p = next; diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 257dc872f46..e32b39dc7e7 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -89,6 +89,8 @@ struct fw_cdev_event_iso_interrupt { __u32 type; __u32 cycle; __u64 closure; + __u32 header_length; /* Length in bytes of following headers. */ + __u32 header[0]; }; #define FW_CDEV_IOC_GET_CONFIG_ROM _IOR('#', 0x00, struct fw_cdev_get_config_rom) diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index d601ec7ff4d..b5a154583e0 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -143,6 +143,8 @@ struct at_context { struct iso_context { struct fw_iso_context base; struct context context; + void *header; + size_t header_length; }; #define CONFIG_ROM_SIZE 1024 @@ -501,7 +503,7 @@ context_init(struct context *ctx, struct fw_ohci *ohci, return 0; } - static void +static void context_release(struct context *ctx) { struct fw_card *card = &ctx->ohci->card; @@ -1273,16 +1275,23 @@ static int handle_ir_packet(struct context *context, struct iso_context *ctx = container_of(context, struct iso_context, context); struct db_descriptor *db = (struct db_descriptor *) d; + size_t header_length; if (db->first_res_count > 0 && db->second_res_count > 0) /* This descriptor isn't done yet, stop iteration. */ return 0; - if (le16_to_cpu(db->control) & descriptor_irq_always) - /* FIXME: we should pass payload address here. */ - ctx->base.callback(&ctx->base, - 0, 0, + header_length = db->first_req_count - db->first_res_count; + if (ctx->header_length + header_length <= PAGE_SIZE) + memcpy(ctx->header + ctx->header_length, db + 1, header_length); + ctx->header_length += header_length; + + if (le16_to_cpu(db->control) & descriptor_irq_always) { + ctx->base.callback(&ctx->base, 0, + ctx->header_length, ctx->header, ctx->base.callback_data); + ctx->header_length = 0; + } return 1; } @@ -1301,9 +1310,8 @@ static int handle_it_packet(struct context *context, return 0; if (le16_to_cpu(last->control) & descriptor_irq_always) - ctx->base.callback(&ctx->base, - 0, le16_to_cpu(last->res_count), - ctx->base.callback_data); + ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count), + 0, NULL, ctx->base.callback_data); return 1; } @@ -1316,7 +1324,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type) descriptor_callback_t callback; u32 *mask, regs; unsigned long flags; - int index, retval; + int index, retval = -ENOMEM; if (type == FW_ISO_CONTEXT_TRANSMIT) { mask = &ohci->it_context_mask; @@ -1344,16 +1352,26 @@ ohci_allocate_iso_context(struct fw_card *card, int type) ctx = &list[index]; memset(ctx, 0, sizeof *ctx); + ctx->header_length = 0; + ctx->header = (void *) __get_free_page(GFP_KERNEL); + if (ctx->header == NULL) + goto out; + retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE, regs, callback); - if (retval < 0) { - spin_lock_irqsave(&ohci->lock, flags); - *mask |= 1 << index; - spin_unlock_irqrestore(&ohci->lock, flags); - return ERR_PTR(retval); - } + if (retval < 0) + goto out_with_header; return &ctx->base; + + out_with_header: + free_page((unsigned long)ctx->header); + out: + spin_lock_irqsave(&ohci->lock, flags); + *mask |= 1 << index; + spin_unlock_irqrestore(&ohci->lock, flags); + + return ERR_PTR(retval); } static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) @@ -1413,6 +1431,7 @@ static void ohci_free_iso_context(struct fw_iso_context *base) ohci_stop_iso(base); context_release(&ctx->context); + free_page((unsigned long)ctx->header); spin_lock_irqsave(&ohci->lock, flags); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index b2a0a030c0f..7942e914b8f 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -335,7 +335,10 @@ struct fw_iso_packet { struct fw_iso_context; typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, - int status, u32 cycle, void *data); + u32 cycle, + size_t header_length, + void *header, + void *data); /* An iso buffer is just a set of pages mapped for DMA in the * specified direction. Since the pages are to be used for DMA, they -- cgit v1.2.3-70-g09d2 From d2746dc192e8b9446ea1cb843e94c30f177b7e54 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:46 -0500 Subject: firewire: Use a buffer fill descriptor for receive when header size is 0. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the DMA is setup to not strip any headers, we need to use the buffer fill descriptor instead of the dual buffer, since the dual buffer descriptor must strip a non-zero number of header quadlets. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-iso.c | 2 +- drivers/firewire/fw-ohci.c | 107 ++++++++++++++++++++++++++++++++------ drivers/firewire/fw-transaction.h | 3 +- 3 files changed, 95 insertions(+), 17 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 1605e115723..736b1bf1513 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -111,7 +111,7 @@ fw_iso_context_create(struct fw_card *card, int type, size_t header_size, { struct fw_iso_context *ctx; - ctx = card->driver->allocate_iso_context(card, type); + ctx = card->driver->allocate_iso_context(card, type, header_size); if (IS_ERR(ctx)) return ctx; diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 76ac70a3854..9b9ea0f3c41 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1267,16 +1267,34 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) spin_unlock_irqrestore(&ohci->lock, flags); return retval; } + +static int handle_ir_bufferfill_packet(struct context *context, + struct descriptor *d, + struct descriptor *last) +{ + struct iso_context *ctx = + container_of(context, struct iso_context, context); -static int handle_ir_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) + if (d->res_count > 0) + return 0; + + if (le16_to_cpu(last->control) & descriptor_irq_always) + ctx->base.callback(&ctx->base, + le16_to_cpu(last->res_count), + 0, NULL, ctx->base.callback_data); + + return 1; +} + +static int handle_ir_dualbuffer_packet(struct context *context, + struct descriptor *d, + struct descriptor *last) { struct iso_context *ctx = container_of(context, struct iso_context, context); struct db_descriptor *db = (struct db_descriptor *) d; size_t header_length; - + if (db->first_res_count > 0 && db->second_res_count > 0) /* This descriptor isn't done yet, stop iteration. */ return 0; @@ -1317,7 +1335,7 @@ static int handle_it_packet(struct context *context, } static struct fw_iso_context * -ohci_allocate_iso_context(struct fw_card *card, int type) +ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) { struct fw_ohci *ohci = fw_ohci(card); struct iso_context *ctx, *list; @@ -1333,7 +1351,10 @@ ohci_allocate_iso_context(struct fw_card *card, int type) } else { mask = &ohci->ir_context_mask; list = ohci->ir_context_list; - callback = handle_ir_packet; + if (header_size > 0) + callback = handle_ir_dualbuffer_packet; + else + callback = handle_ir_bufferfill_packet; } spin_lock_irqsave(&ohci->lock, flags); @@ -1378,7 +1399,7 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct fw_ohci *ohci = ctx->context.ohci; - u32 cycle_match = 0; + u32 cycle_match = 0, mode; int index; if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { @@ -1393,11 +1414,15 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) } else { index = ctx - ohci->ir_context_list; + if (ctx->base.header_size > 0) + mode = IR_CONTEXT_DUAL_BUFFER_MODE; + else + mode = IR_CONTEXT_BUFFER_FILL; reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); reg_write(ohci, context_match(ctx->context.regs), 0xf0000000 | ctx->base.channel); - context_run(&ctx->context, IR_CONTEXT_DUAL_BUFFER_MODE); + context_run(&ctx->context, mode); } return 0; @@ -1544,10 +1569,10 @@ ohci_queue_iso_transmit(struct fw_iso_context *base, } static int -ohci_queue_iso_receive(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) +ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct db_descriptor *db = NULL; @@ -1604,10 +1629,58 @@ ohci_queue_iso_receive(struct fw_iso_context *base, if (p->interrupt) db->control |= cpu_to_le16(descriptor_irq_always); + + return 0; +} - return 0; - } +static int +ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) +{ + struct iso_context *ctx = container_of(base, struct iso_context, base); + struct descriptor *d = NULL; + dma_addr_t d_bus, page_bus; + u32 length, rest; + int page, offset; + page = payload >> PAGE_SHIFT; + offset = payload & ~PAGE_MASK; + rest = packet->payload_length; + + while (rest > 0) { + d = context_get_descriptors(&ctx->context, 1, &d_bus); + if (d == NULL) + return -ENOMEM; + + d->control = cpu_to_le16(descriptor_input_more | + descriptor_status | + descriptor_branch_always); + + if (offset + rest < PAGE_SIZE) + length = rest; + else + length = PAGE_SIZE - offset; + + page_bus = page_private(buffer->pages[page]); + d->data_address = cpu_to_le32(page_bus + offset); + d->req_count = cpu_to_le16(length); + d->res_count = cpu_to_le16(length); + + context_append(&ctx->context, d, 1, 0); + + offset = (offset + length) & ~PAGE_MASK; + rest -= length; + page++; + } + + if (packet->interrupt) + d->control |= cpu_to_le16(descriptor_irq_always); + + return 0; +} + static int ohci_queue_iso(struct fw_iso_context *base, struct fw_iso_packet *packet, @@ -1616,8 +1689,12 @@ ohci_queue_iso(struct fw_iso_context *base, { if (base->type == FW_ISO_CONTEXT_TRANSMIT) return ohci_queue_iso_transmit(base, packet, buffer, payload); + else if (base->header_size == 0) + return ohci_queue_iso_receive_bufferfill(base, packet, + buffer, payload); else - return ohci_queue_iso_receive(base, packet, buffer, payload); + return ohci_queue_iso_receive_dualbuffer(base, packet, + buffer, payload); } static const struct fw_card_driver ohci_driver = { diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 7942e914b8f..1bbcbb341f2 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -425,7 +425,8 @@ struct fw_card_driver { int node_id, int generation); struct fw_iso_context * - (*allocate_iso_context)(struct fw_card *card, int type); + (*allocate_iso_context)(struct fw_card *card, + int type, size_t header_size); void (*free_iso_context)(struct fw_iso_context *ctx); int (*start_iso)(struct fw_iso_context *ctx, s32 cycle); -- cgit v1.2.3-70-g09d2 From 21efb3cfc6ed49991638000f58bb23b838c76e25 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:50 -0500 Subject: firewire: Configure channel and speed at context creation time. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need the channel number as we queue up iso packets for transmission so we can fill out the header correctly. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 11 +++++++++-- drivers/firewire/fw-device-cdev.h | 5 ++--- drivers/firewire/fw-iso.c | 11 +++++------ drivers/firewire/fw-ohci.c | 4 ++-- drivers/firewire/fw-transaction.h | 6 +++--- 5 files changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 6545fb8214d..5c876188677 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -413,8 +413,16 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) if (request.type > FW_ISO_CONTEXT_RECEIVE) return -EINVAL; + if (request.channel > 63) + return -EINVAL; + + if (request.speed > SCODE_3200) + return -EINVAL; + client->iso_context = fw_iso_context_create(client->device->card, request.type, + request.channel, + request.speed, request.header_size, iso_callback, client); if (IS_ERR(client->iso_context)) @@ -519,8 +527,7 @@ static int ioctl_start_iso(struct client *client, void __user *arg) if (copy_from_user(&request, arg, sizeof request)) return -EFAULT; - return fw_iso_context_start(client->iso_context, request.channel, - request.speed, request.cycle); + return fw_iso_context_start(client->iso_context, request.cycle); } static int ioctl_stop_iso(struct client *client, void __user *arg) diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index e32b39dc7e7..99e6aa629f4 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -134,7 +134,8 @@ struct fw_cdev_allocate { struct fw_cdev_create_iso_context { __u32 type; __u32 header_size; - __u32 handle; + __u32 channel; + __u32 speed; }; struct fw_cdev_iso_packet { @@ -154,8 +155,6 @@ struct fw_cdev_queue_iso { }; struct fw_cdev_start_iso { - __u32 channel; - __u32 speed; __s32 cycle; }; diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index deff6922a98..dc5a7e3558e 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -106,7 +106,8 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, } struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, size_t header_size, +fw_iso_context_create(struct fw_card *card, int type, + int channel, int speed, size_t header_size, fw_iso_callback_t callback, void *callback_data) { struct fw_iso_context *ctx; @@ -117,6 +118,8 @@ fw_iso_context_create(struct fw_card *card, int type, size_t header_size, ctx->card = card; ctx->type = type; + ctx->channel = channel; + ctx->speed = speed; ctx->header_size = header_size; ctx->callback = callback; ctx->callback_data = callback_data; @@ -134,12 +137,8 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx) EXPORT_SYMBOL(fw_iso_context_destroy); int -fw_iso_context_start(struct fw_iso_context *ctx, - int channel, int speed, int cycle) +fw_iso_context_start(struct fw_iso_context *ctx, int cycle) { - ctx->channel = channel; - ctx->speed = speed; - return ctx->card->driver->start_iso(ctx, cycle); } EXPORT_SYMBOL(fw_iso_context_start); diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 12f109da4d8..0088acd7718 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1413,7 +1413,7 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) if (cycle > 0) cycle_match = IT_CONTEXT_CYCLE_MATCH_ENABLE | (cycle & 0x7fff) << 16; - + reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index); reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index); context_run(&ctx->context, cycle_match); @@ -1638,7 +1638,7 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, return 0; } - + static int ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base, struct fw_iso_packet *packet, diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 1bbcbb341f2..22e45ccd7b1 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -373,7 +373,8 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, size_t header_size, +fw_iso_context_create(struct fw_card *card, int type, + int channel, int speed, size_t header_size, fw_iso_callback_t callback, void *callback_data); void @@ -386,8 +387,7 @@ fw_iso_context_queue(struct fw_iso_context *ctx, unsigned long payload); int -fw_iso_context_start(struct fw_iso_context *ctx, - int channel, int speed, int cycle); +fw_iso_context_start(struct fw_iso_context *ctx, int cycle); int fw_iso_context_stop(struct fw_iso_context *ctx); -- cgit v1.2.3-70-g09d2 From 98b6cbe83b6e8db54638746c9040c7962d96b322 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 16 Feb 2007 17:34:51 -0500 Subject: firewire: Implement sync and tag matching for isochronous receive. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 10 +++++++++- drivers/firewire/fw-device-cdev.h | 8 ++++++++ drivers/firewire/fw-iso.c | 8 ++++++-- drivers/firewire/fw-ohci.c | 32 ++++++++++++++++++++++++++++++-- drivers/firewire/fw-transaction.h | 13 +++++++++++-- 5 files changed, 64 insertions(+), 7 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 5c876188677..33fe5768a07 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -416,6 +416,12 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) if (request.channel > 63) return -EINVAL; + if (request.sync > 15) + return -EINVAL; + + if (request.tags == 0 || request.tags > 15) + return -EINVAL; + if (request.speed > SCODE_3200) return -EINVAL; @@ -424,6 +430,8 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) request.channel, request.speed, request.header_size, + request.sync, + request.tags, iso_callback, client); if (IS_ERR(client->iso_context)) return PTR_ERR(client->iso_context); @@ -495,7 +503,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) if (__copy_from_user (u.packet.header, p->header, header_length)) return -EFAULT; - if (u.packet.skip && + if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT && u.packet.header_length + u.packet.payload_length > 0) return -EINVAL; if (payload + u.packet.payload_length > payload_end) diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 99e6aa629f4..739f54fe08c 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -131,11 +131,19 @@ struct fw_cdev_allocate { #define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 #define FW_CDEV_ISO_CONTEXT_RECEIVE 1 +#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1 +#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2 +#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4 +#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8 +#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15 + struct fw_cdev_create_iso_context { __u32 type; __u32 header_size; __u32 channel; __u32 speed; + __u32 sync; + __u32 tags; }; struct fw_cdev_iso_packet { diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index dc5a7e3558e..728cbb3ee91 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -107,12 +107,14 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_iso_context * fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, + int channel, int speed, + int sync, int tags, size_t header_size, fw_iso_callback_t callback, void *callback_data) { struct fw_iso_context *ctx; - ctx = card->driver->allocate_iso_context(card, type, header_size); + ctx = card->driver->allocate_iso_context(card, type, + sync, tags, header_size); if (IS_ERR(ctx)) return ctx; @@ -120,6 +122,8 @@ fw_iso_context_create(struct fw_card *card, int type, ctx->type = type; ctx->channel = channel; ctx->speed = speed; + ctx->sync = sync; + ctx->tags = tags; ctx->header_size = header_size; ctx->callback = callback; ctx->callback_data = callback_data; diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 0088acd7718..ea43a5ed18c 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1337,7 +1337,8 @@ static int handle_it_packet(struct context *context, } static struct fw_iso_context * -ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) +ohci_allocate_iso_context(struct fw_card *card, int type, + int sync, int tags, size_t header_size) { struct fw_ohci *ohci = fw_ohci(card); struct iso_context *ctx, *list; @@ -1427,7 +1428,8 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); reg_write(ohci, context_match(ctx->context.regs), - 0xf0000000 | ctx->base.channel); + (ctx->base.tags << 28) | + (ctx->base.sync << 8) | ctx->base.channel); context_run(&ctx->context, mode); } @@ -1573,6 +1575,26 @@ ohci_queue_iso_transmit(struct fw_iso_context *base, return 0; } + +static int +setup_wait_descriptor(struct context *ctx) +{ + struct descriptor *d; + dma_addr_t d_bus; + + d = context_get_descriptors(ctx, 1, &d_bus); + if (d == NULL) + return -ENOMEM; + + d->control = cpu_to_le16(descriptor_input_more | + descriptor_status | + descriptor_branch_always | + descriptor_wait); + + context_append(ctx, d, 1, 0); + + return 0; +} static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, @@ -1591,6 +1613,9 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, /* FIXME: Cycle lost behavior should be configurable: lose * packet, retransmit or terminate.. */ + if (packet->skip && setup_wait_descriptor(&ctx->context) < 0) + return -ENOMEM; + p = packet; z = 2; @@ -1655,6 +1680,9 @@ ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base, offset = payload & ~PAGE_MASK; rest = packet->payload_length; + if (packet->skip && setup_wait_descriptor(&ctx->context) < 0) + return -ENOMEM; + while (rest > 0) { d = context_get_descriptors(&ctx->context, 1, &d_bus); if (d == NULL) diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 22e45ccd7b1..cbea845dc40 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -332,6 +332,12 @@ struct fw_iso_packet { #define FW_ISO_CONTEXT_TRANSMIT 0 #define FW_ISO_CONTEXT_RECEIVE 1 +#define FW_ISO_CONTEXT_MATCH_TAG0 1 +#define FW_ISO_CONTEXT_MATCH_TAG1 2 +#define FW_ISO_CONTEXT_MATCH_TAG2 4 +#define FW_ISO_CONTEXT_MATCH_TAG3 8 +#define FW_ISO_CONTEXT_MATCH_ALL_TAGS 15 + struct fw_iso_context; typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, @@ -357,6 +363,8 @@ struct fw_iso_context { int type; int channel; int speed; + int sync; + int tags; size_t header_size; fw_iso_callback_t callback; void *callback_data; @@ -374,7 +382,8 @@ fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); struct fw_iso_context * fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, + int channel, int speed, + int sync, int tags, size_t header_size, fw_iso_callback_t callback, void *callback_data); void @@ -425,7 +434,7 @@ struct fw_card_driver { int node_id, int generation); struct fw_iso_context * - (*allocate_iso_context)(struct fw_card *card, + (*allocate_iso_context)(struct fw_card *card, int sync, int tags, int type, size_t header_size); void (*free_iso_context)(struct fw_iso_context *ctx); -- cgit v1.2.3-70-g09d2 From 937f687969f77bfeee5efd71cadfa6f1a813665e Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Wed, 7 Mar 2007 12:12:36 -0500 Subject: firewire: Let an fw_descriptor specify a leading immediate key/value pair. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets us break out "Juju" as the model name in the config rom. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 7 ++++++- drivers/firewire/fw-transaction.c | 34 +++++++++++++++++++++++++--------- drivers/firewire/fw-transaction.h | 1 + 3 files changed, 32 insertions(+), 10 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 3f8661a52ac..8d7c12164bb 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -100,11 +100,12 @@ generate_config_rom (struct fw_card *card, size_t *config_rom_length) i = 5; config_rom[i++] = 0; config_rom[i++] = 0x0c0083c0; /* node capabilities */ - config_rom[i++] = 0x03d00d1e; /* vendor id */ j = i + descriptor_count; /* Generate root directory entries for descriptors. */ list_for_each_entry (desc, &descriptor_list, link) { + if (desc->immediate > 0) + config_rom[i++] = desc->immediate; config_rom[i] = desc->key | (j - i); i++; j += desc->length; @@ -165,6 +166,8 @@ fw_core_add_descriptor (struct fw_descriptor *desc) list_add_tail (&desc->link, &descriptor_list); descriptor_count++; + if (desc->immediate > 0) + descriptor_count++; update_config_roms(); up_write(&fw_bus_type.subsys.rwsem); @@ -180,6 +183,8 @@ fw_core_remove_descriptor (struct fw_descriptor *desc) list_del(&desc->link); descriptor_count--; + if (desc->immediate > 0) + descriptor_count--; update_config_roms(); up_write(&fw_bus_type.subsys.rwsem); diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index abc37fa5249..8e2b9455739 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -720,23 +720,37 @@ MODULE_AUTHOR("Kristian Hoegsberg "); MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); MODULE_LICENSE("GPL"); -static const u32 vendor_textual_descriptor_data[] = { +static const u32 vendor_textual_descriptor[] = { /* textual descriptor leaf () */ - 0x00080000, + 0x00060000, 0x00000000, 0x00000000, 0x4c696e75, /* L i n u */ 0x78204669, /* x F i */ 0x72657769, /* r e w i */ - 0x72652028, /* r e ( */ - 0x4a554a55, /* J U J U */ - 0x29000000, /* ) */ + 0x72650000, /* r e */ }; -static struct fw_descriptor vendor_textual_descriptor = { - .length = ARRAY_SIZE(vendor_textual_descriptor_data), +static const u32 model_textual_descriptor[] = { + /* model descriptor leaf () */ + 0x00030000, + 0x00000000, + 0x00000000, + 0x4a756a75, /* J u j u */ +}; + +static struct fw_descriptor vendor_id_descriptor = { + .length = ARRAY_SIZE(vendor_textual_descriptor), + .immediate = 0x03d00d1e, .key = 0x81000000, - .data = vendor_textual_descriptor_data, + .data = vendor_textual_descriptor, +}; + +static struct fw_descriptor model_id_descriptor = { + .length = ARRAY_SIZE(model_textual_descriptor), + .immediate = 0x17000001, + .key = 0x81000000, + .data = model_textual_descriptor, }; static int __init fw_core_init(void) @@ -748,7 +762,9 @@ static int __init fw_core_init(void) return retval; /* Add the vendor textual descriptor. */ - retval = fw_core_add_descriptor(&vendor_textual_descriptor); + retval = fw_core_add_descriptor(&vendor_id_descriptor); + BUG_ON(retval < 0); + retval = fw_core_add_descriptor(&model_id_descriptor); BUG_ON(retval < 0); return 0; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index cbea845dc40..552e9af081e 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -164,6 +164,7 @@ struct fw_request; struct fw_descriptor { struct list_head link; size_t length; + u32 immediate; u32 key; const u32 *data; }; -- cgit v1.2.3-70-g09d2 From 49e1179b16fe54bfa070cd955a24c5ce82e21d16 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Wed, 7 Mar 2007 12:12:37 -0500 Subject: firewire: Drop the unused fw_card device. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 40 ++++++++++++--------------------------- drivers/firewire/fw-transaction.h | 3 +-- 2 files changed, 13 insertions(+), 30 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 8d7c12164bb..b1deb5214bd 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -351,15 +351,6 @@ fw_card_bm_work(struct work_struct *work) } } -static void -release_card(struct device *device) -{ - struct fw_card *card = - container_of(device, struct fw_card, card_device); - - kfree(card); -} - static void flush_timer_callback(unsigned long data) { @@ -374,6 +365,7 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, { static atomic_t index = ATOMIC_INIT(-1); + kref_init(&card->kref); card->index = atomic_inc_return(&index); card->driver = driver; card->device = device; @@ -389,14 +381,6 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, card->local_node = NULL; INIT_DELAYED_WORK(&card->work, fw_card_bm_work); - - card->card_device.bus = &fw_bus_type; - card->card_device.release = release_card; - card->card_device.parent = card->device; - snprintf(card->card_device.bus_id, sizeof card->card_device.bus_id, - "fwcard%d", card->index); - - device_initialize(&card->card_device); } EXPORT_SYMBOL(fw_card_initialize); @@ -404,7 +388,6 @@ int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid) { - int retval; u32 *config_rom; size_t length; @@ -417,12 +400,6 @@ fw_card_add(struct fw_card *card, if (card->driver->update_phy_reg(card, 4, 0, 0x80 | 0x40) < 0) return -EIO; - retval = device_add(&card->card_device); - if (retval < 0) { - fw_error("Failed to register card device."); - return retval; - } - /* The subsystem grabs a reference when the card is added and * drops it when the driver calls fw_core_remove_card. */ fw_card_get(card); @@ -520,27 +497,34 @@ fw_core_remove_card(struct fw_card *card) fw_destroy_nodes(card); - /* This also drops the subsystem reference. */ - device_unregister(&card->card_device); + fw_card_put(card); } EXPORT_SYMBOL(fw_core_remove_card); struct fw_card * fw_card_get(struct fw_card *card) { - get_device(&card->card_device); + kref_get(&card->kref); return card; } EXPORT_SYMBOL(fw_card_get); +static void +release_card(struct kref *kref) +{ + struct fw_card *card = container_of(kref, struct fw_card, kref); + + kfree(card); +} + /* An assumption for fw_card_put() is that the card driver allocates * the fw_card struct with kalloc and that it has been shut down * before the last ref is dropped. */ void fw_card_put(struct fw_card *card) { - put_device(&card->card_device); + kref_put(&card->kref, release_card); } EXPORT_SYMBOL(fw_card_put); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 552e9af081e..b0d057533fb 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -270,6 +270,7 @@ extern struct bus_type fw_bus_type; struct fw_card { const struct fw_card_driver *driver; struct device *device; + struct kref kref; int node_id; int generation; @@ -300,8 +301,6 @@ struct fw_card { int index; - struct device card_device; - struct list_head link; /* Work struct for BM duties. */ -- cgit v1.2.3-70-g09d2 From f319b6a02f12c3712eb64eee6a23584367cb3588 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Wed, 7 Mar 2007 12:12:49 -0500 Subject: firewire: Move async transmit to use the general context code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old async transmit context handling was starting and stopping DMA for every packet transmission. This could cause silently failing packet transmission, if the DMA was reprogrammed too close to being stopped. The general context code keeps DMA running at all times and fixes this problem. It's also a nice cleanup. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 360 ++++++++++++++++---------------------- drivers/firewire/fw-transaction.h | 3 +- 2 files changed, 149 insertions(+), 214 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 37467923e98..9e8a8f90930 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -112,25 +112,6 @@ struct context { struct tasklet_struct tasklet; }; -struct at_context { - struct fw_ohci *ohci; - dma_addr_t descriptor_bus; - dma_addr_t buffer_bus; - struct fw_packet *current_packet; - - struct list_head list; - - struct { - struct descriptor more; - __le32 header[4]; - struct descriptor last; - } d; - - u32 regs; - - struct tasklet_struct tasklet; -}; - #define it_header_sy(v) ((v) << 0) #define it_header_tcode(v) ((v) << 4) #define it_header_channel(v) ((v) << 8) @@ -173,8 +154,8 @@ struct fw_ohci { struct ar_context ar_request_ctx; struct ar_context ar_response_ctx; - struct at_context at_request_ctx; - struct at_context at_response_ctx; + struct context at_request_ctx; + struct context at_response_ctx; u32 it_context_mask; struct iso_context *it_context_list; @@ -210,6 +191,8 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) #define SELF_ID_BUF_SIZE 0x800 #define OHCI_TCODE_PHY_PACKET 0x0e #define OHCI_VERSION_1_1 0x010010 +#define ISO_BUFFER_SIZE (64 * 1024) +#define AT_BUFFER_SIZE 4096 static char ohci_driver_name[] = KBUILD_MODNAME; @@ -587,210 +570,166 @@ static void context_stop(struct context *ctx) } } -static void -do_packet_callbacks(struct fw_ohci *ohci, struct list_head *list) -{ - struct fw_packet *p, *next; - - list_for_each_entry_safe(p, next, list, link) - p->callback(p, &ohci->card, p->ack); -} - -static void -complete_transmission(struct fw_packet *packet, - int ack, struct list_head *list) -{ - list_move_tail(&packet->link, list); - packet->ack = ack; -} +struct driver_data { + struct fw_packet *packet; +}; -/* This function prepares the first packet in the context queue for - * transmission. Must always be called with the ochi->lock held to - * ensure proper generation handling and locking around packet queue - * manipulation. */ -static void -at_context_setup_packet(struct at_context *ctx, struct list_head *list) +/* 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) { - struct fw_packet *packet; struct fw_ohci *ohci = ctx->ohci; + dma_addr_t d_bus, payload_bus; + struct driver_data *driver_data; + struct descriptor *d, *last; + __le32 *header; int z, tcode; + u32 reg; - packet = fw_packet(ctx->list.next); - - memset(&ctx->d, 0, sizeof ctx->d); - if (packet->payload_length > 0) { - packet->payload_bus = dma_map_single(ohci->card.device, - packet->payload, - packet->payload_length, - DMA_TO_DEVICE); - if (dma_mapping_error(packet->payload_bus)) { - complete_transmission(packet, RCODE_SEND_ERROR, list); - return; - } - - ctx->d.more.control = - cpu_to_le16(descriptor_output_more | - descriptor_key_immediate); - ctx->d.more.req_count = cpu_to_le16(packet->header_length); - ctx->d.more.res_count = cpu_to_le16(packet->timestamp); - ctx->d.last.control = - cpu_to_le16(descriptor_output_last | - descriptor_irq_always | - descriptor_branch_always); - ctx->d.last.req_count = cpu_to_le16(packet->payload_length); - ctx->d.last.data_address = cpu_to_le32(packet->payload_bus); - z = 3; - } else { - ctx->d.more.control = - cpu_to_le16(descriptor_output_last | - descriptor_key_immediate | - descriptor_irq_always | - descriptor_branch_always); - ctx->d.more.req_count = cpu_to_le16(packet->header_length); - ctx->d.more.res_count = cpu_to_le16(packet->timestamp); - z = 2; + d = context_get_descriptors(ctx, 4, &d_bus); + if (d == NULL) { + packet->ack = RCODE_SEND_ERROR; + return -1; } + d[0].control = cpu_to_le16(descriptor_key_immediate); + d[0].res_count = cpu_to_le16(packet->timestamp); + /* The DMA format for asyncronous link packets is different * from the IEEE1394 layout, so shift the fields around * accordingly. If header_length is 8, it's a PHY packet, to * which we need to prepend an extra quadlet. */ + + header = (__le32 *) &d[1]; if (packet->header_length > 8) { - ctx->d.header[0] = cpu_to_le32((packet->header[0] & 0xffff) | - (packet->speed << 16)); - ctx->d.header[1] = cpu_to_le32((packet->header[1] & 0xffff) | - (packet->header[0] & 0xffff0000)); - ctx->d.header[2] = cpu_to_le32(packet->header[2]); + header[0] = cpu_to_le32((packet->header[0] & 0xffff) | + (packet->speed << 16)); + header[1] = cpu_to_le32((packet->header[1] & 0xffff) | + (packet->header[0] & 0xffff0000)); + header[2] = cpu_to_le32(packet->header[2]); tcode = (packet->header[0] >> 4) & 0x0f; if (TCODE_IS_BLOCK_PACKET(tcode)) - ctx->d.header[3] = cpu_to_le32(packet->header[3]); + header[3] = cpu_to_le32(packet->header[3]); else - ctx->d.header[3] = packet->header[3]; + header[3] = (__force __le32) packet->header[3]; + + d[0].req_count = cpu_to_le16(packet->header_length); } else { - ctx->d.header[0] = - cpu_to_le32((OHCI1394_phy_tcode << 4) | - (packet->speed << 16)); - ctx->d.header[1] = cpu_to_le32(packet->header[0]); - ctx->d.header[2] = cpu_to_le32(packet->header[1]); - ctx->d.more.req_count = cpu_to_le16(12); + header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) | + (packet->speed << 16)); + header[1] = cpu_to_le32(packet->header[0]); + header[2] = cpu_to_le32(packet->header[1]); + d[0].req_count = cpu_to_le16(12); } - /* FIXME: Document how the locking works. */ - if (ohci->generation == packet->generation) { - reg_write(ctx->ohci, command_ptr(ctx->regs), - ctx->descriptor_bus | z); - reg_write(ctx->ohci, control_set(ctx->regs), - CONTEXT_RUN | CONTEXT_WAKE); - ctx->current_packet = packet; + driver_data = (struct driver_data *) &d[3]; + driver_data->packet = packet; + + if (packet->payload_length > 0) { + payload_bus = + dma_map_single(ohci->card.device, packet->payload, + packet->payload_length, DMA_TO_DEVICE); + if (dma_mapping_error(payload_bus)) { + packet->ack = RCODE_SEND_ERROR; + return -1; + } + + d[2].req_count = cpu_to_le16(packet->payload_length); + d[2].data_address = cpu_to_le32(payload_bus); + last = &d[2]; + z = 3; } else { - /* We dont return error codes from this function; all - * transmission errors are reported through the - * callback. */ - complete_transmission(packet, RCODE_GENERATION, list); + last = &d[0]; + z = 2; } -} -static void at_context_stop(struct at_context *ctx) -{ - u32 reg; + last->control |= cpu_to_le16(descriptor_output_last | + descriptor_irq_always | + descriptor_branch_always); - reg_write(ctx->ohci, control_clear(ctx->regs), CONTEXT_RUN); + /* FIXME: Document how the locking works. */ + if (ohci->generation != packet->generation) { + packet->ack = RCODE_GENERATION; + return -1; + } + + context_append(ctx, d, z, 4 - z); + /* If the context isn't already running, start it up. */ reg = reg_read(ctx->ohci, control_set(ctx->regs)); - if (reg & CONTEXT_ACTIVE) - fw_notify("Tried to stop context, but it is still active " - "(0x%08x).\n", reg); + if ((reg & CONTEXT_ACTIVE) == 0) + context_run(ctx, 0); + + return 0; } -static void at_context_tasklet(unsigned long data) +static int handle_at_packet(struct context *context, + struct descriptor *d, + struct descriptor *last) { - struct at_context *ctx = (struct at_context *)data; - struct fw_ohci *ohci = ctx->ohci; + struct driver_data *driver_data; struct fw_packet *packet; - LIST_HEAD(list); - unsigned long flags; + struct fw_ohci *ohci = context->ohci; + dma_addr_t payload_bus; int evt; - spin_lock_irqsave(&ohci->lock, flags); - - packet = fw_packet(ctx->list.next); - - at_context_stop(ctx); + if (last->transfer_status == 0) + /* This descriptor isn't done yet, stop iteration. */ + return 0; - /* If the head of the list isn't the packet that just got - * transmitted, the packet got cancelled before we finished - * transmitting it. */ - if (ctx->current_packet != packet) - goto skip_to_next; + driver_data = (struct driver_data *) &d[3]; + packet = driver_data->packet; + if (packet == NULL) + /* This packet was cancelled, just continue. */ + return 1; - if (packet->payload_length > 0) { - dma_unmap_single(ohci->card.device, packet->payload_bus, + payload_bus = le32_to_cpu(last->data_address); + if (payload_bus != 0) + dma_unmap_single(ohci->card.device, payload_bus, packet->payload_length, DMA_TO_DEVICE); - evt = le16_to_cpu(ctx->d.last.transfer_status) & 0x1f; - packet->timestamp = le16_to_cpu(ctx->d.last.res_count); - } - else { - evt = le16_to_cpu(ctx->d.more.transfer_status) & 0x1f; - packet->timestamp = le16_to_cpu(ctx->d.more.res_count); - } - - if (evt < 16) { - switch (evt) { - case OHCI1394_evt_timeout: - /* Async response transmit timed out. */ - complete_transmission(packet, RCODE_CANCELLED, &list); - break; - - case OHCI1394_evt_flushed: - /* The packet was flushed should give same - * error as when we try to use a stale - * generation count. */ - complete_transmission(packet, - RCODE_GENERATION, &list); - break; - - case OHCI1394_evt_missing_ack: - /* Using a valid (current) generation count, - * but the node is not on the bus or not - * sending acks. */ - complete_transmission(packet, RCODE_NO_ACK, &list); - break; - - default: - complete_transmission(packet, RCODE_SEND_ERROR, &list); - break; - } - } else - complete_transmission(packet, evt - 16, &list); - skip_to_next: - /* If more packets are queued, set up the next one. */ - if (!list_empty(&ctx->list)) - at_context_setup_packet(ctx, &list); + evt = le16_to_cpu(last->transfer_status) & 0x1f; + packet->timestamp = le16_to_cpu(last->res_count); - spin_unlock_irqrestore(&ohci->lock, flags); + switch (evt) { + case OHCI1394_evt_timeout: + /* Async response transmit timed out. */ + packet->ack = RCODE_CANCELLED; + break; - do_packet_callbacks(ohci, &list); -} + case OHCI1394_evt_flushed: + /* The packet was flushed should give same error as + * when we try to use a stale generation count. */ + packet->ack = RCODE_GENERATION; + break; -static int -at_context_init(struct at_context *ctx, struct fw_ohci *ohci, u32 regs) -{ - INIT_LIST_HEAD(&ctx->list); + case OHCI1394_evt_missing_ack: + /* Using a valid (current) generation count, but the + * node is not on the bus or not sending acks. */ + packet->ack = RCODE_NO_ACK; + break; - ctx->descriptor_bus = - dma_map_single(ohci->card.device, &ctx->d, - sizeof ctx->d, DMA_TO_DEVICE); - if (dma_mapping_error(ctx->descriptor_bus)) - return -ENOMEM; + case ACK_COMPLETE + 0x10: + case ACK_PENDING + 0x10: + case ACK_BUSY_X + 0x10: + case ACK_BUSY_A + 0x10: + case ACK_BUSY_B + 0x10: + case ACK_DATA_ERROR + 0x10: + case ACK_TYPE_ERROR + 0x10: + packet->ack = evt - 0x10; + break; - ctx->regs = regs; - ctx->ohci = ohci; + default: + packet->ack = RCODE_SEND_ERROR; + break; + } - tasklet_init(&ctx->tasklet, at_context_tasklet, (unsigned long)ctx); + packet->callback(packet, &ohci->card, packet->ack); - return 0; + return 1; } #define header_get_destination(q) (((q) >> 16) & 0xffff) @@ -869,7 +808,7 @@ handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) } static void -handle_local_request(struct at_context *ctx, struct fw_packet *packet) +handle_local_request(struct context *ctx, struct fw_packet *packet) { u64 offset; u32 csr; @@ -903,10 +842,10 @@ handle_local_request(struct at_context *ctx, struct fw_packet *packet) } static void -at_context_transmit(struct at_context *ctx, struct fw_packet *packet) +at_context_transmit(struct context *ctx, struct fw_packet *packet) { - LIST_HEAD(list); unsigned long flags; + int retval; spin_lock_irqsave(&ctx->ohci->lock, flags); @@ -917,13 +856,12 @@ at_context_transmit(struct at_context *ctx, struct fw_packet *packet) return; } - list_add_tail(&packet->link, &ctx->list); - if (ctx->list.next == &packet->link) - at_context_setup_packet(ctx, &list); - + retval = at_context_queue_packet(ctx, packet); spin_unlock_irqrestore(&ctx->ohci->lock, flags); - do_packet_callbacks(ctx->ohci, &list); + if (retval < 0) + packet->callback(packet, &ctx->ohci->card, packet->ack); + } static void bus_reset_tasklet(unsigned long data) @@ -977,8 +915,8 @@ static void bus_reset_tasklet(unsigned long data) spin_lock_irqsave(&ohci->lock, flags); ohci->generation = generation; - at_context_stop(&ohci->at_request_ctx); - at_context_stop(&ohci->at_response_ctx); + context_stop(&ohci->at_request_ctx); + context_stop(&ohci->at_response_ctx); reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); /* This next bit is unrelated to the AT context stuff but we @@ -1216,24 +1154,24 @@ 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) { struct fw_ohci *ohci = fw_ohci(card); - LIST_HEAD(list); - unsigned long flags; - - spin_lock_irqsave(&ohci->lock, flags); + struct context *ctx = &ohci->at_request_ctx; + struct driver_data *driver_data = packet->driver_data; + int retval = -ENOENT; - if (packet->ack == 0) { - fw_notify("cancelling packet %p (header[0]=%08x)\n", - packet, packet->header[0]); + tasklet_disable(&ctx->tasklet); - complete_transmission(packet, RCODE_CANCELLED, &list); - } + if (packet->ack != 0) + goto out; - spin_unlock_irqrestore(&ohci->lock, flags); + driver_data->packet = NULL; + packet->ack = RCODE_CANCELLED; + packet->callback(packet, &ohci->card, packet->ack); + retval = 0; - do_packet_callbacks(ohci, &list); + out: + tasklet_enable(&ctx->tasklet); - /* Return success if we actually cancelled something. */ - return list_empty(&list) ? -ENOENT : 0; + return retval; } static int @@ -1314,8 +1252,6 @@ static int handle_ir_dualbuffer_packet(struct context *context, return 1; } -#define ISO_BUFFER_SIZE (64 * 1024) - static int handle_it_packet(struct context *context, struct descriptor *d, struct descriptor *last) @@ -1872,11 +1808,11 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) ar_context_init(&ohci->ar_response_ctx, ohci, OHCI1394_AsRspRcvContextControlSet); - at_context_init(&ohci->at_request_ctx, ohci, - OHCI1394_AsReqTrContextControlSet); + context_init(&ohci->at_request_ctx, ohci, AT_BUFFER_SIZE, + OHCI1394_AsReqTrContextControlSet, handle_at_packet); - at_context_init(&ohci->at_response_ctx, ohci, - OHCI1394_AsRspTrContextControlSet); + context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE, + OHCI1394_AsRspTrContextControlSet, handle_at_packet); reg_write(ohci, OHCI1394_ATRetries, OHCI1394_MAX_AT_REQ_RETRIES | diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index b0d057533fb..e7301b83f91 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -203,8 +203,6 @@ struct fw_packet { size_t payload_length; u32 timestamp; - dma_addr_t payload_bus; - /* This callback is called when the packet transmission has * completed; for successful transmission, the status code is * the ack received from the destination, otherwise it's a @@ -215,6 +213,7 @@ struct fw_packet { fw_packet_callback_t callback; int ack; struct list_head link; + void *driver_data; }; struct fw_transaction { -- cgit v1.2.3-70-g09d2 From 473d28c730e2de888c24b226cfe4183868eacde2 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Wed, 7 Mar 2007 12:12:55 -0500 Subject: firewire: Implement topology map and fix a couple of loopback bugs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 2 +- drivers/firewire/fw-ohci.c | 11 +++++++-- drivers/firewire/fw-topology.c | 28 +++++++++++++++------ drivers/firewire/fw-topology.h | 3 +++ drivers/firewire/fw-transaction.c | 52 ++++++++++++++++++++++++++++++++++++--- drivers/firewire/fw-transaction.h | 5 ++-- 6 files changed, 85 insertions(+), 16 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index b1deb5214bd..d929eb6fef6 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -30,7 +30,7 @@ * polynomial, but we need the ITU-T (or CCITT) polynomial (0x1021). * The implementation below works on an array of host-endian u32 * words, assuming they'll be transmited msb first. */ -static u16 +u16 crc16_itu_t(const u32 *buffer, size_t length) { int shift, i; diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 9e8a8f90930..a9e13468f60 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -813,8 +813,10 @@ handle_local_request(struct context *ctx, struct fw_packet *packet) u64 offset; u32 csr; - packet->ack = ACK_PENDING; - packet->callback(packet, &ctx->ohci->card, packet->ack); + if (ctx == &ctx->ohci->at_request_ctx) { + packet->ack = ACK_PENDING; + packet->callback(packet, &ctx->ohci->card, packet->ack); + } offset = ((unsigned long long) @@ -839,6 +841,11 @@ handle_local_request(struct context *ctx, struct fw_packet *packet) fw_core_handle_response(&ctx->ohci->card, packet); break; } + + if (ctx == &ctx->ohci->at_response_ctx) { + packet->ack = ACK_COMPLETE; + packet->callback(packet, &ctx->ohci->card, packet->ack); + } } static void diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 36c9be75b02..7923463fdbf 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -163,11 +163,12 @@ static void update_hop_count(struct fw_node *node) * internally consistent. On succcess this funtions returns the * fw_node corresponding to the local card otherwise NULL. */ -static struct fw_node *build_tree(struct fw_card *card) +static struct fw_node *build_tree(struct fw_card *card, + u32 *sid, int self_id_count) { struct fw_node *node, *child, *local_node; struct list_head stack, *h; - u32 *sid, *next_sid, *end, q; + u32 *next_sid, *end, q; int i, port_count, child_port_count, phy_id, parent_count, stack_depth; int gap_count, topology_type; @@ -175,8 +176,7 @@ static struct fw_node *build_tree(struct fw_card *card) node = NULL; INIT_LIST_HEAD(&stack); stack_depth = 0; - sid = card->self_ids; - end = sid + card->self_id_count; + end = sid + self_id_count; phy_id = 0; card->irm_node = NULL; gap_count = self_id_gap_count(*sid); @@ -460,6 +460,20 @@ update_tree(struct fw_card *card, struct fw_node *root) } } +static void +update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) +{ + int node_count; + u32 crc; + + card->topology_map[1]++; + node_count = (card->root_node->node_id & 0x3f) + 1; + card->topology_map[2] = (node_count << 16) | self_id_count; + crc = crc16_itu_t(card->topology_map + 1, self_id_count + 2); + card->topology_map[0] = ((self_id_count + 2) << 16) | crc; + memcpy(&card->topology_map[3], self_ids, self_id_count * 4); +} + void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, @@ -479,13 +493,13 @@ fw_core_handle_bus_reset(struct fw_card *card, card->bm_retries = 0; card->node_id = node_id; - card->self_id_count = self_id_count; card->generation = generation; - memcpy(card->self_ids, self_ids, self_id_count * 4); card->reset_jiffies = jiffies; schedule_delayed_work(&card->work, 0); - local_node = build_tree(card); + local_node = build_tree(card, self_ids, self_id_count); + + update_topology_map(card, self_ids, self_id_count); card->color++; diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index f2a575e05ae..913bfe16088 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -88,4 +88,7 @@ fw_node_put(struct fw_node *node) void fw_destroy_nodes(struct fw_card *card); +u16 +crc16_itu_t(const u32 *buffer, size_t length); + #endif /* __fw_topology_h */ diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 3052698c13a..38b286ed744 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -140,7 +140,7 @@ transmit_complete_callback(struct fw_packet *packet, static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, - int node_id, int generation, int speed, + int node_id, int source_id, int generation, int speed, unsigned long long offset, void *payload, size_t length) { int ext_tcode; @@ -157,7 +157,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, header_tcode(tcode) | header_destination(node_id); packet->header[1] = - header_offset_high(offset >> 32) | header_source(0); + header_offset_high(offset >> 32) | header_source(source_id); packet->header[2] = offset; @@ -241,7 +241,7 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, fw_transaction_callback_t callback, void *callback_data) { unsigned long flags; - int tlabel; + int tlabel, source; /* Bump the flush timer up 100ms first of all so we * don't race with a flush timer callback. */ @@ -253,6 +253,7 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, spin_lock_irqsave(&card->lock, flags); + source = card->node_id; tlabel = card->current_tlabel; if (card->tlabel_mask & (1 << tlabel)) { spin_unlock_irqrestore(&card->lock, flags); @@ -274,7 +275,8 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, t->callback_data = callback_data; fw_fill_request(&t->packet, tcode, t->tlabel, - node_id, generation, speed, offset, payload, length); + node_id, source, generation, + speed, offset, payload, length); t->packet.callback = transmit_complete_callback; card->driver->send_request(card, &t->packet); @@ -716,6 +718,44 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p) } EXPORT_SYMBOL(fw_core_handle_response); +const struct fw_address_region topology_map_region = + { .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, }; + +static void +handle_topology_map(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, + int generation, int speed, + unsigned long long offset, + void *payload, size_t length, void *callback_data) +{ + int i, start, end; + u32 *map; + + if (!TCODE_IS_READ_REQUEST(tcode)) { + fw_send_response(card, request, RCODE_TYPE_ERROR); + return; + } + + if ((offset & 3) > 0 || (length & 3) > 0) { + fw_send_response(card, request, RCODE_ADDRESS_ERROR); + return; + } + + start = (offset - topology_map_region.start) / 4; + end = start + length / 4; + map = payload; + + for (i = 0; i < length / 4; i++) + map[i] = cpu_to_be32(card->topology_map[start + i]); + + fw_send_response(card, request, RCODE_COMPLETE); +} + +static struct fw_address_handler topology_map = { + .length = 0x400, + .address_callback = handle_topology_map, +}; + MODULE_AUTHOR("Kristian Hoegsberg "); MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); MODULE_LICENSE("GPL"); @@ -767,6 +807,10 @@ static int __init fw_core_init(void) return fw_cdev_major; } + retval = fw_core_add_address_handler(&topology_map, + &topology_map_region); + BUG_ON(retval < 0); + /* Add the vendor textual descriptor. */ retval = fw_core_add_descriptor(&vendor_id_descriptor); BUG_ON(retval < 0); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index e7301b83f91..a661afb9d68 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -285,9 +285,10 @@ struct fw_card { int link_speed; int config_rom_generation; - /* We need to store up to 4 self ID for a maximum of 63 devices. */ + /* We need to store up to 4 self ID for a maximum of 63 + * devices plus 3 words for the topology map header. */ int self_id_count; - u32 self_ids[252]; + u32 topology_map[252 + 3]; spinlock_t lock; /* Take this lock when handling the lists in * this struct. */ -- cgit v1.2.3-70-g09d2 From d60d7f1d5ce83d1be8d79256f711d6a645b7a2fa Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Wed, 7 Mar 2007 12:12:56 -0500 Subject: firewire: Implement CSR cycle time and bus time registers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 26 +++++++++++++++-- drivers/firewire/fw-transaction.c | 61 ++++++++++++++++++++++++++++++++++++++- drivers/firewire/fw-transaction.h | 2 ++ 3 files changed, 86 insertions(+), 3 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index a9e13468f60..6f9895d201b 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -139,6 +139,7 @@ struct fw_ohci { int node_id; int generation; int request_generation; + u32 bus_seconds; /* Spinlock for accessing fw_ohci data. Never call out of * this driver with this lock held. */ @@ -959,7 +960,7 @@ static void bus_reset_tasklet(unsigned long data) static irqreturn_t irq_handler(int irq, void *data) { struct fw_ohci *ohci = data; - u32 event, iso_event; + u32 event, iso_event, cycle_time; int i; event = reg_read(ohci, OHCI1394_IntEventClear); @@ -1002,6 +1003,12 @@ static irqreturn_t irq_handler(int irq, void *data) iso_event &= ~(1 << i); } + if (event & OHCI1394_cycle64Seconds) { + cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); + if ((cycle_time & 0x80000000) == 0) + ohci->bus_seconds++; + } + return IRQ_HANDLED; } @@ -1213,6 +1220,19 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) return retval; } +static u64 +ohci_get_bus_time(struct fw_card *card) +{ + struct fw_ohci *ohci = fw_ohci(card); + u32 cycle_time; + u64 bus_time; + + cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); + bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time; + + return bus_time; +} + static int handle_ir_bufferfill_packet(struct context *context, struct descriptor *d, struct descriptor *last) @@ -1686,6 +1706,7 @@ static const struct fw_card_driver ohci_driver = { .send_response = ohci_send_response, .cancel_packet = ohci_cancel_packet, .enable_phys_dma = ohci_enable_phys_dma, + .get_bus_time = ohci_get_bus_time, .allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, @@ -1862,7 +1883,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) OHCI1394_RQPkt | OHCI1394_RSPkt | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | OHCI1394_isochRx | OHCI1394_isochTx | - OHCI1394_masterIntEnable); + OHCI1394_masterIntEnable | + OHCI1394_cycle64Seconds); bus_options = reg_read(ohci, OHCI1394_BusOptions); max_receive = (bus_options >> 12) & 0xf; diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 38b286ed744..d36dd512a59 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -752,10 +752,65 @@ handle_topology_map(struct fw_card *card, struct fw_request *request, } static struct fw_address_handler topology_map = { - .length = 0x400, + .length = 0x200, .address_callback = handle_topology_map, }; +const struct fw_address_region registers_region = + { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, }; + +static void +handle_registers(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, + int generation, int speed, + unsigned long long offset, + void *payload, size_t length, void *callback_data) +{ + int reg = offset - CSR_REGISTER_BASE; + unsigned long long bus_time; + __be32 *data = payload; + + switch (reg) { + case CSR_CYCLE_TIME: + case CSR_BUS_TIME: + if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) { + fw_send_response(card, request, RCODE_TYPE_ERROR); + break; + } + + bus_time = card->driver->get_bus_time(card); + if (reg == CSR_CYCLE_TIME) + *data = cpu_to_be32(bus_time); + else + *data = cpu_to_be32(bus_time >> 25); + fw_send_response(card, request, RCODE_COMPLETE); + break; + + case CSR_BUS_MANAGER_ID: + case CSR_BANDWIDTH_AVAILABLE: + case CSR_CHANNELS_AVAILABLE_HI: + case CSR_CHANNELS_AVAILABLE_LO: + /* FIXME: these are handled by the OHCI hardware and + * the stack never sees these request. If we add + * support for a new type of controller that doesn't + * handle this in hardware we need to deal with these + * transactions. */ + BUG(); + break; + + case CSR_BUSY_TIMEOUT: + /* FIXME: Implement this. */ + default: + fw_send_response(card, request, RCODE_ADDRESS_ERROR); + break; + } +} + +static struct fw_address_handler registers = { + .length = 0x400, + .address_callback = handle_registers, +}; + MODULE_AUTHOR("Kristian Hoegsberg "); MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); MODULE_LICENSE("GPL"); @@ -811,6 +866,10 @@ static int __init fw_core_init(void) &topology_map_region); BUG_ON(retval < 0); + retval = fw_core_add_address_handler(®isters, + ®isters_region); + BUG_ON(retval < 0); + /* Add the vendor textual descriptor. */ retval = fw_core_add_descriptor(&vendor_id_descriptor); BUG_ON(retval < 0); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index a661afb9d68..855beb27216 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -433,6 +433,8 @@ struct fw_card_driver { int (*enable_phys_dma) (struct fw_card *card, int node_id, int generation); + u64 (*get_bus_time) (struct fw_card *card); + struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, int sync, int tags, int type, size_t header_size); -- cgit v1.2.3-70-g09d2 From eb0306eac0aad0b7da18d8fbfb777f155b2c010d Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Wed, 14 Mar 2007 17:34:54 -0400 Subject: firewire: Move sync and tag parameters to start_iso ioctl. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting these at create_context time or start_iso time doesn't matter much, but raw1394 sets them at start_iso time so that will be easier to emulate this way. Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-device-cdev.c | 20 ++++++++++---------- drivers/firewire/fw-device-cdev.h | 4 ++-- drivers/firewire/fw-iso.c | 12 ++++-------- drivers/firewire/fw-ohci.c | 9 ++++----- drivers/firewire/fw-transaction.h | 13 ++++++------- 5 files changed, 26 insertions(+), 32 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index be6bfcfb906..175ea042ba3 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c @@ -546,12 +546,6 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) switch (request.type) { case FW_ISO_CONTEXT_RECEIVE: - if (request.sync > 15) - return -EINVAL; - - if (request.tags == 0 || request.tags > 15) - return -EINVAL; - if (request.header_size < 4 || (request.header_size & 3)) return -EINVAL; @@ -567,13 +561,10 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) return -EINVAL; } - client->iso_context = fw_iso_context_create(client->device->card, request.type, request.channel, request.speed, - request.sync, - request.tags, request.header_size, iso_callback, client); if (IS_ERR(client->iso_context)) @@ -678,7 +669,16 @@ static int ioctl_start_iso(struct client *client, void __user *arg) if (copy_from_user(&request, arg, sizeof request)) return -EFAULT; - return fw_iso_context_start(client->iso_context, request.cycle); + if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { + if (request.tags == 0 || request.tags > 15) + return -EINVAL; + + if (request.sync > 15) + return -EINVAL; + } + + return fw_iso_context_start(client->iso_context, + request.cycle, request.sync, request.tags); } static int ioctl_stop_iso(struct client *client, void __user *arg) diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 440fb742aae..3437a360d7d 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h @@ -194,8 +194,6 @@ struct fw_cdev_create_iso_context { __u32 header_size; __u32 channel; __u32 speed; - __u32 sync; - __u32 tags; }; struct fw_cdev_iso_packet { @@ -216,6 +214,8 @@ struct fw_cdev_queue_iso { struct fw_cdev_start_iso { __s32 cycle; + __u32 sync; + __u32 tags; }; #endif /* __fw_cdev_h */ diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 3eaf88005c5..2ce26db656e 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -107,14 +107,12 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_iso_context * fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, - int sync, int tags, size_t header_size, + int channel, int speed, size_t header_size, fw_iso_callback_t callback, void *callback_data) { struct fw_iso_context *ctx; - ctx = card->driver->allocate_iso_context(card, type, - sync, tags, header_size); + ctx = card->driver->allocate_iso_context(card, type, header_size); if (IS_ERR(ctx)) return ctx; @@ -122,8 +120,6 @@ fw_iso_context_create(struct fw_card *card, int type, ctx->type = type; ctx->channel = channel; ctx->speed = speed; - ctx->sync = sync; - ctx->tags = tags; ctx->header_size = header_size; ctx->callback = callback; ctx->callback_data = callback_data; @@ -141,9 +137,9 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx) EXPORT_SYMBOL(fw_iso_context_destroy); int -fw_iso_context_start(struct fw_iso_context *ctx, int cycle) +fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags) { - return ctx->card->driver->start_iso(ctx, cycle); + return ctx->card->driver->start_iso(ctx, cycle, sync, tags); } EXPORT_SYMBOL(fw_iso_context_start); diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 17e13d09929..abb9dc12a61 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1294,8 +1294,7 @@ static int handle_it_packet(struct context *context, } static struct fw_iso_context * -ohci_allocate_iso_context(struct fw_card *card, int type, - int sync, int tags, size_t header_size) +ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) { struct fw_ohci *ohci = fw_ohci(card); struct iso_context *ctx, *list; @@ -1357,7 +1356,8 @@ ohci_allocate_iso_context(struct fw_card *card, int type, return ERR_PTR(retval); } -static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) +static int ohci_start_iso(struct fw_iso_context *base, + s32 cycle, u32 sync, u32 tags) { struct iso_context *ctx = container_of(base, struct iso_context, base); struct fw_ohci *ohci = ctx->context.ohci; @@ -1379,8 +1379,7 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); reg_write(ohci, context_match(ctx->context.regs), - (ctx->base.tags << 28) | - (ctx->base.sync << 8) | ctx->base.channel); + (tags << 28) | (sync << 8) | ctx->base.channel); context_run(&ctx->context, IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 855beb27216..662149723e9 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -363,8 +363,6 @@ struct fw_iso_context { int type; int channel; int speed; - int sync; - int tags; size_t header_size; fw_iso_callback_t callback; void *callback_data; @@ -382,8 +380,7 @@ fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); struct fw_iso_context * fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, - int sync, int tags, size_t header_size, + int channel, int speed, size_t header_size, fw_iso_callback_t callback, void *callback_data); void @@ -396,7 +393,8 @@ fw_iso_context_queue(struct fw_iso_context *ctx, unsigned long payload); int -fw_iso_context_start(struct fw_iso_context *ctx, int cycle); +fw_iso_context_start(struct fw_iso_context *ctx, + int cycle, int sync, int tags); int fw_iso_context_stop(struct fw_iso_context *ctx); @@ -436,11 +434,12 @@ struct fw_card_driver { u64 (*get_bus_time) (struct fw_card *card); struct fw_iso_context * - (*allocate_iso_context)(struct fw_card *card, int sync, int tags, + (*allocate_iso_context)(struct fw_card *card, int type, size_t header_size); void (*free_iso_context)(struct fw_iso_context *ctx); - int (*start_iso)(struct fw_iso_context *ctx, s32 cycle); + int (*start_iso)(struct fw_iso_context *ctx, + s32 cycle, u32 sync, u32 tags); int (*queue_iso)(struct fw_iso_context *ctx, struct fw_iso_packet *packet, -- cgit v1.2.3-70-g09d2 From ecab413359541b1dbe8e8c91cb5fa8eafa662c05 Mon Sep 17 00:00:00 2001 From: Marc Butler Date: Fri, 23 Mar 2007 10:24:02 -0600 Subject: firewire: Add phy register defines. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc Butler Signed-off-by: Kristian Høgsberg Signed-off-by: Stefan Richter (added whitespace) --- drivers/firewire/fw-card.c | 14 ++++++++++---- drivers/firewire/fw-transaction.h | 6 ++++++ 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index d929eb6fef6..34863b60e23 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -395,9 +395,9 @@ fw_card_add(struct fw_card *card, card->link_speed = link_speed; card->guid = guid; - /* FIXME: add #define's for phy registers. */ /* Activate link_on bit and contender bit in our self ID packets.*/ - if (card->driver->update_phy_reg(card, 4, 0, 0x80 | 0x40) < 0) + if (card->driver->update_phy_reg(card, 4, 0, + PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) return -EIO; /* The subsystem grabs a reference when the card is added and @@ -483,7 +483,8 @@ static struct fw_card_driver dummy_driver = { void fw_core_remove_card(struct fw_card *card) { - card->driver->update_phy_reg(card, 4, 0x80 | 0x40, 0); + card->driver->update_phy_reg(card, 4, + PHY_LINK_ACTIVE | PHY_CONTENDER, 0); fw_core_initiate_bus_reset(card, 1); down_write(&fw_bus_type.subsys.rwsem); @@ -531,6 +532,11 @@ EXPORT_SYMBOL(fw_card_put); int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) { - return card->driver->update_phy_reg(card, short_reset ? 5 : 1, 0, 0x40); + int reg = short_reset ? 5 : 1; + /* The following values happen to be the same bit. However be + * explicit for clarity. */ + int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; + + return card->driver->update_phy_reg(card, reg, 0, bit); } EXPORT_SYMBOL(fw_core_initiate_bus_reset); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 662149723e9..63527340152 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -107,6 +107,12 @@ #define PHY_PACKET_LINK_ON 0x1 #define PHY_PACKET_SELF_ID 0x2 +/* Bit fields _within_ the PHY registers. */ +#define PHY_LINK_ACTIVE 0x80 +#define PHY_CONTENDER 0x40 +#define PHY_BUS_RESET 0x40 +#define PHY_BUS_SHORT_RESET 0x40 + #define CSR_REGISTER_BASE 0xfffff0000000ULL /* register offsets relative to CSR_REGISTER_BASE */ -- cgit v1.2.3-70-g09d2 From c781c06d119d04601727f2fbc30151e6760d536d Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Mon, 7 May 2007 20:33:32 -0400 Subject: firewire: Clean up comment style. Drop filenames from file preamble, drop editor annotations and use standard indent style for block comments. Signed-off-by: Kristian Hoegsberg Signed-off-by: Stefan Richter (fixed typo) --- drivers/firewire/fw-card.c | 105 ++++++++++++++++----------- drivers/firewire/fw-cdev.c | 33 +++++---- drivers/firewire/fw-device.c | 101 +++++++++++++++++--------- drivers/firewire/fw-device.h | 5 +- drivers/firewire/fw-iso.c | 4 +- drivers/firewire/fw-ohci.c | 144 +++++++++++++++++++++++++------------- drivers/firewire/fw-sbp2.c | 101 +++++++++++++++++--------- drivers/firewire/fw-topology.c | 65 +++++++++++------ drivers/firewire/fw-topology.h | 5 +- drivers/firewire/fw-transaction.c | 71 ++++++++++++------- drivers/firewire/fw-transaction.h | 58 +++++++++------ 11 files changed, 439 insertions(+), 253 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 216965615ee..b2aa85555a7 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -1,8 +1,5 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-card.c - card level functions - * - * Copyright (C) 2005-2006 Kristian Hoegsberg +/* + * Copyright (C) 2005-2007 Kristian Hoegsberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,12 +66,14 @@ generate_config_rom (struct fw_card *card, size_t *config_rom_length) static u32 config_rom[256]; int i, j, length; - /* Initialize contents of config rom buffer. On the OHCI + /* + * Initialize contents of config rom buffer. On the OHCI * 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 * sure the contents of bus info block in host memory mathces - * the version stored in the OHCI registers. */ + * the version stored in the OHCI registers. + */ memset(config_rom, 0, sizeof config_rom); config_rom[0] = bib_crc_length(4) | bib_info_length(4) | bib_crc(0); @@ -143,9 +142,11 @@ fw_core_add_descriptor (struct fw_descriptor *desc) { size_t i; - /* Check descriptor is valid; the length of all blocks in the + /* + * Check descriptor is valid; the length of all blocks in the * descriptor has to add up to exactly the length of the - * block. */ + * block. + */ i = 0; while (i < desc->length) i += (desc->data[i] >> 16) + 1; @@ -228,7 +229,8 @@ fw_card_bm_work(struct work_struct *work) if (card->bm_generation + 1 == generation || (card->bm_generation != generation && grace)) { - /* This first step is to figure out who is IRM and + /* + * This first step is to figure out who is IRM and * 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 @@ -236,7 +238,8 @@ fw_card_bm_work(struct work_struct *work) * 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 - * next generation. */ + * next generation. + */ irm_id = card->irm_node->node_id; if (!card->irm_node->link_on) { @@ -260,8 +263,10 @@ fw_card_bm_work(struct work_struct *work) wait_for_completion(&bmd.done); if (bmd.rcode == RCODE_GENERATION) { - /* Another bus reset happened. Just return, - * the BM work has been rescheduled. */ + /* + * Another bus reset happened. Just return, + * the BM work has been rescheduled. + */ return; } @@ -271,48 +276,62 @@ fw_card_bm_work(struct work_struct *work) spin_lock_irqsave(&card->lock, flags); if (bmd.rcode != RCODE_COMPLETE) { - /* The lock request failed, maybe the IRM + /* + * The lock request failed, maybe the IRM * isn't really IRM capable after all. Let's * do a bus reset and pick the local node as - * root, and thus, IRM. */ + * root, and thus, IRM. + */ new_root_id = card->local_node->node_id; fw_notify("BM lock failed, making local node (%02x) root.\n", new_root_id); goto pick_me; } } else if (card->bm_generation != generation) { - /* OK, we weren't BM in the last generation, and it's + /* + * OK, we weren't BM in the last generation, and it's * less than 100ms since last bus reset. Reschedule - * this task 100ms from now. */ + * this task 100ms from now. + */ spin_unlock_irqrestore(&card->lock, flags); schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); return; } - /* We're bus manager for this generation, so next step is to + /* + * We're bus manager for this generation, so next step is to * make sure we have an active cycle master and do gap count - * optimization. */ + * optimization. + */ card->bm_generation = generation; if (root == NULL) { - /* Either link_on is false, or we failed to read the - * config rom. In either case, pick another root. */ + /* + * Either link_on is false, or we failed to read the + * config rom. In either case, pick another root. + */ new_root_id = card->local_node->node_id; } else if (atomic_read(&root->state) != FW_DEVICE_RUNNING) { - /* If we haven't probed this device yet, bail out now - * and let's try again once that's done. */ + /* + * If we haven't probed this device yet, bail out now + * and let's try again once that's done. + */ spin_unlock_irqrestore(&card->lock, flags); return; } else if (root->config_rom[2] & bib_cmc) { - /* FIXME: I suppose we should set the cmstr bit in the + /* + * FIXME: I suppose we should set the cmstr bit in the * STATE_CLEAR register of this node, as described in * 1394-1995, 8.4.2.6. Also, send out a force root - * packet for this node. */ + * packet for this node. + */ new_root_id = root_id; } else { - /* Current root has an active link layer and we + /* + * Current root has an active link layer and we * successfully read the config rom, but it's not - * cycle master capable. */ + * cycle master capable. + */ new_root_id = card->local_node->node_id; } @@ -324,9 +343,11 @@ fw_card_bm_work(struct work_struct *work) else gap_count = 63; - /* Finally, figure out if we should do a reset or not. If we've + /* + * Finally, figure out if we should do a reset or not. If we've * done less that 5 resets with the same physical topology and we - * have either a new root or a new gap count setting, let's do it. */ + * have either a new root or a new gap count setting, let's do it. + */ if (card->bm_retries++ < 5 && (card->gap_count != gap_count || new_root_id != root_id)) @@ -391,8 +412,10 @@ fw_card_add(struct fw_card *card, PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) return -EIO; - /* The subsystem grabs a reference when the card is added and - * drops it when the driver calls fw_core_remove_card. */ + /* + * The subsystem grabs a reference when the card is added and + * drops it when the driver calls fw_core_remove_card. + */ fw_card_get(card); down_write(&card_rwsem); @@ -405,11 +428,13 @@ fw_card_add(struct fw_card *card, EXPORT_SYMBOL(fw_card_add); -/* The next few functions implements a dummy driver that use once a +/* + * The next few functions implements a dummy driver that use 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 by the dummy * driver instead of calling into the (possibly) unloaded module. The - * dummy driver just fails all IO. */ + * dummy driver just fails all IO. + */ static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) @@ -429,8 +454,10 @@ static int dummy_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) { - /* We take the card out of card_list before setting the dummy - * driver, so this should never get called. */ + /* + * We take the card out of card_list before setting the dummy + * driver, so this should never get called. + */ BUG(); return -1; } @@ -510,9 +537,11 @@ release_card(struct kref *kref) kfree(card); } -/* An assumption for fw_card_put() is that the card driver allocates +/* + * An assumption for fw_card_put() is that the card driver allocates * the fw_card struct with kalloc and that it has been shut down - * before the last ref is dropped. */ + * before the last ref is dropped. + */ void fw_card_put(struct fw_card *card) { @@ -524,8 +553,6 @@ int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) { int reg = short_reset ? 5 : 1; - /* The following values happen to be the same bit. However be - * explicit for clarity. */ int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; return card->driver->update_phy_reg(card, reg, 0, bit); diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 88b8fd917f5..c876ac3c50e 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -1,8 +1,7 @@ -/* -*- c-basic-offset: 8 -*- +/* + * Char device for device raw access * - * fw-device-cdev.c - Char device for device raw access - * - * Copyright (C) 2005-2006 Kristian Hoegsberg + * Copyright (C) 2005-2007 Kristian Hoegsberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,9 +35,6 @@ #include "fw-topology.h" #include "fw-device.h" -/* dequeue_event() just kfree()'s the event, so the event has to be - * the first field in the struct. */ - struct client; struct client_resource { struct list_head link; @@ -46,6 +42,11 @@ struct client_resource { u32 handle; }; +/* + * dequeue_event() just kfree()'s the event, so the event has to be + * the first field in the struct. + */ + struct event { struct { void *data; size_t size; } v[2]; struct list_head link; @@ -691,13 +692,15 @@ static int ioctl_queue_iso(struct client *client, void *buffer) if (ctx == NULL || request->handle != 0) return -EINVAL; - /* If the user passes a non-NULL data pointer, has mmap()'ed + /* + * If the user passes a non-NULL data pointer, has mmap()'ed * the iso buffer, and the pointer points inside the buffer, * we setup the payload pointers accordingly. Otherwise we * set them both to 0, which will still let packets with * payload_length == 0 through. In other words, if no packets * use the indirect payload, the iso buffer need not be mapped - * and the request->data pointer is ignored.*/ + * and the request->data pointer is ignored. + */ payload = (unsigned long)request->data - client->vm_start; buffer_end = client->buffer.page_count << PAGE_SHIFT; @@ -720,8 +723,10 @@ static int ioctl_queue_iso(struct client *client, void *buffer) if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { header_length = u.packet.header_length; } else { - /* We require that header_length is a multiple of - * the fixed header size, ctx->header_size */ + /* + * We require that header_length is a multiple of + * the fixed header size, ctx->header_size. + */ if (ctx->header_size == 0) { if (u.packet.header_length > 0) return -EINVAL; @@ -908,8 +913,10 @@ static int fw_device_op_release(struct inode *inode, struct file *file) list_for_each_entry_safe(r, next_r, &client->resource_list, link) r->release(client, r); - /* FIXME: We should wait for the async tasklets to stop - * running before freeing the memory. */ + /* + * FIXME: We should wait for the async tasklets to stop + * running before freeing the memory. + */ list_for_each_entry_safe(e, next_e, &client->event_list, link) kfree(e); diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 99d1c418d2b..8e5f17f5e98 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -1,6 +1,5 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-device.c - Device probing and sysfs code. +/* + * Device probing and sysfs code. * * Copyright (C) 2005-2006 Kristian Hoegsberg * @@ -174,8 +173,10 @@ static void fw_device_release(struct device *dev) struct fw_device *device = fw_device(dev); unsigned long flags; - /* Take the card lock so we don't set this to NULL while a - * FW_NODE_UPDATED callback is being handled. */ + /* + * Take the card lock so we don't set this to NULL while a + * FW_NODE_UPDATED callback is being handled. + */ spin_lock_irqsave(&device->card->lock, flags); device->node->data = NULL; spin_unlock_irqrestore(&device->card->lock, flags); @@ -421,34 +422,42 @@ static int read_bus_info_block(struct fw_device *device) for (i = 0; i < 5; i++) { if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) return -1; - /* As per IEEE1212 7.2, during power-up, devices can + /* + * As per IEEE1212 7.2, during power-up, devices can * reply with a 0 for the first quadlet of the config * rom to indicate that they are booting (for example, * if the firmware is on the disk of a external * harddisk). In that case we just fail, and the - * retry mechanism will try again later. */ + * retry mechanism will try again later. + */ if (i == 0 && rom[i] == 0) return -1; } - /* Now parse the config rom. The config rom is a recursive + /* + * Now parse the config rom. The config rom is a recursive * directory structure so we parse it using a stack of * references to the blocks that make up the structure. We * push a reference to the root directory on the stack to - * start things off. */ + * start things off. + */ length = i; sp = 0; stack[sp++] = 0xc0000005; while (sp > 0) { - /* Pop the next block reference of the stack. The + /* + * Pop the next block reference of the stack. The * lower 24 bits is the offset into the config rom, * the upper 8 bits are the type of the reference the - * block. */ + * block. + */ key = stack[--sp]; i = key & 0xffffff; if (i >= ARRAY_SIZE(rom)) - /* The reference points outside the standard - * config rom area, something's fishy. */ + /* + * The reference points outside the standard + * config rom area, something's fishy. + */ return -1; /* Read header quadlet for the block to get the length. */ @@ -457,15 +466,19 @@ static int read_bus_info_block(struct fw_device *device) end = i + (rom[i] >> 16) + 1; i++; if (end > ARRAY_SIZE(rom)) - /* This block extends outside standard config + /* + * This block extends outside standard config * area (and the array we're reading it * into). That's broken, so ignore this - * device. */ + * device. + */ return -1; - /* Now read in the block. If this is a directory + /* + * Now read in the block. If this is a directory * block, check the entries as we read them to see if - * it references another block, and push it in that case. */ + * it references another block, and push it in that case. + */ while (i < end) { if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) return -1; @@ -516,8 +529,10 @@ static void create_units(struct fw_device *device) if (key != (CSR_UNIT | CSR_DIRECTORY)) continue; - /* Get the address of the unit directory and try to - * match the drivers id_tables against it. */ + /* + * Get the address of the unit directory and try to + * match the drivers id_tables against it. + */ unit = kzalloc(sizeof *unit, GFP_KERNEL); if (unit == NULL) { fw_error("failed to allocate memory for unit\n"); @@ -585,14 +600,16 @@ static struct device_type fw_device_type = { .release = fw_device_release, }; -/* These defines control the retry behavior for reading the config +/* + * These defines control the retry behavior for reading the config * rom. It shouldn't be necessary to tweak these; if the device * doesn't respond to a config rom read within 10 seconds, it's not * going to respond at all. As for the initial delay, a lot of * devices will be able to respond within half a second after bus * reset. On the other hand, it's not really worth being more * aggressive than that, since it scales pretty well; if 10 devices - * are plugged in, they're all getting read within one second. */ + * are plugged in, they're all getting read within one second. + */ #define MAX_RETRIES 10 #define RETRY_DELAY (3 * HZ) @@ -604,9 +621,11 @@ static void fw_device_init(struct work_struct *work) container_of(work, struct fw_device, work.work); int minor, err; - /* All failure paths here set node->data to NULL, so that we + /* + * All failure paths here set node->data to NULL, so that we * don't try to do device_for_each_child() on a kfree()'d - * device. */ + * device. + */ if (read_bus_info_block(device) < 0) { if (device->config_rom_retries < MAX_RETRIES) { @@ -647,13 +666,15 @@ static void fw_device_init(struct work_struct *work) create_units(device); - /* Transition the device to running state. If it got pulled + /* + * Transition the device to running state. If it got pulled * out from under us while we did the intialization work, we * have to shut down the device again here. Normally, though, * fw_node_event will be responsible for shutting it down when * necessary. We have to use the atomic cmpxchg here to avoid * racing with the FW_NODE_DESTROYED case in - * fw_node_event(). */ + * fw_node_event(). + */ if (atomic_cmpxchg(&device->state, FW_DEVICE_INITIALIZING, FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) @@ -662,10 +683,12 @@ static void fw_device_init(struct work_struct *work) fw_notify("created new fw device %s (%d config rom retries)\n", device->device.bus_id, device->config_rom_retries); - /* Reschedule the IRM work if we just finished reading the + /* + * Reschedule the IRM work if we just finished reading the * root node config rom. If this races with a bus reset we * just end up running the IRM work a couple of extra times - - * pretty harmless. */ + * pretty harmless. + */ if (device->node == device->card->root_node) schedule_delayed_work(&device->card->work, 0); @@ -716,12 +739,14 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) if (device == NULL) break; - /* Do minimal intialization of the device here, the + /* + * Do minimal intialization of the device here, the * rest will happen in fw_device_init(). We need the * card and node so we can read the config rom and we * need to do device_initialize() now so * device_for_each_child() in FW_NODE_UPDATED is - * doesn't freak out. */ + * doesn't freak out. + */ device_initialize(&device->device); atomic_set(&device->state, FW_DEVICE_INITIALIZING); device->card = fw_card_get(card); @@ -730,15 +755,19 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) device->generation = card->generation; INIT_LIST_HEAD(&device->client_list); - /* Set the node data to point back to this device so + /* + * Set the node data to point back to this device so * FW_NODE_UPDATED callbacks can update the node_id - * and generation for the device. */ + * and generation for the device. + */ node->data = device; - /* Many devices are slow to respond after bus resets, + /* + * Many devices are slow to respond after bus resets, * especially if they are bus powered and go through * power-up after getting plugged in. We schedule the - * first config rom scan half a second after bus reset. */ + * first config rom scan half a second after bus reset. + */ INIT_DELAYED_WORK(&device->work, fw_device_init); schedule_delayed_work(&device->work, INITIAL_DELAY); break; @@ -761,7 +790,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) if (!node->data) break; - /* Destroy the device associated with the node. There + /* + * Destroy the device associated with the node. There * are two cases here: either the device is fully * initialized (FW_DEVICE_RUNNING) or we're in the * process of reading its config rom @@ -770,7 +800,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) * full fw_device_shutdown(). If not, there's work * scheduled to read it's config rom, and we just put * the device in shutdown state to have that code fail - * to create the device. */ + * to create the device. + */ device = node->data; if (atomic_xchg(&device->state, FW_DEVICE_SHUTDOWN) == FW_DEVICE_RUNNING) { diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index c167d59da68..0ba9d64ccf4 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h @@ -1,7 +1,4 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-device.h - Device probing and sysfs code. - * +/* * Copyright (C) 2005-2006 Kristian Hoegsberg * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index 2ce26db656e..2b640e9be6d 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c @@ -1,6 +1,6 @@ -/* -*- c-basic-offset: 8 -*- +/* + * Isochronous IO functionality * - * fw-iso.c - Isochronous IO * Copyright (C) 2006 Kristian Hoegsberg * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 34eb4681e27..beb924403da 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1,6 +1,6 @@ -/* -*- c-basic-offset: 8 -*- +/* + * Driver for OHCI 1394 controllers * - * fw-ohci.c - Driver for OHCI 1394 boards * Copyright (C) 2003-2006 Kristian Hoegsberg * * This program is free software; you can redistribute it and/or modify @@ -141,8 +141,10 @@ struct fw_ohci { int request_generation; u32 bus_seconds; - /* Spinlock for accessing fw_ohci data. Never call out of - * this driver with this lock held. */ + /* + * Spinlock for accessing fw_ohci data. Never call out of + * this driver with this lock held. + */ spinlock_t lock; u32 self_id_buffer[512]; @@ -328,13 +330,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) p.timestamp = status & 0xffff; p.generation = ohci->request_generation; - /* The OHCI bus reset handler synthesizes a phy packet with + /* + * The OHCI bus reset handler synthesizes a phy packet with * the new generation number when a bus reset happens (see * section 8.4.2.3). This helps us determine when a request * was received and make sure we send the response in the same * generation. We only need this for requests; for responses * we use the unique tlabel for finding the matching - * request. */ + * request. + */ if (p.ack + 16 == 0x09) ohci->request_generation = (buffer[2] >> 16) & 0xff; @@ -360,9 +364,11 @@ static void ar_context_tasklet(unsigned long data) if (d->res_count == 0) { size_t size, rest, offset; - /* This descriptor is finished and we may have a + /* + * This descriptor is finished and we may have a * packet split across this and the next buffer. We - * reuse the page for reassembling the split packet. */ + * reuse the page for reassembling the split packet. + */ offset = offsetof(struct ar_buffer, data); dma_unmap_single(ohci->card.device, @@ -473,11 +479,13 @@ context_init(struct context *ctx, struct fw_ohci *ohci, ctx->tail_descriptor = ctx->buffer; ctx->tail_descriptor_last = ctx->buffer; - /* We put a dummy descriptor in the buffer that has a NULL + /* + * We put a dummy descriptor in the buffer that has a NULL * branch address and looks like it's been sent. That way we * have a descriptor to append DMA programs to. Also, the * ring buffer invariant is that it always has at least one - * element so that head == tail means buffer full. */ + * element so that head == tail means buffer full. + */ memset(ctx->head_descriptor, 0, sizeof *ctx->head_descriptor); ctx->head_descriptor->control = cpu_to_le16(descriptor_output_last); @@ -575,9 +583,11 @@ struct driver_data { struct fw_packet *packet; }; -/* This function apppends a packet to the DMA queue for transmission. +/* + * 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. */ + * generation handling and locking around packet queue manipulation. + */ static int at_context_queue_packet(struct context *ctx, struct fw_packet *packet) { @@ -598,10 +608,12 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) d[0].control = cpu_to_le16(descriptor_key_immediate); d[0].res_count = cpu_to_le16(packet->timestamp); - /* The DMA format for asyncronous link packets is different + /* + * The DMA format for asyncronous link packets is different * from the IEEE1394 layout, so shift the fields around * accordingly. If header_length is 8, it's a PHY packet, to - * which we need to prepend an extra quadlet. */ + * which we need to prepend an extra quadlet. + */ header = (__le32 *) &d[1]; if (packet->header_length > 8) { @@ -703,14 +715,18 @@ static int handle_at_packet(struct context *context, break; case OHCI1394_evt_flushed: - /* The packet was flushed should give same error as - * when we try to use a stale generation count. */ + /* + * The packet was flushed should give same error as + * when we try to use a stale generation count. + */ packet->ack = RCODE_GENERATION; break; case OHCI1394_evt_missing_ack: - /* Using a valid (current) generation count, but the - * node is not on the bus or not sending acks. */ + /* + * Using a valid (current) generation count, but the + * node is not on the bus or not sending acks. + */ packet->ack = RCODE_NO_ACK; break; @@ -887,10 +903,12 @@ static void bus_reset_tasklet(unsigned long data) } ohci->node_id = reg & 0xffff; - /* The count in the SelfIDCount register is the number of + /* + * The count in the SelfIDCount register is the number of * bytes in the self ID receive buffer. Since we also receive * the inverted quadlets and a header quadlet, we shift one - * bit extra to get the actual number of self IDs. */ + * bit extra to get the actual number of self IDs. + */ self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff; generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; @@ -901,7 +919,8 @@ static void bus_reset_tasklet(unsigned long data) ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]); } - /* Check the consistency of the self IDs we just read. The + /* + * Check the consistency of the self IDs we just read. The * problem we face is that a new bus reset can start while we * read out the self IDs from the DMA buffer. If this happens, * the DMA buffer will be overwritten with new self IDs and we @@ -911,7 +930,8 @@ static void bus_reset_tasklet(unsigned long data) * self IDs in the buffer before reading them out and compare * it to the current generation after reading them out. If * the two generations match we know we have a consistent set - * of self IDs. */ + * of self IDs. + */ new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff; if (new_generation != generation) { @@ -928,12 +948,14 @@ static void bus_reset_tasklet(unsigned long data) context_stop(&ohci->at_response_ctx); reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); - /* This next bit is unrelated to the AT context stuff but we + /* + * This next bit is unrelated to the AT context stuff but we * have to do it under the spinlock also. If a new config rom * was set up before this reset, the old one is now no longer * in use and we can free it. Update the config rom pointers * to point to the current config rom and clear the - * next_config_rom pointer so a new udpate can take place. */ + * next_config_rom pointer so a new udpate can take place. + */ if (ohci->next_config_rom != NULL) { dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, @@ -942,10 +964,12 @@ static void bus_reset_tasklet(unsigned long data) ohci->config_rom_bus = ohci->next_config_rom_bus; ohci->next_config_rom = NULL; - /* Restore config_rom image and manually update + /* + * Restore config_rom image and manually update * config_rom registers. Writing the header quadlet * will indicate that the config rom is ready, so we - * do that last. */ + * do that last. + */ reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(ohci->config_rom[2])); ohci->config_rom[0] = cpu_to_be32(ohci->next_header); @@ -1018,7 +1042,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); - /* When the link is not yet enabled, the atomic config rom + /* + * When the link is not yet enabled, the atomic config rom * update mechanism described below in ohci_set_config_rom() * is not active. We have to update ConfigRomHeader and * BusOptions manually, and the write to ConfigROMmap takes @@ -1067,8 +1092,10 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) OHCI1394_HCControl_BIBimageValid); flush_writes(ohci); - /* We are ready to go, initiate bus reset to finish the - * initialization. */ + /* + * We are ready to go, initiate bus reset to finish the + * initialization. + */ fw_core_initiate_bus_reset(&ohci->card, 1); @@ -1086,7 +1113,8 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) ohci = fw_ohci(card); - /* When the OHCI controller is enabled, the config rom update + /* + * When the OHCI controller is enabled, the config rom update * mechanism is a bit tricky, but easy enough to use. See * section 5.5.6 in the OHCI specification. * @@ -1141,11 +1169,13 @@ ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) spin_unlock_irqrestore(&ohci->lock, flags); - /* Now initiate a bus reset to have the changes take + /* + * Now initiate a bus reset to have the changes take * effect. We clean up the old config rom memory and DMA * mappings in the bus reset tasklet, since the OHCI * controller could need to access it before the bus reset - * takes effect. */ + * takes effect. + */ if (retval == 0) fw_core_initiate_bus_reset(&ohci->card, 1); @@ -1196,8 +1226,10 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) unsigned long flags; int n, retval = 0; - /* FIXME: Make sure this bitmask is cleared when we clear the busReset - * interrupt bit. Clear physReqResourceAllBuses on bus reset. */ + /* + * FIXME: Make sure this bitmask is cleared when we clear the busReset + * interrupt bit. Clear physReqResourceAllBuses on bus reset. + */ spin_lock_irqsave(&ohci->lock, flags); @@ -1206,8 +1238,10 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) goto out; } - /* NOTE, if the node ID contains a non-local bus ID, physical DMA is - * enabled for _all_ nodes on remote buses. */ + /* + * Note, if the node ID contains a non-local bus ID, physical DMA is + * enabled for _all_ nodes on remote buses. + */ n = (node_id & 0xffc0) == LOCAL_BUS ? node_id & 0x3f : 63; if (n < 32) @@ -1257,11 +1291,13 @@ static int handle_ir_dualbuffer_packet(struct context *context, p = db + 1; end = p + header_length; while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { - /* The iso header is byteswapped to little endian by + /* + * The iso header is byteswapped to little endian by * the controller, but the remaining header quadlets * are big endian. We want to present all the headers * as big endian, so we have to swap the first - * quadlet. */ + * quadlet. + */ *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); i += ctx->base.header_size; @@ -1457,8 +1493,10 @@ ohci_queue_iso_transmit(struct fw_iso_context *base, u32 payload_index, payload_end_index, next_page_index; int page, end_page, i, length, offset; - /* FIXME: Cycle lost behavior should be configurable: lose - * packet, retransmit or terminate.. */ + /* + * FIXME: Cycle lost behavior should be configurable: lose + * packet, retransmit or terminate.. + */ p = packet; payload_index = payload; @@ -1553,8 +1591,10 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, u32 z, header_z, length, rest; int page, offset, packet_count, header_size; - /* FIXME: Cycle lost behavior should be configurable: lose - * packet, retransmit or terminate.. */ + /* + * FIXME: Cycle lost behavior should be configurable: lose + * packet, retransmit or terminate.. + */ if (packet->skip) { d = context_get_descriptors(&ctx->context, 2, &d_bus); @@ -1572,8 +1612,10 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, p = packet; z = 2; - /* The OHCI controller puts the status word in the header - * buffer too, so we need 4 extra bytes per packet. */ + /* + * The OHCI controller puts the status word in the header + * buffer too, so we need 4 extra bytes per packet. + */ packet_count = p->header_length / ctx->base.header_size; header_size = packet_count * (ctx->base.header_size + 4); @@ -1673,8 +1715,6 @@ static int software_reset(struct fw_ohci *ohci) return -EBUSY; } -/* ---------- pci subsystem interface ---------- */ - enum { CLEANUP_SELF_ID, CLEANUP_REGISTERS, @@ -1753,11 +1793,13 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) return cleanup(ohci, CLEANUP_REGISTERS, -EBUSY); } - /* Now enable LPS, which we need in order to start accessing + /* + * Now enable LPS, which we need in order to start accessing * most of the registers. In fact, on some cards (ALI M5251), * accessing registers in the SClk domain without LPS enabled * will lock up the machine. Wait 50msec to make sure we have - * full link enabled. */ + * full link enabled. + */ reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS | OHCI1394_HCControl_postedWriteEnable); @@ -1854,8 +1896,10 @@ static void pci_remove(struct pci_dev *dev) flush_writes(ohci); fw_core_remove_card(&ohci->card); - /* FIXME: Fail all pending packets here, now that the upper - * layers can't queue any more. */ + /* + * FIXME: Fail all pending packets here, now that the upper + * layers can't queue any more. + */ software_reset(ohci); free_irq(dev->irq, ohci); diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 7ce9b811431..eb3bddb162e 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -1,5 +1,5 @@ -/* -*- c-basic-offset: 8 -*- - * fw-spb2.c -- SBP2 driver (SCSI over IEEE1394) +/* + * SBP2 driver (SCSI over IEEE1394) * * Copyright (C) 2005-2007 Kristian Hoegsberg * @@ -18,7 +18,8 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* The basic structure of this driver is based the old storage driver, +/* + * The basic structure of this driver is based on the old storage driver, * drivers/ieee1394/sbp2.c, originally written by * James Goodwin * with later contributions and ongoing maintenance from @@ -60,11 +61,13 @@ struct sbp2_device { u32 workarounds; int login_id; - /* We cache these addresses and only update them once we've + /* + * We cache these addresses and only update them once we've * logged in or reconnected to the sbp2 device. That way, any * IO to the device will automatically fail and get retried if * it happens in a window where the device is not ready to - * handle it (e.g. after a bus reset but before we reconnect). */ + * handle it (e.g. after a bus reset but before we reconnect). + */ int node_id; int address_high; int generation; @@ -239,10 +242,14 @@ static const struct { .model = ~0, .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, }, - /* There are iPods (2nd gen, 3rd gen) with model_id == 0, but + + /* + * There are iPods (2nd gen, 3rd gen) with model_id == 0, but * these iPods do not feature the read_capacity bug according * to one report. Read_capacity behaviour as well as model_id - * could change due to Apple-supplied firmware updates though. */ + * could change due to Apple-supplied firmware updates though. + */ + /* iPod 4th generation. */ { .firmware_revision = 0x0a2700, .model = 0x000021, @@ -398,9 +405,10 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, if (orb == NULL) return -ENOMEM; - /* The sbp2 device is going to send a block read request to - * read out the request from host memory, so map it for - * dma. */ + /* + * The sbp2 device is going to send a block read request to + * read out the request from host memory, so map it for dma. + */ orb->base.request_bus = dma_map_single(device->card->device, &orb->request, sizeof orb->request, DMA_TO_DEVICE); @@ -426,10 +434,11 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, orb->request.status_fifo.high = sd->address_handler.offset >> 32; orb->request.status_fifo.low = sd->address_handler.offset; - /* FIXME: Yeah, ok this isn't elegant, we hardwire exclusive + /* + * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive * login and 1 second reconnect time. The reconnect setting - * is probably fine, but the exclusive login should be an - * option. */ + * is probably fine, but the exclusive login should be an option. + */ if (function == SBP2_LOGIN_REQUEST) { orb->request.misc |= management_orb_exclusive | @@ -592,8 +601,10 @@ static void sbp2_login(struct work_struct *work) sbp2_send_management_orb(unit, sd->node_id, sd->generation, SBP2_LOGOUT_REQUEST, sd->login_id, NULL); - /* Set this back to sbp2_login so we fall back and - * retry login on bus reset. */ + /* + * Set this back to sbp2_login so we fall back and + * retry login on bus reset. + */ PREPARE_DELAYED_WORK(&sd->work, sbp2_login); } kref_put(&sd->kref, release_sbp2_device); @@ -633,9 +644,11 @@ static int sbp2_probe(struct device *dev) return -EBUSY; } - /* Scan unit directory to get management agent address, + /* + * Scan unit directory to get management agent address, * firmware revison and model. Initialize firmware_revision - * and model to values that wont match anything in our table. */ + * and model to values that wont match anything in our table. + */ firmware_revision = 0xff000000; model = 0xff000000; fw_csr_iterator_init(&ci, unit->directory); @@ -673,9 +686,11 @@ static int sbp2_probe(struct device *dev) get_device(&unit->device); - /* We schedule work to do the login so we can easily + /* + * We schedule work to do the login so we can easily * reschedule retries. Always get the ref before scheduling - * work.*/ + * work. + */ INIT_DELAYED_WORK(&sd->work, sbp2_login); if (schedule_delayed_work(&sd->work, 0)) kref_get(&sd->kref); @@ -834,9 +849,11 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) result = sbp2_status_to_sense_data(status_get_data(*status), orb->cmd->sense_buffer); } else { - /* If the orb completes with status == NULL, something + /* + * If the orb completes with status == NULL, something * went wrong, typically a bus reset happened mid-orb - * or when sending the write (less likely). */ + * or when sending the write (less likely). + */ result = DID_BUS_BUSY << 16; } @@ -878,11 +895,13 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) count = dma_map_sg(device->card->device, sg, orb->cmd->use_sg, orb->cmd->sc_data_direction); - /* Handle the special case where there is only one element in + /* + * Handle the special case where there is only one element in * the scatter list by converting it to an immediate block * request. This is also a workaround for broken devices such * as the second generation iPod which doesn't support page - * tables. */ + * tables. + */ if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { orb->request.data_descriptor.high = sd->address_high; orb->request.data_descriptor.low = sg_dma_address(sg); @@ -891,8 +910,10 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) return; } - /* Convert the scatterlist to an sbp2 page table. If any - * scatterlist entries are too big for sbp2 we split the as we go. */ + /* + * Convert the scatterlist to an sbp2 page table. If any + * scatterlist entries are too big for sbp2 we split the as we go. + */ for (i = 0, j = 0; i < count; i++) { sg_len = sg_dma_len(sg + i); sg_addr = sg_dma_address(sg + i); @@ -908,11 +929,13 @@ static void sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) size = sizeof orb->page_table[0] * j; - /* The data_descriptor pointer is the one case where we need + /* + * The data_descriptor pointer is the one case where we need * to fill in the node ID part of the address. All other * pointers assume that the data referenced reside on the * initiator (i.e. us), but data_descriptor can refer to data - * on other nodes so we need to put our ID in descriptor.high. */ + * on other nodes so we need to put our ID in descriptor.high. + */ orb->page_table_bus = dma_map_single(device->card->device, orb->page_table, @@ -933,8 +956,10 @@ static void sbp2_command_orb_map_buffer(struct sbp2_command_orb *orb) struct fw_device *device = fw_device(unit->device.parent); struct sbp2_device *sd = unit->device.driver_data; - /* As for map_scatterlist, we need to fill in the high bits of - * the data_descriptor pointer. */ + /* + * As for map_scatterlist, we need to fill in the high bits of + * the data_descriptor pointer. + */ orb->request_buffer_bus = dma_map_single(device->card->device, @@ -956,8 +981,10 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) struct sbp2_device *sd = unit->device.driver_data; struct sbp2_command_orb *orb; - /* Bidirectional commands are not yet implemented, and unknown - * transfer direction not handled. */ + /* + * Bidirectional commands are not yet implemented, and unknown + * transfer direction not handled. + */ if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) { fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command"); goto fail_alloc; @@ -983,10 +1010,12 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) orb->request.next.high = SBP2_ORB_NULL; orb->request.next.low = 0x0; - /* At speed 100 we can do 512 bytes per packet, at speed 200, + /* + * At speed 100 we can do 512 bytes per packet, at speed 200, * 1024 bytes per packet etc. The SBP-2 max_payload field * specifies the max payload size as 2 ^ (max_payload + 2), so - * if we set this to max_speed + 7, we get the right value. */ + * if we set this to max_speed + 7, we get the right value. + */ orb->request.misc = command_orb_max_payload(device->node->max_speed + 7) | command_orb_speed(device->node->max_speed) | @@ -1002,9 +1031,11 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) if (cmd->use_sg) { sbp2_command_orb_map_scatterlist(orb); } else if (cmd->request_bufflen > SBP2_MAX_SG_ELEMENT_LENGTH) { - /* FIXME: Need to split this into a sg list... but + /* + * FIXME: Need to split this into a sg list... but * could we get the scsi or blk layer to do that by - * reporting our max supported block size? */ + * reporting our max supported block size? + */ fw_error("command > 64k\n"); goto fail_bufflen; } else if (cmd->request_bufflen > 0) { diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 018c6b8afba..c26d5d5e8d5 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -1,6 +1,5 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-topology.c - Incremental bus scan, based on bus topology +/* + * Incremental bus scan, based on bus topology * * Copyright (C) 2004-2006 Kristian Hoegsberg * @@ -69,10 +68,12 @@ static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count) sid++; q = *sid; - /* Check that the extra packets actually are + /* + * Check that the extra packets actually are * extended self ID packets and that the * sequence numbers in the extended self ID - * packets increase as expected. */ + * packets increase as expected. + */ if (!self_id_extended(q) || seq != self_id_ext_sequence(q)) @@ -113,7 +114,8 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color) return node; } -/* Compute the maximum hop count for this node and it's children. The +/* + * Compute the maximum hop count for this node and it's children. The * maximum hop count is the maximum number of connections between any * two nodes in the subtree rooted at this node. We need this for * setting the gap count. As we build the tree bottom up in @@ -202,8 +204,10 @@ static struct fw_node *build_tree(struct fw_card *card, return NULL; } - /* Seek back from the top of our stack to find the - * start of the child nodes for this node. */ + /* + * Seek back from the top of our stack to find the + * start of the child nodes for this node. + */ for (i = 0, h = &stack; i < child_port_count; i++) h = h->prev; child = fw_node(h); @@ -230,7 +234,8 @@ static struct fw_node *build_tree(struct fw_card *card, for (i = 0; i < port_count; i++) { switch (get_port_type(sid, i)) { case SELFID_PORT_PARENT: - /* Who's your daddy? We dont know the + /* + * Who's your daddy? We dont know the * parent node at this time, so we * temporarily abuse node->color for * remembering the entry in the @@ -245,8 +250,10 @@ static struct fw_node *build_tree(struct fw_card *card, case SELFID_PORT_CHILD: node->ports[i].node = child; - /* Fix up parent reference for this - * child node. */ + /* + * Fix up parent reference for this + * child node. + */ child->ports[child->color].node = node; child->color = card->color; child = fw_node(child->link.next); @@ -254,9 +261,11 @@ static struct fw_node *build_tree(struct fw_card *card, } } - /* Check that the node reports exactly one parent + /* + * Check that the node reports exactly one parent * port, except for the root, which of course should - * have no parents. */ + * have no parents. + */ if ((next_sid == end && parent_count != 0) || (next_sid < end && parent_count != 1)) { fw_error("Parent port inconsistency for node %d: " @@ -269,9 +278,11 @@ static struct fw_node *build_tree(struct fw_card *card, list_add_tail(&node->link, &stack); stack_depth += 1 - child_port_count; - /* If all PHYs does not report the same gap count + /* + * If all PHYs does not report the same gap count * setting, we fall back to 63 which will force a gap - * count reconfiguration and a reset. */ + * count reconfiguration and a reset. + */ if (self_id_gap_count(q) != gap_count) gap_count = 63; @@ -427,9 +438,11 @@ update_tree(struct fw_card *card, struct fw_node *root) for (i = 0; i < node0->port_count; i++) { if (node0->ports[i].node && node1->ports[i].node) { - /* This port didn't change, queue the + /* + * This port didn't change, queue the * connected node for further - * investigation. */ + * investigation. + */ if (node0->ports[i].node->color == card->color) continue; list_add_tail(&node0->ports[i].node->link, @@ -437,19 +450,23 @@ update_tree(struct fw_card *card, struct fw_node *root) list_add_tail(&node1->ports[i].node->link, &list1); } else if (node0->ports[i].node) { - /* The nodes connected here were + /* + * The nodes connected here were * unplugged; unref the lost nodes and * queue FW_NODE_LOST callbacks for - * them. */ + * them. + */ for_each_fw_node(card, node0->ports[i].node, report_lost_node); node0->ports[i].node = NULL; } else if (node1->ports[i].node) { - /* One or more node were connected to + /* + * One or more node were connected to * this port. Move the new nodes into * the tree and queue FW_NODE_CREATED - * callbacks for them. */ + * callbacks for them. + */ move_tree(node0, node1, i); for_each_fw_node(card, node0->ports[i].node, report_found_node); @@ -486,9 +503,11 @@ fw_core_handle_bus_reset(struct fw_card *card, spin_lock_irqsave(&card->lock, flags); - /* If the new topology has a different self_id_count the topology + /* + * If the new topology has a different self_id_count the topology * changed, either nodes were added or removed. In that case we - * reset the IRM reset counter. */ + * reset the IRM reset counter. + */ if (card->self_id_count != self_id_count) card->bm_retries = 0; diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index 0778077e9d8..be2a6bed384 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -1,7 +1,4 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-topology.h -- Incremental bus scan, based on bus topology - * +/* * Copyright (C) 2003-2006 Kristian Hoegsberg * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index d36dd512a59..e4355de710f 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -1,6 +1,5 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-transaction.c - core IEEE1394 transaction logic +/* + * Core IEEE1394 transaction logic * * Copyright (C) 2004-2006 Kristian Hoegsberg * @@ -85,21 +84,27 @@ close_transaction(struct fw_transaction *transaction, return -ENOENT; } -/* Only valid for transactions that are potentially pending (ie have - * been sent). */ +/* + * Only valid for transactions that are potentially pending (ie have + * been sent). + */ int fw_cancel_transaction(struct fw_card *card, struct fw_transaction *transaction) { - /* Cancel the packet transmission if it's still queued. That + /* + * Cancel the packet transmission if it's still queued. That * will call the packet transmission callback which cancels - * the transaction. */ + * the transaction. + */ if (card->driver->cancel_packet(card, &transaction->packet) == 0) return 0; - /* If the request packet has already been sent, we need to see - * if the transaction is still pending and remove it in that case. */ + /* + * If the request packet has already been sent, we need to see + * if the transaction is still pending and remove it in that case. + */ return close_transaction(transaction, card, RCODE_CANCELLED, NULL, 0); } @@ -131,8 +136,10 @@ transmit_complete_callback(struct fw_packet *packet, close_transaction(t, card, RCODE_TYPE_ERROR, NULL, 0); break; default: - /* In this case the ack is really a juju specific - * rcode, so just forward that to the callback. */ + /* + * In this case the ack is really a juju specific + * rcode, so just forward that to the callback. + */ close_transaction(t, card, status, NULL, 0); break; } @@ -243,13 +250,17 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, unsigned long flags; int tlabel, source; - /* Bump the flush timer up 100ms first of all so we - * don't race with a flush timer callback. */ + /* + * Bump the flush timer up 100ms first of all so we + * don't race with a flush timer callback. + */ mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10)); - /* Allocate tlabel from the bitmap and put the transaction on - * the list while holding the card spinlock. */ + /* + * Allocate tlabel from the bitmap and put the transaction on + * the list while holding the card spinlock. + */ spin_lock_irqsave(&card->lock, flags); @@ -336,9 +347,11 @@ void fw_flush_transactions(struct fw_card *card) list_for_each_entry_safe(t, next, &list, link) { card->driver->cancel_packet(card, &t->packet); - /* At this point cancel_packet will never call the + /* + * At this point cancel_packet will never call the * transaction callback, since we just took all the - * transactions out of the list. So do it here.*/ + * transactions out of the list. So do it here. + */ t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data); } } @@ -587,9 +600,11 @@ allocate_request(struct fw_packet *p) void fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) { - /* Broadcast packets are reported as ACK_COMPLETE, so this + /* + * Broadcast packets are reported as ACK_COMPLETE, so this * check is sufficient to ensure we don't send response to - * broadcast packets or posted writes. */ + * broadcast packets or posted writes. + */ if (request->ack != ACK_PENDING) return; @@ -639,11 +654,13 @@ fw_core_handle_request(struct fw_card *card, struct fw_packet *p) offset, request->length); spin_unlock_irqrestore(&address_handler_lock, flags); - /* FIXME: lookup the fw_node corresponding to the sender of + /* + * FIXME: lookup the fw_node corresponding to the sender of * this request and pass that to the address handler instead * of the node ID. We may also want to move the address * allocations to fw_node so we only do this callback if the - * upper layers registered it for this node. */ + * upper layers registered it for this node. + */ if (handler == NULL) fw_send_response(card, request, RCODE_ADDRESS_ERROR); @@ -687,8 +704,10 @@ fw_core_handle_response(struct fw_card *card, struct fw_packet *p) return; } - /* FIXME: sanity check packet, is length correct, does tcodes - * and addresses match. */ + /* + * FIXME: sanity check packet, is length correct, does tcodes + * and addresses match. + */ switch (tcode) { case TCODE_READ_QUADLET_RESPONSE: @@ -790,11 +809,13 @@ handle_registers(struct fw_card *card, struct fw_request *request, case CSR_BANDWIDTH_AVAILABLE: case CSR_CHANNELS_AVAILABLE_HI: case CSR_CHANNELS_AVAILABLE_LO: - /* FIXME: these are handled by the OHCI hardware and + /* + * FIXME: these are handled by the OHCI hardware and * the stack never sees these request. If we add * support for a new type of controller that doesn't * handle this in hardware we need to deal with these - * transactions. */ + * transactions. + */ BUG(); break; diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 63527340152..1b7e4dc6c2c 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -1,7 +1,4 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-transaction.h - Header for IEEE1394 transaction logic - * +/* * Copyright (C) 2003-2006 Kristian Hoegsberg * * This program is free software; you can redistribute it and/or modify @@ -209,7 +206,8 @@ struct fw_packet { size_t payload_length; u32 timestamp; - /* This callback is called when the packet transmission has + /* + * This callback is called when the packet transmission has * completed; for successful transmission, the status code is * the ack received from the destination, otherwise it's a * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO. @@ -230,8 +228,10 @@ struct fw_transaction { struct fw_packet packet; - /* The data passed to the callback is valid only during the - * callback. */ + /* + * The data passed to the callback is valid only during the + * callback. + */ fw_transaction_callback_t callback; void *callback_data; }; @@ -291,8 +291,10 @@ struct fw_card { int link_speed; int config_rom_generation; - /* We need to store up to 4 self ID for a maximum of 63 - * devices plus 3 words for the topology map header. */ + /* + * We need to store up to 4 self ID for a maximum of 63 + * devices plus 3 words for the topology map header. + */ int self_id_count; u32 topology_map[252 + 3]; @@ -318,12 +320,14 @@ struct fw_card { struct fw_card *fw_card_get(struct fw_card *card); void fw_card_put(struct fw_card *card); -/* The iso packet format allows for an immediate header/payload part +/* + * The iso packet format allows for an immediate header/payload part * stored in 'header' immediately after the packet info plus an * indirect payload part that is pointer to by the 'payload' field. * Applications can use one or the other or both to implement simple * low-bandwidth streaming (e.g. audio) or more advanced - * scatter-gather streaming (e.g. assembling video frame automatically). */ + * scatter-gather streaming (e.g. assembling video frame automatically). + */ struct fw_iso_packet { u16 payload_length; /* Length of indirect payload. */ @@ -352,11 +356,13 @@ typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, void *header, void *data); -/* An iso buffer is just a set of pages mapped for DMA in the +/* + * An iso buffer is just a set of pages mapped for DMA in the * specified direction. Since the pages are to be used for DMA, they * are not mapped into the kernel virtual address space. We store the * DMA address in the page private. The helper function - * fw_iso_buffer_map() will map the pages into a given vma. */ + * fw_iso_buffer_map() will map the pages into a given vma. + */ struct fw_iso_buffer { enum dma_data_direction direction; @@ -408,18 +414,22 @@ fw_iso_context_stop(struct fw_iso_context *ctx); struct fw_card_driver { const char *name; - /* Enable the given card with the given initial config rom. + /* + * Enable the given card with the given initial config rom. * This function is expected to activate the card, and either * enable the PHY or set the link_on bit and initiate a bus - * reset. */ + * reset. + */ int (*enable) (struct fw_card *card, u32 *config_rom, size_t length); int (*update_phy_reg) (struct fw_card *card, int address, int clear_bits, int set_bits); - /* Update the config rom for an enabled card. This function + /* + * Update the config rom for an enabled card. This function * should change the config rom that is presented on the bus - * an initiate a bus reset. */ + * an initiate a bus reset. + */ int (*set_config_rom) (struct fw_card *card, u32 *config_rom, size_t length); @@ -428,12 +438,14 @@ struct fw_card_driver { /* Calling cancel is valid once a packet has been submitted. */ int (*cancel_packet) (struct fw_card *card, struct fw_packet *packet); - /* Allow the specified node ID to do direct DMA out and in of + /* + * Allow the specified node ID to do direct DMA out and in of * host memory. The card will disable this for all node when * a bus reset happens, so driver need to reenable this after * bus reset. Returns 0 on success, -ENODEV if the card * doesn't support this, -ESTALE if the generation doesn't - * match. */ + * match. + */ int (*enable_phys_dma) (struct fw_card *card, int node_id, int generation); @@ -473,15 +485,15 @@ void fw_flush_transactions(struct fw_card *card); void fw_send_phy_config(struct fw_card *card, int node_id, int generation, int gap_count); -/* Called by the topology code to inform the device code of node - * activity; found, lost, or updated nodes */ +/* + * Called by the topology code to inform the device code of node + * activity; found, lost, or updated nodes. + */ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); /* API used by card level drivers */ -/* Do we need phy speed here also? If we add more args, maybe we - should go back to struct fw_card_info. */ void fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, struct device *device); -- cgit v1.2.3-70-g09d2 From a98e27198771d066934a263177673ebde797e8fb Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Mon, 7 May 2007 20:33:34 -0400 Subject: firewire: Coding style cleanup: no spaces after function names. Signed-off-by: Kristian Hoegsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-card.c | 12 +++++------ drivers/firewire/fw-sbp2.c | 4 ++-- drivers/firewire/fw-topology.c | 6 +++--- drivers/firewire/fw-topology.h | 2 +- drivers/firewire/fw-transaction.h | 42 +++++++++++++++++++-------------------- 5 files changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 3322d6169bd..74aab9aafd2 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -60,7 +60,7 @@ static int descriptor_count; #define bib_imc ((1) << 31) static u32 * -generate_config_rom (struct fw_card *card, size_t *config_rom_length) +generate_config_rom(struct fw_card *card, size_t *config_rom_length) { struct fw_descriptor *desc; static u32 config_rom[256]; @@ -125,7 +125,7 @@ generate_config_rom (struct fw_card *card, size_t *config_rom_length) } static void -update_config_roms (void) +update_config_roms(void) { struct fw_card *card; u32 *config_rom; @@ -138,7 +138,7 @@ update_config_roms (void) } int -fw_core_add_descriptor (struct fw_descriptor *desc) +fw_core_add_descriptor(struct fw_descriptor *desc) { size_t i; @@ -156,7 +156,7 @@ fw_core_add_descriptor (struct fw_descriptor *desc) mutex_lock(&card_mutex); - list_add_tail (&desc->link, &descriptor_list); + list_add_tail(&desc->link, &descriptor_list); descriptor_count++; if (desc->immediate > 0) descriptor_count++; @@ -169,7 +169,7 @@ fw_core_add_descriptor (struct fw_descriptor *desc) EXPORT_SYMBOL(fw_core_add_descriptor); void -fw_core_remove_descriptor (struct fw_descriptor *desc) +fw_core_remove_descriptor(struct fw_descriptor *desc) { mutex_lock(&card_mutex); @@ -419,7 +419,7 @@ fw_card_add(struct fw_card *card, fw_card_get(card); mutex_lock(&card_mutex); - config_rom = generate_config_rom (card, &length); + config_rom = generate_config_rom(card, &length); list_add_tail(&card->link, &card_list); mutex_unlock(&card_mutex); diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index eb3bddb162e..3308bc089be 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -47,7 +47,7 @@ #include "fw-device.h" /* I don't know why the SCSI stack doesn't define something like this... */ -typedef void (*scsi_done_fn_t) (struct scsi_cmnd *); +typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); static const char sbp2_driver_name[] = "sbp2"; @@ -148,7 +148,7 @@ struct sbp2_orb { dma_addr_t request_bus; int rcode; struct sbp2_pointer pointer; - void (*callback) (struct sbp2_orb * orb, struct sbp2_status * status); + void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status); struct list_head link; }; diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index c26d5d5e8d5..490490205ea 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c @@ -300,9 +300,9 @@ static struct fw_node *build_tree(struct fw_card *card, return local_node; } -typedef void (*fw_node_callback_t) (struct fw_card * card, - struct fw_node * node, - struct fw_node * parent); +typedef void (*fw_node_callback_t)(struct fw_card * card, + struct fw_node * node, + struct fw_node * parent); static void for_each_fw_node(struct fw_card *card, struct fw_node *root, diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h index be2a6bed384..363b6cbcd0b 100644 --- a/drivers/firewire/fw-topology.h +++ b/drivers/firewire/fw-topology.h @@ -64,7 +64,7 @@ struct fw_node { static inline struct fw_node * fw_node(struct list_head *l) { - return list_entry (l, struct fw_node, link); + return list_entry(l, struct fw_node, link); } static inline struct fw_node * diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 1b7e4dc6c2c..a1507cf8d76 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -172,11 +172,11 @@ struct fw_descriptor { const u32 *data; }; -int fw_core_add_descriptor (struct fw_descriptor *desc); -void fw_core_remove_descriptor (struct fw_descriptor *desc); +int fw_core_add_descriptor(struct fw_descriptor *desc); +void fw_core_remove_descriptor(struct fw_descriptor *desc); -typedef void (*fw_packet_callback_t) (struct fw_packet *packet, - struct fw_card *card, int status); +typedef void (*fw_packet_callback_t)(struct fw_packet *packet, + struct fw_card *card, int status); typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, void *data, @@ -239,7 +239,7 @@ struct fw_transaction { static inline struct fw_packet * fw_packet(struct list_head *l) { - return list_entry (l, struct fw_packet, link); + return list_entry(l, struct fw_packet, link); } struct fw_address_handler { @@ -350,11 +350,11 @@ struct fw_iso_packet { struct fw_iso_context; -typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, - u32 cycle, - size_t header_length, - void *header, - void *data); +typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, + u32 cycle, + size_t header_length, + void *header, + void *data); /* * An iso buffer is just a set of pages mapped for DMA in the @@ -420,23 +420,23 @@ struct fw_card_driver { * enable the PHY or set the link_on bit and initiate a bus * reset. */ - int (*enable) (struct fw_card *card, u32 *config_rom, size_t length); + int (*enable)(struct fw_card *card, u32 *config_rom, size_t length); - int (*update_phy_reg) (struct fw_card *card, int address, - int clear_bits, int set_bits); + int (*update_phy_reg)(struct fw_card *card, int address, + int clear_bits, int set_bits); /* * Update the config rom for an enabled card. This function * should change the config rom that is presented on the bus * an initiate a bus reset. */ - int (*set_config_rom) (struct fw_card *card, - u32 *config_rom, size_t length); + int (*set_config_rom)(struct fw_card *card, + u32 *config_rom, size_t length); - void (*send_request) (struct fw_card *card, struct fw_packet *packet); - void (*send_response) (struct fw_card *card, struct fw_packet *packet); + void (*send_request)(struct fw_card *card, struct fw_packet *packet); + void (*send_response)(struct fw_card *card, struct fw_packet *packet); /* Calling cancel is valid once a packet has been submitted. */ - int (*cancel_packet) (struct fw_card *card, struct fw_packet *packet); + int (*cancel_packet)(struct fw_card *card, struct fw_packet *packet); /* * Allow the specified node ID to do direct DMA out and in of @@ -446,10 +446,10 @@ struct fw_card_driver { * doesn't support this, -ESTALE if the generation doesn't * match. */ - int (*enable_phys_dma) (struct fw_card *card, - int node_id, int generation); + int (*enable_phys_dma)(struct fw_card *card, + int node_id, int generation); - u64 (*get_bus_time) (struct fw_card *card); + u64 (*get_bus_time)(struct fw_card *card); struct fw_iso_context * (*allocate_iso_context)(struct fw_card *card, -- cgit v1.2.3-70-g09d2 From 4c5a443e80e6d85e5c84a56bf30b61fe84c1f292 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Mon, 7 May 2007 20:33:37 -0400 Subject: firewire: Break out shared IEEE1394 constant to separate header file. Signed-off-by: Kristian Hoegsberg Signed-off-by: Stefan Richter --- drivers/firewire/fw-transaction.h | 61 +--------------------------------- include/linux/firewire-cdev.h | 51 ++++------------------------- include/linux/firewire-constants.h | 67 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 105 deletions(-) create mode 100644 include/linux/firewire-constants.h (limited to 'drivers/firewire/fw-transaction.h') diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index a1507cf8d76..acdc3be38c6 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -25,18 +25,7 @@ #include #include #include - -#define TCODE_WRITE_QUADLET_REQUEST 0 -#define TCODE_WRITE_BLOCK_REQUEST 1 -#define TCODE_WRITE_RESPONSE 2 -#define TCODE_READ_QUADLET_REQUEST 4 -#define TCODE_READ_BLOCK_REQUEST 5 -#define TCODE_READ_QUADLET_RESPONSE 6 -#define TCODE_READ_BLOCK_RESPONSE 7 -#define TCODE_CYCLE_START 8 -#define TCODE_LOCK_REQUEST 9 -#define TCODE_STREAM_DATA 10 -#define TCODE_LOCK_RESPONSE 11 +#include #define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) #define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) @@ -45,54 +34,6 @@ #define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4) #define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0) -/* Juju specific tcodes */ -#define TCODE_DEALLOCATE 0x10 -#define TCODE_LOCK_MASK_SWAP 0x11 -#define TCODE_LOCK_COMPARE_SWAP 0x12 -#define TCODE_LOCK_FETCH_ADD 0x13 -#define TCODE_LOCK_LITTLE_ADD 0x14 -#define TCODE_LOCK_BOUNDED_ADD 0x15 -#define TCODE_LOCK_WRAP_ADD 0x16 -#define TCODE_LOCK_VENDOR_SPECIFIC 0x17 - -#define SCODE_100 0x0 -#define SCODE_200 0x1 -#define SCODE_400 0x2 -#define SCODE_BETA 0x3 - -#define EXTCODE_MASK_SWAP 0x1 -#define EXTCODE_COMPARE_SWAP 0x2 -#define EXTCODE_FETCH_ADD 0x3 -#define EXTCODE_LITTLE_ADD 0x4 -#define EXTCODE_BOUNDED_ADD 0x5 -#define EXTCODE_WRAP_ADD 0x6 - -#define ACK_COMPLETE 0x1 -#define ACK_PENDING 0x2 -#define ACK_BUSY_X 0x4 -#define ACK_BUSY_A 0x5 -#define ACK_BUSY_B 0x6 -#define ACK_DATA_ERROR 0xd -#define ACK_TYPE_ERROR 0xe - -#define RCODE_COMPLETE 0x0 -#define RCODE_CONFLICT_ERROR 0x4 -#define RCODE_DATA_ERROR 0x5 -#define RCODE_TYPE_ERROR 0x6 -#define RCODE_ADDRESS_ERROR 0x7 - -/* Juju specific rcodes */ -#define RCODE_SEND_ERROR 0x10 -#define RCODE_CANCELLED 0x11 -#define RCODE_BUSY 0x12 -#define RCODE_GENERATION 0x13 -#define RCODE_NO_ACK 0x14 - -#define RETRY_1 0x00 -#define RETRY_X 0x01 -#define RETRY_A 0x02 -#define RETRY_B 0x03 - #define LOCAL_BUS 0xffc0 #define SELFID_PORT_CHILD 0x3 diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 3cb83a1fa9b..d4455eb2ae3 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -1,6 +1,5 @@ -/* -*- c-basic-offset: 8 -*- - * - * fw-device-cdev.h -- Char device interface. +/* + * Char device interface. * * Copyright (C) 2005-2006 Kristian Hoegsberg * @@ -19,50 +18,12 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __fw_cdev_h -#define __fw_cdev_h +#ifndef _LINUX_FIREWIRE_CDEV_H +#define _LINUX_FIREWIRE_CDEV_H #include #include - -#define TCODE_WRITE_QUADLET_REQUEST 0 -#define TCODE_WRITE_BLOCK_REQUEST 1 -#define TCODE_WRITE_RESPONSE 2 -#define TCODE_READ_QUADLET_REQUEST 4 -#define TCODE_READ_BLOCK_REQUEST 5 -#define TCODE_READ_QUADLET_RESPONSE 6 -#define TCODE_READ_BLOCK_RESPONSE 7 -#define TCODE_CYCLE_START 8 -#define TCODE_LOCK_REQUEST 9 -#define TCODE_STREAM_DATA 10 -#define TCODE_LOCK_RESPONSE 11 - -#define TCODE_LOCK_MASK_SWAP 0x11 -#define TCODE_LOCK_COMPARE_SWAP 0x12 -#define TCODE_LOCK_FETCH_ADD 0x13 -#define TCODE_LOCK_LITTLE_ADD 0x14 -#define TCODE_LOCK_BOUNDED_ADD 0x15 -#define TCODE_LOCK_WRAP_ADD 0x16 -#define TCODE_LOCK_VENDOR_DEPENDENT 0x17 - -#define RCODE_COMPLETE 0x0 -#define RCODE_CONFLICT_ERROR 0x4 -#define RCODE_DATA_ERROR 0x5 -#define RCODE_TYPE_ERROR 0x6 -#define RCODE_ADDRESS_ERROR 0x7 - -#define RCODE_SEND_ERROR 0x10 -#define RCODE_CANCELLED 0x11 -#define RCODE_BUSY 0x12 -#define RCODE_GENERATION 0x13 -#define RCODE_NO_ACK 0x14 - -#define SCODE_100 0x0 -#define SCODE_200 0x1 -#define SCODE_400 0x2 -#define SCODE_800 0x3 -#define SCODE_1600 0x4 -#define SCODE_3200 0x5 +#include #define FW_CDEV_EVENT_BUS_RESET 0x00 #define FW_CDEV_EVENT_RESPONSE 0x01 @@ -265,4 +226,4 @@ struct fw_cdev_stop_iso { __u32 handle; }; -#endif /* __fw_cdev_h */ +#endif /* _LINUX_FIREWIRE_CDEV_H */ diff --git a/include/linux/firewire-constants.h b/include/linux/firewire-constants.h new file mode 100644 index 00000000000..b316770a43f --- /dev/null +++ b/include/linux/firewire-constants.h @@ -0,0 +1,67 @@ +#ifndef _LINUX_FIREWIRE_CONSTANTS_H +#define _LINUX_FIREWIRE_CONSTANTS_H + +#define TCODE_WRITE_QUADLET_REQUEST 0x0 +#define TCODE_WRITE_BLOCK_REQUEST 0x1 +#define TCODE_WRITE_RESPONSE 0x2 +#define TCODE_READ_QUADLET_REQUEST 0x4 +#define TCODE_READ_BLOCK_REQUEST 0x5 +#define TCODE_READ_QUADLET_RESPONSE 0x6 +#define TCODE_READ_BLOCK_RESPONSE 0x7 +#define TCODE_CYCLE_START 0x8 +#define TCODE_LOCK_REQUEST 0x9 +#define TCODE_STREAM_DATA 0xa +#define TCODE_LOCK_RESPONSE 0xb + +#define EXTCODE_MASK_SWAP 0x1 +#define EXTCODE_COMPARE_SWAP 0x2 +#define EXTCODE_FETCH_ADD 0x3 +#define EXTCODE_LITTLE_ADD 0x4 +#define EXTCODE_BOUNDED_ADD 0x5 +#define EXTCODE_WRAP_ADD 0x6 +#define EXTCODE_VENDOR_DEPENDENT 0x7 + +/* Juju specific tcodes */ +#define TCODE_LOCK_MASK_SWAP (0x10 | EXTCODE_MASK_SWAP) +#define TCODE_LOCK_COMPARE_SWAP (0x10 | EXTCODE_COMPARE_SWAP) +#define TCODE_LOCK_FETCH_ADD (0x10 | EXTCODE_FETCH_ADD) +#define TCODE_LOCK_LITTLE_ADD (0x10 | EXTCODE_LITTLE_ADD) +#define TCODE_LOCK_BOUNDED_ADD (0x10 | EXTCODE_BOUNDED_ADD) +#define TCODE_LOCK_WRAP_ADD (0x10 | EXTCODE_WRAP_ADD) +#define TCODE_LOCK_VENDOR_DEPENDENT (0x10 | EXTCODE_VENDOR_DEPENDENT) + +#define RCODE_COMPLETE 0x0 +#define RCODE_CONFLICT_ERROR 0x4 +#define RCODE_DATA_ERROR 0x5 +#define RCODE_TYPE_ERROR 0x6 +#define RCODE_ADDRESS_ERROR 0x7 + +/* Juju specific rcodes */ +#define RCODE_SEND_ERROR 0x10 +#define RCODE_CANCELLED 0x11 +#define RCODE_BUSY 0x12 +#define RCODE_GENERATION 0x13 +#define RCODE_NO_ACK 0x14 + +#define SCODE_100 0x0 +#define SCODE_200 0x1 +#define SCODE_400 0x2 +#define SCODE_800 0x3 +#define SCODE_1600 0x4 +#define SCODE_3200 0x5 +#define SCODE_BETA 0x3 + +#define ACK_COMPLETE 0x1 +#define ACK_PENDING 0x2 +#define ACK_BUSY_X 0x4 +#define ACK_BUSY_A 0x5 +#define ACK_BUSY_B 0x6 +#define ACK_DATA_ERROR 0xd +#define ACK_TYPE_ERROR 0xe + +#define RETRY_1 0x00 +#define RETRY_X 0x01 +#define RETRY_A 0x02 +#define RETRY_B 0x03 + +#endif /* _LINUX_FIREWIRE_CONSTANTS_H */ -- cgit v1.2.3-70-g09d2