Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

GenWQE: Support blocking when DDCB queue is busy

When the GenWQE hardware queue was busy, the driver returned simply
-EBUSY. This caused polling by applications which increased the load
on the already busy system. This change implements the possiblity to
sleep on a waitqueue instead when the DDCB queue is busy. The
requestor is woken up when there is free space on the queue again.
The old way to get -EBUSY is still available if the device is openend
with O_NONBLOCKING. The default is now blocking behavior.

Signed-off-by: Frank Haverkamp <haver@linux.vnet.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Frank Haverkamp and committed by
Greg Kroah-Hartman
1451f414 08e4906c

+57 -22
+11 -6
drivers/misc/genwqe/card_base.h
··· 201 201 * @ddcb_seq: Sequence number of last DDCB 202 202 * @ddcbs_in_flight: Currently enqueued DDCBs 203 203 * @ddcbs_completed: Number of already completed DDCBs 204 - * @busy: Number of -EBUSY returns 204 + * @return_on_busy: Number of -EBUSY returns on full queue 205 + * @wait_on_busy: Number of waits on full queue 205 206 * @ddcb_daddr: DMA address of first DDCB in the queue 206 207 * @ddcb_vaddr: Kernel virtual address of first DDCB in the queue 207 208 * @ddcb_req: Associated requests (one per DDCB) ··· 219 218 unsigned int ddcbs_in_flight; /* number of ddcbs in processing */ 220 219 unsigned int ddcbs_completed; 221 220 unsigned int ddcbs_max_in_flight; 222 - unsigned int busy; /* how many times -EBUSY? */ 221 + unsigned int return_on_busy; /* how many times -EBUSY? */ 222 + unsigned int wait_on_busy; 223 223 224 224 dma_addr_t ddcb_daddr; /* DMA address */ 225 225 struct ddcb *ddcb_vaddr; /* kernel virtual addr for DDCBs */ ··· 228 226 wait_queue_head_t *ddcb_waitqs; /* waitqueue per ddcb */ 229 227 230 228 spinlock_t ddcb_lock; /* exclusive access to queue */ 231 - wait_queue_head_t ddcb_waitq; /* wait for ddcb processing */ 229 + wait_queue_head_t busy_waitq; /* wait for ddcb processing */ 232 230 233 231 /* registers or the respective queue to be used */ 234 232 u32 IO_QUEUE_CONFIG; ··· 510 508 * buildup and teardown. 511 509 */ 512 510 int __genwqe_execute_ddcb(struct genwqe_dev *cd, 513 - struct genwqe_ddcb_cmd *cmd); 511 + struct genwqe_ddcb_cmd *cmd, unsigned int f_flags); 514 512 515 513 /** 516 514 * __genwqe_execute_raw_ddcb() - Execute DDCB request without addr translation ··· 522 520 * modification. 523 521 */ 524 522 int __genwqe_execute_raw_ddcb(struct genwqe_dev *cd, 525 - struct genwqe_ddcb_cmd *cmd); 523 + struct genwqe_ddcb_cmd *cmd, 524 + unsigned int f_flags); 525 + int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, 526 + struct ddcb_requ *req, 527 + unsigned int f_flags); 526 528 527 - int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req); 528 529 int __genwqe_wait_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req); 529 530 int __genwqe_purge_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req); 530 531
+34 -10
drivers/misc/genwqe/card_ddcb.c
··· 448 448 queue->ddcbs_completed++; 449 449 queue->ddcbs_in_flight--; 450 450 451 - /* wake up process waiting for this DDCB */ 451 + /* wake up process waiting for this DDCB, and 452 + processes on the busy queue */ 452 453 wake_up_interruptible(&queue->ddcb_waitqs[queue->ddcb_act]); 454 + wake_up_interruptible(&queue->busy_waitq); 453 455 454 456 pick_next_one: 455 457 queue->ddcb_act = (queue->ddcb_act + 1) % queue->ddcb_max; ··· 747 745 748 746 /** 749 747 * __genwqe_enqueue_ddcb() - Enqueue a DDCB 750 - * @cd: pointer to genwqe device descriptor 751 - * @req: pointer to DDCB execution request 748 + * @cd: pointer to genwqe device descriptor 749 + * @req: pointer to DDCB execution request 750 + * @f_flags: file mode: blocking, non-blocking 752 751 * 753 752 * Return: 0 if enqueuing succeeded 754 753 * -EIO if card is unusable/PCIe problems 755 754 * -EBUSY if enqueuing failed 756 755 */ 757 - int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req) 756 + int __genwqe_enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_requ *req, 757 + unsigned int f_flags) 758 758 { 759 759 struct ddcb *pddcb; 760 760 unsigned long flags; ··· 764 760 struct pci_dev *pci_dev = cd->pci_dev; 765 761 u16 icrc; 766 762 763 + retry: 767 764 if (cd->card_state != GENWQE_CARD_USED) { 768 765 printk_ratelimited(KERN_ERR 769 766 "%s %s: [%s] Card is unusable/PCIe problem Req#%d\n", ··· 790 785 791 786 pddcb = get_next_ddcb(cd, queue, &req->num); /* get ptr and num */ 792 787 if (pddcb == NULL) { 788 + int rc; 789 + 793 790 spin_unlock_irqrestore(&queue->ddcb_lock, flags); 794 - queue->busy++; 795 - return -EBUSY; 791 + 792 + if (f_flags & O_NONBLOCK) { 793 + queue->return_on_busy++; 794 + return -EBUSY; 795 + } 796 + 797 + queue->wait_on_busy++; 798 + rc = wait_event_interruptible(queue->busy_waitq, 799 + queue_free_ddcbs(queue) != 0); 800 + dev_dbg(&pci_dev->dev, "[%s] waiting for free DDCB: rc=%d\n", 801 + __func__, rc); 802 + if (rc == -ERESTARTSYS) 803 + return rc; /* interrupted by a signal */ 804 + 805 + goto retry; 796 806 } 797 807 798 808 if (queue->ddcb_req[req->num] != NULL) { ··· 910 890 * __genwqe_execute_raw_ddcb() - Setup and execute DDCB 911 891 * @cd: pointer to genwqe device descriptor 912 892 * @req: user provided DDCB request 893 + * @f_flags: file mode: blocking, non-blocking 913 894 */ 914 895 int __genwqe_execute_raw_ddcb(struct genwqe_dev *cd, 915 - struct genwqe_ddcb_cmd *cmd) 896 + struct genwqe_ddcb_cmd *cmd, 897 + unsigned int f_flags) 916 898 { 917 899 int rc = 0; 918 900 struct pci_dev *pci_dev = cd->pci_dev; ··· 930 908 __func__, cmd->asiv_length); 931 909 return -EINVAL; 932 910 } 933 - rc = __genwqe_enqueue_ddcb(cd, req); 911 + rc = __genwqe_enqueue_ddcb(cd, req, f_flags); 934 912 if (rc != 0) 935 913 return rc; 936 914 ··· 1036 1014 queue->ddcbs_in_flight = 0; /* statistics */ 1037 1015 queue->ddcbs_max_in_flight = 0; 1038 1016 queue->ddcbs_completed = 0; 1039 - queue->busy = 0; 1017 + queue->return_on_busy = 0; 1018 + queue->wait_on_busy = 0; 1040 1019 1041 1020 queue->ddcb_seq = 0x100; /* start sequence number */ 1042 1021 queue->ddcb_max = genwqe_ddcb_max; /* module parameter */ ··· 1077 1054 queue->ddcb_next = 0; /* queue is empty */ 1078 1055 1079 1056 spin_lock_init(&queue->ddcb_lock); 1080 - init_waitqueue_head(&queue->ddcb_waitq); 1057 + init_waitqueue_head(&queue->busy_waitq); 1081 1058 1082 1059 val64 = ((u64)(queue->ddcb_max - 1) << 8); /* lastptr */ 1083 1060 __genwqe_writeq(cd, queue->IO_QUEUE_CONFIG, 0x07); /* iCRC/vCRC */ ··· 1325 1302 for (i = 0; i < queue->ddcb_max; i++) 1326 1303 wake_up_interruptible(&queue->ddcb_waitqs[queue->ddcb_act]); 1327 1304 1305 + wake_up_interruptible(&queue->busy_waitq); 1328 1306 spin_unlock_irqrestore(&queue->ddcb_lock, flags); 1329 1307 1330 1308 return 0;
+4 -2
drivers/misc/genwqe/card_debugfs.c
··· 244 244 " ddcbs_in_flight: %u\n" 245 245 " ddcbs_max_in_flight: %u\n" 246 246 " ddcbs_completed: %u\n" 247 - " busy: %u\n" 247 + " return_on_busy: %u\n" 248 + " wait_on_busy: %u\n" 248 249 " irqs_processed: %u\n", 249 250 queue->ddcb_max, (long long)queue->ddcb_daddr, 250 251 (long long)queue->ddcb_daddr + 251 252 (queue->ddcb_max * DDCB_LENGTH), 252 253 (long long)queue->ddcb_vaddr, queue->ddcbs_in_flight, 253 254 queue->ddcbs_max_in_flight, queue->ddcbs_completed, 254 - queue->busy, cd->irqs_processed); 255 + queue->return_on_busy, queue->wait_on_busy, 256 + cd->irqs_processed); 255 257 256 258 /* Hardware State */ 257 259 seq_printf(s, " 0x%08x 0x%016llx IO_QUEUE_CONFIG\n"
+8 -4
drivers/misc/genwqe/card_dev.c
··· 516 516 u32 crc; 517 517 u8 cmdopts; 518 518 struct genwqe_dev *cd = cfile->cd; 519 + struct file *filp = cfile->filp; 519 520 struct pci_dev *pci_dev = cd->pci_dev; 520 521 521 522 if ((load->size & 0x3) != 0) ··· 611 610 /* For Genwqe5 we get back the calculated CRC */ 612 611 *(u64 *)&req->asv[0] = 0ULL; /* 0x80 */ 613 612 614 - rc = __genwqe_execute_raw_ddcb(cd, req); 613 + rc = __genwqe_execute_raw_ddcb(cd, req, filp->f_flags); 615 614 616 615 load->retc = req->retc; 617 616 load->attn = req->attn; ··· 651 650 u8 *xbuf; 652 651 u8 cmdopts; 653 652 struct genwqe_dev *cd = cfile->cd; 653 + struct file *filp = cfile->filp; 654 654 struct pci_dev *pci_dev = cd->pci_dev; 655 655 struct genwqe_ddcb_cmd *cmd; 656 656 ··· 729 727 /* we only get back the calculated CRC */ 730 728 *(u64 *)&cmd->asv[0] = 0ULL; /* 0x80 */ 731 729 732 - rc = __genwqe_execute_raw_ddcb(cd, cmd); 730 + rc = __genwqe_execute_raw_ddcb(cd, cmd, filp->f_flags); 733 731 734 732 load->retc = cmd->retc; 735 733 load->attn = cmd->attn; ··· 990 988 { 991 989 int rc; 992 990 struct genwqe_dev *cd = cfile->cd; 991 + struct file *filp = cfile->filp; 993 992 struct ddcb_requ *req = container_of(cmd, struct ddcb_requ, cmd); 994 993 995 994 rc = ddcb_cmd_fixups(cfile, req); 996 995 if (rc != 0) 997 996 return rc; 998 997 999 - rc = __genwqe_execute_raw_ddcb(cd, cmd); 998 + rc = __genwqe_execute_raw_ddcb(cd, cmd, filp->f_flags); 1000 999 ddcb_cmd_cleanup(cfile, req); 1001 1000 return rc; 1002 1001 } ··· 1009 1006 struct genwqe_ddcb_cmd *cmd; 1010 1007 struct ddcb_requ *req; 1011 1008 struct genwqe_dev *cd = cfile->cd; 1009 + struct file *filp = cfile->filp; 1012 1010 1013 1011 cmd = ddcb_requ_alloc(); 1014 1012 if (cmd == NULL) ··· 1025 1021 if (!raw) 1026 1022 rc = genwqe_execute_ddcb(cfile, cmd); 1027 1023 else 1028 - rc = __genwqe_execute_raw_ddcb(cd, cmd); 1024 + rc = __genwqe_execute_raw_ddcb(cd, cmd, filp->f_flags); 1029 1025 1030 1026 /* Copy back only the modifed fields. Do not copy ASIV 1031 1027 back since the copy got modified by the driver. */