Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 136028
b: refs/heads/master
c: 18e9b10
h: refs/heads/master
v: v3
  • Loading branch information
Stefan Richter committed Mar 24, 2009
1 parent 1650647 commit f4ffe69
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 73 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 664d8010b170ae8b3ce9268b4f4da934d27b0491
refs/heads/master: 18e9b10fcdc090d3a38606958167d5923c7099b7
46 changes: 19 additions & 27 deletions trunk/drivers/firewire/fw-cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,8 @@ static int init_request(struct client *client,
struct outbound_transaction_event *e;
int ret;

if (request->length > 4096 || request->length > 512 << speed)
if (request->tcode != TCODE_STREAM_DATA &&
(request->length > 4096 || request->length > 512 << speed))
return -EIO;

e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
Expand Down Expand Up @@ -1247,36 +1248,27 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer)
return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100);
}

struct stream_packet {
struct fw_packet packet;
u8 data[0];
};

static void send_stream_packet_done(struct fw_packet *packet,
struct fw_card *card, int status)
{
kfree(container_of(packet, struct stream_packet, packet));
}

static int ioctl_send_stream_packet(struct client *client, void *buffer)
{
struct fw_cdev_send_stream_packet *request = buffer;
struct stream_packet *p;
struct fw_cdev_send_stream_packet *p = buffer;
struct fw_cdev_send_request request;
int dest;

p = kmalloc(sizeof(*p) + request->size, GFP_KERNEL);
if (p == NULL)
return -ENOMEM;
if (p->speed > client->device->card->link_speed ||
p->length > 1024 << p->speed)
return -EIO;

if (request->data &&
copy_from_user(p->data, u64_to_uptr(request->data), request->size)) {
kfree(p);
return -EFAULT;
}
fw_send_stream_packet(client->device->card, &p->packet,
request->generation, request->speed,
request->channel, request->sy, request->tag,
p->data, request->size, send_stream_packet_done);
return 0;
if (p->tag > 3 || p->channel > 63 || p->sy > 15)
return -EINVAL;

dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy);
request.tcode = TCODE_STREAM_DATA;
request.length = p->length;
request.closure = p->closure;
request.data = p->data;
request.generation = p->generation;

return init_request(client, &request, dest, p->speed);
}

static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
Expand Down
42 changes: 16 additions & 26 deletions trunk/drivers/firewire/fw-transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@
#include "fw-topology.h"
#include "fw-device.h"

#define HEADER_TAG(tag) ((tag) << 14)
#define HEADER_CHANNEL(ch) ((ch) << 8)
#define HEADER_SY(sy) ((sy) << 0)

#define HEADER_PRI(pri) ((pri) << 0)
#define HEADER_TCODE(tcode) ((tcode) << 4)
#define HEADER_RETRY(retry) ((retry) << 8)
Expand Down Expand Up @@ -158,6 +154,18 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
{
int ext_tcode;

if (tcode == TCODE_STREAM_DATA) {
packet->header[0] =
HEADER_DATA_LENGTH(length) |
destination_id |
HEADER_TCODE(TCODE_STREAM_DATA);
packet->header_length = 4;
packet->payload = payload;
packet->payload_length = length;

goto common;
}

if (tcode > 0x10) {
ext_tcode = tcode & ~0x10;
tcode = TCODE_LOCK_REQUEST;
Expand Down Expand Up @@ -204,7 +212,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
packet->payload_length = 0;
break;
}

common:
packet->speed = speed;
packet->generation = generation;
packet->ack = 0;
Expand Down Expand Up @@ -246,6 +254,9 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
* @param callback function to be called when the transaction is completed
* @param callback_data pointer to arbitrary data, which will be
* passed to the callback
*
* In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller
* needs to synthesize @destination_id with fw_stream_packet_destination_id().
*/
void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
int destination_id, int generation, int speed,
Expand Down Expand Up @@ -297,27 +308,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
}
EXPORT_SYMBOL(fw_send_request);

void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p,
int generation, int speed, int channel, int sy, int tag,
void *payload, size_t length, fw_packet_callback_t callback)
{
p->callback = callback;
p->header[0] =
HEADER_DATA_LENGTH(length)
| HEADER_TAG(tag)
| HEADER_CHANNEL(channel)
| HEADER_TCODE(TCODE_STREAM_DATA)
| HEADER_SY(sy);
p->header_length = 4;
p->payload = payload;
p->payload_length = length;
p->speed = speed;
p->generation = generation;
p->ack = 0;

card->driver->send_request(card, p);
}

struct transaction_callback_data {
struct completion done;
void *payload;
Expand Down
9 changes: 5 additions & 4 deletions trunk/drivers/firewire/fw-transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,6 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int destination_id, int generation, int speed,
unsigned long long offset, void *payload, size_t length,
fw_transaction_callback_t callback, void *callback_data);
void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p,
int generation, int speed, int channel, int sy, int tag,
void *payload, size_t length, fw_packet_callback_t callback);

int fw_cancel_transaction(struct fw_card *card,
struct fw_transaction *transaction);
void fw_flush_transactions(struct fw_card *card);
Expand All @@ -425,6 +421,11 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
void fw_send_phy_config(struct fw_card *card,
int node_id, int generation, int gap_count);

static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
{
return tag << 14 | channel << 8 | sy;
}

/*
* Called by the topology code to inform the device code of node
* activity; found, lost, or updated nodes.
Expand Down
31 changes: 16 additions & 15 deletions trunk/include/linux/firewire-cdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -606,28 +606,29 @@ struct fw_cdev_allocate_iso_resource {

/**
* struct fw_cdev_send_stream_packet - send an asynchronous stream packet
* @generation: Bus generation where the packet is valid
* @speed: Speed code to send the packet at
* @channel: Channel to send the packet on
* @sy: Four-bit sy code for the packet
* @tag: Two-bit tag field to use for the packet
* @size: Size of the packet's data payload
* @data: Userspace pointer to the payload
* @length: Length of outgoing payload, in bytes
* @tag: Data format tag
* @channel: Isochronous channel to transmit to
* @sy: Synchronization code
* @closure: Passed back to userspace in the response event
* @data: Userspace pointer to payload
* @generation: The bus generation where packet is valid
* @speed: Speed to transmit at
*
* The %FW_CDEV_IOC_SEND_STREAM_PACKET ioctl sends an asynchronous stream packet
* to every device (that is listening to the specified channel) on the
* firewire bus. It is the applications's job to ensure
* that the intended device(s) will be able to receive the packet at the chosen
* transmit speed.
* to every device which is listening to the specified channel. The kernel
* writes an &fw_cdev_event_response event which indicates success or failure of
* the transmission.
*/
struct fw_cdev_send_stream_packet {
__u32 generation;
__u32 speed;
__u32 length;
__u32 tag;
__u32 channel;
__u32 sy;
__u32 tag;
__u32 size;
__u64 closure;
__u64 data;
__u32 generation;
__u32 speed;
};

#endif /* _LINUX_FIREWIRE_CDEV_H */

0 comments on commit f4ffe69

Please sign in to comment.