diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/core-card.c | 1 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 73 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 5 | ||||
-rw-r--r-- | drivers/firewire/core.h | 2 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 3 |
5 files changed, 77 insertions, 7 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 0c312c4bb4bd..6d1cfae6aad4 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 f95719926487..0425dd5dfcd3 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 | ||
207 | struct inbound_phy_packet_event { | ||
208 | struct event event; | ||
209 | struct fw_cdev_event_phy_packet phy_packet; | ||
210 | }; | ||
211 | |||
204 | static inline void __user *u64_to_uptr(__u64 value) | 212 | static 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 | ||
409 | static int ioctl_get_info(struct client *client, union ioctl_arg *arg) | 419 | static 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 | ||
1462 | static 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 | |||
1481 | void 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 | |||
1450 | static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = { | 1508 | static 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 | ||
1475 | static int dispatch_ioctl(struct client *client, | 1534 | static 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 e2e4dc624fb6..6f225cacbc3d 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 ff6c90922001..3102b6b63438 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 | ||
129 | void fw_device_cdev_update(struct fw_device *device); | 129 | void fw_device_cdev_update(struct fw_device *device); |
130 | void fw_device_cdev_remove(struct fw_device *device); | 130 | void fw_device_cdev_remove(struct fw_device *device); |
131 | void 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 bb6a92bc9e6a..08afccc66333 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 | ||