qeth: HiperSockets Network Traffic Analyzer
New feature to trace HiperSockets network traffic for debugging purposes. Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
ab8932f3e8
commit
76b11f8e27
@@ -269,6 +269,7 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
|
||||
card->qdio.init_pool.buf_count = bufcnt;
|
||||
return qeth_alloc_buffer_pool(card);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool);
|
||||
|
||||
static int qeth_issue_next_read(struct qeth_card *card)
|
||||
{
|
||||
@@ -350,8 +351,10 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
|
||||
if (IS_IPA(iob->data)) {
|
||||
cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
|
||||
if (IS_IPA_REPLY(cmd)) {
|
||||
if (cmd->hdr.command < IPA_CMD_SETCCID ||
|
||||
cmd->hdr.command > IPA_CMD_MODCCID)
|
||||
if (cmd->hdr.command != IPA_CMD_SETCCID &&
|
||||
cmd->hdr.command != IPA_CMD_DELCCID &&
|
||||
cmd->hdr.command != IPA_CMD_MODCCID &&
|
||||
cmd->hdr.command != IPA_CMD_SET_DIAG_ASS)
|
||||
qeth_issue_ipa_msg(cmd,
|
||||
cmd->hdr.return_code, card);
|
||||
return cmd;
|
||||
@@ -1100,11 +1103,6 @@ static int qeth_setup_card(struct qeth_card *card)
|
||||
card->thread_running_mask = 0;
|
||||
INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
|
||||
INIT_LIST_HEAD(&card->ip_list);
|
||||
card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
|
||||
if (!card->ip_tbd_list) {
|
||||
QETH_DBF_TEXT(SETUP, 0, "iptbdnom");
|
||||
return -ENOMEM;
|
||||
}
|
||||
INIT_LIST_HEAD(card->ip_tbd_list);
|
||||
INIT_LIST_HEAD(&card->cmd_waiter_list);
|
||||
init_waitqueue_head(&card->wait_q);
|
||||
@@ -1138,21 +1136,30 @@ static struct qeth_card *qeth_alloc_card(void)
|
||||
QETH_DBF_TEXT(SETUP, 2, "alloccrd");
|
||||
card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL);
|
||||
if (!card)
|
||||
return NULL;
|
||||
goto out;
|
||||
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
|
||||
if (qeth_setup_channel(&card->read)) {
|
||||
kfree(card);
|
||||
return NULL;
|
||||
}
|
||||
if (qeth_setup_channel(&card->write)) {
|
||||
qeth_clean_channel(&card->read);
|
||||
kfree(card);
|
||||
return NULL;
|
||||
card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
|
||||
if (!card->ip_tbd_list) {
|
||||
QETH_DBF_TEXT(SETUP, 0, "iptbdnom");
|
||||
goto out_card;
|
||||
}
|
||||
if (qeth_setup_channel(&card->read))
|
||||
goto out_ip;
|
||||
if (qeth_setup_channel(&card->write))
|
||||
goto out_channel;
|
||||
card->options.layer2 = -1;
|
||||
card->qeth_service_level.seq_print = qeth_core_sl_print;
|
||||
register_service_level(&card->qeth_service_level);
|
||||
return card;
|
||||
|
||||
out_channel:
|
||||
qeth_clean_channel(&card->read);
|
||||
out_ip:
|
||||
kfree(card->ip_tbd_list);
|
||||
out_card:
|
||||
kfree(card);
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int qeth_determine_card_type(struct qeth_card *card)
|
||||
@@ -2573,8 +2580,8 @@ 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,
|
||||
const char *dbftext)
|
||||
int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf,
|
||||
unsigned int qdio_error, const char *dbftext)
|
||||
{
|
||||
if (qdio_error) {
|
||||
QETH_DBF_TEXT(TRACE, 2, dbftext);
|
||||
@@ -2584,7 +2591,11 @@ 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);
|
||||
return 1;
|
||||
if ((buf->element[15].flags & 0xff) == 0x12) {
|
||||
card->stats.rx_dropped++;
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2667,7 +2678,7 @@ static int qeth_handle_send_error(struct qeth_card *card,
|
||||
qdio_err = 1;
|
||||
}
|
||||
}
|
||||
qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr");
|
||||
qeth_check_qdio_errors(card, buffer->buffer, qdio_err, "qouterr");
|
||||
|
||||
if (!qdio_err)
|
||||
return QETH_SEND_ERROR_NONE;
|
||||
@@ -3509,6 +3520,7 @@ void qeth_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
|
||||
QETH_DBF_TEXT(TRACE, 4, "txtimeo");
|
||||
card = dev->ml_priv;
|
||||
card->stats.tx_errors++;
|
||||
qeth_schedule_recovery(card);
|
||||
@@ -3847,9 +3859,7 @@ 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 *ssqd;
|
||||
int retries = 0;
|
||||
int mpno = 0;
|
||||
int rc;
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "hrdsetup");
|
||||
@@ -3882,31 +3892,6 @@ retriable:
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
rc = qeth_get_unitaddr(card);
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ssqd = kmalloc(sizeof(struct qdio_ssqd_desc), GFP_KERNEL);
|
||||
if (!ssqd) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
rc = qdio_get_ssqd_desc(CARD_DDEV(card), ssqd);
|
||||
if (rc == 0)
|
||||
mpno = ssqd->pcnt;
|
||||
kfree(ssqd);
|
||||
|
||||
if (mpno)
|
||||
mpno = min(mpno - 1, QETH_MAX_PORTNO);
|
||||
if (card->info.portno > mpno) {
|
||||
QETH_DBF_MESSAGE(2, "Device %s does not offer port number %d"
|
||||
"\n.", CARD_BUS_ID(card), card->info.portno);
|
||||
rc = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
qeth_init_tokens(card);
|
||||
qeth_init_func_level(card);
|
||||
rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
|
||||
@@ -3990,7 +3975,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
|
||||
struct qdio_buffer_element *element = *__element;
|
||||
int offset = *__offset;
|
||||
struct sk_buff *skb = NULL;
|
||||
int skb_len;
|
||||
int skb_len = 0;
|
||||
void *data_ptr;
|
||||
int data_len;
|
||||
int headroom = 0;
|
||||
@@ -4009,20 +3994,24 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
|
||||
*hdr = element->addr + offset;
|
||||
|
||||
offset += sizeof(struct qeth_hdr);
|
||||
if (card->options.layer2) {
|
||||
if (card->info.type == QETH_CARD_TYPE_OSN) {
|
||||
skb_len = (*hdr)->hdr.osn.pdu_length;
|
||||
headroom = sizeof(struct qeth_hdr);
|
||||
} else {
|
||||
skb_len = (*hdr)->hdr.l2.pkt_length;
|
||||
}
|
||||
} else {
|
||||
switch ((*hdr)->hdr.l2.id) {
|
||||
case QETH_HEADER_TYPE_LAYER2:
|
||||
skb_len = (*hdr)->hdr.l2.pkt_length;
|
||||
break;
|
||||
case QETH_HEADER_TYPE_LAYER3:
|
||||
skb_len = (*hdr)->hdr.l3.length;
|
||||
if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
|
||||
(card->info.link_type == QETH_LINK_TYPE_HSTR))
|
||||
headroom = TR_HLEN;
|
||||
else
|
||||
headroom = ETH_HLEN;
|
||||
break;
|
||||
case QETH_HEADER_TYPE_OSN:
|
||||
skb_len = (*hdr)->hdr.osn.pdu_length;
|
||||
headroom = sizeof(struct qeth_hdr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!skb_len)
|
||||
@@ -4177,6 +4166,33 @@ void qeth_core_free_discipline(struct qeth_card *card)
|
||||
card->discipline.ccwgdriver = NULL;
|
||||
}
|
||||
|
||||
static void qeth_determine_capabilities(struct qeth_card *card)
|
||||
{
|
||||
int rc;
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "detcapab");
|
||||
rc = ccw_device_set_online(CARD_DDEV(card));
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = qeth_get_unitaddr(card);
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
|
||||
goto out_offline;
|
||||
}
|
||||
|
||||
rc = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
|
||||
if (rc)
|
||||
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
|
||||
|
||||
out_offline:
|
||||
ccw_device_set_offline(CARD_DDEV(card));
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
@@ -4242,6 +4258,8 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
||||
write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
|
||||
list_add_tail(&card->list, &qeth_core_card_list.list);
|
||||
write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
|
||||
|
||||
qeth_determine_capabilities(card);
|
||||
return 0;
|
||||
|
||||
err_card:
|
||||
|
||||
Reference in New Issue
Block a user