diff options
author | Lilach Edelstein <lilach.edelstein@intel.com> | 2013-01-16 04:34:49 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-02-01 05:27:22 -0500 |
commit | e56b04efc1f795da42cf1d9651b52a4a5bebd730 (patch) | |
tree | a9740ffd4d47ffb7b90507691a0a066c20f42a2d /drivers/net/wireless | |
parent | e139dc4aebf52a9c88552963b9794fd1dff036f1 (diff) |
iwlwifi: move register access lock into transport
Move the reg_lock that protects HW register access
into the transport implementation. Locking is no
longer exposed, but handled internally in grab and
release NIC access. This simplifies the users.
Signed-off-by: Lilach Edelstein <lilach.edelstein@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/main.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/tt.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.c | 43 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-test.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/internal.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 47 |
8 files changed, 75 insertions, 88 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index b55181275fd0..c2f03ecd4bf8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -459,14 +459,12 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
459 | 459 | ||
460 | base = priv->device_pointers.error_event_table; | 460 | base = priv->device_pointers.error_event_table; |
461 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 461 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
462 | spin_lock_irqsave(&priv->trans->reg_lock, flags); | 462 | if (iwl_trans_grab_nic_access(priv->trans, true, &flags)) { |
463 | if (iwl_trans_grab_nic_access(priv->trans, true)) { | ||
464 | iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base); | 463 | iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base); |
465 | status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); | 464 | status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); |
466 | iwl_trans_release_nic_access(priv->trans); | 465 | iwl_trans_release_nic_access(priv->trans, &flags); |
467 | ret = 0; | 466 | ret = 0; |
468 | } | 467 | } |
469 | spin_unlock_irqrestore(&priv->trans->reg_lock, flags); | ||
470 | 468 | ||
471 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 469 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
472 | if (ret == 0) { | 470 | if (ret == 0) { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index f5f91644adaa..b9e3517652d6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -353,11 +353,8 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | |||
353 | ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); | 353 | ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); |
354 | 354 | ||
355 | /* Make sure device is powered up for SRAM reads */ | 355 | /* Make sure device is powered up for SRAM reads */ |
356 | spin_lock_irqsave(&priv->trans->reg_lock, reg_flags); | 356 | if (!iwl_trans_grab_nic_access(priv->trans, false, ®_flags)) |
357 | if (!iwl_trans_grab_nic_access(priv->trans, false)) { | ||
358 | spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags); | ||
359 | return; | 357 | return; |
360 | } | ||
361 | 358 | ||
362 | /* Set starting address; reads will auto-increment */ | 359 | /* Set starting address; reads will auto-increment */ |
363 | iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr); | 360 | iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr); |
@@ -388,8 +385,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | |||
388 | } | 385 | } |
389 | } | 386 | } |
390 | /* Allow device to power down */ | 387 | /* Allow device to power down */ |
391 | iwl_trans_release_nic_access(priv->trans); | 388 | iwl_trans_release_nic_access(priv->trans, ®_flags); |
392 | spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags); | ||
393 | } | 389 | } |
394 | 390 | ||
395 | static void iwl_continuous_event_trace(struct iwl_priv *priv) | 391 | static void iwl_continuous_event_trace(struct iwl_priv *priv) |
@@ -1717,9 +1713,8 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1717 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | 1713 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); |
1718 | 1714 | ||
1719 | /* Make sure device is powered up for SRAM reads */ | 1715 | /* Make sure device is powered up for SRAM reads */ |
1720 | spin_lock_irqsave(&trans->reg_lock, reg_flags); | 1716 | if (!iwl_trans_grab_nic_access(trans, false, ®_flags)) |
1721 | if (!iwl_trans_grab_nic_access(trans, false)) | 1717 | return pos; |
1722 | goto out_unlock; | ||
1723 | 1718 | ||
1724 | /* Set starting address; reads will auto-increment */ | 1719 | /* Set starting address; reads will auto-increment */ |
1725 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); | 1720 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); |
@@ -1757,9 +1752,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1757 | } | 1752 | } |
1758 | 1753 | ||
1759 | /* Allow device to power down */ | 1754 | /* Allow device to power down */ |
1760 | iwl_trans_release_nic_access(trans); | 1755 | iwl_trans_release_nic_access(trans, ®_flags); |
1761 | out_unlock: | ||
1762 | spin_unlock_irqrestore(&trans->reg_lock, reg_flags); | ||
1763 | return pos; | 1756 | return pos; |
1764 | } | 1757 | } |
1765 | 1758 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index 617fca3cffe0..67e2e1321b40 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
@@ -185,10 +185,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) | |||
185 | priv->thermal_throttle.ct_kill_toggle = true; | 185 | priv->thermal_throttle.ct_kill_toggle = true; |
186 | } | 186 | } |
187 | iwl_read32(priv->trans, CSR_UCODE_DRV_GP1); | 187 | iwl_read32(priv->trans, CSR_UCODE_DRV_GP1); |
188 | spin_lock_irqsave(&priv->trans->reg_lock, flags); | 188 | if (iwl_trans_grab_nic_access(priv->trans, false, &flags)) |
189 | if (iwl_trans_grab_nic_access(priv->trans, false)) | 189 | iwl_trans_release_nic_access(priv->trans, &flags); |
190 | iwl_trans_release_nic_access(priv->trans); | ||
191 | spin_unlock_irqrestore(&priv->trans->reg_lock, flags); | ||
192 | 190 | ||
193 | /* Reschedule the ct_kill timer to occur in | 191 | /* Reschedule the ct_kill timer to occur in |
194 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | 192 | * CT_KILL_EXIT_DURATION seconds to ensure we get a |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 7ef47389953e..276410d82de4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -55,13 +55,10 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) | |||
55 | { | 55 | { |
56 | u32 value = 0x5a5a5a5a; | 56 | u32 value = 0x5a5a5a5a; |
57 | unsigned long flags; | 57 | unsigned long flags; |
58 | 58 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { | |
59 | spin_lock_irqsave(&trans->reg_lock, flags); | ||
60 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
61 | value = iwl_read32(trans, reg); | 59 | value = iwl_read32(trans, reg); |
62 | iwl_trans_release_nic_access(trans); | 60 | iwl_trans_release_nic_access(trans, &flags); |
63 | } | 61 | } |
64 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
65 | 62 | ||
66 | return value; | 63 | return value; |
67 | } | 64 | } |
@@ -71,12 +68,10 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) | |||
71 | { | 68 | { |
72 | unsigned long flags; | 69 | unsigned long flags; |
73 | 70 | ||
74 | spin_lock_irqsave(&trans->reg_lock, flags); | 71 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
75 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
76 | iwl_write32(trans, reg, value); | 72 | iwl_write32(trans, reg, value); |
77 | iwl_trans_release_nic_access(trans); | 73 | iwl_trans_release_nic_access(trans, &flags); |
78 | } | 74 | } |
79 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
80 | } | 75 | } |
81 | EXPORT_SYMBOL_GPL(iwl_write_direct32); | 76 | EXPORT_SYMBOL_GPL(iwl_write_direct32); |
82 | 77 | ||
@@ -114,12 +109,10 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) | |||
114 | unsigned long flags; | 109 | unsigned long flags; |
115 | u32 val = 0x5a5a5a5a; | 110 | u32 val = 0x5a5a5a5a; |
116 | 111 | ||
117 | spin_lock_irqsave(&trans->reg_lock, flags); | 112 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
118 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
119 | val = __iwl_read_prph(trans, ofs); | 113 | val = __iwl_read_prph(trans, ofs); |
120 | iwl_trans_release_nic_access(trans); | 114 | iwl_trans_release_nic_access(trans, &flags); |
121 | } | 115 | } |
122 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
123 | return val; | 116 | return val; |
124 | } | 117 | } |
125 | EXPORT_SYMBOL_GPL(iwl_read_prph); | 118 | EXPORT_SYMBOL_GPL(iwl_read_prph); |
@@ -128,12 +121,10 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) | |||
128 | { | 121 | { |
129 | unsigned long flags; | 122 | unsigned long flags; |
130 | 123 | ||
131 | spin_lock_irqsave(&trans->reg_lock, flags); | 124 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
132 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
133 | __iwl_write_prph(trans, ofs, val); | 125 | __iwl_write_prph(trans, ofs, val); |
134 | iwl_trans_release_nic_access(trans); | 126 | iwl_trans_release_nic_access(trans, &flags); |
135 | } | 127 | } |
136 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
137 | } | 128 | } |
138 | EXPORT_SYMBOL_GPL(iwl_write_prph); | 129 | EXPORT_SYMBOL_GPL(iwl_write_prph); |
139 | 130 | ||
@@ -141,13 +132,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
141 | { | 132 | { |
142 | unsigned long flags; | 133 | unsigned long flags; |
143 | 134 | ||
144 | spin_lock_irqsave(&trans->reg_lock, flags); | 135 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
145 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
146 | __iwl_write_prph(trans, ofs, | 136 | __iwl_write_prph(trans, ofs, |
147 | __iwl_read_prph(trans, ofs) | mask); | 137 | __iwl_read_prph(trans, ofs) | mask); |
148 | iwl_trans_release_nic_access(trans); | 138 | iwl_trans_release_nic_access(trans, &flags); |
149 | } | 139 | } |
150 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
151 | } | 140 | } |
152 | EXPORT_SYMBOL_GPL(iwl_set_bits_prph); | 141 | EXPORT_SYMBOL_GPL(iwl_set_bits_prph); |
153 | 142 | ||
@@ -156,13 +145,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, | |||
156 | { | 145 | { |
157 | unsigned long flags; | 146 | unsigned long flags; |
158 | 147 | ||
159 | spin_lock_irqsave(&trans->reg_lock, flags); | 148 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
160 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
161 | __iwl_write_prph(trans, ofs, | 149 | __iwl_write_prph(trans, ofs, |
162 | (__iwl_read_prph(trans, ofs) & mask) | bits); | 150 | (__iwl_read_prph(trans, ofs) & mask) | bits); |
163 | iwl_trans_release_nic_access(trans); | 151 | iwl_trans_release_nic_access(trans, &flags); |
164 | } | 152 | } |
165 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
166 | } | 153 | } |
167 | EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph); | 154 | EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph); |
168 | 155 | ||
@@ -171,12 +158,10 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) | |||
171 | unsigned long flags; | 158 | unsigned long flags; |
172 | u32 val; | 159 | u32 val; |
173 | 160 | ||
174 | spin_lock_irqsave(&trans->reg_lock, flags); | 161 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
175 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
176 | val = __iwl_read_prph(trans, ofs); | 162 | val = __iwl_read_prph(trans, ofs); |
177 | __iwl_write_prph(trans, ofs, (val & ~mask)); | 163 | __iwl_write_prph(trans, ofs, (val & ~mask)); |
178 | iwl_trans_release_nic_access(trans); | 164 | iwl_trans_release_nic_access(trans, &flags); |
179 | } | 165 | } |
180 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
181 | } | 166 | } |
182 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); | 167 | EXPORT_SYMBOL_GPL(iwl_clear_bits_prph); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c index d06fc55067df..ce0c67b425ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-test.c +++ b/drivers/net/wireless/iwlwifi/iwl-test.c | |||
@@ -466,9 +466,7 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size) | |||
466 | /* Hard-coded periphery absolute address */ | 466 | /* Hard-coded periphery absolute address */ |
467 | if (IWL_ABS_PRPH_START <= addr && | 467 | if (IWL_ABS_PRPH_START <= addr && |
468 | addr < IWL_ABS_PRPH_START + PRPH_END) { | 468 | addr < IWL_ABS_PRPH_START + PRPH_END) { |
469 | spin_lock_irqsave(&trans->reg_lock, flags); | 469 | if (!iwl_trans_grab_nic_access(trans, false, &flags)) { |
470 | if (!iwl_trans_grab_nic_access(trans, false)) { | ||
471 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
472 | return -EIO; | 470 | return -EIO; |
473 | } | 471 | } |
474 | iwl_write32(trans, HBUS_TARG_PRPH_RADDR, | 472 | iwl_write32(trans, HBUS_TARG_PRPH_RADDR, |
@@ -476,8 +474,7 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size) | |||
476 | for (i = 0; i < size; i += 4) | 474 | for (i = 0; i < size; i += 4) |
477 | *(u32 *)(tst->mem.addr + i) = | 475 | *(u32 *)(tst->mem.addr + i) = |
478 | iwl_read32(trans, HBUS_TARG_PRPH_RDAT); | 476 | iwl_read32(trans, HBUS_TARG_PRPH_RDAT); |
479 | iwl_trans_release_nic_access(trans); | 477 | iwl_trans_release_nic_access(trans, &flags); |
480 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
481 | } else { /* target memory (SRAM) */ | 478 | } else { /* target memory (SRAM) */ |
482 | iwl_trans_read_mem(trans, addr, tst->mem.addr, | 479 | iwl_trans_read_mem(trans, addr, tst->mem.addr, |
483 | tst->mem.size / 4); | 480 | tst->mem.size / 4); |
@@ -506,19 +503,13 @@ static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr, | |||
506 | /* Periphery writes can be 1-3 bytes long, or DWORDs */ | 503 | /* Periphery writes can be 1-3 bytes long, or DWORDs */ |
507 | if (size < 4) { | 504 | if (size < 4) { |
508 | memcpy(&val, buf, size); | 505 | memcpy(&val, buf, size); |
509 | spin_lock_irqsave(&trans->reg_lock, flags); | 506 | if (!iwl_trans_grab_nic_access(trans, false, &flags)) |
510 | if (!iwl_trans_grab_nic_access(trans, false)) { | ||
511 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
512 | return -EIO; | 507 | return -EIO; |
513 | } | ||
514 | iwl_write32(trans, HBUS_TARG_PRPH_WADDR, | 508 | iwl_write32(trans, HBUS_TARG_PRPH_WADDR, |
515 | (addr & 0x0000FFFF) | | 509 | (addr & 0x0000FFFF) | |
516 | ((size - 1) << 24)); | 510 | ((size - 1) << 24)); |
517 | iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); | 511 | iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); |
518 | iwl_trans_release_nic_access(trans); | 512 | iwl_trans_release_nic_access(trans, &flags); |
519 | /* needed after consecutive writes w/o read */ | ||
520 | mmiowb(); | ||
521 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
522 | } else { | 513 | } else { |
523 | if (size % 4) | 514 | if (size % 4) |
524 | return -EINVAL; | 515 | return -EINVAL; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c2b7e856a726..0a3d4df5f434 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -416,8 +416,11 @@ struct iwl_trans; | |||
416 | * the op_mode. May be called several times before start_fw, can't be | 416 | * the op_mode. May be called several times before start_fw, can't be |
417 | * called after that. | 417 | * called after that. |
418 | * @set_pmi: set the power pmi state | 418 | * @set_pmi: set the power pmi state |
419 | * @grab_nic_access: wake the NIC to be able to access non-HBUS regs | 419 | * @grab_nic_access: wake the NIC to be able to access non-HBUS regs. |
420 | * @release_nic_access: let the NIC go to sleep | 420 | * Sleeping is not allowed between grab_nic_access and |
421 | * release_nic_access. | ||
422 | * @release_nic_access: let the NIC go to sleep. The "flags" parameter | ||
423 | * must be the same one that was sent before to the grab_nic_access. | ||
421 | * @set_bits_mask - set SRAM register according to value and mask. | 424 | * @set_bits_mask - set SRAM register according to value and mask. |
422 | */ | 425 | */ |
423 | struct iwl_trans_ops { | 426 | struct iwl_trans_ops { |
@@ -461,8 +464,10 @@ struct iwl_trans_ops { | |||
461 | void (*configure)(struct iwl_trans *trans, | 464 | void (*configure)(struct iwl_trans *trans, |
462 | const struct iwl_trans_config *trans_cfg); | 465 | const struct iwl_trans_config *trans_cfg); |
463 | void (*set_pmi)(struct iwl_trans *trans, bool state); | 466 | void (*set_pmi)(struct iwl_trans *trans, bool state); |
464 | bool (*grab_nic_access)(struct iwl_trans *trans, bool silent); | 467 | bool (*grab_nic_access)(struct iwl_trans *trans, bool silent, |
465 | void (*release_nic_access)(struct iwl_trans *trans); | 468 | unsigned long *flags); |
469 | void (*release_nic_access)(struct iwl_trans *trans, | ||
470 | unsigned long *flags); | ||
466 | void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask, | 471 | void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask, |
467 | u32 value); | 472 | u32 value); |
468 | }; | 473 | }; |
@@ -484,7 +489,6 @@ enum iwl_trans_state { | |||
484 | * @ops - pointer to iwl_trans_ops | 489 | * @ops - pointer to iwl_trans_ops |
485 | * @op_mode - pointer to the op_mode | 490 | * @op_mode - pointer to the op_mode |
486 | * @cfg - pointer to the configuration | 491 | * @cfg - pointer to the configuration |
487 | * @reg_lock - protect hw register access | ||
488 | * @dev - pointer to struct device * that represents the device | 492 | * @dev - pointer to struct device * that represents the device |
489 | * @hw_id: a u32 with the ID of the device / subdevice. | 493 | * @hw_id: a u32 with the ID of the device / subdevice. |
490 | * Set during transport allocation. | 494 | * Set during transport allocation. |
@@ -505,7 +509,6 @@ struct iwl_trans { | |||
505 | struct iwl_op_mode *op_mode; | 509 | struct iwl_op_mode *op_mode; |
506 | const struct iwl_cfg *cfg; | 510 | const struct iwl_cfg *cfg; |
507 | enum iwl_trans_state state; | 511 | enum iwl_trans_state state; |
508 | spinlock_t reg_lock; | ||
509 | 512 | ||
510 | struct device *dev; | 513 | struct device *dev; |
511 | u32 hw_rev; | 514 | u32 hw_rev; |
@@ -771,14 +774,14 @@ iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) | |||
771 | trans->ops->set_bits_mask(trans, reg, mask, value); | 774 | trans->ops->set_bits_mask(trans, reg, mask, value); |
772 | } | 775 | } |
773 | 776 | ||
774 | #define iwl_trans_grab_nic_access(trans, silent) \ | 777 | #define iwl_trans_grab_nic_access(trans, silent, flags) \ |
775 | __cond_lock(nic_access, \ | 778 | __cond_lock(nic_access, \ |
776 | likely((trans)->ops->grab_nic_access(trans, silent))) | 779 | likely((trans)->ops->grab_nic_access(trans, silent, flags))) |
777 | 780 | ||
778 | static inline void __releases(nic_access) | 781 | static inline void __releases(nic_access) |
779 | iwl_trans_release_nic_access(struct iwl_trans *trans) | 782 | iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags) |
780 | { | 783 | { |
781 | trans->ops->release_nic_access(trans); | 784 | trans->ops->release_nic_access(trans, flags); |
782 | __release(nic_access); | 785 | __release(nic_access); |
783 | } | 786 | } |
784 | 787 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 21395fae03c0..5f6bb4e09d42 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -235,6 +235,7 @@ struct iwl_txq { | |||
235 | * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes) | 235 | * @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes) |
236 | * @rx_page_order: page order for receive buffer size | 236 | * @rx_page_order: page order for receive buffer size |
237 | * @wd_timeout: queue watchdog timeout (jiffies) | 237 | * @wd_timeout: queue watchdog timeout (jiffies) |
238 | * @reg_lock: protect hw register access | ||
238 | */ | 239 | */ |
239 | struct iwl_trans_pcie { | 240 | struct iwl_trans_pcie { |
240 | struct iwl_rxq rxq; | 241 | struct iwl_rxq rxq; |
@@ -283,6 +284,9 @@ struct iwl_trans_pcie { | |||
283 | 284 | ||
284 | /* queue watchdog */ | 285 | /* queue watchdog */ |
285 | unsigned long wd_timeout; | 286 | unsigned long wd_timeout; |
287 | |||
288 | /*protect hw register */ | ||
289 | spinlock_t reg_lock; | ||
286 | }; | 290 | }; |
287 | 291 | ||
288 | /** | 292 | /** |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 8692494c1c48..56d4f72500bc 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -806,11 +806,12 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) | |||
806 | } | 806 | } |
807 | #endif /* CONFIG_PM_SLEEP */ | 807 | #endif /* CONFIG_PM_SLEEP */ |
808 | 808 | ||
809 | static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) | 809 | static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, |
810 | unsigned long *flags) | ||
810 | { | 811 | { |
811 | int ret; | 812 | int ret; |
812 | 813 | struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); | |
813 | lockdep_assert_held(&trans->reg_lock); | 814 | spin_lock_irqsave(&pcie_trans->reg_lock, *flags); |
814 | 815 | ||
815 | /* this bit wakes up the NIC */ | 816 | /* this bit wakes up the NIC */ |
816 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, | 817 | __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, |
@@ -846,16 +847,32 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) | |||
846 | WARN_ONCE(1, | 847 | WARN_ONCE(1, |
847 | "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", | 848 | "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", |
848 | val); | 849 | val); |
850 | spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); | ||
849 | return false; | 851 | return false; |
850 | } | 852 | } |
851 | } | 853 | } |
852 | 854 | ||
855 | /* | ||
856 | * Fool sparse by faking we release the lock - sparse will | ||
857 | * track nic_access anyway. | ||
858 | */ | ||
859 | __release(&pcie_trans->reg_lock); | ||
853 | return true; | 860 | return true; |
854 | } | 861 | } |
855 | 862 | ||
856 | static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) | 863 | static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, |
864 | unsigned long *flags) | ||
857 | { | 865 | { |
858 | lockdep_assert_held(&trans->reg_lock); | 866 | struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); |
867 | |||
868 | lockdep_assert_held(&pcie_trans->reg_lock); | ||
869 | |||
870 | /* | ||
871 | * Fool sparse by faking we acquiring the lock - sparse will | ||
872 | * track nic_access anyway. | ||
873 | */ | ||
874 | __acquire(&pcie_trans->reg_lock); | ||
875 | |||
859 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, | 876 | __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, |
860 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 877 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
861 | /* | 878 | /* |
@@ -865,6 +882,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) | |||
865 | * scheduled on different CPUs (after we drop reg_lock). | 882 | * scheduled on different CPUs (after we drop reg_lock). |
866 | */ | 883 | */ |
867 | mmiowb(); | 884 | mmiowb(); |
885 | spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); | ||
868 | } | 886 | } |
869 | 887 | ||
870 | static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, | 888 | static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, |
@@ -874,16 +892,14 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, | |||
874 | int offs, ret = 0; | 892 | int offs, ret = 0; |
875 | u32 *vals = buf; | 893 | u32 *vals = buf; |
876 | 894 | ||
877 | spin_lock_irqsave(&trans->reg_lock, flags); | 895 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
878 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
879 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); | 896 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); |
880 | for (offs = 0; offs < dwords; offs++) | 897 | for (offs = 0; offs < dwords; offs++) |
881 | vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | 898 | vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); |
882 | iwl_trans_release_nic_access(trans); | 899 | iwl_trans_release_nic_access(trans, &flags); |
883 | } else { | 900 | } else { |
884 | ret = -EBUSY; | 901 | ret = -EBUSY; |
885 | } | 902 | } |
886 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
887 | return ret; | 903 | return ret; |
888 | } | 904 | } |
889 | 905 | ||
@@ -894,17 +910,15 @@ static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, | |||
894 | int offs, ret = 0; | 910 | int offs, ret = 0; |
895 | u32 *vals = buf; | 911 | u32 *vals = buf; |
896 | 912 | ||
897 | spin_lock_irqsave(&trans->reg_lock, flags); | 913 | if (iwl_trans_grab_nic_access(trans, false, &flags)) { |
898 | if (iwl_trans_grab_nic_access(trans, false)) { | ||
899 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); | 914 | iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); |
900 | for (offs = 0; offs < dwords; offs++) | 915 | for (offs = 0; offs < dwords; offs++) |
901 | iwl_write32(trans, HBUS_TARG_MEM_WDAT, | 916 | iwl_write32(trans, HBUS_TARG_MEM_WDAT, |
902 | vals ? vals[offs] : 0); | 917 | vals ? vals[offs] : 0); |
903 | iwl_trans_release_nic_access(trans); | 918 | iwl_trans_release_nic_access(trans, &flags); |
904 | } else { | 919 | } else { |
905 | ret = -EBUSY; | 920 | ret = -EBUSY; |
906 | } | 921 | } |
907 | spin_unlock_irqrestore(&trans->reg_lock, flags); | ||
908 | return ret; | 922 | return ret; |
909 | } | 923 | } |
910 | 924 | ||
@@ -982,11 +996,12 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) | |||
982 | static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, | 996 | static void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, |
983 | u32 mask, u32 value) | 997 | u32 mask, u32 value) |
984 | { | 998 | { |
999 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
985 | unsigned long flags; | 1000 | unsigned long flags; |
986 | 1001 | ||
987 | spin_lock_irqsave(&trans->reg_lock, flags); | 1002 | spin_lock_irqsave(&trans_pcie->reg_lock, flags); |
988 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, value); | 1003 | __iwl_trans_pcie_set_bits_mask(trans, reg, mask, value); |
989 | spin_unlock_irqrestore(&trans->reg_lock, flags); | 1004 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); |
990 | } | 1005 | } |
991 | 1006 | ||
992 | static const char *get_fh_string(int cmd) | 1007 | static const char *get_fh_string(int cmd) |
@@ -1467,6 +1482,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1467 | trans->cfg = cfg; | 1482 | trans->cfg = cfg; |
1468 | trans_pcie->trans = trans; | 1483 | trans_pcie->trans = trans; |
1469 | spin_lock_init(&trans_pcie->irq_lock); | 1484 | spin_lock_init(&trans_pcie->irq_lock); |
1485 | spin_lock_init(&trans_pcie->reg_lock); | ||
1470 | init_waitqueue_head(&trans_pcie->ucode_write_waitq); | 1486 | init_waitqueue_head(&trans_pcie->ucode_write_waitq); |
1471 | 1487 | ||
1472 | /* W/A - seems to solve weird behavior. We need to remove this if we | 1488 | /* W/A - seems to solve weird behavior. We need to remove this if we |
@@ -1533,7 +1549,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1533 | 1549 | ||
1534 | /* Initialize the wait queue for commands */ | 1550 | /* Initialize the wait queue for commands */ |
1535 | init_waitqueue_head(&trans_pcie->wait_command_queue); | 1551 | init_waitqueue_head(&trans_pcie->wait_command_queue); |
1536 | spin_lock_init(&trans->reg_lock); | ||
1537 | 1552 | ||
1538 | snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), | 1553 | snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), |
1539 | "iwl_cmd_pool:%s", dev_name(trans->dev)); | 1554 | "iwl_cmd_pool:%s", dev_name(trans->dev)); |