struct qeth_ipa_cmd *cmd);
};
-struct qeth_vlan_vid {
- struct list_head list;
- unsigned short vid;
-};
-
enum qeth_addr_disposition {
QETH_DISP_ADDR_DELETE = 0,
QETH_DISP_ADDR_DO_NOTHING = 1,
wait_queue_head_t wait_q;
spinlock_t mclock;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
- struct mutex vid_list_mutex; /* vid_list */
- struct list_head vid_list;
DECLARE_HASHTABLE(mac_htable, 4);
DECLARE_HASHTABLE(ip_htable, 4);
DECLARE_HASHTABLE(ip_mc_htable, 4);
spin_lock_init(&card->thread_mask_lock);
mutex_init(&card->conf_mutex);
mutex_init(&card->discipline_mutex);
- mutex_init(&card->vid_list_mutex);
INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
INIT_LIST_HEAD(&card->cmd_waiter_list);
init_waitqueue_head(&card->wait_q);
return (rc_ipv6) ? rc_ipv6 : rc_ipv4;
}
-#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \
- NETIF_F_IPV6_CSUM | NETIF_F_TSO6)
/**
* qeth_enable_hw_features() - (Re-)Enable HW functions for device features
* @dev: a net_device
netdev_features_t features;
features = dev->features;
- /* force-off any feature that needs an IPA sequence.
+ /* force-off any feature that might need an IPA sequence.
* netdev_update_features() will restart them.
*/
- dev->features &= ~QETH_HW_FEATURES;
+ dev->features &= ~dev->hw_features;
+ /* toggle VLAN filter, so that VIDs are re-programmed: */
+ if (IS_LAYER2(card) && IS_VM_NIC(card)) {
+ dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
+ dev->wanted_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ }
netdev_update_features(dev);
if (features != dev->features)
dev_warn(&card->gdev->dev,
qeth_l2_send_setdelvlan_cb, NULL));
}
-static void qeth_l2_process_vlans(struct qeth_card *card)
-{
- struct qeth_vlan_vid *id;
-
- QETH_CARD_TEXT(card, 3, "L2prcvln");
- mutex_lock(&card->vid_list_mutex);
- list_for_each_entry(id, &card->vid_list, list) {
- qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
- }
- mutex_unlock(&card->vid_list_mutex);
-}
-
static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
__be16 proto, u16 vid)
{
struct qeth_card *card = dev->ml_priv;
- struct qeth_vlan_vid *id;
- int rc;
QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
if (!vid)
return 0;
- id = kmalloc(sizeof(*id), GFP_KERNEL);
- if (id) {
- id->vid = vid;
- rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
- if (rc) {
- kfree(id);
- return rc;
- }
- mutex_lock(&card->vid_list_mutex);
- list_add_tail(&id->list, &card->vid_list);
- mutex_unlock(&card->vid_list_mutex);
- } else {
- return -ENOMEM;
- }
- return 0;
+ return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
}
static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
__be16 proto, u16 vid)
{
- struct qeth_vlan_vid *id, *tmpid = NULL;
struct qeth_card *card = dev->ml_priv;
- int rc = 0;
QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
+ if (!vid)
+ return 0;
- mutex_lock(&card->vid_list_mutex);
- list_for_each_entry(id, &card->vid_list, list) {
- if (id->vid == vid) {
- list_del(&id->list);
- tmpid = id;
- break;
- }
- }
- mutex_unlock(&card->vid_list_mutex);
- if (tmpid) {
- rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
- kfree(tmpid);
- }
- return rc;
+ return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
}
static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
if (rc)
return rc;
}
- INIT_LIST_HEAD(&card->vid_list);
+
hash_init(card->mac_htable);
card->info.hwtrap = 0;
qeth_l2_vnicc_set_defaults(card);
card->dev->needed_headroom = sizeof(struct qeth_hdr);
}
- if (card->info.type == QETH_CARD_TYPE_OSM)
+ if (IS_OSM(card)) {
card->dev->features |= NETIF_F_VLAN_CHALLENGED;
- else
+ } else {
+ if (!IS_VM_NIC(card))
+ card->dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+ }
if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
card->dev->features |= NETIF_F_SG;
goto out_remove;
}
- if (card->info.type != QETH_CARD_TYPE_OSN)
- qeth_l2_process_vlans(card);
-
rc = qeth_init_qdio_queues(card);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);