qeth: add support for af_iucv HiperSockets transport

This patch extends the HiperSockets device driver to send and receive
af_iucv traffic over HiperSockets transport.
TX: Driver uses new asynchronous delivery of storage blocks to pass
    flow control/congestion information from the HiperSockets microcode
    to the af_iucv socket.
RX: Memory for incoming traffic is preallocated and passed to
    HiperSockets layer. If receiver is not capable to clean its buffers
    shared with HiperSockets and pass new memory to the HiperSockets
    layer this will cause flow control/congestion events on the
    sender.

Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: Einar Lueck <elelueck@de.ibm.com>
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Cette révision appartient à :
Frank Blaschka
2011-08-08 01:33:59 +00:00
révisé par David S. Miller
Parent 0da9581ddb
révision b333293058
6 fichiers modifiés avec 391 ajouts et 61 suppressions

Voir le fichier

@@ -9,7 +9,7 @@
*/
#include <linux/slab.h>
#include <asm/ebcdic.h>
#include "qeth_l3.h"
#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
@@ -308,6 +308,8 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
if (card->options.cq == QETH_CQ_ENABLED)
return -EPERM;
mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
@@ -347,6 +349,111 @@ out:
static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
qeth_l3_dev_sniffer_store);
static ssize_t qeth_l3_dev_hsuid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev_get_drvdata(dev);
char tmp_hsuid[9];
if (!card)
return -EINVAL;
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
if (card->state == CARD_STATE_DOWN)
return -EPERM;
memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid));
EBCASC(tmp_hsuid, 8);
return sprintf(buf, "%s\n", tmp_hsuid);
}
static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
struct qeth_ipaddr *addr;
char *tmp;
int i;
if (!card)
return -EINVAL;
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
if (card->state != CARD_STATE_DOWN &&
card->state != CARD_STATE_RECOVER)
return -EPERM;
if (card->options.sniffer)
return -EPERM;
if (card->options.cq == QETH_CQ_NOTAVAILABLE)
return -EPERM;
tmp = strsep((char **)&buf, "\n");
if (strlen(tmp) > 8)
return -EINVAL;
if (card->options.hsuid[0]) {
/* delete old ip address */
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
if (addr != NULL) {
addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
addr->u.a6.addr.s6_addr32[1] = 0x00000000;
for (i = 8; i < 16; i++)
addr->u.a6.addr.s6_addr[i] =
card->options.hsuid[i - 8];
addr->u.a6.pfxlen = 0;
addr->type = QETH_IP_TYPE_NORMAL;
} else
return -ENOMEM;
if (!qeth_l3_delete_ip(card, addr))
kfree(addr);
qeth_l3_set_ip_addr_list(card);
}
if (strlen(tmp) == 0) {
/* delete ip address only */
card->options.hsuid[0] = '\0';
if (card->dev)
memcpy(card->dev->perm_addr, card->options.hsuid, 9);
qeth_configure_cq(card, QETH_CQ_DISABLED);
return count;
}
if (qeth_configure_cq(card, QETH_CQ_ENABLED))
return -EPERM;
for (i = 0; i < 8; i++)
card->options.hsuid[i] = ' ';
card->options.hsuid[8] = '\0';
strncpy(card->options.hsuid, tmp, strlen(tmp));
ASCEBC(card->options.hsuid, 8);
if (card->dev)
memcpy(card->dev->perm_addr, card->options.hsuid, 9);
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
if (addr != NULL) {
addr->u.a6.addr.s6_addr32[0] = 0xfe800000;
addr->u.a6.addr.s6_addr32[1] = 0x00000000;
for (i = 8; i < 16; i++)
addr->u.a6.addr.s6_addr[i] = card->options.hsuid[i - 8];
addr->u.a6.pfxlen = 0;
addr->type = QETH_IP_TYPE_NORMAL;
} else
return -ENOMEM;
if (!qeth_l3_add_ip(card, addr))
kfree(addr);
qeth_l3_set_ip_addr_list(card);
return count;
}
static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show,
qeth_l3_dev_hsuid_store);
static struct attribute *qeth_l3_device_attrs[] = {
&dev_attr_route4.attr,
&dev_attr_route6.attr,
@@ -354,6 +461,7 @@ static struct attribute *qeth_l3_device_attrs[] = {
&dev_attr_broadcast_mode.attr,
&dev_attr_canonical_macaddr.attr,
&dev_attr_sniffer.attr,
&dev_attr_hsuid.attr,
NULL,
};