aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-card.c1
-rw-r--r--drivers/firewire/core-cdev.c73
-rw-r--r--drivers/firewire/core-transaction.c5
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/ohci.c3
-rw-r--r--include/linux/firewire-cdev.h39
-rw-r--r--include/linux/firewire.h3
7 files changed, 111 insertions, 15 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 0c312c4bb4b..6d1cfae6aad 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -500,6 +500,7 @@ void fw_card_initialize(struct fw_card *card,
500 kref_init(&card->kref); 500 kref_init(&card->kref);
501 init_completion(&card->done); 501 init_completion(&card->done);
502 INIT_LIST_HEAD(&card->transaction_list); 502 INIT_LIST_HEAD(&card->transaction_list);
503 INIT_LIST_HEAD(&card->phy_receiver_list);
503 spin_lock_init(&card->lock); 504 spin_lock_init(&card->lock);
504 505
505 card->local_node = NULL; 506 card->local_node = NULL;
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index f9571992648..0425dd5dfcd 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -69,6 +69,9 @@ struct client {
69 struct fw_iso_buffer buffer; 69 struct fw_iso_buffer buffer;
70 unsigned long vm_start; 70 unsigned long vm_start;
71 71
72 struct list_head phy_receiver_link;
73 u64 phy_receiver_closure;
74
72 struct list_head link; 75 struct list_head link;
73 struct kref kref; 76 struct kref kref;
74}; 77};
@@ -201,6 +204,11 @@ struct outbound_phy_packet_event {
201 struct fw_cdev_event_phy_packet phy_packet; 204 struct fw_cdev_event_phy_packet phy_packet;
202}; 205};
203 206
207struct inbound_phy_packet_event {
208 struct event event;
209 struct fw_cdev_event_phy_packet phy_packet;
210};
211
204static inline void __user *u64_to_uptr(__u64 value) 212static inline void __user *u64_to_uptr(__u64 value)
205{ 213{
206 return (void __user *)(unsigned long)value; 214 return (void __user *)(unsigned long)value;
@@ -236,6 +244,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
236 idr_init(&client->resource_idr); 244 idr_init(&client->resource_idr);
237 INIT_LIST_HEAD(&client->event_list); 245 INIT_LIST_HEAD(&client->event_list);
238 init_waitqueue_head(&client->wait); 246 init_waitqueue_head(&client->wait);
247 INIT_LIST_HEAD(&client->phy_receiver_link);
239 kref_init(&client->kref); 248 kref_init(&client->kref);
240 249
241 file->private_data = client; 250 file->private_data = client;
@@ -357,7 +366,7 @@ static void queue_bus_reset_event(struct client *client)
357 366
358 e = kzalloc(sizeof(*e), GFP_KERNEL); 367 e = kzalloc(sizeof(*e), GFP_KERNEL);
359 if (e == NULL) { 368 if (e == NULL) {
360 fw_notify("Out of memory when allocating bus reset event\n"); 369 fw_notify("Out of memory when allocating event\n");
361 return; 370 return;
362 } 371 }
363 372
@@ -404,6 +413,7 @@ union ioctl_arg {
404 struct fw_cdev_send_stream_packet send_stream_packet; 413 struct fw_cdev_send_stream_packet send_stream_packet;
405 struct fw_cdev_get_cycle_timer2 get_cycle_timer2; 414 struct fw_cdev_get_cycle_timer2 get_cycle_timer2;
406 struct fw_cdev_send_phy_packet send_phy_packet; 415 struct fw_cdev_send_phy_packet send_phy_packet;
416 struct fw_cdev_receive_phy_packets receive_phy_packets;
407}; 417};
408 418
409static int ioctl_get_info(struct client *client, union ioctl_arg *arg) 419static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
@@ -671,9 +681,10 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
671 681
672 r = kmalloc(sizeof(*r), GFP_ATOMIC); 682 r = kmalloc(sizeof(*r), GFP_ATOMIC);
673 e = kmalloc(sizeof(*e), GFP_ATOMIC); 683 e = kmalloc(sizeof(*e), GFP_ATOMIC);
674 if (r == NULL || e == NULL) 684 if (r == NULL || e == NULL) {
685 fw_notify("Out of memory when allocating event\n");
675 goto failed; 686 goto failed;
676 687 }
677 r->card = card; 688 r->card = card;
678 r->request = request; 689 r->request = request;
679 r->data = payload; 690 r->data = payload;
@@ -902,9 +913,10 @@ static void iso_callback(struct fw_iso_context *context, u32 cycle,
902 struct iso_interrupt_event *e; 913 struct iso_interrupt_event *e;
903 914
904 e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC); 915 e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC);
905 if (e == NULL) 916 if (e == NULL) {
917 fw_notify("Out of memory when allocating event\n");
906 return; 918 return;
907 919 }
908 e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; 920 e->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT;
909 e->interrupt.closure = client->iso_closure; 921 e->interrupt.closure = client->iso_closure;
910 e->interrupt.cycle = cycle; 922 e->interrupt.cycle = cycle;
@@ -1447,6 +1459,52 @@ static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
1447 return 0; 1459 return 0;
1448} 1460}
1449 1461
1462static int ioctl_receive_phy_packets(struct client *client, union ioctl_arg *arg)
1463{
1464 struct fw_cdev_receive_phy_packets *a = &arg->receive_phy_packets;
1465 struct fw_card *card = client->device->card;
1466
1467 /* Access policy: Allow this ioctl only on local nodes' device files. */
1468 if (!client->device->is_local)
1469 return -ENOSYS;
1470
1471 spin_lock_irq(&card->lock);
1472
1473 list_move_tail(&client->phy_receiver_link, &card->phy_receiver_list);
1474 client->phy_receiver_closure = a->closure;
1475
1476 spin_unlock_irq(&card->lock);
1477
1478 return 0;
1479}
1480
1481void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p)
1482{
1483 struct client *client;
1484 struct inbound_phy_packet_event *e;
1485 unsigned long flags;
1486
1487 spin_lock_irqsave(&card->lock, flags);
1488
1489 list_for_each_entry(client, &card->phy_receiver_list, phy_receiver_link) {
1490 e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC);
1491 if (e == NULL) {
1492 fw_notify("Out of memory when allocating event\n");
1493 break;
1494 }
1495 e->phy_packet.closure = client->phy_receiver_closure;
1496 e->phy_packet.type = FW_CDEV_EVENT_PHY_PACKET_RECEIVED;
1497 e->phy_packet.rcode = RCODE_COMPLETE;
1498 e->phy_packet.length = 8;
1499 e->phy_packet.data[0] = p->header[1];
1500 e->phy_packet.data[1] = p->header[2];
1501 queue_event(client, &e->event,
1502 &e->phy_packet, sizeof(e->phy_packet) + 8, NULL, 0);
1503 }
1504
1505 spin_unlock_irqrestore(&card->lock, flags);
1506}
1507
1450static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = { 1508static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
1451 [0x00] = ioctl_get_info, 1509 [0x00] = ioctl_get_info,
1452 [0x01] = ioctl_send_request, 1510 [0x01] = ioctl_send_request,
@@ -1470,6 +1528,7 @@ static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
1470 [0x13] = ioctl_send_stream_packet, 1528 [0x13] = ioctl_send_stream_packet,
1471 [0x14] = ioctl_get_cycle_timer2, 1529 [0x14] = ioctl_get_cycle_timer2,
1472 [0x15] = ioctl_send_phy_packet, 1530 [0x15] = ioctl_send_phy_packet,
1531 [0x16] = ioctl_receive_phy_packets,
1473}; 1532};
1474 1533
1475static int dispatch_ioctl(struct client *client, 1534static int dispatch_ioctl(struct client *client,
@@ -1577,6 +1636,10 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
1577 struct client *client = file->private_data; 1636 struct client *client = file->private_data;
1578 struct event *event, *next_event; 1637 struct event *event, *next_event;
1579 1638
1639 spin_lock_irq(&client->device->card->lock);
1640 list_del(&client->phy_receiver_link);
1641 spin_unlock_irq(&client->device->card->lock);
1642
1580 mutex_lock(&client->device->client_list_mutex); 1643 mutex_lock(&client->device->client_list_mutex);
1581 list_del(&client->link); 1644 list_del(&client->link);
1582 mutex_unlock(&client->device->client_list_mutex); 1645 mutex_unlock(&client->device->client_list_mutex);
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index e2e4dc624fb..6f225cacbc3 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -883,6 +883,11 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
883 if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) 883 if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)
884 return; 884 return;
885 885
886 if (TCODE_IS_LINK_INTERNAL(HEADER_GET_TCODE(p->header[0]))) {
887 fw_cdev_handle_phy_packet(card, p);
888 return;
889 }
890
886 request = allocate_request(card, p); 891 request = allocate_request(card, p);
887 if (request == NULL) { 892 if (request == NULL) {
888 /* FIXME: send statically allocated busy packet. */ 893 /* FIXME: send statically allocated busy packet. */
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index ff6c9092200..3102b6b6343 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -128,6 +128,7 @@ extern const struct file_operations fw_device_ops;
128 128
129void fw_device_cdev_update(struct fw_device *device); 129void fw_device_cdev_update(struct fw_device *device);
130void fw_device_cdev_remove(struct fw_device *device); 130void fw_device_cdev_remove(struct fw_device *device);
131void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p);
131 132
132 133
133/* -device */ 134/* -device */
@@ -214,6 +215,7 @@ static inline bool is_next_generation(int new_generation, int old_generation)
214 215
215#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) 216#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)
216#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) 217#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)
218#define TCODE_IS_LINK_INTERNAL(tcode) ((tcode) == 0xe)
217#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0) 219#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)
218#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0) 220#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)
219#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4) 221#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index bb6a92bc9e6..08afccc6633 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1759,10 +1759,9 @@ static int ohci_enable(struct fw_card *card,
1759 OHCI1394_HCControl_noByteSwapData); 1759 OHCI1394_HCControl_noByteSwapData);
1760 1760
1761 reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); 1761 reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
1762 reg_write(ohci, OHCI1394_LinkControlClear,
1763 OHCI1394_LinkControl_rcvPhyPkt);
1764 reg_write(ohci, OHCI1394_LinkControlSet, 1762 reg_write(ohci, OHCI1394_LinkControlSet,
1765 OHCI1394_LinkControl_rcvSelfID | 1763 OHCI1394_LinkControl_rcvSelfID |
1764 OHCI1394_LinkControl_rcvPhyPkt |
1766 OHCI1394_LinkControl_cycleTimerEnable | 1765 OHCI1394_LinkControl_cycleTimerEnable |
1767 OHCI1394_LinkControl_cycleMaster); 1766 OHCI1394_LinkControl_cycleMaster);
1768 1767
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 5bc051b9a01..b8740916079 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -35,6 +35,7 @@
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#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07
38#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x08
38 39
39/** 40/**
40 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types 41 * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
@@ -285,16 +286,24 @@ struct fw_cdev_event_iso_resource {
285}; 286};
286 287
287/** 288/**
288 * struct fw_cdev_event_phy_packet - A PHY packet was transmitted 289 * struct fw_cdev_event_phy_packet - A PHY packet was transmitted or received
289 * @closure: See &fw_cdev_event_common; 290 * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_SEND_PHY_PACKET
290 * set by %FW_CDEV_IOC_SEND_PHY_PACKET ioctl 291 * or %FW_CDEV_IOC_RECEIVE_PHY_PACKETS ioctl
291 * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT 292 * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT or %..._RECEIVED
292 * @rcode: %RCODE_..., indicates success or failure of transmission 293 * @rcode: %RCODE_..., indicates success or failure of transmission
294 * @length: Data length in bytes
295 * @data: Incoming data
296 *
297 * If @type is %FW_CDEV_EVENT_PHY_PACKET_SENT, @length is 0 and @data empty.
298 * If @type is %FW_CDEV_EVENT_PHY_PACKET_RECEIVED, @length is 8 and @data
299 * consists of the two PHY packet quadlets, in host byte order.
293 */ 300 */
294struct fw_cdev_event_phy_packet { 301struct fw_cdev_event_phy_packet {
295 __u64 closure; 302 __u64 closure;
296 __u32 type; 303 __u32 type;
297 __u32 rcode; 304 __u32 rcode;
305 __u32 length;
306 __u32 data[0];
298}; 307};
299 308
300/** 309/**
@@ -308,7 +317,9 @@ struct fw_cdev_event_phy_packet {
308 * @iso_resource: Valid if @common.type == 317 * @iso_resource: Valid if @common.type ==
309 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or 318 * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or
310 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 319 * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED
311 * @phy_packet: Valid if @common.type == %FW_CDEV_EVENT_PHY_PACKET_SENT 320 * @phy_packet: Valid if @common.type ==
321 * %FW_CDEV_EVENT_PHY_PACKET_SENT or
322 * %FW_CDEV_EVENT_PHY_PACKET_RECEIVED
312 * 323 *
313 * Convenience union for userspace use. Events could be read(2) into an 324 * Convenience union for userspace use. Events could be read(2) into an
314 * appropriately aligned char buffer and then cast to this union for further 325 * appropriately aligned char buffer and then cast to this union for further
@@ -360,6 +371,7 @@ union fw_cdev_event {
360 371
361/* available since kernel version 2.6.36 */ 372/* available since kernel version 2.6.36 */
362#define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet) 373#define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet)
374#define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets)
363 375
364/* 376/*
365 * ABI version history 377 * ABI version history
@@ -376,9 +388,9 @@ union fw_cdev_event {
376 * - shared use and auto-response for FCP registers 388 * - shared use and auto-response for FCP registers
377 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable 389 * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable
378 * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 390 * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2
379 * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_SENT 391 * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_*
380 * - implemented &fw_cdev_event_bus_reset.bm_node_id 392 * - implemented &fw_cdev_event_bus_reset.bm_node_id
381 * - added %FW_CDEV_IOC_SEND_PHY_PACKET 393 * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS
382 */ 394 */
383#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ 395#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */
384 396
@@ -850,4 +862,17 @@ struct fw_cdev_send_phy_packet {
850 __u32 generation; 862 __u32 generation;
851}; 863};
852 864
865/**
866 * struct fw_cdev_receive_phy_packets - start reception of PHY packets
867 * @closure: Passed back to userspace in phy packet events
868 *
869 * This ioctl activates issuing of %FW_CDEV_EVENT_PHY_PACKET_RECEIVED due to
870 * incoming PHY packets from any node on the same bus as the device.
871 *
872 * The ioctl is only permitted on device files which represent a local node.
873 */
874struct fw_cdev_receive_phy_packets {
875 __u64 closure;
876};
877
853#endif /* _LINUX_FIREWIRE_CDEV_H */ 878#endif /* _LINUX_FIREWIRE_CDEV_H */
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index 0c38b8e9772..d974aa4a24c 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -111,9 +111,10 @@ struct fw_card {
111 bool beta_repeaters_present; 111 bool beta_repeaters_present;
112 112
113 int index; 113 int index;
114
115 struct list_head link; 114 struct list_head link;
116 115
116 struct list_head phy_receiver_list;
117
117 struct delayed_work br_work; /* bus reset job */ 118 struct delayed_work br_work; /* bus reset job */
118 bool br_short; 119 bool br_short;
119 120