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