diff options
author | Xiangliang Yu <yuxiangl@marvell.com> | 2011-05-24 10:26:50 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-26 02:25:02 -0400 |
commit | 534ff10104427ccad071ef87ae7017d47d08e50b (patch) | |
tree | 3e0e7a74ef1c109a7a343817295ed6e925fd22c7 /drivers/scsi/mvsas | |
parent | 45b583b10a8b438b970e95a7d1d4db22c9e35004 (diff) |
[SCSI] mvsas: Add support for Non specific NCQ error interrupt
Signed-off-by: Xiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/mvsas')
-rw-r--r-- | drivers/scsi/mvsas/mv_64xx.c | 1 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_94xx.c | 32 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_chips.h | 3 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_defs.h | 1 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.c | 14 | ||||
-rw-r--r-- | drivers/scsi/mvsas/mv_sas.h | 2 |
6 files changed, 52 insertions, 1 deletions
diff --git a/drivers/scsi/mvsas/mv_64xx.c b/drivers/scsi/mvsas/mv_64xx.c index 13c960481391..0e13e6441da7 100644 --- a/drivers/scsi/mvsas/mv_64xx.c +++ b/drivers/scsi/mvsas/mv_64xx.c | |||
@@ -811,5 +811,6 @@ const struct mvs_dispatch mvs_64xx_dispatch = { | |||
811 | #ifndef DISABLE_HOTPLUG_DMA_FIX | 811 | #ifndef DISABLE_HOTPLUG_DMA_FIX |
812 | mvs_64xx_fix_dma, | 812 | mvs_64xx_fix_dma, |
813 | #endif | 813 | #endif |
814 | NULL, | ||
814 | }; | 815 | }; |
815 | 816 | ||
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c index 78162c3c36e6..9d60c7c19b32 100644 --- a/drivers/scsi/mvsas/mv_94xx.c +++ b/drivers/scsi/mvsas/mv_94xx.c | |||
@@ -249,7 +249,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi) | |||
249 | 249 | ||
250 | /* enable completion queue interrupt */ | 250 | /* enable completion queue interrupt */ |
251 | tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP | | 251 | tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP | |
252 | CINT_DMA_PCIE); | 252 | CINT_DMA_PCIE | CINT_NON_SPEC_NCQ_ERROR); |
253 | tmp |= CINT_PHY_MASK; | 253 | tmp |= CINT_PHY_MASK; |
254 | mw32(MVS_INT_MASK, tmp); | 254 | mw32(MVS_INT_MASK, tmp); |
255 | 255 | ||
@@ -367,6 +367,35 @@ static void mvs_94xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type, | |||
367 | mw32(MVS_PCS, tmp); | 367 | mw32(MVS_PCS, tmp); |
368 | } | 368 | } |
369 | 369 | ||
370 | static void mvs_94xx_non_spec_ncq_error(struct mvs_info *mvi) | ||
371 | { | ||
372 | void __iomem *regs = mvi->regs; | ||
373 | u32 err_0, err_1; | ||
374 | u8 i; | ||
375 | struct mvs_device *device; | ||
376 | |||
377 | err_0 = mr32(MVS_NON_NCQ_ERR_0); | ||
378 | err_1 = mr32(MVS_NON_NCQ_ERR_1); | ||
379 | |||
380 | mv_dprintk("non specific ncq error err_0:%x,err_1:%x.\n", | ||
381 | err_0, err_1); | ||
382 | for (i = 0; i < 32; i++) { | ||
383 | if (err_0 & bit(i)) { | ||
384 | device = mvs_find_dev_by_reg_set(mvi, i); | ||
385 | if (device) | ||
386 | mvs_release_task(mvi, device->sas_device); | ||
387 | } | ||
388 | if (err_1 & bit(i)) { | ||
389 | device = mvs_find_dev_by_reg_set(mvi, i+32); | ||
390 | if (device) | ||
391 | mvs_release_task(mvi, device->sas_device); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | mw32(MVS_NON_NCQ_ERR_0, err_0); | ||
396 | mw32(MVS_NON_NCQ_ERR_1, err_1); | ||
397 | } | ||
398 | |||
370 | static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs) | 399 | static void mvs_94xx_free_reg_set(struct mvs_info *mvi, u8 *tfs) |
371 | { | 400 | { |
372 | void __iomem *regs = mvi->regs; | 401 | void __iomem *regs = mvi->regs; |
@@ -679,5 +708,6 @@ const struct mvs_dispatch mvs_94xx_dispatch = { | |||
679 | #ifndef DISABLE_HOTPLUG_DMA_FIX | 708 | #ifndef DISABLE_HOTPLUG_DMA_FIX |
680 | mvs_94xx_fix_dma, | 709 | mvs_94xx_fix_dma, |
681 | #endif | 710 | #endif |
711 | mvs_94xx_non_spec_ncq_error, | ||
682 | }; | 712 | }; |
683 | 713 | ||
diff --git a/drivers/scsi/mvsas/mv_chips.h b/drivers/scsi/mvsas/mv_chips.h index 1753a6fc42d0..4519f809a8df 100644 --- a/drivers/scsi/mvsas/mv_chips.h +++ b/drivers/scsi/mvsas/mv_chips.h | |||
@@ -223,6 +223,9 @@ static inline void mvs_int_full(struct mvs_info *mvi) | |||
223 | mvs_int_port(mvi, i, tmp); | 223 | mvs_int_port(mvi, i, tmp); |
224 | } | 224 | } |
225 | 225 | ||
226 | if (stat & CINT_NON_SPEC_NCQ_ERROR) | ||
227 | MVS_CHIP_DISP->non_spec_ncq_error(mvi); | ||
228 | |||
226 | if (stat & CINT_SRS) | 229 | if (stat & CINT_SRS) |
227 | mvs_int_sata(mvi); | 230 | mvs_int_sata(mvi); |
228 | 231 | ||
diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h index bc00c940743c..9202bc68801d 100644 --- a/drivers/scsi/mvsas/mv_defs.h +++ b/drivers/scsi/mvsas/mv_defs.h | |||
@@ -144,6 +144,7 @@ enum hw_register_bits { | |||
144 | CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */ | 144 | CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */ |
145 | CINT_MEM = (1U << 26), /* int mem parity err */ | 145 | CINT_MEM = (1U << 26), /* int mem parity err */ |
146 | CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */ | 146 | CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */ |
147 | CINT_NON_SPEC_NCQ_ERROR = (1U << 25), /* Non specific NCQ error */ | ||
147 | CINT_SRS = (1U << 3), /* SRS event */ | 148 | CINT_SRS = (1U << 3), /* SRS event */ |
148 | CINT_CI_STOP = (1U << 1), /* cmd issue stopped */ | 149 | CINT_CI_STOP = (1U << 1), /* cmd issue stopped */ |
149 | CINT_DONE = (1U << 0), /* cmd completion */ | 150 | CINT_DONE = (1U << 0), /* cmd completion */ |
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 0ef27425c447..aaa475a3eda6 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c | |||
@@ -253,6 +253,20 @@ int mvs_find_dev_phyno(struct domain_device *dev, int *phyno) | |||
253 | return num; | 253 | return num; |
254 | } | 254 | } |
255 | 255 | ||
256 | struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, | ||
257 | u8 reg_set) | ||
258 | { | ||
259 | u32 dev_no; | ||
260 | for (dev_no = 0; dev_no < MVS_MAX_DEVICES; dev_no++) { | ||
261 | if (mvi->devices[dev_no].taskfileset == MVS_ID_NOT_MAPPED) | ||
262 | continue; | ||
263 | |||
264 | if (mvi->devices[dev_no].taskfileset == reg_set) | ||
265 | return &mvi->devices[dev_no]; | ||
266 | } | ||
267 | return NULL; | ||
268 | } | ||
269 | |||
256 | static inline void mvs_free_reg_set(struct mvs_info *mvi, | 270 | static inline void mvs_free_reg_set(struct mvs_info *mvi, |
257 | struct mvs_device *dev) | 271 | struct mvs_device *dev) |
258 | { | 272 | { |
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 1367d8b9350d..f96100d7aee1 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h | |||
@@ -170,6 +170,7 @@ struct mvs_dispatch { | |||
170 | #ifndef DISABLE_HOTPLUG_DMA_FIX | 170 | #ifndef DISABLE_HOTPLUG_DMA_FIX |
171 | void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd); | 171 | void (*dma_fix)(dma_addr_t buf_dma, int buf_len, int from, void *prd); |
172 | #endif | 172 | #endif |
173 | void (*non_spec_ncq_error)(struct mvs_info *mvi); | ||
173 | 174 | ||
174 | }; | 175 | }; |
175 | 176 | ||
@@ -416,5 +417,6 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events); | |||
416 | void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); | 417 | void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); |
417 | int mvs_int_rx(struct mvs_info *mvi, bool self_clear); | 418 | int mvs_int_rx(struct mvs_info *mvi, bool self_clear); |
418 | void mvs_hexdump(u32 size, u8 *data, u32 baseaddr); | 419 | void mvs_hexdump(u32 size, u8 *data, u32 baseaddr); |
420 | struct mvs_device *mvs_find_dev_by_reg_set(struct mvs_info *mvi, u8 reg_set); | ||
419 | #endif | 421 | #endif |
420 | 422 | ||