Skip to content

Commit fd8c8d4

Browse files
author
Stefan Richter
committed
firewire: nosy: endianess fixes and annotations
1.) The DMA programs (struct pcl) are PCI-endian = little endian data (except for the 3rd quadlet in a PCL which the controller does not touch). Annotate them as such. Fix all accesses of the PCL to work with big endian CPUs also. Not actually tested, I only have a little endian PC to test with. This includes replacement of a bitfield struct pcl_status by open-coded shift and mask operations. 2.) The two __attribute__ ((packed)) at struct pcl are not really required since it consists of u32/__le32 only, i.e. there will be no padding with or without the attribute. 3.) The received IEEE 1394 data are byteswapped by the controller from IEEE 1394 endian = big endian to PCI endian = little endian because the PCL_BIGENDIAN control bit is set. Therefore annotate the DMA buffer as a __le32 array. Fix the one access of the DMA buffer (the check of the transaction code of link packets) to work with big endian CPUs. Also fix the two accesses of the client bounce buffer (the reading of packet length). 4.) Add a comment to the userspace ABI header that all of the data gets out as little endian data, except for the timestamp which is CPU endian. (We could make it little endian too, but why? Vice versa, an ioctl could be added to dump packet data in big endian byte order...) Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
1 parent c89db7b commit fd8c8d4

2 files changed

Lines changed: 29 additions & 51 deletions

File tree

drivers/firewire/nosy-user.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ struct nosy_stats {
1717
/*
1818
* Format of packets returned from the kernel driver:
1919
*
20-
* quadlet with timestamp (microseconds)
21-
* quadlet padded packet data...
22-
* quadlet with ack
20+
* quadlet with timestamp (microseconds, CPU endian)
21+
* quadlet-padded packet data... (little endian)
22+
* quadlet with ack (little endian)
2323
*/
2424

2525
#endif /* __nosy_user_h */

drivers/firewire/nosy.c

Lines changed: 26 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -51,33 +51,19 @@
5151

5252
static char driver_name[] = KBUILD_MODNAME;
5353

54-
struct pcl_status {
55-
unsigned int transfer_count : 13;
56-
unsigned int reserved0 : 1;
57-
unsigned int ack_type : 1;
58-
unsigned int ack : 4;
59-
unsigned int rcv_speed : 2;
60-
unsigned int rcv_dma_channel : 6;
61-
unsigned int packet_complete : 1;
62-
unsigned int packet_error : 1;
63-
unsigned int master_error : 1;
64-
unsigned int iso_mode : 1;
65-
unsigned int self_id : 1;
66-
};
67-
6854
/* this is the physical layout of a PCL, its size is 128 bytes */
6955
struct pcl {
70-
u32 next;
71-
u32 async_error_next;
72-
u32 user_data;
73-
struct pcl_status pcl_status;
74-
u32 remaining_transfer_count;
75-
u32 next_data_buffer;
76-
struct {
77-
u32 control;
78-
u32 pointer;
79-
} buffer[13] __attribute__ ((packed));
80-
} __attribute__ ((packed));
56+
__le32 next;
57+
__le32 async_error_next;
58+
u32 user_data;
59+
__le32 pcl_status;
60+
__le32 remaining_transfer_count;
61+
__le32 next_data_buffer;
62+
struct {
63+
__le32 control;
64+
__le32 pointer;
65+
} buffer[13];
66+
};
8167

8268
struct packet {
8369
unsigned int length;
@@ -98,7 +84,7 @@ struct pcilynx {
9884
__iomem char *registers;
9985

10086
struct pcl *rcv_start_pcl, *rcv_pcl;
101-
u32 *rcv_buffer;
87+
__le32 *rcv_buffer;
10288

10389
dma_addr_t rcv_start_pcl_bus, rcv_pcl_bus, rcv_buffer_bus;
10490

@@ -426,35 +412,26 @@ static const struct file_operations nosy_ops = {
426412

427413
#define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
428414

429-
struct link_packet {
430-
unsigned int priority : 4;
431-
unsigned int tcode : 4;
432-
unsigned int rt : 2;
433-
unsigned int tlabel : 6;
434-
unsigned int destination : 16;
435-
};
436-
437415
static void
438416
packet_irq_handler(struct pcilynx *lynx)
439417
{
440418
struct client *client;
441-
u32 tcode_mask;
419+
u32 tcode_mask, tcode;
442420
size_t length;
443-
struct link_packet *packet;
444421
struct timeval tv;
445422

446423
/* FIXME: Also report rcv_speed. */
447424

448-
length = lynx->rcv_pcl->pcl_status.transfer_count;
449-
packet = (struct link_packet *) &lynx->rcv_buffer[1];
425+
length = __le32_to_cpu(lynx->rcv_pcl->pcl_status) & 0x00001fff;
426+
tcode = __le32_to_cpu(lynx->rcv_buffer[1]) >> 4 & 0xf;
450427

451428
do_gettimeofday(&tv);
452-
lynx->rcv_buffer[0] = tv.tv_usec;
429+
lynx->rcv_buffer[0] = (__force __le32)tv.tv_usec;
453430

454431
if (length == PHY_PACKET_SIZE)
455432
tcode_mask = 1 << TCODE_PHY_PACKET;
456433
else
457-
tcode_mask = 1 << packet->tcode;
434+
tcode_mask = 1 << tcode;
458435

459436
spin_lock(&lynx->client_list_lock);
460437

@@ -602,21 +579,22 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
602579
ret = -ENOMEM;
603580
goto fail_deallocate;
604581
}
605-
lynx->rcv_start_pcl->next = lynx->rcv_pcl_bus;
606-
lynx->rcv_pcl->next = PCL_NEXT_INVALID;
607-
lynx->rcv_pcl->async_error_next = PCL_NEXT_INVALID;
582+
lynx->rcv_start_pcl->next = cpu_to_le32(lynx->rcv_pcl_bus);
583+
lynx->rcv_pcl->next = cpu_to_le32(PCL_NEXT_INVALID);
584+
lynx->rcv_pcl->async_error_next = cpu_to_le32(PCL_NEXT_INVALID);
608585

609586
lynx->rcv_pcl->buffer[0].control =
610-
PCL_CMD_RCV | PCL_BIGENDIAN | 2044;
611-
lynx->rcv_pcl->buffer[0].pointer = lynx->rcv_buffer_bus + 4;
587+
cpu_to_le32(PCL_CMD_RCV | PCL_BIGENDIAN | 2044);
588+
lynx->rcv_pcl->buffer[0].pointer =
589+
cpu_to_le32(lynx->rcv_buffer_bus + 4);
612590
p = lynx->rcv_buffer_bus + 2048;
613591
end = lynx->rcv_buffer_bus + RCV_BUFFER_SIZE;
614592
for (i = 1; p < end; i++, p += 2048) {
615593
lynx->rcv_pcl->buffer[i].control =
616-
PCL_CMD_RCV | PCL_BIGENDIAN | 2048;
617-
lynx->rcv_pcl->buffer[i].pointer = p;
594+
cpu_to_le32(PCL_CMD_RCV | PCL_BIGENDIAN | 2048);
595+
lynx->rcv_pcl->buffer[i].pointer = cpu_to_le32(p);
618596
}
619-
lynx->rcv_pcl->buffer[i - 1].control |= PCL_LAST_BUFF;
597+
lynx->rcv_pcl->buffer[i - 1].control |= cpu_to_le32(PCL_LAST_BUFF);
620598

621599
reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
622600
/* Fix buggy cards with autoboot pin not tied low: */

0 commit comments

Comments
 (0)