[S390] qdio: new qdio driver.

List of major changes:
- split qdio driver into several files
- seperation of thin interrupt code
- improved handling for multiple thin interrupt devices
- inbound and outbound processing now always runs in tasklet context
- significant less tasklet schedules per interrupt needed
- merged qebsm with non-qebsm handling
- cleanup qdio interface and added kerneldoc
- coding style

Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Utz Bacher <utz.bacher@de.ibm.com>
Reviewed-by: Ursula Braun <braunu@de.ibm.com>
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
This commit is contained in:
Jan Glauber
2008-07-17 17:16:48 +02:00
committed by Heiko Carstens
parent dae39843f4
commit 779e6e1c72
20 changed files with 3885 additions and 4954 deletions

View File

@@ -2073,7 +2073,7 @@ static void qeth_create_qib_param_field_blkt(struct qeth_card *card,
static int qeth_qdio_activate(struct qeth_card *card)
{
QETH_DBF_TEXT(SETUP, 3, "qdioact");
return qdio_activate(CARD_DDEV(card), 0);
return qdio_activate(CARD_DDEV(card));
}
static int qeth_dm_act(struct qeth_card *card)
@@ -2349,16 +2349,11 @@ int qeth_init_qdio_queues(struct qeth_card *card)
card->qdio.in_q->next_buf_to_init =
card->qdio.in_buf_pool.buf_count - 1;
rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
card->qdio.in_buf_pool.buf_count - 1, NULL);
card->qdio.in_buf_pool.buf_count - 1);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
return rc;
}
rc = qdio_synchronize(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
return rc;
}
/* outbound queue */
for (i = 0; i < card->qdio.no_out_queues; ++i) {
memset(card->qdio.out_qs[i]->qdio_bufs, 0,
@@ -2559,9 +2554,9 @@ int qeth_query_setadapterparms(struct qeth_card *card)
EXPORT_SYMBOL_GPL(qeth_query_setadapterparms);
int qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
unsigned int siga_error, const char *dbftext)
const char *dbftext)
{
if (qdio_error || siga_error) {
if (qdio_error) {
QETH_DBF_TEXT(TRACE, 2, dbftext);
QETH_DBF_TEXT(QERR, 2, dbftext);
QETH_DBF_TEXT_(QERR, 2, " F15=%02X",
@@ -2569,7 +2564,6 @@ int qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
QETH_DBF_TEXT_(QERR, 2, " F14=%02X",
buf->element[14].flags & 0xff);
QETH_DBF_TEXT_(QERR, 2, " qerr=%X", qdio_error);
QETH_DBF_TEXT_(QERR, 2, " serr=%X", siga_error);
return 1;
}
return 0;
@@ -2622,9 +2616,8 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
card->perf_stats.inbound_do_qdio_start_time =
qeth_get_micros();
}
rc = do_QDIO(CARD_DDEV(card),
QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
0, queue->next_buf_to_init, count, NULL);
rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0,
queue->next_buf_to_init, count);
if (card->options.performance_stats)
card->perf_stats.inbound_do_qdio_time +=
qeth_get_micros() -
@@ -2643,14 +2636,13 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index)
EXPORT_SYMBOL_GPL(qeth_queue_input_buffer);
static int qeth_handle_send_error(struct qeth_card *card,
struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err,
unsigned int siga_err)
struct qeth_qdio_out_buffer *buffer, unsigned int qdio_err)
{
int sbalf15 = buffer->buffer->element[15].flags & 0xff;
int cc = siga_err & 3;
int cc = qdio_err & 3;
QETH_DBF_TEXT(TRACE, 6, "hdsnderr");
qeth_check_qdio_errors(buffer->buffer, qdio_err, siga_err, "qouterr");
qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr");
switch (cc) {
case 0:
if (qdio_err) {
@@ -2662,7 +2654,7 @@ static int qeth_handle_send_error(struct qeth_card *card,
}
return QETH_SEND_ERROR_NONE;
case 2:
if (siga_err & QDIO_SIGA_ERROR_B_BIT_SET) {
if (qdio_err & QDIO_ERROR_SIGA_BUSY) {
QETH_DBF_TEXT(TRACE, 1, "SIGAcc2B");
QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
return QETH_SEND_ERROR_KICK_IT;
@@ -2758,8 +2750,8 @@ static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
return 0;
}
static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
int index, int count)
static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
int count)
{
struct qeth_qdio_out_buffer *buf;
int rc;
@@ -2807,12 +2799,10 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
qeth_get_micros();
}
qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
if (under_int)
qdio_flags |= QDIO_FLAG_UNDER_INTERRUPT;
if (atomic_read(&queue->set_pci_flags_count))
qdio_flags |= QDIO_FLAG_PCI_OUT;
rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
queue->queue_no, index, count, NULL);
queue->queue_no, index, count);
if (queue->card->options.performance_stats)
queue->card->perf_stats.outbound_do_qdio_time +=
qeth_get_micros() -
@@ -2866,16 +2856,15 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
queue->card->perf_stats.bufs_sent_pack +=
flush_cnt;
if (flush_cnt)
qeth_flush_buffers(queue, 1, index, flush_cnt);
qeth_flush_buffers(queue, index, flush_cnt);
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
}
}
}
void qeth_qdio_output_handler(struct ccw_device *ccwdev, unsigned int status,
unsigned int qdio_error, unsigned int siga_error,
unsigned int __queue, int first_element, int count,
unsigned long card_ptr)
void qeth_qdio_output_handler(struct ccw_device *ccwdev,
unsigned int qdio_error, int __queue, int first_element,
int count, unsigned long card_ptr)
{
struct qeth_card *card = (struct qeth_card *) card_ptr;
struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
@@ -2883,15 +2872,12 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, unsigned int status,
int i;
QETH_DBF_TEXT(TRACE, 6, "qdouhdl");
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
QETH_DBF_TEXT(TRACE, 2, "achkcond");
QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(TRACE, 2, "%08x", status);
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
return;
}
if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
QETH_DBF_TEXT(TRACE, 2, "achkcond");
QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card));
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
return;
}
if (card->options.performance_stats) {
card->perf_stats.outbound_handler_cnt++;
@@ -2901,8 +2887,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, unsigned int status,
for (i = first_element; i < (first_element + count); ++i) {
buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
/*we only handle the KICK_IT error by doing a recovery */
if (qeth_handle_send_error(card, buffer,
qdio_error, siga_error)
if (qeth_handle_send_error(card, buffer, qdio_error)
== QETH_SEND_ERROR_KICK_IT){
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
@@ -3164,11 +3149,11 @@ int qeth_do_send_packet_fast(struct qeth_card *card,
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
if (ctx == NULL) {
qeth_fill_buffer(queue, buffer, skb);
qeth_flush_buffers(queue, 0, index, 1);
qeth_flush_buffers(queue, index, 1);
} else {
flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
WARN_ON(buffers_needed != flush_cnt);
qeth_flush_buffers(queue, 0, index, flush_cnt);
qeth_flush_buffers(queue, index, flush_cnt);
}
return 0;
out:
@@ -3221,8 +3206,8 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
* again */
if (atomic_read(&buffer->state) !=
QETH_QDIO_BUF_EMPTY){
qeth_flush_buffers(queue, 0,
start_index, flush_count);
qeth_flush_buffers(queue, start_index,
flush_count);
atomic_set(&queue->state,
QETH_OUT_Q_UNLOCKED);
return -EBUSY;
@@ -3253,7 +3238,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
flush_count += tmp;
out:
if (flush_count)
qeth_flush_buffers(queue, 0, start_index, flush_count);
qeth_flush_buffers(queue, start_index, flush_count);
else if (!atomic_read(&queue->set_pci_flags_count))
atomic_xchg(&queue->state, QETH_OUT_Q_LOCKED_FLUSH);
/*
@@ -3274,7 +3259,7 @@ out:
if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
flush_count += qeth_flush_buffers_on_no_pci(queue);
if (flush_count)
qeth_flush_buffers(queue, 0, start_index, flush_count);
qeth_flush_buffers(queue, start_index, flush_count);
}
/* at this point the queue is UNLOCKED again */
if (queue->card->options.performance_stats && do_pack)
@@ -3686,10 +3671,6 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.q_format = qeth_get_qdio_q_format(card);
init_data.qib_param_field_format = 0;
init_data.qib_param_field = qib_param_field;
init_data.min_input_threshold = QETH_MIN_INPUT_THRESHOLD;
init_data.max_input_threshold = QETH_MAX_INPUT_THRESHOLD;
init_data.min_output_threshold = QETH_MIN_OUTPUT_THRESHOLD;
init_data.max_output_threshold = QETH_MAX_OUTPUT_THRESHOLD;
init_data.no_input_qs = 1;
init_data.no_output_qs = card->qdio.no_out_queues;
init_data.input_handler = card->discipline.input_handler;
@@ -3751,8 +3732,9 @@ static int qeth_core_driver_group(const char *buf, struct device *root_dev,
int qeth_core_hardsetup_card(struct qeth_card *card)
{
struct qdio_ssqd_desc *qdio_ssqd;
int retries = 3;
int mpno;
int mpno = 0;
int rc;
QETH_DBF_TEXT(SETUP, 2, "hrdsetup");
@@ -3784,7 +3766,10 @@ retry:
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
return rc;
}
mpno = qdio_get_ssqd_pct(CARD_DDEV(card));
qdio_ssqd = qdio_get_ssqd_desc(CARD_DDEV(card));
if (qdio_ssqd)
mpno = qdio_ssqd->pcnt;
if (mpno)
mpno = min(mpno - 1, QETH_MAX_PORTNO);
if (card->info.portno > mpno) {