aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mic/host
diff options
context:
space:
mode:
authorDasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>2013-12-10 12:51:12 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-12-11 02:05:52 -0500
commitdf5e4e8b576108f88f79e5b4c984d51d460d2360 (patch)
tree47f1d8e49f3e62e887b73d806beec6e4127974c9 /drivers/misc/mic/host
parentd6a484520c5572a4170fa915109ccfc0c38f5008 (diff)
misc: mic: bug fix for interrupt acknowledgement in MSI/INTx case.
The interrupt handler (mic_interrupt), called in the MSI/INTx mode, writes to the interrupt sources register to acknowledge the interrupt and then calls the corresponding callback handlers to handle the same. These callback handlers acknowledge the interrupts again leading to missed interrupts. This patch fixes the issue by removing the interrupt acknowlegment code from the callback handlers. Reviewed-by: Sudeep Dutt <sudeep.dutt@intel.com> Reviewed-by: Nikhil Rao <nikhil.rao@intel.com> Reviewed-by: Siva Krishna Kumar Reddy Yerramreddy <siva.krishna.kumar.reddy.yerramreddy@intel.com> Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Cc: stable <stable@vger.kernel.org> # 3.13 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mic/host')
-rw-r--r--drivers/misc/mic/host/mic_device.h3
-rw-r--r--drivers/misc/mic/host/mic_main.c2
-rw-r--r--drivers/misc/mic/host/mic_virtio.c2
-rw-r--r--drivers/misc/mic/host/mic_x100.c36
4 files changed, 25 insertions, 18 deletions
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
index 3574cc375bb9..b2da289320c9 100644
--- a/drivers/misc/mic/host/mic_device.h
+++ b/drivers/misc/mic/host/mic_device.h
@@ -134,6 +134,8 @@ struct mic_device {
134 * @send_intr: Send an interrupt for a particular doorbell on the card. 134 * @send_intr: Send an interrupt for a particular doorbell on the card.
135 * @ack_interrupt: Hardware specific operations to ack the h/w on 135 * @ack_interrupt: Hardware specific operations to ack the h/w on
136 * receipt of an interrupt. 136 * receipt of an interrupt.
137 * @intr_workarounds: Hardware specific workarounds needed after
138 * handling an interrupt.
137 * @reset: Reset the remote processor. 139 * @reset: Reset the remote processor.
138 * @reset_fw_ready: Reset firmware ready field. 140 * @reset_fw_ready: Reset firmware ready field.
139 * @is_fw_ready: Check if firmware is ready for OS download. 141 * @is_fw_ready: Check if firmware is ready for OS download.
@@ -149,6 +151,7 @@ struct mic_hw_ops {
149 void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val); 151 void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val);
150 void (*send_intr)(struct mic_device *mdev, int doorbell); 152 void (*send_intr)(struct mic_device *mdev, int doorbell);
151 u32 (*ack_interrupt)(struct mic_device *mdev); 153 u32 (*ack_interrupt)(struct mic_device *mdev);
154 void (*intr_workarounds)(struct mic_device *mdev);
152 void (*reset)(struct mic_device *mdev); 155 void (*reset)(struct mic_device *mdev);
153 void (*reset_fw_ready)(struct mic_device *mdev); 156 void (*reset_fw_ready)(struct mic_device *mdev);
154 bool (*is_fw_ready)(struct mic_device *mdev); 157 bool (*is_fw_ready)(struct mic_device *mdev);
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
index ad838c7651c4..c04a021e20c7 100644
--- a/drivers/misc/mic/host/mic_main.c
+++ b/drivers/misc/mic/host/mic_main.c
@@ -115,7 +115,7 @@ static irqreturn_t mic_shutdown_db(int irq, void *data)
115 struct mic_device *mdev = data; 115 struct mic_device *mdev = data;
116 struct mic_bootparam *bootparam = mdev->dp; 116 struct mic_bootparam *bootparam = mdev->dp;
117 117
118 mdev->ops->ack_interrupt(mdev); 118 mdev->ops->intr_workarounds(mdev);
119 119
120 switch (bootparam->shutdown_status) { 120 switch (bootparam->shutdown_status) {
121 case MIC_HALTED: 121 case MIC_HALTED:
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
index 5b8494bd1e00..8d3c21cd1d9c 100644
--- a/drivers/misc/mic/host/mic_virtio.c
+++ b/drivers/misc/mic/host/mic_virtio.c
@@ -369,7 +369,7 @@ static irqreturn_t mic_virtio_intr_handler(int irq, void *data)
369 struct mic_vdev *mvdev = data; 369 struct mic_vdev *mvdev = data;
370 struct mic_device *mdev = mvdev->mdev; 370 struct mic_device *mdev = mvdev->mdev;
371 371
372 mdev->ops->ack_interrupt(mdev); 372 mdev->ops->intr_workarounds(mdev);
373 schedule_work(&mvdev->virtio_bh_work); 373 schedule_work(&mvdev->virtio_bh_work);
374 return IRQ_HANDLED; 374 return IRQ_HANDLED;
375} 375}
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
index 81e9541b784c..6fccb13493a5 100644
--- a/drivers/misc/mic/host/mic_x100.c
+++ b/drivers/misc/mic/host/mic_x100.c
@@ -174,35 +174,38 @@ static void mic_x100_send_intr(struct mic_device *mdev, int doorbell)
174} 174}
175 175
176/** 176/**
177 * mic_ack_interrupt - Device specific interrupt handling. 177 * mic_x100_ack_interrupt - Read the interrupt sources register and
178 * @mdev: pointer to mic_device instance 178 * clear it. This function will be called in the MSI/INTx case.
179 * @mdev: Pointer to mic_device instance.
179 * 180 *
180 * Returns: bitmask of doorbell events triggered. 181 * Returns: bitmask of interrupt sources triggered.
181 */ 182 */
182static u32 mic_x100_ack_interrupt(struct mic_device *mdev) 183static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
183{ 184{
184 u32 reg = 0;
185 struct mic_mw *mw = &mdev->mmio;
186 u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0; 185 u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
186 u32 reg = mic_mmio_read(&mdev->mmio, sicr0);
187 mic_mmio_write(&mdev->mmio, reg, sicr0);
188 return reg;
189}
190
191/**
192 * mic_x100_intr_workarounds - These hardware specific workarounds are
193 * to be invoked everytime an interrupt is handled.
194 * @mdev: Pointer to mic_device instance.
195 *
196 * Returns: none
197 */
198static void mic_x100_intr_workarounds(struct mic_device *mdev)
199{
200 struct mic_mw *mw = &mdev->mmio;
187 201
188 /* Clear pending bit array. */ 202 /* Clear pending bit array. */
189 if (MIC_A0_STEP == mdev->stepping) 203 if (MIC_A0_STEP == mdev->stepping)
190 mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS + 204 mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
191 MIC_X100_SBOX_MSIXPBACR); 205 MIC_X100_SBOX_MSIXPBACR);
192 206
193 if (mdev->irq_info.num_vectors <= 1) {
194 reg = mic_mmio_read(mw, sicr0);
195
196 if (unlikely(!reg))
197 goto done;
198
199 mic_mmio_write(mw, reg, sicr0);
200 }
201
202 if (mdev->stepping >= MIC_B0_STEP) 207 if (mdev->stepping >= MIC_B0_STEP)
203 mdev->intr_ops->enable_interrupts(mdev); 208 mdev->intr_ops->enable_interrupts(mdev);
204done:
205 return reg;
206} 209}
207 210
208/** 211/**
@@ -553,6 +556,7 @@ struct mic_hw_ops mic_x100_ops = {
553 .write_spad = mic_x100_write_spad, 556 .write_spad = mic_x100_write_spad,
554 .send_intr = mic_x100_send_intr, 557 .send_intr = mic_x100_send_intr,
555 .ack_interrupt = mic_x100_ack_interrupt, 558 .ack_interrupt = mic_x100_ack_interrupt,
559 .intr_workarounds = mic_x100_intr_workarounds,
556 .reset = mic_x100_hw_reset, 560 .reset = mic_x100_hw_reset,
557 .reset_fw_ready = mic_x100_reset_fw_ready, 561 .reset_fw_ready = mic_x100_reset_fw_ready,
558 .is_fw_ready = mic_x100_is_fw_ready, 562 .is_fw_ready = mic_x100_is_fw_ready,