patch-2.2.16 linux/drivers/s390/block/dasd_ccwstuff.c
Next file: linux/drivers/s390/block/dasd_ccwstuff.h
Previous file: linux/drivers/s390/block/dasd_9343_erp.c
Back to the patch index
Back to the overall index
- Lines: 203
- Date:
Wed Jun 7 14:26:43 2000
- Orig file:
v2.2.15/linux/drivers/s390/block/dasd_ccwstuff.c
- Orig date:
Wed May 3 17:16:43 2000
diff -urN v2.2.15/linux/drivers/s390/block/dasd_ccwstuff.c linux/drivers/s390/block/dasd_ccwstuff.c
@@ -9,9 +9,9 @@
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <asm/spinlock.h>
+#include <linux/dasd.h>
#include <asm/atomic.h>
-#include "dasd.h"
#include "dasd_types.h"
#define PRINTK_HEADER "dasd_ccw:"
@@ -148,7 +148,6 @@
}
#endif /* DASD_PARANOIA */
exit:
- FUNCTION_EXIT ("request_cpa");
return freeblk;
}
@@ -263,6 +262,69 @@
return;
}
+/* ---------------------------------------------------------- */
+
+static erp_t *erpp = NULL;
+#ifdef __SMP__
+static spinlock_t erp_lock = SPIN_LOCK_UNLOCKED;
+#endif /* __SMP__ */
+
+void
+erf_enq (erp_t * cqf)
+{
+ *(erp_t **) cqf = erpp;
+ erpp = cqf;
+}
+
+erp_t *
+erf_deq (void)
+{
+ erp_t *erp = erpp;
+ erpp = *(erp_t **) erpp;
+ return erp;
+}
+
+erp_t *
+request_er (void)
+{
+ erp_t *erp = NULL;
+ int i;
+ erp_t *area;
+
+ spin_lock (&erp_lock);
+ while (erpp == NULL) {
+ do {
+ area = (erp_t *) get_free_page (GFP_ATOMIC);
+ if (area == NULL) {
+ printk (KERN_WARNING PRINTK_HEADER
+ "No memory for chanq area\n");
+ }
+ } while (!area);
+ memset (area, 0, PAGE_SIZE);
+ if (dasd_page_count + 1 >= MAX_DASD_PAGES) {
+ PRINT_WARN ("Requesting too many pages...");
+ } else {
+ dasd_page[dasd_page_count++] =
+ (long) area;
+ }
+ for (i = 0; i < 4096 / sizeof (erp_t); i++) {
+ erf_enq (area + i);
+ }
+ }
+ erp = erf_deq ();
+ spin_unlock (&erp_lock);
+ return erp;
+}
+
+void
+release_er (erp_t * erp)
+{
+ spin_lock (&erp_lock);
+ erf_enq (erp);
+ spin_unlock (&erp_lock);
+ return;
+}
+
/* ----------------------------------------------------------- */
cqr_t *
request_cqr (int cpsize, int datasize)
@@ -296,8 +358,6 @@
memset (cqr->data,0,datasize);
}
goto exit;
- nodata:
- release_cp (cqr->cplength, cqr->cpaddr);
nocp:
release_cq (cqr);
cqr = NULL;
@@ -327,6 +387,59 @@
return rc;
}
+/* ----------------------------------------------------------- */
+erp_t *
+allloc_erp (erp_t * erp, int cpsize, int datasize)
+{
+ if (cpsize) {
+ erp->cqr.cpaddr = request_cp (cpsize);
+ if (erp->cqr.cpaddr == NULL) {
+ printk (KERN_WARNING PRINTK_HEADER __FILE__
+ "No memory for channel program\n");
+ goto nocp;
+ }
+ erp->cqr.cplength = cpsize;
+ }
+ if (datasize) {
+ do {
+ erp->cqr.data = (char *) kmalloc (datasize, GFP_ATOMIC);
+ if (erp->cqr.data == NULL) {
+ printk (KERN_WARNING PRINTK_HEADER __FILE__
+ "No memory for ERP data area\n");
+ }
+ } while (!erp->cqr.data);
+ memset (erp->cqr.data, 0, datasize);
+ }
+ goto exit;
+ nocp:
+ release_er (erp);
+ erp = NULL;
+ exit:
+ return erp;
+}
+
+int
+release_erp (erp_t * erp)
+{
+ int rc = 0;
+ if (erp == NULL) {
+ rc = -ENOENT;
+ return rc;
+ }
+ if (erp->cqr.data) {
+ kfree (erp->cqr.data);
+ }
+ if (erp->cqr.dstat) {
+ kfree (erp->cqr.dstat);
+ }
+ if (erp->cqr.cpaddr) {
+ release_cp (erp->cqr.cplength, erp->cqr.cpaddr);
+ }
+ erp->cqr.magic = dasd_MAGIC;
+ release_er (erp);
+ return rc;
+}
+
/* -------------------------------------------------------------- */
void
dasd_chanq_enq (dasd_chanq_t * q, cqr_t * cqr)
@@ -338,13 +451,18 @@
cqr->next = NULL;
q->tail = cqr;
q->queued_requests ++;
- if (atomic_compare_and_swap(CQR_STATUS_FILLED,
- CQR_STATUS_QUEUED,
- &cqr->status)) {
- PRINT_WARN ("q_cqr: %p status changed %d\n",
- cqr,atomic_read(&cqr->status));
- atomic_set(&cqr->status,CQR_STATUS_QUEUED);
+ ACS (cqr->status, CQR_STATUS_FILLED, CQR_STATUS_QUEUED);
}
+
+void
+dasd_chanq_enq_head (dasd_chanq_t * q, cqr_t * cqr)
+{
+ cqr->next = q->head;
+ q->head = cqr;
+ if (q->tail == NULL)
+ q->tail = cqr;
+ q->queued_requests++;
+ ACS (cqr->status, CQR_STATUS_FILLED, CQR_STATUS_QUEUED);
}
int
@@ -370,6 +488,9 @@
}
cqr->next = NULL;
q->queued_requests --;
+ if (cqr->magic == ERP_MAGIC)
+ return release_erp ((erp_t *) cqr);
+ else
return release_cqr(cqr);
}
@@ -408,8 +529,7 @@
spin_lock(&cq_lock);
if (! (atomic_read(&q->flags) & DASD_CHANQ_ACTIVE)) {
PRINT_WARN("Queue not active\n");
- }
- else if (cq_head == q) {
+ } else if (cq_head == q) {
cq_head = q->next_q;
} else {
c = cq_head;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)