aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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 95a207545eb3..7eb6594cc3e5 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -522,7 +522,8 @@ static int init_request(struct client *client,
522 struct outbound_transaction_event *e; 522 struct outbound_transaction_event *e;
523 int ret; 523 int ret;
524 524
525 if (request->length > 4096 || request->length > 512 << speed) 525 if (request->tcode != TCODE_STREAM_DATA &&
526 (request->length > 4096 || request->length > 512 << speed))
526 return -EIO; 527 return -EIO;
527 528
528 e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL); 529 e = kmalloc(sizeof(*e) + request->length, GFP_KERNEL);
@@ -1247,36 +1248,27 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer)
1247 return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); 1248 return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100);
1248} 1249}
1249 1250
1250struct stream_packet {
1251 struct fw_packet packet;
1252 u8 data[0];
1253};
1254
1255static void send_stream_packet_done(struct fw_packet *packet,
1256 struct fw_card *card, int status)
1257{
1258 kfree(container_of(packet, struct stream_packet, packet));
1259}
1260
1261static int ioctl_send_stream_packet(struct client *client, void *buffer) 1251static int ioctl_send_stream_packet(struct client *client, void *buffer)
1262{ 1252{
1263 struct fw_cdev_send_stream_packet *request = buffer; 1253 struct fw_cdev_send_stream_packet *p = buffer;
1264 struct stream_packet *p; 1254 struct fw_cdev_send_request request;
1255 int dest;
1265 1256
1266 p = kmalloc(sizeof(*p) + request->size, GFP_KERNEL); 1257 if (p->speed > client->device->card->link_speed ||
1267 if (p == NULL) 1258 p->length > 1024 << p->speed)
1268 return -ENOMEM; 1259 return -EIO;
1269 1260
1270 if (request->data && 1261 if (p->tag > 3 || p->channel > 63 || p->sy > 15)
1271 copy_from_user(p->data, u64_to_uptr(request->data), request->size)) { 1262 return -EINVAL;
1272 kfree(p); 1263
1273 return -EFAULT; 1264 dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy);
1274 } 1265 request.tcode = TCODE_STREAM_DATA;
1275 fw_send_stream_packet(client->device->card, &p->packet, 1266 request.length = p->length;
1276 request->generation, request->speed, 1267 request.closure = p->closure;
1277 request->channel, request->sy, request->tag, 1268 request.data = p->data;
1278 p->data, request->size, send_stream_packet_done); 1269 request.generation = p->generation;
1279 return 0; 1270
1271 return init_request(client, &request, dest, p->speed);
1280} 1272}
1281 1273
1282static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { 1274static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index e3da58991960..4a9b37461c26 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -37,10 +37,6 @@
37#include "fw-topology.h" 37#include "fw-topology.h"
38#include "fw-device.h" 38#include "fw-device.h"
39 39
40#define HEADER_TAG(tag) ((tag) << 14)
41#define HEADER_CHANNEL(ch) ((ch) << 8)
42#define HEADER_SY(sy) ((sy) << 0)
43
44#define HEADER_PRI(pri) ((pri) << 0) 40#define HEADER_PRI(pri) ((pri) << 0)
45#define HEADER_TCODE(tcode) ((tcode) << 4) 41#define HEADER_TCODE(tcode) ((tcode) << 4)
46#define HEADER_RETRY(retry) ((retry) << 8) 42#define HEADER_RETRY(retry) ((retry) << 8)
@@ -158,6 +154,18 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
158{ 154{
159 int ext_tcode; 155 int ext_tcode;
160 156
157 if (tcode == TCODE_STREAM_DATA) {
158 packet->header[0] =
159 HEADER_DATA_LENGTH(length) |
160 destination_id |
161 HEADER_TCODE(TCODE_STREAM_DATA);
162 packet->header_length = 4;
163 packet->payload = payload;
164 packet->payload_length = length;
165
166 goto common;
167 }
168
161 if (tcode > 0x10) { 169 if (tcode > 0x10) {
162 ext_tcode = tcode & ~0x10; 170 ext_tcode = tcode & ~0x10;
163 tcode = TCODE_LOCK_REQUEST; 171 tcode = TCODE_LOCK_REQUEST;
@@ -204,7 +212,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
204 packet->payload_length = 0; 212 packet->payload_length = 0;
205 break; 213 break;
206 } 214 }
207 215 common:
208 packet->speed = speed; 216 packet->speed = speed;
209 packet->generation = generation; 217 packet->generation = generation;
210 packet->ack = 0; 218 packet->ack = 0;
@@ -246,6 +254,9 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
246 * @param callback function to be called when the transaction is completed 254 * @param callback function to be called when the transaction is completed
247 * @param callback_data pointer to arbitrary data, which will be 255 * @param callback_data pointer to arbitrary data, which will be
248 * passed to the callback 256 * passed to the callback
257 *
258 * In case of asynchronous stream packets i.e. TCODE_STREAM_DATA, the caller
259 * needs to synthesize @destination_id with fw_stream_packet_destination_id().
249 */ 260 */
250void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, 261void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode,
251 int destination_id, int generation, int speed, 262 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,
297} 308}
298EXPORT_SYMBOL(fw_send_request); 309EXPORT_SYMBOL(fw_send_request);
299 310
300void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p,
301 int generation, int speed, int channel, int sy, int tag,
302 void *payload, size_t length, fw_packet_callback_t callback)
303{
304 p->callback = callback;
305 p->header[0] =
306 HEADER_DATA_LENGTH(length)
307 | HEADER_TAG(tag)
308 | HEADER_CHANNEL(channel)
309 | HEADER_TCODE(TCODE_STREAM_DATA)
310 | HEADER_SY(sy);
311 p->header_length = 4;
312 p->payload = payload;
313 p->payload_length = length;
314 p->speed = speed;
315 p->generation = generation;
316 p->ack = 0;
317
318 card->driver->send_request(card, p);
319}
320
321struct transaction_callback_data { 311struct transaction_callback_data {
322 struct completion done; 312 struct completion done;
323 void *payload; 313 void *payload;
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index f90f09c05833..d4f42cecbdfa 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,
412 int tcode, int destination_id, int generation, int speed, 412 int tcode, int destination_id, int generation, int speed,
413 unsigned long long offset, void *payload, size_t length, 413 unsigned long long offset, void *payload, size_t length,
414 fw_transaction_callback_t callback, void *callback_data); 414 fw_transaction_callback_t callback, void *callback_data);
415void fw_send_stream_packet(struct fw_card *card, struct fw_packet *p,
416 int generation, int speed, int channel, int sy, int tag,
417 void *payload, size_t length, fw_packet_callback_t callback);
418
419int fw_cancel_transaction(struct fw_card *card, 415int fw_cancel_transaction(struct fw_card *card,
420 struct fw_transaction *transaction); 416 struct fw_transaction *transaction);
421void fw_flush_transactions(struct fw_card *card); 417void fw_flush_transactions(struct fw_card *card);
@@ -425,6 +421,11 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
425void fw_send_phy_config(struct fw_card *card, 421void fw_send_phy_config(struct fw_card *card,
426 int node_id, int generation, int gap_count); 422 int node_id, int generation, int gap_count);
427 423
424static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
425{
426 return tag << 14 | channel << 8 | sy;
427}
428
428/* 429/*
429 * Called by the topology code to inform the device code of node 430 * Called by the topology code to inform the device code of node
430 * activity; found, lost, or updated nodes. 431 * activity; found, lost, or updated nodes.