patch-2.4.8 linux/drivers/s390/block/dasd_fba.c
Next file: linux/drivers/s390/block/dasd_fba.h
Previous file: linux/drivers/s390/block/dasd_eckd.h
Back to the patch index
Back to the overall index
- Lines: 513
- Date:
Sun Aug 5 13:12:41 2001
- Orig file:
v2.4.7/linux/drivers/s390/block/dasd_fba.c
- Orig date:
Wed Apr 11 19:02:28 2001
diff -u --recursive --new-file v2.4.7/linux/drivers/s390/block/dasd_fba.c linux/drivers/s390/block/dasd_fba.c
@@ -12,19 +12,21 @@
#include <linux/kernel.h>
#include <asm/debug.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/blk.h>
+
#include <asm/ccwcache.h>
#include <asm/idals.h>
-#include <asm/dasd.h>
-
#include <asm/ebcdic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/s390dyn.h>
+#include "dasd_int.h"
#include "dasd_fba.h"
+#include "dasd_3370_erp.h"
+#include "dasd_9336_erp.h"
#ifdef PRINTK_HEADER
#undef PRINTK_HEADER
@@ -39,44 +41,38 @@
dasd_discipline_t dasd_fba_discipline;
typedef struct
-dasd_fba_private_t {
+ dasd_fba_private_t {
dasd_fba_characteristics_t rdc_data;
} dasd_fba_private_t;
#ifdef CONFIG_DASD_DYNAMIC
static
-devreg_t dasd_fba_known_devices[] =
-{
+devreg_t dasd_fba_known_devices[] = {
{
- ci:
- {hc:
- {ctype:0x6310,
- dtype:0x9336}},
- flag:(DEVREG_MATCH_CU_TYPE |
- DEVREG_MATCH_DEV_TYPE|
- DEVREG_TYPE_DEVCHARS),
- oper_func:dasd_oper_handler
- },
+ ci: { hc: {ctype:0x6310, dtype:0x9336}},
+ flag:(DEVREG_MATCH_CU_TYPE |
+ DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS),
+ oper_func:dasd_oper_handler
+ },
{
- ci:
- {hc:
- {ctype:0x3880,
- dtype:0x3370}},
- flag:(DEVREG_MATCH_CU_TYPE |
- DEVREG_MATCH_DEV_TYPE|
- DEVREG_TYPE_DEVCHARS),
- oper_func:dasd_oper_handler
- }
+ ci: { hc: {ctype:0x3880, dtype:0x3370}},
+ flag:(DEVREG_MATCH_CU_TYPE |
+ DEVREG_MATCH_DEV_TYPE | DEVREG_TYPE_DEVCHARS),
+ oper_func:dasd_oper_handler
+ }
};
#endif
-static inline void
+static inline int
define_extent (ccw1_t * ccw, DE_fba_data_t * DE_data, int rw,
- int blksize, int beg, int nr)
+ int blksize, int beg, int nr, ccw_req_t* cqr,
+ dasd_device_t* device)
{
+ int rc=0;
memset (DE_data, 0, sizeof (DE_fba_data_t));
ccw->cmd_code = DASD_FBA_CCW_DEFINE_EXTENT;
ccw->count = 16;
- set_normalized_cda (ccw, __pa (DE_data));
+ if (rc=dasd_set_normalized_cda (ccw, __pa (DE_data), cqr, device))
+ return rc;
if (rw == WRITE)
(DE_data->mask).perm = 0x0;
else if (rw == READ)
@@ -86,16 +82,17 @@
DE_data->blk_size = blksize;
DE_data->ext_loc = beg;
DE_data->ext_end = nr - 1;
+ return rc;
}
static inline void
locate_record (ccw1_t * ccw, LO_fba_data_t * LO_data, int rw, int block_nr,
- int block_ct)
+ int block_ct, ccw_req_t* cqr, dasd_device_t* device)
{
memset (LO_data, 0, sizeof (LO_fba_data_t));
ccw->cmd_code = DASD_FBA_CCW_LOCATE;
ccw->count = 8;
- set_normalized_cda (ccw, __pa (LO_data));
+ dasd_set_normalized_cda (ccw, __pa (LO_data), cqr, device);
if (rw == WRITE)
LO_data->operation.cmd = 0x5;
else if (rw == READ)
@@ -109,9 +106,9 @@
static int
dasd_fba_id_check (s390_dev_info_t * info)
{
- if (info->sid_data.cu_type == 0x3880)
- if (info->sid_data.dev_type == 0x3370)
- return 0;
+ if (info->sid_data.cu_type == 0x3880)
+ if (info->sid_data.dev_type == 0x3370)
+ return 0;
if (info->sid_data.cu_type == 0x6310)
if (info->sid_data.dev_type == 0x9336)
return 0;
@@ -127,37 +124,43 @@
if (device == NULL) {
printk (KERN_WARNING PRINTK_HEADER
- "Null device pointer passed to characteristics checker\n");
- return -ENODEV;
+ "Null device pointer passed to characteristics checker\n");
+ return -ENODEV;
}
- if ( device->private != NULL ) {
- kfree(device->private);
- }
- device->private = kmalloc (sizeof (dasd_fba_private_t), GFP_KERNEL);
+ device->private = kmalloc (sizeof (dasd_fba_private_t), GFP_KERNEL);
if (device->private == NULL) {
- printk (KERN_WARNING PRINTK_HEADER
- "memory allocation failed for private data\n");
- return -ENOMEM;
+ printk (KERN_WARNING PRINTK_HEADER
+ "memory allocation failed for private data\n");
+ rc = -ENOMEM;
+ goto fail;
}
private = (dasd_fba_private_t *) device->private;
rdc_data = (void *) &(private->rdc_data);
rc = read_dev_chars (device->devinfo.irq, &rdc_data, 32);
if (rc) {
- printk (KERN_WARNING PRINTK_HEADER
- "Read device characteristics returned error %d\n", rc);
- kfree(private);
- device->private=NULL;
- return rc;
+ printk (KERN_WARNING PRINTK_HEADER
+ "Read device characteristics returned error %d\n", rc);
+ goto fail;
}
printk (KERN_INFO PRINTK_HEADER
"%04X on sch %d: %04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)\n",
device->devinfo.devno, device->devinfo.irq,
- device->devinfo.sid_data.dev_type, device->devinfo.sid_data.dev_model,
- device->devinfo.sid_data.cu_type, device->devinfo.sid_data.cu_model,
+ device->devinfo.sid_data.dev_type,
+ device->devinfo.sid_data.dev_model,
+ device->devinfo.sid_data.cu_type,
+ device->devinfo.sid_data.cu_model,
(private->rdc_data.blk_bdsa *
(private->rdc_data.blk_size >> 9)) >> 11,
private->rdc_data.blk_size);
- return 0;
+ goto out;
+ fail:
+ if ( rc ) {
+ kfree(device->private);
+ device->private = NULL;
+ }
+
+ out:
+ return rc;
}
static int
@@ -187,7 +190,7 @@
device->sizes.s2b_shift++;
device->sizes.blocks = (private->rdc_data.blk_bdsa);
- device->sizes.pt_block = 1;
+ device->sizes.pt_block = 1;
return rc;
}
@@ -221,7 +224,7 @@
dasd_device_t *device = (dasd_device_t *) cqr->device;
if (stat->cstat == 0x00 &&
stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
- return dasd_era_none;
+ return dasd_era_none;
switch (device->devinfo.sid_data.dev_model) {
case 0x3370:
@@ -236,17 +239,16 @@
static dasd_erp_action_fn_t
dasd_fba_erp_action (ccw_req_t * cqr)
{
- return default_erp_action;
+ return dasd_default_erp_action;
}
static dasd_erp_postaction_fn_t
dasd_fba_erp_postaction (ccw_req_t * cqr)
{
- if (cqr->function == default_erp_action)
- return default_erp_postaction;
+ if (cqr->function == dasd_default_erp_action)
+ return dasd_default_erp_postaction;
printk (KERN_WARNING PRINTK_HEADER
- "unknown ERP action %p\n",
- cqr->function);
+ "unknown ERP action %p\n", cqr->function);
return NULL;
}
@@ -255,7 +257,7 @@
{
ccw_req_t *rw_cp = NULL;
int rw_cmd;
- int bhct, i;
+ int bhct, i = 0;
long size;
ccw1_t *ccw;
DE_fba_data_t *DE_data;
@@ -263,7 +265,7 @@
struct buffer_head *bh;
dasd_fba_private_t *private = (dasd_fba_private_t *) device->private;
int byt_per_blk = device->sizes.bp_block;
-
+
if (req->cmd == READ) {
rw_cmd = DASD_FBA_CCW_READ;
} else if (req->cmd == WRITE) {
@@ -273,20 +275,30 @@
return NULL;
}
/* Build the request */
- /* count bhs to prevent errors, when bh smaller than block */
+ /* count hs to prevent errors, when bh smaller than block */
+ bh = req -> bh;
bhct = 0;
- for (bh = req->bh; bh; bh = bh->b_reqnext) {
- if (bh->b_size > byt_per_blk)
- for (size = 0; size < bh->b_size; size += byt_per_blk)
- bhct++;
- else
- bhct++;
- }
-
- rw_cp = dasd_alloc_request (dasd_fba_discipline.name,
- 1 + 2*bhct,
- sizeof (DE_fba_data_t) +
- bhct*sizeof (LO_fba_data_t));
+ while ( bh != NULL ) {
+ if (bh->b_size < byt_per_blk) {
+ BUG();
+ }
+ bhct += bh->b_size >> (device->sizes.s2b_shift+9);
+ bh = bh->b_reqnext;
+ }
+
+ if (private->rdc_data.mode.bits.data_chain) {
+ rw_cp = dasd_alloc_request (dasd_fba_discipline.name,
+ 2 + bhct,
+ sizeof (DE_fba_data_t) +
+ sizeof (LO_fba_data_t),
+ device);
+ } else {
+ rw_cp = dasd_alloc_request (dasd_fba_discipline.name,
+ 1 + 2 * bhct,
+ sizeof (DE_fba_data_t) +
+ bhct * sizeof (LO_fba_data_t),
+ device);
+ }
if (!rw_cp) {
return NULL;
}
@@ -294,64 +306,77 @@
LO_data = rw_cp->data + sizeof (DE_fba_data_t);
ccw = rw_cp->cpaddr;
- define_extent (ccw, DE_data, req->cmd, byt_per_blk,
- req->sector, req->nr_sectors);
+ if (define_extent (ccw, DE_data, req->cmd, byt_per_blk,
+ req->sector, req->nr_sectors, rw_cp, device)) {
+ goto clear_rw_cp;
+ }
ccw->flags |= CCW_FLAG_CC;
-
- for (i = 0, bh = req->bh; bh;) {
- if (bh->b_size > byt_per_blk) {
- for (size = 0; size < bh->b_size; size += byt_per_blk) {
- ccw++;
- locate_record (ccw, LO_data, req->cmd, i, 1);
- ccw->flags |= CCW_FLAG_CC;
- ccw++;
- ccw->flags |= CCW_FLAG_CC|CCW_FLAG_SLI;
- ccw->cmd_code = rw_cmd;
- ccw->count = byt_per_blk;
- set_normalized_cda (ccw, __pa (bh->b_data + size));
- i++;
- LO_data++;
- }
- bh = bh->b_reqnext;
- } else { /* group N bhs to fit into byt_per_blk */
- for (size = 0; bh != NULL && size < byt_per_blk;) {
- ccw++;
- locate_record (ccw, LO_data, req->cmd, i, 1);
+ ccw ++;
+ locate_record (ccw, LO_data, req->cmd, 0,
+ private->rdc_data.mode.bits.data_chain ? bhct : 1, rw_cp, device);
+ if (ccw->cda == 0) {
+ goto clear_rw_cp;
+ }
+ ccw->flags |= CCW_FLAG_CC;
+
+ bh = req -> bh;
+ i = 0;
+ while ( bh != NULL ) {
+ for (size = 0; size < bh->b_size; size += byt_per_blk) {
+ ccw ++;
+ ccw->cmd_code = rw_cmd;
+ ccw->count = byt_per_blk;
+ if (dasd_set_normalized_cda (ccw,__pa (bh->b_data + size), rw_cp, device)) {
+ goto clear_rw_cp;
+ }
+ if (private->rdc_data.mode.bits.data_chain) {
+ ccw->flags |= CCW_FLAG_DC;
+ } else {
ccw->flags |= CCW_FLAG_CC;
- ccw++;
- if (private->rdc_data.mode.bits.data_chain) {
- ccw->flags |= CCW_FLAG_DC|CCW_FLAG_SLI;
- } else {
- PRINT_WARN ("Cannot chain chunks smaller than one block\n");
- ccw_free_request (rw_cp);
- return NULL;
- }
- ccw->cmd_code = rw_cmd;
- ccw->count = bh->b_size;
- set_normalized_cda (ccw, __pa (bh->b_data));
- size += bh->b_size;
- bh = bh->b_reqnext;
- i++;
- LO_data++;
- }
- ccw->flags &= ~CCW_FLAG_DC;
- ccw->flags |= CCW_FLAG_CC|CCW_FLAG_SLI;
- if (size != byt_per_blk) {
- PRINT_WARN ("Cannot fulfill request smaller than block\n");
- ccw_free_request (rw_cp);
- return NULL;
- }
- }
- }
+ }
+ }
+ bh = bh->b_reqnext;
+ if ( bh != NULL &&
+ !(private->rdc_data.mode.bits.data_chain)) {
+ ccw++;
+ i++;
+ LO_data++;
+ locate_record (ccw, LO_data, req->cmd, i, 1, rw_cp, device);
+ if (ccw->cda == 0) {
+ goto clear_rw_cp;
+ }
+ ccw->flags |= CCW_FLAG_CC;
+ }
+ }
ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC);
rw_cp->device = device;
rw_cp->expires = 5 * TOD_MIN; /* 5 minutes */
rw_cp->req = req;
check_then_set (&rw_cp->status, CQR_STATUS_EMPTY, CQR_STATUS_FILLED);
+ goto out;
+ clear_rw_cp:
+ dasd_free_request (rw_cp, device);
+ rw_cp = NULL;
+ out:
return rw_cp;
}
+static int
+dasd_fba_fill_info (dasd_device_t * device, dasd_information_t * info)
+{
+ int rc = 0;
+ info->label_block = 1;
+ info->FBA_layout = 1;
+ info->characteristics_size = sizeof (dasd_fba_characteristics_t);
+ memcpy (info->characteristics,
+ &((dasd_fba_private_t *) device->private)->rdc_data,
+ sizeof (dasd_fba_characteristics_t));
+ info->confdata_size = 0;
+ return rc;
+}
+
+
static char *
dasd_fba_dump_sense (struct dasd_device_t *device, ccw_req_t * req)
{
@@ -367,25 +392,26 @@
return page;
}
-dasd_discipline_t dasd_fba_discipline =
-{
+dasd_discipline_t dasd_fba_discipline = {
+ owner: THIS_MODULE,
name:"FBA ",
ebcname:"FBA ",
- max_blocks:((PAGE_SIZE >> 1)/sizeof(ccw1_t)-1),
+ max_blocks:((PAGE_SIZE >> 1) / sizeof (ccw1_t) - 1),
id_check:dasd_fba_id_check,
check_characteristics:dasd_fba_check_characteristics,
do_analysis:dasd_fba_do_analysis,
fill_geometry:dasd_fba_fill_geometry,
start_IO:dasd_start_IO,
+ term_IO:dasd_term_IO,
examine_error:dasd_fba_examine_error,
erp_action:dasd_fba_erp_action,
erp_postaction:dasd_fba_erp_postaction,
build_cp_from_req:dasd_fba_build_cp_from_req,
dump_sense:dasd_fba_dump_sense,
- int_handler:dasd_int_handler
+ int_handler:dasd_int_handler,
+ fill_info:dasd_fba_fill_info,
};
-
int
dasd_fba_init (void)
{
@@ -393,18 +419,22 @@
printk (KERN_INFO PRINTK_HEADER
"%s discipline initializing\n", dasd_fba_discipline.name);
ASCEBC (dasd_fba_discipline.ebcname, 4);
- dasd_discipline_enq (&dasd_fba_discipline);
-#ifdef CONFIG_DASD_DYNAMIC
- {
- int i;
- for (i = 0; i < sizeof (dasd_fba_known_devices) / sizeof (devreg_t); i++) {
- printk (KERN_INFO PRINTK_HEADER
- "We are interested in: CU %04X/%02x\n",
- dasd_fba_known_devices[i].ci.hc.ctype,
- dasd_fba_known_devices[i].ci.hc.cmode);
- s390_device_register (&dasd_fba_known_devices[i]);
- }
- }
+ dasd_discipline_add (&dasd_fba_discipline);
+#ifdef CONFIG_DASD_DYNAMIC
+ {
+ int i;
+ for (i = 0;
+ i < sizeof (dasd_fba_known_devices) / sizeof (devreg_t);
+ i++) {
+ printk (KERN_INFO PRINTK_HEADER
+ "We are interested in: Dev %04X/%02X @ CU %04X/%02x\n",
+ dasd_fba_known_devices[i].ci.hc.dtype,
+ dasd_fba_known_devices[i].ci.hc.dmode,
+ dasd_fba_known_devices[i].ci.hc.ctype,
+ dasd_fba_known_devices[i].ci.hc.cmode);
+ s390_device_register (&dasd_fba_known_devices[i]);
+ }
+ }
#endif /* CONFIG_DASD_DYNAMIC */
return rc;
}
@@ -417,16 +447,31 @@
{
int i;
for ( i=0; i<sizeof(dasd_fba_known_devices)/sizeof(devreg_t); i++) {
- printk (KERN_INFO PRINTK_HEADER
- "We were interested in: CU %04X/%02x\n",
- dasd_fba_known_devices[i].ci.hc.ctype,
- dasd_fba_known_devices[i].ci.hc.cmode);
s390_device_unregister(&dasd_fba_known_devices[i]);
}
}
#endif /* CONFIG_DASD_DYNAMIC */
- dasd_discipline_deq(&dasd_fba_discipline);
+ dasd_discipline_del(&dasd_fba_discipline);
+}
+
+#ifdef MODULE
+int
+init_module (void)
+{
+ int rc = 0;
+ rc = dasd_fba_init ();
+ return rc;
}
+
+void
+cleanup_module (void)
+{
+ dasd_fba_cleanup ();
+ return;
+}
+#endif
+
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)