Merge branch 's390-next-updates'
Julian Wiedmann says: ==================== s390/net updates please apply the following qeth updates for net-next. Aside from some janitorial changes, this adds early setup for virtualized HiperSockets devices - building upon the code that landed via -net earlier. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ea30afb4ae
|
@ -659,6 +659,7 @@ struct qeth_card_info {
|
|||
int max_mtu;
|
||||
int broadcast_capable;
|
||||
int unique_id;
|
||||
bool layer_enforced;
|
||||
struct qeth_card_blkt blkt;
|
||||
enum qeth_ipa_promisc_modes promisc_mode;
|
||||
__u32 diagass_support;
|
||||
|
@ -696,6 +697,7 @@ struct qeth_osn_info {
|
|||
};
|
||||
|
||||
enum qeth_discipline_id {
|
||||
QETH_DISCIPLINE_UNDETERMINED = -1,
|
||||
QETH_DISCIPLINE_LAYER3 = 0,
|
||||
QETH_DISCIPLINE_LAYER2 = 1,
|
||||
};
|
||||
|
|
|
@ -1723,6 +1723,25 @@ static void qeth_configure_unitaddr(struct qeth_card *card, char *prcd)
|
|||
(prcd[0x11] == _ascebc['M']));
|
||||
}
|
||||
|
||||
/* Determine whether the device requires a specific layer discipline */
|
||||
static enum qeth_discipline_id qeth_enforce_discipline(struct qeth_card *card)
|
||||
{
|
||||
if (card->info.type == QETH_CARD_TYPE_OSM ||
|
||||
card->info.type == QETH_CARD_TYPE_OSN) {
|
||||
QETH_DBF_TEXT(SETUP, 3, "force l2");
|
||||
return QETH_DISCIPLINE_LAYER2;
|
||||
}
|
||||
|
||||
/* virtual HiperSocket is L3 only: */
|
||||
if (card->info.guestlan && card->info.type == QETH_CARD_TYPE_IQD) {
|
||||
QETH_DBF_TEXT(SETUP, 3, "force l3");
|
||||
return QETH_DISCIPLINE_LAYER3;
|
||||
}
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 3, "force no");
|
||||
return QETH_DISCIPLINE_UNDETERMINED;
|
||||
}
|
||||
|
||||
static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd)
|
||||
{
|
||||
QETH_DBF_TEXT(SETUP, 2, "cfgblkt");
|
||||
|
@ -3347,6 +3366,28 @@ static void qeth_handle_send_error(struct qeth_card *card,
|
|||
(u16)qdio_err, (u8)sbalf15);
|
||||
}
|
||||
|
||||
/**
|
||||
* qeth_prep_flush_pack_buffer - Prepares flushing of a packing buffer.
|
||||
* @queue: queue to check for packing buffer
|
||||
*
|
||||
* Returns number of buffers that were prepared for flush.
|
||||
*/
|
||||
static int qeth_prep_flush_pack_buffer(struct qeth_qdio_out_q *queue)
|
||||
{
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
|
||||
buffer = queue->bufs[queue->next_buf_to_fill];
|
||||
if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
|
||||
(buffer->next_element_to_fill > 0)) {
|
||||
/* it's a packing buffer */
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
|
||||
queue->next_buf_to_fill =
|
||||
(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switched to packing state if the number of used buffers on a queue
|
||||
* reaches a certain limit.
|
||||
|
@ -3373,9 +3414,6 @@ static void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
|
|||
*/
|
||||
static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
|
||||
{
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
int flush_count = 0;
|
||||
|
||||
if (queue->do_pack) {
|
||||
if (atomic_read(&queue->used_buffers)
|
||||
<= QETH_LOW_WATERMARK_PACK) {
|
||||
|
@ -3384,42 +3422,9 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
|
|||
if (queue->card->options.performance_stats)
|
||||
queue->card->perf_stats.sc_p_dp++;
|
||||
queue->do_pack = 0;
|
||||
/* flush packing buffers */
|
||||
buffer = queue->bufs[queue->next_buf_to_fill];
|
||||
if ((atomic_read(&buffer->state) ==
|
||||
QETH_QDIO_BUF_EMPTY) &&
|
||||
(buffer->next_element_to_fill > 0)) {
|
||||
atomic_set(&buffer->state,
|
||||
QETH_QDIO_BUF_PRIMED);
|
||||
flush_count++;
|
||||
queue->next_buf_to_fill =
|
||||
(queue->next_buf_to_fill + 1) %
|
||||
QDIO_MAX_BUFFERS_PER_Q;
|
||||
}
|
||||
return qeth_prep_flush_pack_buffer(queue);
|
||||
}
|
||||
}
|
||||
return flush_count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called to flush a packing buffer if no more pci flags are on the queue.
|
||||
* Checks if there is a packing buffer and prepares it to be flushed.
|
||||
* In that case returns 1, otherwise zero.
|
||||
*/
|
||||
static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
|
||||
{
|
||||
struct qeth_qdio_out_buffer *buffer;
|
||||
|
||||
buffer = queue->bufs[queue->next_buf_to_fill];
|
||||
if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
|
||||
(buffer->next_element_to_fill > 0)) {
|
||||
/* it's a packing buffer */
|
||||
atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
|
||||
queue->next_buf_to_fill =
|
||||
(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3532,8 +3537,7 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
|
|||
flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
|
||||
if (!flush_cnt &&
|
||||
!atomic_read(&queue->set_pci_flags_count))
|
||||
flush_cnt +=
|
||||
qeth_flush_buffers_on_no_pci(queue);
|
||||
flush_cnt += qeth_prep_flush_pack_buffer(queue);
|
||||
if (queue->card->options.performance_stats &&
|
||||
q_was_packing)
|
||||
queue->card->perf_stats.bufs_sent_pack +=
|
||||
|
@ -4127,7 +4131,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
|
|||
* flag out on the queue
|
||||
*/
|
||||
if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
|
||||
flush_count += qeth_flush_buffers_on_no_pci(queue);
|
||||
flush_count += qeth_prep_flush_pack_buffer(queue);
|
||||
if (flush_count)
|
||||
qeth_flush_buffers(queue, start_index, flush_count);
|
||||
}
|
||||
|
@ -4199,8 +4203,7 @@ int qeth_change_mtu(struct net_device *dev, int new_mtu)
|
|||
sprintf(dbf_text, "%8x", new_mtu);
|
||||
QETH_CARD_TEXT(card, 4, dbf_text);
|
||||
|
||||
if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) &&
|
||||
(!qeth_mtu_is_valid(card, new_mtu)))
|
||||
if (!qeth_mtu_is_valid(card, new_mtu))
|
||||
return -EINVAL;
|
||||
dev->mtu = new_mtu;
|
||||
return 0;
|
||||
|
@ -5501,6 +5504,7 @@ int qeth_core_load_discipline(struct qeth_card *card,
|
|||
enum qeth_discipline_id discipline)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
mutex_lock(&qeth_mod_mutex);
|
||||
switch (discipline) {
|
||||
case QETH_DISCIPLINE_LAYER3:
|
||||
|
@ -5511,7 +5515,10 @@ int qeth_core_load_discipline(struct qeth_card *card,
|
|||
card->discipline = try_then_request_module(
|
||||
symbol_get(qeth_l2_discipline), "qeth_l2");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!card->discipline) {
|
||||
dev_err(&card->gdev->dev, "There is no kernel module to "
|
||||
"support discipline %d\n", discipline);
|
||||
|
@ -5614,6 +5621,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
|||
struct qeth_card *card;
|
||||
struct device *dev;
|
||||
int rc;
|
||||
enum qeth_discipline_id enforced_disc;
|
||||
unsigned long flags;
|
||||
char dbf_name[DBF_NAME_LEN];
|
||||
|
||||
|
@ -5661,10 +5669,15 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
|||
goto err_card;
|
||||
}
|
||||
|
||||
switch (card->info.type) {
|
||||
case QETH_CARD_TYPE_OSN:
|
||||
case QETH_CARD_TYPE_OSM:
|
||||
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
|
||||
qeth_determine_capabilities(card);
|
||||
enforced_disc = qeth_enforce_discipline(card);
|
||||
switch (enforced_disc) {
|
||||
case QETH_DISCIPLINE_UNDETERMINED:
|
||||
gdev->dev.type = &qeth_generic_devtype;
|
||||
break;
|
||||
default:
|
||||
card->info.layer_enforced = true;
|
||||
rc = qeth_core_load_discipline(card, enforced_disc);
|
||||
if (rc)
|
||||
goto err_card;
|
||||
|
||||
|
@ -5675,16 +5688,11 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
|||
if (rc)
|
||||
goto err_disc;
|
||||
break;
|
||||
default:
|
||||
gdev->dev.type = &qeth_generic_devtype;
|
||||
break;
|
||||
}
|
||||
|
||||
write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
|
||||
list_add_tail(&card->list, &qeth_core_card_list.list);
|
||||
write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
|
||||
|
||||
qeth_determine_capabilities(card);
|
||||
return 0;
|
||||
|
||||
err_disc:
|
||||
|
@ -5721,7 +5729,7 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
|
|||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
int rc = 0;
|
||||
int def_discipline;
|
||||
enum qeth_discipline_id def_discipline;
|
||||
|
||||
if (!card->discipline) {
|
||||
if (card->info.type == QETH_CARD_TYPE_IQD)
|
||||
|
@ -6406,11 +6414,8 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
|
|||
features &= ~NETIF_F_IP_CSUM;
|
||||
if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
|
||||
features &= ~NETIF_F_RXCSUM;
|
||||
if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
|
||||
if (!qeth_is_supported(card, IPA_OUTBOUND_TSO))
|
||||
features &= ~NETIF_F_TSO;
|
||||
dev_info(&card->gdev->dev, "Outbound TSO not supported on %s\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
}
|
||||
/* if the card isn't up, remove features that require hw changes */
|
||||
if (card->state == CARD_STATE_DOWN ||
|
||||
card->state == CARD_STATE_RECOVER)
|
||||
|
|
|
@ -167,6 +167,8 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
|
|||
{IPA_RC_IP_TABLE_FULL, "Add Addr IP Table Full - ipv6"},
|
||||
{IPA_RC_UNKNOWN_ERROR, "IPA command failed - reason unknown"},
|
||||
{IPA_RC_UNSUPPORTED_COMMAND, "Command not supported"},
|
||||
{IPA_RC_TRACE_ALREADY_ACTIVE, "trace already active"},
|
||||
{IPA_RC_INVALID_FORMAT, "invalid format or length"},
|
||||
{IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"},
|
||||
{IPA_RC_DUP_IPV6_HOME, "ipv6 address already registered"},
|
||||
{IPA_RC_UNREGISTERED_ADDR, "Address not registered"},
|
||||
|
|
|
@ -192,7 +192,7 @@ enum qeth_ipa_funcs {
|
|||
IPA_ARP_PROCESSING = 0x00000001L,
|
||||
IPA_INBOUND_CHECKSUM = 0x00000002L,
|
||||
IPA_OUTBOUND_CHECKSUM = 0x00000004L,
|
||||
IPA_IP_FRAGMENTATION = 0x00000008L,
|
||||
/* RESERVED = 0x00000008L,*/
|
||||
IPA_FILTERING = 0x00000010L,
|
||||
IPA_IPV6 = 0x00000020L,
|
||||
IPA_MULTICASTING = 0x00000040L,
|
||||
|
|
|
@ -413,7 +413,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
|
|||
|
||||
if (card->options.layer2 == newdis)
|
||||
goto out;
|
||||
if (card->info.type == QETH_CARD_TYPE_OSM) {
|
||||
if (card->info.layer_enforced) {
|
||||
/* fixed layer, can't switch */
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
|
|
|
@ -1017,6 +1017,13 @@ static int qeth_l2_start_ipassists(struct qeth_card *card)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void qeth_l2_trace_features(struct qeth_card *card)
|
||||
{
|
||||
QETH_CARD_TEXT(card, 2, "l2featur");
|
||||
QETH_CARD_HEX(card, 2, &card->options.sbp.supported_funcs,
|
||||
sizeof(card->options.sbp.supported_funcs));
|
||||
}
|
||||
|
||||
static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
|
@ -1040,6 +1047,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
dev_info(&card->gdev->dev,
|
||||
"The device represents a Bridge Capable Port\n");
|
||||
qeth_trace_features(card);
|
||||
qeth_l2_trace_features(card);
|
||||
|
||||
if (!card->dev && qeth_l2_setup_netdev(card)) {
|
||||
rc = -ENODEV;
|
||||
|
|
|
@ -65,6 +65,7 @@ struct qeth_ipato_entry {
|
|||
int mask_bits;
|
||||
};
|
||||
|
||||
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_string_to_ipaddr(const char *, enum qeth_prot_versions, __u8 *);
|
||||
|
|
|
@ -956,31 +956,6 @@ static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_start_ipa_ip_fragmentation(struct qeth_card *card)
|
||||
{
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "ipaipfrg");
|
||||
|
||||
if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
|
||||
dev_info(&card->gdev->dev,
|
||||
"Hardware IP fragmentation not supported on %s\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Starting IP fragmentation support for %s failed\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
} else
|
||||
dev_info(&card->gdev->dev,
|
||||
"Hardware IP fragmentation enabled \n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
|
||||
{
|
||||
int rc;
|
||||
|
@ -1060,9 +1035,6 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
|
|||
|
||||
QETH_CARD_TEXT(card, 3, "softipv6");
|
||||
|
||||
if (card->info.type == QETH_CARD_TYPE_IQD)
|
||||
goto out;
|
||||
|
||||
rc = qeth_query_ipassists(card, QETH_PROT_IPV6);
|
||||
if (rc) {
|
||||
dev_err(&card->gdev->dev,
|
||||
|
@ -1070,6 +1042,10 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
|
|||
QETH_CARD_IFNAME(card));
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (card->info.type == QETH_CARD_TYPE_IQD)
|
||||
goto out;
|
||||
|
||||
rc = qeth_send_simple_setassparms(card, IPA_IPV6,
|
||||
IPA_CMD_ASS_START, 3);
|
||||
if (rc) {
|
||||
|
@ -1171,7 +1147,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
|
|||
if (qeth_set_access_ctrl_online(card, 0))
|
||||
return -EIO;
|
||||
qeth_l3_start_ipa_arp_processing(card); /* go on*/
|
||||
qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/
|
||||
qeth_l3_start_ipa_source_mac(card); /* go on*/
|
||||
qeth_l3_start_ipa_vlan(card); /* go on*/
|
||||
qeth_l3_start_ipa_multicast(card); /* go on*/
|
||||
|
@ -2702,8 +2677,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
|||
use_tso = skb_is_gso(skb) &&
|
||||
(qeth_get_ip_protocol(skb) == IPPROTO_TCP) && (ipv == 4);
|
||||
|
||||
if ((card->info.type == QETH_CARD_TYPE_IQD) &&
|
||||
!skb_is_nonlinear(skb)) {
|
||||
if (card->info.type == QETH_CARD_TYPE_IQD) {
|
||||
new_skb = skb;
|
||||
data_offset = ETH_HLEN;
|
||||
hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
|
||||
|
@ -2716,12 +2690,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
|||
+ VLAN_HLEN);
|
||||
if (!new_skb)
|
||||
goto tx_drop;
|
||||
}
|
||||
|
||||
if (card->info.type == QETH_CARD_TYPE_IQD) {
|
||||
if (data_offset < 0)
|
||||
skb_pull(new_skb, ETH_HLEN);
|
||||
} else {
|
||||
if (ipv == 4) {
|
||||
skb_pull(new_skb, ETH_HLEN);
|
||||
}
|
||||
|
@ -3036,14 +3005,21 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
|
|||
return register_netdev(card->dev);
|
||||
}
|
||||
|
||||
static const struct device_type qeth_l3_devtype = {
|
||||
.name = "qeth_layer3",
|
||||
.groups = qeth_l3_attr_groups,
|
||||
};
|
||||
|
||||
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
int rc;
|
||||
|
||||
rc = qeth_l3_create_device_attributes(&gdev->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (gdev->dev.type == &qeth_generic_devtype) {
|
||||
rc = qeth_l3_create_device_attributes(&gdev->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
hash_init(card->ip_htable);
|
||||
hash_init(card->ip_mc_htable);
|
||||
card->options.layer2 = 0;
|
||||
|
@ -3055,7 +3031,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
|
|||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
|
||||
|
||||
qeth_l3_remove_device_attributes(&cgdev->dev);
|
||||
if (cgdev->dev.type == &qeth_generic_devtype)
|
||||
qeth_l3_remove_device_attributes(&cgdev->dev);
|
||||
|
||||
qeth_set_allowed_threads(card, 0, 1);
|
||||
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
|
||||
|
@ -3311,7 +3288,7 @@ static int qeth_l3_control_event(struct qeth_card *card,
|
|||
}
|
||||
|
||||
struct qeth_discipline qeth_l3_discipline = {
|
||||
.devtype = &qeth_generic_devtype,
|
||||
.devtype = &qeth_l3_devtype,
|
||||
.start_poll = qeth_qdio_start_poll,
|
||||
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
|
||||
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
|
||||
|
|
|
@ -1049,3 +1049,14 @@ void qeth_l3_remove_device_attributes(struct device *dev)
|
|||
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
|
||||
sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
|
||||
}
|
||||
|
||||
const struct attribute_group *qeth_l3_attr_groups[] = {
|
||||
&qeth_device_attr_group,
|
||||
&qeth_device_blkt_group,
|
||||
/* l3 specific, see l3_{create,remove}_device_attributes(): */
|
||||
&qeth_l3_device_attr_group,
|
||||
&qeth_device_ipato_group,
|
||||
&qeth_device_vipa_group,
|
||||
&qeth_device_rxip_group,
|
||||
NULL,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue