Commit b8a5d06a authored by David S. Miller's avatar David S. Miller

Merge branch 's390-qeth-fixes'

Julian Wiedmann says:

====================
s390/qeth: fixes 2018-11-02

please apply one round of qeth fixes for -net.

Patch 1 is rather large and removes a use-after-free hazard from many of our
debug trace entries.
Patch 2 is yet another fix-up for the L3 subdriver's new IP address management
code.
Patch 3 and 4 resolve some fallout from the recent changes wrt how/when qeth
allocates its net_device.
Patch 5 makes sure we don't set reserved bits when building HW commands from
user-provided data.
And finally, patch 6 allows ethtool to play nice with new HW.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 265ad063 54e049c2
...@@ -87,6 +87,18 @@ struct qeth_dbf_info { ...@@ -87,6 +87,18 @@ struct qeth_dbf_info {
#define SENSE_RESETTING_EVENT_BYTE 1 #define SENSE_RESETTING_EVENT_BYTE 1
#define SENSE_RESETTING_EVENT_FLAG 0x80 #define SENSE_RESETTING_EVENT_FLAG 0x80
static inline u32 qeth_get_device_id(struct ccw_device *cdev)
{
struct ccw_dev_id dev_id;
u32 id;
ccw_device_get_id(cdev, &dev_id);
id = dev_id.devno;
id |= (u32) (dev_id.ssid << 16);
return id;
}
/* /*
* Common IO related definitions * Common IO related definitions
*/ */
...@@ -97,7 +109,8 @@ struct qeth_dbf_info { ...@@ -97,7 +109,8 @@ struct qeth_dbf_info {
#define CARD_RDEV_ID(card) dev_name(&card->read.ccwdev->dev) #define CARD_RDEV_ID(card) dev_name(&card->read.ccwdev->dev)
#define CARD_WDEV_ID(card) dev_name(&card->write.ccwdev->dev) #define CARD_WDEV_ID(card) dev_name(&card->write.ccwdev->dev)
#define CARD_DDEV_ID(card) dev_name(&card->data.ccwdev->dev) #define CARD_DDEV_ID(card) dev_name(&card->data.ccwdev->dev)
#define CHANNEL_ID(channel) dev_name(&channel->ccwdev->dev) #define CCW_DEVID(cdev) (qeth_get_device_id(cdev))
#define CARD_DEVID(card) (CCW_DEVID(CARD_RDEV(card)))
/** /**
* card stuff * card stuff
...@@ -830,6 +843,11 @@ struct qeth_trap_id { ...@@ -830,6 +843,11 @@ struct qeth_trap_id {
/*some helper functions*/ /*some helper functions*/
#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
static inline bool qeth_netdev_is_registered(struct net_device *dev)
{
return dev->netdev_ops != NULL;
}
static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf, static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf,
unsigned int elements) unsigned int elements)
{ {
...@@ -973,7 +991,7 @@ int qeth_wait_for_threads(struct qeth_card *, unsigned long); ...@@ -973,7 +991,7 @@ int qeth_wait_for_threads(struct qeth_card *, unsigned long);
int qeth_do_run_thread(struct qeth_card *, unsigned long); int qeth_do_run_thread(struct qeth_card *, unsigned long);
void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long); void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long); void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
int qeth_core_hardsetup_card(struct qeth_card *); int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok);
void qeth_print_status_message(struct qeth_card *); void qeth_print_status_message(struct qeth_card *);
int qeth_init_qdio_queues(struct qeth_card *); int qeth_init_qdio_queues(struct qeth_card *);
int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
...@@ -1028,11 +1046,6 @@ int qeth_configure_cq(struct qeth_card *, enum qeth_cq); ...@@ -1028,11 +1046,6 @@ int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
void qeth_trace_features(struct qeth_card *); void qeth_trace_features(struct qeth_card *);
void qeth_close_dev(struct qeth_card *); void qeth_close_dev(struct qeth_card *);
int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16,
long,
int (*reply_cb)(struct qeth_card *,
struct qeth_reply *, unsigned long),
void *);
int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long); int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *, struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
enum qeth_ipa_funcs, enum qeth_ipa_funcs,
......
...@@ -167,6 +167,8 @@ const char *qeth_get_cardname_short(struct qeth_card *card) ...@@ -167,6 +167,8 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
return "OSD_1000"; return "OSD_1000";
case QETH_LINK_TYPE_10GBIT_ETH: case QETH_LINK_TYPE_10GBIT_ETH:
return "OSD_10GIG"; return "OSD_10GIG";
case QETH_LINK_TYPE_25GBIT_ETH:
return "OSD_25GIG";
case QETH_LINK_TYPE_LANE_ETH100: case QETH_LINK_TYPE_LANE_ETH100:
return "OSD_FE_LANE"; return "OSD_FE_LANE";
case QETH_LINK_TYPE_LANE_TR: case QETH_LINK_TYPE_LANE_TR:
...@@ -554,8 +556,8 @@ static int __qeth_issue_next_read(struct qeth_card *card) ...@@ -554,8 +556,8 @@ static int __qeth_issue_next_read(struct qeth_card *card)
if (!iob) { if (!iob) {
dev_warn(&card->gdev->dev, "The qeth device driver " dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n"); "failed to recover an error on the device\n");
QETH_DBF_MESSAGE(2, "%s issue_next_read failed: no iob " QETH_DBF_MESSAGE(2, "issue_next_read on device %x failed: no iob available\n",
"available\n", dev_name(&card->gdev->dev)); CARD_DEVID(card));
return -ENOMEM; return -ENOMEM;
} }
qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data); qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data);
...@@ -563,8 +565,8 @@ static int __qeth_issue_next_read(struct qeth_card *card) ...@@ -563,8 +565,8 @@ static int __qeth_issue_next_read(struct qeth_card *card)
rc = ccw_device_start(channel->ccwdev, channel->ccw, rc = ccw_device_start(channel->ccwdev, channel->ccw,
(addr_t) iob, 0, 0); (addr_t) iob, 0, 0);
if (rc) { if (rc) {
QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! " QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
"rc=%i\n", dev_name(&card->gdev->dev), rc); rc, CARD_DEVID(card));
atomic_set(&channel->irq_pending, 0); atomic_set(&channel->irq_pending, 0);
card->read_or_write_problem = 1; card->read_or_write_problem = 1;
qeth_schedule_recovery(card); qeth_schedule_recovery(card);
...@@ -613,16 +615,14 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc, ...@@ -613,16 +615,14 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
const char *ipa_name; const char *ipa_name;
int com = cmd->hdr.command; int com = cmd->hdr.command;
ipa_name = qeth_get_ipa_cmd_name(com); ipa_name = qeth_get_ipa_cmd_name(com);
if (rc) if (rc)
QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s/%s returned " QETH_DBF_MESSAGE(2, "IPA: %s(%#x) for device %x returned %#x \"%s\"\n",
"x%X \"%s\"\n", ipa_name, com, CARD_DEVID(card), rc,
ipa_name, com, dev_name(&card->gdev->dev), qeth_get_ipa_msg(rc));
QETH_CARD_IFNAME(card), rc,
qeth_get_ipa_msg(rc));
else else
QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s/%s succeeded\n", QETH_DBF_MESSAGE(5, "IPA: %s(%#x) for device %x succeeded\n",
ipa_name, com, dev_name(&card->gdev->dev), ipa_name, com, CARD_DEVID(card));
QETH_CARD_IFNAME(card));
} }
static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
...@@ -711,7 +711,7 @@ static int qeth_check_idx_response(struct qeth_card *card, ...@@ -711,7 +711,7 @@ static int qeth_check_idx_response(struct qeth_card *card,
QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN); QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN);
if ((buffer[2] & 0xc0) == 0xc0) { if ((buffer[2] & 0xc0) == 0xc0) {
QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#02x\n", QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#04x\n",
buffer[4]); buffer[4]);
QETH_CARD_TEXT(card, 2, "ckidxres"); QETH_CARD_TEXT(card, 2, "ckidxres");
QETH_CARD_TEXT(card, 2, " idxterm"); QETH_CARD_TEXT(card, 2, " idxterm");
...@@ -972,8 +972,8 @@ static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev, ...@@ -972,8 +972,8 @@ static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev,
QETH_CARD_TEXT(card, 2, "CGENCHK"); QETH_CARD_TEXT(card, 2, "CGENCHK");
dev_warn(&cdev->dev, "The qeth device driver " dev_warn(&cdev->dev, "The qeth device driver "
"failed to recover an error on the device\n"); "failed to recover an error on the device\n");
QETH_DBF_MESSAGE(2, "%s check on device dstat=x%x, cstat=x%x\n", QETH_DBF_MESSAGE(2, "check on channel %x with dstat=%#x, cstat=%#x\n",
dev_name(&cdev->dev), dstat, cstat); CCW_DEVID(cdev), dstat, cstat);
print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET, print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
16, 1, irb, 64, 1); 16, 1, irb, 64, 1);
return 1; return 1;
...@@ -1013,8 +1013,8 @@ static long qeth_check_irb_error(struct qeth_card *card, ...@@ -1013,8 +1013,8 @@ static long qeth_check_irb_error(struct qeth_card *card,
switch (PTR_ERR(irb)) { switch (PTR_ERR(irb)) {
case -EIO: case -EIO:
QETH_DBF_MESSAGE(2, "%s i/o-error on device\n", QETH_DBF_MESSAGE(2, "i/o-error on channel %x\n",
dev_name(&cdev->dev)); CCW_DEVID(cdev));
QETH_CARD_TEXT(card, 2, "ckirberr"); QETH_CARD_TEXT(card, 2, "ckirberr");
QETH_CARD_TEXT_(card, 2, " rc%d", -EIO); QETH_CARD_TEXT_(card, 2, " rc%d", -EIO);
break; break;
...@@ -1031,8 +1031,8 @@ static long qeth_check_irb_error(struct qeth_card *card, ...@@ -1031,8 +1031,8 @@ static long qeth_check_irb_error(struct qeth_card *card,
} }
break; break;
default: default:
QETH_DBF_MESSAGE(2, "%s unknown error %ld on device\n", QETH_DBF_MESSAGE(2, "unknown error %ld on channel %x\n",
dev_name(&cdev->dev), PTR_ERR(irb)); PTR_ERR(irb), CCW_DEVID(cdev));
QETH_CARD_TEXT(card, 2, "ckirberr"); QETH_CARD_TEXT(card, 2, "ckirberr");
QETH_CARD_TEXT(card, 2, " rc???"); QETH_CARD_TEXT(card, 2, " rc???");
} }
...@@ -1114,9 +1114,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, ...@@ -1114,9 +1114,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
dev_warn(&channel->ccwdev->dev, dev_warn(&channel->ccwdev->dev,
"The qeth device driver failed to recover " "The qeth device driver failed to recover "
"an error on the device\n"); "an error on the device\n");
QETH_DBF_MESSAGE(2, "%s sense data available. cstat " QETH_DBF_MESSAGE(2, "sense data available on channel %x: cstat %#X dstat %#X\n",
"0x%X dstat 0x%X\n", CCW_DEVID(channel->ccwdev), cstat,
dev_name(&channel->ccwdev->dev), cstat, dstat); dstat);
print_hex_dump(KERN_WARNING, "qeth: irb ", print_hex_dump(KERN_WARNING, "qeth: irb ",
DUMP_PREFIX_OFFSET, 16, 1, irb, 32, 1); DUMP_PREFIX_OFFSET, 16, 1, irb, 32, 1);
print_hex_dump(KERN_WARNING, "qeth: sense data ", print_hex_dump(KERN_WARNING, "qeth: sense data ",
...@@ -1890,8 +1890,8 @@ static int qeth_idx_activate_channel(struct qeth_card *card, ...@@ -1890,8 +1890,8 @@ static int qeth_idx_activate_channel(struct qeth_card *card,
if (channel->state != CH_STATE_ACTIVATING) { if (channel->state != CH_STATE_ACTIVATING) {
dev_warn(&channel->ccwdev->dev, "The qeth device driver" dev_warn(&channel->ccwdev->dev, "The qeth device driver"
" failed to recover an error on the device\n"); " failed to recover an error on the device\n");
QETH_DBF_MESSAGE(2, "%s IDX activate timed out\n", QETH_DBF_MESSAGE(2, "IDX activate timed out on channel %x\n",
dev_name(&channel->ccwdev->dev)); CCW_DEVID(channel->ccwdev));
QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME); QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME);
return -ETIME; return -ETIME;
} }
...@@ -1926,17 +1926,15 @@ static void qeth_idx_write_cb(struct qeth_card *card, ...@@ -1926,17 +1926,15 @@ static void qeth_idx_write_cb(struct qeth_card *card,
"The adapter is used exclusively by another " "The adapter is used exclusively by another "
"host\n"); "host\n");
else else
QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on write channel:" QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: negative reply\n",
" negative reply\n", CCW_DEVID(channel->ccwdev));
dev_name(&channel->ccwdev->dev));
goto out; goto out;
} }
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2); memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) { if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) {
QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on write channel: " QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: function level mismatch (sent: %#x, received: %#x)\n",
"function level mismatch (sent: 0x%x, received: " CCW_DEVID(channel->ccwdev),
"0x%x)\n", dev_name(&channel->ccwdev->dev), card->info.func_level, temp);
card->info.func_level, temp);
goto out; goto out;
} }
channel->state = CH_STATE_UP; channel->state = CH_STATE_UP;
...@@ -1973,9 +1971,8 @@ static void qeth_idx_read_cb(struct qeth_card *card, ...@@ -1973,9 +1971,8 @@ static void qeth_idx_read_cb(struct qeth_card *card,
"insufficient authorization\n"); "insufficient authorization\n");
break; break;
default: default:
QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel:" QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: negative reply\n",
" negative reply\n", CCW_DEVID(channel->ccwdev));
dev_name(&channel->ccwdev->dev));
} }
QETH_CARD_TEXT_(card, 2, "idxread%c", QETH_CARD_TEXT_(card, 2, "idxread%c",
QETH_IDX_ACT_CAUSE_CODE(iob->data)); QETH_IDX_ACT_CAUSE_CODE(iob->data));
...@@ -1984,10 +1981,9 @@ static void qeth_idx_read_cb(struct qeth_card *card, ...@@ -1984,10 +1981,9 @@ static void qeth_idx_read_cb(struct qeth_card *card,
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2); memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
if (temp != qeth_peer_func_level(card->info.func_level)) { if (temp != qeth_peer_func_level(card->info.func_level)) {
QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel: function " QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: function level mismatch (sent: %#x, received: %#x)\n",
"level mismatch (sent: 0x%x, received: 0x%x)\n", CCW_DEVID(channel->ccwdev),
dev_name(&channel->ccwdev->dev), card->info.func_level, temp);
card->info.func_level, temp);
goto out; goto out;
} }
memcpy(&card->token.issuer_rm_r, memcpy(&card->token.issuer_rm_r,
...@@ -2096,9 +2092,8 @@ int qeth_send_control_data(struct qeth_card *card, int len, ...@@ -2096,9 +2092,8 @@ int qeth_send_control_data(struct qeth_card *card, int len,
(addr_t) iob, 0, 0, event_timeout); (addr_t) iob, 0, 0, event_timeout);
spin_unlock_irq(get_ccwdev_lock(channel->ccwdev)); spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc) { if (rc) {
QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: " QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n",
"ccw_device_start rc = %i\n", CARD_DEVID(card), rc);
dev_name(&channel->ccwdev->dev), rc);
QETH_CARD_TEXT_(card, 2, " err%d", rc); QETH_CARD_TEXT_(card, 2, " err%d", rc);
spin_lock_irq(&card->lock); spin_lock_irq(&card->lock);
list_del_init(&reply->list); list_del_init(&reply->list);
...@@ -2853,8 +2848,8 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card, ...@@ -2853,8 +2848,8 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
} else { } else {
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"The qeth driver ran out of channel command buffers\n"); "The qeth driver ran out of channel command buffers\n");
QETH_DBF_MESSAGE(1, "%s The qeth driver ran out of channel command buffers", QETH_DBF_MESSAGE(1, "device %x ran out of channel command buffers",
dev_name(&card->gdev->dev)); CARD_DEVID(card));
} }
return iob; return iob;
...@@ -2989,10 +2984,9 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, ...@@ -2989,10 +2984,9 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
return 0; return 0;
default: default:
if (cmd->hdr.return_code) { if (cmd->hdr.return_code) {
QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled " QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n",
"rc=%d\n", CARD_DEVID(card),
dev_name(&card->gdev->dev), cmd->hdr.return_code);
cmd->hdr.return_code);
return 0; return 0;
} }
} }
...@@ -3004,8 +2998,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, ...@@ -3004,8 +2998,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
} else } else
QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected" QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Flawed LIC detected\n",
"\n", dev_name(&card->gdev->dev)); CARD_DEVID(card));
return 0; return 0;
} }
...@@ -4297,10 +4291,9 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, ...@@ -4297,10 +4291,9 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
cmd->data.setadapterparms.hdr.return_code); cmd->data.setadapterparms.hdr.return_code);
if (cmd->data.setadapterparms.hdr.return_code != if (cmd->data.setadapterparms.hdr.return_code !=
SET_ACCESS_CTRL_RC_SUCCESS) SET_ACCESS_CTRL_RC_SUCCESS)
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n", QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%#x) on device %x: %#x\n",
card->gdev->dev.kobj.name, access_ctrl_req->subcmd_code, CARD_DEVID(card),
access_ctrl_req->subcmd_code, cmd->data.setadapterparms.hdr.return_code);
cmd->data.setadapterparms.hdr.return_code);
switch (cmd->data.setadapterparms.hdr.return_code) { switch (cmd->data.setadapterparms.hdr.return_code) {
case SET_ACCESS_CTRL_RC_SUCCESS: case SET_ACCESS_CTRL_RC_SUCCESS:
if (card->options.isolation == ISOLATION_MODE_NONE) { if (card->options.isolation == ISOLATION_MODE_NONE) {
...@@ -4312,14 +4305,14 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, ...@@ -4312,14 +4305,14 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
} }
break; break;
case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED: case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED:
QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already " QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already deactivated\n",
"deactivated\n", dev_name(&card->gdev->dev)); CARD_DEVID(card));
if (fallback) if (fallback)
card->options.isolation = card->options.prev_isolation; card->options.isolation = card->options.prev_isolation;
break; break;
case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED: case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED:
QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already" QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already activated\n",
" activated\n", dev_name(&card->gdev->dev)); CARD_DEVID(card));
if (fallback) if (fallback)
card->options.isolation = card->options.prev_isolation; card->options.isolation = card->options.prev_isolation;
break; break;
...@@ -4405,10 +4398,8 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback) ...@@ -4405,10 +4398,8 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback)
rc = qeth_setadpparms_set_access_ctrl(card, rc = qeth_setadpparms_set_access_ctrl(card,
card->options.isolation, fallback); card->options.isolation, fallback);
if (rc) { if (rc) {
QETH_DBF_MESSAGE(3, QETH_DBF_MESSAGE(3, "IPA(SET_ACCESS_CTRL(%d) on device %x: sent failed\n",
"IPA(SET_ACCESS_CTRL,%s,%d) sent failed\n", rc, CARD_DEVID(card));
card->gdev->dev.kobj.name,
rc);
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
} else if (card->options.isolation != ISOLATION_MODE_NONE) { } else if (card->options.isolation != ISOLATION_MODE_NONE) {
...@@ -4443,7 +4434,8 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) ...@@ -4443,7 +4434,8 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
rc = BMCR_FULLDPLX; rc = BMCR_FULLDPLX;
if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH) && if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH) &&
(card->info.link_type != QETH_LINK_TYPE_OSN) && (card->info.link_type != QETH_LINK_TYPE_OSN) &&
(card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH)) (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH) &&
(card->info.link_type != QETH_LINK_TYPE_25GBIT_ETH))
rc |= BMCR_SPEED100; rc |= BMCR_SPEED100;
break; break;
case MII_BMSR: /* Basic mode status register */ case MII_BMSR: /* Basic mode status register */
...@@ -4634,8 +4626,8 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata) ...@@ -4634,8 +4626,8 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len, rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
qeth_snmp_command_cb, (void *)&qinfo); qeth_snmp_command_cb, (void *)&qinfo);
if (rc) if (rc)
QETH_DBF_MESSAGE(2, "SNMP command failed on %s: (0x%x)\n", QETH_DBF_MESSAGE(2, "SNMP command failed on device %x: (%#x)\n",
QETH_CARD_IFNAME(card), rc); CARD_DEVID(card), rc);
else { else {
if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))
rc = -EFAULT; rc = -EFAULT;
...@@ -4869,8 +4861,8 @@ static void qeth_determine_capabilities(struct qeth_card *card) ...@@ -4869,8 +4861,8 @@ static void qeth_determine_capabilities(struct qeth_card *card)
rc = qeth_read_conf_data(card, (void **) &prcd, &length); rc = qeth_read_conf_data(card, (void **) &prcd, &length);
if (rc) { if (rc) {
QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", QETH_DBF_MESSAGE(2, "qeth_read_conf_data on device %x returned %i\n",
dev_name(&card->gdev->dev), rc); CARD_DEVID(card), rc);
QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
goto out_offline; goto out_offline;
} }
...@@ -5086,7 +5078,7 @@ static struct ccw_driver qeth_ccw_driver = { ...@@ -5086,7 +5078,7 @@ static struct ccw_driver qeth_ccw_driver = {
.remove = ccwgroup_remove_ccwdev, .remove = ccwgroup_remove_ccwdev,
}; };
int qeth_core_hardsetup_card(struct qeth_card *card) int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
{ {
int retries = 3; int retries = 3;
int rc; int rc;
...@@ -5096,8 +5088,8 @@ int qeth_core_hardsetup_card(struct qeth_card *card) ...@@ -5096,8 +5088,8 @@ int qeth_core_hardsetup_card(struct qeth_card *card)
qeth_update_from_chp_desc(card); qeth_update_from_chp_desc(card);
retry: retry:
if (retries < 3) if (retries < 3)
QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", QETH_DBF_MESSAGE(2, "Retrying to do IDX activates on device %x.\n",
dev_name(&card->gdev->dev)); CARD_DEVID(card));
rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD); rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_DDEV(card));
ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_WDEV(card));
...@@ -5161,13 +5153,20 @@ int qeth_core_hardsetup_card(struct qeth_card *card) ...@@ -5161,13 +5153,20 @@ int qeth_core_hardsetup_card(struct qeth_card *card)
if (rc == IPA_RC_LAN_OFFLINE) { if (rc == IPA_RC_LAN_OFFLINE) {
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"The LAN is offline\n"); "The LAN is offline\n");
netif_carrier_off(card->dev); *carrier_ok = false;
} else { } else {
rc = -ENODEV; rc = -ENODEV;
goto out; goto out;
} }
} else { } else {
netif_carrier_on(card->dev); *carrier_ok = true;
}
if (qeth_netdev_is_registered(card->dev)) {
if (*carrier_ok)
netif_carrier_on(card->dev);
else
netif_carrier_off(card->dev);
} }
card->options.ipa4.supported_funcs = 0; card->options.ipa4.supported_funcs = 0;
...@@ -5201,8 +5200,8 @@ int qeth_core_hardsetup_card(struct qeth_card *card) ...@@ -5201,8 +5200,8 @@ int qeth_core_hardsetup_card(struct qeth_card *card)
out: out:
dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " dev_warn(&card->gdev->dev, "The qeth device driver failed to recover "
"an error on the device\n"); "an error on the device\n");
QETH_DBF_MESSAGE(2, "%s Initialization in hardsetup failed! rc=%d\n", QETH_DBF_MESSAGE(2, "Initialization for device %x failed in hardsetup! rc=%d\n",
dev_name(&card->gdev->dev), rc); CARD_DEVID(card), rc);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card); EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card);
...@@ -5481,11 +5480,12 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card, ...@@ -5481,11 +5480,12 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
} }
EXPORT_SYMBOL_GPL(qeth_get_setassparms_cmd); EXPORT_SYMBOL_GPL(qeth_get_setassparms_cmd);
int qeth_send_setassparms(struct qeth_card *card, static int qeth_send_setassparms(struct qeth_card *card,
struct qeth_cmd_buffer *iob, __u16 len, long data, struct qeth_cmd_buffer *iob, u16 len,
int (*reply_cb)(struct qeth_card *, long data, int (*reply_cb)(struct qeth_card *,
struct qeth_reply *, unsigned long), struct qeth_reply *,
void *reply_param) unsigned long),
void *reply_param)
{ {
int rc; int rc;
struct qeth_ipa_cmd *cmd; struct qeth_ipa_cmd *cmd;
...@@ -5501,7 +5501,6 @@ int qeth_send_setassparms(struct qeth_card *card, ...@@ -5501,7 +5501,6 @@ int qeth_send_setassparms(struct qeth_card *card,
rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param); rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(qeth_send_setassparms);
int qeth_send_simple_setassparms_prot(struct qeth_card *card, int qeth_send_simple_setassparms_prot(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func, enum qeth_ipa_funcs ipa_func,
...@@ -6170,8 +6169,14 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, ...@@ -6170,8 +6169,14 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
/* fallthrough from high to low, to select all legal speeds: */ /* partially does fall through, to also select lower speeds */
switch (maxspeed) { switch (maxspeed) {
case SPEED_25000:
ethtool_link_ksettings_add_link_mode(cmd, supported,
25000baseSR_Full);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
25000baseSR_Full);
break;
case SPEED_10000: case SPEED_10000:
ethtool_link_ksettings_add_link_mode(cmd, supported, ethtool_link_ksettings_add_link_mode(cmd, supported,
10000baseT_Full); 10000baseT_Full);
...@@ -6254,6 +6259,10 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, ...@@ -6254,6 +6259,10 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
cmd->base.speed = SPEED_10000; cmd->base.speed = SPEED_10000;
cmd->base.port = PORT_FIBRE; cmd->base.port = PORT_FIBRE;
break; break;
case QETH_LINK_TYPE_25GBIT_ETH:
cmd->base.speed = SPEED_25000;
cmd->base.port = PORT_FIBRE;
break;
default: default:
cmd->base.speed = SPEED_10; cmd->base.speed = SPEED_10;
cmd->base.port = PORT_TP; cmd->base.port = PORT_TP;
...@@ -6320,6 +6329,9 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, ...@@ -6320,6 +6329,9 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
case CARD_INFO_PORTS_10G: case CARD_INFO_PORTS_10G:
cmd->base.speed = SPEED_10000; cmd->base.speed = SPEED_10000;
break; break;
case CARD_INFO_PORTS_25G:
cmd->base.speed = SPEED_25000;
break;
} }
return 0; return 0;
......
...@@ -90,6 +90,7 @@ enum qeth_link_types { ...@@ -90,6 +90,7 @@ enum qeth_link_types {
QETH_LINK_TYPE_GBIT_ETH = 0x03, QETH_LINK_TYPE_GBIT_ETH = 0x03,
QETH_LINK_TYPE_OSN = 0x04, QETH_LINK_TYPE_OSN = 0x04,
QETH_LINK_TYPE_10GBIT_ETH = 0x10, QETH_LINK_TYPE_10GBIT_ETH = 0x10,
QETH_LINK_TYPE_25GBIT_ETH = 0x12,
QETH_LINK_TYPE_LANE_ETH100 = 0x81, QETH_LINK_TYPE_LANE_ETH100 = 0x81,
QETH_LINK_TYPE_LANE_TR = 0x82, QETH_LINK_TYPE_LANE_TR = 0x82,
QETH_LINK_TYPE_LANE_ETH1000 = 0x83, QETH_LINK_TYPE_LANE_ETH1000 = 0x83,
...@@ -347,6 +348,7 @@ enum qeth_card_info_port_speed { ...@@ -347,6 +348,7 @@ enum qeth_card_info_port_speed {
CARD_INFO_PORTS_100M = 0x00000006, CARD_INFO_PORTS_100M = 0x00000006,
CARD_INFO_PORTS_1G = 0x00000007, CARD_INFO_PORTS_1G = 0x00000007,
CARD_INFO_PORTS_10G = 0x00000008, CARD_INFO_PORTS_10G = 0x00000008,
CARD_INFO_PORTS_25G = 0x0000000A,
}; };
/* (SET)DELIP(M) IPA stuff ***************************************************/ /* (SET)DELIP(M) IPA stuff ***************************************************/
...@@ -436,7 +438,7 @@ struct qeth_ipacmd_setassparms { ...@@ -436,7 +438,7 @@ struct qeth_ipacmd_setassparms {
__u32 flags_32bit; __u32 flags_32bit;
struct qeth_ipa_caps caps; struct qeth_ipa_caps caps;
struct qeth_checksum_cmd chksum; struct qeth_checksum_cmd chksum;
struct qeth_arp_cache_entry add_arp_entry; struct qeth_arp_cache_entry arp_entry;
struct qeth_arp_query_data query_arp; struct qeth_arp_query_data query_arp;
struct qeth_tso_start_data tso; struct qeth_tso_start_data tso;
__u8 ip[16]; __u8 ip[16];
......
...@@ -146,11 +146,11 @@ static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac) ...@@ -146,11 +146,11 @@ static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)
QETH_CARD_TEXT(card, 2, "L2Wmac"); QETH_CARD_TEXT(card, 2, "L2Wmac");
rc = qeth_l2_send_setdelmac(card, mac, cmd); rc = qeth_l2_send_setdelmac(card, mac, cmd);
if (rc == -EEXIST) if (rc == -EEXIST)
QETH_DBF_MESSAGE(2, "MAC %pM already registered on %s\n", QETH_DBF_MESSAGE(2, "MAC already registered on device %x\n",
mac, QETH_CARD_IFNAME(card)); CARD_DEVID(card));
else if (rc) else if (rc)
QETH_DBF_MESSAGE(2, "Failed to register MAC %pM on %s: %d\n", QETH_DBF_MESSAGE(2, "Failed to register MAC on device %x: %d\n",
mac, QETH_CARD_IFNAME(card), rc); CARD_DEVID(card), rc);
return rc; return rc;
} }
...@@ -163,8 +163,8 @@ static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac) ...@@ -163,8 +163,8 @@ static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac)
QETH_CARD_TEXT(card, 2, "L2Rmac"); QETH_CARD_TEXT(card, 2, "L2Rmac");
rc = qeth_l2_send_setdelmac(card, mac, cmd); rc = qeth_l2_send_setdelmac(card, mac, cmd);
if (rc) if (rc)
QETH_DBF_MESSAGE(2, "Failed to delete MAC %pM on %s: %d\n", QETH_DBF_MESSAGE(2, "Failed to delete MAC on device %u: %d\n",
mac, QETH_CARD_IFNAME(card), rc); CARD_DEVID(card), rc);
return rc; return rc;
} }
...@@ -260,9 +260,9 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card, ...@@ -260,9 +260,9 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "L2sdvcb"); QETH_CARD_TEXT(card, 2, "L2sdvcb");
if (cmd->hdr.return_code) { if (cmd->hdr.return_code) {
QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x.\n", QETH_DBF_MESSAGE(2, "Error in processing VLAN %u on device %x: %#x.\n",
cmd->data.setdelvlan.vlan_id, cmd->data.setdelvlan.vlan_id,
QETH_CARD_IFNAME(card), cmd->hdr.return_code); CARD_DEVID(card), cmd->hdr.return_code);
QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command); QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command);
QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code); QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code);
} }
...@@ -455,8 +455,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) ...@@ -455,8 +455,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
rc = qeth_vm_request_mac(card); rc = qeth_vm_request_mac(card);
if (!rc) if (!rc)
goto out; goto out;
QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %s: x%x\n", QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %x: %#x\n",
CARD_BUS_ID(card), rc); CARD_DEVID(card), rc);
QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc); QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc);
/* fall back to alternative mechanism: */ /* fall back to alternative mechanism: */
} }
...@@ -468,8 +468,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) ...@@ -468,8 +468,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
rc = qeth_setadpparms_change_macaddr(card); rc = qeth_setadpparms_change_macaddr(card);
if (!rc) if (!rc)
goto out; goto out;
QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %s: x%x\n", QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n",
CARD_BUS_ID(card), rc); CARD_DEVID(card), rc);
QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc); QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);
/* fall back once more: */ /* fall back once more: */
} }
...@@ -826,7 +826,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) ...@@ -826,7 +826,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
if (cgdev->state == CCWGROUP_ONLINE) if (cgdev->state == CCWGROUP_ONLINE)
qeth_l2_set_offline(cgdev); qeth_l2_set_offline(cgdev);
unregister_netdev(card->dev); if (qeth_netdev_is_registered(card->dev))
unregister_netdev(card->dev);
} }
static const struct ethtool_ops qeth_l2_ethtool_ops = { static const struct ethtool_ops qeth_l2_ethtool_ops = {
...@@ -862,11 +863,11 @@ static const struct net_device_ops qeth_l2_netdev_ops = { ...@@ -862,11 +863,11 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_set_features = qeth_set_features .ndo_set_features = qeth_set_features
}; };
static int qeth_l2_setup_netdev(struct qeth_card *card) static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
{ {
int rc; int rc;
if (card->dev->netdev_ops) if (qeth_netdev_is_registered(card->dev))
return 0; return 0;
card->dev->priv_flags |= IFF_UNICAST_FLT; card->dev->priv_flags |= IFF_UNICAST_FLT;
...@@ -919,6 +920,9 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) ...@@ -919,6 +920,9 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
qeth_l2_request_initial_mac(card); qeth_l2_request_initial_mac(card);
netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT); netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
rc = register_netdev(card->dev); rc = register_netdev(card->dev);
if (!rc && carrier_ok)
netif_carrier_on(card->dev);
if (rc) if (rc)
card->dev->netdev_ops = NULL; card->dev->netdev_ops = NULL;
return rc; return rc;
...@@ -949,6 +953,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -949,6 +953,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct qeth_card *card = dev_get_drvdata(&gdev->dev);
int rc = 0; int rc = 0;
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
bool carrier_ok;
mutex_lock(&card->discipline_mutex); mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex); mutex_lock(&card->conf_mutex);
...@@ -956,7 +961,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -956,7 +961,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
recover_flag = card->state; recover_flag = card->state;
rc = qeth_core_hardsetup_card(card); rc = qeth_core_hardsetup_card(card, &carrier_ok);
if (rc) { if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc); QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
rc = -ENODEV; rc = -ENODEV;
...@@ -967,7 +972,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -967,7 +972,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
dev_info(&card->gdev->dev, dev_info(&card->gdev->dev,
"The device represents a Bridge Capable Port\n"); "The device represents a Bridge Capable Port\n");
rc = qeth_l2_setup_netdev(card); rc = qeth_l2_setup_netdev(card, carrier_ok);
if (rc) if (rc)
goto out_remove; goto out_remove;
......
...@@ -278,9 +278,6 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover) ...@@ -278,9 +278,6 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover)
QETH_CARD_TEXT(card, 4, "clearip"); QETH_CARD_TEXT(card, 4, "clearip");
if (recover && card->options.sniffer)
return;
spin_lock_bh(&card->ip_lock); spin_lock_bh(&card->ip_lock);
hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) { hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) {
...@@ -494,9 +491,8 @@ int qeth_l3_setrouting_v4(struct qeth_card *card) ...@@ -494,9 +491,8 @@ int qeth_l3_setrouting_v4(struct qeth_card *card)
QETH_PROT_IPV4); QETH_PROT_IPV4);
if (rc) { if (rc) {
card->options.route4.type = NO_ROUTER; card->options.route4.type = NO_ROUTER;
QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n",
" on %s. Type set to 'no router'.\n", rc, rc, CARD_DEVID(card));
QETH_CARD_IFNAME(card));
} }
return rc; return rc;
} }
...@@ -518,9 +514,8 @@ int qeth_l3_setrouting_v6(struct qeth_card *card) ...@@ -518,9 +514,8 @@ int qeth_l3_setrouting_v6(struct qeth_card *card)
QETH_PROT_IPV6); QETH_PROT_IPV6);
if (rc) { if (rc) {
card->options.route6.type = NO_ROUTER; card->options.route6.type = NO_ROUTER;
QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n",
" on %s. Type set to 'no router'.\n", rc, rc, CARD_DEVID(card));
QETH_CARD_IFNAME(card));
} }
return rc; return rc;
} }
...@@ -663,6 +658,8 @@ static int qeth_l3_register_addr_entry(struct qeth_card *card, ...@@ -663,6 +658,8 @@ static int qeth_l3_register_addr_entry(struct qeth_card *card,
int rc = 0; int rc = 0;
int cnt = 3; int cnt = 3;
if (card->options.sniffer)
return 0;
if (addr->proto == QETH_PROT_IPV4) { if (addr->proto == QETH_PROT_IPV4) {
QETH_CARD_TEXT(card, 2, "setaddr4"); QETH_CARD_TEXT(card, 2, "setaddr4");
...@@ -697,6 +694,9 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *card, ...@@ -697,6 +694,9 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *card,
{ {
int rc = 0; int rc = 0;
if (card->options.sniffer)
return 0;
if (addr->proto == QETH_PROT_IPV4) { if (addr->proto == QETH_PROT_IPV4) {
QETH_CARD_TEXT(card, 2, "deladdr4"); QETH_CARD_TEXT(card, 2, "deladdr4");
QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int)); QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int));
...@@ -1070,8 +1070,8 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply, ...@@ -1070,8 +1070,8 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply,
} }
break; break;
default: default:
QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n", QETH_DBF_MESSAGE(2, "Unknown sniffer action (%#06x) on device %x\n",
cmd->data.diagass.action, QETH_CARD_IFNAME(card)); cmd->data.diagass.action, CARD_DEVID(card));
} }
return 0; return 0;
...@@ -1517,32 +1517,25 @@ static void qeth_l3_set_rx_mode(struct net_device *dev) ...@@ -1517,32 +1517,25 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)
qeth_l3_handle_promisc_mode(card); qeth_l3_handle_promisc_mode(card);
} }
static const char *qeth_l3_arp_get_error_cause(int *rc) static int qeth_l3_arp_makerc(int rc)
{ {
switch (*rc) { switch (rc) {
case QETH_IPA_ARP_RC_FAILED: case IPA_RC_SUCCESS:
*rc = -EIO; return 0;
return "operation failed";
case QETH_IPA_ARP_RC_NOTSUPP: case QETH_IPA_ARP_RC_NOTSUPP:
*rc = -EOPNOTSUPP;
return "operation not supported";
case QETH_IPA_ARP_RC_OUT_OF_RANGE:
*rc = -EINVAL;
return "argument out of range";
case QETH_IPA_ARP_RC_Q_NOTSUPP: case QETH_IPA_ARP_RC_Q_NOTSUPP:
*rc = -EOPNOTSUPP; return -EOPNOTSUPP;
return "query operation not supported"; case QETH_IPA_ARP_RC_OUT_OF_RANGE:
return -EINVAL;
case QETH_IPA_ARP_RC_Q_NO_DATA: case QETH_IPA_ARP_RC_Q_NO_DATA:
*rc = -ENOENT; return -ENOENT;
return "no query data available";
default: default:
return "unknown error"; return -EIO;
} }
} }
static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
{ {
int tmp;
int rc; int rc;
QETH_CARD_TEXT(card, 3, "arpstnoe"); QETH_CARD_TEXT(card, 3, "arpstnoe");
...@@ -1560,13 +1553,10 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) ...@@ -1560,13 +1553,10 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING, rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_SET_NO_ENTRIES, IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
no_entries); no_entries);
if (rc) { if (rc)
tmp = rc; QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on device %x: %#x\n",
QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on " CARD_DEVID(card), rc);
"%s: %s (0x%x/%d)\n", QETH_CARD_IFNAME(card), return qeth_l3_arp_makerc(rc);
qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
}
return rc;
} }
static __u32 get_arp_entry_size(struct qeth_card *card, static __u32 get_arp_entry_size(struct qeth_card *card,
...@@ -1716,7 +1706,6 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card, ...@@ -1716,7 +1706,6 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
{ {
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd; struct qeth_ipa_cmd *cmd;
int tmp;
int rc; int rc;
QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot); QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot);
...@@ -1735,15 +1724,10 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card, ...@@ -1735,15 +1724,10 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
rc = qeth_l3_send_ipa_arp_cmd(card, iob, rc = qeth_l3_send_ipa_arp_cmd(card, iob,
QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN, QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
qeth_l3_arp_query_cb, (void *)qinfo); qeth_l3_arp_query_cb, (void *)qinfo);
if (rc) { if (rc)
tmp = rc; QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n",
QETH_DBF_MESSAGE(2, CARD_DEVID(card), rc);
"Error while querying ARP cache on %s: %s " return qeth_l3_arp_makerc(rc);
"(0x%x/%d)\n", QETH_CARD_IFNAME(card),
qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
}
return rc;
} }
static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
...@@ -1793,15 +1777,18 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) ...@@ -1793,15 +1777,18 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata)
return rc; return rc;
} }
static int qeth_l3_arp_add_entry(struct qeth_card *card, static int qeth_l3_arp_modify_entry(struct qeth_card *card,
struct qeth_arp_cache_entry *entry) struct qeth_arp_cache_entry *entry,
enum qeth_arp_process_subcmds arp_cmd)
{ {
struct qeth_arp_cache_entry *cmd_entry;
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
char buf[16];
int tmp;
int rc; int rc;
QETH_CARD_TEXT(card, 3, "arpadent"); if (arp_cmd == IPA_CMD_ASS_ARP_ADD_ENTRY)
QETH_CARD_TEXT(card, 3, "arpadd");
else
QETH_CARD_TEXT(card, 3, "arpdel");
/* /*
* currently GuestLAN only supports the ARP assist function * currently GuestLAN only supports the ARP assist function
...@@ -1814,71 +1801,25 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card, ...@@ -1814,71 +1801,25 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, arp_cmd,
IPA_CMD_ASS_ARP_ADD_ENTRY, sizeof(*cmd_entry), QETH_PROT_IPV4);
sizeof(struct qeth_arp_cache_entry),
QETH_PROT_IPV4);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
rc = qeth_send_setassparms(card, iob,
sizeof(struct qeth_arp_cache_entry),
(unsigned long) entry,
qeth_setassparms_cb, NULL);
if (rc) {
tmp = rc;
qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
QETH_DBF_MESSAGE(2, "Could not add ARP entry for address %s "
"on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card),
qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
}
return rc;
}
static int qeth_l3_arp_remove_entry(struct qeth_card *card,
struct qeth_arp_cache_entry *entry)
{
struct qeth_cmd_buffer *iob;
char buf[16] = {0, };
int tmp;
int rc;
QETH_CARD_TEXT(card, 3, "arprment"); cmd_entry = &__ipa_cmd(iob)->data.setassparms.data.arp_entry;
ether_addr_copy(cmd_entry->macaddr, entry->macaddr);
memcpy(cmd_entry->ipaddr, entry->ipaddr, 4);
rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL);
if (rc)
QETH_DBF_MESSAGE(2, "Could not modify (cmd: %#x) ARP entry on device %x: %#x\n",
arp_cmd, CARD_DEVID(card), rc);
/* return qeth_l3_arp_makerc(rc);
* currently GuestLAN only supports the ARP assist function
* IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
* thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) {
return -EOPNOTSUPP;
}
memcpy(buf, entry, 12);
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_REMOVE_ENTRY,
12,
QETH_PROT_IPV4);
if (!iob)
return -ENOMEM;
rc = qeth_send_setassparms(card, iob,
12, (unsigned long)buf,
qeth_setassparms_cb, NULL);
if (rc) {
tmp = rc;
memset(buf, 0, 16);
qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf);
QETH_DBF_MESSAGE(2, "Could not delete ARP entry for address %s"
" on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card),
qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
}
return rc;
} }
static int qeth_l3_arp_flush_cache(struct qeth_card *card) static int qeth_l3_arp_flush_cache(struct qeth_card *card)
{ {
int rc; int rc;
int tmp;
QETH_CARD_TEXT(card, 3, "arpflush"); QETH_CARD_TEXT(card, 3, "arpflush");
...@@ -1894,19 +1835,17 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card) ...@@ -1894,19 +1835,17 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card)
} }
rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING, rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
IPA_CMD_ASS_ARP_FLUSH_CACHE, 0); IPA_CMD_ASS_ARP_FLUSH_CACHE, 0);
if (rc) { if (rc)
tmp = rc; QETH_DBF_MESSAGE(2, "Could not flush ARP cache on device %x: %#x\n",
QETH_DBF_MESSAGE(2, "Could not flush ARP cache on %s: %s " CARD_DEVID(card), rc);
"(0x%x/%d)\n", QETH_CARD_IFNAME(card), return qeth_l3_arp_makerc(rc);
qeth_l3_arp_get_error_cause(&rc), tmp, tmp);
}
return rc;
} }
static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ {
struct qeth_card *card = dev->ml_priv; struct qeth_card *card = dev->ml_priv;
struct qeth_arp_cache_entry arp_entry; struct qeth_arp_cache_entry arp_entry;
enum qeth_arp_process_subcmds arp_cmd;
int rc = 0; int rc = 0;
switch (cmd) { switch (cmd) {
...@@ -1925,27 +1864,16 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -1925,27 +1864,16 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data); rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data);
break; break;
case SIOC_QETH_ARP_ADD_ENTRY: case SIOC_QETH_ARP_ADD_ENTRY:
if (!capable(CAP_NET_ADMIN)) {
rc = -EPERM;
break;
}
if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
sizeof(struct qeth_arp_cache_entry)))
rc = -EFAULT;
else
rc = qeth_l3_arp_add_entry(card, &arp_entry);
break;
case SIOC_QETH_ARP_REMOVE_ENTRY: case SIOC_QETH_ARP_REMOVE_ENTRY:
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN))
rc = -EPERM; return -EPERM;
break; if (copy_from_user(&arp_entry, rq->ifr_data, sizeof(arp_entry)))
} return -EFAULT;
if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data,
sizeof(struct qeth_arp_cache_entry))) arp_cmd = (cmd == SIOC_QETH_ARP_ADD_ENTRY) ?
rc = -EFAULT; IPA_CMD_ASS_ARP_ADD_ENTRY :
else IPA_CMD_ASS_ARP_REMOVE_ENTRY;
rc = qeth_l3_arp_remove_entry(card, &arp_entry); return qeth_l3_arp_modify_entry(card, &arp_entry, arp_cmd);
break;
case SIOC_QETH_ARP_FLUSH_CACHE: case SIOC_QETH_ARP_FLUSH_CACHE:
if (!capable(CAP_NET_ADMIN)) { if (!capable(CAP_NET_ADMIN)) {
rc = -EPERM; rc = -EPERM;
...@@ -2383,12 +2311,12 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { ...@@ -2383,12 +2311,12 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
.ndo_neigh_setup = qeth_l3_neigh_setup, .ndo_neigh_setup = qeth_l3_neigh_setup,
}; };
static int qeth_l3_setup_netdev(struct qeth_card *card) static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)
{ {
unsigned int headroom; unsigned int headroom;
int rc; int rc;
if (card->dev->netdev_ops) if (qeth_netdev_is_registered(card->dev))
return 0; return 0;
if (card->info.type == QETH_CARD_TYPE_OSD || if (card->info.type == QETH_CARD_TYPE_OSD ||
...@@ -2457,6 +2385,9 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) ...@@ -2457,6 +2385,9 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT); netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
rc = register_netdev(card->dev); rc = register_netdev(card->dev);
if (!rc && carrier_ok)
netif_carrier_on(card->dev);
out: out:
if (rc) if (rc)
card->dev->netdev_ops = NULL; card->dev->netdev_ops = NULL;
...@@ -2497,7 +2428,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) ...@@ -2497,7 +2428,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
if (cgdev->state == CCWGROUP_ONLINE) if (cgdev->state == CCWGROUP_ONLINE)
qeth_l3_set_offline(cgdev); qeth_l3_set_offline(cgdev);
unregister_netdev(card->dev); if (qeth_netdev_is_registered(card->dev))
unregister_netdev(card->dev);
qeth_l3_clear_ip_htable(card, 0); qeth_l3_clear_ip_htable(card, 0);
qeth_l3_clear_ipato_list(card); qeth_l3_clear_ipato_list(card);
} }
...@@ -2507,6 +2439,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2507,6 +2439,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct qeth_card *card = dev_get_drvdata(&gdev->dev);
int rc = 0; int rc = 0;
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
bool carrier_ok;
mutex_lock(&card->discipline_mutex); mutex_lock(&card->discipline_mutex);
mutex_lock(&card->conf_mutex); mutex_lock(&card->conf_mutex);
...@@ -2514,14 +2447,14 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2514,14 +2447,14 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
recover_flag = card->state; recover_flag = card->state;
rc = qeth_core_hardsetup_card(card); rc = qeth_core_hardsetup_card(card, &carrier_ok);
if (rc) { if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc); QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
rc = -ENODEV; rc = -ENODEV;
goto out_remove; goto out_remove;
} }
rc = qeth_l3_setup_netdev(card); rc = qeth_l3_setup_netdev(card, carrier_ok);
if (rc) if (rc)
goto out_remove; goto out_remove;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment