aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/fw-cdev.c46
-rw-r--r--drivers/firewire/fw-transaction.c42
-rw-r--r--drivers/firewire/fw-transaction.h9
3 files changed, 40 insertions, 57 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 95a2075..7eb6594 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -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);
@@ -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) = {
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index e3da589..4a9b374 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -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)
@@ -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;
@@ -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;
@@ -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,
@@ -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;
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index f90f09c..d4f42ce 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -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);
@@ -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.