diff options
author | Mark Salyzyn <mark_salyzyn@xyratex.com> | 2012-01-17 09:18:57 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 09:08:51 -0500 |
commit | d95d00016f8f51dc502cadb263d861bd8c0212bb (patch) | |
tree | aa60333c6d9aa97f3dc1f32f0fce3f3f08baa939 /drivers/scsi/pm8001/pm8001_sas.c | |
parent | 5c4fb76af31e9dabcd132a0e69ed3799df1304c3 (diff) |
[SCSI] pm8001: Add FUNC_GET_EVENTS
Jack noticed I dropped a patch fragment associated with a flags automatic
variable in mpi_set_phys_g3_with_ssc (ooops) and that the pre-emptive locking
that piggy-backed this patch was not in-fact necessary because of underlying
atomic accesses to the hardware. Here is the updated patch fixing these two
issues.
The pm8001 driver is missing the FUNC_GET_EVENTS handler in the phy control
function. Since the pm8001_bar4_shift function was not designed to be called
at runtime, added locking surrounding the adjustment for all accesses.
Signed-off-by: Mark Salyzyn <mark_salyzyn@xyratex.com>
Acked-by: Jack Wang <jack_wang@usish.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_sas.c')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 7ae22a67bd31..ab0704e39040 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
@@ -166,6 +166,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | |||
166 | struct pm8001_hba_info *pm8001_ha = NULL; | 166 | struct pm8001_hba_info *pm8001_ha = NULL; |
167 | struct sas_phy_linkrates *rates; | 167 | struct sas_phy_linkrates *rates; |
168 | DECLARE_COMPLETION_ONSTACK(completion); | 168 | DECLARE_COMPLETION_ONSTACK(completion); |
169 | unsigned long flags; | ||
169 | pm8001_ha = sas_phy->ha->lldd_ha; | 170 | pm8001_ha = sas_phy->ha->lldd_ha; |
170 | pm8001_ha->phy[phy_id].enable_completion = &completion; | 171 | pm8001_ha->phy[phy_id].enable_completion = &completion; |
171 | switch (func) { | 172 | switch (func) { |
@@ -209,8 +210,29 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | |||
209 | case PHY_FUNC_DISABLE: | 210 | case PHY_FUNC_DISABLE: |
210 | PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id); | 211 | PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id); |
211 | break; | 212 | break; |
213 | case PHY_FUNC_GET_EVENTS: | ||
214 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
215 | if (-1 == pm8001_bar4_shift(pm8001_ha, | ||
216 | (phy_id < 4) ? 0x30000 : 0x40000)) { | ||
217 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | { | ||
221 | struct sas_phy *phy = sas_phy->phy; | ||
222 | uint32_t *qp = (uint32_t *)(((char *) | ||
223 | pm8001_ha->io_mem[2].memvirtaddr) | ||
224 | + 0x1034 + (0x4000 * (phy_id & 3))); | ||
225 | |||
226 | phy->invalid_dword_count = qp[0]; | ||
227 | phy->running_disparity_error_count = qp[1]; | ||
228 | phy->loss_of_dword_sync_count = qp[3]; | ||
229 | phy->phy_reset_problem_count = qp[4]; | ||
230 | } | ||
231 | pm8001_bar4_shift(pm8001_ha, 0); | ||
232 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
233 | return 0; | ||
212 | default: | 234 | default: |
213 | rc = -ENOSYS; | 235 | rc = -EOPNOTSUPP; |
214 | } | 236 | } |
215 | msleep(300); | 237 | msleep(300); |
216 | return rc; | 238 | return rc; |