Skip to content

Commit 104ea55

Browse files
frank.blaschka@de.ibm.comdavem330
authored andcommitted
qdio: support asynchronous delivery of storage blocks
This patch introduces support for asynchronous delivery of storage blocks for Hipersockets. Upper layers may exploit this functionality to reuse SBALs for which the delivery status is still pending. Signed-off-by: Einar Lueck <[email protected]> Signed-off-by: Jan Glauber <[email protected]> Signed-off-by: Frank Blaschka <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3881ac4 commit 104ea55

File tree

7 files changed

+424
-80
lines changed

7 files changed

+424
-80
lines changed

arch/s390/include/asm/qdio.h

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,40 @@ struct slibe {
122122
u64 parms;
123123
};
124124

125+
/**
126+
* struct qaob - queue asynchronous operation block
127+
* @res0: reserved parameters
128+
* @res1: reserved parameter
129+
* @res2: reserved parameter
130+
* @res3: reserved parameter
131+
* @aorc: asynchronous operation return code
132+
* @flags: internal flags
133+
* @cbtbs: control block type
134+
* @sb_count: number of storage blocks
135+
* @sba: storage block element addresses
136+
* @dcount: size of storage block elements
137+
* @user0: user defineable value
138+
* @res4: reserved paramater
139+
* @user1: user defineable value
140+
* @user2: user defineable value
141+
*/
142+
struct qaob {
143+
u64 res0[6];
144+
u8 res1;
145+
u8 res2;
146+
u8 res3;
147+
u8 aorc;
148+
u8 flags;
149+
u16 cbtbs;
150+
u8 sb_count;
151+
u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER];
152+
u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER];
153+
u64 user0;
154+
u64 res4[2];
155+
u64 user1;
156+
u64 user2;
157+
} __attribute__ ((packed, aligned(256)));
158+
125159
/**
126160
* struct slib - storage list information block (SLIB)
127161
* @nsliba: next SLIB address (if any)
@@ -225,6 +259,31 @@ struct slsb {
225259
#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010
226260
#define CHSC_AC2_DATA_DIV_ENABLED 0x0002
227261

262+
/**
263+
* struct qdio_outbuf_state - SBAL related asynchronous operation information
264+
* (for communication with upper layer programs)
265+
* (only required for use with completion queues)
266+
* @flags: flags indicating state of buffer
267+
* @aob: pointer to QAOB used for the particular SBAL
268+
* @user: pointer to upper layer program's state information related to SBAL
269+
* (stored in user1 data of QAOB)
270+
*/
271+
struct qdio_outbuf_state {
272+
u8 flags;
273+
struct qaob *aob;
274+
void *user;
275+
};
276+
277+
#define QDIO_OUTBUF_STATE_FLAG_NONE 0x00
278+
#define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01
279+
280+
#define CHSC_AC1_INITIATE_INPUTQ 0x80
281+
282+
#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010
283+
#define CHSC_AC2_DATA_DIV_ENABLED 0x0002
284+
285+
#define CHSC_AC3_FORMAT2_CQ_AVAILABLE 0x8000
286+
228287
struct qdio_ssqd_desc {
229288
u8 flags;
230289
u8:8;
@@ -243,8 +302,7 @@ struct qdio_ssqd_desc {
243302
u64 sch_token;
244303
u8 mro;
245304
u8 mri;
246-
u8:8;
247-
u8 sbalic;
305+
u16 qdioac3;
248306
u16:16;
249307
u8:8;
250308
u8 mmwc;
@@ -280,9 +338,11 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
280338
* @no_output_qs: number of output queues
281339
* @input_handler: handler to be called for input queues
282340
* @output_handler: handler to be called for output queues
341+
* @queue_start_poll: polling handlers (one per input queue or NULL)
283342
* @int_parm: interruption parameter
284343
* @input_sbal_addr_array: address of no_input_qs * 128 pointers
285344
* @output_sbal_addr_array: address of no_output_qs * 128 pointers
345+
* @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL)
286346
*/
287347
struct qdio_initialize {
288348
struct ccw_device *cdev;
@@ -297,11 +357,12 @@ struct qdio_initialize {
297357
unsigned int no_output_qs;
298358
qdio_handler_t *input_handler;
299359
qdio_handler_t *output_handler;
300-
void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
360+
void (**queue_start_poll) (struct ccw_device *, int, unsigned long);
301361
int scan_threshold;
302362
unsigned long int_parm;
303363
void **input_sbal_addr_array;
304364
void **output_sbal_addr_array;
365+
struct qdio_outbuf_state *output_sbal_state_array;
305366
};
306367

307368
#define QDIO_STATE_INACTIVE 0x00000002 /* after qdio_cleanup */
@@ -316,6 +377,7 @@ struct qdio_initialize {
316377
extern int qdio_allocate(struct qdio_initialize *);
317378
extern int qdio_establish(struct qdio_initialize *);
318379
extern int qdio_activate(struct ccw_device *);
380+
extern void qdio_release_aob(struct qaob *);
319381
extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,
320382
unsigned int);
321383
extern int qdio_start_irq(struct ccw_device *, int);

drivers/s390/cio/qdio.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum qdio_irq_states {
4444
#define SLSB_STATE_NOT_INIT 0x0
4545
#define SLSB_STATE_EMPTY 0x1
4646
#define SLSB_STATE_PRIMED 0x2
47+
#define SLSB_STATE_PENDING 0x3
4748
#define SLSB_STATE_HALTED 0xe
4849
#define SLSB_STATE_ERROR 0xf
4950
#define SLSB_TYPE_INPUT 0x0
@@ -67,6 +68,8 @@ enum qdio_irq_states {
6768
(SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_NOT_INIT) /* 0xa0 */
6869
#define SLSB_P_OUTPUT_EMPTY \
6970
(SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_EMPTY) /* 0xa1 */
71+
#define SLSB_P_OUTPUT_PENDING \
72+
(SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_PENDING) /* 0xa3 */
7073
#define SLSB_CU_OUTPUT_PRIMED \
7174
(SLSB_OWNER_CU | SLSB_TYPE_OUTPUT | SLSB_STATE_PRIMED) /* 0x62 */
7275
#define SLSB_P_OUTPUT_HALTED \
@@ -97,6 +100,7 @@ enum qdio_irq_states {
97100
#define QDIO_SIGA_WRITE 0x00
98101
#define QDIO_SIGA_READ 0x01
99102
#define QDIO_SIGA_SYNC 0x02
103+
#define QDIO_SIGA_WRITEQ 0x04
100104
#define QDIO_SIGA_QEBSM_FLAG 0x80
101105

102106
#ifdef CONFIG_64BIT
@@ -253,6 +257,12 @@ struct qdio_input_q {
253257
struct qdio_output_q {
254258
/* PCIs are enabled for the queue */
255259
int pci_out_enabled;
260+
/* cq: use asynchronous output buffers */
261+
int use_cq;
262+
/* cq: aobs used for particual SBAL */
263+
struct qaob **aobs;
264+
/* cq: sbal state related to asynchronous operation */
265+
struct qdio_outbuf_state *sbal_state;
256266
/* timer to check for more outbound work */
257267
struct timer_list timer;
258268
/* used SBALs before tasklet schedule */
@@ -432,9 +442,20 @@ struct indicator_t {
432442

433443
extern struct indicator_t *q_indicators;
434444

435-
static inline int shared_ind(u32 *dsci)
445+
static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq)
436446
{
437-
return dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
447+
return irq->nr_input_qs > 1;
448+
}
449+
450+
static inline int references_shared_dsci(struct qdio_irq *irq)
451+
{
452+
return irq->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
453+
}
454+
455+
static inline int shared_ind(struct qdio_q *q)
456+
{
457+
struct qdio_irq *i = q->irq_ptr;
458+
return references_shared_dsci(i) || has_multiple_inq_on_dsci(i);
438459
}
439460

440461
/* prototypes for thin interrupt */
@@ -449,6 +470,7 @@ void tiqdio_free_memory(void);
449470
int tiqdio_register_thinints(void);
450471
void tiqdio_unregister_thinints(void);
451472

473+
452474
/* prototypes for setup */
453475
void qdio_inbound_processing(unsigned long data);
454476
void qdio_outbound_processing(unsigned long data);
@@ -469,6 +491,9 @@ int qdio_setup_create_sysfs(struct ccw_device *cdev);
469491
void qdio_setup_destroy_sysfs(struct ccw_device *cdev);
470492
int qdio_setup_init(void);
471493
void qdio_setup_exit(void);
494+
int qdio_enable_async_operation(struct qdio_output_q *q);
495+
void qdio_disable_async_operation(struct qdio_output_q *q);
496+
struct qaob *qdio_allocate_aob(void);
472497

473498
int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
474499
unsigned char *state);

drivers/s390/cio/qdio_debug.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ static int qstat_show(struct seq_file *m, void *v)
7676
case SLSB_P_OUTPUT_NOT_INIT:
7777
seq_printf(m, "N");
7878
break;
79+
case SLSB_P_OUTPUT_PENDING:
80+
seq_printf(m, "P");
81+
break;
7982
case SLSB_P_INPUT_PRIMED:
8083
case SLSB_CU_OUTPUT_PRIMED:
8184
seq_printf(m, "+");

0 commit comments

Comments
 (0)