aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/hpilo.c
diff options
context:
space:
mode:
authorDavid Altobelli <david.altobelli@hp.com>2009-08-17 19:07:03 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-15 12:50:48 -0400
commit66d5e5169c96f3e0175235e2bcbaedc8bc1c728f (patch)
tree8453acb01486b2e4adea3bc5284ca365fe78ae9c /drivers/misc/hpilo.c
parentdaa4122673f002911122cac2b996bd36b6c01b32 (diff)
hpilo: staging for interrupt handling
Refactor some hpilo routines in order to allow for locking changes in interrupt handling. Should not be functionally different. Signed-off-by: David Altobelli <david.altobelli@hp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/misc/hpilo.c')
-rw-r--r--drivers/misc/hpilo.c120
1 files changed, 73 insertions, 47 deletions
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 880ccf39e23b..35ed12379cd0 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -151,6 +151,7 @@ static inline void doorbell_clr(struct ccb *ccb)
151{ 151{
152 iowrite8(2, ccb->ccb_u5.db_base); 152 iowrite8(2, ccb->ccb_u5.db_base);
153} 153}
154
154static inline int ctrl_set(int l2sz, int idxmask, int desclim) 155static inline int ctrl_set(int l2sz, int idxmask, int desclim)
155{ 156{
156 int active = 0, go = 1; 157 int active = 0, go = 1;
@@ -160,6 +161,7 @@ static inline int ctrl_set(int l2sz, int idxmask, int desclim)
160 active << CTRL_BITPOS_A | 161 active << CTRL_BITPOS_A |
161 go << CTRL_BITPOS_G; 162 go << CTRL_BITPOS_G;
162} 163}
164
163static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz) 165static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz)
164{ 166{
165 /* for simplicity, use the same parameters for send and recv ctrls */ 167 /* for simplicity, use the same parameters for send and recv ctrls */
@@ -192,13 +194,10 @@ static void fifo_setup(void *base_addr, int nr_entry)
192 194
193static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) 195static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
194{ 196{
195 struct ccb *driver_ccb; 197 struct ccb *driver_ccb = &data->driver_ccb;
196 struct ccb __iomem *device_ccb; 198 struct ccb __iomem *device_ccb = data->mapped_ccb;
197 int retries; 199 int retries;
198 200
199 driver_ccb = &data->driver_ccb;
200 device_ccb = data->mapped_ccb;
201
202 /* complicated dance to tell the hw we are stopping */ 201 /* complicated dance to tell the hw we are stopping */
203 doorbell_clr(driver_ccb); 202 doorbell_clr(driver_ccb);
204 iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G), 203 iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G),
@@ -225,26 +224,22 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
225 pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa); 224 pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
226} 225}
227 226
228static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) 227static int ilo_ccb_setup(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
229{ 228{
230 char *dma_va, *dma_pa; 229 char *dma_va, *dma_pa;
231 int pkt_id, pkt_sz, i, error;
232 struct ccb *driver_ccb, *ilo_ccb; 230 struct ccb *driver_ccb, *ilo_ccb;
233 struct pci_dev *pdev;
234 231
235 driver_ccb = &data->driver_ccb; 232 driver_ccb = &data->driver_ccb;
236 ilo_ccb = &data->ilo_ccb; 233 ilo_ccb = &data->ilo_ccb;
237 pdev = hw->ilo_dev;
238 234
239 data->dma_size = 2 * fifo_sz(NR_QENTRY) + 235 data->dma_size = 2 * fifo_sz(NR_QENTRY) +
240 2 * desc_mem_sz(NR_QENTRY) + 236 2 * desc_mem_sz(NR_QENTRY) +
241 ILO_START_ALIGN + ILO_CACHE_SZ; 237 ILO_START_ALIGN + ILO_CACHE_SZ;
242 238
243 error = -ENOMEM; 239 data->dma_va = pci_alloc_consistent(hw->ilo_dev, data->dma_size,
244 data->dma_va = pci_alloc_consistent(pdev, data->dma_size,
245 &data->dma_pa); 240 &data->dma_pa);
246 if (!data->dma_va) 241 if (!data->dma_va)
247 goto out; 242 return -ENOMEM;
248 243
249 dma_va = (char *)data->dma_va; 244 dma_va = (char *)data->dma_va;
250 dma_pa = (char *)data->dma_pa; 245 dma_pa = (char *)data->dma_pa;
@@ -290,10 +285,18 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
290 driver_ccb->ccb_u5.db_base = hw->db_vaddr + (slot << L2_DB_SIZE); 285 driver_ccb->ccb_u5.db_base = hw->db_vaddr + (slot << L2_DB_SIZE);
291 ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */ 286 ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */
292 287
288 return 0;
289}
290
291static void ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
292{
293 int pkt_id, pkt_sz;
294 struct ccb *driver_ccb = &data->driver_ccb;
295
293 /* copy the ccb with physical addrs to device memory */ 296 /* copy the ccb with physical addrs to device memory */
294 data->mapped_ccb = (struct ccb __iomem *) 297 data->mapped_ccb = (struct ccb __iomem *)
295 (hw->ram_vaddr + (slot * ILOHW_CCB_SZ)); 298 (hw->ram_vaddr + (slot * ILOHW_CCB_SZ));
296 memcpy_toio(data->mapped_ccb, ilo_ccb, sizeof(struct ccb)); 299 memcpy_toio(data->mapped_ccb, &data->ilo_ccb, sizeof(struct ccb));
297 300
298 /* put packets on the send and receive queues */ 301 /* put packets on the send and receive queues */
299 pkt_sz = 0; 302 pkt_sz = 0;
@@ -306,7 +309,14 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
306 for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) 309 for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++)
307 ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz); 310 ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz);
308 311
312 /* the ccb is ready to use */
309 doorbell_clr(driver_ccb); 313 doorbell_clr(driver_ccb);
314}
315
316static int ilo_ccb_verify(struct ilo_hwinfo *hw, struct ccb_data *data)
317{
318 int pkt_id, i;
319 struct ccb *driver_ccb = &data->driver_ccb;
310 320
311 /* make sure iLO is really handling requests */ 321 /* make sure iLO is really handling requests */
312 for (i = MAX_WAIT; i > 0; i--) { 322 for (i = MAX_WAIT; i > 0; i--) {
@@ -315,20 +325,14 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
315 udelay(WAIT_TIME); 325 udelay(WAIT_TIME);
316 } 326 }
317 327
318 if (i) { 328 if (i == 0) {
319 ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0); 329 dev_err(&hw->ilo_dev->dev, "Open could not dequeue a packet\n");
320 doorbell_set(driver_ccb); 330 return -EBUSY;
321 } else {
322 dev_err(&pdev->dev, "Open could not dequeue a packet\n");
323 error = -EBUSY;
324 goto free;
325 } 331 }
326 332
333 ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0);
334 doorbell_set(driver_ccb);
327 return 0; 335 return 0;
328free:
329 ilo_ccb_close(pdev, data);
330out:
331 return error;
332} 336}
333 337
334static inline int is_channel_reset(struct ccb *ccb) 338static inline int is_channel_reset(struct ccb *ccb)
@@ -343,16 +347,31 @@ static inline void set_channel_reset(struct ccb *ccb)
343 FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1; 347 FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1;
344} 348}
345 349
350static inline int get_device_outbound(struct ilo_hwinfo *hw)
351{
352 return ioread32(&hw->mmio_vaddr[DB_OUT]);
353}
354
355static inline int is_db_reset(int db_out)
356{
357 return db_out & (1 << DB_RESET);
358}
359
346static inline int is_device_reset(struct ilo_hwinfo *hw) 360static inline int is_device_reset(struct ilo_hwinfo *hw)
347{ 361{
348 /* check for global reset condition */ 362 /* check for global reset condition */
349 return ioread32(&hw->mmio_vaddr[DB_OUT]) & (1 << DB_RESET); 363 return is_db_reset(get_device_outbound(hw));
364}
365
366static inline void clear_pending_db(struct ilo_hwinfo *hw, int clr)
367{
368 iowrite32(clr, &hw->mmio_vaddr[DB_OUT]);
350} 369}
351 370
352static inline void clear_device(struct ilo_hwinfo *hw) 371static inline void clear_device(struct ilo_hwinfo *hw)
353{ 372{
354 /* clear the device (reset bits, pending channel entries) */ 373 /* clear the device (reset bits, pending channel entries) */
355 iowrite32(-1, &hw->mmio_vaddr[DB_OUT]); 374 clear_pending_db(hw, -1);
356} 375}
357 376
358static void ilo_locked_reset(struct ilo_hwinfo *hw) 377static void ilo_locked_reset(struct ilo_hwinfo *hw)
@@ -387,15 +406,11 @@ static ssize_t ilo_read(struct file *fp, char __user *buf,
387 size_t len, loff_t *off) 406 size_t len, loff_t *off)
388{ 407{
389 int err, found, cnt, pkt_id, pkt_len; 408 int err, found, cnt, pkt_id, pkt_len;
390 struct ccb_data *data; 409 struct ccb_data *data = fp->private_data;
391 struct ccb *driver_ccb; 410 struct ccb *driver_ccb = &data->driver_ccb;
392 struct ilo_hwinfo *hw; 411 struct ilo_hwinfo *hw = data->ilo_hw;
393 void *pkt; 412 void *pkt;
394 413
395 data = fp->private_data;
396 driver_ccb = &data->driver_ccb;
397 hw = data->ilo_hw;
398
399 if (is_device_reset(hw) || is_channel_reset(driver_ccb)) { 414 if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
400 /* 415 /*
401 * If the device has been reset, applications 416 * If the device has been reset, applications
@@ -442,15 +457,11 @@ static ssize_t ilo_write(struct file *fp, const char __user *buf,
442 size_t len, loff_t *off) 457 size_t len, loff_t *off)
443{ 458{
444 int err, pkt_id, pkt_len; 459 int err, pkt_id, pkt_len;
445 struct ccb_data *data; 460 struct ccb_data *data = fp->private_data;
446 struct ccb *driver_ccb; 461 struct ccb *driver_ccb = &data->driver_ccb;
447 struct ilo_hwinfo *hw; 462 struct ilo_hwinfo *hw = data->ilo_hw;
448 void *pkt; 463 void *pkt;
449 464
450 data = fp->private_data;
451 driver_ccb = &data->driver_ccb;
452 hw = data->ilo_hw;
453
454 if (is_device_reset(hw) || is_channel_reset(driver_ccb)) { 465 if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
455 /* 466 /*
456 * If the device has been reset, applications 467 * If the device has been reset, applications
@@ -532,14 +543,28 @@ static int ilo_open(struct inode *ip, struct file *fp)
532 /* each fd private_data holds sw/hw view of ccb */ 543 /* each fd private_data holds sw/hw view of ccb */
533 if (hw->ccb_alloc[slot] == NULL) { 544 if (hw->ccb_alloc[slot] == NULL) {
534 /* create a channel control block for this minor */ 545 /* create a channel control block for this minor */
535 error = ilo_ccb_open(hw, data, slot); 546 error = ilo_ccb_setup(hw, data, slot);
536 if (!error) { 547 if (error) {
537 hw->ccb_alloc[slot] = data; 548 kfree(data);
538 hw->ccb_alloc[slot]->ccb_cnt = 1; 549 goto out;
539 hw->ccb_alloc[slot]->ccb_excl = fp->f_flags & O_EXCL; 550 }
540 hw->ccb_alloc[slot]->ilo_hw = hw; 551
541 } else 552 /* write the ccb to hw */
553 ilo_ccb_open(hw, data, slot);
554
555 /* make sure the channel is functional */
556 error = ilo_ccb_verify(hw, data);
557 if (error) {
558 ilo_ccb_close(hw->ilo_dev, data);
542 kfree(data); 559 kfree(data);
560 goto out;
561 }
562
563 data->ccb_cnt = 1;
564 data->ccb_excl = fp->f_flags & O_EXCL;
565 data->ilo_hw = hw;
566 hw->ccb_alloc[slot] = data;
567
543 } else { 568 } else {
544 kfree(data); 569 kfree(data);
545 if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) { 570 if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) {
@@ -554,6 +579,7 @@ static int ilo_open(struct inode *ip, struct file *fp)
554 error = 0; 579 error = 0;
555 } 580 }
556 } 581 }
582out:
557 spin_unlock(&hw->alloc_lock); 583 spin_unlock(&hw->alloc_lock);
558 584
559 if (!error) 585 if (!error)