aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/hpilo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/hpilo.c')
-rw-r--r--drivers/misc/hpilo.c290
1 files changed, 203 insertions, 87 deletions
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 880ccf39e23b..1ad27c6abcca 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/fs.h> 14#include <linux/fs.h>
15#include <linux/pci.h> 15#include <linux/pci.h>
16#include <linux/interrupt.h>
16#include <linux/ioport.h> 17#include <linux/ioport.h>
17#include <linux/device.h> 18#include <linux/device.h>
18#include <linux/file.h> 19#include <linux/file.h>
@@ -21,6 +22,8 @@
21#include <linux/delay.h> 22#include <linux/delay.h>
22#include <linux/uaccess.h> 23#include <linux/uaccess.h>
23#include <linux/io.h> 24#include <linux/io.h>
25#include <linux/wait.h>
26#include <linux/poll.h>
24#include "hpilo.h" 27#include "hpilo.h"
25 28
26static struct class *ilo_class; 29static struct class *ilo_class;
@@ -61,9 +64,10 @@ static inline int desc_mem_sz(int nr_entry)
61static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry) 64static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry)
62{ 65{
63 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar); 66 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
67 unsigned long flags;
64 int ret = 0; 68 int ret = 0;
65 69
66 spin_lock(&hw->fifo_lock); 70 spin_lock_irqsave(&hw->fifo_lock, flags);
67 if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask] 71 if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask]
68 & ENTRY_MASK_O)) { 72 & ENTRY_MASK_O)) {
69 fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |= 73 fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |=
@@ -71,7 +75,7 @@ static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry)
71 fifo_q->tail += 1; 75 fifo_q->tail += 1;
72 ret = 1; 76 ret = 1;
73 } 77 }
74 spin_unlock(&hw->fifo_lock); 78 spin_unlock_irqrestore(&hw->fifo_lock, flags);
75 79
76 return ret; 80 return ret;
77} 81}
@@ -79,10 +83,11 @@ static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry)
79static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry) 83static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry)
80{ 84{
81 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar); 85 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
86 unsigned long flags;
82 int ret = 0; 87 int ret = 0;
83 u64 c; 88 u64 c;
84 89
85 spin_lock(&hw->fifo_lock); 90 spin_lock_irqsave(&hw->fifo_lock, flags);
86 c = fifo_q->fifobar[fifo_q->head & fifo_q->imask]; 91 c = fifo_q->fifobar[fifo_q->head & fifo_q->imask];
87 if (c & ENTRY_MASK_C) { 92 if (c & ENTRY_MASK_C) {
88 if (entry) 93 if (entry)
@@ -93,7 +98,23 @@ static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry)
93 fifo_q->head += 1; 98 fifo_q->head += 1;
94 ret = 1; 99 ret = 1;
95 } 100 }
96 spin_unlock(&hw->fifo_lock); 101 spin_unlock_irqrestore(&hw->fifo_lock, flags);
102
103 return ret;
104}
105
106static int fifo_check_recv(struct ilo_hwinfo *hw, char *fifobar)
107{
108 struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
109 unsigned long flags;
110 int ret = 0;
111 u64 c;
112
113 spin_lock_irqsave(&hw->fifo_lock, flags);
114 c = fifo_q->fifobar[fifo_q->head & fifo_q->imask];
115 if (c & ENTRY_MASK_C)
116 ret = 1;
117 spin_unlock_irqrestore(&hw->fifo_lock, flags);
97 118
98 return ret; 119 return ret;
99} 120}
@@ -142,6 +163,13 @@ static int ilo_pkt_dequeue(struct ilo_hwinfo *hw, struct ccb *ccb,
142 return ret; 163 return ret;
143} 164}
144 165
166static int ilo_pkt_recv(struct ilo_hwinfo *hw, struct ccb *ccb)
167{
168 char *fifobar = ccb->ccb_u3.recv_fifobar;
169
170 return fifo_check_recv(hw, fifobar);
171}
172
145static inline void doorbell_set(struct ccb *ccb) 173static inline void doorbell_set(struct ccb *ccb)
146{ 174{
147 iowrite8(1, ccb->ccb_u5.db_base); 175 iowrite8(1, ccb->ccb_u5.db_base);
@@ -151,6 +179,7 @@ static inline void doorbell_clr(struct ccb *ccb)
151{ 179{
152 iowrite8(2, ccb->ccb_u5.db_base); 180 iowrite8(2, ccb->ccb_u5.db_base);
153} 181}
182
154static inline int ctrl_set(int l2sz, int idxmask, int desclim) 183static inline int ctrl_set(int l2sz, int idxmask, int desclim)
155{ 184{
156 int active = 0, go = 1; 185 int active = 0, go = 1;
@@ -160,6 +189,7 @@ static inline int ctrl_set(int l2sz, int idxmask, int desclim)
160 active << CTRL_BITPOS_A | 189 active << CTRL_BITPOS_A |
161 go << CTRL_BITPOS_G; 190 go << CTRL_BITPOS_G;
162} 191}
192
163static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz) 193static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz)
164{ 194{
165 /* for simplicity, use the same parameters for send and recv ctrls */ 195 /* for simplicity, use the same parameters for send and recv ctrls */
@@ -192,13 +222,10 @@ static void fifo_setup(void *base_addr, int nr_entry)
192 222
193static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) 223static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
194{ 224{
195 struct ccb *driver_ccb; 225 struct ccb *driver_ccb = &data->driver_ccb;
196 struct ccb __iomem *device_ccb; 226 struct ccb __iomem *device_ccb = data->mapped_ccb;
197 int retries; 227 int retries;
198 228
199 driver_ccb = &data->driver_ccb;
200 device_ccb = data->mapped_ccb;
201
202 /* complicated dance to tell the hw we are stopping */ 229 /* complicated dance to tell the hw we are stopping */
203 doorbell_clr(driver_ccb); 230 doorbell_clr(driver_ccb);
204 iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G), 231 iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G),
@@ -225,26 +252,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); 252 pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
226} 253}
227 254
228static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) 255static int ilo_ccb_setup(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
229{ 256{
230 char *dma_va, *dma_pa; 257 char *dma_va, *dma_pa;
231 int pkt_id, pkt_sz, i, error;
232 struct ccb *driver_ccb, *ilo_ccb; 258 struct ccb *driver_ccb, *ilo_ccb;
233 struct pci_dev *pdev;
234 259
235 driver_ccb = &data->driver_ccb; 260 driver_ccb = &data->driver_ccb;
236 ilo_ccb = &data->ilo_ccb; 261 ilo_ccb = &data->ilo_ccb;
237 pdev = hw->ilo_dev;
238 262
239 data->dma_size = 2 * fifo_sz(NR_QENTRY) + 263 data->dma_size = 2 * fifo_sz(NR_QENTRY) +
240 2 * desc_mem_sz(NR_QENTRY) + 264 2 * desc_mem_sz(NR_QENTRY) +
241 ILO_START_ALIGN + ILO_CACHE_SZ; 265 ILO_START_ALIGN + ILO_CACHE_SZ;
242 266
243 error = -ENOMEM; 267 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); 268 &data->dma_pa);
246 if (!data->dma_va) 269 if (!data->dma_va)
247 goto out; 270 return -ENOMEM;
248 271
249 dma_va = (char *)data->dma_va; 272 dma_va = (char *)data->dma_va;
250 dma_pa = (char *)data->dma_pa; 273 dma_pa = (char *)data->dma_pa;
@@ -290,10 +313,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); 313 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 */ 314 ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */
292 315
316 return 0;
317}
318
319static void ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
320{
321 int pkt_id, pkt_sz;
322 struct ccb *driver_ccb = &data->driver_ccb;
323
293 /* copy the ccb with physical addrs to device memory */ 324 /* copy the ccb with physical addrs to device memory */
294 data->mapped_ccb = (struct ccb __iomem *) 325 data->mapped_ccb = (struct ccb __iomem *)
295 (hw->ram_vaddr + (slot * ILOHW_CCB_SZ)); 326 (hw->ram_vaddr + (slot * ILOHW_CCB_SZ));
296 memcpy_toio(data->mapped_ccb, ilo_ccb, sizeof(struct ccb)); 327 memcpy_toio(data->mapped_ccb, &data->ilo_ccb, sizeof(struct ccb));
297 328
298 /* put packets on the send and receive queues */ 329 /* put packets on the send and receive queues */
299 pkt_sz = 0; 330 pkt_sz = 0;
@@ -306,7 +337,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++) 337 for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++)
307 ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz); 338 ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz);
308 339
340 /* the ccb is ready to use */
309 doorbell_clr(driver_ccb); 341 doorbell_clr(driver_ccb);
342}
343
344static int ilo_ccb_verify(struct ilo_hwinfo *hw, struct ccb_data *data)
345{
346 int pkt_id, i;
347 struct ccb *driver_ccb = &data->driver_ccb;
310 348
311 /* make sure iLO is really handling requests */ 349 /* make sure iLO is really handling requests */
312 for (i = MAX_WAIT; i > 0; i--) { 350 for (i = MAX_WAIT; i > 0; i--) {
@@ -315,20 +353,14 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
315 udelay(WAIT_TIME); 353 udelay(WAIT_TIME);
316 } 354 }
317 355
318 if (i) { 356 if (i == 0) {
319 ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0); 357 dev_err(&hw->ilo_dev->dev, "Open could not dequeue a packet\n");
320 doorbell_set(driver_ccb); 358 return -EBUSY;
321 } else {
322 dev_err(&pdev->dev, "Open could not dequeue a packet\n");
323 error = -EBUSY;
324 goto free;
325 } 359 }
326 360
361 ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0);
362 doorbell_set(driver_ccb);
327 return 0; 363 return 0;
328free:
329 ilo_ccb_close(pdev, data);
330out:
331 return error;
332} 364}
333 365
334static inline int is_channel_reset(struct ccb *ccb) 366static inline int is_channel_reset(struct ccb *ccb)
@@ -343,19 +375,45 @@ static inline void set_channel_reset(struct ccb *ccb)
343 FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1; 375 FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1;
344} 376}
345 377
378static inline int get_device_outbound(struct ilo_hwinfo *hw)
379{
380 return ioread32(&hw->mmio_vaddr[DB_OUT]);
381}
382
383static inline int is_db_reset(int db_out)
384{
385 return db_out & (1 << DB_RESET);
386}
387
346static inline int is_device_reset(struct ilo_hwinfo *hw) 388static inline int is_device_reset(struct ilo_hwinfo *hw)
347{ 389{
348 /* check for global reset condition */ 390 /* check for global reset condition */
349 return ioread32(&hw->mmio_vaddr[DB_OUT]) & (1 << DB_RESET); 391 return is_db_reset(get_device_outbound(hw));
392}
393
394static inline void clear_pending_db(struct ilo_hwinfo *hw, int clr)
395{
396 iowrite32(clr, &hw->mmio_vaddr[DB_OUT]);
350} 397}
351 398
352static inline void clear_device(struct ilo_hwinfo *hw) 399static inline void clear_device(struct ilo_hwinfo *hw)
353{ 400{
354 /* clear the device (reset bits, pending channel entries) */ 401 /* clear the device (reset bits, pending channel entries) */
355 iowrite32(-1, &hw->mmio_vaddr[DB_OUT]); 402 clear_pending_db(hw, -1);
403}
404
405static inline void ilo_enable_interrupts(struct ilo_hwinfo *hw)
406{
407 iowrite8(ioread8(&hw->mmio_vaddr[DB_IRQ]) | 1, &hw->mmio_vaddr[DB_IRQ]);
356} 408}
357 409
358static void ilo_locked_reset(struct ilo_hwinfo *hw) 410static inline void ilo_disable_interrupts(struct ilo_hwinfo *hw)
411{
412 iowrite8(ioread8(&hw->mmio_vaddr[DB_IRQ]) & ~1,
413 &hw->mmio_vaddr[DB_IRQ]);
414}
415
416static void ilo_set_reset(struct ilo_hwinfo *hw)
359{ 417{
360 int slot; 418 int slot;
361 419
@@ -368,40 +426,22 @@ static void ilo_locked_reset(struct ilo_hwinfo *hw)
368 continue; 426 continue;
369 set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb); 427 set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb);
370 } 428 }
371
372 clear_device(hw);
373}
374
375static void ilo_reset(struct ilo_hwinfo *hw)
376{
377 spin_lock(&hw->alloc_lock);
378
379 /* reset might have been handled after lock was taken */
380 if (is_device_reset(hw))
381 ilo_locked_reset(hw);
382
383 spin_unlock(&hw->alloc_lock);
384} 429}
385 430
386static ssize_t ilo_read(struct file *fp, char __user *buf, 431static ssize_t ilo_read(struct file *fp, char __user *buf,
387 size_t len, loff_t *off) 432 size_t len, loff_t *off)
388{ 433{
389 int err, found, cnt, pkt_id, pkt_len; 434 int err, found, cnt, pkt_id, pkt_len;
390 struct ccb_data *data; 435 struct ccb_data *data = fp->private_data;
391 struct ccb *driver_ccb; 436 struct ccb *driver_ccb = &data->driver_ccb;
392 struct ilo_hwinfo *hw; 437 struct ilo_hwinfo *hw = data->ilo_hw;
393 void *pkt; 438 void *pkt;
394 439
395 data = fp->private_data; 440 if (is_channel_reset(driver_ccb)) {
396 driver_ccb = &data->driver_ccb;
397 hw = data->ilo_hw;
398
399 if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
400 /* 441 /*
401 * If the device has been reset, applications 442 * If the device has been reset, applications
402 * need to close and reopen all ccbs. 443 * need to close and reopen all ccbs.
403 */ 444 */
404 ilo_reset(hw);
405 return -ENODEV; 445 return -ENODEV;
406 } 446 }
407 447
@@ -442,23 +482,13 @@ static ssize_t ilo_write(struct file *fp, const char __user *buf,
442 size_t len, loff_t *off) 482 size_t len, loff_t *off)
443{ 483{
444 int err, pkt_id, pkt_len; 484 int err, pkt_id, pkt_len;
445 struct ccb_data *data; 485 struct ccb_data *data = fp->private_data;
446 struct ccb *driver_ccb; 486 struct ccb *driver_ccb = &data->driver_ccb;
447 struct ilo_hwinfo *hw; 487 struct ilo_hwinfo *hw = data->ilo_hw;
448 void *pkt; 488 void *pkt;
449 489
450 data = fp->private_data; 490 if (is_channel_reset(driver_ccb))
451 driver_ccb = &data->driver_ccb;
452 hw = data->ilo_hw;
453
454 if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
455 /*
456 * If the device has been reset, applications
457 * need to close and reopen all ccbs.
458 */
459 ilo_reset(hw);
460 return -ENODEV; 491 return -ENODEV;
461 }
462 492
463 /* get a packet to send the user command */ 493 /* get a packet to send the user command */
464 if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt)) 494 if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt))
@@ -480,32 +510,48 @@ static ssize_t ilo_write(struct file *fp, const char __user *buf,
480 return err ? -EFAULT : len; 510 return err ? -EFAULT : len;
481} 511}
482 512
513static unsigned int ilo_poll(struct file *fp, poll_table *wait)
514{
515 struct ccb_data *data = fp->private_data;
516 struct ccb *driver_ccb = &data->driver_ccb;
517
518 poll_wait(fp, &data->ccb_waitq, wait);
519
520 if (is_channel_reset(driver_ccb))
521 return POLLERR;
522 else if (ilo_pkt_recv(data->ilo_hw, driver_ccb))
523 return POLLIN | POLLRDNORM;
524
525 return 0;
526}
527
483static int ilo_close(struct inode *ip, struct file *fp) 528static int ilo_close(struct inode *ip, struct file *fp)
484{ 529{
485 int slot; 530 int slot;
486 struct ccb_data *data; 531 struct ccb_data *data;
487 struct ilo_hwinfo *hw; 532 struct ilo_hwinfo *hw;
533 unsigned long flags;
488 534
489 slot = iminor(ip) % MAX_CCB; 535 slot = iminor(ip) % MAX_CCB;
490 hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); 536 hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
491 537
492 spin_lock(&hw->alloc_lock); 538 spin_lock(&hw->open_lock);
493
494 if (is_device_reset(hw))
495 ilo_locked_reset(hw);
496 539
497 if (hw->ccb_alloc[slot]->ccb_cnt == 1) { 540 if (hw->ccb_alloc[slot]->ccb_cnt == 1) {
498 541
499 data = fp->private_data; 542 data = fp->private_data;
500 543
544 spin_lock_irqsave(&hw->alloc_lock, flags);
545 hw->ccb_alloc[slot] = NULL;
546 spin_unlock_irqrestore(&hw->alloc_lock, flags);
547
501 ilo_ccb_close(hw->ilo_dev, data); 548 ilo_ccb_close(hw->ilo_dev, data);
502 549
503 kfree(data); 550 kfree(data);
504 hw->ccb_alloc[slot] = NULL;
505 } else 551 } else
506 hw->ccb_alloc[slot]->ccb_cnt--; 552 hw->ccb_alloc[slot]->ccb_cnt--;
507 553
508 spin_unlock(&hw->alloc_lock); 554 spin_unlock(&hw->open_lock);
509 555
510 return 0; 556 return 0;
511} 557}
@@ -515,6 +561,7 @@ static int ilo_open(struct inode *ip, struct file *fp)
515 int slot, error; 561 int slot, error;
516 struct ccb_data *data; 562 struct ccb_data *data;
517 struct ilo_hwinfo *hw; 563 struct ilo_hwinfo *hw;
564 unsigned long flags;
518 565
519 slot = iminor(ip) % MAX_CCB; 566 slot = iminor(ip) % MAX_CCB;
520 hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev); 567 hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
@@ -524,22 +571,42 @@ static int ilo_open(struct inode *ip, struct file *fp)
524 if (!data) 571 if (!data)
525 return -ENOMEM; 572 return -ENOMEM;
526 573
527 spin_lock(&hw->alloc_lock); 574 spin_lock(&hw->open_lock);
528
529 if (is_device_reset(hw))
530 ilo_locked_reset(hw);
531 575
532 /* each fd private_data holds sw/hw view of ccb */ 576 /* each fd private_data holds sw/hw view of ccb */
533 if (hw->ccb_alloc[slot] == NULL) { 577 if (hw->ccb_alloc[slot] == NULL) {
534 /* create a channel control block for this minor */ 578 /* create a channel control block for this minor */
535 error = ilo_ccb_open(hw, data, slot); 579 error = ilo_ccb_setup(hw, data, slot);
536 if (!error) { 580 if (error) {
537 hw->ccb_alloc[slot] = data;
538 hw->ccb_alloc[slot]->ccb_cnt = 1;
539 hw->ccb_alloc[slot]->ccb_excl = fp->f_flags & O_EXCL;
540 hw->ccb_alloc[slot]->ilo_hw = hw;
541 } else
542 kfree(data); 581 kfree(data);
582 goto out;
583 }
584
585 data->ccb_cnt = 1;
586 data->ccb_excl = fp->f_flags & O_EXCL;
587 data->ilo_hw = hw;
588 init_waitqueue_head(&data->ccb_waitq);
589
590 /* write the ccb to hw */
591 spin_lock_irqsave(&hw->alloc_lock, flags);
592 ilo_ccb_open(hw, data, slot);
593 hw->ccb_alloc[slot] = data;
594 spin_unlock_irqrestore(&hw->alloc_lock, flags);
595
596 /* make sure the channel is functional */
597 error = ilo_ccb_verify(hw, data);
598 if (error) {
599
600 spin_lock_irqsave(&hw->alloc_lock, flags);
601 hw->ccb_alloc[slot] = NULL;
602 spin_unlock_irqrestore(&hw->alloc_lock, flags);
603
604 ilo_ccb_close(hw->ilo_dev, data);
605
606 kfree(data);
607 goto out;
608 }
609
543 } else { 610 } else {
544 kfree(data); 611 kfree(data);
545 if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) { 612 if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) {
@@ -554,7 +621,8 @@ static int ilo_open(struct inode *ip, struct file *fp)
554 error = 0; 621 error = 0;
555 } 622 }
556 } 623 }
557 spin_unlock(&hw->alloc_lock); 624out:
625 spin_unlock(&hw->open_lock);
558 626
559 if (!error) 627 if (!error)
560 fp->private_data = hw->ccb_alloc[slot]; 628 fp->private_data = hw->ccb_alloc[slot];
@@ -566,10 +634,46 @@ static const struct file_operations ilo_fops = {
566 .owner = THIS_MODULE, 634 .owner = THIS_MODULE,
567 .read = ilo_read, 635 .read = ilo_read,
568 .write = ilo_write, 636 .write = ilo_write,
637 .poll = ilo_poll,
569 .open = ilo_open, 638 .open = ilo_open,
570 .release = ilo_close, 639 .release = ilo_close,
571}; 640};
572 641
642static irqreturn_t ilo_isr(int irq, void *data)
643{
644 struct ilo_hwinfo *hw = data;
645 int pending, i;
646
647 spin_lock(&hw->alloc_lock);
648
649 /* check for ccbs which have data */
650 pending = get_device_outbound(hw);
651 if (!pending) {
652 spin_unlock(&hw->alloc_lock);
653 return IRQ_NONE;
654 }
655
656 if (is_db_reset(pending)) {
657 /* wake up all ccbs if the device was reset */
658 pending = -1;
659 ilo_set_reset(hw);
660 }
661
662 for (i = 0; i < MAX_CCB; i++) {
663 if (!hw->ccb_alloc[i])
664 continue;
665 if (pending & (1 << i))
666 wake_up_interruptible(&hw->ccb_alloc[i]->ccb_waitq);
667 }
668
669 /* clear the device of the channels that have been handled */
670 clear_pending_db(hw, pending);
671
672 spin_unlock(&hw->alloc_lock);
673
674 return IRQ_HANDLED;
675}
676
573static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw) 677static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
574{ 678{
575 pci_iounmap(pdev, hw->db_vaddr); 679 pci_iounmap(pdev, hw->db_vaddr);
@@ -623,6 +727,8 @@ static void ilo_remove(struct pci_dev *pdev)
623 device_destroy(ilo_class, MKDEV(ilo_major, i)); 727 device_destroy(ilo_class, MKDEV(ilo_major, i));
624 728
625 cdev_del(&ilo_hw->cdev); 729 cdev_del(&ilo_hw->cdev);
730 ilo_disable_interrupts(ilo_hw);
731 free_irq(pdev->irq, ilo_hw);
626 ilo_unmap_device(pdev, ilo_hw); 732 ilo_unmap_device(pdev, ilo_hw);
627 pci_release_regions(pdev); 733 pci_release_regions(pdev);
628 pci_disable_device(pdev); 734 pci_disable_device(pdev);
@@ -658,6 +764,7 @@ static int __devinit ilo_probe(struct pci_dev *pdev,
658 ilo_hw->ilo_dev = pdev; 764 ilo_hw->ilo_dev = pdev;
659 spin_lock_init(&ilo_hw->alloc_lock); 765 spin_lock_init(&ilo_hw->alloc_lock);
660 spin_lock_init(&ilo_hw->fifo_lock); 766 spin_lock_init(&ilo_hw->fifo_lock);
767 spin_lock_init(&ilo_hw->open_lock);
661 768
662 error = pci_enable_device(pdev); 769 error = pci_enable_device(pdev);
663 if (error) 770 if (error)
@@ -676,13 +783,19 @@ static int __devinit ilo_probe(struct pci_dev *pdev,
676 pci_set_drvdata(pdev, ilo_hw); 783 pci_set_drvdata(pdev, ilo_hw);
677 clear_device(ilo_hw); 784 clear_device(ilo_hw);
678 785
786 error = request_irq(pdev->irq, ilo_isr, IRQF_SHARED, "hpilo", ilo_hw);
787 if (error)
788 goto unmap;
789
790 ilo_enable_interrupts(ilo_hw);
791
679 cdev_init(&ilo_hw->cdev, &ilo_fops); 792 cdev_init(&ilo_hw->cdev, &ilo_fops);
680 ilo_hw->cdev.owner = THIS_MODULE; 793 ilo_hw->cdev.owner = THIS_MODULE;
681 start = devnum * MAX_CCB; 794 start = devnum * MAX_CCB;
682 error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB); 795 error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB);
683 if (error) { 796 if (error) {
684 dev_err(&pdev->dev, "Could not add cdev\n"); 797 dev_err(&pdev->dev, "Could not add cdev\n");
685 goto unmap; 798 goto remove_isr;
686 } 799 }
687 800
688 for (minor = 0 ; minor < MAX_CCB; minor++) { 801 for (minor = 0 ; minor < MAX_CCB; minor++) {
@@ -695,6 +808,9 @@ static int __devinit ilo_probe(struct pci_dev *pdev,
695 } 808 }
696 809
697 return 0; 810 return 0;
811remove_isr:
812 ilo_disable_interrupts(ilo_hw);
813 free_irq(pdev->irq, ilo_hw);
698unmap: 814unmap:
699 ilo_unmap_device(pdev, ilo_hw); 815 ilo_unmap_device(pdev, ilo_hw);
700free_regions: 816free_regions:
@@ -759,7 +875,7 @@ static void __exit ilo_exit(void)
759 class_destroy(ilo_class); 875 class_destroy(ilo_class);
760} 876}
761 877
762MODULE_VERSION("1.1"); 878MODULE_VERSION("1.2");
763MODULE_ALIAS(ILO_NAME); 879MODULE_ALIAS(ILO_NAME);
764MODULE_DESCRIPTION(ILO_NAME); 880MODULE_DESCRIPTION(ILO_NAME);
765MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); 881MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");