aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-cdev.c64
-rw-r--r--include/linux/firewire-cdev.h44
2 files changed, 107 insertions, 1 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index acf4fa1f3f8c..f95719926487 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -194,6 +194,13 @@ struct iso_resource_event {
194 struct fw_cdev_event_iso_resource iso_resource; 194 struct fw_cdev_event_iso_resource iso_resource;
195}; 195};
196 196
197struct outbound_phy_packet_event {
198 struct event event;
199 struct client *client;
200 struct fw_packet p;
201 struct fw_cdev_event_phy_packet phy_packet;
202};
203
197static inline void __user *u64_to_uptr(__u64 value) 204static inline void __user *u64_to_uptr(__u64 value)
198{ 205{
199 return (void __user *)(unsigned long)value; 206 return (void __user *)(unsigned long)value;
@@ -396,6 +403,7 @@ union ioctl_arg {
396 struct fw_cdev_allocate_iso_resource allocate_iso_resource; 403 struct fw_cdev_allocate_iso_resource allocate_iso_resource;
397 struct fw_cdev_send_stream_packet send_stream_packet; 404 struct fw_cdev_send_stream_packet send_stream_packet;
398 struct fw_cdev_get_cycle_timer2 get_cycle_timer2; 405 struct fw_cdev_get_cycle_timer2 get_cycle_timer2;
406 struct fw_cdev_send_phy_packet send_phy_packet;
399}; 407};
400 408
401static int ioctl_get_info(struct client *client, union ioctl_arg *arg) 409static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
@@ -1384,6 +1392,61 @@ static int ioctl_send_stream_packet(struct client *client, union ioctl_arg *arg)
1384 return init_request(client, &request, dest, a->speed); 1392 return init_request(client, &request, dest, a->speed);
1385} 1393}
1386 1394
1395static void outbound_phy_packet_callback(struct fw_packet *packet,
1396 struct fw_card *card, int status)
1397{
1398 struct outbound_phy_packet_event *e =
1399 container_of(packet, struct outbound_phy_packet_event, p);
1400
1401 switch (status) {
1402 /* expected: */
1403 case ACK_COMPLETE: e->phy_packet.rcode = RCODE_COMPLETE; break;
1404 /* should never happen with PHY packets: */
1405 case ACK_PENDING: e->phy_packet.rcode = RCODE_COMPLETE; break;
1406 case ACK_BUSY_X:
1407 case ACK_BUSY_A:
1408 case ACK_BUSY_B: e->phy_packet.rcode = RCODE_BUSY; break;
1409 case ACK_DATA_ERROR: e->phy_packet.rcode = RCODE_DATA_ERROR; break;
1410 case ACK_TYPE_ERROR: e->phy_packet.rcode = RCODE_TYPE_ERROR; break;
1411 /* stale generation; cancelled; on certain controllers: no ack */
1412 default: e->phy_packet.rcode = status; break;
1413 }
1414
1415 queue_event(e->client, &e->event,
1416 &e->phy_packet, sizeof(e->phy_packet), NULL, 0);
1417 client_put(e->client);
1418}
1419
1420static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
1421{
1422 struct fw_cdev_send_phy_packet *a = &arg->send_phy_packet;
1423 struct fw_card *card = client->device->card;
1424 struct outbound_phy_packet_event *e;
1425
1426 /* Access policy: Allow this ioctl only on local nodes' device files. */
1427 if (!client->device->is_local)
1428 return -ENOSYS;
1429
1430 e = kzalloc(sizeof(*e), GFP_KERNEL);
1431 if (e == NULL)
1432 return -ENOMEM;
1433
1434 client_get(client);
1435 e->client = client;
1436 e->p.speed = SCODE_100;
1437 e->p.generation = a->generation;
1438 e->p.header[0] = a->data[0];
1439 e->p.header[1] = a->data[1];
1440 e->p.header_length = 8;
1441 e->p.callback = outbound_phy_packet_callback;
1442 e->phy_packet.closure = a->closure;
1443 e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_SENT;
1444
1445 card->driver->send_request(card, &e->p);
1446
1447 return 0;
1448}
1449
1387static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = { 1450static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
1388 [0x00] = ioctl_get_info, 1451 [0x00] = ioctl_get_info,
1389 [0x01] = ioctl_send_request, 1452 [0x01] = ioctl_send_request,
@@ -1406,6 +1469,7 @@ static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
1406 [0x12] = ioctl_send_broadcast_request, 1469 [0x12] = ioctl_send_broadcast_request,
1407 [0x13] = ioctl_send_stream_packet, 1470 [0x13] = ioctl_send_stream_packet,
1408 [0x14] = ioctl_get_cycle_timer2, 1471 [0x14] = ioctl_get_cycle_timer2,
1472 [0x15] = ioctl_send_phy_packet,
1409}; 1473};
1410 1474
1411static int dispatch_ioctl(struct client *client, 1475static int dispatch_ioctl(struct client *client,
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index fde9568151d5..5bc051b9a013 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -34,6 +34,7 @@
34 34
35/* available since kernel version 2.6.36 */ 35/* available since kernel version 2.6.36 */
36#define FW_CDEV_EVENT_REQUEST2 0x06 36#define FW_CDEV_EVENT_REQUEST2 0x06
37#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07
37 38
38/** 39/**
39 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types 40 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
@@ -284,6 +285,19 @@ struct fw_cdev_event_iso_resource {
284}; 285};
285 286
286/** 287/**
288 * struct fw_cdev_event_phy_packet - A PHY packet was transmitted
289 * @closure: See &fw_cdev_event_common;
290 * set by %FW_CDEV_IOC_SEND_PHY_PACKET ioctl
291 * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT
292 * @rcode: %RCODE_..., indicates success or failure of transmission
293 */
294struct fw_cdev_event_phy_packet {
295 __u64 closure;
296 __u32 type;
297 __u32 rcode;
298};
299
300/**
287 * union fw_cdev_event - Convenience union of fw_cdev_event_ types 301 * union fw_cdev_event - Convenience union of fw_cdev_event_ types
288 * @common: Valid for all types 302 * @common: Valid for all types
289 * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET 303 * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
@@ -294,6 +308,7 @@ struct fw_cdev_event_iso_resource {
294 * @iso_resource: Valid if @common.type == 308 * @iso_resource: Valid if @common.type ==
295 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or 309 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or
296 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 310 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED
311 * @phy_packet: Valid if @common.type == %FW_CDEV_EVENT_PHY_PACKET_SENT
297 * 312 *
298 * Convenience union for userspace use. Events could be read(2) into an 313 * Convenience union for userspace use. Events could be read(2) into an
299 * appropriately aligned char buffer and then cast to this union for further 314 * appropriately aligned char buffer and then cast to this union for further
@@ -311,6 +326,7 @@ union fw_cdev_event {
311 struct fw_cdev_event_request2 request2; /* added in 2.6.36 */ 326 struct fw_cdev_event_request2 request2; /* added in 2.6.36 */
312 struct fw_cdev_event_iso_interrupt iso_interrupt; 327 struct fw_cdev_event_iso_interrupt iso_interrupt;
313 struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ 328 struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */
329 struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */
314}; 330};
315 331
316/* available since kernel version 2.6.22 */ 332/* available since kernel version 2.6.22 */
@@ -342,6 +358,9 @@ union fw_cdev_event {
342/* available since kernel version 2.6.34 */ 358/* available since kernel version 2.6.34 */
343#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2) 359#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)
344 360
361/* available since kernel version 2.6.36 */
362#define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet)
363
345/* 364/*
346 * ABI version history 365 * ABI version history
347 * 1 (2.6.22) - initial version 366 * 1 (2.6.22) - initial version
@@ -357,8 +376,9 @@ union fw_cdev_event {
357 * - shared use and auto-response for FCP registers 376 * - shared use and auto-response for FCP registers
358 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable 377 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable
359 * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 378 * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2
360 * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2 379 * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_SENT
361 * - implemented &fw_cdev_event_bus_reset.bm_node_id 380 * - implemented &fw_cdev_event_bus_reset.bm_node_id
381 * - added %FW_CDEV_IOC_SEND_PHY_PACKET
362 */ 382 */
363#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ 383#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */
364 384
@@ -808,4 +828,26 @@ struct fw_cdev_send_stream_packet {
808 __u32 speed; 828 __u32 speed;
809}; 829};
810 830
831/**
832 * struct fw_cdev_send_phy_packet - send a PHY packet
833 * @closure: Passed back to userspace in the PHY-packet-sent event
834 * @data: First and second quadlet of the PHY packet
835 * @generation: The bus generation where packet is valid
836 *
837 * The %FW_CDEV_IOC_SEND_PHY_PACKET ioctl sends a PHY packet to all nodes
838 * on the same card as this device. After transmission, an
839 * %FW_CDEV_EVENT_PHY_PACKET_SENT event is generated.
840 *
841 * The payload @data[] shall be specified in host byte order. Usually,
842 * @data[1] needs to be the bitwise inverse of @data[0]. VersaPHY packets
843 * are an exception to this rule.
844 *
845 * The ioctl is only permitted on device files which represent a local node.
846 */
847struct fw_cdev_send_phy_packet {
848 __u64 closure;
849 __u32 data[2];
850 __u32 generation;
851};
852
811#endif /* _LINUX_FIREWIRE_CDEV_H */ 853#endif /* _LINUX_FIREWIRE_CDEV_H */