aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-05-14 14:44:18 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:51 -0400
commit98441973105b80e133fcaa47ebf17be1e024ea30 (patch)
tree87a083ad72dff9b398c9276f5eabf51b6fe17612 /drivers/usb
parent6071d8363b7b284038069f1795a98372fbc1a48e (diff)
USB: xhci: Remove packed attribute from structures.
The packed attribute allows gcc to muck with the alignment of data structures, which may lead to byte-wise writes that break atomicity of writes. Packed should only be used when the compile may add undesired padding to the structure. Each element of the structure will be aligned by C based on its size and the size of the elements around it. E.g. a u64 would be aligned on an 8 byte boundary, the next u32 would be aligned on a four byte boundary, etc. Since most of the xHCI structures contain only u32 bit values, removing the packed attribute for them should be harmless. (A future patch will change some of the twin 32-bit address fields to one 64-bit field, but all those places have an even number of 32-bit fields before them, so the alignment should be correct.) Add BUILD_BUG_ON statements to check that the compiler doesn't add padding to the data structures that have a hardware-defined layout. While we're modifying the registers, change the name of intr_reg to xhci_intr_reg to avoid global conflicts. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-dbg.c2
-rw-r--r--drivers/usb/host/xhci-hcd.c19
-rw-r--r--drivers/usb/host/xhci.h46
3 files changed, 43 insertions, 24 deletions
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 6473cbf329f9..2501c571f855 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -169,7 +169,7 @@ static void xhci_print_ports(struct xhci_hcd *xhci)
169 } 169 }
170} 170}
171 171
172void xhci_print_ir_set(struct xhci_hcd *xhci, struct intr_reg *ir_set, int set_num) 172void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num)
173{ 173{
174 void *addr; 174 void *addr;
175 u32 temp; 175 u32 temp;
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c
index c6b921994b28..59ee61d2a198 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -1243,6 +1243,25 @@ static int __init xhci_hcd_init(void)
1243 return retval; 1243 return retval;
1244 } 1244 }
1245#endif 1245#endif
1246 /*
1247 * Check the compiler generated sizes of structures that must be laid
1248 * out in specific ways for hardware access.
1249 */
1250 BUILD_BUG_ON(sizeof(struct xhci_doorbell_array) != 256*32/8);
1251 BUILD_BUG_ON(sizeof(struct xhci_slot_ctx) != 8*32/8);
1252 BUILD_BUG_ON(sizeof(struct xhci_ep_ctx) != 8*32/8);
1253 /* xhci_device_control has eight fields, and also
1254 * embeds one xhci_slot_ctx and 31 xhci_ep_ctx
1255 */
1256 BUILD_BUG_ON(sizeof(struct xhci_device_control) != (8+8+8*31)*32/8);
1257 BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
1258 BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
1259 BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
1260 BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 7*32/8);
1261 BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
1262 /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
1263 BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
1264 BUILD_BUG_ON(sizeof(struct xhci_doorbell_array) != 256*32/8);
1246 return 0; 1265 return 0;
1247} 1266}
1248module_init(xhci_hcd_init); 1267module_init(xhci_hcd_init);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index df8778e1cfc6..3e8e09c4c2bf 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -71,7 +71,7 @@ struct xhci_cap_regs {
71 u32 db_off; 71 u32 db_off;
72 u32 run_regs_off; 72 u32 run_regs_off;
73 /* Reserved up to (CAPLENGTH - 0x1C) */ 73 /* Reserved up to (CAPLENGTH - 0x1C) */
74} __attribute__ ((packed)); 74};
75 75
76/* hc_capbase bitmasks */ 76/* hc_capbase bitmasks */
77/* bits 7:0 - how long is the Capabilities register */ 77/* bits 7:0 - how long is the Capabilities register */
@@ -180,7 +180,7 @@ struct xhci_op_regs {
180 u32 reserved5; 180 u32 reserved5;
181 /* registers for ports 2-255 */ 181 /* registers for ports 2-255 */
182 u32 reserved6[NUM_PORT_REGS*254]; 182 u32 reserved6[NUM_PORT_REGS*254];
183} __attribute__ ((packed)); 183};
184 184
185/* USBCMD - USB command - command bitmasks */ 185/* USBCMD - USB command - command bitmasks */
186/* start/stop HC execution - do not write unless HC is halted*/ 186/* start/stop HC execution - do not write unless HC is halted*/
@@ -361,7 +361,7 @@ struct xhci_op_regs {
361 361
362 362
363/** 363/**
364 * struct intr_reg - Interrupt Register Set 364 * struct xhci_intr_reg - Interrupt Register Set
365 * @irq_pending: IMAN - Interrupt Management Register. Used to enable 365 * @irq_pending: IMAN - Interrupt Management Register. Used to enable
366 * interrupts and check for pending interrupts. 366 * interrupts and check for pending interrupts.
367 * @irq_control: IMOD - Interrupt Moderation Register. 367 * @irq_control: IMOD - Interrupt Moderation Register.
@@ -377,14 +377,14 @@ struct xhci_op_regs {
377 * position of the Enqueue Pointer." The HCD (Linux) processes those events and 377 * position of the Enqueue Pointer." The HCD (Linux) processes those events and
378 * updates the dequeue pointer. 378 * updates the dequeue pointer.
379 */ 379 */
380struct intr_reg { 380struct xhci_intr_reg {
381 u32 irq_pending; 381 u32 irq_pending;
382 u32 irq_control; 382 u32 irq_control;
383 u32 erst_size; 383 u32 erst_size;
384 u32 rsvd; 384 u32 rsvd;
385 u32 erst_base[2]; 385 u32 erst_base[2];
386 u32 erst_dequeue[2]; 386 u32 erst_dequeue[2];
387} __attribute__ ((packed)); 387};
388 388
389/* irq_pending bitmasks */ 389/* irq_pending bitmasks */
390#define ER_IRQ_PENDING(p) ((p) & 0x1) 390#define ER_IRQ_PENDING(p) ((p) & 0x1)
@@ -428,10 +428,10 @@ struct intr_reg {
428 * or larger accesses" 428 * or larger accesses"
429 */ 429 */
430struct xhci_run_regs { 430struct xhci_run_regs {
431 u32 microframe_index; 431 u32 microframe_index;
432 u32 rsvd[7]; 432 u32 rsvd[7];
433 struct intr_reg ir_set[128]; 433 struct xhci_intr_reg ir_set[128];
434} __attribute__ ((packed)); 434};
435 435
436/** 436/**
437 * struct doorbell_array 437 * struct doorbell_array
@@ -440,7 +440,7 @@ struct xhci_run_regs {
440 */ 440 */
441struct xhci_doorbell_array { 441struct xhci_doorbell_array {
442 u32 doorbell[256]; 442 u32 doorbell[256];
443} __attribute__ ((packed)); 443};
444 444
445#define DB_TARGET_MASK 0xFFFFFF00 445#define DB_TARGET_MASK 0xFFFFFF00
446#define DB_STREAM_ID_MASK 0x0000FFFF 446#define DB_STREAM_ID_MASK 0x0000FFFF
@@ -470,7 +470,7 @@ struct xhci_slot_ctx {
470 u32 dev_state; 470 u32 dev_state;
471 /* offset 0x10 to 0x1f reserved for HC internal use */ 471 /* offset 0x10 to 0x1f reserved for HC internal use */
472 u32 reserved[4]; 472 u32 reserved[4];
473} __attribute__ ((packed)); 473};
474 474
475/* dev_info bitmasks */ 475/* dev_info bitmasks */
476/* Route String - 0:19 */ 476/* Route String - 0:19 */
@@ -542,7 +542,7 @@ struct xhci_ep_ctx {
542 u32 tx_info; 542 u32 tx_info;
543 /* offset 0x14 - 0x1f reserved for HC internal use */ 543 /* offset 0x14 - 0x1f reserved for HC internal use */
544 u32 reserved[3]; 544 u32 reserved[3];
545} __attribute__ ((packed)); 545};
546 546
547/* ep_info bitmasks */ 547/* ep_info bitmasks */
548/* 548/*
@@ -601,7 +601,7 @@ struct xhci_device_control {
601 u32 rsvd[6]; 601 u32 rsvd[6];
602 struct xhci_slot_ctx slot; 602 struct xhci_slot_ctx slot;
603 struct xhci_ep_ctx ep[31]; 603 struct xhci_ep_ctx ep[31];
604} __attribute__ ((packed)); 604};
605 605
606/* drop context bitmasks */ 606/* drop context bitmasks */
607#define DROP_EP(x) (0x1 << x) 607#define DROP_EP(x) (0x1 << x)
@@ -644,7 +644,7 @@ struct xhci_device_context_array {
644 u32 dev_context_ptrs[2*MAX_HC_SLOTS]; 644 u32 dev_context_ptrs[2*MAX_HC_SLOTS];
645 /* private xHCD pointers */ 645 /* private xHCD pointers */
646 dma_addr_t dma; 646 dma_addr_t dma;
647} __attribute__ ((packed)); 647};
648/* TODO: write function to set the 64-bit device DMA address */ 648/* TODO: write function to set the 64-bit device DMA address */
649/* 649/*
650 * TODO: change this to be dynamically sized at HC mem init time since the HC 650 * TODO: change this to be dynamically sized at HC mem init time since the HC
@@ -657,7 +657,7 @@ struct xhci_stream_ctx {
657 u32 stream_ring[2]; 657 u32 stream_ring[2];
658 /* offset 0x14 - 0x1f reserved for HC internal use */ 658 /* offset 0x14 - 0x1f reserved for HC internal use */
659 u32 reserved[2]; 659 u32 reserved[2];
660} __attribute__ ((packed)); 660};
661 661
662 662
663struct xhci_transfer_event { 663struct xhci_transfer_event {
@@ -666,7 +666,7 @@ struct xhci_transfer_event {
666 u32 transfer_len; 666 u32 transfer_len;
667 /* This field is interpreted differently based on the type of TRB */ 667 /* This field is interpreted differently based on the type of TRB */
668 u32 flags; 668 u32 flags;
669} __attribute__ ((packed)); 669};
670 670
671/** Transfer Event bit fields **/ 671/** Transfer Event bit fields **/
672#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) 672#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f)
@@ -747,7 +747,7 @@ struct xhci_link_trb {
747 u32 segment_ptr[2]; 747 u32 segment_ptr[2];
748 u32 intr_target; 748 u32 intr_target;
749 u32 control; 749 u32 control;
750} __attribute__ ((packed)); 750};
751 751
752/* control bitfields */ 752/* control bitfields */
753#define LINK_TOGGLE (0x1<<1) 753#define LINK_TOGGLE (0x1<<1)
@@ -758,7 +758,7 @@ struct xhci_event_cmd {
758 u32 cmd_trb[2]; 758 u32 cmd_trb[2];
759 u32 status; 759 u32 status;
760 u32 flags; 760 u32 flags;
761} __attribute__ ((packed)); 761};
762 762
763/* flags bitmasks */ 763/* flags bitmasks */
764/* bits 16:23 are the virtual function ID */ 764/* bits 16:23 are the virtual function ID */
@@ -809,7 +809,7 @@ struct xhci_event_cmd {
809 809
810struct xhci_generic_trb { 810struct xhci_generic_trb {
811 u32 field[4]; 811 u32 field[4];
812} __attribute__ ((packed)); 812};
813 813
814union xhci_trb { 814union xhci_trb {
815 struct xhci_link_trb link; 815 struct xhci_link_trb link;
@@ -904,7 +904,7 @@ struct xhci_segment {
904 /* private to HCD */ 904 /* private to HCD */
905 struct xhci_segment *next; 905 struct xhci_segment *next;
906 dma_addr_t dma; 906 dma_addr_t dma;
907} __attribute__ ((packed)); 907};
908 908
909struct xhci_td { 909struct xhci_td {
910 struct list_head td_list; 910 struct list_head td_list;
@@ -946,7 +946,7 @@ struct xhci_erst_entry {
946 u32 seg_size; 946 u32 seg_size;
947 /* Set to zero */ 947 /* Set to zero */
948 u32 rsvd; 948 u32 rsvd;
949} __attribute__ ((packed)); 949};
950 950
951struct xhci_erst { 951struct xhci_erst {
952 struct xhci_erst_entry *entries; 952 struct xhci_erst_entry *entries;
@@ -980,7 +980,7 @@ struct xhci_hcd {
980 struct xhci_run_regs __iomem *run_regs; 980 struct xhci_run_regs __iomem *run_regs;
981 struct xhci_doorbell_array __iomem *dba; 981 struct xhci_doorbell_array __iomem *dba;
982 /* Our HCD's current interrupter register set */ 982 /* Our HCD's current interrupter register set */
983 struct intr_reg __iomem *ir_set; 983 struct xhci_intr_reg __iomem *ir_set;
984 984
985 /* Cached register copies of read-only HC data */ 985 /* Cached register copies of read-only HC data */
986 __u32 hcs_params1; 986 __u32 hcs_params1;
@@ -1079,7 +1079,7 @@ static inline void xhci_writel(struct xhci_hcd *xhci,
1079} 1079}
1080 1080
1081/* xHCI debugging */ 1081/* xHCI debugging */
1082void xhci_print_ir_set(struct xhci_hcd *xhci, struct intr_reg *ir_set, int set_num); 1082void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
1083void xhci_print_registers(struct xhci_hcd *xhci); 1083void xhci_print_registers(struct xhci_hcd *xhci);
1084void xhci_dbg_regs(struct xhci_hcd *xhci); 1084void xhci_dbg_regs(struct xhci_hcd *xhci);
1085void xhci_print_run_regs(struct xhci_hcd *xhci); 1085void xhci_print_run_regs(struct xhci_hcd *xhci);