aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/access.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 39bb96b413ef..98ddba94b5b9 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -133,39 +133,46 @@ PCI_USER_WRITE_CONFIG(dword, u32)
133 133
134struct pci_vpd_pci22 { 134struct pci_vpd_pci22 {
135 struct pci_vpd base; 135 struct pci_vpd base;
136 spinlock_t lock; /* controls access to hardware and the flags */ 136 struct mutex lock;
137 u8 cap; 137 u16 flag;
138 bool busy; 138 bool busy;
139 bool flag; /* value of F bit to wait for */ 139 u8 cap;
140}; 140};
141 141
142/* Wait for last operation to complete */ 142/*
143 * Wait for last operation to complete.
144 * This code has to spin since there is no other notification from the PCI
145 * hardware. Since the VPD is often implemented by serial attachment to an
146 * EEPROM, it may take many milliseconds to complete.
147 */
143static int pci_vpd_pci22_wait(struct pci_dev *dev) 148static int pci_vpd_pci22_wait(struct pci_dev *dev)
144{ 149{
145 struct pci_vpd_pci22 *vpd = 150 struct pci_vpd_pci22 *vpd =
146 container_of(dev->vpd, struct pci_vpd_pci22, base); 151 container_of(dev->vpd, struct pci_vpd_pci22, base);
147 u16 flag, status; 152 unsigned long timeout = jiffies + HZ/20 + 2;
148 int wait; 153 u16 status;
149 int ret; 154 int ret;
150 155
151 if (!vpd->busy) 156 if (!vpd->busy)
152 return 0; 157 return 0;
153 158
154 flag = vpd->flag ? PCI_VPD_ADDR_F : 0;
155 wait = vpd->flag ? 10 : 1000; /* read: 100 us; write: 10 ms */
156 for (;;) { 159 for (;;) {
157 ret = pci_user_read_config_word(dev, 160 ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
158 vpd->cap + PCI_VPD_ADDR,
159 &status); 161 &status);
160 if (ret < 0) 162 if (ret)
161 return ret; 163 return ret;
162 if ((status & PCI_VPD_ADDR_F) == flag) { 164
165 if ((status & PCI_VPD_ADDR_F) == vpd->flag) {
163 vpd->busy = false; 166 vpd->busy = false;
164 return 0; 167 return 0;
165 } 168 }
166 if (wait-- == 0) 169
170 if (time_after(jiffies, timeout))
167 return -ETIMEDOUT; 171 return -ETIMEDOUT;
168 udelay(10); 172 if (fatal_signal_pending(current))
173 return -EINTR;
174 if (!cond_resched())
175 udelay(10);
169 } 176 }
170} 177}
171 178
@@ -175,7 +182,7 @@ static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
175 struct pci_vpd_pci22 *vpd = 182 struct pci_vpd_pci22 *vpd =
176 container_of(dev->vpd, struct pci_vpd_pci22, base); 183 container_of(dev->vpd, struct pci_vpd_pci22, base);
177 u32 val; 184 u32 val;
178 int ret; 185 int ret = 0;
179 int begin, end, i; 186 int begin, end, i;
180 187
181 if (pos < 0 || pos > vpd->base.len || size > vpd->base.len - pos) 188 if (pos < 0 || pos > vpd->base.len || size > vpd->base.len - pos)
@@ -183,7 +190,9 @@ static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
183 if (size == 0) 190 if (size == 0)
184 return 0; 191 return 0;
185 192
186 spin_lock_irq(&vpd->lock); 193 if (mutex_lock_killable(&vpd->lock))
194 return -EINTR;
195
187 ret = pci_vpd_pci22_wait(dev); 196 ret = pci_vpd_pci22_wait(dev);
188 if (ret < 0) 197 if (ret < 0)
189 goto out; 198 goto out;
@@ -191,15 +200,16 @@ static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
191 pos & ~3); 200 pos & ~3);
192 if (ret < 0) 201 if (ret < 0)
193 goto out; 202 goto out;
203
194 vpd->busy = true; 204 vpd->busy = true;
195 vpd->flag = 1; 205 vpd->flag = PCI_VPD_ADDR_F;
196 ret = pci_vpd_pci22_wait(dev); 206 ret = pci_vpd_pci22_wait(dev);
197 if (ret < 0) 207 if (ret < 0)
198 goto out; 208 goto out;
199 ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA, 209 ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA,
200 &val); 210 &val);
201out: 211out:
202 spin_unlock_irq(&vpd->lock); 212 mutex_unlock(&vpd->lock);
203 if (ret < 0) 213 if (ret < 0)
204 return ret; 214 return ret;
205 215
@@ -220,7 +230,7 @@ static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size,
220 struct pci_vpd_pci22 *vpd = 230 struct pci_vpd_pci22 *vpd =
221 container_of(dev->vpd, struct pci_vpd_pci22, base); 231 container_of(dev->vpd, struct pci_vpd_pci22, base);
222 u32 val; 232 u32 val;
223 int ret; 233 int ret = 0;
224 234
225 if (pos < 0 || pos > vpd->base.len || pos & 3 || 235 if (pos < 0 || pos > vpd->base.len || pos & 3 ||
226 size > vpd->base.len - pos || size < 4) 236 size > vpd->base.len - pos || size < 4)
@@ -231,7 +241,8 @@ static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size,
231 val |= ((u8) *buf++) << 16; 241 val |= ((u8) *buf++) << 16;
232 val |= ((u32)(u8) *buf++) << 24; 242 val |= ((u32)(u8) *buf++) << 24;
233 243
234 spin_lock_irq(&vpd->lock); 244 if (mutex_lock_killable(&vpd->lock))
245 return -EINTR;
235 ret = pci_vpd_pci22_wait(dev); 246 ret = pci_vpd_pci22_wait(dev);
236 if (ret < 0) 247 if (ret < 0)
237 goto out; 248 goto out;
@@ -247,7 +258,7 @@ static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size,
247 vpd->flag = 0; 258 vpd->flag = 0;
248 ret = pci_vpd_pci22_wait(dev); 259 ret = pci_vpd_pci22_wait(dev);
249out: 260out:
250 spin_unlock_irq(&vpd->lock); 261 mutex_unlock(&vpd->lock);
251 if (ret < 0) 262 if (ret < 0)
252 return ret; 263 return ret;
253 264
@@ -279,7 +290,7 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
279 290
280 vpd->base.len = PCI_VPD_PCI22_SIZE; 291 vpd->base.len = PCI_VPD_PCI22_SIZE;
281 vpd->base.ops = &pci_vpd_pci22_ops; 292 vpd->base.ops = &pci_vpd_pci22_ops;
282 spin_lock_init(&vpd->lock); 293 mutex_init(&vpd->lock);
283 vpd->cap = cap; 294 vpd->cap = cap;
284 vpd->busy = false; 295 vpd->busy = false;
285 dev->vpd = &vpd->base; 296 dev->vpd = &vpd->base;