Skip to content

Commit

Permalink
Merge branch 's390-qeth-updates-2020-11-17'
Browse files Browse the repository at this point in the history
Julian Wiedmann says:

====================
s390/qeth: updates 2020-11-17

This brings some cleanups, and a bunch of improvements for our
.get_link_ksettings() code.
====================

Link: https://lore.kernel.org/r/20201117161520.1089-1-jwi@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Nov 19, 2020
2 parents bd4bdeb + 235db52 commit aa8f2cb
Show file tree
Hide file tree
Showing 6 changed files with 373 additions and 193 deletions.
22 changes: 15 additions & 7 deletions drivers/s390/net/qeth_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,19 @@ enum qeth_pnso_mode {
QETH_PNSO_ADDR_INFO,
};

enum qeth_link_mode {
QETH_LINK_MODE_UNKNOWN,
QETH_LINK_MODE_FIBRE_SHORT,
QETH_LINK_MODE_FIBRE_LONG,
};

struct qeth_link_info {
u32 speed;
u8 duplex;
u8 port;
enum qeth_link_mode link_mode;
};

#define QETH_BROADCAST_WITH_ECHO 0x01
#define QETH_BROADCAST_WITHOUT_ECHO 0x02
struct qeth_card_info {
Expand Down Expand Up @@ -732,6 +745,7 @@ struct qeth_card_info {
struct qeth_card_blkt blkt;
__u32 diagass_support;
__u32 hwtrap;
struct qeth_link_info link_info;
};

enum qeth_discipline_id {
Expand Down Expand Up @@ -796,12 +810,6 @@ struct qeth_rx {
u8 bufs_refill;
};

struct carrier_info {
__u8 card_type;
__u16 port_mode;
__u32 port_speed;
};

struct qeth_switch_info {
__u32 capabilities;
__u32 settings;
Expand Down Expand Up @@ -1108,7 +1116,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info);
int qeth_query_card_info(struct qeth_card *card,
struct carrier_info *carrier_info);
struct qeth_link_info *link_info);
int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
enum qeth_ipa_isolation_modes mode);

Expand Down
223 changes: 216 additions & 7 deletions drivers/s390/net/qeth_core_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4868,23 +4868,76 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
static int qeth_query_card_info_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
struct carrier_info *carrier_info = (struct carrier_info *)reply->param;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
struct qeth_link_info *link_info = reply->param;
struct qeth_query_card_info *card_info;

QETH_CARD_TEXT(card, 2, "qcrdincb");
if (qeth_setadpparms_inspect_rc(cmd))
return -EIO;

card_info = &cmd->data.setadapterparms.data.card_info;
carrier_info->card_type = card_info->card_type;
carrier_info->port_mode = card_info->port_mode;
carrier_info->port_speed = card_info->port_speed;
netdev_dbg(card->dev,
"card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
card_info->card_type, card_info->port_mode,
card_info->port_speed);

switch (card_info->port_mode) {
case CARD_INFO_PORTM_FULLDUPLEX:
link_info->duplex = DUPLEX_FULL;
break;
case CARD_INFO_PORTM_HALFDUPLEX:
link_info->duplex = DUPLEX_HALF;
break;
default:
link_info->duplex = DUPLEX_UNKNOWN;
}

switch (card_info->card_type) {
case CARD_INFO_TYPE_1G_COPPER_A:
case CARD_INFO_TYPE_1G_COPPER_B:
link_info->speed = SPEED_1000;
link_info->port = PORT_TP;
break;
case CARD_INFO_TYPE_1G_FIBRE_A:
case CARD_INFO_TYPE_1G_FIBRE_B:
link_info->speed = SPEED_1000;
link_info->port = PORT_FIBRE;
break;
case CARD_INFO_TYPE_10G_FIBRE_A:
case CARD_INFO_TYPE_10G_FIBRE_B:
link_info->speed = SPEED_10000;
link_info->port = PORT_FIBRE;
break;
default:
switch (card_info->port_speed) {
case CARD_INFO_PORTS_10M:
link_info->speed = SPEED_10;
break;
case CARD_INFO_PORTS_100M:
link_info->speed = SPEED_100;
break;
case CARD_INFO_PORTS_1G:
link_info->speed = SPEED_1000;
break;
case CARD_INFO_PORTS_10G:
link_info->speed = SPEED_10000;
break;
case CARD_INFO_PORTS_25G:
link_info->speed = SPEED_25000;
break;
default:
link_info->speed = SPEED_UNKNOWN;
}

link_info->port = PORT_OTHER;
}

return 0;
}

int qeth_query_card_info(struct qeth_card *card,
struct carrier_info *carrier_info)
struct qeth_link_info *link_info)
{
struct qeth_cmd_buffer *iob;

Expand All @@ -4894,8 +4947,162 @@ int qeth_query_card_info(struct qeth_card *card,
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO, 0);
if (!iob)
return -ENOMEM;
return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb,
(void *)carrier_info);

return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb, link_info);
}

static int qeth_init_link_info_oat_cb(struct qeth_card *card,
struct qeth_reply *reply_priv,
unsigned long data)
{
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
struct qeth_link_info *link_info = reply_priv->param;
struct qeth_query_oat_physical_if *phys_if;
struct qeth_query_oat_reply *reply;

if (qeth_setadpparms_inspect_rc(cmd))
return -EIO;

/* Multi-part reply is unexpected, don't bother: */
if (cmd->data.setadapterparms.hdr.used_total > 1)
return -EINVAL;

/* Expect the reply to start with phys_if data: */
reply = &cmd->data.setadapterparms.data.query_oat.reply[0];
if (reply->type != QETH_QOAT_REPLY_TYPE_PHYS_IF ||
reply->length < sizeof(*reply))
return -EINVAL;

phys_if = &reply->phys_if;

switch (phys_if->speed_duplex) {
case QETH_QOAT_PHYS_SPEED_10M_HALF:
link_info->speed = SPEED_10;
link_info->duplex = DUPLEX_HALF;
break;
case QETH_QOAT_PHYS_SPEED_10M_FULL:
link_info->speed = SPEED_10;
link_info->duplex = DUPLEX_FULL;
break;
case QETH_QOAT_PHYS_SPEED_100M_HALF:
link_info->speed = SPEED_100;
link_info->duplex = DUPLEX_HALF;
break;
case QETH_QOAT_PHYS_SPEED_100M_FULL:
link_info->speed = SPEED_100;
link_info->duplex = DUPLEX_FULL;
break;
case QETH_QOAT_PHYS_SPEED_1000M_HALF:
link_info->speed = SPEED_1000;
link_info->duplex = DUPLEX_HALF;
break;
case QETH_QOAT_PHYS_SPEED_1000M_FULL:
link_info->speed = SPEED_1000;
link_info->duplex = DUPLEX_FULL;
break;
case QETH_QOAT_PHYS_SPEED_10G_FULL:
link_info->speed = SPEED_10000;
link_info->duplex = DUPLEX_FULL;
break;
case QETH_QOAT_PHYS_SPEED_25G_FULL:
link_info->speed = SPEED_25000;
link_info->duplex = DUPLEX_FULL;
break;
case QETH_QOAT_PHYS_SPEED_UNKNOWN:
default:
link_info->speed = SPEED_UNKNOWN;
link_info->duplex = DUPLEX_UNKNOWN;
break;
}

switch (phys_if->media_type) {
case QETH_QOAT_PHYS_MEDIA_COPPER:
link_info->port = PORT_TP;
link_info->link_mode = QETH_LINK_MODE_UNKNOWN;
break;
case QETH_QOAT_PHYS_MEDIA_FIBRE_SHORT:
link_info->port = PORT_FIBRE;
link_info->link_mode = QETH_LINK_MODE_FIBRE_SHORT;
break;
case QETH_QOAT_PHYS_MEDIA_FIBRE_LONG:
link_info->port = PORT_FIBRE;
link_info->link_mode = QETH_LINK_MODE_FIBRE_LONG;
break;
default:
link_info->port = PORT_OTHER;
link_info->link_mode = QETH_LINK_MODE_UNKNOWN;
break;
}

return 0;
}

static void qeth_init_link_info(struct qeth_card *card)
{
card->info.link_info.duplex = DUPLEX_FULL;

if (IS_IQD(card) || IS_VM_NIC(card)) {
card->info.link_info.speed = SPEED_10000;
card->info.link_info.port = PORT_FIBRE;
card->info.link_info.link_mode = QETH_LINK_MODE_FIBRE_SHORT;
} else {
switch (card->info.link_type) {
case QETH_LINK_TYPE_FAST_ETH:
case QETH_LINK_TYPE_LANE_ETH100:
card->info.link_info.speed = SPEED_100;
card->info.link_info.port = PORT_TP;
break;
case QETH_LINK_TYPE_GBIT_ETH:
case QETH_LINK_TYPE_LANE_ETH1000:
card->info.link_info.speed = SPEED_1000;
card->info.link_info.port = PORT_FIBRE;
break;
case QETH_LINK_TYPE_10GBIT_ETH:
card->info.link_info.speed = SPEED_10000;
card->info.link_info.port = PORT_FIBRE;
break;
case QETH_LINK_TYPE_25GBIT_ETH:
card->info.link_info.speed = SPEED_25000;
card->info.link_info.port = PORT_FIBRE;
break;
default:
dev_info(&card->gdev->dev, "Unknown link type %x\n",
card->info.link_type);
card->info.link_info.speed = SPEED_UNKNOWN;
card->info.link_info.port = PORT_OTHER;
}

card->info.link_info.link_mode = QETH_LINK_MODE_UNKNOWN;
}

/* Get more accurate data via QUERY OAT: */
if (qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) {
struct qeth_link_info link_info;
struct qeth_cmd_buffer *iob;

iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT,
SETADP_DATA_SIZEOF(query_oat));
if (iob) {
struct qeth_ipa_cmd *cmd = __ipa_cmd(iob);
struct qeth_query_oat *oat_req;

oat_req = &cmd->data.setadapterparms.data.query_oat;
oat_req->subcmd_code = QETH_QOAT_SCOPE_INTERFACE;

if (!qeth_send_ipa_cmd(card, iob,
qeth_init_link_info_oat_cb,
&link_info)) {
if (link_info.speed != SPEED_UNKNOWN)
card->info.link_info.speed = link_info.speed;
if (link_info.duplex != DUPLEX_UNKNOWN)
card->info.link_info.duplex = link_info.duplex;
if (link_info.port != PORT_OTHER)
card->info.link_info.port = link_info.port;
if (link_info.link_mode != QETH_LINK_MODE_UNKNOWN)
card->info.link_info.link_mode = link_info.link_mode;
}
}
}
}

/**
Expand Down Expand Up @@ -5282,6 +5489,8 @@ static int qeth_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
goto out;
}

qeth_init_link_info(card);

rc = qeth_init_qdio_queues(card);
if (rc) {
QETH_CARD_TEXT_(card, 2, "9err%d", rc);
Expand Down
40 changes: 38 additions & 2 deletions drivers/s390/net/qeth_core_mpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,9 +489,45 @@ struct qeth_set_access_ctrl {
__u8 reserved[8];
} __attribute__((packed));

#define QETH_QOAT_PHYS_SPEED_UNKNOWN 0x00
#define QETH_QOAT_PHYS_SPEED_10M_HALF 0x01
#define QETH_QOAT_PHYS_SPEED_10M_FULL 0x02
#define QETH_QOAT_PHYS_SPEED_100M_HALF 0x03
#define QETH_QOAT_PHYS_SPEED_100M_FULL 0x04
#define QETH_QOAT_PHYS_SPEED_1000M_HALF 0x05
#define QETH_QOAT_PHYS_SPEED_1000M_FULL 0x06
// n/a 0x07
#define QETH_QOAT_PHYS_SPEED_10G_FULL 0x08
// n/a 0x09
#define QETH_QOAT_PHYS_SPEED_25G_FULL 0x0A

#define QETH_QOAT_PHYS_MEDIA_COPPER 0x01
#define QETH_QOAT_PHYS_MEDIA_FIBRE_SHORT 0x02
#define QETH_QOAT_PHYS_MEDIA_FIBRE_LONG 0x04

struct qeth_query_oat_physical_if {
u8 res_head[33];
u8 speed_duplex;
u8 media_type;
u8 res_tail[29];
};

#define QETH_QOAT_REPLY_TYPE_PHYS_IF 0x0004

struct qeth_query_oat_reply {
u16 type;
u16 length;
u16 version;
u8 res[10];
struct qeth_query_oat_physical_if phys_if;
};

#define QETH_QOAT_SCOPE_INTERFACE 0x00000001

struct qeth_query_oat {
__u32 subcmd_code;
__u8 reserved[12];
u32 subcmd_code;
u8 reserved[12];
struct qeth_query_oat_reply reply[];
} __packed;

struct qeth_qoat_priv {
Expand Down
Loading

0 comments on commit aa8f2cb

Please sign in to comment.