[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:
committed by
Heiko Carstens
parent
dae39843f4
commit
779e6e1c72
@@ -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) {
|
||||
|
Reference in New Issue
Block a user