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

Merge branch 's390-qeth-next'

Julian Wiedmann says:

====================
s390/qeth: updates 2018-03-09

here is the current pile of qeth patches for net-next. Just the usual
small updates and clean ups. Please apply.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f5426250 b1d5e36b
...@@ -233,8 +233,6 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, ...@@ -233,8 +233,6 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
#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
#define QETH_REAL_CARD 1
#define QETH_VLAN_CARD 2
#define QETH_BUFSIZE 4096 #define QETH_BUFSIZE 4096
/** /**
...@@ -556,12 +554,6 @@ enum qeth_prot_versions { ...@@ -556,12 +554,6 @@ enum qeth_prot_versions {
QETH_PROT_IPV6 = 0x0006, QETH_PROT_IPV6 = 0x0006,
}; };
enum qeth_ip_types {
QETH_IP_TYPE_NORMAL,
QETH_IP_TYPE_VIPA,
QETH_IP_TYPE_RXIP,
};
enum qeth_cmd_buffer_state { enum qeth_cmd_buffer_state {
BUF_STATE_FREE, BUF_STATE_FREE,
BUF_STATE_LOCKED, BUF_STATE_LOCKED,
......
...@@ -708,11 +708,8 @@ static int qeth_check_idx_response(struct qeth_card *card, ...@@ -708,11 +708,8 @@ 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 " QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#02x\n",
"with cause code 0x%02x%s\n", buffer[4]);
buffer[4],
((buffer[4] == 0x22) ?
" -- try another portname" : ""));
QETH_CARD_TEXT(card, 2, "ckidxres"); QETH_CARD_TEXT(card, 2, "ckidxres");
QETH_CARD_TEXT(card, 2, " idxterm"); QETH_CARD_TEXT(card, 2, " idxterm");
QETH_CARD_TEXT_(card, 2, " rc%d", -EIO); QETH_CARD_TEXT_(card, 2, " rc%d", -EIO);
...@@ -2838,7 +2835,8 @@ static int qeth_init_input_buffer(struct qeth_card *card, ...@@ -2838,7 +2835,8 @@ static int qeth_init_input_buffer(struct qeth_card *card,
int i; int i;
if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) { if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
buf->rx_skb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN); buf->rx_skb = netdev_alloc_skb(card->dev,
QETH_RX_PULL_LEN + ETH_HLEN);
if (!buf->rx_skb) if (!buf->rx_skb)
return 1; return 1;
} }
...@@ -2875,8 +2873,8 @@ int qeth_init_qdio_queues(struct qeth_card *card) ...@@ -2875,8 +2873,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
QETH_DBF_TEXT(SETUP, 2, "initqdqs"); QETH_DBF_TEXT(SETUP, 2, "initqdqs");
/* inbound queue */ /* inbound queue */
qdio_reset_buffers(card->qdio.in_q->qdio_bufs, qdio_reset_buffers(card->qdio.in_q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
QDIO_MAX_BUFFERS_PER_Q); memset(&card->rx, 0, sizeof(struct qeth_rx));
qeth_initialize_working_pool_list(card); qeth_initialize_working_pool_list(card);
/*give only as many buffers to hardware as we have buffer pool entries*/ /*give only as many buffers to hardware as we have buffer pool entries*/
for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i) for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
...@@ -2951,12 +2949,10 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card, ...@@ -2951,12 +2949,10 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot) enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
{ {
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
iob = qeth_get_buffer(&card->write); iob = qeth_get_buffer(&card->write);
if (iob) { if (iob) {
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); qeth_fill_ipacmd_header(card, __ipa_cmd(iob), ipacmd, prot);
qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
} 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");
...@@ -3067,7 +3063,7 @@ static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card, ...@@ -3067,7 +3063,7 @@ static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETADAPTERPARMS, iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETADAPTERPARMS,
QETH_PROT_IPV4); QETH_PROT_IPV4);
if (iob) { if (iob) {
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setadapterparms.hdr.cmdlength = cmdlen; cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
cmd->data.setadapterparms.hdr.command_code = command; cmd->data.setadapterparms.hdr.command_code = command;
cmd->data.setadapterparms.hdr.used_total = 1; cmd->data.setadapterparms.hdr.used_total = 1;
...@@ -3209,7 +3205,7 @@ static int qeth_query_setdiagass(struct qeth_card *card) ...@@ -3209,7 +3205,7 @@ static int qeth_query_setdiagass(struct qeth_card *card)
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.diagass.subcmd_len = 16; cmd->data.diagass.subcmd_len = 16;
cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY; cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY;
return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL); return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL);
...@@ -3262,7 +3258,7 @@ int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action) ...@@ -3262,7 +3258,7 @@ int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action)
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.diagass.subcmd_len = 80; cmd->data.diagass.subcmd_len = 80;
cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP; cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP;
cmd->data.diagass.type = 1; cmd->data.diagass.type = 1;
...@@ -4240,7 +4236,7 @@ void qeth_setadp_promisc_mode(struct qeth_card *card) ...@@ -4240,7 +4236,7 @@ void qeth_setadp_promisc_mode(struct qeth_card *card)
sizeof(struct qeth_ipacmd_setadpparms_hdr) + 8); sizeof(struct qeth_ipacmd_setadpparms_hdr) + 8);
if (!iob) if (!iob)
return; return;
cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setadapterparms.data.mode = mode; cmd->data.setadapterparms.data.mode = mode;
qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL); qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
} }
...@@ -4307,7 +4303,7 @@ int qeth_setadpparms_change_macaddr(struct qeth_card *card) ...@@ -4307,7 +4303,7 @@ int qeth_setadpparms_change_macaddr(struct qeth_card *card)
sizeof(struct qeth_change_addr)); sizeof(struct qeth_change_addr));
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC; cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
cmd->data.setadapterparms.data.change_addr.addr_size = ETH_ALEN; cmd->data.setadapterparms.data.change_addr.addr_size = ETH_ALEN;
ether_addr_copy(cmd->data.setadapterparms.data.change_addr.addr, ether_addr_copy(cmd->data.setadapterparms.data.change_addr.addr,
...@@ -4422,7 +4418,7 @@ static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card, ...@@ -4422,7 +4418,7 @@ static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
sizeof(struct qeth_set_access_ctrl)); sizeof(struct qeth_set_access_ctrl));
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl; access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
access_ctrl_req->subcmd_code = isolation; access_ctrl_req->subcmd_code = isolation;
...@@ -4668,7 +4664,7 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata) ...@@ -4668,7 +4664,7 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len); memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
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);
...@@ -4753,7 +4749,7 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata) ...@@ -4753,7 +4749,7 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
rc = -ENOMEM; rc = -ENOMEM;
goto out_free; goto out_free;
} }
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
oat_req = &cmd->data.setadapterparms.data.query_oat; oat_req = &cmd->data.setadapterparms.data.query_oat;
oat_req->subcmd_code = oat_data.command; oat_req->subcmd_code = oat_data.command;
...@@ -5330,7 +5326,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, ...@@ -5330,7 +5326,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
} else { } else {
unsigned int linear = (use_rx_sg) ? QETH_RX_PULL_LEN : skb_len; unsigned int linear = (use_rx_sg) ? QETH_RX_PULL_LEN : skb_len;
skb = dev_alloc_skb(linear + headroom); skb = napi_alloc_skb(&card->napi, linear + headroom);
} }
if (!skb) if (!skb)
goto no_mem; goto no_mem;
...@@ -5494,7 +5490,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card, ...@@ -5494,7 +5490,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot); iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
if (iob) { if (iob) {
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setassparms.hdr.assist_no = ipa_func; cmd->data.setassparms.hdr.assist_no = ipa_func;
cmd->data.setassparms.hdr.length = 8 + len; cmd->data.setassparms.hdr.length = 8 + len;
cmd->data.setassparms.hdr.command_code = cmd_code; cmd->data.setassparms.hdr.command_code = cmd_code;
...@@ -5517,7 +5513,7 @@ int qeth_send_setassparms(struct qeth_card *card, ...@@ -5517,7 +5513,7 @@ int qeth_send_setassparms(struct qeth_card *card,
QETH_CARD_TEXT(card, 4, "sendassp"); QETH_CARD_TEXT(card, 4, "sendassp");
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
if (len <= sizeof(__u32)) if (len <= sizeof(__u32))
cmd->data.setassparms.data.flags_32bit = (__u32) data; cmd->data.setassparms.data.flags_32bit = (__u32) data;
else /* (len > sizeof(__u32)) */ else /* (len > sizeof(__u32)) */
......
...@@ -108,7 +108,7 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, ...@@ -108,7 +108,7 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setdelmac.mac_length = ETH_ALEN; cmd->data.setdelmac.mac_length = ETH_ALEN;
ether_addr_copy(cmd->data.setdelmac.mac, mac); ether_addr_copy(cmd->data.setdelmac.mac, mac);
return qeth_setdelmac_makerc(card, qeth_send_ipa_cmd(card, iob, return qeth_setdelmac_makerc(card, qeth_send_ipa_cmd(card, iob,
...@@ -305,7 +305,7 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, ...@@ -305,7 +305,7 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4); iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setdelvlan.vlan_id = i; cmd->data.setdelvlan.vlan_id = i;
return qeth_setdelvlan_makerc(card, qeth_send_ipa_cmd(card, iob, return qeth_setdelvlan_makerc(card, qeth_send_ipa_cmd(card, iob,
qeth_l2_send_setdelvlan_cb, NULL)); qeth_l2_send_setdelvlan_cb, NULL));
...@@ -437,10 +437,8 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, ...@@ -437,10 +437,8 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
*done = 1; *done = 1;
break; break;
} }
skb->dev = card->dev;
switch (hdr->hdr.l2.id) { switch (hdr->hdr.l2.id) {
case QETH_HEADER_TYPE_LAYER2: case QETH_HEADER_TYPE_LAYER2:
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, skb->dev); skb->protocol = eth_type_trans(skb, skb->dev);
if ((card->dev->features & NETIF_F_RXCSUM) if ((card->dev->features & NETIF_F_RXCSUM)
&& ((hdr->hdr.l2.flags[1] & && ((hdr->hdr.l2.flags[1] &
...@@ -975,6 +973,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) ...@@ -975,6 +973,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
return -ENODEV; return -ENODEV;
card->dev->ml_priv = card; card->dev->ml_priv = card;
card->dev->priv_flags |= IFF_UNICAST_FLT;
card->dev->watchdog_timeo = QETH_TX_TIMEOUT; card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
card->dev->mtu = card->info.initial_mtu; card->dev->mtu = card->info.initial_mtu;
card->dev->min_mtu = 64; card->dev->min_mtu = 64;
...@@ -991,9 +990,16 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) ...@@ -991,9 +990,16 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
card->dev->features |= NETIF_F_VLAN_CHALLENGED; card->dev->features |= NETIF_F_VLAN_CHALLENGED;
else else
card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
if (card->info.type != QETH_CARD_TYPE_OSN &&
card->info.type != QETH_CARD_TYPE_IQD) {
card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
card->dev->needed_headroom = sizeof(struct qeth_hdr);
card->dev->hw_features |= NETIF_F_SG;
card->dev->vlan_features |= NETIF_F_SG;
}
if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) { if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
card->dev->hw_features = NETIF_F_SG;
card->dev->vlan_features = NETIF_F_SG;
card->dev->features |= NETIF_F_SG; card->dev->features |= NETIF_F_SG;
/* OSA 3S and earlier has no RX/TX support */ /* OSA 3S and earlier has no RX/TX support */
if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) { if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) {
...@@ -1005,11 +1011,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) ...@@ -1005,11 +1011,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
card->dev->vlan_features |= NETIF_F_RXCSUM; card->dev->vlan_features |= NETIF_F_RXCSUM;
} }
} }
if (card->info.type != QETH_CARD_TYPE_OSN &&
card->info.type != QETH_CARD_TYPE_IQD) {
card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
card->dev->needed_headroom = sizeof(struct qeth_hdr);
}
card->info.broadcast_capable = 1; card->info.broadcast_capable = 1;
qeth_l2_request_initial_mac(card); qeth_l2_request_initial_mac(card);
...@@ -1086,7 +1087,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -1086,7 +1087,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_l2_setup_bridgeport_attrs(card); qeth_l2_setup_bridgeport_attrs(card);
card->state = CARD_STATE_HARDSETUP; card->state = CARD_STATE_HARDSETUP;
memset(&card->rx, 0, sizeof(struct qeth_rx));
qeth_print_status_message(card); qeth_print_status_message(card);
/* softsetup */ /* softsetup */
...@@ -1374,7 +1374,6 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len) ...@@ -1374,7 +1374,6 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
{ {
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
struct qeth_card *card; struct qeth_card *card;
int rc;
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
...@@ -1385,9 +1384,8 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len) ...@@ -1385,9 +1384,8 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
if (!qeth_card_hw_is_reachable(card)) if (!qeth_card_hw_is_reachable(card))
return -ENODEV; return -ENODEV;
iob = qeth_wait_for_buffer(&card->write); iob = qeth_wait_for_buffer(&card->write);
memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len); memcpy(__ipa_cmd(iob), data, data_len);
rc = qeth_osn_send_ipa_cmd(card, iob, data_len); return qeth_osn_send_ipa_cmd(card, iob, data_len);
return rc;
} }
EXPORT_SYMBOL(qeth_osn_assist); EXPORT_SYMBOL(qeth_osn_assist);
...@@ -1764,7 +1762,7 @@ static struct qeth_cmd_buffer *qeth_sbp_build_cmd(struct qeth_card *card, ...@@ -1764,7 +1762,7 @@ static struct qeth_cmd_buffer *qeth_sbp_build_cmd(struct qeth_card *card,
iob = qeth_get_ipacmd_buffer(card, ipa_cmd, 0); iob = qeth_get_ipacmd_buffer(card, ipa_cmd, 0);
if (!iob) if (!iob)
return iob; return iob;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.sbp.hdr.cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) + cmd->data.sbp.hdr.cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
cmd_length; cmd_length;
cmd->data.sbp.hdr.command_code = sbp_cmd; cmd->data.sbp.hdr.command_code = sbp_cmd;
...@@ -2129,7 +2127,7 @@ static int qeth_l2_vnicc_request(struct qeth_card *card, ...@@ -2129,7 +2127,7 @@ static int qeth_l2_vnicc_request(struct qeth_card *card,
return -ENOMEM; return -ENOMEM;
/* create header for request */ /* create header for request */
cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
req = &cmd->data.vnicc; req = &cmd->data.vnicc;
/* create sub command header for request */ /* create sub command header for request */
......
...@@ -15,21 +15,26 @@ ...@@ -15,21 +15,26 @@
#define QETH_SNIFF_AVAIL 0x0008 #define QETH_SNIFF_AVAIL 0x0008
enum qeth_ip_types {
QETH_IP_TYPE_NORMAL,
QETH_IP_TYPE_VIPA,
QETH_IP_TYPE_RXIP,
};
struct qeth_ipaddr { struct qeth_ipaddr {
struct hlist_node hnode; struct hlist_node hnode;
enum qeth_ip_types type; enum qeth_ip_types type;
enum qeth_ipa_setdelip_flags set_flags; unsigned char mac[ETH_ALEN];
enum qeth_ipa_setdelip_flags del_flags;
u8 is_multicast:1; u8 is_multicast:1;
u8 in_progress:1; u8 in_progress:1;
u8 disp_flag:2; u8 disp_flag:2;
u8 ipato:1; /* ucast only */
/* is changed only for normal ip addresses /* is changed only for normal ip addresses
* for non-normal addresses it always is 1 * for non-normal addresses it always is 1
*/ */
int ref_counter; int ref_counter;
enum qeth_prot_versions proto; enum qeth_prot_versions proto;
unsigned char mac[ETH_ALEN];
union { union {
struct { struct {
unsigned int addr; unsigned int addr;
...@@ -42,6 +47,16 @@ struct qeth_ipaddr { ...@@ -42,6 +47,16 @@ struct qeth_ipaddr {
} u; } u;
}; };
static inline void qeth_l3_init_ipaddr(struct qeth_ipaddr *addr,
enum qeth_ip_types type,
enum qeth_prot_versions proto)
{
memset(addr, 0, sizeof(*addr));
addr->type = type;
addr->proto = proto;
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
}
static inline bool qeth_l3_addr_match_ip(struct qeth_ipaddr *a1, static inline bool qeth_l3_addr_match_ip(struct qeth_ipaddr *a1,
struct qeth_ipaddr *a2) struct qeth_ipaddr *a2)
{ {
...@@ -109,15 +124,10 @@ int qeth_l3_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *); ...@@ -109,15 +124,10 @@ int qeth_l3_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *);
int qeth_l3_del_ipato_entry(struct qeth_card *card, int qeth_l3_del_ipato_entry(struct qeth_card *card,
enum qeth_prot_versions proto, u8 *addr, enum qeth_prot_versions proto, u8 *addr,
int mask_bits); int mask_bits);
int qeth_l3_add_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
int qeth_l3_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
const u8 *addr);
int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
int qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
const u8 *addr);
void qeth_l3_update_ipato(struct qeth_card *card); void qeth_l3_update_ipato(struct qeth_card *card);
struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions); int qeth_l3_modify_hsuid(struct qeth_card *card, bool add);
int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *); int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip,
int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *); enum qeth_ip_types type,
enum qeth_prot_versions proto);
#endif /* __QETH_L3_H__ */ #endif /* __QETH_L3_H__ */
...@@ -67,6 +67,15 @@ void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr, ...@@ -67,6 +67,15 @@ void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
qeth_l3_ipaddr6_to_string(addr, buf); qeth_l3_ipaddr6_to_string(addr, buf);
} }
static struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions prot)
{
struct qeth_ipaddr *addr = kmalloc(sizeof(*addr), GFP_ATOMIC);
if (addr)
qeth_l3_init_ipaddr(addr, QETH_IP_TYPE_NORMAL, prot);
return 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,
struct qeth_ipaddr *query) struct qeth_ipaddr *query)
{ {
...@@ -138,12 +147,18 @@ static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, ...@@ -138,12 +147,18 @@ static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card,
return rc; return rc;
} }
int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) static int qeth_l3_delete_ip(struct qeth_card *card,
struct qeth_ipaddr *tmp_addr)
{ {
int rc = 0; int rc = 0;
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
QETH_CARD_TEXT(card, 4, "delip"); if (tmp_addr->type == QETH_IP_TYPE_RXIP)
QETH_CARD_TEXT(card, 2, "delrxip");
else if (tmp_addr->type == QETH_IP_TYPE_VIPA)
QETH_CARD_TEXT(card, 2, "delvipa");
else
QETH_CARD_TEXT(card, 2, "delip");
if (tmp_addr->proto == QETH_PROT_IPV4) if (tmp_addr->proto == QETH_PROT_IPV4)
QETH_CARD_HEX(card, 4, &tmp_addr->u.a4.addr, 4); QETH_CARD_HEX(card, 4, &tmp_addr->u.a4.addr, 4);
...@@ -171,13 +186,18 @@ int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) ...@@ -171,13 +186,18 @@ int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
return rc; return rc;
} }
int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
{ {
int rc = 0; int rc = 0;
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
char buf[40]; char buf[40];
QETH_CARD_TEXT(card, 4, "addip"); if (tmp_addr->type == QETH_IP_TYPE_RXIP)
QETH_CARD_TEXT(card, 2, "addrxip");
else if (tmp_addr->type == QETH_IP_TYPE_VIPA)
QETH_CARD_TEXT(card, 2, "addvipa");
else
QETH_CARD_TEXT(card, 2, "addip");
if (tmp_addr->proto == QETH_PROT_IPV4) if (tmp_addr->proto == QETH_PROT_IPV4)
QETH_CARD_HEX(card, 4, &tmp_addr->u.a4.addr, 4); QETH_CARD_HEX(card, 4, &tmp_addr->u.a4.addr, 4);
...@@ -209,7 +229,7 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) ...@@ -209,7 +229,7 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
if (qeth_l3_is_addr_covered_by_ipato(card, addr)) { if (qeth_l3_is_addr_covered_by_ipato(card, addr)) {
QETH_CARD_TEXT(card, 2, "tkovaddr"); QETH_CARD_TEXT(card, 2, "tkovaddr");
addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG; addr->ipato = 1;
} }
hash_add(card->ip_htable, &addr->hnode, hash_add(card->ip_htable, &addr->hnode,
qeth_l3_ipaddr_hash(addr)); qeth_l3_ipaddr_hash(addr));
...@@ -251,23 +271,6 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) ...@@ -251,23 +271,6 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr)
return rc; return rc;
} }
struct qeth_ipaddr *qeth_l3_get_addr_buffer(
enum qeth_prot_versions prot)
{
struct qeth_ipaddr *addr;
addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC);
if (!addr)
return NULL;
addr->type = QETH_IP_TYPE_NORMAL;
addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
addr->proto = prot;
return addr;
}
static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover) static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover)
{ {
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
...@@ -352,7 +355,7 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card, ...@@ -352,7 +355,7 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto); iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
ether_addr_copy(cmd->data.setdelipm.mac, addr->mac); ether_addr_copy(cmd->data.setdelipm.mac, addr->mac);
if (addr->proto == QETH_PROT_IPV6) if (addr->proto == QETH_PROT_IPV6)
memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr, memcpy(cmd->data.setdelipm.ip6, &addr->u.a6.addr,
...@@ -379,21 +382,38 @@ static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len) ...@@ -379,21 +382,38 @@ static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len)
} }
} }
static u32 qeth_l3_get_setdelip_flags(struct qeth_ipaddr *addr, bool set)
{
switch (addr->type) {
case QETH_IP_TYPE_RXIP:
return (set) ? QETH_IPA_SETIP_TAKEOVER_FLAG : 0;
case QETH_IP_TYPE_VIPA:
return (set) ? QETH_IPA_SETIP_VIPA_FLAG :
QETH_IPA_DELIP_VIPA_FLAG;
default:
return (set && addr->ipato) ? QETH_IPA_SETIP_TAKEOVER_FLAG : 0;
}
}
static int qeth_l3_send_setdelip(struct qeth_card *card, static int qeth_l3_send_setdelip(struct qeth_card *card,
struct qeth_ipaddr *addr, int ipacmd, unsigned int flags) struct qeth_ipaddr *addr,
enum qeth_ipa_cmds ipacmd)
{ {
int rc;
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd; struct qeth_ipa_cmd *cmd;
__u8 netmask[16]; __u8 netmask[16];
u32 flags;
QETH_CARD_TEXT(card, 4, "setdelip"); QETH_CARD_TEXT(card, 4, "setdelip");
QETH_CARD_TEXT_(card, 4, "flags%02X", flags);
iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto); iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
flags = qeth_l3_get_setdelip_flags(addr, ipacmd == IPA_CMD_SETIP);
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, memcpy(cmd->data.setdelip6.ip_addr, &addr->u.a6.addr,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
...@@ -407,9 +427,7 @@ static int qeth_l3_send_setdelip(struct qeth_card *card, ...@@ -407,9 +427,7 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
cmd->data.setdelip4.flags = flags; cmd->data.setdelip4.flags = flags;
} }
rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); return qeth_send_ipa_cmd(card, iob, NULL, NULL);
return rc;
} }
static int qeth_l3_send_setrouting(struct qeth_card *card, static int qeth_l3_send_setrouting(struct qeth_card *card,
...@@ -423,7 +441,7 @@ static int qeth_l3_send_setrouting(struct qeth_card *card, ...@@ -423,7 +441,7 @@ static int qeth_l3_send_setrouting(struct qeth_card *card,
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot); iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setrtg.type = (type); cmd->data.setrtg.type = (type);
rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
...@@ -525,10 +543,7 @@ void qeth_l3_update_ipato(struct qeth_card *card) ...@@ -525,10 +543,7 @@ void qeth_l3_update_ipato(struct qeth_card *card)
hash_for_each(card->ip_htable, i, addr, hnode) { hash_for_each(card->ip_htable, i, addr, hnode) {
if (addr->type != QETH_IP_TYPE_NORMAL) if (addr->type != QETH_IP_TYPE_NORMAL)
continue; continue;
if (qeth_l3_is_addr_covered_by_ipato(card, addr)) addr->ipato = qeth_l3_is_addr_covered_by_ipato(card, addr);
addr->set_flags |= QETH_IPA_SETIP_TAKEOVER_FLAG;
else
addr->set_flags &= ~QETH_IPA_SETIP_TAKEOVER_FLAG;
} }
} }
...@@ -606,132 +621,39 @@ int qeth_l3_del_ipato_entry(struct qeth_card *card, ...@@ -606,132 +621,39 @@ int qeth_l3_del_ipato_entry(struct qeth_card *card,
return rc; return rc;
} }
/* int qeth_l3_modify_rxip_vipa(struct qeth_card *card, bool add, const u8 *ip,
* VIPA related functions enum qeth_ip_types type,
*/ enum qeth_prot_versions proto)
int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
const u8 *addr)
{
struct qeth_ipaddr *ipaddr;
int rc;
ipaddr = qeth_l3_get_addr_buffer(proto);
if (ipaddr) {
if (proto == QETH_PROT_IPV4) {
QETH_CARD_TEXT(card, 2, "addvipa4");
memcpy(&ipaddr->u.a4.addr, addr, 4);
ipaddr->u.a4.mask = 0;
} else if (proto == QETH_PROT_IPV6) {
QETH_CARD_TEXT(card, 2, "addvipa6");
memcpy(&ipaddr->u.a6.addr, addr, 16);
ipaddr->u.a6.pfxlen = 0;
}
ipaddr->type = QETH_IP_TYPE_VIPA;
ipaddr->set_flags = QETH_IPA_SETIP_VIPA_FLAG;
ipaddr->del_flags = QETH_IPA_DELIP_VIPA_FLAG;
} else
return -ENOMEM;
spin_lock_bh(&card->ip_lock);
rc = qeth_l3_add_ip(card, ipaddr);
spin_unlock_bh(&card->ip_lock);
kfree(ipaddr);
return rc;
}
int qeth_l3_del_vipa(struct qeth_card *card, enum qeth_prot_versions proto,
const u8 *addr)
{
struct qeth_ipaddr *ipaddr;
int rc;
ipaddr = qeth_l3_get_addr_buffer(proto);
if (ipaddr) {
if (proto == QETH_PROT_IPV4) {
QETH_CARD_TEXT(card, 2, "delvipa4");
memcpy(&ipaddr->u.a4.addr, addr, 4);
ipaddr->u.a4.mask = 0;
} else if (proto == QETH_PROT_IPV6) {
QETH_CARD_TEXT(card, 2, "delvipa6");
memcpy(&ipaddr->u.a6.addr, addr, 16);
ipaddr->u.a6.pfxlen = 0;
}
ipaddr->type = QETH_IP_TYPE_VIPA;
} else
return -ENOMEM;
spin_lock_bh(&card->ip_lock);
rc = qeth_l3_delete_ip(card, ipaddr);
spin_unlock_bh(&card->ip_lock);
kfree(ipaddr);
return rc;
}
/*
* proxy ARP related functions
*/
int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto,
const u8 *addr)
{ {
struct qeth_ipaddr *ipaddr; struct qeth_ipaddr addr;
int rc; int rc;
ipaddr = qeth_l3_get_addr_buffer(proto); qeth_l3_init_ipaddr(&addr, type, proto);
if (ipaddr) { if (proto == QETH_PROT_IPV4)
if (proto == QETH_PROT_IPV4) { memcpy(&addr.u.a4.addr, ip, 4);
QETH_CARD_TEXT(card, 2, "addrxip4"); else
memcpy(&ipaddr->u.a4.addr, addr, 4); memcpy(&addr.u.a6.addr, ip, 16);
ipaddr->u.a4.mask = 0;
} else if (proto == QETH_PROT_IPV6) {
QETH_CARD_TEXT(card, 2, "addrxip6");
memcpy(&ipaddr->u.a6.addr, addr, 16);
ipaddr->u.a6.pfxlen = 0;
}
ipaddr->type = QETH_IP_TYPE_RXIP;
ipaddr->set_flags = QETH_IPA_SETIP_TAKEOVER_FLAG;
ipaddr->del_flags = 0;
} else
return -ENOMEM;
spin_lock_bh(&card->ip_lock); spin_lock_bh(&card->ip_lock);
rc = qeth_l3_add_ip(card, ipaddr); rc = add ? qeth_l3_add_ip(card, &addr) : qeth_l3_delete_ip(card, &addr);
spin_unlock_bh(&card->ip_lock); spin_unlock_bh(&card->ip_lock);
kfree(ipaddr);
return rc; return rc;
} }
int qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions proto, int qeth_l3_modify_hsuid(struct qeth_card *card, bool add)
const u8 *addr)
{ {
struct qeth_ipaddr *ipaddr; struct qeth_ipaddr addr;
int rc; int rc, i;
ipaddr = qeth_l3_get_addr_buffer(proto); qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV6);
if (ipaddr) { addr.u.a6.addr.s6_addr[0] = 0xfe;
if (proto == QETH_PROT_IPV4) { addr.u.a6.addr.s6_addr[1] = 0x80;
QETH_CARD_TEXT(card, 2, "delrxip4"); for (i = 0; i < 8; i++)
memcpy(&ipaddr->u.a4.addr, addr, 4); addr.u.a6.addr.s6_addr[8+i] = card->options.hsuid[i];
ipaddr->u.a4.mask = 0;
} else if (proto == QETH_PROT_IPV6) {
QETH_CARD_TEXT(card, 2, "delrxip6");
memcpy(&ipaddr->u.a6.addr, addr, 16);
ipaddr->u.a6.pfxlen = 0;
}
ipaddr->type = QETH_IP_TYPE_RXIP;
} else
return -ENOMEM;
spin_lock_bh(&card->ip_lock); spin_lock_bh(&card->ip_lock);
rc = qeth_l3_delete_ip(card, ipaddr); rc = add ? qeth_l3_add_ip(card, &addr) : qeth_l3_delete_ip(card, &addr);
spin_unlock_bh(&card->ip_lock); spin_unlock_bh(&card->ip_lock);
kfree(ipaddr);
return rc; return rc;
} }
...@@ -758,8 +680,7 @@ static int qeth_l3_register_addr_entry(struct qeth_card *card, ...@@ -758,8 +680,7 @@ static int qeth_l3_register_addr_entry(struct qeth_card *card,
if (addr->is_multicast) if (addr->is_multicast)
rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_SETIPM); rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_SETIPM);
else else
rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_SETIP, rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_SETIP);
addr->set_flags);
if (rc) if (rc)
QETH_CARD_TEXT(card, 2, "failed"); QETH_CARD_TEXT(card, 2, "failed");
} while ((--cnt > 0) && rc); } while ((--cnt > 0) && rc);
...@@ -791,8 +712,7 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *card, ...@@ -791,8 +712,7 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *card,
if (addr->is_multicast) if (addr->is_multicast)
rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_DELIPM); rc = qeth_l3_send_setdelmc(card, addr, IPA_CMD_DELIPM);
else else
rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP, rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP);
addr->del_flags);
if (rc) if (rc)
QETH_CARD_TEXT(card, 2, "failed"); QETH_CARD_TEXT(card, 2, "failed");
...@@ -1072,7 +992,7 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card) ...@@ -1072,7 +992,7 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
QETH_PROT_IPV6); QETH_PROT_IPV6);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) = *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
card->info.unique_id; card->info.unique_id;
...@@ -1117,7 +1037,7 @@ static int qeth_l3_get_unique_id(struct qeth_card *card) ...@@ -1117,7 +1037,7 @@ static int qeth_l3_get_unique_id(struct qeth_card *card)
QETH_PROT_IPV6); QETH_PROT_IPV6);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) = *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
card->info.unique_id; card->info.unique_id;
...@@ -1193,7 +1113,7 @@ qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd) ...@@ -1193,7 +1113,7 @@ qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd)
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.diagass.subcmd_len = 16; cmd->data.diagass.subcmd_len = 16;
cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRACE; cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRACE;
cmd->data.diagass.type = QETH_DIAGS_TYPE_HIPERSOCKET; cmd->data.diagass.type = QETH_DIAGS_TYPE_HIPERSOCKET;
...@@ -1502,30 +1422,24 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, ...@@ -1502,30 +1422,24 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr); ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr);
card->stats.multicast++; card->stats.multicast++;
skb->pkt_type = PACKET_MULTICAST;
break; break;
case QETH_CAST_BROADCAST: case QETH_CAST_BROADCAST:
ether_addr_copy(tg_addr, card->dev->broadcast); ether_addr_copy(tg_addr, card->dev->broadcast);
card->stats.multicast++; card->stats.multicast++;
skb->pkt_type = PACKET_BROADCAST;
break; break;
case QETH_CAST_UNICAST:
case QETH_CAST_ANYCAST:
case QETH_CAST_NOCAST:
default: default:
if (card->options.sniffer) if (card->options.sniffer)
skb->pkt_type = PACKET_OTHERHOST; skb->pkt_type = PACKET_OTHERHOST;
else
skb->pkt_type = PACKET_HOST;
ether_addr_copy(tg_addr, card->dev->dev_addr); ether_addr_copy(tg_addr, card->dev->dev_addr);
} }
if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
card->dev->header_ops->create(skb, card->dev, prot, card->dev->header_ops->create(skb, card->dev, prot,
tg_addr, &hdr->hdr.l3.next_hop.rx.src_mac, tg_addr, &hdr->hdr.l3.next_hop.rx.src_mac,
card->dev->addr_len); skb->len);
else else
card->dev->header_ops->create(skb, card->dev, prot, card->dev->header_ops->create(skb, card->dev, prot,
tg_addr, "FAKELL", card->dev->addr_len); tg_addr, "FAKELL", skb->len);
} }
skb->protocol = eth_type_trans(skb, card->dev); skb->protocol = eth_type_trans(skb, card->dev);
...@@ -1572,20 +1486,16 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, ...@@ -1572,20 +1486,16 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
*done = 1; *done = 1;
break; break;
} }
skb->dev = card->dev;
switch (hdr->hdr.l3.id) { switch (hdr->hdr.l3.id) {
case QETH_HEADER_TYPE_LAYER3: case QETH_HEADER_TYPE_LAYER3:
magic = *(__u16 *)skb->data; magic = *(__u16 *)skb->data;
if ((card->info.type == QETH_CARD_TYPE_IQD) && if ((card->info.type == QETH_CARD_TYPE_IQD) &&
(magic == ETH_P_AF_IUCV)) { (magic == ETH_P_AF_IUCV)) {
skb->protocol = cpu_to_be16(ETH_P_AF_IUCV); skb->protocol = cpu_to_be16(ETH_P_AF_IUCV);
skb->pkt_type = PACKET_HOST;
skb->mac_header = NET_SKB_PAD;
skb->dev = card->dev;
len = skb->len; len = skb->len;
card->dev->header_ops->create(skb, card->dev, 0, card->dev->header_ops->create(skb, card->dev, 0,
card->dev->dev_addr, "FAKELL", card->dev->dev_addr, "FAKELL", len);
card->dev->addr_len); skb_reset_mac_header(skb);
netif_receive_skb(skb); netif_receive_skb(skb);
} else { } else {
qeth_l3_rebuild_skb(card, skb, hdr); qeth_l3_rebuild_skb(card, skb, hdr);
...@@ -1594,7 +1504,6 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, ...@@ -1594,7 +1504,6 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
} }
break; break;
case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, skb->dev); skb->protocol = eth_type_trans(skb, skb->dev);
len = skb->len; len = skb->len;
netif_receive_skb(skb); netif_receive_skb(skb);
...@@ -1613,69 +1522,6 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, ...@@ -1613,69 +1522,6 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
return work_done; return work_done;
} }
static int qeth_l3_verify_vlan_dev(struct net_device *dev,
struct qeth_card *card)
{
int rc = 0;
u16 vid;
for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) {
struct net_device *netdev;
rcu_read_lock();
netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q),
vid);
rcu_read_unlock();
if (netdev == dev) {
rc = QETH_VLAN_CARD;
break;
}
}
if (rc && !(vlan_dev_real_dev(dev)->ml_priv == (void *)card))
return 0;
return rc;
}
static int qeth_l3_verify_dev(struct net_device *dev)
{
struct qeth_card *card;
int rc = 0;
unsigned long flags;
read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
list_for_each_entry(card, &qeth_core_card_list.list, list) {
if (card->dev == dev) {
rc = QETH_REAL_CARD;
break;
}
rc = qeth_l3_verify_vlan_dev(dev, card);
if (rc)
break;
}
read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
return rc;
}
static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
{
struct qeth_card *card = NULL;
int rc;
rc = qeth_l3_verify_dev(dev);
if (rc == QETH_REAL_CARD)
card = dev->ml_priv;
else if (rc == QETH_VLAN_CARD)
card = vlan_dev_real_dev(dev)->ml_priv;
if (card && card->options.layer2)
card = NULL;
if (card)
QETH_CARD_TEXT_(card, 4, "%d", rc);
return card ;
}
static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
{ {
QETH_DBF_TEXT(SETUP, 2, "stopcard"); QETH_DBF_TEXT(SETUP, 2, "stopcard");
...@@ -2004,7 +1850,7 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card, ...@@ -2004,7 +1850,7 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
prot); prot);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); cmd = __ipa_cmd(iob);
cmd->data.setassparms.data.query_arp.request_bits = 0x000F; cmd->data.setassparms.data.query_arp.request_bits = 0x000F;
cmd->data.setassparms.data.query_arp.reply_bits = 0; cmd->data.setassparms.data.query_arp.reply_bits = 0;
cmd->data.setassparms.data.query_arp.no_entries = 0; cmd->data.setassparms.data.query_arp.no_entries = 0;
...@@ -2785,14 +2631,16 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) ...@@ -2785,14 +2631,16 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
card->dev->dev_id = card->info.unique_id & card->dev->dev_id = card->info.unique_id &
0xffff; 0xffff;
card->dev->hw_features |= NETIF_F_SG;
card->dev->vlan_features |= NETIF_F_SG;
if (!card->info.guestlan) { if (!card->info.guestlan) {
card->dev->hw_features = NETIF_F_SG |
NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
NETIF_F_TSO;
card->dev->vlan_features = NETIF_F_SG |
NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
NETIF_F_TSO;
card->dev->features |= NETIF_F_SG; card->dev->features |= NETIF_F_SG;
card->dev->hw_features |= NETIF_F_TSO |
NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
card->dev->vlan_features |= NETIF_F_TSO |
NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
} }
} }
} else if (card->info.type == QETH_CARD_TYPE_IQD) { } else if (card->info.type == QETH_CARD_TYPE_IQD) {
...@@ -2907,7 +2755,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2907,7 +2755,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
card->info.hwtrap = 0; card->info.hwtrap = 0;
card->state = CARD_STATE_HARDSETUP; card->state = CARD_STATE_HARDSETUP;
memset(&card->rx, 0, sizeof(struct qeth_rx));
qeth_print_status_message(card); qeth_print_status_message(card);
/* softsetup */ /* softsetup */
...@@ -3130,13 +2977,43 @@ struct qeth_discipline qeth_l3_discipline = { ...@@ -3130,13 +2977,43 @@ struct qeth_discipline qeth_l3_discipline = {
}; };
EXPORT_SYMBOL_GPL(qeth_l3_discipline); EXPORT_SYMBOL_GPL(qeth_l3_discipline);
static int qeth_l3_handle_ip_event(struct qeth_card *card,
struct qeth_ipaddr *addr,
unsigned long event)
{
switch (event) {
case NETDEV_UP:
spin_lock_bh(&card->ip_lock);
qeth_l3_add_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
return NOTIFY_OK;
case NETDEV_DOWN:
spin_lock_bh(&card->ip_lock);
qeth_l3_delete_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
return NOTIFY_OK;
default:
return NOTIFY_DONE;
}
}
static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev)
{
if (is_vlan_dev(dev))
dev = vlan_dev_real_dev(dev);
if (dev->netdev_ops == &qeth_l3_osa_netdev_ops ||
dev->netdev_ops == &qeth_l3_netdev_ops)
return (struct qeth_card *) dev->ml_priv;
return NULL;
}
static int qeth_l3_ip_event(struct notifier_block *this, static int qeth_l3_ip_event(struct notifier_block *this,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct net_device *dev = (struct net_device *)ifa->ifa_dev->dev; struct net_device *dev = ifa->ifa_dev->dev;
struct qeth_ipaddr *addr; struct qeth_ipaddr addr;
struct qeth_card *card; struct qeth_card *card;
if (dev_net(dev) != &init_net) if (dev_net(dev) != &init_net)
...@@ -3147,29 +3024,11 @@ static int qeth_l3_ip_event(struct notifier_block *this, ...@@ -3147,29 +3024,11 @@ static int qeth_l3_ip_event(struct notifier_block *this,
return NOTIFY_DONE; return NOTIFY_DONE;
QETH_CARD_TEXT(card, 3, "ipevent"); QETH_CARD_TEXT(card, 3, "ipevent");
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV4);
if (addr) { addr.u.a4.addr = be32_to_cpu(ifa->ifa_address);
addr->u.a4.addr = be32_to_cpu(ifa->ifa_address); addr.u.a4.mask = be32_to_cpu(ifa->ifa_mask);
addr->u.a4.mask = be32_to_cpu(ifa->ifa_mask);
addr->type = QETH_IP_TYPE_NORMAL;
} else
return NOTIFY_DONE;
switch (event) {
case NETDEV_UP:
spin_lock_bh(&card->ip_lock);
qeth_l3_add_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
break;
case NETDEV_DOWN:
spin_lock_bh(&card->ip_lock);
qeth_l3_delete_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
break;
}
kfree(addr); return qeth_l3_handle_ip_event(card, &addr, event);
return NOTIFY_DONE;
} }
static struct notifier_block qeth_l3_ip_notifier = { static struct notifier_block qeth_l3_ip_notifier = {
...@@ -3181,8 +3040,8 @@ static int qeth_l3_ip6_event(struct notifier_block *this, ...@@ -3181,8 +3040,8 @@ static int qeth_l3_ip6_event(struct notifier_block *this,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
struct net_device *dev = (struct net_device *)ifa->idev->dev; struct net_device *dev = ifa->idev->dev;
struct qeth_ipaddr *addr; struct qeth_ipaddr addr;
struct qeth_card *card; struct qeth_card *card;
card = qeth_l3_get_card_from_dev(dev); card = qeth_l3_get_card_from_dev(dev);
...@@ -3192,29 +3051,11 @@ static int qeth_l3_ip6_event(struct notifier_block *this, ...@@ -3192,29 +3051,11 @@ static int qeth_l3_ip6_event(struct notifier_block *this,
if (!qeth_is_supported(card, IPA_IPV6)) if (!qeth_is_supported(card, IPA_IPV6))
return NOTIFY_DONE; return NOTIFY_DONE;
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6); qeth_l3_init_ipaddr(&addr, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV6);
if (addr) { addr.u.a6.addr = ifa->addr;
memcpy(&addr->u.a6.addr, &ifa->addr, sizeof(struct in6_addr)); addr.u.a6.pfxlen = ifa->prefix_len;
addr->u.a6.pfxlen = ifa->prefix_len;
addr->type = QETH_IP_TYPE_NORMAL;
} else
return NOTIFY_DONE;
switch (event) {
case NETDEV_UP:
spin_lock_bh(&card->ip_lock);
qeth_l3_add_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
break;
case NETDEV_DOWN:
spin_lock_bh(&card->ip_lock);
qeth_l3_delete_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
break;
}
kfree(addr); return qeth_l3_handle_ip_event(card, &addr, event);
return NOTIFY_DONE;
} }
static struct notifier_block qeth_l3_ip6_notifier = { static struct notifier_block qeth_l3_ip6_notifier = {
......
...@@ -272,9 +272,8 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev, ...@@ -272,9 +272,8 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count) struct device_attribute *attr, const char *buf, size_t count)
{ {
struct qeth_card *card = dev_get_drvdata(dev); struct qeth_card *card = dev_get_drvdata(dev);
struct qeth_ipaddr *addr;
char *tmp; char *tmp;
int rc, i; int rc;
if (!card) if (!card)
return -EINVAL; return -EINVAL;
...@@ -293,25 +292,9 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev, ...@@ -293,25 +292,9 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
if (strlen(tmp) > 8) if (strlen(tmp) > 8)
return -EINVAL; return -EINVAL;
if (card->options.hsuid[0]) { if (card->options.hsuid[0])
/* delete old ip address */ /* delete old ip address */
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6); qeth_l3_modify_hsuid(card, false);
if (!addr)
return -ENOMEM;
addr->u.a6.addr.s6_addr32[0] = cpu_to_be32(0xfe800000);
addr->u.a6.addr.s6_addr32[1] = 0x00000000;
for (i = 8; i < 16; i++)
addr->u.a6.addr.s6_addr[i] =
card->options.hsuid[i - 8];
addr->u.a6.pfxlen = 0;
addr->type = QETH_IP_TYPE_NORMAL;
spin_lock_bh(&card->ip_lock);
qeth_l3_delete_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
kfree(addr);
}
if (strlen(tmp) == 0) { if (strlen(tmp) == 0) {
/* delete ip address only */ /* delete ip address only */
...@@ -331,21 +314,7 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev, ...@@ -331,21 +314,7 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
if (card->dev) if (card->dev)
memcpy(card->dev->perm_addr, card->options.hsuid, 9); memcpy(card->dev->perm_addr, card->options.hsuid, 9);
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6); rc = qeth_l3_modify_hsuid(card, true);
if (addr != NULL) {
addr->u.a6.addr.s6_addr32[0] = cpu_to_be32(0xfe800000);
addr->u.a6.addr.s6_addr32[1] = 0x00000000;
for (i = 8; i < 16; i++)
addr->u.a6.addr.s6_addr[i] = card->options.hsuid[i - 8];
addr->u.a6.pfxlen = 0;
addr->type = QETH_IP_TYPE_NORMAL;
} else
return -ENOMEM;
spin_lock_bh(&card->ip_lock);
rc = qeth_l3_add_ip(card, addr);
spin_unlock_bh(&card->ip_lock);
kfree(addr);
return rc ? rc : count; return rc ? rc : count;
} }
...@@ -767,7 +736,8 @@ static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count, ...@@ -767,7 +736,8 @@ static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
mutex_lock(&card->conf_mutex); mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr); rc = qeth_l3_parse_vipae(buf, proto, addr);
if (!rc) if (!rc)
rc = qeth_l3_add_vipa(card, proto, addr); rc = qeth_l3_modify_rxip_vipa(card, true, addr,
QETH_IP_TYPE_VIPA, proto);
mutex_unlock(&card->conf_mutex); mutex_unlock(&card->conf_mutex);
return rc ? rc : count; return rc ? rc : count;
} }
...@@ -796,7 +766,8 @@ static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count, ...@@ -796,7 +766,8 @@ static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
mutex_lock(&card->conf_mutex); mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr); rc = qeth_l3_parse_vipae(buf, proto, addr);
if (!rc) if (!rc)
rc = qeth_l3_del_vipa(card, proto, addr); rc = qeth_l3_modify_rxip_vipa(card, false, addr,
QETH_IP_TYPE_VIPA, proto);
mutex_unlock(&card->conf_mutex); mutex_unlock(&card->conf_mutex);
return rc ? rc : count; return rc ? rc : count;
} }
...@@ -908,7 +879,8 @@ static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count, ...@@ -908,7 +879,8 @@ static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
mutex_lock(&card->conf_mutex); mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr); rc = qeth_l3_parse_rxipe(buf, proto, addr);
if (!rc) if (!rc)
rc = qeth_l3_add_rxip(card, proto, addr); rc = qeth_l3_modify_rxip_vipa(card, true, addr,
QETH_IP_TYPE_RXIP, proto);
mutex_unlock(&card->conf_mutex); mutex_unlock(&card->conf_mutex);
return rc ? rc : count; return rc ? rc : count;
} }
...@@ -937,7 +909,8 @@ static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count, ...@@ -937,7 +909,8 @@ static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
mutex_lock(&card->conf_mutex); mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr); rc = qeth_l3_parse_rxipe(buf, proto, addr);
if (!rc) if (!rc)
rc = qeth_l3_del_rxip(card, proto, addr); rc = qeth_l3_modify_rxip_vipa(card, false, addr,
QETH_IP_TYPE_RXIP, proto);
mutex_unlock(&card->conf_mutex); mutex_unlock(&card->conf_mutex);
return rc ? rc : count; return rc ? rc : count;
} }
......
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