diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-29 18:54:48 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-29 18:54:48 -0700 |
commit | bf603625660b1742004bf86432ce3c210d14d4fd (patch) | |
tree | db327975e92e01f2f2badb8ec5ae55282f156674 | |
parent | fbe96f92b3d9450e77a3a4bb1d46aa1bb908c1ab (diff) | |
parent | 6656e3c4c8e0c80f2d2bfece574876d269f64861 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
[ATM]: [lec] use refcnt to protect lec_arp_entries outside lock
[ATM]: [lec] add reference counting to lec_arp entries
[ATM]: [lec] use work queue instead of timer for lec arp expiry
[ATM]: [lec] old_close is no longer used
[ATM]: [lec] convert lec_arp_table to hlist
[ATM]: [lec] header indent, comment and whitespace cleanup
[ATM]: [lec] indent, comment and whitespace cleanup [continued]
[ATM]: [lec] indent, comment and whitespace cleanup
[SCTP]: Do not timestamp every SCTP packet.
[SCTP]: Use correct mask when disabling PMTUD.
[SCTP]: Include sk_buff overhead while updating the peer's receive window.
[SCTP]: Enable Nagle algorithm by default.
[BNX2]: Disable MSI on 5706 if AMD 8132 bridge is present.
[NetLabel]: audit fixups due to delayed feedback
-rw-r--r-- | drivers/net/bnx2.c | 32 | ||||
-rw-r--r-- | include/linux/atmlec.h | 119 | ||||
-rw-r--r-- | include/linux/audit.h | 11 | ||||
-rw-r--r-- | include/linux/pci_ids.h | 1 | ||||
-rw-r--r-- | include/net/cipso_ipv4.h | 4 | ||||
-rw-r--r-- | include/net/netlabel.h | 8 | ||||
-rw-r--r-- | net/atm/lec.c | 3161 | ||||
-rw-r--r-- | net/atm/lec.h | 172 | ||||
-rw-r--r-- | net/atm/lec_arpc.h | 146 | ||||
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 4 | ||||
-rw-r--r-- | net/netlabel/netlabel_cipso_v4.c | 48 | ||||
-rw-r--r-- | net/netlabel/netlabel_domainhash.c | 82 | ||||
-rw-r--r-- | net/netlabel/netlabel_domainhash.h | 8 | ||||
-rw-r--r-- | net/netlabel/netlabel_mgmt.c | 27 | ||||
-rw-r--r-- | net/netlabel/netlabel_unlabeled.c | 34 | ||||
-rw-r--r-- | net/netlabel/netlabel_user.c | 66 | ||||
-rw-r--r-- | net/netlabel/netlabel_user.h | 16 | ||||
-rw-r--r-- | net/sctp/input.c | 8 | ||||
-rw-r--r-- | net/sctp/output.c | 10 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 3 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 10 | ||||
-rw-r--r-- | net/sctp/socket.c | 4 |
22 files changed, 1999 insertions, 1975 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 7fcf015021e..6b4edb63c4c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.44" -#define DRV_MODULE_RELDATE "August 10, 2006" +#define DRV_MODULE_VERSION "1.4.45" +#define DRV_MODULE_RELDATE "September 29, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -5805,6 +5805,34 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->cmd_ticks_int = bp->cmd_ticks; } + /* Disable MSI on 5706 if AMD 8132 bridge is found. + * + * MSI is defined to be 32-bit write. The 5706 does 64-bit MSI writes + * with byte enables disabled on the unused 32-bit word. This is legal + * but causes problems on the AMD 8132 which will eventually stop + * responding after a while. + * + * AMD believes this incompatibility is unique to the 5706, and + * prefers to locally disable MSI rather than globally disabling it + * using pci_msi_quirk. + */ + if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { + struct pci_dev *amd_8132 = NULL; + + while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_8132_BRIDGE, + amd_8132))) { + u8 rev; + + pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev); + if (rev >= 0x10 && rev <= 0x13) { + disable_msi = 1; + pci_dev_put(amd_8132); + break; + } + } + } + bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; bp->req_line_speed = 0; if (bp->phy_flags & PHY_SERDES_FLAG) { diff --git a/include/linux/atmlec.h b/include/linux/atmlec.h index f267f244276..6f5a1bab8f5 100644 --- a/include/linux/atmlec.h +++ b/include/linux/atmlec.h @@ -1,9 +1,7 @@ /* - * - * ATM Lan Emulation Daemon vs. driver interface - * - * mkiiskila@yahoo.com + * ATM Lan Emulation Daemon driver interface * + * Marko Kiiskila <mkiiskila@yahoo.com> */ #ifndef _ATMLEC_H_ @@ -13,76 +11,87 @@ #include <linux/atmioc.h> #include <linux/atm.h> #include <linux/if_ether.h> + /* ATM lec daemon control socket */ -#define ATMLEC_CTRL _IO('a',ATMIOC_LANE) -#define ATMLEC_DATA _IO('a',ATMIOC_LANE+1) -#define ATMLEC_MCAST _IO('a',ATMIOC_LANE+2) +#define ATMLEC_CTRL _IO('a', ATMIOC_LANE) +#define ATMLEC_DATA _IO('a', ATMIOC_LANE+1) +#define ATMLEC_MCAST _IO('a', ATMIOC_LANE+2) /* Maximum number of LEC interfaces (tweakable) */ #define MAX_LEC_ITF 48 -/* From the total of MAX_LEC_ITF, last NUM_TR_DEVS are reserved for Token Ring. +/* + * From the total of MAX_LEC_ITF, last NUM_TR_DEVS are reserved for Token Ring. * E.g. if MAX_LEC_ITF = 48 and NUM_TR_DEVS = 8, then lec0-lec39 are for * Ethernet ELANs and lec40-lec47 are for Token Ring ELANS. */ #define NUM_TR_DEVS 8 -typedef enum { - l_set_mac_addr, l_del_mac_addr, - l_svc_setup, - l_addr_delete, l_topology_change, - l_flush_complete, l_arp_update, - l_narp_req, /* LANE2 mandates the use of this */ - l_config, l_flush_tran_id, - l_set_lecid, l_arp_xmt, - l_rdesc_arp_xmt, - l_associate_req, - l_should_bridge /* should we bridge this MAC? */ +typedef enum { + l_set_mac_addr, + l_del_mac_addr, + l_svc_setup, + l_addr_delete, + l_topology_change, + l_flush_complete, + l_arp_update, + l_narp_req, /* LANE2 mandates the use of this */ + l_config, + l_flush_tran_id, + l_set_lecid, + l_arp_xmt, + l_rdesc_arp_xmt, + l_associate_req, + l_should_bridge /* should we bridge this MAC? */ } atmlec_msg_type; #define ATMLEC_MSG_TYPE_MAX l_should_bridge struct atmlec_config_msg { - unsigned int maximum_unknown_frame_count; - unsigned int max_unknown_frame_time; - unsigned short max_retry_count; - unsigned int aging_time; - unsigned int forward_delay_time; - unsigned int arp_response_time; - unsigned int flush_timeout; - unsigned int path_switching_delay; - unsigned int lane_version; /* LANE2: 1 for LANEv1, 2 for LANEv2 */ - int mtu; - int is_proxy; + unsigned int maximum_unknown_frame_count; + unsigned int max_unknown_frame_time; + unsigned short max_retry_count; + unsigned int aging_time; + unsigned int forward_delay_time; + unsigned int arp_response_time; + unsigned int flush_timeout; + unsigned int path_switching_delay; + unsigned int lane_version; /* LANE2: 1 for LANEv1, 2 for LANEv2 */ + int mtu; + int is_proxy; }; - + struct atmlec_msg { - atmlec_msg_type type; - int sizeoftlvs; /* LANE2: if != 0, tlvs follow */ - union { - struct { - unsigned char mac_addr[ETH_ALEN]; - unsigned char atm_addr[ATM_ESA_LEN]; - unsigned int flag;/* Topology_change flag, - remoteflag, permanent flag, - lecid, transaction id */ - unsigned int targetless_le_arp; /* LANE2 */ - unsigned int no_source_le_narp; /* LANE2 */ - } normal; - struct atmlec_config_msg config; - struct { - uint16_t lec_id; /* requestor lec_id */ - uint32_t tran_id; /* transaction id */ - unsigned char mac_addr[ETH_ALEN]; /* dst mac addr */ - unsigned char atm_addr[ATM_ESA_LEN]; /* reqestor ATM addr */ - } proxy; - /* For mapping LE_ARP requests to responses. Filled by */ - } content; /* zeppelin, returned by kernel. Used only when proxying */ + atmlec_msg_type type; + int sizeoftlvs; /* LANE2: if != 0, tlvs follow */ + union { + struct { + unsigned char mac_addr[ETH_ALEN]; + unsigned char atm_addr[ATM_ESA_LEN]; + unsigned int flag; /* + * Topology_change flag, + * remoteflag, permanent flag, + * lecid, transaction id + */ + unsigned int targetless_le_arp; /* LANE2 */ + unsigned int no_source_le_narp; /* LANE2 */ + } normal; + struct atmlec_config_msg config; + struct { + uint16_t lec_id; /* requestor lec_id */ + uint32_t tran_id; /* transaction id */ + unsigned char mac_addr[ETH_ALEN]; /* dst mac addr */ + unsigned char atm_addr[ATM_ESA_LEN]; /* reqestor ATM addr */ + } proxy; /* + * For mapping LE_ARP requests to responses. Filled by + * zeppelin, returned by kernel. Used only when proxying + */ + } content; } __ATM_API_ALIGN; struct atmlec_ioc { - int dev_num; - unsigned char atm_addr[ATM_ESA_LEN]; - unsigned char receive; /* 1= receive vcc, 0 = send vcc */ + int dev_num; + unsigned char atm_addr[ATM_ESA_LEN]; + unsigned char receive; /* 1= receive vcc, 0 = send vcc */ }; #endif /* _ATMLEC_H_ */ diff --git a/include/linux/audit.h b/include/linux/audit.h index 42719d07612..c3aa0975181 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -95,12 +95,11 @@ #define AUDIT_MAC_POLICY_LOAD 1403 /* Policy file load */ #define AUDIT_MAC_STATUS 1404 /* Changed enforcing,permissive,off */ #define AUDIT_MAC_CONFIG_CHANGE 1405 /* Changes to booleans */ -#define AUDIT_MAC_UNLBL_ACCEPT 1406 /* NetLabel: allow unlabeled traffic */ -#define AUDIT_MAC_UNLBL_DENY 1407 /* NetLabel: deny unlabeled traffic */ -#define AUDIT_MAC_CIPSOV4_ADD 1408 /* NetLabel: add CIPSOv4 DOI entry */ -#define AUDIT_MAC_CIPSOV4_DEL 1409 /* NetLabel: del CIPSOv4 DOI entry */ -#define AUDIT_MAC_MAP_ADD 1410 /* NetLabel: add LSM domain mapping */ -#define AUDIT_MAC_MAP_DEL 1411 /* NetLabel: del LSM domain mapping */ +#define AUDIT_MAC_UNLBL_ALLOW 1406 /* NetLabel: allow unlabeled traffic */ +#define AUDIT_MAC_CIPSOV4_ADD 1407 /* NetLabel: add CIPSOv4 DOI entry */ +#define AUDIT_MAC_CIPSOV4_DEL 1408 /* NetLabel: del CIPSOv4 DOI entry */ +#define AUDIT_MAC_MAP_ADD 1409 /* NetLabel: add LSM domain mapping */ +#define AUDIT_MAC_MAP_DEL 1410 /* NetLabel: del LSM domain mapping */ #define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_LAST_KERN_ANOM_MSG 1799 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b7e85ff045e..c9ffbc3843d 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -507,6 +507,7 @@ #define PCI_DEVICE_ID_AMD_8151_0 0x7454 #define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450 #define PCI_DEVICE_ID_AMD_8131_APIC 0x7451 +#define PCI_DEVICE_ID_AMD_8132_BRIDGE 0x7458 #define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090 #define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091 #define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 5d6ae1b2b19..718b4d9c891 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -129,7 +129,7 @@ extern int cipso_v4_rbm_strictvalid; #ifdef CONFIG_NETLABEL int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); int cipso_v4_doi_remove(u32 doi, - u32 audit_secid, + struct netlbl_audit *audit_info, void (*callback) (struct rcu_head * head)); struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); int cipso_v4_doi_walk(u32 *skip_cnt, @@ -145,7 +145,7 @@ static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) } static inline int cipso_v4_doi_remove(u32 doi, - u32 audit_secid, + struct netlbl_audit *audit_info, void (*callback) (struct rcu_head * head)) { return 0; diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 190bfdbbdba..c63a58058e2 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -92,11 +92,17 @@ * */ +/* NetLabel audit information */ +struct netlbl_audit { + u32 secid; + uid_t loginuid; +}; + /* Domain mapping definition struct */ struct netlbl_dom_map; /* Domain mapping operations */ -int netlbl_domhsh_remove(const char *domain, u32 audit_secid); +int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); /* LSM security attributes */ struct netlbl_lsm_cache { diff --git a/net/atm/lec.c b/net/atm/lec.c index b4aa489849d..66c57c1091a 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -1,7 +1,7 @@ /* * lec.c: Lan Emulation driver - * Marko Kiiskila mkiiskila@yahoo.com * + * Marko Kiiskila <mkiiskila@yahoo.com> */ #include <linux/kernel.h> @@ -38,7 +38,7 @@ #include <linux/if_bridge.h> #include "../bridge/br_private.h" -static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; +static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; #endif /* Modular too */ @@ -55,38 +55,41 @@ static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; #define DPRINTK(format,args...) #endif -#define DUMP_PACKETS 0 /* 0 = None, - * 1 = 30 first bytes - * 2 = Whole packet - */ +#define DUMP_PACKETS 0 /* + * 0 = None, + * 1 = 30 first bytes + * 2 = Whole packet + */ -#define LEC_UNRES_QUE_LEN 8 /* number of tx packets to queue for a - single destination while waiting for SVC */ +#define LEC_UNRES_QUE_LEN 8 /* + * number of tx packets to queue for a + * single destination while waiting for SVC + */ static int lec_open(struct net_device *dev); static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev); static int lec_close(struct net_device *dev); static struct net_device_stats *lec_get_stats(struct net_device *dev); static void lec_init(struct net_device *dev); -static struct lec_arp_table* lec_arp_find(struct lec_priv *priv, - unsigned char *mac_addr); +static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, + unsigned char *mac_addr); static int lec_arp_remove(struct lec_priv *priv, - struct lec_arp_table *to_remove); + struct lec_arp_table *to_remove); /* LANE2 functions */ -static void lane2_associate_ind (struct net_device *dev, u8 *mac_address, - u8 *tlvs, u32 sizeoftlvs); +static void lane2_associate_ind(struct net_device *dev, u8 *mac_address, + u8 *tlvs, u32 sizeoftlvs); static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force, - u8 **tlvs, u32 *sizeoftlvs); -static int lane2_associate_req (struct net_device *dev, u8 *lan_dst, - u8 *tlvs, u32 sizeoftlvs); + u8 **tlvs, u32 *sizeoftlvs); +static int lane2_associate_req(struct net_device *dev, u8 *lan_dst, + u8 *tlvs, u32 sizeoftlvs); -static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, +static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, unsigned long permanent); static void lec_arp_check_empties(struct lec_priv *priv, struct atm_vcc *vcc, struct sk_buff *skb); static void lec_arp_destroy(struct lec_priv *priv); static void lec_arp_init(struct lec_priv *priv); -static struct atm_vcc* lec_arp_resolve(struct lec_priv *priv, +static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, struct lec_arp_table **ret_entry); @@ -100,16 +103,30 @@ static void lec_set_flush_tran_id(struct lec_priv *priv, unsigned long tran_id); static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data, struct atm_vcc *vcc, - void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb)); + void (*old_push) (struct atm_vcc *vcc, + struct sk_buff *skb)); static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); +/* must be done under lec_arp_lock */ +static inline void lec_arp_hold(struct lec_arp_table *entry) +{ + atomic_inc(&entry->usage); +} + +static inline void lec_arp_put(struct lec_arp_table *entry) +{ + if (atomic_dec_and_test(&entry->usage)) + kfree(entry); +} + + static struct lane2_ops lane2_ops = { - lane2_resolve, /* resolve, spec 3.1.3 */ - lane2_associate_req, /* associate_req, spec 3.1.4 */ - NULL /* associate indicator, spec 3.1.5 */ + lane2_resolve, /* resolve, spec 3.1.3 */ + lane2_associate_req, /* associate_req, spec 3.1.4 */ + NULL /* associate indicator, spec 3.1.5 */ }; -static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; +static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* Device structures */ static struct net_device *dev_lec[MAX_LEC_ITF]; @@ -117,36 +134,39 @@ static struct net_device *dev_lec[MAX_LEC_ITF]; #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) { - struct ethhdr *eth; - char *buff; - struct lec_priv *priv; - - /* Check if this is a BPDU. If so, ask zeppelin to send - * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit - * as the Config BPDU has */ - eth = (struct ethhdr *)skb->data; - buff = skb->data + skb->dev->hard_header_len; - if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) { + struct ethhdr *eth; + char *buff; + struct lec_priv *priv; + + /* + * Check if this is a BPDU. If so, ask zeppelin to send + * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit + * as the Config BPDU has + */ + eth = (struct ethhdr *)skb->data; + buff = skb->data + skb->dev->hard_header_len; + if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) { struct sock *sk; - struct sk_buff *skb2; - struct atmlec_msg *mesg; - - skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); - if (skb2 == NULL) return; - skb2->len = sizeof(struct atmlec_msg); - mesg = (struct atmlec_msg *)skb2->data; - mesg->type = l_topology_change; - buff += 4; - mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */ - - priv = (struct lec_priv *)dev->priv; - atm_force_charge(priv->lecd, skb2->truesize); + struct sk_buff *skb2; + struct atmlec_msg *mesg; + + skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); + if (skb2 == NULL) + return; + skb2->len = sizeof(struct atmlec_msg); + mesg = (struct atmlec_msg *)skb2->data; + mesg->type = l_topology_change; + buff += 4; + mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */ + + priv = (struct lec_priv *)dev->priv; + atm_force_charge(priv->lecd, skb2->truesize); sk = sk_atm(priv->lecd); - skb_queue_tail(&sk->sk_receive_queue, skb2); - sk->sk_data_ready(sk, skb2->len); - } + skb_queue_tail(&sk->sk_receive_queue, skb2); + sk->sk_data_ready(sk, skb2->len); + } - return; + return; } #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ @@ -162,36 +182,35 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) #ifdef CONFIG_TR static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) { - struct trh_hdr *trh; - int riflen, num_rdsc; - - trh = (struct trh_hdr *)packet; - if (trh->daddr[0] & (uint8_t)0x80) - return bus_mac; /* multicast */ - - if (trh->saddr[0] & TR_RII) { - riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; - if ((ntohs(trh->rcf) >> 13) != 0) - return bus_mac; /* ARE or STE */ - } - else - return trh->daddr; /* not source routed */ - - if (riflen < 6) - return trh->daddr; /* last hop, source routed */ - - /* riflen is 6 or more, packet has more than one route descriptor */ - num_rdsc = (riflen/2) - 1; - memset(rdesc, 0, ETH_ALEN); - /* offset 4 comes from LAN destination field in LE control frames */ - if (trh->rcf & htons((uint16_t)TR_RCF_DIR_BIT)) - memcpy(&rdesc[4], &trh->rseg[num_rdsc-2], sizeof(uint16_t)); - else { - memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t)); - rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0)); - } - - return NULL; + struct trh_hdr *trh; + int riflen, num_rdsc; + + trh = (struct trh_hdr *)packet; + if (trh->daddr[0] & (uint8_t) 0x80) + return bus_mac; /* multicast */ + + if (trh->saddr[0] & TR_RII) { + riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; + if ((ntohs(trh->rcf) >> 13) != 0) + return bus_mac; /* ARE or STE */ + } else + return trh->daddr; /* not source routed */ + + if (riflen < 6) + return trh->daddr; /* last hop, source routed */ + + /* riflen is 6 or more, packet has more than one route descriptor */ + num_rdsc = (riflen / 2) - 1; + memset(rdesc, 0, ETH_ALEN); + /* offset 4 comes from LAN destination field in LE control frames */ + if (trh->rcf & htons((uint16_t) TR_RCF_DIR_BIT)) + memcpy(&rdesc[4], &trh->rseg[num_rdsc - 2], sizeof(uint16_t)); + else { + memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t)); + rdesc[5] = ((ntohs(trh->rseg[0]) & 0x000f) | (rdesc[5] & 0xf0)); + } + + return NULL; } #endif /* CONFIG_TR */ @@ -204,15 +223,14 @@ static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) * there is non-reboot way to recover if something goes wrong. */ -static int -lec_open(struct net_device *dev) +static int lec_open(struct net_device *dev) { - struct lec_priv *priv = (struct lec_priv *)dev->priv; - + struct lec_priv *priv = (struct lec_priv *)dev->priv; + netif_start_queue(dev); - memset(&priv->stats,0,sizeof(struct net_device_stats)); - - return 0; + memset(&priv->stats, 0, sizeof(struct net_device_stats)); + + return 0; } static __inline__ void @@ -231,160 +249,166 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv) priv->stats.tx_bytes += skb->len; } -static void -lec_tx_timeout(struct net_device *dev) +static void lec_tx_timeout(struct net_device *dev) { printk(KERN_INFO "%s: tx timeout\n", dev->name); dev->trans_start = jiffies; netif_wake_queue(dev); } -static int -lec_start_xmit(struct sk_buff *skb, struct net_device *dev) +static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct sk_buff *skb2; - struct lec_priv *priv = (struct lec_priv *)dev->priv; - struct lecdatahdr_8023 *lec_h; - struct atm_vcc *vcc; + struct sk_buff *skb2; + struct lec_priv *priv = (struct lec_priv *)dev->priv; + struct lecdatahdr_8023 *lec_h; + struct atm_vcc *vcc; struct lec_arp_table *entry; - unsigned char *dst; + unsigned char *dst; int min_frame_size; #ifdef CONFIG_TR - unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */ + unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */ #endif - int is_rdesc; + int is_rdesc; #if DUMP_PACKETS > 0 - char buf[300]; - int i=0; + char buf[300]; + int i = 0; #endif /* DUMP_PACKETS >0 */ - - DPRINTK("lec_start_xmit called\n"); - if (!priv->lecd) { - printk("%s:No lecd attached\n",dev->name); - priv->stats.tx_errors++; - netif_stop_queue(dev); - return -EUNATCH; - } - - DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n", - (long)skb->head, (long)skb->data, (long)skb->tail, - (long)skb->end); + + DPRINTK("lec_start_xmit called\n"); + if (!priv->lecd) { + printk("%s:No lecd attached\n", dev->name); + priv->stats.tx_errors++; + netif_stop_queue(dev); + return -EUNATCH; + } + + DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n", + (long)skb->head, (long)skb->data, (long)skb->tail, + (long)skb->end); #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0) - lec_handle_bridge(skb, dev); + if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0) + lec_handle_bridge(skb, dev); #endif - /* Make sure we have room for lec_id */ - if (skb_headroom(skb) < 2) { + /* Make sure we have room for lec_id */ + if (skb_headroom(skb) < 2) { - DPRINTK("lec_start_xmit: reallocating skb\n"); - skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); - kfree_skb(skb); - if (skb2 == NULL) return 0; - skb = skb2; - } - skb_push(skb, 2); + DPRINTK("lec_start_xmit: reallocating skb\n"); + skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); + kfree_skb(skb); + if (skb2 == NULL) + return 0; + skb = skb2; + } + skb_push(skb, 2); - /* Put le header to place, works for TokenRing too */ - lec_h = (struct lecdatahdr_8023*)skb->data; - lec_h->le_header = htons(priv->lecid); + /* Put le header to place, works for TokenRing too */ + lec_h = (struct lecdatahdr_8023 *)skb->data; + lec_h->le_header = htons(priv->lecid); #ifdef CONFIG_TR - /* Ugly. Use this to realign Token Ring packets for - * e.g. PCA-200E driver. */ - if (priv->is_trdev) { - skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); - kfree_skb(skb); - if (skb2 == NULL) return 0; - skb = skb2; - } + /* + * Ugly. Use this to realign Token Ring packets for + * e.g. PCA-200E driver. + */ + if (priv->is_trdev) { + skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); + kfree_skb(skb); + if (skb2 == NULL) + return 0; + skb = skb2; + } #endif #if DUMP_PACKETS > 0 - printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, - skb->len, priv->lecid); + printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, + skb->len, priv->lecid); #if DUMP_PACKETS >= 2 - for(i=0;i<skb->len && i <99;i++) { - sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); - } + for (i = 0; i < skb->len && i < 99; i++) { + sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); + } #elif DUMP_PACKETS >= 1 - for(i=0;i<skb->len && i < 30;i++) { - sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); - } + for (i = 0; i < skb->len && i < 30; i++) { + sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); + } #endif /* DUMP_PACKETS >= 1 */ - if (i==skb->len) - printk("%s\n",buf); - else - printk("%s...\n",buf); + if (i == skb->len) + printk("%s\n", buf); + else + printk("%s...\n", buf); #endif /* DUMP_PACKETS > 0 */ - /* Minimum ethernet-frame size */ + /* Minimum ethernet-frame size */ #ifdef CONFIG_TR - if (priv->is_trdev) - min_frame_size = LEC_MINIMUM_8025_SIZE; + if (priv->is_trdev) + min_frame_size = LEC_MINIMUM_8025_SIZE; else #endif - min_frame_size = LEC_MINIMUM_8023_SIZE; - if (skb->len < min_frame_size) { - if ((skb->len + skb_tailroom(skb)) < min_frame_size) { - skb2 = skb_copy_expand(skb, 0, - min_frame_size - skb->truesize, GFP_ATOMIC); - dev_kfree_skb(skb); - if (skb2 == NULL) { - priv->stats.tx_dropped++; - return 0; - } - skb = skb2; - } + min_frame_size = LEC_MINIMUM_8023_SIZE; + if (skb->len < min_frame_size) { + if ((skb->len + skb_tailroom(skb)) < min_frame_size) { + skb2 = skb_copy_expand(skb, 0, + min_frame_size - skb->truesize, + GFP_ATOMIC); + dev_kfree_skb(skb); + if (skb2 == NULL) { + priv->stats.tx_dropped++; + return 0; + } + skb = skb2; + } skb_put(skb, min_frame_size - skb->len); - } - - /* Send to right vcc */ - is_rdesc = 0; - dst = lec_h->h_dest; + } + + /* Send to right vcc */ + is_rdesc = 0; + dst = lec_h->h_dest; #ifdef CONFIG_TR - if (priv->is_trdev) { - dst = get_tr_dst(skb->data+2, rdesc); - if (dst == NULL) { - dst = rdesc; - is_rdesc = 1; - } - } + if (priv->is_trdev) { + dst = get_tr_dst(skb->data + 2, rdesc); + if (dst == NULL) { + dst = rdesc; + is_rdesc = 1; + } + } #endif - entry = NULL; - vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); - DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name, - vcc, vcc?vcc->flags:0, entry); - if (!vcc || !test_bit(ATM_VF_READY,&vcc->flags)) { - if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { - DPRINTK("%s:lec_start_xmit: queuing packet, ", dev->name); - DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", - lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], - lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); - skb_queue_tail(&entry->tx_wait, skb); - } else { - DPRINTK("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name); - DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", - lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], - lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); - priv->stats.tx_dropped++; - dev_kfree_skb(skb); - } - return 0; - } - -#if DUMP_PACKETS > 0 - printk("%s:sending to vpi:%d vci:%d\n", dev->name, - vcc->vpi, vcc->vci); + entry = NULL; + vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); + DPRINTK("%s:vcc:%p vcc_flags:%x, entry:%p\n", dev->name, + vcc, vcc ? vcc->flags : 0, entry); + if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) { + if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { + DPRINTK("%s:lec_start_xmit: queuing packet, ", + dev->name); + DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + lec_h->h_dest[0], lec_h->h_dest[1], + lec_h->h_dest[2], lec_h->h_dest[3], + lec_h->h_dest[4], lec_h->h_dest[5]); + skb_queue_tail(&entry->tx_wait, skb); + } else { + DPRINTK + ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", + dev->name); + DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + lec_h->h_dest[0], lec_h->h_dest[1], + lec_h->h_dest[2], lec_h->h_dest[3], + lec_h->h_dest[4], lec_h->h_dest[5]); + priv->stats.tx_dropped++; + dev_kfree_skb(skb); + } + goto out; + } +#if DUMP_PACKETS > 0 + printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci); #endif /* DUMP_PACKETS > 0 */ - - while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { - DPRINTK("lec.c: emptying tx queue, "); - DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", - lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], - lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); + + while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { + DPRINTK("lec.c: emptying tx queue, "); + DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], + lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); lec_send(vcc, skb2, priv); - } + } lec_send(vcc, skb, priv); @@ -404,210 +428,219 @@ lec_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_wake_queue(dev); |