diff options
Diffstat (limited to 'drivers/pci/htirq.c')
-rw-r--r-- | drivers/pci/htirq.c | 72 |
1 files changed, 24 insertions, 48 deletions
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 0e27f2404a83..e346fe31f97a 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c | |||
@@ -27,82 +27,55 @@ struct ht_irq_cfg { | |||
27 | struct pci_dev *dev; | 27 | struct pci_dev *dev; |
28 | unsigned pos; | 28 | unsigned pos; |
29 | unsigned idx; | 29 | unsigned idx; |
30 | struct ht_irq_msg msg; | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | void write_ht_irq_low(unsigned int irq, u32 data) | ||
33 | { | ||
34 | struct ht_irq_cfg *cfg = get_irq_data(irq); | ||
35 | unsigned long flags; | ||
36 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
37 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | ||
38 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
39 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
40 | } | ||
41 | |||
42 | void write_ht_irq_high(unsigned int irq, u32 data) | ||
43 | { | ||
44 | struct ht_irq_cfg *cfg = get_irq_data(irq); | ||
45 | unsigned long flags; | ||
46 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
47 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
48 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
49 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
50 | } | ||
51 | 33 | ||
52 | u32 read_ht_irq_low(unsigned int irq) | 34 | void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) |
53 | { | 35 | { |
54 | struct ht_irq_cfg *cfg = get_irq_data(irq); | 36 | struct ht_irq_cfg *cfg = get_irq_data(irq); |
55 | unsigned long flags; | 37 | unsigned long flags; |
56 | u32 data; | ||
57 | spin_lock_irqsave(&ht_irq_lock, flags); | 38 | spin_lock_irqsave(&ht_irq_lock, flags); |
58 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | 39 | if (cfg->msg.address_lo != msg->address_lo) { |
59 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | 40 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); |
41 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo); | ||
42 | } | ||
43 | if (cfg->msg.address_hi != msg->address_hi) { | ||
44 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
45 | pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); | ||
46 | } | ||
60 | spin_unlock_irqrestore(&ht_irq_lock, flags); | 47 | spin_unlock_irqrestore(&ht_irq_lock, flags); |
61 | return data; | 48 | cfg->msg = *msg; |
62 | } | 49 | } |
63 | 50 | ||
64 | u32 read_ht_irq_high(unsigned int irq) | 51 | void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) |
65 | { | 52 | { |
66 | struct ht_irq_cfg *cfg = get_irq_data(irq); | 53 | struct ht_irq_cfg *cfg = get_irq_data(irq); |
67 | unsigned long flags; | 54 | *msg = cfg->msg; |
68 | u32 data; | ||
69 | spin_lock_irqsave(&ht_irq_lock, flags); | ||
70 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); | ||
71 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | ||
72 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
73 | return data; | ||
74 | } | 55 | } |
75 | 56 | ||
76 | void mask_ht_irq(unsigned int irq) | 57 | void mask_ht_irq(unsigned int irq) |
77 | { | 58 | { |
78 | struct ht_irq_cfg *cfg; | 59 | struct ht_irq_cfg *cfg; |
79 | unsigned long flags; | 60 | struct ht_irq_msg msg; |
80 | u32 data; | ||
81 | 61 | ||
82 | cfg = get_irq_data(irq); | 62 | cfg = get_irq_data(irq); |
83 | 63 | ||
84 | spin_lock_irqsave(&ht_irq_lock, flags); | 64 | msg = cfg->msg; |
85 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | 65 | msg.address_lo |= 1; |
86 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | 66 | write_ht_irq_msg(irq, &msg); |
87 | data |= 1; | ||
88 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
89 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
90 | } | 67 | } |
91 | 68 | ||
92 | void unmask_ht_irq(unsigned int irq) | 69 | void unmask_ht_irq(unsigned int irq) |
93 | { | 70 | { |
94 | struct ht_irq_cfg *cfg; | 71 | struct ht_irq_cfg *cfg; |
95 | unsigned long flags; | 72 | struct ht_irq_msg msg; |
96 | u32 data; | ||
97 | 73 | ||
98 | cfg = get_irq_data(irq); | 74 | cfg = get_irq_data(irq); |
99 | 75 | ||
100 | spin_lock_irqsave(&ht_irq_lock, flags); | 76 | msg = cfg->msg; |
101 | pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); | 77 | msg.address_lo &= ~1; |
102 | pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); | 78 | write_ht_irq_msg(irq, &msg); |
103 | data &= ~1; | ||
104 | pci_write_config_dword(cfg->dev, cfg->pos + 4, data); | ||
105 | spin_unlock_irqrestore(&ht_irq_lock, flags); | ||
106 | } | 79 | } |
107 | 80 | ||
108 | /** | 81 | /** |
@@ -152,6 +125,9 @@ int ht_create_irq(struct pci_dev *dev, int idx) | |||
152 | cfg->dev = dev; | 125 | cfg->dev = dev; |
153 | cfg->pos = pos; | 126 | cfg->pos = pos; |
154 | cfg->idx = 0x10 + (idx * 2); | 127 | cfg->idx = 0x10 + (idx * 2); |
128 | /* Initialize msg to a value that will never match the first write. */ | ||
129 | cfg->msg.address_lo = 0xffffffff; | ||
130 | cfg->msg.address_hi = 0xffffffff; | ||
155 | 131 | ||
156 | irq = create_irq(); | 132 | irq = create_irq(); |
157 | if (irq < 0) { | 133 | if (irq < 0) { |