Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/s390/linux

Pull s390 updates from Martin Schwidefsky:
 "common I/O layer
   - Fix bit-fields crossing storage-unit boundaries in css_general_char

  dasd driver
   - Avoid a sparse warning in regard to the queue lock
   - Allocate the struct dasd_ccw_req as per request data. Only for
     internal I/O is the structure allocated separately
   - Remove the unused function dasd_kmalloc_set_cda
   - Save a few bytes in struct dasd_ccw_req by reordering fields
   - Convert remaining users of dasd_kmalloc_request to
     dasd_smalloc_request and remove the now unused function

  vfio/ccw
   - Refactor and improve pfn_array_alloc_pin/pfn_array_pin
   - Add a new tracepoint for failed vfio/ccw requests
   - Add a CCW translation improvement to accept more requests as valid
   - Bug fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/dasd: only use preallocated requests
  s390/dasd: reshuffle struct dasd_ccw_req
  s390/dasd: remove dasd_kmalloc_set_cda
  s390/dasd: move dasd_ccw_req to per request data
  s390/dasd: simplify locking in process_final_queue
  s390/cio: sanitize css_general_characteristics definition
  vfio: ccw: add tracepoints for interesting error paths
  vfio: ccw: set ccw->cda to NULL defensively
  vfio: ccw: refactor and improve pfn_array_alloc_pin()
  vfio: ccw: shorten kernel doc description for pfn_array_pin()
  vfio: ccw: push down unsupported IDA check
  vfio: ccw: fix error return in vfio_ccw_sch_event
  s390/archrandom: Rework arch random implementation.
  s390/net: add pnetid support
  • Loading branch information
Linus Torvalds committed Jun 18, 2018
2 parents 6cc22dc + ec53017 commit c0d1a7e
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 265 deletions.
62 changes: 32 additions & 30 deletions arch/s390/include/asm/css_chars.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,38 @@

struct css_general_char {
u64 : 12;
u32 dynio : 1; /* bit 12 */
u32 : 4;
u32 eadm : 1; /* bit 17 */
u32 : 23;
u32 aif : 1; /* bit 41 */
u32 : 3;
u32 mcss : 1; /* bit 45 */
u32 fcs : 1; /* bit 46 */
u32 : 1;
u32 ext_mb : 1; /* bit 48 */
u32 : 7;
u32 aif_tdd : 1; /* bit 56 */
u32 : 1;
u32 qebsm : 1; /* bit 58 */
u32 : 2;
u32 aiv : 1; /* bit 61 */
u32 : 5;
u32 aif_osa : 1; /* bit 67 */
u32 : 12;
u32 eadm_rf : 1; /* bit 80 */
u32 : 1;
u32 cib : 1; /* bit 82 */
u32 : 5;
u32 fcx : 1; /* bit 88 */
u32 : 19;
u32 alt_ssi : 1; /* bit 108 */
u32 : 1;
u32 narf : 1; /* bit 110 */
u32 : 12;
u32 util_str : 1;/* bit 123 */
u64 dynio : 1; /* bit 12 */
u64 : 4;
u64 eadm : 1; /* bit 17 */
u64 : 23;
u64 aif : 1; /* bit 41 */
u64 : 3;
u64 mcss : 1; /* bit 45 */
u64 fcs : 1; /* bit 46 */
u64 : 1;
u64 ext_mb : 1; /* bit 48 */
u64 : 7;
u64 aif_tdd : 1; /* bit 56 */
u64 : 1;
u64 qebsm : 1; /* bit 58 */
u64 : 2;
u64 aiv : 1; /* bit 61 */
u64 : 2;

u64 : 3;
u64 aif_osa : 1; /* bit 67 */
u64 : 12;
u64 eadm_rf : 1; /* bit 80 */
u64 : 1;
u64 cib : 1; /* bit 82 */
u64 : 5;
u64 fcx : 1; /* bit 88 */
u64 : 19;
u64 alt_ssi : 1; /* bit 108 */
u64 : 1;
u64 narf : 1; /* bit 110 */
u64 : 12;
u64 util_str : 1;/* bit 123 */
} __packed;

extern struct css_general_char css_general_characteristics;
Expand Down
171 changes: 56 additions & 115 deletions drivers/s390/block/dasd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1222,80 +1222,37 @@ static void dasd_hosts_init(struct dentry *base_dentry,
device->hosts_dentry = pde;
}

/*
* Allocate memory for a channel program with 'cplength' channel
* command words and 'datasize' additional space. There are two
* variantes: 1) dasd_kmalloc_request uses kmalloc to get the needed
* memory and 2) dasd_smalloc_request uses the static ccw memory
* that gets allocated for each device.
*/
struct dasd_ccw_req *dasd_kmalloc_request(int magic, int cplength,
int datasize,
struct dasd_device *device)
{
struct dasd_ccw_req *cqr;

/* Sanity checks */
BUG_ON(datasize > PAGE_SIZE ||
(cplength*sizeof(struct ccw1)) > PAGE_SIZE);

cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC);
if (cqr == NULL)
return ERR_PTR(-ENOMEM);
cqr->cpaddr = NULL;
if (cplength > 0) {
cqr->cpaddr = kcalloc(cplength, sizeof(struct ccw1),
GFP_ATOMIC | GFP_DMA);
if (cqr->cpaddr == NULL) {
kfree(cqr);
return ERR_PTR(-ENOMEM);
}
}
cqr->data = NULL;
if (datasize > 0) {
cqr->data = kzalloc(datasize, GFP_ATOMIC | GFP_DMA);
if (cqr->data == NULL) {
kfree(cqr->cpaddr);
kfree(cqr);
return ERR_PTR(-ENOMEM);
}
}
cqr->magic = magic;
set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
dasd_get_device(device);
return cqr;
}
EXPORT_SYMBOL(dasd_kmalloc_request);

struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
int datasize,
struct dasd_device *device)
struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength, int datasize,
struct dasd_device *device,
struct dasd_ccw_req *cqr)
{
unsigned long flags;
struct dasd_ccw_req *cqr;
char *data;
int size;
char *data, *chunk;
int size = 0;

size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
if (cplength > 0)
size += cplength * sizeof(struct ccw1);
if (datasize > 0)
size += datasize;
if (!cqr)
size += (sizeof(*cqr) + 7L) & -8L;

spin_lock_irqsave(&device->mem_lock, flags);
cqr = (struct dasd_ccw_req *)
dasd_alloc_chunk(&device->ccw_chunks, size);
data = chunk = dasd_alloc_chunk(&device->ccw_chunks, size);
spin_unlock_irqrestore(&device->mem_lock, flags);
if (cqr == NULL)
if (!chunk)
return ERR_PTR(-ENOMEM);
memset(cqr, 0, sizeof(struct dasd_ccw_req));
data = (char *) cqr + ((sizeof(struct dasd_ccw_req) + 7L) & -8L);
cqr->cpaddr = NULL;
if (!cqr) {
cqr = (void *) data;
data += (sizeof(*cqr) + 7L) & -8L;
}
memset(cqr, 0, sizeof(*cqr));
cqr->mem_chunk = chunk;
if (cplength > 0) {
cqr->cpaddr = (struct ccw1 *) data;
data += cplength*sizeof(struct ccw1);
memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
cqr->cpaddr = data;
data += cplength * sizeof(struct ccw1);
memset(cqr->cpaddr, 0, cplength * sizeof(struct ccw1));
}
cqr->data = NULL;
if (datasize > 0) {
cqr->data = data;
memset(cqr->data, 0, datasize);
Expand All @@ -1307,33 +1264,12 @@ struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
}
EXPORT_SYMBOL(dasd_smalloc_request);

/*
* Free memory of a channel program. This function needs to free all the
* idal lists that might have been created by dasd_set_cda and the
* struct dasd_ccw_req itself.
*/
void dasd_kfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
{
struct ccw1 *ccw;

/* Clear any idals used for the request. */
ccw = cqr->cpaddr;
do {
clear_normalized_cda(ccw);
} while (ccw++->flags & (CCW_FLAG_CC | CCW_FLAG_DC));
kfree(cqr->cpaddr);
kfree(cqr->data);
kfree(cqr);
dasd_put_device(device);
}
EXPORT_SYMBOL(dasd_kfree_request);

void dasd_sfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
{
unsigned long flags;

spin_lock_irqsave(&device->mem_lock, flags);
dasd_free_chunk(&device->ccw_chunks, cqr);
dasd_free_chunk(&device->ccw_chunks, cqr->mem_chunk);
spin_unlock_irqrestore(&device->mem_lock, flags);
dasd_put_device(device);
}
Expand Down Expand Up @@ -1885,6 +1821,33 @@ static void __dasd_device_process_ccw_queue(struct dasd_device *device,
}
}

static void __dasd_process_cqr(struct dasd_device *device,
struct dasd_ccw_req *cqr)
{
char errorstring[ERRORLENGTH];

switch (cqr->status) {
case DASD_CQR_SUCCESS:
cqr->status = DASD_CQR_DONE;
break;
case DASD_CQR_ERROR:
cqr->status = DASD_CQR_NEED_ERP;
break;
case DASD_CQR_CLEARED:
cqr->status = DASD_CQR_TERMINATED;
break;
default:
/* internal error 12 - wrong cqr status*/
snprintf(errorstring, ERRORLENGTH, "12 %p %x02", cqr, cqr->status);
dev_err(&device->cdev->dev,
"An error occurred in the DASD device driver, "
"reason=%s\n", errorstring);
BUG();
}
if (cqr->callback)
cqr->callback(cqr, cqr->callback_data);
}

/*
* the cqrs from the final queue are returned to the upper layer
* by setting a dasd_block state and calling the callback function
Expand All @@ -1895,40 +1858,18 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
struct list_head *l, *n;
struct dasd_ccw_req *cqr;
struct dasd_block *block;
void (*callback)(struct dasd_ccw_req *, void *data);
void *callback_data;
char errorstring[ERRORLENGTH];

list_for_each_safe(l, n, final_queue) {
cqr = list_entry(l, struct dasd_ccw_req, devlist);
list_del_init(&cqr->devlist);
block = cqr->block;
callback = cqr->callback;
callback_data = cqr->callback_data;
if (block)
if (!block) {
__dasd_process_cqr(device, cqr);
} else {
spin_lock_bh(&block->queue_lock);
switch (cqr->status) {
case DASD_CQR_SUCCESS:
cqr->status = DASD_CQR_DONE;
break;
case DASD_CQR_ERROR:
cqr->status = DASD_CQR_NEED_ERP;
break;
case DASD_CQR_CLEARED:
cqr->status = DASD_CQR_TERMINATED;
break;
default:
/* internal error 12 - wrong cqr status*/
snprintf(errorstring, ERRORLENGTH, "12 %p %x02", cqr, cqr->status);
dev_err(&device->cdev->dev,
"An error occurred in the DASD device driver, "
"reason=%s\n", errorstring);
BUG();
}
if (cqr->callback != NULL)
(callback)(cqr, callback_data);
if (block)
__dasd_process_cqr(device, cqr);
spin_unlock_bh(&block->queue_lock);
}
}
}

Expand Down Expand Up @@ -3041,7 +2982,6 @@ static blk_status_t do_dasd_request(struct blk_mq_hw_ctx *hctx,
cqr->callback_data = req;
cqr->status = DASD_CQR_FILLED;
cqr->dq = dq;
*((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req)) = cqr;

blk_mq_start_request(req);
spin_lock(&block->queue_lock);
Expand Down Expand Up @@ -3072,7 +3012,7 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved)
unsigned long flags;
int rc = 0;

cqr = *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req));
cqr = blk_mq_rq_to_pdu(req);
if (!cqr)
return BLK_EH_DONE;

Expand Down Expand Up @@ -3174,7 +3114,7 @@ static int dasd_alloc_queue(struct dasd_block *block)
int rc;

block->tag_set.ops = &dasd_mq_ops;
block->tag_set.cmd_size = sizeof(struct dasd_ccw_req *);
block->tag_set.cmd_size = sizeof(struct dasd_ccw_req);
block->tag_set.nr_hw_queues = DASD_NR_HW_QUEUES;
block->tag_set.queue_depth = DASD_MAX_LCU_DEV * DASD_REQ_PER_DEV;
block->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
Expand Down Expand Up @@ -4038,7 +3978,8 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
struct ccw1 *ccw;
unsigned long *idaw;

cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device);
cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device,
NULL);

if (IS_ERR(cqr)) {
/* internal error 13 - Allocating the RDC request failed*/
Expand Down
6 changes: 3 additions & 3 deletions drivers/s390/block/dasd_alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,9 @@ static int read_unit_address_configuration(struct dasd_device *device,
int rc;
unsigned long flags;

cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data)),
device);
device, NULL);
if (IS_ERR(cqr))
return PTR_ERR(cqr);
cqr->startdev = device;
Expand Down Expand Up @@ -457,7 +457,7 @@ static int read_unit_address_configuration(struct dasd_device *device,
lcu->flags |= NEED_UAC_UPDATE;
spin_unlock_irqrestore(&lcu->lock, flags);
}
dasd_kfree_request(cqr, cqr->memdev);
dasd_sfree_request(cqr, cqr->memdev);
return rc;
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/s390/block/dasd_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,8 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
/* Build the request */
datasize = sizeof(struct dasd_diag_req) +
count*sizeof(struct dasd_diag_bio);
cqr = dasd_smalloc_request(DASD_DIAG_MAGIC, 0, datasize, memdev);
cqr = dasd_smalloc_request(DASD_DIAG_MAGIC, 0, datasize, memdev,
blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;

Expand Down
Loading

0 comments on commit c0d1a7e

Please sign in to comment.