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