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

Merge branch 's390-next'

Julian Wiedmann says:

====================
s390/qeth: features 2019-12-18

please apply the following patch series to your net-next tree.
Nothing major, just the usual mix of small improvements and cleanups.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3a74a62d 334b49de
...@@ -125,12 +125,6 @@ struct qeth_routing_info { ...@@ -125,12 +125,6 @@ struct qeth_routing_info {
enum qeth_routing_types type; enum qeth_routing_types type;
}; };
/* IPA stuff */
struct qeth_ipa_info {
__u32 supported_funcs;
__u32 enabled_funcs;
};
/* SETBRIDGEPORT stuff */ /* SETBRIDGEPORT stuff */
enum qeth_sbp_roles { enum qeth_sbp_roles {
QETH_SBP_ROLE_NONE = 0, QETH_SBP_ROLE_NONE = 0,
...@@ -169,41 +163,6 @@ struct qeth_vnicc_info { ...@@ -169,41 +163,6 @@ struct qeth_vnicc_info {
bool rx_bcast_enabled; bool rx_bcast_enabled;
}; };
static inline int qeth_is_adp_supported(struct qeth_ipa_info *ipa,
enum qeth_ipa_setadp_cmd func)
{
return (ipa->supported_funcs & func);
}
static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
enum qeth_ipa_funcs func)
{
return (ipa->supported_funcs & func);
}
static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
enum qeth_ipa_funcs func)
{
return (ipa->supported_funcs & ipa->enabled_funcs & func);
}
#define qeth_adp_supported(c, f) \
qeth_is_adp_supported(&c->options.adp, f)
#define qeth_is_supported(c, f) \
qeth_is_ipa_supported(&c->options.ipa4, f)
#define qeth_is_enabled(c, f) \
qeth_is_ipa_enabled(&c->options.ipa4, f)
#define qeth_is_supported6(c, f) \
qeth_is_ipa_supported(&c->options.ipa6, f)
#define qeth_is_enabled6(c, f) \
qeth_is_ipa_enabled(&c->options.ipa6, f)
#define qeth_is_ipafunc_supported(c, prot, f) \
((prot == QETH_PROT_IPV6) ? \
qeth_is_supported6(c, f) : qeth_is_supported(c, f))
#define qeth_is_ipafunc_enabled(c, prot, f) \
((prot == QETH_PROT_IPV6) ? \
qeth_is_enabled6(c, f) : qeth_is_enabled(c, f))
#define QETH_IDX_FUNC_LEVEL_OSD 0x0101 #define QETH_IDX_FUNC_LEVEL_OSD 0x0101
#define QETH_IDX_FUNC_LEVEL_IQD 0x4108 #define QETH_IDX_FUNC_LEVEL_IQD 0x4108
...@@ -735,11 +694,11 @@ enum qeth_discipline_id { ...@@ -735,11 +694,11 @@ enum qeth_discipline_id {
}; };
struct qeth_card_options { struct qeth_card_options {
struct qeth_ipa_caps ipa4;
struct qeth_ipa_caps ipa6;
struct qeth_routing_info route4; struct qeth_routing_info route4;
struct qeth_ipa_info ipa4;
struct qeth_ipa_info adp; /*Adapter parameters*/
struct qeth_routing_info route6; struct qeth_routing_info route6;
struct qeth_ipa_info ipa6; struct qeth_ipa_caps adp; /* Adapter parameters */
struct qeth_sbp_info sbp; /* SETBRIDGEPORT options */ struct qeth_sbp_info sbp; /* SETBRIDGEPORT options */
struct qeth_vnicc_info vnicc; /* VNICC options */ struct qeth_vnicc_info vnicc; /* VNICC options */
int fake_broadcast; int fake_broadcast;
...@@ -862,6 +821,13 @@ static inline bool qeth_card_hw_is_reachable(struct qeth_card *card) ...@@ -862,6 +821,13 @@ static inline bool qeth_card_hw_is_reachable(struct qeth_card *card)
return card->state == CARD_STATE_SOFTSETUP; return card->state == CARD_STATE_SOFTSETUP;
} }
static inline void qeth_unlock_channel(struct qeth_card *card,
struct qeth_channel *channel)
{
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
}
struct qeth_trap_id { struct qeth_trap_id {
__u16 lparnr; __u16 lparnr;
char vmname[8]; char vmname[8];
......
...@@ -520,11 +520,10 @@ static int __qeth_issue_next_read(struct qeth_card *card) ...@@ -520,11 +520,10 @@ static int __qeth_issue_next_read(struct qeth_card *card)
} else { } else {
QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n", QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
rc, CARD_DEVID(card)); rc, CARD_DEVID(card));
atomic_set(&channel->irq_pending, 0); qeth_unlock_channel(card, channel);
qeth_put_cmd(iob); qeth_put_cmd(iob);
card->read_or_write_problem = 1; card->read_or_write_problem = 1;
qeth_schedule_recovery(card); qeth_schedule_recovery(card);
wake_up(&card->wait_q);
} }
return rc; return rc;
} }
...@@ -972,8 +971,6 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, ...@@ -972,8 +971,6 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
/* while we hold the ccwdev lock, this stays valid: */ /* while we hold the ccwdev lock, this stays valid: */
gdev = dev_get_drvdata(&cdev->dev); gdev = dev_get_drvdata(&cdev->dev);
card = dev_get_drvdata(&gdev->dev); card = dev_get_drvdata(&gdev->dev);
if (!card)
return;
QETH_CARD_TEXT(card, 5, "irq"); QETH_CARD_TEXT(card, 5, "irq");
...@@ -1003,24 +1000,25 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, ...@@ -1003,24 +1000,25 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
} }
channel->active_cmd = NULL; channel->active_cmd = NULL;
qeth_unlock_channel(card, channel);
rc = qeth_check_irb_error(card, cdev, irb); rc = qeth_check_irb_error(card, cdev, irb);
if (rc) { if (rc) {
/* IO was terminated, free its resources. */ /* IO was terminated, free its resources. */
if (iob) if (iob)
qeth_cancel_cmd(iob, rc); qeth_cancel_cmd(iob, rc);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
return; return;
} }
atomic_set(&channel->irq_pending, 0); if (irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC) {
if (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC))
channel->state = CH_STATE_STOPPED; channel->state = CH_STATE_STOPPED;
wake_up(&card->wait_q);
}
if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC)) if (irb->scsw.cmd.fctl & SCSW_FCTL_HALT_FUNC) {
channel->state = CH_STATE_HALTED; channel->state = CH_STATE_HALTED;
wake_up(&card->wait_q);
}
if (iob && (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC | if (iob && (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC |
SCSW_FCTL_HALT_FUNC))) { SCSW_FCTL_HALT_FUNC))) {
...@@ -1054,7 +1052,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, ...@@ -1054,7 +1052,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
qeth_cancel_cmd(iob, rc); qeth_cancel_cmd(iob, rc);
qeth_clear_ipacmd_list(card); qeth_clear_ipacmd_list(card);
qeth_schedule_recovery(card); qeth_schedule_recovery(card);
goto out; return;
} }
} }
...@@ -1062,16 +1060,12 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, ...@@ -1062,16 +1060,12 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
/* sanity check: */ /* sanity check: */
if (irb->scsw.cmd.count > iob->length) { if (irb->scsw.cmd.count > iob->length) {
qeth_cancel_cmd(iob, -EIO); qeth_cancel_cmd(iob, -EIO);
goto out; return;
} }
if (iob->callback) if (iob->callback)
iob->callback(card, iob, iob->callback(card, iob,
iob->length - irb->scsw.cmd.count); iob->length - irb->scsw.cmd.count);
} }
out:
wake_up(&card->wait_q);
return;
} }
static void qeth_notify_skbs(struct qeth_qdio_out_q *q, static void qeth_notify_skbs(struct qeth_qdio_out_q *q,
...@@ -1198,31 +1192,6 @@ static void qeth_free_buffer_pool(struct qeth_card *card) ...@@ -1198,31 +1192,6 @@ static void qeth_free_buffer_pool(struct qeth_card *card)
} }
} }
static void qeth_clean_channel(struct qeth_channel *channel)
{
struct ccw_device *cdev = channel->ccwdev;
QETH_DBF_TEXT(SETUP, 2, "freech");
spin_lock_irq(get_ccwdev_lock(cdev));
cdev->handler = NULL;
spin_unlock_irq(get_ccwdev_lock(cdev));
}
static void qeth_setup_channel(struct qeth_channel *channel)
{
struct ccw_device *cdev = channel->ccwdev;
QETH_DBF_TEXT(SETUP, 2, "setupch");
channel->state = CH_STATE_DOWN;
atomic_set(&channel->irq_pending, 0);
spin_lock_irq(get_ccwdev_lock(cdev));
cdev->handler = qeth_irq;
spin_unlock_irq(get_ccwdev_lock(cdev));
}
static int qeth_osa_set_output_queues(struct qeth_card *card, bool single) static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
{ {
unsigned int count = single ? 1 : card->dev->num_tx_queues; unsigned int count = single ? 1 : card->dev->num_tx_queues;
...@@ -1395,9 +1364,6 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev) ...@@ -1395,9 +1364,6 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
if (!card->read_cmd) if (!card->read_cmd)
goto out_read_cmd; goto out_read_cmd;
qeth_setup_channel(&card->read);
qeth_setup_channel(&card->write);
qeth_setup_channel(&card->data);
card->qeth_service_level.seq_print = qeth_core_sl_print; card->qeth_service_level.seq_print = qeth_core_sl_print;
register_service_level(&card->qeth_service_level); register_service_level(&card->qeth_service_level);
return card; return card;
...@@ -1467,12 +1433,38 @@ int qeth_stop_channel(struct qeth_channel *channel) ...@@ -1467,12 +1433,38 @@ int qeth_stop_channel(struct qeth_channel *channel)
channel->active_cmd); channel->active_cmd);
channel->active_cmd = NULL; channel->active_cmd = NULL;
} }
cdev->handler = NULL;
spin_unlock_irq(get_ccwdev_lock(cdev)); spin_unlock_irq(get_ccwdev_lock(cdev));
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(qeth_stop_channel); EXPORT_SYMBOL_GPL(qeth_stop_channel);
static int qeth_start_channel(struct qeth_channel *channel)
{
struct ccw_device *cdev = channel->ccwdev;
int rc;
channel->state = CH_STATE_DOWN;
atomic_set(&channel->irq_pending, 0);
spin_lock_irq(get_ccwdev_lock(cdev));
cdev->handler = qeth_irq;
spin_unlock_irq(get_ccwdev_lock(cdev));
rc = ccw_device_set_online(cdev);
if (rc)
goto err;
return 0;
err:
spin_lock_irq(get_ccwdev_lock(cdev));
cdev->handler = NULL;
spin_unlock_irq(get_ccwdev_lock(cdev));
return rc;
}
static int qeth_halt_channels(struct qeth_card *card) static int qeth_halt_channels(struct qeth_card *card)
{ {
int rc1 = 0, rc2 = 0, rc3 = 0; int rc1 = 0, rc2 = 0, rc3 = 0;
...@@ -1784,8 +1776,7 @@ static int qeth_send_control_data(struct qeth_card *card, ...@@ -1784,8 +1776,7 @@ static int qeth_send_control_data(struct qeth_card *card,
QETH_CARD_TEXT_(card, 2, " err%d", rc); QETH_CARD_TEXT_(card, 2, " err%d", rc);
qeth_dequeue_cmd(card, iob); qeth_dequeue_cmd(card, iob);
qeth_put_cmd(iob); qeth_put_cmd(iob);
atomic_set(&channel->irq_pending, 0); qeth_unlock_channel(card, channel);
wake_up(&card->wait_q);
goto out; goto out;
} }
...@@ -2871,7 +2862,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card, ...@@ -2871,7 +2862,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
cmd->data.setadapterparms.data.query_cmds_supp.lan_type; cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
QETH_CARD_TEXT_(card, 2, "lnk %d", card->info.link_type); QETH_CARD_TEXT_(card, 2, "lnk %d", card->info.link_type);
} }
card->options.adp.supported_funcs = card->options.adp.supported =
cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds; cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
return 0; return 0;
} }
...@@ -2927,8 +2918,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, ...@@ -2927,8 +2918,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
case IPA_RC_NOTSUPP: case IPA_RC_NOTSUPP:
case IPA_RC_L2_UNSUPPORTED_CMD: case IPA_RC_L2_UNSUPPORTED_CMD:
QETH_CARD_TEXT(card, 2, "ipaunsup"); QETH_CARD_TEXT(card, 2, "ipaunsup");
card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS; card->options.ipa4.supported |= IPA_SETADAPTERPARMS;
card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS; card->options.ipa6.supported |= IPA_SETADAPTERPARMS;
return -EOPNOTSUPP; return -EOPNOTSUPP;
default: default:
QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n", QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n",
...@@ -2936,13 +2927,11 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, ...@@ -2936,13 +2927,11 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
return -EIO; return -EIO;
} }
if (cmd->hdr.prot_version == QETH_PROT_IPV4) { if (cmd->hdr.prot_version == QETH_PROT_IPV4)
card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa4 = cmd->hdr.assists;
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; else if (cmd->hdr.prot_version == QETH_PROT_IPV6)
} else if (cmd->hdr.prot_version == QETH_PROT_IPV6) { card->options.ipa6 = cmd->hdr.assists;
card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; else
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
} else
QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Flawed LIC detected\n", QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Flawed LIC detected\n",
CARD_DEVID(card)); CARD_DEVID(card));
return 0; return 0;
...@@ -3413,7 +3402,7 @@ static void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, ...@@ -3413,7 +3402,7 @@ static void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
struct qeth_card *card = (struct qeth_card *)card_ptr; struct qeth_card *card = (struct qeth_card *)card_ptr;
if (card->dev->flags & IFF_UP) if (card->dev->flags & IFF_UP)
napi_schedule(&card->napi); napi_schedule_irqoff(&card->napi);
} }
int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
...@@ -4706,7 +4695,7 @@ static void qeth_determine_capabilities(struct qeth_card *card) ...@@ -4706,7 +4695,7 @@ static void qeth_determine_capabilities(struct qeth_card *card)
QETH_CARD_TEXT(card, 2, "detcapab"); QETH_CARD_TEXT(card, 2, "detcapab");
if (!ddev->online) { if (!ddev->online) {
ddev_offline = 1; ddev_offline = 1;
rc = ccw_device_set_online(ddev); rc = qeth_start_channel(channel);
if (rc) { if (rc) {
QETH_CARD_TEXT_(card, 2, "3err%d", rc); QETH_CARD_TEXT_(card, 2, "3err%d", rc);
goto out; goto out;
...@@ -4881,9 +4870,6 @@ static int qeth_qdio_establish(struct qeth_card *card) ...@@ -4881,9 +4870,6 @@ static int qeth_qdio_establish(struct qeth_card *card)
static void qeth_core_free_card(struct qeth_card *card) static void qeth_core_free_card(struct qeth_card *card)
{ {
QETH_CARD_TEXT(card, 2, "freecrd"); QETH_CARD_TEXT(card, 2, "freecrd");
qeth_clean_channel(&card->read);
qeth_clean_channel(&card->write);
qeth_clean_channel(&card->data);
qeth_put_cmd(card->read_cmd); qeth_put_cmd(card->read_cmd);
destroy_workqueue(card->event_wq); destroy_workqueue(card->event_wq);
unregister_service_level(&card->qeth_service_level); unregister_service_level(&card->qeth_service_level);
...@@ -4946,13 +4932,14 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok) ...@@ -4946,13 +4932,14 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
qeth_stop_channel(&card->write); qeth_stop_channel(&card->write);
qeth_stop_channel(&card->read); qeth_stop_channel(&card->read);
qdio_free(CARD_DDEV(card)); qdio_free(CARD_DDEV(card));
rc = ccw_device_set_online(CARD_RDEV(card));
rc = qeth_start_channel(&card->read);
if (rc) if (rc)
goto retriable; goto retriable;
rc = ccw_device_set_online(CARD_WDEV(card)); rc = qeth_start_channel(&card->write);
if (rc) if (rc)
goto retriable; goto retriable;
rc = ccw_device_set_online(CARD_DDEV(card)); rc = qeth_start_channel(&card->data);
if (rc) if (rc)
goto retriable; goto retriable;
retriable: retriable:
...@@ -5013,9 +5000,9 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok) ...@@ -5013,9 +5000,9 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
*carrier_ok = true; *carrier_ok = true;
} }
card->options.ipa4.supported_funcs = 0; card->options.ipa4.supported = 0;
card->options.ipa6.supported_funcs = 0; card->options.ipa6.supported = 0;
card->options.adp.supported_funcs = 0; card->options.adp.supported = 0;
card->options.sbp.supported_funcs = 0; card->options.sbp.supported_funcs = 0;
card->info.diagass_support = 0; card->info.diagass_support = 0;
rc = qeth_query_ipassists(card, QETH_PROT_IPV4); rc = qeth_query_ipassists(card, QETH_PROT_IPV4);
...@@ -5432,9 +5419,9 @@ int qeth_setassparms_cb(struct qeth_card *card, ...@@ -5432,9 +5419,9 @@ int qeth_setassparms_cb(struct qeth_card *card,
cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
if (cmd->hdr.prot_version == QETH_PROT_IPV4) if (cmd->hdr.prot_version == QETH_PROT_IPV4)
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; card->options.ipa4.enabled = cmd->hdr.assists.enabled;
if (cmd->hdr.prot_version == QETH_PROT_IPV6) if (cmd->hdr.prot_version == QETH_PROT_IPV6)
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; card->options.ipa6.enabled = cmd->hdr.assists.enabled;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(qeth_setassparms_cb); EXPORT_SYMBOL_GPL(qeth_setassparms_cb);
......
...@@ -53,6 +53,16 @@ static inline bool qeth_ipa_caps_enabled(struct qeth_ipa_caps *caps, u32 mask) ...@@ -53,6 +53,16 @@ static inline bool qeth_ipa_caps_enabled(struct qeth_ipa_caps *caps, u32 mask)
return (caps->enabled & mask) == mask; return (caps->enabled & mask) == mask;
} }
#define qeth_adp_supported(c, f) \
qeth_ipa_caps_supported(&c->options.adp, f)
#define qeth_is_supported(c, f) \
qeth_ipa_caps_supported(&c->options.ipa4, f)
#define qeth_is_supported6(c, f) \
qeth_ipa_caps_supported(&c->options.ipa6, f)
#define qeth_is_ipafunc_supported(c, prot, f) \
((prot == QETH_PROT_IPV6) ? qeth_is_supported6(c, f) : \
qeth_is_supported(c, f))
enum qeth_card_types { enum qeth_card_types {
QETH_CARD_TYPE_OSD = 1, QETH_CARD_TYPE_OSD = 1,
QETH_CARD_TYPE_IQD = 5, QETH_CARD_TYPE_IQD = 5,
...@@ -338,14 +348,14 @@ enum qeth_card_info_port_speed { ...@@ -338,14 +348,14 @@ enum qeth_card_info_port_speed {
/* (SET)DELIP(M) IPA stuff ***************************************************/ /* (SET)DELIP(M) IPA stuff ***************************************************/
struct qeth_ipacmd_setdelip4 { struct qeth_ipacmd_setdelip4 {
__u8 ip_addr[4]; __be32 addr;
__u8 mask[4]; __be32 mask;
__u32 flags; __u32 flags;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct qeth_ipacmd_setdelip6 { struct qeth_ipacmd_setdelip6 {
__u8 ip_addr[16]; struct in6_addr addr;
__u8 mask[16]; struct in6_addr prefix;
__u32 flags; __u32 flags;
} __attribute__ ((packed)); } __attribute__ ((packed));
...@@ -766,8 +776,7 @@ struct qeth_ipacmd_hdr { ...@@ -766,8 +776,7 @@ struct qeth_ipacmd_hdr {
__u8 prim_version_no; __u8 prim_version_no;
__u8 param_count; __u8 param_count;
__u16 prot_version; __u16 prot_version;
__u32 ipa_supported; struct qeth_ipa_caps assists;
__u32 ipa_enabled;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* The IPA command itself */ /* The IPA command itself */
......
...@@ -23,7 +23,6 @@ struct qeth_ipaddr { ...@@ -23,7 +23,6 @@ struct qeth_ipaddr {
struct hlist_node hnode; struct hlist_node hnode;
enum qeth_ip_types type; enum qeth_ip_types type;
u8 is_multicast:1; u8 is_multicast:1;
u8 in_progress:1;
u8 disp_flag:2; u8 disp_flag:2;
u8 ipato:1; /* ucast only */ u8 ipato:1; /* ucast only */
...@@ -35,7 +34,7 @@ struct qeth_ipaddr { ...@@ -35,7 +34,7 @@ struct qeth_ipaddr {
union { union {
struct { struct {
__be32 addr; __be32 addr;
unsigned int mask; __be32 mask;
} a4; } a4;
struct { struct {
struct in6_addr addr; struct in6_addr addr;
...@@ -102,7 +101,8 @@ struct qeth_ipato_entry { ...@@ -102,7 +101,8 @@ struct qeth_ipato_entry {
extern const struct attribute_group *qeth_l3_attr_groups[]; extern const struct attribute_group *qeth_l3_attr_groups[];
void qeth_l3_ipaddr_to_string(enum qeth_prot_versions, const __u8 *, char *); int qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const u8 *addr,
char *buf);
int qeth_l3_create_device_attributes(struct device *); int qeth_l3_create_device_attributes(struct device *);
void qeth_l3_remove_device_attributes(struct device *); void qeth_l3_remove_device_attributes(struct device *);
int qeth_l3_setrouting_v4(struct qeth_card *); int qeth_l3_setrouting_v4(struct qeth_card *);
......
...@@ -44,23 +44,13 @@ static int qeth_l3_register_addr_entry(struct qeth_card *, ...@@ -44,23 +44,13 @@ static int qeth_l3_register_addr_entry(struct qeth_card *,
static int qeth_l3_deregister_addr_entry(struct qeth_card *, static int qeth_l3_deregister_addr_entry(struct qeth_card *,
struct qeth_ipaddr *); struct qeth_ipaddr *);
static void qeth_l3_ipaddr4_to_string(const __u8 *addr, char *buf) int qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const u8 *addr,
{ char *buf)
sprintf(buf, "%pI4", addr);
}
static void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf)
{
sprintf(buf, "%pI6", addr);
}
void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
char *buf)
{ {
if (proto == QETH_PROT_IPV4) if (proto == QETH_PROT_IPV4)
qeth_l3_ipaddr4_to_string(addr, buf); return sprintf(buf, "%pI4", addr);
else if (proto == QETH_PROT_IPV6) else
qeth_l3_ipaddr6_to_string(addr, buf); return sprintf(buf, "%pI6", addr);
} }
static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card, static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card,
...@@ -161,8 +151,6 @@ static int qeth_l3_delete_ip(struct qeth_card *card, ...@@ -161,8 +151,6 @@ static int qeth_l3_delete_ip(struct qeth_card *card,
addr->ref_counter--; addr->ref_counter--;
if (addr->type == QETH_IP_TYPE_NORMAL && addr->ref_counter > 0) if (addr->type == QETH_IP_TYPE_NORMAL && addr->ref_counter > 0)
return rc; return rc;
if (addr->in_progress)
return -EINPROGRESS;
if (qeth_card_hw_is_reachable(card)) if (qeth_card_hw_is_reachable(card))
rc = qeth_l3_deregister_addr_entry(card, addr); rc = qeth_l3_deregister_addr_entry(card, addr);
...@@ -223,29 +211,10 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) ...@@ -223,29 +211,10 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
return 0; return 0;
} }
/* qeth_l3_register_addr_entry can go to sleep rc = qeth_l3_register_addr_entry(card, addr);
* if we add a IPV4 addr. It is caused by the reason
* that SETIP ipa cmd starts ARP staff for IPV4 addr.
* Thus we should unlock spinlock, and make a protection
* using in_progress variable to indicate that there is
* an hardware operation with this IPV4 address
*/
if (addr->proto == QETH_PROT_IPV4) {
addr->in_progress = 1;
mutex_unlock(&card->ip_lock);
rc = qeth_l3_register_addr_entry(card, addr);
mutex_lock(&card->ip_lock);
addr->in_progress = 0;
} else
rc = qeth_l3_register_addr_entry(card, addr);
if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) { if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
if (addr->ref_counter < 1) {
qeth_l3_deregister_addr_entry(card, addr);
hash_del(&addr->hnode);
kfree(addr);
}
} else { } else {
hash_del(&addr->hnode); hash_del(&addr->hnode);
kfree(addr); kfree(addr);
...@@ -313,19 +282,10 @@ static void qeth_l3_recover_ip(struct qeth_card *card) ...@@ -313,19 +282,10 @@ static void qeth_l3_recover_ip(struct qeth_card *card)
hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) { hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) {
if (addr->disp_flag == QETH_DISP_ADDR_ADD) { if (addr->disp_flag == QETH_DISP_ADDR_ADD) {
if (addr->proto == QETH_PROT_IPV4) { rc = qeth_l3_register_addr_entry(card, addr);
addr->in_progress = 1;
mutex_unlock(&card->ip_lock);
rc = qeth_l3_register_addr_entry(card, addr);
mutex_lock(&card->ip_lock);
addr->in_progress = 0;
} else
rc = qeth_l3_register_addr_entry(card, addr);
if (!rc) { if (!rc) {
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
if (addr->ref_counter < 1)
qeth_l3_delete_ip(card, addr);
} else { } else {
hash_del(&addr->hnode); hash_del(&addr->hnode);
kfree(addr); kfree(addr);
...@@ -379,17 +339,16 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card, ...@@ -379,17 +339,16 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL); return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL);
} }
static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len) static void qeth_l3_set_ipv6_prefix(struct in6_addr *prefix, unsigned int len)
{ {
int i, j; unsigned int i = 0;
for (i = 0; i < 16; i++) {
j = (len) - (i * 8); while (len && i < 4) {
if (j >= 8) int mask_len = min_t(int, len, 32);
netmask[i] = 0xff;
else if (j > 0) prefix->s6_addr32[i] = inet_make_mask(mask_len);
netmask[i] = (u8)(0xFF00 >> j); len -= mask_len;
else i++;
netmask[i] = 0;
} }
} }
...@@ -412,7 +371,6 @@ static int qeth_l3_send_setdelip(struct qeth_card *card, ...@@ -412,7 +371,6 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
{ {
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd; struct qeth_ipa_cmd *cmd;
__u8 netmask[16];
u32 flags; u32 flags;
QETH_CARD_TEXT(card, 4, "setdelip"); QETH_CARD_TEXT(card, 4, "setdelip");
...@@ -427,15 +385,13 @@ static int qeth_l3_send_setdelip(struct qeth_card *card, ...@@ -427,15 +385,13 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
QETH_CARD_TEXT_(card, 4, "flags%02X", flags); QETH_CARD_TEXT_(card, 4, "flags%02X", flags);
if (addr->proto == QETH_PROT_IPV6) { if (addr->proto == QETH_PROT_IPV6) {
memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr, cmd->data.setdelip6.addr = addr->u.a6.addr;
sizeof(struct in6_addr)); qeth_l3_set_ipv6_prefix(&cmd->data.setdelip6.prefix,
qeth_l3_fill_netmask(netmask, addr->u.a6.pfxlen); addr->u.a6.pfxlen);
memcpy(cmd->data.setdelip6.mask, netmask,
sizeof(struct in6_addr));
cmd->data.setdelip6.flags = flags; cmd->data.setdelip6.flags = flags;
} else { } else {
memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4); cmd->data.setdelip4.addr = addr->u.a4.addr;
memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4); cmd->data.setdelip4.mask = addr->u.a4.mask;
cmd->data.setdelip4.flags = flags; cmd->data.setdelip4.flags = flags;
} }
...@@ -581,6 +537,7 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card, ...@@ -581,6 +537,7 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "addipato"); QETH_CARD_TEXT(card, 2, "addipato");
mutex_lock(&card->conf_mutex);
mutex_lock(&card->ip_lock); mutex_lock(&card->ip_lock);
list_for_each_entry(ipatoe, &card->ipato.entries, entry) { list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
...@@ -600,6 +557,7 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card, ...@@ -600,6 +557,7 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card,
} }
mutex_unlock(&card->ip_lock); mutex_unlock(&card->ip_lock);
mutex_unlock(&card->conf_mutex);
return rc; return rc;
} }
...@@ -613,6 +571,7 @@ int qeth_l3_del_ipato_entry(struct qeth_card *card, ...@@ -613,6 +571,7 @@ int qeth_l3_del_ipato_entry(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "delipato"); QETH_CARD_TEXT(card, 2, "delipato");
mutex_lock(&card->conf_mutex);
mutex_lock(&card->ip_lock); mutex_lock(&card->ip_lock);
list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) { list_for_each_entry_safe(ipatoe, tmp, &card->ipato.entries, entry) {
...@@ -629,6 +588,8 @@ int qeth_l3_del_ipato_entry(struct qeth_card *card, ...@@ -629,6 +588,8 @@ int qeth_l3_del_ipato_entry(struct qeth_card *card,
} }
mutex_unlock(&card->ip_lock); mutex_unlock(&card->ip_lock);
mutex_unlock(&card->conf_mutex);
return rc; return rc;
} }
...@@ -637,6 +598,7 @@ int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip, ...@@ -637,6 +598,7 @@ int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip,
enum qeth_prot_versions proto) enum qeth_prot_versions proto)
{ {
struct qeth_ipaddr addr; struct qeth_ipaddr addr;
int rc;
qeth_l3_init_ipaddr(&addr, type, proto); qeth_l3_init_ipaddr(&addr, type, proto);
if (proto == QETH_PROT_IPV4) if (proto == QETH_PROT_IPV4)
...@@ -644,7 +606,11 @@ int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip, ...@@ -644,7 +606,11 @@ int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip,
else else
memcpy(&addr.u.a6.addr, ip, 16); memcpy(&addr.u.a6.addr, ip, 16);
return qeth_l3_modify_ip(card, &addr, add); mutex_lock(&card->conf_mutex);
rc = qeth_l3_modify_ip(card, &addr, add);
mutex_unlock(&card->conf_mutex);
return rc;
} }
int qeth_l3_modify_hsuid(struct qeth_card *card, bool add) int qeth_l3_modify_hsuid(struct qeth_card *card, bool add)
...@@ -2292,12 +2258,6 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, ...@@ -2292,12 +2258,6 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
rtnl_unlock(); rtnl_unlock();
qeth_l3_stop_card(card); qeth_l3_stop_card(card);
if (card->options.cq == QETH_CQ_ENABLED) {
rtnl_lock();
call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
rtnl_unlock();
}
rc = qeth_stop_channel(&card->data); rc = qeth_stop_channel(&card->data);
rc2 = qeth_stop_channel(&card->write); rc2 = qeth_stop_channel(&card->write);
rc3 = qeth_stop_channel(&card->read); rc3 = qeth_stop_channel(&card->read);
...@@ -2436,7 +2396,7 @@ static int qeth_l3_ip_event(struct notifier_block *this, ...@@ -2436,7 +2396,7 @@ static int qeth_l3_ip_event(struct notifier_block *this,
qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV4); qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV4);
addr.u.a4.addr = ifa->ifa_address; addr.u.a4.addr = ifa->ifa_address;
addr.u.a4.mask = be32_to_cpu(ifa->ifa_mask); addr.u.a4.mask = ifa->ifa_mask;
return qeth_l3_handle_ip_event(card, &addr, event); return qeth_l3_handle_ip_event(card, &addr, event);
} }
......
This diff is collapsed.
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