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 {
enum qeth_routing_types type;
};
/* IPA stuff */
struct qeth_ipa_info {
__u32 supported_funcs;
__u32 enabled_funcs;
};
/* SETBRIDGEPORT stuff */
enum qeth_sbp_roles {
QETH_SBP_ROLE_NONE = 0,
......@@ -169,41 +163,6 @@ struct qeth_vnicc_info {
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_IQD 0x4108
......@@ -735,11 +694,11 @@ enum qeth_discipline_id {
};
struct qeth_card_options {
struct qeth_ipa_caps ipa4;
struct qeth_ipa_caps ipa6;
struct qeth_routing_info route4;
struct qeth_ipa_info ipa4;
struct qeth_ipa_info adp; /*Adapter parameters*/
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_vnicc_info vnicc; /* VNICC options */
int fake_broadcast;
......@@ -862,6 +821,13 @@ static inline bool qeth_card_hw_is_reachable(struct qeth_card *card)
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 {
__u16 lparnr;
char vmname[8];
......
......@@ -520,11 +520,10 @@ static int __qeth_issue_next_read(struct qeth_card *card)
} else {
QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
rc, CARD_DEVID(card));
atomic_set(&channel->irq_pending, 0);
qeth_unlock_channel(card, channel);
qeth_put_cmd(iob);
card->read_or_write_problem = 1;
qeth_schedule_recovery(card);
wake_up(&card->wait_q);
}
return rc;
}
......@@ -972,8 +971,6 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
/* while we hold the ccwdev lock, this stays valid: */
gdev = dev_get_drvdata(&cdev->dev);
card = dev_get_drvdata(&gdev->dev);
if (!card)
return;
QETH_CARD_TEXT(card, 5, "irq");
......@@ -1003,24 +1000,25 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
}
channel->active_cmd = NULL;
qeth_unlock_channel(card, channel);
rc = qeth_check_irb_error(card, cdev, irb);
if (rc) {
/* IO was terminated, free its resources. */
if (iob)
qeth_cancel_cmd(iob, rc);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
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;
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;
wake_up(&card->wait_q);
}
if (iob && (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC |
SCSW_FCTL_HALT_FUNC))) {
......@@ -1054,7 +1052,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
qeth_cancel_cmd(iob, rc);
qeth_clear_ipacmd_list(card);
qeth_schedule_recovery(card);
goto out;
return;
}
}
......@@ -1062,16 +1060,12 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
/* sanity check: */
if (irb->scsw.cmd.count > iob->length) {
qeth_cancel_cmd(iob, -EIO);
goto out;
return;
}
if (iob->callback)
iob->callback(card, iob,
iob->length - irb->scsw.cmd.count);
}
out:
wake_up(&card->wait_q);
return;
}
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)
}
}
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)
{
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)
if (!card->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;
register_service_level(&card->qeth_service_level);
return card;
......@@ -1467,12 +1433,38 @@ int qeth_stop_channel(struct qeth_channel *channel)
channel->active_cmd);
channel->active_cmd = NULL;
}
cdev->handler = NULL;
spin_unlock_irq(get_ccwdev_lock(cdev));
return rc;
}
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)
{
int rc1 = 0, rc2 = 0, rc3 = 0;
......@@ -1784,8 +1776,7 @@ static int qeth_send_control_data(struct qeth_card *card,
QETH_CARD_TEXT_(card, 2, " err%d", rc);
qeth_dequeue_cmd(card, iob);
qeth_put_cmd(iob);
atomic_set(&channel->irq_pending, 0);
wake_up(&card->wait_q);
qeth_unlock_channel(card, channel);
goto out;
}
......@@ -2871,7 +2862,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
cmd->data.setadapterparms.data.query_cmds_supp.lan_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;
return 0;
}
......@@ -2927,8 +2918,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
case IPA_RC_NOTSUPP:
case IPA_RC_L2_UNSUPPORTED_CMD:
QETH_CARD_TEXT(card, 2, "ipaunsup");
card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
card->options.ipa4.supported |= IPA_SETADAPTERPARMS;
card->options.ipa6.supported |= IPA_SETADAPTERPARMS;
return -EOPNOTSUPP;
default:
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,
return -EIO;
}
if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
} else if (cmd->hdr.prot_version == QETH_PROT_IPV6) {
card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
} else
if (cmd->hdr.prot_version == QETH_PROT_IPV4)
card->options.ipa4 = cmd->hdr.assists;
else if (cmd->hdr.prot_version == QETH_PROT_IPV6)
card->options.ipa6 = cmd->hdr.assists;
else
QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Flawed LIC detected\n",
CARD_DEVID(card));
return 0;
......@@ -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;
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)
......@@ -4706,7 +4695,7 @@ static void qeth_determine_capabilities(struct qeth_card *card)
QETH_CARD_TEXT(card, 2, "detcapab");
if (!ddev->online) {
ddev_offline = 1;
rc = ccw_device_set_online(ddev);
rc = qeth_start_channel(channel);
if (rc) {
QETH_CARD_TEXT_(card, 2, "3err%d", rc);
goto out;
......@@ -4881,9 +4870,6 @@ static int qeth_qdio_establish(struct qeth_card *card)
static void qeth_core_free_card(struct qeth_card *card)
{
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);
destroy_workqueue(card->event_wq);
unregister_service_level(&card->qeth_service_level);
......@@ -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->read);
qdio_free(CARD_DDEV(card));
rc = ccw_device_set_online(CARD_RDEV(card));
rc = qeth_start_channel(&card->read);
if (rc)
goto retriable;
rc = ccw_device_set_online(CARD_WDEV(card));
rc = qeth_start_channel(&card->write);
if (rc)
goto retriable;
rc = ccw_device_set_online(CARD_DDEV(card));
rc = qeth_start_channel(&card->data);
if (rc)
goto retriable;
retriable:
......@@ -5013,9 +5000,9 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
*carrier_ok = true;
}
card->options.ipa4.supported_funcs = 0;
card->options.ipa6.supported_funcs = 0;
card->options.adp.supported_funcs = 0;
card->options.ipa4.supported = 0;
card->options.ipa6.supported = 0;
card->options.adp.supported = 0;
card->options.sbp.supported_funcs = 0;
card->info.diagass_support = 0;
rc = qeth_query_ipassists(card, QETH_PROT_IPV4);
......@@ -5432,9 +5419,9 @@ int qeth_setassparms_cb(struct qeth_card *card,
cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code;
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)
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
card->options.ipa6.enabled = cmd->hdr.assists.enabled;
return 0;
}
EXPORT_SYMBOL_GPL(qeth_setassparms_cb);
......
......@@ -53,6 +53,16 @@ static inline bool qeth_ipa_caps_enabled(struct qeth_ipa_caps *caps, u32 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 {
QETH_CARD_TYPE_OSD = 1,
QETH_CARD_TYPE_IQD = 5,
......@@ -338,14 +348,14 @@ enum qeth_card_info_port_speed {
/* (SET)DELIP(M) IPA stuff ***************************************************/
struct qeth_ipacmd_setdelip4 {
__u8 ip_addr[4];
__u8 mask[4];
__be32 addr;
__be32 mask;
__u32 flags;
} __attribute__ ((packed));
struct qeth_ipacmd_setdelip6 {
__u8 ip_addr[16];
__u8 mask[16];
struct in6_addr addr;
struct in6_addr prefix;
__u32 flags;
} __attribute__ ((packed));
......@@ -766,8 +776,7 @@ struct qeth_ipacmd_hdr {
__u8 prim_version_no;
__u8 param_count;
__u16 prot_version;
__u32 ipa_supported;
__u32 ipa_enabled;
struct qeth_ipa_caps assists;
} __attribute__ ((packed));
/* The IPA command itself */
......
......@@ -23,7 +23,6 @@ struct qeth_ipaddr {
struct hlist_node hnode;
enum qeth_ip_types type;
u8 is_multicast:1;
u8 in_progress:1;
u8 disp_flag:2;
u8 ipato:1; /* ucast only */
......@@ -35,7 +34,7 @@ struct qeth_ipaddr {
union {
struct {
__be32 addr;
unsigned int mask;
__be32 mask;
} a4;
struct {
struct in6_addr addr;
......@@ -102,7 +101,8 @@ struct qeth_ipato_entry {
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 *);
void qeth_l3_remove_device_attributes(struct device *);
int qeth_l3_setrouting_v4(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 *,
struct qeth_ipaddr *);
static void qeth_l3_ipaddr4_to_string(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)
int qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const u8 *addr,
char *buf)
{
if (proto == QETH_PROT_IPV4)
qeth_l3_ipaddr4_to_string(addr, buf);
else if (proto == QETH_PROT_IPV6)
qeth_l3_ipaddr6_to_string(addr, buf);
return sprintf(buf, "%pI4", addr);
else
return sprintf(buf, "%pI6", addr);
}
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,
addr->ref_counter--;
if (addr->type == QETH_IP_TYPE_NORMAL && addr->ref_counter > 0)
return rc;
if (addr->in_progress)
return -EINPROGRESS;
if (qeth_card_hw_is_reachable(card))
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)
return 0;
}
/* qeth_l3_register_addr_entry can go to sleep
* 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);
rc = qeth_l3_register_addr_entry(card, addr);
if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
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 {
hash_del(&addr->hnode);
kfree(addr);
......@@ -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) {
if (addr->disp_flag == QETH_DISP_ADDR_ADD) {
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);
rc = qeth_l3_register_addr_entry(card, addr);
if (!rc) {
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
if (addr->ref_counter < 1)
qeth_l3_delete_ip(card, addr);
} else {
hash_del(&addr->hnode);
kfree(addr);
......@@ -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);
}
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;
for (i = 0; i < 16; i++) {
j = (len) - (i * 8);
if (j >= 8)
netmask[i] = 0xff;
else if (j > 0)
netmask[i] = (u8)(0xFF00 >> j);
else
netmask[i] = 0;
unsigned int i = 0;
while (len && i < 4) {
int mask_len = min_t(int, len, 32);
prefix->s6_addr32[i] = inet_make_mask(mask_len);
len -= mask_len;
i++;
}
}
......@@ -412,7 +371,6 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
{
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
__u8 netmask[16];
u32 flags;
QETH_CARD_TEXT(card, 4, "setdelip");
......@@ -427,15 +385,13 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
QETH_CARD_TEXT_(card, 4, "flags%02X", flags);
if (addr->proto == QETH_PROT_IPV6) {
memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
sizeof(struct in6_addr));
qeth_l3_fill_netmask(netmask, addr->u.a6.pfxlen);
memcpy(cmd->data.setdelip6.mask, netmask,
sizeof(struct in6_addr));
cmd->data.setdelip6.addr = addr->u.a6.addr;
qeth_l3_set_ipv6_prefix(&cmd->data.setdelip6.prefix,
addr->u.a6.pfxlen);
cmd->data.setdelip6.flags = flags;
} else {
memcpy(cmd->data.setdelip4.ip_addr, &addr->u.a4.addr, 4);
memcpy(cmd->data.setdelip4.mask, &addr->u.a4.mask, 4);
cmd->data.setdelip4.addr = addr->u.a4.addr;
cmd->data.setdelip4.mask = addr->u.a4.mask;
cmd->data.setdelip4.flags = flags;
}
......@@ -581,6 +537,7 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "addipato");
mutex_lock(&card->conf_mutex);
mutex_lock(&card->ip_lock);
list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
......@@ -600,6 +557,7 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card,
}
mutex_unlock(&card->ip_lock);
mutex_unlock(&card->conf_mutex);
return rc;
}
......@@ -613,6 +571,7 @@ int qeth_l3_del_ipato_entry(struct qeth_card *card,
QETH_CARD_TEXT(card, 2, "delipato");
mutex_lock(&card->conf_mutex);
mutex_lock(&card->ip_lock);
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,
}
mutex_unlock(&card->ip_lock);
mutex_unlock(&card->conf_mutex);
return rc;
}
......@@ -637,6 +598,7 @@ int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip,
enum qeth_prot_versions proto)
{
struct qeth_ipaddr addr;
int rc;
qeth_l3_init_ipaddr(&addr, type, proto);
if (proto == QETH_PROT_IPV4)
......@@ -644,7 +606,11 @@ int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip,
else
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)
......@@ -2292,12 +2258,6 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
rtnl_unlock();
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);
rc2 = qeth_stop_channel(&card->write);
rc3 = qeth_stop_channel(&card->read);
......@@ -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);
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);
}
......
......@@ -386,30 +386,35 @@ static ssize_t qeth_l3_dev_ipato_add_show(char *buf, struct qeth_card *card,
enum qeth_prot_versions proto)
{
struct qeth_ipato_entry *ipatoe;
char addr_str[40];
int entry_len; /* length of 1 entry string, differs between v4 and v6 */
int i = 0;
int str_len = 0;
entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
/* add strlen for "/<mask>\n" */
entry_len += (proto == QETH_PROT_IPV4)? 5 : 6;
mutex_lock(&card->ip_lock);
list_for_each_entry(ipatoe, &card->ipato.entries, entry) {
char addr_str[40];
int entry_len;
if (ipatoe->proto != proto)
continue;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE. Then we can savely display
* the next IPv6 address (worst case, compared to IPv4) */
if ((PAGE_SIZE - i) <= entry_len)
entry_len = qeth_l3_ipaddr_to_string(proto, ipatoe->addr,
addr_str);
if (entry_len < 0)
continue;
/* Append /%mask to the entry: */
entry_len += 1 + ((proto == QETH_PROT_IPV4) ? 2 : 3);
/* Enough room to format %entry\n into null terminated page? */
if (entry_len + 1 > PAGE_SIZE - str_len - 1)
break;
qeth_l3_ipaddr_to_string(proto, ipatoe->addr, addr_str);
i += snprintf(buf + i, PAGE_SIZE - i,
"%s/%i\n", addr_str, ipatoe->mask_bits);
entry_len = scnprintf(buf, PAGE_SIZE - str_len,
"%s/%i\n", addr_str, ipatoe->mask_bits);
str_len += entry_len;
buf += entry_len;
}
mutex_unlock(&card->ip_lock);
i += snprintf(buf + i, PAGE_SIZE - i, "\n");
return i;
return str_len ? str_len : scnprintf(buf, PAGE_SIZE, "\n");
}
static ssize_t qeth_l3_dev_ipato_add4_show(struct device *dev,
......@@ -455,16 +460,14 @@ static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
int mask_bits;
int rc = 0;
mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
if (rc)
goto out;
return rc;
ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
if (!ipatoe) {
rc = -ENOMEM;
goto out;
}
if (!ipatoe)
return -ENOMEM;
ipatoe->proto = proto;
memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
ipatoe->mask_bits = mask_bits;
......@@ -472,8 +475,7 @@ static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
rc = qeth_l3_add_ipato_entry(card, ipatoe);
if (rc)
kfree(ipatoe);
out:
mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
}
......@@ -496,11 +498,9 @@ static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
int mask_bits;
int rc = 0;
mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
if (!rc)
rc = qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
}
......@@ -607,31 +607,34 @@ static ssize_t qeth_l3_dev_ip_add_show(struct device *dev, char *buf,
{
struct qeth_card *card = dev_get_drvdata(dev);
struct qeth_ipaddr *ipaddr;
char addr_str[40];
int str_len = 0;
int entry_len; /* length of 1 entry string, differs between v4 and v6 */
int i;
entry_len = (proto == QETH_PROT_IPV4)? 12 : 40;
entry_len += 2; /* \n + terminator */
mutex_lock(&card->ip_lock);
hash_for_each(card->ip_htable, i, ipaddr, hnode) {
char addr_str[40];
int entry_len;
if (ipaddr->proto != proto || ipaddr->type != type)
continue;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE. Then we can savely display
* the next IPv6 address (worst case, compared to IPv4) */
if ((PAGE_SIZE - str_len) <= entry_len)
entry_len = qeth_l3_ipaddr_to_string(proto, (u8 *)&ipaddr->u,
addr_str);
if (entry_len < 0)
continue;
/* Enough room to format %addr\n into null terminated page? */
if (entry_len + 1 > PAGE_SIZE - str_len - 1)
break;
qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u,
addr_str);
str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "%s\n",
addr_str);
entry_len = scnprintf(buf, PAGE_SIZE - str_len, "%s\n",
addr_str);
str_len += entry_len;
buf += entry_len;
}
mutex_unlock(&card->ip_lock);
str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "\n");
return str_len;
return str_len ? str_len : scnprintf(buf, PAGE_SIZE, "\n");
}
static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
......@@ -642,63 +645,34 @@ static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev,
QETH_IP_TYPE_VIPA);
}
static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto,
u8 *addr)
{
if (qeth_l3_string_to_ipaddr(buf, proto, addr)) {
return -EINVAL;
}
return 0;
}
static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
struct qeth_card *card, enum qeth_prot_versions proto)
static ssize_t qeth_l3_vipa_store(struct device *dev, const char *buf, bool add,
size_t count, enum qeth_prot_versions proto)
{
struct qeth_card *card = dev_get_drvdata(dev);
u8 addr[16] = {0, };
int rc;
mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr);
rc = qeth_l3_string_to_ipaddr(buf, proto, addr);
if (!rc)
rc = qeth_l3_modify_rxip_vipa(card, true, addr,
rc = qeth_l3_modify_rxip_vipa(card, add, addr,
QETH_IP_TYPE_VIPA, proto);
mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
}
static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV4);
return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4);
}
static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
qeth_l3_dev_vipa_add4_show,
qeth_l3_dev_vipa_add4_store);
static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
struct qeth_card *card, enum qeth_prot_versions proto)
{
u8 addr[16];
int rc;
mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr);
if (!rc)
rc = qeth_l3_modify_rxip_vipa(card, false, addr,
QETH_IP_TYPE_VIPA, proto);
mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
}
static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV4);
return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV4);
}
static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
......@@ -715,9 +689,7 @@ static ssize_t qeth_l3_dev_vipa_add6_show(struct device *dev,
static ssize_t qeth_l3_dev_vipa_add6_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_vipa_add_store(buf, count, card, QETH_PROT_IPV6);
return qeth_l3_vipa_store(dev, buf, true, count, QETH_PROT_IPV6);
}
static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
......@@ -727,9 +699,7 @@ static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
static ssize_t qeth_l3_dev_vipa_del6_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_vipa_del_store(buf, count, card, QETH_PROT_IPV6);
return qeth_l3_vipa_store(dev, buf, false, count, QETH_PROT_IPV6);
}
static QETH_DEVICE_ATTR(vipa_del6, del6, 0200, NULL,
......@@ -782,54 +752,34 @@ static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto,
return 0;
}
static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
struct qeth_card *card, enum qeth_prot_versions proto)
static ssize_t qeth_l3_rxip_store(struct device *dev, const char *buf, bool add,
size_t count, enum qeth_prot_versions proto)
{
struct qeth_card *card = dev_get_drvdata(dev);
u8 addr[16] = {0, };
int rc;
mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr);
if (!rc)
rc = qeth_l3_modify_rxip_vipa(card, true, addr,
rc = qeth_l3_modify_rxip_vipa(card, add, addr,
QETH_IP_TYPE_RXIP, proto);
mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
}
static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV4);
return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV4);
}
static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
qeth_l3_dev_rxip_add4_show,
qeth_l3_dev_rxip_add4_store);
static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
struct qeth_card *card, enum qeth_prot_versions proto)
{
u8 addr[16];
int rc;
mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr);
if (!rc)
rc = qeth_l3_modify_rxip_vipa(card, false, addr,
QETH_IP_TYPE_RXIP, proto);
mutex_unlock(&card->conf_mutex);
return rc ? rc : count;
}
static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV4);
return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV4);
}
static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
......@@ -846,9 +796,7 @@ static ssize_t qeth_l3_dev_rxip_add6_show(struct device *dev,
static ssize_t qeth_l3_dev_rxip_add6_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_rxip_add_store(buf, count, card, QETH_PROT_IPV6);
return qeth_l3_rxip_store(dev, buf, true, count, QETH_PROT_IPV6);
}
static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
......@@ -858,9 +806,7 @@ static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
static ssize_t qeth_l3_dev_rxip_del6_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
return qeth_l3_dev_rxip_del_store(buf, count, card, QETH_PROT_IPV6);
return qeth_l3_rxip_store(dev, buf, false, count, QETH_PROT_IPV6);
}
static QETH_DEVICE_ATTR(rxip_del6, del6, 0200, NULL,
......
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