summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2015-08-02 15:20:52 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-08-03 20:33:54 -0400
commit1fa55b4e0e161b3d16b52f5bab1b39b39607bc27 (patch)
treebe74705f98e7de456914050cbe13ac11cd4af7d3
parentbb9f4d26dda7d2a875cadc0f7eedee3d65d3d1f5 (diff)
mei: me: d0i3: enable d0i3 interrupts
D0i3 adds additional interrupt reason bit, therefore we add a variable intr_source to save the interrupt causes for further dispatching. The interrupt cause is saved in the irq quick handler to achieve unified behavior for both MSI enabled and shared interrupt platforms. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/mei/hw-me-regs.h4
-rw-r--r--drivers/misc/mei/hw-me.c35
-rw-r--r--drivers/misc/mei/hw-me.h2
-rw-r--r--drivers/misc/mei/pci-me.c27
4 files changed, 33 insertions, 35 deletions
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 4c8f05ea3651..8793ccca12ad 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -166,6 +166,10 @@
166/* Host D0I3 Interrupt Status */ 166/* Host D0I3 Interrupt Status */
167#define H_D0I3C_IS 0x00000040 167#define H_D0I3C_IS 0x00000040
168 168
169/* H_CSR masks */
170#define H_CSR_IE_MASK (H_IE | H_D0I3C_IE)
171#define H_CSR_IS_MASK (H_IS | H_D0I3C_IS)
172
169/* register bits of ME_CSR_HA (ME Control Status Host Access register) */ 173/* register bits of ME_CSR_HA (ME Control Status Host Access register) */
170/* ME CB (Circular Buffer) Depth HRA (Host Read Access) - host read only 174/* ME CB (Circular Buffer) Depth HRA (Host Read Access) - host read only
171access to ME_CBD */ 175access to ME_CBD */
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 17d6894b0fd2..910af88b3214 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -134,7 +134,7 @@ static inline void mei_hcsr_write(struct mei_device *dev, u32 reg)
134 */ 134 */
135static inline void mei_hcsr_set(struct mei_device *dev, u32 reg) 135static inline void mei_hcsr_set(struct mei_device *dev, u32 reg)
136{ 136{
137 reg &= ~H_IS; 137 reg &= ~H_CSR_IS_MASK;
138 mei_hcsr_write(dev, reg); 138 mei_hcsr_write(dev, reg);
139} 139}
140 140
@@ -216,7 +216,7 @@ static void mei_me_intr_clear(struct mei_device *dev)
216{ 216{
217 u32 hcsr = mei_hcsr_read(dev); 217 u32 hcsr = mei_hcsr_read(dev);
218 218
219 if ((hcsr & H_IS) == H_IS) 219 if (hcsr & H_CSR_IS_MASK)
220 mei_hcsr_write(dev, hcsr); 220 mei_hcsr_write(dev, hcsr);
221} 221}
222/** 222/**
@@ -228,7 +228,7 @@ static void mei_me_intr_enable(struct mei_device *dev)
228{ 228{
229 u32 hcsr = mei_hcsr_read(dev); 229 u32 hcsr = mei_hcsr_read(dev);
230 230
231 hcsr |= H_IE; 231 hcsr |= H_CSR_IE_MASK;
232 mei_hcsr_set(dev, hcsr); 232 mei_hcsr_set(dev, hcsr);
233} 233}
234 234
@@ -241,7 +241,7 @@ static void mei_me_intr_disable(struct mei_device *dev)
241{ 241{
242 u32 hcsr = mei_hcsr_read(dev); 242 u32 hcsr = mei_hcsr_read(dev);
243 243
244 hcsr &= ~H_IE; 244 hcsr &= ~H_CSR_IE_MASK;
245 mei_hcsr_set(dev, hcsr); 245 mei_hcsr_set(dev, hcsr);
246} 246}
247 247
@@ -285,12 +285,12 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
285 hcsr = mei_hcsr_read(dev); 285 hcsr = mei_hcsr_read(dev);
286 } 286 }
287 287
288 hcsr |= H_RST | H_IG | H_IS; 288 hcsr |= H_RST | H_IG | H_CSR_IS_MASK;
289 289
290 if (intr_enable) 290 if (intr_enable)
291 hcsr |= H_IE; 291 hcsr |= H_CSR_IE_MASK;
292 else 292 else
293 hcsr &= ~H_IE; 293 hcsr &= ~H_CSR_IE_MASK;
294 294
295 dev->recvd_hw_ready = false; 295 dev->recvd_hw_ready = false;
296 mei_hcsr_write(dev, hcsr); 296 mei_hcsr_write(dev, hcsr);
@@ -322,7 +322,7 @@ static void mei_me_host_set_ready(struct mei_device *dev)
322{ 322{
323 u32 hcsr = mei_hcsr_read(dev); 323 u32 hcsr = mei_hcsr_read(dev);
324 324
325 hcsr |= H_IE | H_IG | H_RDY; 325 hcsr |= H_CSR_IE_MASK | H_IG | H_RDY;
326 mei_hcsr_set(dev, hcsr); 326 mei_hcsr_set(dev, hcsr);
327} 327}
328 328
@@ -767,16 +767,20 @@ static void mei_me_pg_intr(struct mei_device *dev)
767 * 767 *
768 * Return: irqreturn_t 768 * Return: irqreturn_t
769 */ 769 */
770
771irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id) 770irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
772{ 771{
773 struct mei_device *dev = (struct mei_device *) dev_id; 772 struct mei_device *dev = (struct mei_device *)dev_id;
774 u32 hcsr = mei_hcsr_read(dev); 773 struct mei_me_hw *hw = to_me_hw(dev);
774 u32 hcsr;
775 775
776 if ((hcsr & H_IS) != H_IS) 776 hcsr = mei_hcsr_read(dev);
777 if (!(hcsr & H_CSR_IS_MASK))
777 return IRQ_NONE; 778 return IRQ_NONE;
778 779
779 /* clear H_IS bit in H_CSR */ 780 hw->intr_source = hcsr & H_CSR_IS_MASK;
781 dev_dbg(dev->dev, "interrupt source 0x%08X.\n", hw->intr_source);
782
783 /* clear H_IS and H_D0I3C_IS bits in H_CSR to clear the interrupts */
780 mei_hcsr_write(dev, hcsr); 784 mei_hcsr_write(dev, hcsr);
781 785
782 return IRQ_WAKE_THREAD; 786 return IRQ_WAKE_THREAD;
@@ -804,11 +808,6 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
804 mutex_lock(&dev->device_lock); 808 mutex_lock(&dev->device_lock);
805 mei_io_list_init(&complete_list); 809 mei_io_list_init(&complete_list);
806 810
807 /* Ack the interrupt here
808 * In case of MSI we don't go through the quick handler */
809 if (pci_dev_msi_enabled(to_pci_dev(dev->dev)))
810 mei_clear_interrupts(dev);
811
812 /* check if ME wants a reset */ 811 /* check if ME wants a reset */
813 if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) { 812 if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
814 dev_warn(dev->dev, "FW not ready: resetting.\n"); 813 dev_warn(dev->dev, "FW not ready: resetting.\n");
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index cf64847a35b9..2ee14dc1b2ea 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -51,12 +51,14 @@ struct mei_cfg {
51 * 51 *
52 * @cfg: per device generation config and ops 52 * @cfg: per device generation config and ops
53 * @mem_addr: io memory address 53 * @mem_addr: io memory address
54 * @intr_source: interrupt source
54 * @pg_state: power gating state 55 * @pg_state: power gating state
55 * @d0i3_supported: di03 support 56 * @d0i3_supported: di03 support
56 */ 57 */
57struct mei_me_hw { 58struct mei_me_hw {
58 const struct mei_cfg *cfg; 59 const struct mei_cfg *cfg;
59 void __iomem *mem_addr; 60 void __iomem *mem_addr;
61 u32 intr_source;
60 enum mei_pg_state pg_state; 62 enum mei_pg_state pg_state;
61 bool d0i3_supported; 63 bool d0i3_supported;
62}; 64};
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 23f71f5ce4fb..7fee74abbc21 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -128,6 +128,7 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
128 const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data); 128 const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data);
129 struct mei_device *dev; 129 struct mei_device *dev;
130 struct mei_me_hw *hw; 130 struct mei_me_hw *hw;
131 unsigned int irqflags;
131 int err; 132 int err;
132 133
133 134
@@ -180,17 +181,12 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
180 pci_enable_msi(pdev); 181 pci_enable_msi(pdev);
181 182
182 /* request and enable interrupt */ 183 /* request and enable interrupt */
183 if (pci_dev_msi_enabled(pdev)) 184 irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
184 err = request_threaded_irq(pdev->irq, 185
185 NULL, 186 err = request_threaded_irq(pdev->irq,
186 mei_me_irq_thread_handler,
187 IRQF_ONESHOT, KBUILD_MODNAME, dev);
188 else
189 err = request_threaded_irq(pdev->irq,
190 mei_me_irq_quick_handler, 187 mei_me_irq_quick_handler,
191 mei_me_irq_thread_handler, 188 mei_me_irq_thread_handler,
192 IRQF_SHARED, KBUILD_MODNAME, dev); 189 irqflags, KBUILD_MODNAME, dev);
193
194 if (err) { 190 if (err) {
195 dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n", 191 dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
196 pdev->irq); 192 pdev->irq);
@@ -319,6 +315,7 @@ static int mei_me_pci_resume(struct device *device)
319{ 315{
320 struct pci_dev *pdev = to_pci_dev(device); 316 struct pci_dev *pdev = to_pci_dev(device);
321 struct mei_device *dev; 317 struct mei_device *dev;
318 unsigned int irqflags;
322 int err; 319 int err;
323 320
324 dev = pci_get_drvdata(pdev); 321 dev = pci_get_drvdata(pdev);
@@ -327,17 +324,13 @@ static int mei_me_pci_resume(struct device *device)
327 324
328 pci_enable_msi(pdev); 325 pci_enable_msi(pdev);
329 326
327 irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
328
330 /* request and enable interrupt */ 329 /* request and enable interrupt */
331 if (pci_dev_msi_enabled(pdev)) 330 err = request_threaded_irq(pdev->irq,
332 err = request_threaded_irq(pdev->irq,
333 NULL,
334 mei_me_irq_thread_handler,
335 IRQF_ONESHOT, KBUILD_MODNAME, dev);
336 else
337 err = request_threaded_irq(pdev->irq,
338 mei_me_irq_quick_handler, 331 mei_me_irq_quick_handler,
339 mei_me_irq_thread_handler, 332 mei_me_irq_thread_handler,
340 IRQF_SHARED, KBUILD_MODNAME, dev); 333 irqflags, KBUILD_MODNAME, dev);
341 334
342 if (err) { 335 if (err) {
343 dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", 336 dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",