aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/htirq.c72
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
32void 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
42void 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
52u32 read_ht_irq_low(unsigned int irq) 34void 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
64u32 read_ht_irq_high(unsigned int irq) 51void 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
76void mask_ht_irq(unsigned int irq) 57void 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
92void unmask_ht_irq(unsigned int irq) 69void 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) {