Commit 52358cb5 authored by David S. Miller's avatar David S. Miller

Merge branch 's390-qeth-next'

Julian Wiedmann says:

====================
s390/qeth: updates 2018-11-08

please apply the following qeth patches to net-next.

The first patch allows one more device type to query the FW for a MAC address,
the others are all basically just removal of duplicated or unused code.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 04087d9a ded9da1f
...@@ -314,7 +314,7 @@ struct qeth_hdr_layer3 { ...@@ -314,7 +314,7 @@ struct qeth_hdr_layer3 {
__u16 frame_offset; __u16 frame_offset;
union { union {
/* TX: */ /* TX: */
u8 ipv6_addr[16]; struct in6_addr ipv6_addr;
struct ipv4 { struct ipv4 {
u8 res[12]; u8 res[12];
u32 addr; u32 addr;
...@@ -665,7 +665,6 @@ struct qeth_card_blkt { ...@@ -665,7 +665,6 @@ struct qeth_card_blkt {
#define QETH_BROADCAST_WITH_ECHO 0x01 #define QETH_BROADCAST_WITH_ECHO 0x01
#define QETH_BROADCAST_WITHOUT_ECHO 0x02 #define QETH_BROADCAST_WITHOUT_ECHO 0x02
#define QETH_LAYER2_MAC_READ 0x01
#define QETH_LAYER2_MAC_REGISTERED 0x02 #define QETH_LAYER2_MAC_REGISTERED 0x02
struct qeth_card_info { struct qeth_card_info {
unsigned short unit_addr2; unsigned short unit_addr2;
...@@ -775,7 +774,6 @@ struct qeth_switch_info { ...@@ -775,7 +774,6 @@ struct qeth_switch_info {
#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT #define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT
struct qeth_card { struct qeth_card {
struct list_head list;
enum qeth_card_states state; enum qeth_card_states state;
spinlock_t lock; spinlock_t lock;
struct ccwgroup_device *gdev; struct ccwgroup_device *gdev;
...@@ -827,11 +825,6 @@ struct qeth_card { ...@@ -827,11 +825,6 @@ struct qeth_card {
struct work_struct close_dev_work; struct work_struct close_dev_work;
}; };
struct qeth_card_list_struct {
struct list_head list;
rwlock_t rwlock;
};
struct qeth_trap_id { struct qeth_trap_id {
__u16 lparnr; __u16 lparnr;
char vmname[8]; char vmname[8];
...@@ -978,11 +971,11 @@ int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id); ...@@ -978,11 +971,11 @@ int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
void qeth_core_free_discipline(struct qeth_card *); void qeth_core_free_discipline(struct qeth_card *);
/* exports for qeth discipline device drivers */ /* exports for qeth discipline device drivers */
extern struct qeth_card_list_struct qeth_core_card_list;
extern struct kmem_cache *qeth_core_header_cache; extern struct kmem_cache *qeth_core_header_cache;
extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS]; extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
struct net_device *qeth_clone_netdev(struct net_device *orig); struct net_device *qeth_clone_netdev(struct net_device *orig);
struct qeth_card *qeth_get_card_by_busid(char *bus_id);
void qeth_set_recovery_task(struct qeth_card *); void qeth_set_recovery_task(struct qeth_card *);
void qeth_clear_recovery_task(struct qeth_card *); void qeth_clear_recovery_task(struct qeth_card *);
void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int); void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
...@@ -1025,9 +1018,6 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, ...@@ -1025,9 +1018,6 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
void *reply_param); void *reply_param);
unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset); unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset);
int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb,
struct qeth_hdr *hdr, unsigned int offset,
unsigned int hd_len);
int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct sk_buff *skb, struct qeth_hdr *hdr, struct sk_buff *skb, struct qeth_hdr *hdr,
unsigned int offset, unsigned int hd_len, unsigned int offset, unsigned int hd_len,
...@@ -1058,11 +1048,6 @@ netdev_features_t qeth_features_check(struct sk_buff *skb, ...@@ -1058,11 +1048,6 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
netdev_features_t features); netdev_features_t features);
int qeth_vm_request_mac(struct qeth_card *card); int qeth_vm_request_mac(struct qeth_card *card);
int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr **hdr, unsigned int hdr_len,
unsigned int proto_len, unsigned int *elements);
void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr, unsigned int payload_len,
struct sk_buff *skb, unsigned int proto_len);
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type, struct qeth_qdio_out_q *queue, int ipv, int cast_type,
void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr, void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr,
......
This diff is collapsed.
...@@ -144,7 +144,6 @@ unsigned char IPA_PDU_HEADER[] = { ...@@ -144,7 +144,6 @@ unsigned char IPA_PDU_HEADER[] = {
sizeof(struct qeth_ipa_cmd) % 256, sizeof(struct qeth_ipa_cmd) % 256,
0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40,
}; };
EXPORT_SYMBOL_GPL(IPA_PDU_HEADER);
struct ipa_rc_msg { struct ipa_rc_msg {
enum qeth_ipa_return_codes rc; enum qeth_ipa_return_codes rc;
......
...@@ -80,7 +80,9 @@ enum qeth_card_types { ...@@ -80,7 +80,9 @@ enum qeth_card_types {
}; };
#define IS_IQD(card) ((card)->info.type == QETH_CARD_TYPE_IQD) #define IS_IQD(card) ((card)->info.type == QETH_CARD_TYPE_IQD)
#define IS_OSD(card) ((card)->info.type == QETH_CARD_TYPE_OSD)
#define IS_OSN(card) ((card)->info.type == QETH_CARD_TYPE_OSN) #define IS_OSN(card) ((card)->info.type == QETH_CARD_TYPE_OSN)
#define IS_VM_NIC(card) ((card)->info.guestlan)
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18 #define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
/* only the first two bytes are looked at in qeth_get_cardname_short */ /* only the first two bytes are looked at in qeth_get_cardname_short */
...@@ -529,17 +531,20 @@ struct qeth_query_switch_attributes { ...@@ -529,17 +531,20 @@ struct qeth_query_switch_attributes {
__u8 reserved3[8]; __u8 reserved3[8];
}; };
#define QETH_SETADP_FLAGS_VIRTUAL_MAC 0x80 /* for CHANGE_ADDR_READ_MAC */
struct qeth_ipacmd_setadpparms_hdr { struct qeth_ipacmd_setadpparms_hdr {
__u32 supp_hw_cmds; u32 supp_hw_cmds;
__u32 reserved1; u32 reserved1;
__u16 cmdlength; u16 cmdlength;
__u16 reserved2; u16 reserved2;
__u32 command_code; u32 command_code;
__u16 return_code; u16 return_code;
__u8 used_total; u8 used_total;
__u8 seq_no; u8 seq_no;
__u32 reserved3; u8 flags;
} __attribute__ ((packed)); u8 reserved3[3];
};
struct qeth_ipacmd_setadpparms { struct qeth_ipacmd_setadpparms {
struct qeth_ipacmd_setadpparms_hdr hdr; struct qeth_ipacmd_setadpparms_hdr hdr;
...@@ -828,10 +833,9 @@ enum qeth_ipa_arp_return_codes { ...@@ -828,10 +833,9 @@ enum qeth_ipa_arp_return_codes {
extern const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc); extern const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd); extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \ #define QETH_SETASS_BASE_LEN (IPA_PDU_HEADER_SIZE + \
sizeof(struct qeth_ipacmd_setassparms_hdr)) sizeof(struct qeth_ipacmd_hdr) + \
#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \ sizeof(struct qeth_ipacmd_setassparms_hdr))
QETH_SETASS_BASE_LEN)
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \ #define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
sizeof(struct qeth_ipacmd_setadpparms_hdr)) sizeof(struct qeth_ipacmd_setadpparms_hdr))
#define QETH_SNMP_SETADP_CMDLENGTH 16 #define QETH_SNMP_SETADP_CMDLENGTH 16
......
...@@ -36,28 +36,6 @@ static void qeth_l2_vnicc_init(struct qeth_card *card); ...@@ -36,28 +36,6 @@ static void qeth_l2_vnicc_init(struct qeth_card *card);
static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc, static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
u32 *timeout); u32 *timeout);
static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
{
struct qeth_card *card;
struct net_device *ndev;
__u16 temp_dev_no;
unsigned long flags;
struct ccw_dev_id read_devid;
ndev = NULL;
memcpy(&temp_dev_no, read_dev_no, 2);
read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
list_for_each_entry(card, &qeth_core_card_list.list, list) {
ccw_device_get_id(CARD_RDEV(card), &read_devid);
if (read_devid.devno == temp_dev_no) {
ndev = card->dev;
break;
}
}
read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
return ndev;
}
static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode) static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
{ {
int rc; int rc;
...@@ -461,12 +439,9 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) ...@@ -461,12 +439,9 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
/* fall back to alternative mechanism: */ /* fall back to alternative mechanism: */
} }
if (card->info.type == QETH_CARD_TYPE_IQD || if (!IS_OSN(card)) {
card->info.type == QETH_CARD_TYPE_OSM ||
card->info.type == QETH_CARD_TYPE_OSX ||
card->info.guestlan) {
rc = qeth_setadpparms_change_macaddr(card); rc = qeth_setadpparms_change_macaddr(card);
if (!rc) if (!rc && is_valid_ether_addr(card->dev->dev_addr))
goto out; goto out;
QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n", QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n",
CARD_DEVID(card), rc); CARD_DEVID(card), rc);
...@@ -917,7 +892,8 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) ...@@ -917,7 +892,8 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
PAGE_SIZE * (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)); PAGE_SIZE * (QDIO_MAX_ELEMENTS_PER_BUFFER - 1));
} }
qeth_l2_request_initial_mac(card); if (!is_valid_ether_addr(card->dev->dev_addr))
qeth_l2_request_initial_mac(card);
netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT); netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
rc = register_netdev(card->dev); rc = register_netdev(card->dev);
if (!rc && carrier_ok) if (!rc && carrier_ok)
...@@ -1288,13 +1264,16 @@ int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev, ...@@ -1288,13 +1264,16 @@ int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
int (*data_cb)(struct sk_buff *)) int (*data_cb)(struct sk_buff *))
{ {
struct qeth_card *card; struct qeth_card *card;
char bus_id[16];
u16 devno;
*dev = qeth_l2_netdev_by_devno(read_dev_no); memcpy(&devno, read_dev_no, 2);
if (*dev == NULL) sprintf(bus_id, "0.0.%04x", devno);
return -ENODEV; card = qeth_get_card_by_busid(bus_id);
card = (*dev)->ml_priv; if (!card || !IS_OSN(card))
if (!card)
return -ENODEV; return -ENODEV;
*dev = card->dev;
QETH_CARD_TEXT(card, 2, "osnreg"); QETH_CARD_TEXT(card, 2, "osnreg");
if ((assist_cb == NULL) || (data_cb == NULL)) if ((assist_cb == NULL) || (data_cb == NULL))
return -EINVAL; return -EINVAL;
......
...@@ -949,9 +949,6 @@ static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, ...@@ -949,9 +949,6 @@ static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
if (cmd->hdr.return_code == 0) if (cmd->hdr.return_code == 0)
ether_addr_copy(card->dev->dev_addr, ether_addr_copy(card->dev->dev_addr,
cmd->data.create_destroy_addr.unique_id); cmd->data.create_destroy_addr.unique_id);
else
eth_random_addr(card->dev->dev_addr);
return 0; return 0;
} }
...@@ -1685,21 +1682,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, ...@@ -1685,21 +1682,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card,
return 0; return 0;
} }
static int qeth_l3_send_ipa_arp_cmd(struct qeth_card *card,
struct qeth_cmd_buffer *iob, int len,
int (*reply_cb)(struct qeth_card *, struct qeth_reply *,
unsigned long),
void *reply_param)
{
QETH_CARD_TEXT(card, 4, "sendarp");
memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
&card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
reply_cb, reply_param);
}
static int qeth_l3_query_arp_cache_info(struct qeth_card *card, static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
enum qeth_prot_versions prot, enum qeth_prot_versions prot,
struct qeth_arp_query_info *qinfo) struct qeth_arp_query_info *qinfo)
...@@ -1719,11 +1701,9 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card, ...@@ -1719,11 +1701,9 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
return -ENOMEM; return -ENOMEM;
cmd = __ipa_cmd(iob); 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; rc = qeth_send_control_data(card,
cmd->data.setassparms.data.query_arp.no_entries = 0; QETH_SETASS_BASE_LEN + QETH_ARP_CMD_LEN,
rc = qeth_l3_send_ipa_arp_cmd(card, iob, iob, qeth_l3_arp_query_cb, qinfo);
QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
qeth_l3_arp_query_cb, (void *)qinfo);
if (rc) if (rc)
QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n", QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n",
CARD_DEVID(card), rc); CARD_DEVID(card), rc);
...@@ -1929,22 +1909,6 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb) ...@@ -1929,22 +1909,6 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
} }
} }
static void qeth_l3_fill_af_iucv_hdr(struct qeth_hdr *hdr, struct sk_buff *skb,
unsigned int data_len)
{
char daddr[16];
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
hdr->hdr.l3.length = data_len;
hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
memset(daddr, 0, sizeof(daddr));
daddr[0] = 0xfe;
daddr[1] = 0x80;
memcpy(&daddr[8], iucv_trans_hdr(skb)->destUserID, 8);
memcpy(hdr->hdr.l3.next_hop.ipv6_addr, daddr, 16);
}
static u8 qeth_l3_cast_type_to_flag(int cast_type) static u8 qeth_l3_cast_type_to_flag(int cast_type)
{ {
if (cast_type == RTN_MULTICAST) if (cast_type == RTN_MULTICAST)
...@@ -1960,6 +1924,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, ...@@ -1960,6 +1924,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type, struct sk_buff *skb, int ipv, int cast_type,
unsigned int data_len) unsigned int data_len)
{ {
struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3;
struct vlan_ethhdr *veth = vlan_eth_hdr(skb); struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
hdr->hdr.l3.length = data_len; hdr->hdr.l3.length = data_len;
...@@ -1968,6 +1933,15 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, ...@@ -1968,6 +1933,15 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
hdr->hdr.l3.id = QETH_HEADER_TYPE_L3_TSO; hdr->hdr.l3.id = QETH_HEADER_TYPE_L3_TSO;
} else { } else {
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
if (skb->protocol == htons(ETH_P_AF_IUCV)) {
l3_hdr->flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
l3_hdr->next_hop.ipv6_addr.s6_addr16[0] = htons(0xfe80);
memcpy(&l3_hdr->next_hop.ipv6_addr.s6_addr32[2],
iucv_trans_hdr(skb)->destUserID, 8);
return;
}
if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->ip_summed == CHECKSUM_PARTIAL) {
qeth_tx_csum(skb, &hdr->hdr.l3.ext_flags, ipv); qeth_tx_csum(skb, &hdr->hdr.l3.ext_flags, ipv);
/* some HW requires combined L3+L4 csum offload: */ /* some HW requires combined L3+L4 csum offload: */
...@@ -2012,13 +1986,11 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, ...@@ -2012,13 +1986,11 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
} else { } else {
/* IPv6 */ /* IPv6 */
const struct rt6_info *rt = skb_rt6_info(skb); const struct rt6_info *rt = skb_rt6_info(skb);
const struct in6_addr *next_hop;
if (rt && !ipv6_addr_any(&rt->rt6i_gateway)) if (rt && !ipv6_addr_any(&rt->rt6i_gateway))
next_hop = &rt->rt6i_gateway; l3_hdr->next_hop.ipv6_addr = rt->rt6i_gateway;
else else
next_hop = &ipv6_hdr(skb)->daddr; l3_hdr->next_hop.ipv6_addr = ipv6_hdr(skb)->daddr;
memcpy(hdr->hdr.l3.next_hop.ipv6_addr, next_hop, 16);
hdr->hdr.l3.flags |= QETH_HDR_IPV6; hdr->hdr.l3.flags |= QETH_HDR_IPV6;
if (card->info.type != QETH_CARD_TYPE_IQD) if (card->info.type != QETH_CARD_TYPE_IQD)
...@@ -2044,84 +2016,25 @@ static void qeth_l3_fixup_headers(struct sk_buff *skb) ...@@ -2044,84 +2016,25 @@ static void qeth_l3_fixup_headers(struct sk_buff *skb)
static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb, static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type) struct qeth_qdio_out_q *queue, int ipv, int cast_type)
{ {
unsigned int hw_hdr_len, proto_len, frame_len, elements;
unsigned char eth_hdr[ETH_HLEN]; unsigned char eth_hdr[ETH_HLEN];
bool is_tso = skb_is_gso(skb); unsigned int hw_hdr_len;
unsigned int data_offset = 0; int rc;
struct qeth_hdr *hdr = NULL;
unsigned int hd_len = 0;
int push_len, rc;
bool is_sg;
if (is_tso) {
hw_hdr_len = sizeof(struct qeth_hdr_tso);
proto_len = skb_transport_offset(skb) + tcp_hdrlen(skb) -
ETH_HLEN;
} else {
hw_hdr_len = sizeof(struct qeth_hdr);
proto_len = 0;
}
/* re-use the L2 header area for the HW header: */ /* re-use the L2 header area for the HW header: */
hw_hdr_len = skb_is_gso(skb) ? sizeof(struct qeth_hdr_tso) :
sizeof(struct qeth_hdr);
rc = skb_cow_head(skb, hw_hdr_len - ETH_HLEN); rc = skb_cow_head(skb, hw_hdr_len - ETH_HLEN);
if (rc) if (rc)
return rc; return rc;
skb_copy_from_linear_data(skb, eth_hdr, ETH_HLEN); skb_copy_from_linear_data(skb, eth_hdr, ETH_HLEN);
skb_pull(skb, ETH_HLEN); skb_pull(skb, ETH_HLEN);
frame_len = skb->len;
qeth_l3_fixup_headers(skb); qeth_l3_fixup_headers(skb);
push_len = qeth_add_hw_header(card, skb, &hdr, hw_hdr_len, proto_len, rc = qeth_xmit(card, skb, queue, ipv, cast_type, qeth_l3_fill_header);
&elements); if (rc == -EBUSY) {
if (push_len < 0) /* roll back to ETH header */
return push_len; skb_push(skb, ETH_HLEN);
if (is_tso || !push_len) { skb_copy_to_linear_data(skb, eth_hdr, ETH_HLEN);
/* HW header needs its own buffer element. */
hd_len = hw_hdr_len + proto_len;
data_offset = push_len + proto_len;
}
memset(hdr, 0, hw_hdr_len);
if (skb->protocol == htons(ETH_P_AF_IUCV)) {
qeth_l3_fill_af_iucv_hdr(hdr, skb, frame_len);
} else {
qeth_l3_fill_header(card, hdr, skb, ipv, cast_type, frame_len);
if (is_tso)
qeth_fill_tso_ext((struct qeth_hdr_tso *) hdr,
frame_len - proto_len, skb,
proto_len);
}
is_sg = skb_is_nonlinear(skb);
if (IS_IQD(card)) {
rc = qeth_do_send_packet_fast(queue, skb, hdr, data_offset,
hd_len);
} else {
/* TODO: drop skb_orphan() once TX completion is fast enough */
skb_orphan(skb);
rc = qeth_do_send_packet(card, queue, skb, hdr, data_offset,
hd_len, elements);
}
if (!rc) {
if (card->options.performance_stats) {
card->perf_stats.buf_elements_sent += elements;
if (is_sg)
card->perf_stats.sg_skbs_sent++;
if (is_tso) {
card->perf_stats.large_send_bytes += frame_len;
card->perf_stats.large_send_cnt++;
}
}
} else {
if (!push_len)
kmem_cache_free(qeth_core_header_cache, hdr);
if (rc == -EBUSY) {
/* roll back to ETH header */
skb_pull(skb, push_len);
skb_push(skb, ETH_HLEN);
skb_copy_to_linear_data(skb, eth_hdr, ETH_HLEN);
}
} }
return rc; return rc;
} }
...@@ -2366,9 +2279,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok) ...@@ -2366,9 +2279,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)
rc = qeth_l3_iqd_read_initial_mac(card); rc = qeth_l3_iqd_read_initial_mac(card);
if (rc) if (rc)
goto out; goto out;
if (card->options.hsuid[0])
memcpy(card->dev->perm_addr, card->options.hsuid, 9);
} else } else
return -ENODEV; return -ENODEV;
......
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