mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (37 commits) forcedeth bug fix: realtek phy forcedeth bug fix: vitesse phy forcedeth bug fix: cicada phy atl1: reorder atl1_main functions atl1: fix excessively indented code atl1: cleanup atl1_main atl1: header file cleanup atl1: remove irq_sem cdc-subset to support new vendor/product ID 8139cp: implement the missing dev->tx_timeout myri10ge: Remove nonsensical limit in the tx done routine gianfar: kill unused header EP93XX_ETH must select MII macb: Add multicast capability macb: Use generic PHY layer s390: add barriers to qeth driver s390: scatter-gather for inbound traffic in qeth driver eHEA: Introducing support vor DLPAR memory add Fix a potential NULL pointer dereference in free_shared_mem() in drivers/net/s2io.c [PATCH] softmac: Fix ESSID problem ...
This commit is contained in:
commit
1f1c2881f6
@ -26,7 +26,6 @@
|
||||
|
||||
TODO:
|
||||
* Test Tx checksumming thoroughly
|
||||
* Implement dev->tx_timeout
|
||||
|
||||
Low priority TODO:
|
||||
* Complete reset on PciErr
|
||||
@ -1218,6 +1217,30 @@ static int cp_close (struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cp_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct cp_private *cp = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n",
|
||||
dev->name, cpr8(Cmd), cpr16(CpCmd),
|
||||
cpr16(IntrStatus), cpr16(IntrMask));
|
||||
|
||||
spin_lock_irqsave(&cp->lock, flags);
|
||||
|
||||
cp_stop_hw(cp);
|
||||
cp_clean_rings(cp);
|
||||
rc = cp_init_rings(cp);
|
||||
cp_start_hw(cp);
|
||||
|
||||
netif_wake_queue(dev);
|
||||
|
||||
spin_unlock_irqrestore(&cp->lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef BROKEN
|
||||
static int cp_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
@ -1920,10 +1943,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dev->change_mtu = cp_change_mtu;
|
||||
#endif
|
||||
dev->ethtool_ops = &cp_ethtool_ops;
|
||||
#if 0
|
||||
dev->tx_timeout = cp_tx_timeout;
|
||||
dev->watchdog_timeo = TX_TIMEOUT;
|
||||
#endif
|
||||
|
||||
#if CP_VLAN_TAG_USED
|
||||
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
|
||||
|
@ -205,7 +205,7 @@ config MII
|
||||
config MACB
|
||||
tristate "Atmel MACB support"
|
||||
depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
|
||||
select MII
|
||||
select PHYLIB
|
||||
help
|
||||
The Atmel MACB ethernet interface is found on many AT32 and AT91
|
||||
parts. Say Y to include support for the MACB chip.
|
||||
|
@ -43,6 +43,7 @@ config ARM_AT91_ETHER
|
||||
config EP93XX_ETH
|
||||
tristate "EP93xx Ethernet support"
|
||||
depends on ARM && ARCH_EP93XX
|
||||
select MII
|
||||
help
|
||||
This is a driver for the ethernet hardware included in EP93xx CPUs.
|
||||
Say Y if you are building a kernel for EP93xx based devices.
|
||||
|
@ -43,6 +43,7 @@ extern const struct ethtool_ops atl1_ethtool_ops;
|
||||
struct atl1_adapter;
|
||||
|
||||
#define ATL1_MAX_INTR 3
|
||||
#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */
|
||||
|
||||
#define ATL1_DEFAULT_TPD 256
|
||||
#define ATL1_MAX_TPD 1024
|
||||
@ -57,29 +58,45 @@ struct atl1_adapter;
|
||||
#define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc)
|
||||
|
||||
/*
|
||||
* This detached comment is preserved for documentation purposes only.
|
||||
* It was originally attached to some code that got deleted, but seems
|
||||
* important enough to keep around...
|
||||
*
|
||||
* <begin detached comment>
|
||||
* Some workarounds require millisecond delays and are run during interrupt
|
||||
* context. Most notably, when establishing link, the phy may need tweaking
|
||||
* but cannot process phy register reads/writes faster than millisecond
|
||||
* intervals...and we establish link due to a "link status change" interrupt.
|
||||
* <end detached comment>
|
||||
*/
|
||||
|
||||
/*
|
||||
* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
* atl1_ring_header represents a single, contiguous block of DMA space
|
||||
* mapped for the three descriptor rings (tpd, rfd, rrd) and the two
|
||||
* message blocks (cmb, smb) described below
|
||||
*/
|
||||
struct atl1_ring_header {
|
||||
void *desc; /* virtual address */
|
||||
dma_addr_t dma; /* physical address*/
|
||||
unsigned int size; /* length in bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* atl1_buffer is wrapper around a pointer to a socket buffer
|
||||
* so a DMA handle can be stored along with the skb
|
||||
*/
|
||||
struct atl1_buffer {
|
||||
struct sk_buff *skb;
|
||||
u16 length;
|
||||
u16 alloced;
|
||||
struct sk_buff *skb; /* socket buffer */
|
||||
u16 length; /* rx buffer length */
|
||||
u16 alloced; /* 1 if skb allocated */
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
#define MAX_TX_BUF_LEN 0x3000 /* 12KB */
|
||||
|
||||
/* transmit packet descriptor (tpd) ring */
|
||||
struct atl1_tpd_ring {
|
||||
void *desc; /* pointer to the descriptor ring memory */
|
||||
dma_addr_t dma; /* physical adress of the descriptor ring */
|
||||
u16 size; /* length of descriptor ring in bytes */
|
||||
void *desc; /* descriptor ring virtual address */
|
||||
dma_addr_t dma; /* descriptor ring physical address */
|
||||
u16 size; /* descriptor ring length in bytes */
|
||||
u16 count; /* number of descriptors in the ring */
|
||||
u16 hw_idx; /* hardware index */
|
||||
atomic_t next_to_clean;
|
||||
@ -87,36 +104,34 @@ struct atl1_tpd_ring {
|
||||
struct atl1_buffer *buffer_info;
|
||||
};
|
||||
|
||||
/* receive free descriptor (rfd) ring */
|
||||
struct atl1_rfd_ring {
|
||||
void *desc;
|
||||
dma_addr_t dma;
|
||||
u16 size;
|
||||
u16 count;
|
||||
void *desc; /* descriptor ring virtual address */
|
||||
dma_addr_t dma; /* descriptor ring physical address */
|
||||
u16 size; /* descriptor ring length in bytes */
|
||||
u16 count; /* number of descriptors in the ring */
|
||||
atomic_t next_to_use;
|
||||
u16 next_to_clean;
|
||||
struct atl1_buffer *buffer_info;
|
||||
};
|
||||
|
||||
/* receive return descriptor (rrd) ring */
|
||||
struct atl1_rrd_ring {
|
||||
void *desc;
|
||||
dma_addr_t dma;
|
||||
unsigned int size;
|
||||
u16 count;
|
||||
void *desc; /* descriptor ring virtual address */
|
||||
dma_addr_t dma; /* descriptor ring physical address */
|
||||
unsigned int size; /* descriptor ring length in bytes */
|
||||
u16 count; /* number of descriptors in the ring */
|
||||
u16 next_to_use;
|
||||
atomic_t next_to_clean;
|
||||
};
|
||||
|
||||
struct atl1_ring_header {
|
||||
void *desc; /* pointer to the descriptor ring memory */
|
||||
dma_addr_t dma; /* physical adress of the descriptor ring */
|
||||
unsigned int size; /* length of descriptor ring in bytes */
|
||||
};
|
||||
|
||||
/* coalescing message block (cmb) */
|
||||
struct atl1_cmb {
|
||||
struct coals_msg_block *cmb;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
/* statistics message block (smb) */
|
||||
struct atl1_smb {
|
||||
struct stats_msg_block *smb;
|
||||
dma_addr_t dma;
|
||||
@ -141,24 +156,26 @@ struct atl1_sft_stats {
|
||||
u64 tx_aborted_errors;
|
||||
u64 tx_window_errors;
|
||||
u64 tx_carrier_errors;
|
||||
|
||||
u64 tx_pause; /* num Pause packet transmitted. */
|
||||
u64 excecol; /* num tx packets aborted due to excessive collisions. */
|
||||
u64 deffer; /* num deferred tx packets */
|
||||
u64 scc; /* num packets subsequently transmitted successfully w/ single prior collision. */
|
||||
u64 mcc; /* num packets subsequently transmitted successfully w/ multiple prior collisions. */
|
||||
u64 tx_pause; /* num pause packets transmitted. */
|
||||
u64 excecol; /* num tx packets w/ excessive collisions. */
|
||||
u64 deffer; /* num tx packets deferred */
|
||||
u64 scc; /* num packets subsequently transmitted
|
||||
* successfully w/ single prior collision. */
|
||||
u64 mcc; /* num packets subsequently transmitted
|
||||
* successfully w/ multiple prior collisions. */
|
||||
u64 latecol; /* num tx packets w/ late collisions. */
|
||||
u64 tx_underun; /* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
|
||||
u64 tx_trunc; /* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */
|
||||
u64 tx_underun; /* num tx packets aborted due to transmit
|
||||
* FIFO underrun, or TRD FIFO underrun */
|
||||
u64 tx_trunc; /* num tx packets truncated due to size
|
||||
* exceeding MTU, regardless whether truncated
|
||||
* by the chip or not. (The name doesn't really
|
||||
* reflect the meaning in this case.) */
|
||||
u64 rx_pause; /* num Pause packets received. */
|
||||
u64 rx_rrd_ov;
|
||||
u64 rx_trunc;
|
||||
};
|
||||
|
||||
/* board specific private data structure */
|
||||
#define ATL1_REGS_LEN 8
|
||||
|
||||
/* Structure containing variables used by the shared code */
|
||||
/* hardware structure */
|
||||
struct atl1_hw {
|
||||
u8 __iomem *hw_addr;
|
||||
struct atl1_adapter *back;
|
||||
@ -167,24 +184,35 @@ struct atl1_hw {
|
||||
enum atl1_dma_req_block dmar_block;
|
||||
enum atl1_dma_req_block dmaw_block;
|
||||
u8 preamble_len;
|
||||
u8 max_retry; /* Retransmission maximum, after which the packet will be discarded */
|
||||
u8 jam_ipg; /* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */
|
||||
u8 ipgt; /* Desired back to back inter-packet gap. The default is 96-bit time */
|
||||
u8 min_ifg; /* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */
|
||||
u8 max_retry; /* Retransmission maximum, after which the
|
||||
* packet will be discarded */
|
||||
u8 jam_ipg; /* IPG to start JAM for collision based flow
|
||||
* control in half-duplex mode. In units of
|
||||
* 8-bit time */
|
||||
u8 ipgt; /* Desired back to back inter-packet gap.
|
||||
* The default is 96-bit time */
|
||||
u8 min_ifg; /* Minimum number of IFG to enforce in between
|
||||
* receive frames. Frame gap below such IFP
|
||||
* is dropped */
|
||||
u8 ipgr1; /* 64bit Carrier-Sense window */
|
||||
u8 ipgr2; /* 96-bit IPG window */
|
||||
u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */
|
||||
u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */
|
||||
u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned
|
||||
* burst. Each TPD is 16 bytes long */
|
||||
u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned
|
||||
* burst. Each RFD is 12 bytes long */
|
||||
u8 rfd_fetch_gap;
|
||||
u8 rrd_burst; /* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */
|
||||
u8 rrd_burst; /* Threshold number of RRDs that can be retired
|
||||
* in a burst. Each RRD is 16 bytes long */
|
||||
u8 tpd_fetch_th;
|
||||
u8 tpd_fetch_gap;
|
||||
u16 tx_jumbo_task_th;
|
||||
u16 txf_burst; /* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is
|
||||
8 bytes long */
|
||||
u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */
|
||||
u16 txf_burst; /* Number of data bytes to read in a cache-
|
||||
* aligned burst. Each SRAM entry is 8 bytes */
|
||||
u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN
|
||||
* packets should add 4 bytes */
|
||||
u16 rx_jumbo_lkah;
|
||||
u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after every 512ns passes. */
|
||||
u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after
|
||||
* every 512ns passes. */
|
||||
u16 lcol; /* Collision Window */
|
||||
|
||||
u16 cmb_tpd;
|
||||
@ -194,48 +222,35 @@ struct atl1_hw {
|
||||
u32 smb_timer;
|
||||
u16 media_type;
|
||||
u16 autoneg_advertised;
|
||||
u16 pci_cmd_word;
|
||||
|
||||
u16 mii_autoneg_adv_reg;
|
||||
u16 mii_1000t_ctrl_reg;
|
||||
|
||||
u32 mem_rang;
|
||||
u32 txcw;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
u32 mc_filter_type;
|
||||
u32 num_mc_addrs;
|
||||
u32 collision_delta;
|
||||
u32 tx_packet_delta;
|
||||
u16 phy_spd_default;
|
||||
|
||||
u16 dev_rev;
|
||||
|
||||
/* spi flash */
|
||||
u8 flash_vendor;
|
||||
|
||||
u8 dma_fairness;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 perm_mac_addr[ETH_ALEN];
|
||||
|
||||
/* bool phy_preamble_sup; */
|
||||
bool phy_configured;
|
||||
};
|
||||
|
||||
struct atl1_adapter {
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
struct net_device_stats net_stats;
|
||||
struct atl1_sft_stats soft_stats;
|
||||
|
||||
struct vlan_group *vlgrp;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t lock;
|
||||
atomic_t irq_sem;
|
||||
struct work_struct tx_timeout_task;
|
||||
struct work_struct link_chg_task;
|
||||
struct work_struct pcie_dma_to_rst_task;
|
||||
@ -243,9 +258,7 @@ struct atl1_adapter {
|
||||
struct timer_list phy_config_timer;
|
||||
bool phy_timer_pending;
|
||||
|
||||
bool mac_disabled;
|
||||
|
||||
/* All descriptor rings' memory */
|
||||
/* all descriptor rings' memory */
|
||||
struct atl1_ring_header ring_header;
|
||||
|
||||
/* TX */
|
||||
@ -258,25 +271,16 @@ struct atl1_adapter {
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* Interrupt Moderator timer ( 2us resolution) */
|
||||
u16 imt;
|
||||
/* Interrupt Clear timer (2us resolution) */
|
||||
u16 ict;
|
||||
|
||||
/* MII interface info */
|
||||
struct mii_if_info mii;
|
||||
u16 imt; /* interrupt moderator timer (2us resolution */
|
||||
u16 ict; /* interrupt clear timer (2us resolution */
|
||||
struct mii_if_info mii; /* MII interface info */
|
||||
|
||||
/* structs defined in atl1_hw.h */
|
||||
u32 bd_number; /* board number */
|
||||
u32 bd_number; /* board number */
|
||||
bool pci_using_64;
|
||||
struct atl1_hw hw;
|
||||
struct atl1_smb smb;
|
||||
struct atl1_cmb cmb;
|
||||
|
||||
u32 pci_state[16];
|
||||
};
|
||||
|
||||
#endif /* _ATL1_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -39,13 +39,13 @@
|
||||
#include <asm/io.h>
|
||||
|
||||
#define DRV_NAME "ehea"
|
||||
#define DRV_VERSION "EHEA_0067"
|
||||
#define DRV_VERSION "EHEA_0070"
|
||||
|
||||
/* EHEA capability flags */
|
||||
/* eHEA capability flags */
|
||||
#define DLPAR_PORT_ADD_REM 1
|
||||
#define DLPAR_MEM_ADD 2
|
||||
#define DLPAR_MEM_REM 4
|
||||
#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
|
||||
#define DLPAR_MEM_ADD 2
|
||||
#define DLPAR_MEM_REM 4
|
||||
#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
|
||||
|
||||
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
|
||||
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
|
||||
@ -113,6 +113,8 @@
|
||||
/* Memory Regions */
|
||||
#define EHEA_MR_ACC_CTRL 0x00800000
|
||||
|
||||
#define EHEA_BUSMAP_START 0x8000000000000000ULL
|
||||
|
||||
#define EHEA_WATCH_DOG_TIMEOUT 10*HZ
|
||||
|
||||
/* utility functions */
|
||||
@ -186,6 +188,12 @@ struct h_epas {
|
||||
set to 0 if unused */
|
||||
};
|
||||
|
||||
struct ehea_busmap {
|
||||
unsigned int entries; /* total number of entries */
|
||||
unsigned int valid_sections; /* number of valid sections */
|
||||
u64 *vaddr;
|
||||
};
|
||||
|
||||
struct ehea_qp;
|
||||
struct ehea_cq;
|
||||
struct ehea_eq;
|
||||
@ -382,6 +390,8 @@ struct ehea_adapter {
|
||||
struct ehea_mr mr;
|
||||
u32 pd; /* protection domain */
|
||||
u64 max_mc_mac; /* max number of multicast mac addresses */
|
||||
int active_ports;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
||||
@ -431,6 +441,9 @@ struct port_res_cfg {
|
||||
int max_entries_rq3;
|
||||
};
|
||||
|
||||
enum ehea_flag_bits {
|
||||
__EHEA_STOP_XFER
|
||||
};
|
||||
|
||||
void ehea_set_ethtool_ops(struct net_device *netdev);
|
||||
int ehea_sense_port_attr(struct ehea_port *port);
|
||||
|
@ -79,6 +79,11 @@ MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
|
||||
MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
|
||||
|
||||
static int port_name_cnt = 0;
|
||||
static LIST_HEAD(adapter_list);
|
||||
u64 ehea_driver_flags = 0;
|
||||
struct workqueue_struct *ehea_driver_wq;
|
||||
struct work_struct ehea_rereg_mr_task;
|
||||
|
||||
|
||||
static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
|
||||
const struct of_device_id *id);
|
||||
@ -238,13 +243,17 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
|
||||
rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
|
||||
| EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
|
||||
rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
|
||||
rwqe->sg_list[0].vaddr = (u64)skb->data;
|
||||
rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
|
||||
rwqe->sg_list[0].len = packet_size;
|
||||
rwqe->data_segments = 1;
|
||||
|
||||
index++;
|
||||
index &= max_index_mask;
|
||||
|
||||
if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
q_skba->index = index;
|
||||
|
||||
/* Ring doorbell */
|
||||
@ -253,7 +262,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
|
||||
ehea_update_rq2a(pr->qp, i);
|
||||
else
|
||||
ehea_update_rq3a(pr->qp, i);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1321,7 +1330,7 @@ static void write_swqe2_TSO(struct sk_buff *skb,
|
||||
sg1entry->len = skb_data_size - headersize;
|
||||
|
||||
tmp_addr = (u64)(skb->data + headersize);
|
||||
sg1entry->vaddr = tmp_addr;
|
||||
sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
|
||||
swqe->descriptors++;
|
||||
}
|
||||
} else
|
||||
@ -1352,7 +1361,7 @@ static void write_swqe2_nonTSO(struct sk_buff *skb,
|
||||
sg1entry->l_key = lkey;
|
||||
sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
|
||||
tmp_addr = (u64)(skb->data + SWQE2_MAX_IMM);
|
||||
sg1entry->vaddr = tmp_addr;
|
||||
sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
|
||||
swqe->descriptors++;
|
||||
}
|
||||
} else {
|
||||
@ -1391,7 +1400,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
|
||||
sg1entry->len = frag->size;
|
||||
tmp_addr = (u64)(page_address(frag->page)
|
||||
+ frag->page_offset);
|
||||
sg1entry->vaddr = tmp_addr;
|
||||
sg1entry->vaddr = ehea_map_vaddr(tmp_addr);
|
||||
swqe->descriptors++;
|
||||
sg1entry_contains_frag_data = 1;
|
||||
}
|
||||
@ -1406,7 +1415,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
tmp_addr = (u64)(page_address(frag->page)
|
||||
+ frag->page_offset);
|
||||
sgentry->vaddr = tmp_addr;
|
||||
sgentry->vaddr = ehea_map_vaddr(tmp_addr);
|
||||
swqe->descriptors++;
|
||||
}
|
||||
}
|
||||
@ -1878,6 +1887,9 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
ehea_dump(swqe, 512, "swqe");
|
||||
}
|
||||
|
||||
if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
|
||||
goto out;
|
||||
|
||||
ehea_post_swqe(pr->qp, swqe);
|
||||
pr->tx_packets++;
|
||||
|
||||
@ -1892,7 +1904,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
dev->trans_start = jiffies;
|
||||
spin_unlock(&pr->xmit_lock);
|
||||
|
||||
out:
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
@ -2220,6 +2232,9 @@ out_dereg_bc:
|
||||
out_clean_pr:
|
||||
ehea_clean_all_portres(port);
|
||||
out:
|
||||
if (ret)
|
||||
ehea_info("Failed starting %s. ret=%i", dev->name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2259,8 +2274,13 @@ static int ehea_down(struct net_device *dev)
|
||||
msleep(1);
|
||||
|
||||
ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
|
||||
ret = ehea_clean_all_portres(port);
|
||||
port->state = EHEA_PORT_DOWN;
|
||||
|
||||
ret = ehea_clean_all_portres(port);
|
||||
if (ret)
|
||||
ehea_info("Failed freeing resources for %s. ret=%i",
|
||||
dev->name, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2292,15 +2312,11 @@ static void ehea_reset_port(struct work_struct *work)
|
||||
netif_stop_queue(dev);
|
||||
netif_poll_disable(dev);
|
||||
|
||||
ret = ehea_down(dev);
|
||||
if (ret)
|
||||
ehea_error("ehea_down failed. not all resources are freed");
|
||||
ehea_down(dev);
|
||||
|
||||
ret = ehea_up(dev);
|
||||
if (ret) {
|
||||
ehea_error("Reset device %s failed: ret=%d", dev->name, ret);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (netif_msg_timer(port))
|
||||
ehea_info("Device %s resetted successfully", dev->name);
|
||||
@ -2312,6 +2328,88 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
static void ehea_rereg_mrs(struct work_struct *work)
|
||||
{
|
||||
int ret, i;
|
||||
struct ehea_adapter *adapter;
|
||||
|
||||
ehea_info("LPAR memory enlarged - re-initializing driver");
|
||||
|
||||
list_for_each_entry(adapter, &adapter_list, list)
|
||||
if (adapter->active_ports) {
|
||||
/* Shutdown all ports */
|
||||
for (i = 0; i < EHEA_MAX_PORTS; i++) {
|
||||
struct ehea_port *port = adapter->port[i];
|
||||
|
||||
if (port) {
|
||||
struct net_device *dev = port->netdev;
|
||||
|
||||
if (dev->flags & IFF_UP) {
|
||||
ehea_info("stopping %s",
|
||||
dev->name);
|
||||
down(&port->port_lock);
|
||||
netif_stop_queue(dev);
|
||||
netif_poll_disable(dev);
|
||||
ehea_down(dev);
|
||||
up(&port->port_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Unregister old memory region */
|
||||
ret = ehea_rem_mr(&adapter->mr);
|
||||
if (ret) {
|
||||
ehea_error("unregister MR failed - driver"
|
||||
" inoperable!");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ehea_destroy_busmap();
|
||||
|
||||
ret = ehea_create_busmap();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
|
||||
|
||||
list_for_each_entry(adapter, &adapter_list, list)
|
||||
if (adapter->active_ports) {
|
||||
/* Register new memory region */
|
||||
ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
|
||||
if (ret) {
|
||||
ehea_error("register MR failed - driver"
|
||||
" inoperable!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Restart all ports */
|
||||
for (i = 0; i < EHEA_MAX_PORTS; i++) {
|
||||
struct ehea_port *port = adapter->port[i];
|
||||
|
||||
if (port) {
|
||||
struct net_device *dev = port->netdev;
|
||||
|
||||
if (dev->flags & IFF_UP) {
|
||||
ehea_info("restarting %s",
|
||||
dev->name);
|
||||
down(&port->port_lock);
|
||||
|
||||
ret = ehea_up(dev);
|
||||
if (!ret) {
|
||||
netif_poll_enable(dev);
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
up(&port->port_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static void ehea_tx_watchdog(struct net_device *dev)
|
||||
{
|
||||
struct ehea_port *port = netdev_priv(dev);
|
||||
@ -2573,6 +2671,8 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
|
||||
ehea_info("%s: Jumbo frames are %sabled", dev->name,
|
||||
jumbo == 1 ? "en" : "dis");
|
||||
|
||||
adapter->active_ports++;
|
||||
|
||||
return port;
|
||||
|
||||
out_unreg_port:
|
||||
@ -2596,6 +2696,7 @@ static void ehea_shutdown_single_port(struct ehea_port *port)
|
||||
ehea_unregister_port(port);
|
||||
kfree(port->mc_list);
|
||||
free_netdev(port->netdev);
|
||||
port->adapter->active_ports--;
|
||||
}
|
||||
|
||||
static int ehea_setup_ports(struct ehea_adapter *adapter)
|
||||
@ -2788,6 +2889,8 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_add(&adapter->list, &adapter_list);
|
||||
|
||||
adapter->ebus_dev = dev;
|
||||
|
||||
adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
|
||||
@ -2891,7 +2994,10 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev)
|
||||
|
||||
ehea_destroy_eq(adapter->neq);
|
||||
ehea_remove_adapter_mr(adapter);
|
||||
list_del(&adapter->list);
|
||||
|
||||
kfree(adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2939,9 +3045,18 @@ int __init ehea_module_init(void)
|
||||
printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
|
||||
DRV_VERSION);
|
||||
|
||||
ehea_driver_wq = create_workqueue("ehea_driver_wq");
|
||||
|
||||
INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
|
||||
|
||||
ret = check_module_parm();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = ehea_create_busmap();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = ibmebus_register_driver(&ehea_driver);
|
||||
if (ret) {
|
||||
ehea_error("failed registering eHEA device driver on ebus");
|
||||
@ -2965,6 +3080,7 @@ static void __exit ehea_module_exit(void)
|
||||
{
|
||||
driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
|
||||
ibmebus_unregister_driver(&ehea_driver);
|
||||
ehea_destroy_busmap();
|
||||
}
|
||||
|
||||
module_init(ehea_module_init);
|
||||
|
@ -60,6 +60,9 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code)
|
||||
}
|
||||
}
|
||||
|
||||
/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */
|
||||
#define EHEA_MAX_RPAGE 512
|
||||
|
||||
/* Notification Event Queue (NEQ) Entry bit masks */
|
||||
#define NEQE_EVENT_CODE EHEA_BMASK_IBM(2, 7)
|
||||
#define NEQE_PORTNUM EHEA_BMASK_IBM(32, 47)
|
||||
|
@ -31,6 +31,13 @@
|
||||
#include "ehea_phyp.h"
|
||||
#include "ehea_qmr.h"
|
||||
|
||||
|
||||
struct ehea_busmap ehea_bmap = { 0, 0, NULL };
|
||||
extern u64 ehea_driver_flags;
|
||||
extern struct workqueue_struct *ehea_driver_wq;
|
||||
extern struct work_struct ehea_rereg_mr_task;
|
||||
|
||||
|
||||
static void *hw_qpageit_get_inc(struct hw_queue *queue)
|
||||
{
|
||||
void *retvalue = hw_qeit_get(queue);
|
||||
@ -547,18 +554,84 @@ int ehea_destroy_qp(struct ehea_qp *qp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ehea_create_busmap( void )
|
||||
{
|
||||
u64 vaddr = EHEA_BUSMAP_START;
|
||||
unsigned long abs_max_pfn = 0;
|
||||
unsigned long sec_max_pfn;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Sections are not in ascending order -> Loop over all sections and
|
||||
* find the highest PFN to compute the required map size.
|
||||
*/
|
||||
ehea_bmap.valid_sections = 0;
|
||||
|
||||
for (i = 0; i < NR_MEM_SECTIONS; i++)
|
||||
if (valid_section_nr(i)) {
|
||||
sec_max_pfn = section_nr_to_pfn(i);
|
||||
if (sec_max_pfn > abs_max_pfn)
|
||||
abs_max_pfn = sec_max_pfn;
|
||||
ehea_bmap.valid_sections++;
|
||||
}
|
||||
|
||||
ehea_bmap.entries = abs_max_pfn / EHEA_PAGES_PER_SECTION + 1;
|
||||
ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr));
|
||||
|
||||
if (!ehea_bmap.vaddr)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0 ; i < ehea_bmap.entries; i++) {
|
||||
unsigned long pfn = section_nr_to_pfn(i);
|
||||
|
||||
if (pfn_valid(pfn)) {
|
||||
ehea_bmap.vaddr[i] = vaddr;
|
||||
vaddr += EHEA_SECTSIZE;
|
||||
} else
|
||||
ehea_bmap.vaddr[i] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ehea_destroy_busmap( void )
|
||||
{
|
||||
vfree(ehea_bmap.vaddr);
|
||||
}
|
||||
|
||||
u64 ehea_map_vaddr(void *caddr)
|
||||
{
|
||||
u64 mapped_addr;
|
||||
unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS;
|
||||
|
||||
if (likely(index < ehea_bmap.entries)) {
|
||||
mapped_addr = ehea_bmap.vaddr[index];
|
||||
if (likely(mapped_addr))
|
||||
mapped_addr |= (((unsigned long)caddr)
|
||||
& (EHEA_SECTSIZE - 1));
|
||||
else
|
||||
mapped_addr = -1;
|
||||
} else
|
||||
mapped_addr = -1;
|
||||
|
||||
if (unlikely(mapped_addr == -1))
|
||||
if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
|
||||
queue_work(ehea_driver_wq, &ehea_rereg_mr_task);
|
||||
|
||||
return mapped_addr;
|
||||
}
|
||||
|
||||
int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
|
||||
{
|
||||
int i, k, ret;
|
||||
u64 hret, pt_abs, start, end, nr_pages;
|
||||
u32 acc_ctrl = EHEA_MR_ACC_CTRL;
|
||||
int ret;
|
||||
u64 *pt;
|
||||
void *pg;
|
||||
u64 hret, pt_abs, i, j, m, mr_len;
|
||||
u32 acc_ctrl = EHEA_MR_ACC_CTRL;
|
||||
|
||||
start = KERNELBASE;
|
||||
end = (u64)high_memory;
|
||||
nr_pages = (end - start) / EHEA_PAGESIZE;
|
||||
mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE;
|
||||
|
||||
pt = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
pt = kzalloc(EHEA_MAX_RPAGE * sizeof(u64), GFP_KERNEL);
|
||||
if (!pt) {
|
||||
ehea_error("no mem");
|
||||
ret = -ENOMEM;
|
||||
@ -566,7 +639,8 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
|
||||
}
|
||||
pt_abs = virt_to_abs(pt);
|
||||
|
||||
hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start,
|
||||
hret = ehea_h_alloc_resource_mr(adapter->handle,
|
||||
EHEA_BUSMAP_START, mr_len,
|
||||
acc_ctrl, adapter->pd,
|
||||
&mr->handle, &mr->lkey);
|
||||
if (hret != H_SUCCESS) {
|
||||
@ -575,49 +649,43 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
|
||||
goto out;
|
||||
}
|
||||
|
||||
mr->vaddr = KERNELBASE;
|
||||
k = 0;
|
||||
for (i = 0 ; i < ehea_bmap.entries; i++)
|
||||
if (ehea_bmap.vaddr[i]) {
|
||||
void *sectbase = __va(i << SECTION_SIZE_BITS);
|
||||
unsigned long k = 0;
|
||||
|
||||
while (nr_pages > 0) {
|
||||
if (nr_pages > 1) {
|
||||
u64 num_pages = min(nr_pages, (u64)512);
|
||||
for (i = 0; i < num_pages; i++)
|
||||
pt[i] = virt_to_abs((void*)(((u64)start) +
|
||||
((k++) *
|
||||
EHEA_PAGESIZE)));
|
||||
for (j = 0; j < (PAGES_PER_SECTION / EHEA_MAX_RPAGE);
|
||||
j++) {
|
||||
|
||||
hret = ehea_h_register_rpage_mr(adapter->handle,
|
||||
mr->handle, 0,
|
||||
0, (u64)pt_abs,
|
||||
num_pages);
|
||||
nr_pages -= num_pages;
|
||||
} else {
|
||||
u64 abs_adr = virt_to_abs((void*)(((u64)start) +
|
||||
(k * EHEA_PAGESIZE)));
|
||||
for (m = 0; m < EHEA_MAX_RPAGE; m++) {
|
||||
pg = sectbase + ((k++) * EHEA_PAGESIZE);
|
||||
pt[m] = virt_to_abs(pg);
|
||||
}
|
||||
|
||||
hret = ehea_h_register_rpage_mr(adapter->handle,
|
||||
mr->handle, 0,
|
||||
0, abs_adr,1);
|
||||
nr_pages--;
|
||||
hret = ehea_h_register_rpage_mr(adapter->handle,
|
||||
mr->handle,
|
||||
0, 0, pt_abs,
|
||||
EHEA_MAX_RPAGE);
|
||||
if ((hret != H_SUCCESS)
|
||||
&& (hret != H_PAGE_REGISTERED)) {
|
||||
ehea_h_free_resource(adapter->handle,
|
||||
mr->handle,
|
||||
FORCE_FREE);
|
||||
ehea_error("register_rpage_mr failed");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) {
|
||||
ehea_h_free_resource(adapter->handle,
|
||||
mr->handle, FORCE_FREE);
|
||||
ehea_error("register_rpage_mr failed");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (hret != H_SUCCESS) {
|
||||
ehea_h_free_resource(adapter->handle, mr->handle,
|
||||
FORCE_FREE);
|
||||
ehea_error("register_rpage failed for last page");
|
||||
ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE);
|
||||
ehea_error("registering mr failed");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mr->vaddr = EHEA_BUSMAP_START;
|
||||
mr->adapter = adapter;
|
||||
ret = 0;
|
||||
out:
|
||||
|
@ -36,8 +36,14 @@
|
||||
* page size of ehea hardware queues
|
||||
*/
|
||||
|
||||
#define EHEA_PAGESHIFT 12
|
||||
#define EHEA_PAGESIZE 4096UL
|
||||
#define EHEA_PAGESHIFT 12
|
||||
#define EHEA_PAGESIZE (1UL << EHEA_PAGESHIFT)
|
||||
#define EHEA_SECTSIZE (1UL << 24)
|
||||
#define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> PAGE_SHIFT)
|
||||
|
||||
#if (1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE
|
||||
#error eHEA module can't work if kernel sectionsize < ehea sectionsize
|
||||
#endif
|
||||
|
||||
/* Some abbreviations used here:
|
||||
*
|
||||
@ -372,4 +378,8 @@ int ehea_rem_mr(struct ehea_mr *mr);
|
||||
|
||||
void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
|
||||
|
||||
int ehea_create_busmap( void );
|
||||
void ehea_destroy_busmap( void );
|
||||
u64 ehea_map_vaddr(void *caddr);
|
||||
|
||||
#endif /* __EHEA_QMR_H__ */
|
||||
|
@ -550,6 +550,8 @@ union ring_type {
|
||||
/* PHY defines */
|
||||
#define PHY_OUI_MARVELL 0x5043
|
||||
#define PHY_OUI_CICADA 0x03f1
|
||||
#define PHY_OUI_VITESSE 0x01c1
|
||||
#define PHY_OUI_REALTEK 0x01c1
|
||||
#define PHYID1_OUI_MASK 0x03ff
|
||||
#define PHYID1_OUI_SHFT 6
|
||||
#define PHYID2_OUI_MASK 0xfc00
|
||||
@ -557,12 +559,36 @@ union ring_type {
|
||||
#define PHYID2_MODEL_MASK 0x03f0
|
||||
#define PHY_MODEL_MARVELL_E3016 0x220
|
||||
#define PHY_MARVELL_E3016_INITMASK 0x0300
|
||||
#define PHY_INIT1 0x0f000
|
||||
#define PHY_INIT2 0x0e00
|
||||
#define PHY_INIT3 0x01000
|
||||
#define PHY_INIT4 0x0200
|
||||
#define PHY_INIT5 0x0004
|
||||
#define PHY_INIT6 0x02000
|
||||
#define PHY_CICADA_INIT1 0x0f000
|
||||
#define PHY_CICADA_INIT2 0x0e00
|
||||
#define PHY_CICADA_INIT3 0x01000
|
||||
#define PHY_CICADA_INIT4 0x0200
|
||||
#define PHY_CICADA_INIT5 0x0004
|
||||
#define PHY_CICADA_INIT6 0x02000
|
||||
#define PHY_VITESSE_INIT_REG1 0x1f
|
||||
#define PHY_VITESSE_INIT_REG2 0x10
|
||||
#define PHY_VITESSE_INIT_REG3 0x11
|
||||
#define PHY_VITESSE_INIT_REG4 0x12
|
||||
#define PHY_VITESSE_INIT_MSK1 0xc
|
||||
#define PHY_VITESSE_INIT_MSK2 0x0180
|
||||
#define PHY_VITESSE_INIT1 0x52b5
|
||||
#define PHY_VITESSE_INIT2 0xaf8a
|
||||
#define PHY_VITESSE_INIT3 0x8
|
||||
#define PHY_VITESSE_INIT4 0x8f8a
|
||||
#define PHY_VITESSE_INIT5 0xaf86
|
||||
#define PHY_VITESSE_INIT6 0x8f86
|
||||
#define PHY_VITESSE_INIT7 0xaf82
|
||||
#define PHY_VITESSE_INIT8 0x0100
|
||||
#define PHY_VITESSE_INIT9 0x8f82
|
||||
#define PHY_VITESSE_INIT10 0x0
|
||||
#define PHY_REALTEK_INIT_REG1 0x1f
|
||||
#define PHY_REALTEK_INIT_REG2 0x19
|
||||
#define PHY_REALTEK_INIT_REG3 0x13
|
||||
#define PHY_REALTEK_INIT1 0x0000
|
||||
#define PHY_REALTEK_INIT2 0x8e00
|
||||
#define PHY_REALTEK_INIT3 0x0001
|
||||
#define PHY_REALTEK_INIT4 0xad17
|
||||
|
||||
#define PHY_GIGABIT 0x0100
|
||||
|
||||
#define PHY_TIMEOUT 0x1
|
||||
@ -1096,6 +1122,28 @@ static int phy_init(struct net_device *dev)
|
||||
return PHY_ERROR;
|
||||
}
|
||||
}
|
||||
if (np->phy_oui == PHY_OUI_REALTEK) {
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* set advertise register */
|
||||
reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
|
||||
@ -1141,14 +1189,14 @@ static int phy_init(struct net_device *dev)
|
||||
/* phy vendor specific configuration */
|
||||
if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) {
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ);
|
||||
phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
|
||||
phy_reserved |= (PHY_INIT3 | PHY_INIT4);
|
||||
phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2);
|
||||
phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4);
|
||||
if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
|
||||
phy_reserved |= PHY_INIT5;
|
||||
phy_reserved |= PHY_CICADA_INIT5;
|
||||
if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
@ -1156,12 +1204,106 @@ static int phy_init(struct net_device *dev)
|
||||
}
|
||||
if (np->phy_oui == PHY_OUI_CICADA) {
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ);
|
||||
phy_reserved |= PHY_INIT6;
|
||||
phy_reserved |= PHY_CICADA_INIT6;
|
||||
if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
}
|
||||
if (np->phy_oui == PHY_OUI_VITESSE) {
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
|
||||
phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
|
||||
phy_reserved |= PHY_VITESSE_INIT3;
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
|
||||
phy_reserved &= ~PHY_VITESSE_INIT_MSK1;
|
||||
phy_reserved |= PHY_VITESSE_INIT3;
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ);
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ);
|
||||
phy_reserved &= ~PHY_VITESSE_INIT_MSK2;
|
||||
phy_reserved |= PHY_VITESSE_INIT8;
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
}
|
||||
if (np->phy_oui == PHY_OUI_REALTEK) {
|
||||
/* reset could have cleared these out, set them back */
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) {
|
||||
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
|
||||
return PHY_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* some phys clear out pause advertisment on reset, set it back */
|
||||
mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/ocp.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
@ -17,13 +17,12 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include <asm/arch/board.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
|
||||
#include "macb.h"
|
||||
|
||||
@ -85,172 +84,202 @@ static void __init macb_get_hwaddr(struct macb *bp)
|
||||
memcpy(bp->dev->dev_addr, addr, sizeof(addr));
|
||||
}
|
||||
|
||||
static void macb_enable_mdio(struct macb *bp)
|
||||
static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(&bp->lock, flags);
|
||||
reg = macb_readl(bp, NCR);
|
||||
reg |= MACB_BIT(MPE);
|
||||
macb_writel(bp, NCR, reg);
|
||||
macb_writel(bp, IER, MACB_BIT(MFD));
|
||||
spin_unlock_irqrestore(&bp->lock, flags);
|
||||
}
|
||||
|
||||
static void macb_disable_mdio(struct macb *bp)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(&bp->lock, flags);
|
||||
reg = macb_readl(bp, NCR);
|
||||
reg &= ~MACB_BIT(MPE);
|
||||
macb_writel(bp, NCR, reg);
|
||||
macb_writel(bp, IDR, MACB_BIT(MFD));
|
||||
spin_unlock_irqrestore(&bp->lock, flags);
|
||||
}
|
||||
|
||||
static int macb_mdio_read(struct net_device *dev, int phy_id, int location)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
struct macb *bp = bus->priv;
|
||||
int value;
|
||||
|
||||
mutex_lock(&bp->mdio_mutex);
|
||||
|
||||
macb_enable_mdio(bp);
|
||||
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
|
||||
| MACB_BF(RW, MACB_MAN_READ)
|
||||
| MACB_BF(PHYA, phy_id)
|
||||
| MACB_BF(REGA, location)
|
||||
| MACB_BF(PHYA, mii_id)
|
||||
| MACB_BF(REGA, regnum)
|
||||
| MACB_BF(CODE, MACB_MAN_CODE)));
|
||||
|
||||
wait_for_completion(&bp->mdio_complete);
|
||||
/* wait for end of transfer */
|
||||
while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
|
||||
cpu_relax();
|
||||
|
||||
value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
|
||||
macb_disable_mdio(bp);
|
||||
mutex_unlock(&bp->mdio_mutex);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void macb_mdio_write(struct net_device *dev, int phy_id,
|
||||
int location, int val)
|
||||
static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
||||
u16 value)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
|
||||
dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n",
|
||||
phy_id, location, val);
|
||||
|
||||
mutex_lock(&bp->mdio_mutex);
|
||||
macb_enable_mdio(bp);
|
||||
struct macb *bp = bus->priv;
|
||||
|
||||
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
|
||||
| MACB_BF(RW, MACB_MAN_WRITE)
|
||||
| MACB_BF(PHYA, phy_id)
|
||||
| MACB_BF(REGA, location)
|
||||
| MACB_BF(PHYA, mii_id)
|
||||
| MACB_BF(REGA, regnum)
|
||||
| MACB_BF(CODE, MACB_MAN_CODE)
|
||||
| MACB_BF(DATA, val)));
|
||||
| MACB_BF(DATA, value)));
|
||||
|
||||
wait_for_completion(&bp->mdio_complete);
|
||||
/* wait for end of transfer */
|
||||
while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
|
||||
cpu_relax();
|
||||
|
||||
macb_disable_mdio(bp);
|
||||
mutex_unlock(&bp->mdio_mutex);
|
||||
}
|
||||
|
||||
static int macb_phy_probe(struct macb *bp)
|
||||
{
|
||||
int phy_address;
|
||||
u16 phyid1, phyid2;
|
||||
|
||||
for (phy_address = 0; phy_address < 32; phy_address++) {
|
||||
phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1);
|
||||
phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2);
|
||||
|
||||
if (phyid1 != 0xffff && phyid1 != 0x0000
|
||||
&& phyid2 != 0xffff && phyid2 != 0x0000)
|
||||
break;
|
||||
}
|
||||
|
||||
if (phy_address == 32)
|
||||
return -ENODEV;
|
||||
|
||||
dev_info(&bp->pdev->dev,
|
||||
"detected PHY at address %d (ID %04x:%04x)\n",
|
||||
phy_address, phyid1, phyid2);
|
||||
|
||||
bp->mii.phy_id = phy_address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void macb_set_media(struct macb *bp, int media)
|
||||
static int macb_mdio_reset(struct mii_bus *bus)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irq(&bp->lock);
|
||||
reg = macb_readl(bp, NCFGR);
|
||||
reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
|
||||
if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL))
|
||||
reg |= MACB_BIT(SPD);
|
||||
if (media & ADVERTISE_FULL)
|
||||
reg |= MACB_BIT(FD);
|
||||
macb_writel(bp, NCFGR, reg);
|
||||
spin_unlock_irq(&bp->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void macb_check_media(struct macb *bp, int ok_to_print, int init_media)
|
||||
static void macb_handle_link_change(struct net_device *dev)
|
||||
{
|
||||
struct mii_if_info *mii = &bp->mii;
|
||||
unsigned int old_carrier, new_carrier;
|
||||
int advertise, lpa, media, duplex;
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
struct phy_device *phydev = bp->phy_dev;
|
||||
unsigned long flags;
|
||||
|
||||
/* if forced media, go no further */
|
||||
if (mii->force_media)
|
||||
return;
|
||||
int status_change = 0;
|
||||
|
||||
/* check current and old link status */
|
||||
old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
|
||||
new_carrier = (unsigned int) mii_link_ok(mii);
|
||||
spin_lock_irqsave(&bp->lock, flags);
|
||||
|
||||
/* if carrier state did not change, assume nothing else did */
|
||||
if (!init_media && old_carrier == new_carrier)
|
||||
return;
|
||||
if (phydev->link) {
|
||||
if ((bp->speed != phydev->speed) ||
|
||||
(bp->duplex != phydev->duplex)) {
|
||||
u32 reg;
|
||||
|
||||
/* no carrier, nothing much to do */
|
||||
if (!new_carrier) {
|
||||
netif_carrier_off(mii->dev);
|
||||
printk(KERN_INFO "%s: link down\n", mii->dev->name);
|
||||
return;
|
||||
reg = macb_readl(bp, NCFGR);
|
||||
reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
|
||||
|
||||
if (phydev->duplex)
|
||||
reg |= MACB_BIT(FD);
|
||||
if (phydev->speed)
|
||||
reg |= MACB_BIT(SPD);
|
||||
|
||||
macb_writel(bp, NCFGR, reg);
|
||||
|
||||
bp->speed = phydev->speed;
|
||||
bp->duplex = phydev->duplex;
|
||||
status_change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we have carrier, see who's on the other end
|
||||
*/
|
||||
netif_carrier_on(mii->dev);
|
||||
if (phydev->link != bp->link) {
|
||||
if (phydev->link)
|
||||
netif_schedule(dev);
|
||||
else {
|
||||
bp->speed = 0;
|
||||
bp->duplex = -1;
|
||||
}
|
||||
bp->link = phydev->link;
|
||||
|
||||
/* get MII advertise and LPA values */
|
||||
if (!init_media && mii->advertising) {
|
||||
advertise = mii->advertising;
|
||||
status_change = 1;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&bp->lock, flags);
|
||||
|
||||
if (status_change) {
|
||||
if (phydev->link)
|
||||
printk(KERN_INFO "%s: link up (%d/%s)\n",
|
||||
dev->name, phydev->speed,
|
||||
DUPLEX_FULL == phydev->duplex ? "Full":"Half");
|
||||
else
|
||||
printk(KERN_INFO "%s: link down\n", dev->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* based on au1000_eth. c*/
|
||||
static int macb_mii_probe(struct net_device *dev)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
struct phy_device *phydev = NULL;
|
||||
struct eth_platform_data *pdata;
|
||||
int phy_addr;
|
||||
|
||||
/* find the first phy */
|
||||
for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
|
||||
if (bp->mii_bus.phy_map[phy_addr]) {
|
||||
phydev = bp->mii_bus.phy_map[phy_addr];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!phydev) {
|
||||
printk (KERN_ERR "%s: no PHY found\n", dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdata = bp->pdev->dev.platform_data;
|
||||
/* TODO : add pin_irq */
|
||||
|
||||
/* attach the mac to the phy */
|
||||
if (pdata && pdata->is_rmii) {
|
||||
phydev = phy_connect(dev, phydev->dev.bus_id,
|
||||
&macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII);
|
||||
} else {
|
||||
advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
|
||||
mii->advertising = advertise;
|
||||
phydev = phy_connect(dev, phydev->dev.bus_id,
|
||||
&macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII);
|
||||
}
|
||||
lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
|
||||
|
||||
/* figure out media and duplex from advertise and LPA values */
|
||||
media = mii_nway_result(lpa & advertise);
|
||||
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
|
||||
if (IS_ERR(phydev)) {
|
||||
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
|
||||
return PTR_ERR(phydev);
|
||||
}
|
||||
|
||||
if (ok_to_print)
|
||||
printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
|
||||
mii->dev->name,
|
||||
media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
|
||||
duplex ? "full" : "half", lpa);
|
||||
/* mask with MAC supported features */
|
||||
phydev->supported &= PHY_BASIC_FEATURES;
|
||||
|
||||
mii->full_duplex = duplex;
|
||||
phydev->advertising = phydev->supported;
|
||||
|
||||
/* Let the MAC know about the new link state */
|
||||
macb_set_media(bp, media);
|
||||
bp->link = 0;
|
||||
bp->speed = 0;
|
||||
bp->duplex = -1;
|
||||
bp->phy_dev = phydev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int macb_mii_init(struct macb *bp)
|
||||
{
|
||||
struct eth_platform_data *pdata;
|
||||
int err = -ENXIO, i;
|
||||
|
||||
/* Enable managment port */
|
||||
macb_writel(bp, NCR, MACB_BIT(MPE));
|
||||
|
||||
bp->mii_bus.name = "MACB_mii_bus",
|
||||
bp->mii_bus.read = &macb_mdio_read,
|
||||
bp->mii_bus.write = &macb_mdio_write,
|
||||
bp->mii_bus.reset = &macb_mdio_reset,
|
||||
bp->mii_bus.id = bp->pdev->id,
|
||||
bp->mii_bus.priv = bp,
|
||||
bp->mii_bus.dev = &bp->dev->dev;
|
||||
pdata = bp->pdev->dev.platform_data;
|
||||
|
||||
if (pdata)
|
||||
bp->mii_bus.phy_mask = pdata->phy_mask;
|
||||
|
||||
bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
|
||||
if (!bp->mii_bus.irq) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++)
|
||||
bp->mii_bus.irq[i] = PHY_POLL;
|
||||
|
||||
platform_set_drvdata(bp->dev, &bp->mii_bus);
|
||||
|
||||
if (mdiobus_register(&bp->mii_bus))
|
||||
goto err_out_free_mdio_irq;
|
||||
|
||||
if (macb_mii_probe(bp->dev) != 0) {
|
||||
goto err_out_unregister_bus;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_unregister_bus:
|
||||
mdiobus_unregister(&bp->mii_bus);
|
||||
err_out_free_mdio_irq:
|
||||
kfree(bp->mii_bus.irq);
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void macb_update_stats(struct macb *bp)
|
||||
@ -265,16 +294,6 @@ static void macb_update_stats(struct macb *bp)
|
||||
*p += __raw_readl(reg);
|
||||
}
|
||||
|
||||
static void macb_periodic_task(struct work_struct *work)
|
||||
{
|
||||
struct macb *bp = container_of(work, struct macb, periodic_task.work);
|
||||
|
||||
macb_update_stats(bp);
|
||||
macb_check_media(bp, 1, 0);
|
||||
|
||||
schedule_delayed_work(&bp->periodic_task, HZ);
|
||||
}
|
||||
|
||||
static void macb_tx(struct macb *bp)
|
||||
{
|
||||
unsigned int tail;
|
||||
@ -519,9 +538,6 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
|
||||
spin_lock(&bp->lock);
|
||||
|
||||
while (status) {
|
||||
if (status & MACB_BIT(MFD))
|
||||
complete(&bp->mdio_complete);
|
||||
|
||||
/* close possible race with dev_close */
|
||||
if (unlikely(!netif_running(dev))) {
|
||||
macb_writel(bp, IDR, ~0UL);
|
||||
@ -535,7 +551,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
|
||||
* until we have processed the buffers
|
||||
*/
|
||||
macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
|
||||
dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n");
|
||||
dev_dbg(&bp->pdev->dev,
|
||||
"scheduling RX softirq\n");
|
||||
__netif_rx_schedule(dev);
|
||||
}
|
||||
}
|
||||
@ -765,7 +782,7 @@ static void macb_init_hw(struct macb *bp)
|
||||
macb_writel(bp, TBQP, bp->tx_ring_dma);
|
||||
|
||||
/* Enable TX and RX */
|
||||
macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE));
|
||||
macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
|
||||
|
||||
/* Enable interrupts */
|
||||
macb_writel(bp, IER, (MACB_BIT(RCOMP)
|
||||
@ -776,18 +793,126 @@ static void macb_init_hw(struct macb *bp)
|
||||
| MACB_BIT(TCOMP)
|
||||
| MACB_BIT(ISR_ROVR)
|
||||
| MACB_BIT(HRESP)));
|
||||
|
||||
}
|
||||
|
||||
static void macb_init_phy(struct net_device *dev)
|
||||
/*
|
||||
* The hash address register is 64 bits long and takes up two
|
||||
* locations in the memory map. The least significant bits are stored
|
||||
* in EMAC_HSL and the most significant bits in EMAC_HSH.
|
||||
*
|
||||
* The unicast hash enable and the multicast hash enable bits in the
|
||||
* network configuration register enable the reception of hash matched
|
||||
* frames. The destination address is reduced to a 6 bit index into
|
||||
* the 64 bit hash register using the following hash function. The
|
||||
* hash function is an exclusive or of every sixth bit of the
|
||||
* destination address.
|
||||
*
|
||||
* hi[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
|
||||
* hi[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
|
||||
* hi[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
|
||||
* hi[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
|
||||
* hi[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
|
||||
* hi[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
|
||||
*
|
||||
* da[0] represents the least significant bit of the first byte
|
||||
* received, that is, the multicast/unicast indicator, and da[47]
|
||||
* represents the most significant bit of the last byte received. If
|
||||
* the hash index, hi[n], points to a bit that is set in the hash
|
||||
* register then the frame will be matched according to whether the
|
||||
* frame is multicast or unicast. A multicast match will be signalled
|
||||
* if the multicast hash enable bit is set, da[0] is 1 and the hash
|
||||
* index points to a bit set in the hash register. A unicast match
|
||||
* will be signalled if the unicast hash enable bit is set, da[0] is 0
|
||||
* and the hash index points to a bit set in the hash register. To
|
||||
* receive all multicast frames, the hash register should be set with
|
||||
* all ones and the multicast hash enable bit should be set in the
|
||||
* network configuration register.
|
||||
*/
|
||||
|
||||
static inline int hash_bit_value(int bitnr, __u8 *addr)
|
||||
{
|
||||
if (addr[bitnr / 8] & (1 << (bitnr % 8)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the hash index value for the specified address.
|
||||
*/
|
||||
static int hash_get_index(__u8 *addr)
|
||||
{
|
||||
int i, j, bitval;
|
||||
int hash_index = 0;
|
||||
|
||||
for (j = 0; j < 6; j++) {
|
||||
for (i = 0, bitval = 0; i < 8; i++)
|
||||
bitval ^= hash_bit_value(i*6 + j, addr);
|
||||
|
||||
hash_index |= (bitval << j);
|
||||
}
|
||||
|
||||
return hash_index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add multicast addresses to the internal multicast-hash table.
|
||||
*/
|
||||
static void macb_sethashtable(struct net_device *dev)
|
||||
{
|
||||
struct dev_mc_list *curr;
|
||||
unsigned long mc_filter[2];
|
||||
unsigned int i, bitnr;
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
|
||||
/* Set some reasonable default settings */
|
||||
macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE,
|
||||
ADVERTISE_CSMA | ADVERTISE_ALL);
|
||||
macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR,
|
||||
(BMCR_SPEED100 | BMCR_ANENABLE
|
||||
| BMCR_ANRESTART | BMCR_FULLDPLX));
|
||||
mc_filter[0] = mc_filter[1] = 0;
|
||||
|
||||
curr = dev->mc_list;
|
||||
for (i = 0; i < dev->mc_count; i++, curr = curr->next) {
|
||||
if (!curr) break; /* unexpected end of list */
|
||||
|
||||
bitnr = hash_get_index(curr->dmi_addr);
|
||||
mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
|
||||
}
|
||||
|
||||
macb_writel(bp, HRB, mc_filter[0]);
|
||||
macb_writel(bp, HRT, mc_filter[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable/Disable promiscuous and multicast modes.
|
||||
*/
|
||||
static void macb_set_rx_mode(struct net_device *dev)
|
||||
{
|
||||
unsigned long cfg;
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
|
||||
cfg = macb_readl(bp, NCFGR);
|
||||
|
||||
if (dev->flags & IFF_PROMISC)
|
||||
/* Enable promiscuous mode */
|
||||
cfg |= MACB_BIT(CAF);
|
||||
else if (dev->flags & (~IFF_PROMISC))
|
||||
/* Disable promiscuous mode */
|
||||
cfg &= ~MACB_BIT(CAF);
|
||||
|
||||
if (dev->flags & IFF_ALLMULTI) {
|
||||
/* Enable all multicast mode */
|
||||
macb_writel(bp, HRB, -1);
|
||||
macb_writel(bp, HRT, -1);
|
||||
cfg |= MACB_BIT(NCFGR_MTI);
|
||||
} else if (dev->mc_count > 0) {
|
||||
/* Enable specific multicasts */
|
||||
macb_sethashtable(dev);
|
||||
cfg |= MACB_BIT(NCFGR_MTI);
|
||||
} else if (dev->flags & (~IFF_ALLMULTI)) {
|
||||
/* Disable all multicast mode */
|
||||
macb_writel(bp, HRB, 0);
|
||||
macb_writel(bp, HRT, 0);
|
||||
cfg &= ~MACB_BIT(NCFGR_MTI);
|
||||
}
|
||||
|
||||
macb_writel(bp, NCFGR, cfg);
|
||||
}
|
||||
|
||||
static int macb_open(struct net_device *dev)
|
||||
@ -797,6 +922,10 @@ static int macb_open(struct net_device *dev)
|
||||
|
||||
dev_dbg(&bp->pdev->dev, "open\n");
|
||||
|
||||
/* if the phy is not yet register, retry later*/
|
||||
if (!bp->phy_dev)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!is_valid_ether_addr(dev->dev_addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
@ -810,13 +939,12 @@ static int macb_open(struct net_device *dev)
|
||||
|
||||
macb_init_rings(bp);
|
||||
macb_init_hw(bp);
|
||||
macb_init_phy(dev);
|
||||
|
||||
macb_check_media(bp, 1, 1);
|
||||
/* schedule a link state check */
|
||||
phy_start(bp->phy_dev);
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
schedule_delayed_work(&bp->periodic_task, HZ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -825,10 +953,11 @@ static int macb_close(struct net_device *dev)
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
|
||||
cancel_rearming_delayed_work(&bp->periodic_task);
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
if (bp->phy_dev)
|
||||
phy_stop(bp->phy_dev);
|
||||
|
||||
spin_lock_irqsave(&bp->lock, flags);
|
||||
macb_reset_hw(bp);
|
||||
netif_carrier_off(dev);
|
||||
@ -845,6 +974,9 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
|
||||
struct net_device_stats *nstat = &bp->stats;
|
||||
struct macb_stats *hwstat = &bp->hw_stats;
|
||||
|
||||
/* read stats from hardware */
|
||||
macb_update_stats(bp);
|
||||
|
||||
/* Convert HW stats into netdevice stats */
|
||||
nstat->rx_errors = (hwstat->rx_fcs_errors +
|
||||
hwstat->rx_align_errors +
|
||||
@ -882,18 +1014,27 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
|
||||
static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
struct phy_device *phydev = bp->phy_dev;
|
||||
|
||||
return mii_ethtool_gset(&bp->mii, cmd);
|
||||
if (!phydev)
|
||||
return -ENODEV;
|
||||
|
||||
return phy_ethtool_gset(phydev, cmd);
|
||||
}
|
||||
|
||||
static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
struct phy_device *phydev = bp->phy_dev;
|
||||
|
||||
return mii_ethtool_sset(&bp->mii, cmd);
|
||||
if (!phydev)
|
||||
return -ENODEV;
|
||||
|
||||
return phy_ethtool_sset(phydev, cmd);
|
||||
}
|
||||
|
||||
static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
||||
static void macb_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
|
||||
@ -902,104 +1043,34 @@ static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf
|
||||
strcpy(info->bus_info, bp->pdev->dev.bus_id);
|
||||
}
|
||||
|
||||
static int macb_nway_reset(struct net_device *dev)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
return mii_nway_restart(&bp->mii);
|
||||
}
|
||||
|
||||
static struct ethtool_ops macb_ethtool_ops = {
|
||||
.get_settings = macb_get_settings,
|
||||
.set_settings = macb_set_settings,
|
||||
.get_drvinfo = macb_get_drvinfo,
|
||||
.nway_reset = macb_nway_reset,
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
{
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
struct phy_device *phydev = bp->phy_dev;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return -EINVAL;
|
||||
|
||||
return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL);
|
||||
if (!phydev)
|
||||
return -ENODEV;
|
||||
|
||||
return phy_mii_ioctl(phydev, if_mii(rq), cmd);
|
||||
}
|
||||
|
||||
static ssize_t macb_mii_show(const struct device *_dev, char *buf,
|
||||
unsigned long addr)
|
||||
{
|
||||
struct net_device *dev = to_net_dev(_dev);
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
if (netif_running(dev)) {
|
||||
int value;
|
||||
value = macb_mdio_read(dev, bp->mii.phy_id, addr);
|
||||
ret = sprintf(buf, "0x%04x\n", (uint16_t)value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MII_ENTRY(name, addr) \
|
||||
static ssize_t show_##name(struct device *_dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return macb_mii_show(_dev, buf, addr); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
|
||||
|
||||
MII_ENTRY(bmcr, MII_BMCR);
|
||||
MII_ENTRY(bmsr, MII_BMSR);
|
||||
MII_ENTRY(physid1, MII_PHYSID1);
|
||||
MII_ENTRY(physid2, MII_PHYSID2);
|
||||
MII_ENTRY(advertise, MII_ADVERTISE);
|
||||
MII_ENTRY(lpa, MII_LPA);
|
||||
MII_ENTRY(expansion, MII_EXPANSION);
|
||||
|
||||
static struct attribute *macb_mii_attrs[] = {
|
||||
&dev_attr_bmcr.attr,
|
||||
&dev_attr_bmsr.attr,
|
||||
&dev_attr_physid1.attr,
|
||||
&dev_attr_physid2.attr,
|
||||
&dev_attr_advertise.attr,
|
||||
&dev_attr_lpa.attr,
|
||||
&dev_attr_expansion.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group macb_mii_group = {
|
||||
.name = "mii",
|
||||
.attrs = macb_mii_attrs,
|
||||
};
|
||||
|
||||
static void macb_unregister_sysfs(struct net_device *net)
|
||||
{
|
||||
struct device *_dev = &net->dev;
|
||||
|
||||
sysfs_remove_group(&_dev->kobj, &macb_mii_group);
|
||||
}
|
||||
|
||||
static int macb_register_sysfs(struct net_device *net)
|
||||
{
|
||||
struct device *_dev = &net->dev;
|
||||
int ret;
|
||||
|
||||
ret = sysfs_create_group(&_dev->kobj, &macb_mii_group);
|
||||
if (ret)
|
||||
printk(KERN_WARNING
|
||||
"%s: sysfs mii attribute registration failed: %d\n",
|
||||
net->name, ret);
|
||||
return ret;
|
||||
}
|
||||
static int __devinit macb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct eth_platform_data *pdata;
|
||||
struct resource *regs;
|
||||
struct net_device *dev;
|
||||
struct macb *bp;
|
||||
struct phy_device *phydev;
|
||||
unsigned long pclk_hz;
|
||||
u32 config;
|
||||
int err = -ENXIO;
|
||||
@ -1073,6 +1144,7 @@ static int __devinit macb_probe(struct platform_device *pdev)
|
||||
dev->stop = macb_close;
|
||||
dev->hard_start_xmit = macb_start_xmit;
|
||||
dev->get_stats = macb_get_stats;
|
||||
dev->set_multicast_list = macb_set_rx_mode;
|
||||
dev->do_ioctl = macb_ioctl;
|
||||
dev->poll = macb_poll;
|
||||
dev->weight = 64;
|
||||
@ -1080,10 +1152,6 @@ static int __devinit macb_probe(struct platform_device *pdev)
|
||||
|
||||
dev->base_addr = regs->start;
|
||||
|
||||
INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task);
|
||||
mutex_init(&bp->mdio_mutex);
|
||||
init_completion(&bp->mdio_complete);
|
||||
|
||||
/* Set MII management clock divider */
|
||||
pclk_hz = clk_get_rate(bp->pclk);
|
||||
if (pclk_hz <= 20000000)
|
||||
@ -1096,20 +1164,9 @@ static int __devinit macb_probe(struct platform_device *pdev)
|
||||
config = MACB_BF(CLK, MACB_CLK_DIV64);
|
||||
macb_writel(bp, NCFGR, config);
|
||||
|
||||
bp->mii.dev = dev;
|
||||
bp->mii.mdio_read = macb_mdio_read;
|
||||
bp->mii.mdio_write = macb_mdio_write;
|
||||
bp->mii.phy_id_mask = 0x1f;
|
||||
bp->mii.reg_num_mask = 0x1f;
|
||||
|
||||
macb_get_hwaddr(bp);
|
||||
err = macb_phy_probe(bp);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n");
|
||||
goto err_out_free_irq;
|
||||
}
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
|
||||
if (pdata && pdata->is_rmii)
|
||||
#if defined(CONFIG_ARCH_AT91)
|
||||
macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) );
|
||||
@ -1131,9 +1188,11 @@ static int __devinit macb_probe(struct platform_device *pdev)
|
||||
goto err_out_free_irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
if (macb_mii_init(bp) != 0) {
|
||||
goto err_out_unregister_netdev;
|
||||
}
|
||||
|
||||
macb_register_sysfs(dev);
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
|
||||
"(%02x:%02x:%02x:%02x:%02x:%02x)\n",
|
||||
@ -1141,8 +1200,15 @@ static int __devinit macb_probe(struct platform_device *pdev)
|
||||
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
|
||||
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
|
||||
|
||||
phydev = bp->phy_dev;
|
||||
printk(KERN_INFO "%s: attached PHY driver [%s] "
|
||||
"(mii_bus:phy_addr=%s, irq=%d)\n",
|
||||
dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_unregister_netdev:
|
||||
unregister_netdev(dev);
|
||||
err_out_free_irq:
|
||||
free_irq(dev->irq, dev);
|
||||
err_out_iounmap:
|
||||
@ -1153,7 +1219,9 @@ err_out_disable_clocks:
|
||||
clk_put(bp->hclk);
|
||||
#endif
|
||||
clk_disable(bp->pclk);
|
||||
#ifndef CONFIG_ARCH_AT91
|
||||
err_out_put_pclk:
|
||||
#endif
|
||||
clk_put(bp->pclk);
|
||||
err_out_free_dev:
|
||||
free_netdev(dev);
|
||||
@ -1171,7 +1239,8 @@ static int __devexit macb_remove(struct platform_device *pdev)
|
||||
|
||||
if (dev) {
|
||||
bp = netdev_priv(dev);
|
||||
macb_unregister_sysfs(dev);
|
||||
mdiobus_unregister(&bp->mii_bus);
|
||||
kfree(bp->mii_bus.irq);
|
||||
unregister_netdev(dev);
|
||||
free_irq(dev->irq, dev);
|
||||
iounmap(bp->regs);
|
||||
|
@ -383,11 +383,11 @@ struct macb {
|
||||
|
||||
unsigned int rx_pending, tx_pending;
|
||||
|
||||
struct delayed_work periodic_task;
|
||||
|
||||
struct mutex mdio_mutex;
|
||||
struct completion mdio_complete;
|
||||
struct mii_if_info mii;
|
||||
struct mii_bus mii_bus;
|
||||
struct phy_device *phy_dev;
|
||||
unsigned int link;
|
||||
unsigned int speed;
|
||||
unsigned int duplex;
|
||||
};
|
||||
|
||||
#endif /* _MACB_H */
|
||||
|
@ -1060,7 +1060,6 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
|
||||
struct myri10ge_tx_buf *tx = &mgp->tx;
|
||||
struct sk_buff *skb;
|
||||
int idx, len;
|
||||
int limit = 0;
|
||||
|
||||
while (tx->pkt_done != mcp_index) {
|
||||
idx = tx->done & tx->mask;
|
||||
@ -1091,11 +1090,6 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
|
||||
bus), len,
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
|
||||
/* limit potential for livelock by only handling
|
||||
* 2 full tx rings per call */
|
||||
if (unlikely(++limit > 2 * tx->mask))
|
||||
break;
|
||||
}
|
||||
/* start the queue if we've stopped it */
|
||||
if (netif_queue_stopped(mgp->dev)
|
||||
|
@ -796,12 +796,14 @@ static void free_shared_mem(struct s2io_nic *nic)
|
||||
struct mac_info *mac_control;
|
||||
struct config_param *config;
|
||||
int lst_size, lst_per_page;
|
||||
struct net_device *dev = nic->dev;
|
||||
struct net_device *dev;
|
||||
int page_num = 0;
|
||||
|
||||
if (!nic)
|
||||
return;
|
||||
|
||||
dev = nic->dev;
|
||||
|
||||
mac_control = &nic->mac_control;
|
||||
config = &nic->config;
|
||||
|
||||
|
@ -304,6 +304,9 @@ static const struct usb_device_id products [] = {
|
||||
}, {
|
||||
USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader
|
||||
.driver_info = (unsigned long) &blob_info,
|
||||
}, {
|
||||
USB_DEVICE (0x1286, 0x8001), // "blob" bootloader
|
||||
.driver_info = (unsigned long) &blob_info,
|
||||
}, {
|
||||
// Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config
|
||||
// e.g. Gumstix, current OpenZaurus, ...
|
||||
|
@ -52,6 +52,8 @@
|
||||
|
||||
#include "airo.h"
|
||||
|
||||
#define DRV_NAME "airo"
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static struct pci_device_id card_ids[] = {
|
||||
{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
|
||||
@ -71,7 +73,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state);
|
||||
static int airo_pci_resume(struct pci_dev *pdev);
|
||||
|
||||
static struct pci_driver airo_driver = {
|
||||
.name = "airo",
|
||||
.name = DRV_NAME,
|
||||
.id_table = card_ids,
|
||||
.probe = airo_pci_probe,
|
||||
.remove = __devexit_p(airo_pci_remove),
|
||||
@ -1092,7 +1094,7 @@ static int get_dec_u16( char *buffer, int *start, int limit );
|
||||
static void OUT4500( struct airo_info *, u16 register, u16 value );
|
||||
static unsigned short IN4500( struct airo_info *, u16 register );
|
||||
static u16 setup_card(struct airo_info*, u8 *mac, int lock);
|
||||
static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock );
|
||||
static int enable_MAC(struct airo_info *ai, int lock);
|
||||
static void disable_MAC(struct airo_info *ai, int lock);
|
||||
static void enable_interrupts(struct airo_info*);
|
||||
static void disable_interrupts(struct airo_info*);
|
||||
@ -1250,7 +1252,7 @@ static int flashputbuf(struct airo_info *ai);
|
||||
static int flashrestart(struct airo_info *ai,struct net_device *dev);
|
||||
|
||||
#define airo_print(type, name, fmt, args...) \
|
||||
{ printk(type "airo(%s): " fmt "\n", name, ##args); }
|
||||
printk(type DRV_NAME "(%s): " fmt "\n", name, ##args)
|
||||
|
||||
#define airo_print_info(name, fmt, args...) \
|
||||
airo_print(KERN_INFO, name, fmt, ##args)
|
||||
@ -1926,28 +1928,54 @@ static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int airo_open(struct net_device *dev) {
|
||||
struct airo_info *info = dev->priv;
|
||||
Resp rsp;
|
||||
static void try_auto_wep(struct airo_info *ai)
|
||||
{
|
||||
if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
|
||||
ai->expires = RUN_AT(3*HZ);
|
||||
wake_up_interruptible(&ai->thr_wait);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(FLAG_FLASHING, &info->flags))
|
||||
static int airo_open(struct net_device *dev) {
|
||||
struct airo_info *ai = dev->priv;
|
||||
int rc = 0;
|
||||
|
||||
if (test_bit(FLAG_FLASHING, &ai->flags))
|
||||
return -EIO;
|
||||
|
||||
/* Make sure the card is configured.
|
||||
* Wireless Extensions may postpone config changes until the card
|
||||
* is open (to pipeline changes and speed-up card setup). If
|
||||
* those changes are not yet commited, do it now - Jean II */
|
||||
if (test_bit (FLAG_COMMIT, &info->flags)) {
|
||||
disable_MAC(info, 1);
|
||||
writeConfigRid(info, 1);
|
||||
if (test_bit(FLAG_COMMIT, &ai->flags)) {
|
||||
disable_MAC(ai, 1);
|
||||
writeConfigRid(ai, 1);
|
||||
}
|
||||
|
||||
if (info->wifidev != dev) {
|
||||
if (ai->wifidev != dev) {
|
||||
clear_bit(JOB_DIE, &ai->jobs);
|
||||
ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
|
||||
if (IS_ERR(ai->airo_thread_task))
|
||||
return (int)PTR_ERR(ai->airo_thread_task);
|
||||
|
||||
rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED,
|
||||
dev->name, dev);
|
||||
if (rc) {
|
||||
airo_print_err(dev->name,
|
||||
"register interrupt %d failed, rc %d",
|
||||
dev->irq, rc);
|
||||
set_bit(JOB_DIE, &ai->jobs);
|
||||
kthread_stop(ai->airo_thread_task);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Power on the MAC controller (which may have been disabled) */
|
||||
clear_bit(FLAG_RADIO_DOWN, &info->flags);
|
||||
enable_interrupts(info);
|
||||
clear_bit(FLAG_RADIO_DOWN, &ai->flags);
|
||||
enable_interrupts(ai);
|
||||
|
||||
try_auto_wep(ai);
|
||||
}
|
||||
enable_MAC(info, &rsp, 1);
|
||||
enable_MAC(ai, 1);
|
||||
|
||||
netif_start_queue(dev);
|
||||
return 0;
|
||||
@ -2338,14 +2366,13 @@ static int airo_set_mac_address(struct net_device *dev, void *p)
|
||||
{
|
||||
struct airo_info *ai = dev->priv;
|
||||
struct sockaddr *addr = p;
|
||||
Resp rsp;
|
||||
|
||||
readConfigRid(ai, 1);
|
||||
memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);
|
||||
set_bit (FLAG_COMMIT, &ai->flags);
|
||||
disable_MAC(ai, 1);
|
||||
writeConfigRid (ai, 1);
|
||||
enable_MAC(ai, &rsp, 1);
|
||||
enable_MAC(ai, 1);
|
||||
memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
|
||||
if (ai->wifidev)
|
||||
memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
|
||||
@ -2392,6 +2419,11 @@ static int airo_close(struct net_device *dev) {
|
||||
disable_MAC(ai, 1);
|
||||
#endif
|
||||
disable_interrupts( ai );
|
||||
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
set_bit(JOB_DIE, &ai->jobs);
|
||||
kthread_stop(ai->airo_thread_task);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -2403,7 +2435,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
|
||||
set_bit(FLAG_RADIO_DOWN, &ai->flags);
|
||||
disable_MAC(ai, 1);
|
||||
disable_interrupts(ai);
|
||||
free_irq( dev->irq, dev );
|
||||
takedown_proc_entry( dev, ai );
|
||||
if (test_bit(FLAG_REGISTERED, &ai->flags)) {
|
||||
unregister_netdev( dev );
|
||||
@ -2414,9 +2445,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
|
||||
}
|
||||
clear_bit(FLAG_REGISTERED, &ai->flags);
|
||||
}
|
||||
set_bit(JOB_DIE, &ai->jobs);
|
||||
kthread_stop(ai->airo_thread_task);
|
||||
|
||||
/*
|
||||
* Clean out tx queue
|
||||
*/
|
||||
@ -2554,8 +2582,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
|
||||
* 2) Map PCI memory for issueing commands.
|
||||
* 3) Allocate memory (shared) to send and receive ethernet frames.
|
||||
*/
|
||||
static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
|
||||
const char *name)
|
||||
static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
|
||||
{
|
||||
unsigned long mem_start, mem_len, aux_start, aux_len;
|
||||
int rc = -1;
|
||||
@ -2569,35 +2596,35 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
|
||||
aux_start = pci_resource_start(pci, 2);
|
||||
aux_len = AUXMEMSIZE;
|
||||
|
||||
if (!request_mem_region(mem_start, mem_len, name)) {
|
||||
airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
|
||||
(int)mem_start, (int)mem_len, name);
|
||||
if (!request_mem_region(mem_start, mem_len, DRV_NAME)) {
|
||||
airo_print_err("", "Couldn't get region %x[%x]",
|
||||
(int)mem_start, (int)mem_len);
|
||||
goto out;
|
||||
}
|
||||
if (!request_mem_region(aux_start, aux_len, name)) {
|
||||
airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
|
||||
(int)aux_start, (int)aux_len, name);
|
||||
if (!request_mem_region(aux_start, aux_len, DRV_NAME)) {
|
||||
airo_print_err("", "Couldn't get region %x[%x]",
|
||||
(int)aux_start, (int)aux_len);
|
||||
goto free_region1;
|
||||
}
|
||||
|
||||
ai->pcimem = ioremap(mem_start, mem_len);
|
||||
if (!ai->pcimem) {
|
||||
airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
|
||||
(int)mem_start, (int)mem_len, name);
|
||||
airo_print_err("", "Couldn't map region %x[%x]",
|
||||
(int)mem_start, (int)mem_len);
|
||||
goto free_region2;
|
||||
}
|
||||
ai->pciaux = ioremap(aux_start, aux_len);
|
||||
if (!ai->pciaux) {
|
||||
airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
|
||||
(int)aux_start, (int)aux_len, name);
|
||||
airo_print_err("", "Couldn't map region %x[%x]",
|
||||
(int)aux_start, (int)aux_len);
|
||||
goto free_memmap;
|
||||
}
|
||||
|
||||
/* Reserve PKTSIZE for each fid and 2K for the Rids */
|
||||
ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
|
||||
if (!ai->shared) {
|
||||
airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d",
|
||||
PCI_SHARED_LEN);
|
||||
airo_print_err("", "Couldn't alloc_consistent %d",
|
||||
PCI_SHARED_LEN);
|
||||
goto free_auxmap;
|
||||
}
|
||||
|
||||
@ -2742,7 +2769,7 @@ static int airo_networks_allocate(struct airo_info *ai)
|
||||
kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
|
||||
GFP_KERNEL);
|
||||
if (!ai->networks) {
|
||||
airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
|
||||
airo_print_warn("", "Out of memory allocating beacons");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -2770,7 +2797,6 @@ static int airo_test_wpa_capable(struct airo_info *ai)
|
||||
{
|
||||
int status;
|
||||
CapabilityRid cap_rid;
|
||||
const char *name = ai->dev->name;
|
||||
|
||||
status = readCapabilityRid(ai, &cap_rid, 1);
|
||||
if (status != SUCCESS) return 0;
|
||||
@ -2778,12 +2804,12 @@ static int airo_test_wpa_capable(struct airo_info *ai)
|
||||
/* Only firmware versions 5.30.17 or better can do WPA */
|
||||
if ((cap_rid.softVer > 0x530)
|
||||
|| ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
|
||||
airo_print_info(name, "WPA is supported.");
|
||||
airo_print_info("", "WPA is supported.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* No WPA support */
|
||||
airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17"
|
||||
airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
|
||||
" and greater support WPA. Detected %s)", cap_rid.prodVer);
|
||||
return 0;
|
||||
}
|
||||
@ -2797,23 +2823,19 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
int i, rc;
|
||||
|
||||
/* Create the network device object. */
|
||||
dev = alloc_etherdev(sizeof(*ai));
|
||||
if (!dev) {
|
||||
dev = alloc_netdev(sizeof(*ai), "", ether_setup);
|
||||
if (!dev) {
|
||||
airo_print_err("", "Couldn't alloc_etherdev");
|
||||
return NULL;
|
||||
}
|
||||
if (dev_alloc_name(dev, dev->name) < 0) {
|
||||
airo_print_err("", "Couldn't get name!");
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
ai = dev->priv;
|
||||
ai->wifidev = NULL;
|
||||
ai->flags = 0;
|
||||
ai->flags = 1 << FLAG_RADIO_DOWN;
|
||||
ai->jobs = 0;
|
||||
ai->dev = dev;
|
||||
if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
|
||||
airo_print_dbg(dev->name, "Found an MPI350 card");
|
||||
airo_print_dbg("", "Found an MPI350 card");
|
||||
set_bit(FLAG_MPI, &ai->flags);
|
||||
}
|
||||
spin_lock_init(&ai->aux_lock);
|
||||
@ -2821,14 +2843,11 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
ai->config.len = 0;
|
||||
ai->pci = pci;
|
||||
init_waitqueue_head (&ai->thr_wait);
|
||||
ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
|
||||
if (IS_ERR(ai->airo_thread_task))
|
||||
goto err_out_free;
|
||||
ai->tfm = NULL;
|
||||
add_airo_dev(ai);
|
||||
|
||||
if (airo_networks_allocate (ai))
|
||||
goto err_out_thr;
|
||||
goto err_out_free;
|
||||
airo_networks_initialize (ai);
|
||||
|
||||
/* The Airo-specific entries in the device structure. */
|
||||
@ -2851,27 +2870,22 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
dev->base_addr = port;
|
||||
|
||||
SET_NETDEV_DEV(dev, dmdev);
|
||||
SET_MODULE_OWNER(dev);
|
||||
|
||||
reset_card (dev, 1);
|
||||
msleep(400);
|
||||
|
||||
rc = request_irq( dev->irq, airo_interrupt, IRQF_SHARED, dev->name, dev );
|
||||
if (rc) {
|
||||
airo_print_err(dev->name, "register interrupt %d failed, rc %d",
|
||||
irq, rc);
|
||||
goto err_out_nets;
|
||||
}
|
||||
if (!is_pcmcia) {
|
||||
if (!request_region( dev->base_addr, 64, dev->name )) {
|
||||
if (!request_region(dev->base_addr, 64, DRV_NAME)) {
|
||||
rc = -EBUSY;
|
||||
airo_print_err(dev->name, "Couldn't request region");
|
||||
goto err_out_irq;
|
||||
goto err_out_nets;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(FLAG_MPI,&ai->flags)) {
|
||||
if (mpi_map_card(ai, pci, dev->name)) {
|
||||
airo_print_err(dev->name, "Could not map memory");
|
||||
if (mpi_map_card(ai, pci)) {
|
||||
airo_print_err("", "Could not map memory");
|
||||
goto err_out_res;
|
||||
}
|
||||
}
|
||||
@ -2899,6 +2913,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
|
||||
}
|
||||
|
||||
strcpy(dev->name, "eth%d");
|
||||
rc = register_netdev(dev);
|
||||
if (rc) {
|
||||
airo_print_err(dev->name, "Couldn't register_netdev");
|
||||
@ -2921,8 +2936,6 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
if (setup_proc_entry(dev, dev->priv) < 0)
|
||||
goto err_out_wifi;
|
||||
|
||||
netif_start_queue(dev);
|
||||
SET_MODULE_OWNER(dev);
|
||||
return dev;
|
||||
|
||||
err_out_wifi:
|
||||
@ -2940,14 +2953,9 @@ err_out_map:
|
||||
err_out_res:
|
||||
if (!is_pcmcia)
|
||||
release_region( dev->base_addr, 64 );
|
||||
err_out_irq:
|
||||
free_irq(dev->irq, dev);
|
||||
err_out_nets:
|
||||
airo_networks_free(ai);
|
||||
err_out_thr:
|
||||
del_airo_dev(ai);
|
||||
set_bit(JOB_DIE, &ai->jobs);
|
||||
kthread_stop(ai->airo_thread_task);
|
||||
err_out_free:
|
||||
free_netdev(dev);
|
||||
return NULL;
|
||||
@ -3529,9 +3537,11 @@ static u16 IN4500( struct airo_info *ai, u16 reg ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
|
||||
static int enable_MAC(struct airo_info *ai, int lock)
|
||||
{
|
||||
int rc;
|
||||
Cmd cmd;
|
||||
Cmd cmd;
|
||||
Resp rsp;
|
||||
|
||||
/* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions
|
||||
* FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"
|
||||
@ -3547,7 +3557,7 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
|
||||
if (!test_bit(FLAG_ENABLED, &ai->flags)) {
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.cmd = MAC_ENABLE;
|
||||
rc = issuecommand(ai, &cmd, rsp);
|
||||
rc = issuecommand(ai, &cmd, &rsp);
|
||||
if (rc == SUCCESS)
|
||||
set_bit(FLAG_ENABLED, &ai->flags);
|
||||
} else
|
||||
@ -3557,8 +3567,12 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
|
||||
up(&ai->sem);
|
||||
|
||||
if (rc)
|
||||
airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d",
|
||||
__FUNCTION__, rc);
|
||||
airo_print_err(ai->dev->name, "Cannot enable MAC");
|
||||
else if ((rsp.status & 0xFF00) != 0) {
|
||||
airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, "
|
||||
"rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2);
|
||||
rc = ERROR;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3902,12 +3916,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
|
||||
if ( status != SUCCESS ) return ERROR;
|
||||
}
|
||||
|
||||
status = enable_MAC(ai, &rsp, lock);
|
||||
if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
|
||||
airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x,"
|
||||
" offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
|
||||
status = enable_MAC(ai, lock);
|
||||
if (status != SUCCESS)
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Grab the initial wep key, we gotta save it for auto_wep */
|
||||
rc = readWepKeyRid(ai, &wkr, 1, lock);
|
||||
@ -3919,10 +3930,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
|
||||
rc = readWepKeyRid(ai, &wkr, 0, lock);
|
||||
} while(lastindex != wkr.kindex);
|
||||
|
||||
if (auto_wep) {
|
||||
ai->expires = RUN_AT(3*HZ);
|
||||
wake_up_interruptible(&ai->thr_wait);
|
||||
}
|
||||
try_auto_wep(ai);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -4004,7 +4012,7 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
|
||||
}
|
||||
if ( !(max_tries--) ) {
|
||||
airo_print_err(ai->dev->name,
|
||||
"airo: BAP setup error too many retries\n");
|
||||
"BAP setup error too many retries\n");
|
||||
return ERROR;
|
||||
}
|
||||
// -- PC4500 missed it, try again
|
||||
@ -5152,7 +5160,6 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
|
||||
struct net_device *dev = dp->data;
|
||||
struct airo_info *ai = dev->priv;
|
||||
SsidRid SSID_rid;
|
||||
Resp rsp;
|
||||
int i;
|
||||
int offset = 0;
|
||||
|
||||
@ -5177,7 +5184,7 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
|
||||
SSID_rid.len = sizeof(SSID_rid);
|
||||
disable_MAC(ai, 1);
|
||||
writeSsidRid(ai, &SSID_rid, 1);
|
||||
enable_MAC(ai, &rsp, 1);
|
||||
enable_MAC(ai, 1);
|
||||
}
|
||||
|
||||
static inline u8 hexVal(char c) {
|
||||
@ -5193,7 +5200,6 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
|
||||
struct net_device *dev = dp->data;
|
||||
struct airo_info *ai = dev->priv;
|
||||
APListRid APList_rid;
|
||||
Resp rsp;
|
||||
int i;
|
||||
|
||||
if ( !data->writelen ) return;
|
||||
@ -5218,18 +5224,17 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
|
||||
}
|
||||
disable_MAC(ai, 1);
|
||||
writeAPListRid(ai, &APList_rid, 1);
|
||||
enable_MAC(ai, &rsp, 1);
|
||||
enable_MAC(ai, 1);
|
||||
}
|
||||
|
||||
/* This function wraps PC4500_writerid with a MAC disable */
|
||||
static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
|
||||
int len, int dummy ) {
|
||||
int rc;
|
||||
Resp rsp;
|
||||
|
||||
disable_MAC(ai, 1);
|
||||
rc = PC4500_writerid(ai, rid, rid_data, len, 1);
|
||||
enable_MAC(ai, &rsp, 1);
|
||||
enable_MAC(ai, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -5260,7 +5265,6 @@ static int set_wep_key(struct airo_info *ai, u16 index,
|
||||
const char *key, u16 keylen, int perm, int lock ) {
|
||||
static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
|
||||
WepKeyRid wkr;
|
||||
Resp rsp;
|
||||
|
||||
memset(&wkr, 0, sizeof(wkr));
|
||||
if (keylen == 0) {
|
||||
@ -5280,7 +5284,7 @@ static int set_wep_key(struct airo_info *ai, u16 index,
|
||||
|
||||
if (perm) disable_MAC(ai, lock);
|
||||
writeWepKeyRid(ai, &wkr, perm, lock);
|
||||
if (perm) enable_MAC(ai, &rsp, lock);
|
||||
if (perm) enable_MAC(ai, lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5548,7 +5552,6 @@ static int proc_close( struct inode *inode, struct file *file )
|
||||
changed. */
|
||||
static void timer_func( struct net_device *dev ) {
|
||||
struct airo_info *apriv = dev->priv;
|
||||
Resp rsp;
|
||||
|
||||
/* We don't have a link so try changing the authtype */
|
||||
readConfigRid(apriv, 0);
|
||||
@ -5575,7 +5578,7 @@ static void timer_func( struct net_device *dev ) {
|
||||
}
|
||||
set_bit (FLAG_COMMIT, &apriv->flags);
|
||||
writeConfigRid(apriv, 0);
|
||||
enable_MAC(apriv, &rsp, 0);
|
||||
enable_MAC(apriv, 0);
|
||||
up(&apriv->sem);
|
||||
|
||||
/* Schedule check to see if the change worked */
|
||||
@ -5597,8 +5600,10 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev,
|
||||
dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
|
||||
else
|
||||
dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
|
||||
if (!dev)
|
||||
if (!dev) {
|
||||
pci_disable_device(pdev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, dev);
|
||||
return 0;
|
||||
@ -5610,6 +5615,8 @@ static void __devexit airo_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
airo_print_info(dev->name, "Unregistering...");
|
||||
stop_airo_card(dev, 1);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
@ -5646,7 +5653,6 @@ static int airo_pci_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct airo_info *ai = dev->priv;
|
||||
Resp rsp;
|
||||
pci_power_t prev_state = pdev->current_state;
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
@ -5679,7 +5685,7 @@ static int airo_pci_resume(struct pci_dev *pdev)
|
||||
ai->APList = NULL;
|
||||
}
|
||||
writeConfigRid(ai, 0);
|
||||
enable_MAC(ai, &rsp, 0);
|
||||
enable_MAC(ai, 0);
|
||||
ai->power = PMSG_ON;
|
||||
netif_device_attach(dev);
|
||||
netif_wake_queue(dev);
|
||||
@ -5903,7 +5909,6 @@ static int airo_set_essid(struct net_device *dev,
|
||||
char *extra)
|
||||
{
|
||||
struct airo_info *local = dev->priv;
|
||||
Resp rsp;
|
||||
SsidRid SSID_rid; /* SSIDs */
|
||||
|
||||
/* Reload the list of current SSID */
|
||||
@ -5935,7 +5940,7 @@ static int airo_set_essid(struct net_device *dev,
|
||||
/* Write it to the card */
|
||||
disable_MAC(local, 1);
|
||||
writeSsidRid(local, &SSID_rid, 1);
|
||||
enable_MAC(local, &rsp, 1);
|
||||
enable_MAC(local, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -6000,7 +6005,7 @@ static int airo_set_wap(struct net_device *dev,
|
||||
memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
|
||||
disable_MAC(local, 1);
|
||||
writeAPListRid(local, &APList_rid, 1);
|
||||
enable_MAC(local, &rsp, 1);
|
||||
enable_MAC(local, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -7454,7 +7459,6 @@ static int airo_config_commit(struct net_device *dev,
|
||||
char *extra) /* NULL */
|
||||
{
|
||||
struct airo_info *local = dev->priv;
|
||||
Resp rsp;
|
||||
|
||||
if (!test_bit (FLAG_COMMIT, &local->flags))
|
||||
return 0;
|
||||
@ -7479,7 +7483,7 @@ static int airo_config_commit(struct net_device *dev,
|
||||
if (down_interruptible(&local->sem))
|
||||
return -ERESTARTSYS;
|
||||
writeConfigRid(local, 0);
|
||||
enable_MAC(local, &rsp, 0);
|
||||
enable_MAC(local, 0);
|
||||
if (test_bit (FLAG_RESET, &local->flags))
|
||||
airo_set_promisc(local);
|
||||
else
|
||||
@ -7746,7 +7750,6 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
|
||||
unsigned char *iobuf;
|
||||
int len;
|
||||
struct airo_info *ai = dev->priv;
|
||||
Resp rsp;
|
||||
|
||||
if (test_bit(FLAG_FLASHING, &ai->flags))
|
||||
return -EIO;
|
||||
@ -7758,7 +7761,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
|
||||
if (test_bit(FLAG_COMMIT, &ai->flags)) {
|
||||
disable_MAC (ai, 1);
|
||||
writeConfigRid (ai, 1);
|
||||
enable_MAC (ai, &rsp, 1);
|
||||
enable_MAC(ai, 1);
|
||||
}
|
||||
break;
|
||||
case AIROGSLIST: ridcode = RID_SSID; break;
|
||||
@ -7815,7 +7818,6 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
|
||||
struct airo_info *ai = dev->priv;
|
||||
int ridcode;
|
||||
int enabled;
|
||||
Resp rsp;
|
||||
static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
|
||||
unsigned char *iobuf;
|
||||
|
||||
@ -7849,7 +7851,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
|
||||
* same with MAC off
|
||||
*/
|
||||
case AIROPMACON:
|
||||
if (enable_MAC(ai, &rsp, 1) != 0)
|
||||
if (enable_MAC(ai, 1) != 0)
|
||||
return -EIO;
|
||||
return 0;
|
||||
|
||||
|
@ -1768,7 +1768,8 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
|
||||
|
||||
if (priv->stop_rf_kill) {
|
||||
priv->stop_rf_kill = 0;
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill,
|
||||
round_jiffies(HZ));
|
||||
}
|
||||
|
||||
deferred = 1;
|
||||
@ -2098,7 +2099,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
|
||||
/* Make sure the RF Kill check timer is running */
|
||||
priv->stop_rf_kill = 0;
|
||||
cancel_delayed_work(&priv->rf_kill);
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ));
|
||||
}
|
||||
|
||||
static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
|
||||
@ -4233,7 +4234,8 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
|
||||
/* Make sure the RF_KILL check timer is running */
|
||||
priv->stop_rf_kill = 0;
|
||||
cancel_delayed_work(&priv->rf_kill);
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill,
|
||||
round_jiffies(HZ));
|
||||
} else
|
||||
schedule_reset(priv);
|
||||
}
|
||||
@ -5969,7 +5971,8 @@ static void ipw2100_rf_kill(struct work_struct *work)
|
||||
if (rf_kill_active(priv)) {
|
||||
IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
|
||||
if (!priv->stop_rf_kill)
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ);
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill,
|
||||
round_jiffies(HZ));
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
|
@ -1751,7 +1751,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
|
||||
/* Make sure the RF_KILL check timer is running */
|
||||
cancel_delayed_work(&priv->rf_kill);
|
||||
queue_delayed_work(priv->workqueue, &priv->rf_kill,
|
||||
2 * HZ);
|
||||
round_jiffies(2 * HZ));
|
||||
} else
|
||||
queue_work(priv->workqueue, &priv->up);
|
||||
}
|
||||
@ -4690,7 +4690,8 @@ static void ipw_rx_notification(struct ipw_priv *priv,
|
||||
else if (priv->config & CFG_BACKGROUND_SCAN
|
||||
&& priv->status & STATUS_ASSOCIATED)
|
||||
queue_delayed_work(priv->workqueue,
|
||||
&priv->request_scan, HZ);
|
||||
&priv->request_scan,
|
||||
round_jiffies(HZ));
|
||||
|
||||
/* Send an empty event to user space.
|
||||
* We don't send the received data on the event because
|
||||
|
@ -240,7 +240,7 @@ static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
|
||||
if (*enable)
|
||||
penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
|
||||
else
|
||||
penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
|
||||
penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
|
||||
}
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
|
@ -439,7 +439,6 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */
|
||||
lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1719,9 +1719,6 @@ static int wlan_set_encodeext(struct net_device *dev,
|
||||
pkey->type = KEY_TYPE_ID_TKIP;
|
||||
} else if (alg == IW_ENCODE_ALG_CCMP) {
|
||||
pkey->type = KEY_TYPE_ID_AES;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If WPA isn't enabled yet, do that now */
|
||||
|
@ -1853,7 +1853,6 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
|
||||
islpci_private *priv = netdev_priv(ndev);
|
||||
struct islpci_acl *acl = &priv->acl;
|
||||
struct mac_entry *entry;
|
||||
struct list_head *ptr;
|
||||
struct sockaddr *addr = (struct sockaddr *) extra;
|
||||
|
||||
if (addr->sa_family != ARPHRD_ETHER)
|
||||
@ -1861,11 +1860,9 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
|
||||
|
||||
if (down_interruptible(&acl->sem))
|
||||
return -ERESTARTSYS;
|
||||
for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
|
||||
entry = list_entry(ptr, struct mac_entry, _list);
|
||||
|
||||
list_for_each_entry(entry, &acl->mac_list, _list) {
|
||||
if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
|
||||
list_del(ptr);
|
||||
list_del(&entry->_list);
|
||||
acl->size--;
|
||||
kfree(entry);
|
||||
up(&acl->sem);
|
||||
@ -1883,7 +1880,6 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
|
||||
islpci_private *priv = netdev_priv(ndev);
|
||||
struct islpci_acl *acl = &priv->acl;
|
||||
struct mac_entry *entry;
|
||||
struct list_head *ptr;
|
||||
struct sockaddr *dst = (struct sockaddr *) extra;
|
||||
|
||||
dwrq->length = 0;
|
||||
@ -1891,9 +1887,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
|
||||
if (down_interruptible(&acl->sem))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
|
||||
entry = list_entry(ptr, struct mac_entry, _list);
|
||||
|
||||
list_for_each_entry(entry, &acl->mac_list, _list) {
|
||||
memcpy(dst->sa_data, entry->addr, ETH_ALEN);
|
||||
dst->sa_family = ARPHRD_ETHER;
|
||||
dwrq->length++;
|
||||
@ -1960,7 +1954,6 @@ prism54_get_policy(struct net_device *ndev, struct iw_request_info *info,
|
||||
static int
|
||||
prism54_mac_accept(struct islpci_acl *acl, char *mac)
|
||||
{
|
||||
struct list_head *ptr;
|
||||
struct mac_entry *entry;
|
||||
int res = 0;
|
||||
|
||||
@ -1972,8 +1965,7 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac)
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
|
||||
entry = list_entry(ptr, struct mac_entry, _list);
|
||||
list_for_each_entry(entry, &acl->mac_list, _list) {
|
||||
if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
|
||||
res = 1;
|
||||
break;
|
||||
@ -2216,11 +2208,9 @@ prism54_wpa_bss_ie_init(islpci_private *priv)
|
||||
void
|
||||
prism54_wpa_bss_ie_clean(islpci_private *priv)
|
||||
{
|
||||
struct list_head *ptr, *n;
|
||||
struct islpci_bss_wpa_ie *bss, *n;
|
||||
|
||||
list_for_each_safe(ptr, n, &priv->bss_wpa_list) {
|
||||
struct islpci_bss_wpa_ie *bss;
|
||||
bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
|
||||
list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) {
|
||||
kfree(bss);
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
|
||||
msleep(2);
|
||||
}
|
||||
|
||||
static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
|
||||
static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
u16 reg80, reg82, reg84;
|
||||
@ -106,7 +106,7 @@ void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
|
||||
if (priv->asic_rev)
|
||||
rtl8225_write_8051(dev, addr, data);
|
||||
rtl8225_write_8051(dev, addr, cpu_to_le16(data));
|
||||
else
|
||||
rtl8225_write_bitbang(dev, addr, data);
|
||||
}
|
||||
|
@ -49,8 +49,9 @@ void zd_chip_clear(struct zd_chip *chip)
|
||||
ZD_MEMCLEAR(chip, sizeof(*chip));
|
||||
}
|
||||
|
||||
static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size)
|
||||
static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
|
||||
{
|
||||
u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr;
|
||||
return scnprintf(buffer, size, "%02x-%02x-%02x",
|
||||
addr[0], addr[1], addr[2]);
|
||||
}
|
||||
@ -61,10 +62,10 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
|
||||
int i = 0;
|
||||
|
||||
i = scnprintf(buffer, size, "zd1211%s chip ",
|
||||
chip->is_zd1211b ? "b" : "");
|
||||
zd_chip_is_zd1211b(chip) ? "b" : "");
|
||||
i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i);
|
||||
i += scnprintf(buffer+i, size-i, " ");
|
||||
i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
|
||||
i += scnprint_mac_oui(chip, buffer+i, size-i);
|
||||
i += scnprintf(buffer+i, size-i, " ");
|
||||
i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
|
||||
i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
|
||||
@ -366,64 +367,9 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr,
|
||||
const zd_addr_t *addr)
|
||||
{
|
||||
int r;
|
||||
u32 parts[2];
|
||||
|
||||
r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2);
|
||||
if (r) {
|
||||
dev_dbg_f(zd_chip_dev(chip),
|
||||
"error: couldn't read e2p macs. Error number %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
mac_addr[0] = parts[0];
|
||||
mac_addr[1] = parts[0] >> 8;
|
||||
mac_addr[2] = parts[0] >> 16;
|
||||
mac_addr[3] = parts[0] >> 24;
|
||||
mac_addr[4] = parts[1];
|
||||
mac_addr[5] = parts[1] >> 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_e2p_mac_addr(struct zd_chip *chip)
|
||||
{
|
||||
static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 };
|
||||
|
||||
ZD_ASSERT(mutex_is_locked(&chip->mutex));
|
||||
return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr);
|
||||
}
|
||||
|
||||
/* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and
|
||||
* CR_MAC_ADDR_P2 must be overwritten
|
||||
*/
|
||||
void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr)
|
||||
{
|
||||
mutex_lock(&chip->mutex);
|
||||
memcpy(mac_addr, chip->e2p_mac, ETH_ALEN);
|
||||
mutex_unlock(&chip->mutex);
|
||||
}
|
||||
|
||||
static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
|
||||
{
|
||||
static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 };
|
||||
return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr);
|
||||
}
|
||||
|
||||
int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr)
|
||||
{
|
||||
int r;
|
||||
|
||||
dev_dbg_f(zd_chip_dev(chip), "\n");
|
||||
mutex_lock(&chip->mutex);
|
||||
r = read_mac_addr(chip, mac_addr);
|
||||
mutex_unlock(&chip->mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
|
||||
{
|
||||
int r;
|
||||
@ -444,12 +390,6 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
|
||||
#ifdef DEBUG
|
||||
{
|
||||
u8 tmp[ETH_ALEN];
|
||||
read_mac_addr(chip, tmp);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
mutex_unlock(&chip->mutex);
|
||||
return r;
|
||||
}
|
||||
@ -809,7 +749,7 @@ out:
|
||||
|
||||
static int hw_reset_phy(struct zd_chip *chip)
|
||||
{
|
||||
return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) :
|
||||
return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) :
|
||||
zd1211_hw_reset_phy(chip);
|
||||
}
|
||||
|
||||
@ -874,7 +814,7 @@ static int hw_init_hmac(struct zd_chip *chip)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return chip->is_zd1211b ?
|
||||
return zd_chip_is_zd1211b(chip) ?
|
||||
zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
|
||||
}
|
||||
|
||||
@ -1136,8 +1076,15 @@ static int read_fw_regs_offset(struct zd_chip *chip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read mac address using pre-firmware interface */
|
||||
int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr)
|
||||
{
|
||||
dev_dbg_f(zd_chip_dev(chip), "\n");
|
||||
return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr,
|
||||
ETH_ALEN);
|
||||
}
|
||||
|
||||
int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
|
||||
int zd_chip_init_hw(struct zd_chip *chip)
|
||||
{
|
||||
int r;
|
||||
u8 rf_type;
|
||||
@ -1145,7 +1092,6 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
|
||||
dev_dbg_f(zd_chip_dev(chip), "\n");
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
r = test_init(chip);
|
||||
@ -1201,10 +1147,6 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type)
|
||||
goto out;
|
||||
#endif /* DEBUG */
|
||||
|
||||
r = read_e2p_mac_addr(chip);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = read_cal_int_tables(chip);
|
||||
if (r)
|
||||
goto out;
|
||||
@ -1259,7 +1201,7 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
|
||||
r = update_pwr_int(chip, channel);
|
||||
if (r)
|
||||
return r;
|
||||
if (chip->is_zd1211b) {
|
||||
if (zd_chip_is_zd1211b(chip)) {
|
||||
static const struct zd_ioreq16 ioreqs[] = {
|
||||
{ CR69, 0x28 },
|
||||
{},
|
||||
|
@ -704,7 +704,6 @@ struct zd_chip {
|
||||
struct mutex mutex;
|
||||
/* Base address of FW_REG_ registers */
|
||||
zd_addr_t fw_regs_base;
|
||||
u8 e2p_mac[ETH_ALEN];
|
||||
/* EepSetPoint in the vendor driver */
|
||||
u8 pwr_cal_values[E2P_CHANNEL_COUNT];
|
||||
/* integration values in the vendor driver */
|
||||
@ -715,7 +714,7 @@ struct zd_chip {
|
||||
unsigned int pa_type:4,
|
||||
patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
|
||||
new_phy_layout:1, al2230s_bit:1,
|
||||
is_zd1211b:1, supports_tx_led:1;
|
||||
supports_tx_led:1;
|
||||
};
|
||||
|
||||
static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
|
||||
@ -734,9 +733,15 @@ void zd_chip_init(struct zd_chip *chip,
|
||||
struct net_device *netdev,
|
||||
struct usb_interface *intf);
|
||||
void zd_chip_clear(struct zd_chip *chip);
|
||||
int zd_chip_init_hw(struct zd_chip *chip, u8 device_type);
|
||||
int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
|
||||
int zd_chip_init_hw(struct zd_chip *chip);
|
||||
int zd_chip_reset(struct zd_chip *chip);
|
||||
|
||||
static inline int zd_chip_is_zd1211b(struct zd_chip *chip)
|
||||
{
|
||||
return chip->usb.is_zd1211b;
|
||||
}
|
||||
|
||||
static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
|
||||
const zd_addr_t *addresses,
|
||||
unsigned int count)
|
||||
@ -825,8 +830,6 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
|
||||
}
|
||||
u8 zd_chip_get_channel(struct zd_chip *chip);
|
||||
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
|
||||
void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr);
|
||||
int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr);
|
||||
int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
|
||||
int zd_chip_switch_radio_on(struct zd_chip *chip);
|
||||
int zd_chip_switch_radio_off(struct zd_chip *chip);
|
||||
|
@ -86,38 +86,46 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
int zd_mac_init_hw(struct zd_mac *mac, u8 device_type)
|
||||
int zd_mac_preinit_hw(struct zd_mac *mac)
|
||||
{
|
||||
int r;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zd_mac_init_hw(struct zd_mac *mac)
|
||||
{
|
||||
int r;
|
||||
struct zd_chip *chip = &mac->chip;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 default_regdomain;
|
||||
|
||||
r = zd_chip_enable_int(chip);
|
||||
if (r)
|
||||
goto out;
|
||||
r = zd_chip_init_hw(chip, device_type);
|
||||
r = zd_chip_init_hw(chip);
|
||||
if (r)
|
||||
goto disable_int;
|
||||
|
||||
zd_get_e2p_mac_addr(chip, addr);
|
||||
r = zd_write_mac_addr(chip, addr);
|
||||
if (r)
|
||||
goto disable_int;
|
||||
ZD_ASSERT(!irqs_disabled());
|
||||
spin_lock_irq(&mac->lock);
|
||||
memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
|
||||
spin_unlock_irq(&mac->lock);
|
||||
|
||||
r = zd_read_regdomain(chip, &default_regdomain);
|
||||
if (r)
|
||||
goto disable_int;
|
||||
if (!zd_regdomain_supported(default_regdomain)) {
|
||||
dev_dbg_f(zd_mac_dev(mac),
|
||||
"Regulatory Domain %#04x is not supported.\n",
|
||||
default_regdomain);
|
||||
r = -EINVAL;
|
||||
goto disable_int;
|
||||
/* The vendor driver overrides the regulatory domain and
|
||||
* allowed channel registers and unconditionally restricts
|
||||
* available channels to 1-11 everywhere. Match their
|
||||
* questionable behaviour only for regdomains which we don't
|
||||
* recognise. */
|
||||
dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: "
|
||||
"%#04x. Defaulting to FCC.\n", default_regdomain);
|
||||
default_regdomain = ZD_REGDOMAIN_FCC;
|
||||
}
|
||||
spin_lock_irq(&mac->lock);
|
||||
mac->regdomain = mac->default_regdomain = default_regdomain;
|
||||
@ -164,14 +172,25 @@ int zd_mac_open(struct net_device *netdev)
|
||||
{
|
||||
struct zd_mac *mac = zd_netdev_mac(netdev);
|
||||
struct zd_chip *chip = &mac->chip;
|
||||
struct zd_usb *usb = &chip->usb;
|
||||
int r;
|
||||
|
||||
if (!usb->initialized) {
|
||||
r = zd_usb_init_hw(usb);
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
|
||||
tasklet_enable(&mac->rx_tasklet);
|
||||
|
||||
r = zd_chip_enable_int(chip);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = zd_write_mac_addr(chip, netdev->dev_addr);
|
||||
if (r)
|
||||
goto disable_int;
|
||||
|
||||
r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
|
||||
if (r < 0)
|
||||
goto disable_int;
|
||||
@ -251,9 +270,11 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p)
|
||||
dev_dbg_f(zd_mac_dev(mac),
|
||||
"Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data));
|
||||
|
||||
r = zd_write_mac_addr(chip, addr->sa_data);
|
||||
if (r)
|
||||
return r;
|
||||
if (netdev->flags & IFF_UP) {
|
||||
r = zd_write_mac_addr(chip, addr->sa_data);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
|
||||
@ -855,7 +876,7 @@ static int fill_ctrlset(struct zd_mac *mac,
|
||||
/* ZD1211B: Computing the length difference this way, gives us
|
||||
* flexibility to compute the packet length.
|
||||
*/
|
||||
cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ?
|
||||
cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
|
||||
packet_length - frag_len : packet_length);
|
||||
|
||||
/*
|
||||
|
@ -189,7 +189,8 @@ int zd_mac_init(struct zd_mac *mac,
|
||||
struct usb_interface *intf);
|
||||
void zd_mac_clear(struct zd_mac *mac);
|
||||
|
||||
int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
|
||||
int zd_mac_preinit_hw(struct zd_mac *mac);
|
||||
int zd_mac_init_hw(struct zd_mac *mac);
|
||||
|
||||
int zd_mac_open(struct net_device *netdev);
|
||||
int zd_mac_stop(struct net_device *netdev);
|
||||
|
@ -34,7 +34,7 @@ static const char * const rfs[] = {
|
||||
[AL2210_RF] = "AL2210_RF",
|
||||
[MAXIM_NEW_RF] = "MAXIM_NEW_RF",
|
||||
[UW2453_RF] = "UW2453_RF",
|
||||
[UNKNOWN_A_RF] = "UNKNOWN_A_RF",
|
||||
[AL2230S_RF] = "AL2230S_RF",
|
||||
[RALINK_RF] = "RALINK_RF",
|
||||
[INTERSIL_RF] = "INTERSIL_RF",
|
||||
[RF2959_RF] = "RF2959_RF",
|
||||
@ -77,6 +77,7 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
|
||||
r = zd_rf_init_rf2959(rf);
|
||||
break;
|
||||
case AL2230_RF:
|
||||
case AL2230S_RF:
|
||||
r = zd_rf_init_al2230(rf);
|
||||
break;
|
||||
case AL7230B_RF:
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define AL2210_RF 0x7
|
||||
#define MAXIM_NEW_RF 0x8
|
||||
#define UW2453_RF 0x9
|
||||
#define UNKNOWN_A_RF 0xa
|
||||
#define AL2230S_RF 0xa
|
||||
#define RALINK_RF 0xb
|
||||
#define INTERSIL_RF 0xc
|
||||
#define RF2959_RF 0xd
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "zd_usb.h"
|
||||
#include "zd_chip.h"
|
||||
|
||||
#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF)
|
||||
|
||||
static const u32 zd1211_al2230_table[][3] = {
|
||||
RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
|
||||
RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
|
||||
@ -176,7 +178,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (chip->al2230s_bit) {
|
||||
if (IS_AL2230S(chip)) {
|
||||
r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
|
||||
ARRAY_SIZE(ioreqs_init_al2230s));
|
||||
if (r)
|
||||
@ -188,7 +190,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf)
|
||||
return r;
|
||||
|
||||
/* improve band edge for AL2230S */
|
||||
if (chip->al2230s_bit)
|
||||
if (IS_AL2230S(chip))
|
||||
r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
|
||||
else
|
||||
r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
|
||||
@ -314,7 +316,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (chip->al2230s_bit) {
|
||||
if (IS_AL2230S(chip)) {
|
||||
r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
|
||||
ARRAY_SIZE(ioreqs_init_al2230s));
|
||||
if (r)
|
||||
@ -328,7 +330,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (chip->al2230s_bit)
|
||||
if (IS_AL2230S(chip))
|
||||
r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
|
||||
else
|
||||
r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
|
||||
@ -422,7 +424,7 @@ int zd_rf_init_al2230(struct zd_rf *rf)
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
rf->switch_radio_off = al2230_switch_radio_off;
|
||||
if (chip->is_zd1211b) {
|
||||
if (zd_chip_is_zd1211b(chip)) {
|
||||
rf->init_hw = zd1211b_al2230_init_hw;
|
||||
rf->set_channel = zd1211b_al2230_set_channel;
|
||||
rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
|
||||
|
@ -473,7 +473,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
|
||||
{
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
if (chip->is_zd1211b) {
|
||||
if (zd_chip_is_zd1211b(chip)) {
|
||||
rf->init_hw = zd1211b_al7230b_init_hw;
|
||||
rf->switch_radio_on = zd1211b_al7230b_switch_radio_on;
|
||||
rf->set_channel = zd1211b_al7230b_set_channel;
|
||||
|
@ -265,7 +265,7 @@ int zd_rf_init_rf2959(struct zd_rf *rf)
|
||||
{
|
||||
struct zd_chip *chip = zd_rf_to_chip(rf);
|
||||
|
||||
if (chip->is_zd1211b) {
|
||||
if (zd_chip_is_zd1211b(chip)) {
|
||||
dev_err(zd_chip_dev(chip),
|
||||
"RF2959 is currently not supported for ZD1211B"
|
||||
" devices\n");
|
||||
|
@ -486,7 +486,7 @@ static int uw2453_switch_radio_on(struct zd_rf *rf)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (chip->is_zd1211b)
|
||||
if (zd_chip_is_zd1211b(chip))
|
||||
ioreqs[1].value = 0x7f;
|
||||
|
||||
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
|
||||
|
@ -71,6 +71,7 @@ static struct usb_device_id usb_ids[] = {
|
||||
{ USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
|
||||
{ USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
|
||||
{ USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
|
||||
{ USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
|
||||
/* "Driverless" devices that need ejecting */
|
||||
{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
|
||||
{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
|
||||
@ -195,26 +196,27 @@ static u16 get_word(const void *data, u16 offset)
|
||||
return le16_to_cpu(p[offset]);
|
||||
}
|
||||
|
||||
static char *get_fw_name(char *buffer, size_t size, u8 device_type,
|
||||
static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size,
|
||||
const char* postfix)
|
||||
{
|
||||
scnprintf(buffer, size, "%s%s",
|
||||
device_type == DEVICE_ZD1211B ?
|
||||
usb->is_zd1211b ?
|
||||
FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
|
||||
postfix);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int handle_version_mismatch(struct usb_device *udev, u8 device_type,
|
||||
static int handle_version_mismatch(struct zd_usb *usb,
|
||||
const struct firmware *ub_fw)
|
||||
{
|
||||
struct usb_device *udev = zd_usb_to_usbdev(usb);
|
||||
const struct firmware *ur_fw = NULL;
|
||||
int offset;
|
||||
int r = 0;
|
||||
char fw_name[128];
|
||||
|
||||
r = request_fw_file(&ur_fw,
|
||||
get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"),
|
||||
get_fw_name(usb, fw_name, sizeof(fw_name), "ur"),
|
||||
&udev->dev);
|
||||
if (r)
|
||||
goto error;
|
||||
@ -237,11 +239,12 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int upload_firmware(struct usb_device *udev, u8 device_type)
|
||||
static int upload_firmware(struct zd_usb *usb)
|
||||
{
|
||||
int r;
|
||||
u16 fw_bcdDevice;
|
||||
u16 bcdDevice;
|
||||
struct usb_device *udev = zd_usb_to_usbdev(usb);
|
||||
const struct firmware *ub_fw = NULL;
|
||||
const struct firmware *uph_fw = NULL;
|
||||
char fw_name[128];
|
||||
@ -249,7 +252,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
|
||||
bcdDevice = get_bcdDevice(udev);
|
||||
|
||||
r = request_fw_file(&ub_fw,
|
||||
get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"),
|
||||
get_fw_name(usb, fw_name, sizeof(fw_name), "ub"),
|
||||
&udev->dev);
|
||||
if (r)
|
||||
goto error;
|
||||
@ -264,7 +267,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
|
||||
dev_warn(&udev->dev, "device has old bootcode, please "
|
||||
"report success or failure\n");
|
||||
|
||||
r = handle_version_mismatch(udev, device_type, ub_fw);
|
||||
r = handle_version_mismatch(usb, ub_fw);
|
||||
if (r)
|
||||
goto error;
|
||||
} else {
|
||||
@ -275,7 +278,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type)
|
||||
|
||||
|
||||
r = request_fw_file(&uph_fw,
|
||||
get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"),
|
||||
get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"),
|
||||
&udev->dev);
|
||||
if (r)
|
||||
goto error;
|
||||
@ -294,6 +297,30 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Read data from device address space using "firmware interface" which does
|
||||
* not require firmware to be loaded. */
|
||||
int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
|
||||
{
|
||||
int r;
|
||||
struct usb_device *udev = zd_usb_to_usbdev(usb);
|
||||
|
||||
r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
|
||||
data, len, 5000);
|
||||
if (r < 0) {
|
||||
dev_err(&udev->dev,
|
||||
"read over firmware interface failed: %d\n", r);
|
||||
return r;
|
||||
} else if (r != len) {
|
||||
dev_err(&udev->dev,
|
||||
"incomplete read over firmware interface: %d/%d\n",
|
||||
r, len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define urb_dev(urb) (&(urb)->dev->dev)
|
||||
|
||||
static inline void handle_regs_int(struct urb *urb)
|
||||
@ -920,9 +947,42 @@ static int eject_installer(struct usb_interface *intf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zd_usb_init_hw(struct zd_usb *usb)
|
||||
{
|
||||
int r;
|
||||
struct zd_mac *mac = zd_usb_to_mac(usb);
|
||||
|
||||
dev_dbg_f(zd_usb_dev(usb), "\n");
|
||||
|
||||
r = upload_firmware(usb);
|
||||
if (r) {
|
||||
dev_err(zd_usb_dev(usb),
|
||||
"couldn't load firmware. Error number %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = usb_reset_configuration(zd_usb_to_usbdev(usb));
|
||||
if (r) {
|
||||
dev_dbg_f(zd_usb_dev(usb),
|
||||
"couldn't reset configuration. Error number %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = zd_mac_init_hw(mac);
|
||||
if (r) {
|
||||
dev_dbg_f(zd_usb_dev(usb),
|
||||
"couldn't initialize mac. Error number %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
usb->initialized = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
int r;
|
||||
struct zd_usb *usb;
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct net_device *netdev = NULL;
|
||||
|
||||
@ -950,26 +1010,10 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = upload_firmware(udev, id->driver_info);
|
||||
if (r) {
|
||||
dev_err(&intf->dev,
|
||||
"couldn't load firmware. Error number %d\n", r);
|
||||
goto error;
|
||||
}
|
||||
usb = &zd_netdev_mac(netdev)->chip.usb;
|
||||
usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
|
||||
|
||||
r = usb_reset_configuration(udev);
|
||||
if (r) {
|
||||
dev_dbg_f(&intf->dev,
|
||||
"couldn't reset configuration. Error number %d\n", r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* At this point the interrupt endpoint is not generally enabled. We
|
||||
* save the USB bandwidth until the network device is opened. But
|
||||
* notify that the initialization of the MAC will require the
|
||||
* interrupts to be temporary enabled.
|
||||
*/
|
||||
r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info);
|
||||
r = zd_mac_preinit_hw(zd_netdev_mac(netdev));
|
||||
if (r) {
|
||||
dev_dbg_f(&intf->dev,
|
||||
"couldn't initialize mac. Error number %d\n", r);
|
||||
|
@ -188,6 +188,7 @@ struct zd_usb {
|
||||
struct zd_usb_rx rx;
|
||||
struct zd_usb_tx tx;
|
||||
struct usb_interface *intf;
|
||||
u8 is_zd1211b:1, initialized:1;
|
||||
};
|
||||
|
||||
#define zd_usb_dev(usb) (&usb->intf->dev)
|
||||
@ -236,6 +237,8 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
|
||||
|
||||
int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
|
||||
|
||||
int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len);
|
||||
|
||||
extern struct workqueue_struct *zd_workqueue;
|
||||
|
||||
#endif /* _ZD_USB_H */
|
||||
|
@ -211,6 +211,10 @@ struct qeth_perf_stats {
|
||||
/* initial values when measuring starts */
|
||||
unsigned long initial_rx_packets;
|
||||
unsigned long initial_tx_packets;
|
||||
/* inbound scatter gather data */
|
||||
unsigned int sg_skbs_rx;
|
||||
unsigned int sg_frags_rx;
|
||||
unsigned int sg_alloc_page_rx;
|
||||
};
|
||||
|
||||
/* Routing stuff */
|
||||
@ -341,6 +345,9 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
|
||||
|
||||
#define QETH_IP_HEADER_SIZE 40
|
||||
|
||||
/* large receive scatter gather copy break */
|
||||
#define QETH_RX_SG_CB (PAGE_SIZE >> 1)
|
||||
|
||||
struct qeth_hdr_layer3 {
|
||||
__u8 id;
|
||||
__u8 flags;
|
||||
@ -771,6 +778,7 @@ struct qeth_card_options {
|
||||
int layer2;
|
||||
enum qeth_large_send_types large_send;
|
||||
int performance_stats;
|
||||
int rx_sg_cb;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -828,6 +836,7 @@ struct qeth_card {
|
||||
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
|
||||
unsigned short,void *,void *,unsigned);
|
||||
struct qeth_osn_info osn_info;
|
||||
atomic_t force_alloc_skb;
|
||||
};
|
||||
|
||||
struct qeth_card_list_struct {
|
||||
|
@ -1054,6 +1054,7 @@ qeth_set_intial_options(struct qeth_card *card)
|
||||
else
|
||||
card->options.layer2 = 0;
|
||||
card->options.performance_stats = 0;
|
||||
card->options.rx_sg_cb = QETH_RX_SG_CB;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1934,6 +1935,7 @@ qeth_send_control_data(struct qeth_card *card, int len,
|
||||
atomic_inc(&reply->received);
|
||||
wake_up(&reply->wait_q);
|
||||
}
|
||||
cpu_relax();
|
||||
};
|
||||
rc = reply->rc;
|
||||
qeth_put_reply(reply);
|
||||
@ -2258,6 +2260,89 @@ qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
|
||||
return skb;
|
||||
}
|
||||
|
||||
static inline int
|
||||
qeth_create_skb_frag(struct qdio_buffer_element *element,
|
||||
struct sk_buff **pskb,
|
||||
int offset, int *pfrag, int data_len)
|
||||
{
|
||||
struct page *page = virt_to_page(element->addr);
|
||||
if (*pfrag == 0) {
|
||||
/* the upper protocol layers assume that there is data in the
|
||||
* skb itself. Copy a small amount (64 bytes) to make them
|
||||
* happy. */
|
||||
*pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH);
|
||||
if (!(*pskb))
|
||||
return -ENOMEM;
|
||||
skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH);
|
||||
if (data_len <= 64) {
|
||||
memcpy(skb_put(*pskb, data_len), element->addr + offset,
|
||||
data_len);
|
||||
} else {
|
||||
get_page(page);
|
||||
memcpy(skb_put(*pskb, 64), element->addr + offset, 64);
|
||||
skb_fill_page_desc(*pskb, *pfrag, page, offset + 64,
|
||||
data_len - 64);
|
||||
(*pskb)->data_len += data_len - 64;
|
||||
(*pskb)->len += data_len - 64;
|
||||
(*pskb)->truesize += data_len - 64;
|
||||
}
|
||||
} else {
|
||||
get_page(page);
|
||||
skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len);
|
||||
(*pskb)->data_len += data_len;
|
||||
(*pskb)->len += data_len;
|
||||
(*pskb)->truesize += data_len;
|
||||
}
|
||||
(*pfrag)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct qeth_buffer_pool_entry *
|
||||
qeth_find_free_buffer_pool_entry(struct qeth_card *card)
|
||||
{
|
||||
struct list_head *plh;
|
||||
struct qeth_buffer_pool_entry *entry;
|
||||
int i, free;
|
||||
struct page *page;
|
||||
|
||||
if (list_empty(&card->qdio.in_buf_pool.entry_list))
|
||||
return NULL;
|
||||
|
||||
list_for_each(plh, &card->qdio.in_buf_pool.entry_list) {
|
||||
entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
|
||||
free = 1;
|
||||
for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
|
||||
if (page_count(virt_to_page(entry->elements[i])) > 1) {
|
||||
free = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (free) {
|
||||
list_del_init(&entry->list);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
/* no free buffer in pool so take first one and swap pages */
|
||||
entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
|
||||
struct qeth_buffer_pool_entry, list);
|
||||
for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
|
||||
if (page_count(virt_to_page(entry->elements[i])) > 1) {
|
||||
page = alloc_page(GFP_ATOMIC|GFP_DMA);
|
||||
if (!page) {
|
||||
return NULL;
|
||||
} else {
|
||||
free_page((unsigned long)entry->elements[i]);
|
||||
entry->elements[i] = page_address(page);
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.sg_alloc_page_rx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
list_del_init(&entry->list);
|
||||
return entry;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
|
||||
struct qdio_buffer_element **__element, int *__offset,
|
||||
@ -2269,6 +2354,8 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
|
||||
int skb_len;
|
||||
void *data_ptr;
|
||||
int data_len;
|
||||
int use_rx_sg = 0;
|
||||
int frag = 0;
|
||||
|
||||
QETH_DBF_TEXT(trace,6,"nextskb");
|
||||
/* qeth_hdr must not cross element boundaries */
|
||||
@ -2293,23 +2380,43 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
|
||||
|
||||
if (!skb_len)
|
||||
return NULL;
|
||||
if (card->options.fake_ll){
|
||||
if(card->dev->type == ARPHRD_IEEE802_TR){
|
||||
if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr)))
|
||||
goto no_mem;
|
||||
skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
|
||||
if ((skb_len >= card->options.rx_sg_cb) &&
|
||||
(!(card->info.type == QETH_CARD_TYPE_OSN)) &&
|
||||
(!atomic_read(&card->force_alloc_skb))) {
|
||||
use_rx_sg = 1;
|
||||
} else {
|
||||
if (card->options.fake_ll) {
|
||||
if (card->dev->type == ARPHRD_IEEE802_TR) {
|
||||
if (!(skb = qeth_get_skb(skb_len +
|
||||
QETH_FAKE_LL_LEN_TR, *hdr)))
|
||||
goto no_mem;
|
||||
skb_reserve(skb, QETH_FAKE_LL_LEN_TR);
|
||||
} else {
|
||||
if (!(skb = qeth_get_skb(skb_len +
|
||||
QETH_FAKE_LL_LEN_ETH, *hdr)))
|
||||
goto no_mem;
|
||||
skb_reserve(skb, QETH_FAKE_LL_LEN_ETH);
|
||||
}
|
||||
} else {
|
||||
if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr)))
|
||||
skb = qeth_get_skb(skb_len, *hdr);
|
||||
if (!skb)
|
||||
goto no_mem;
|
||||
skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
|
||||
}
|
||||
} else if (!(skb = qeth_get_skb(skb_len, *hdr)))
|
||||
goto no_mem;
|
||||
}
|
||||
|
||||
data_ptr = element->addr + offset;
|
||||
while (skb_len) {
|
||||
data_len = min(skb_len, (int)(element->length - offset));
|
||||
if (data_len)
|
||||
memcpy(skb_put(skb, data_len), data_ptr, data_len);
|
||||
if (data_len) {
|
||||
if (use_rx_sg) {
|
||||
if (qeth_create_skb_frag(element, &skb, offset,
|
||||
&frag, data_len))
|
||||
goto no_mem;
|
||||
} else {
|
||||
memcpy(skb_put(skb, data_len), data_ptr,
|
||||
data_len);
|
||||
}
|
||||
}
|
||||
skb_len -= data_len;
|
||||
if (skb_len){
|
||||
if (qeth_is_last_sbale(element)){
|
||||
@ -2331,6 +2438,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
|
||||
}
|
||||
*__element = element;
|
||||
*__offset = offset;
|
||||
if (use_rx_sg && card->options.performance_stats) {
|
||||
card->perf_stats.sg_skbs_rx++;
|
||||
card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags;
|
||||
}
|
||||
return skb;
|
||||
no_mem:
|
||||
if (net_ratelimit()){
|
||||
@ -2608,28 +2719,15 @@ qeth_process_inbound_buffer(struct qeth_card *card,
|
||||
}
|
||||
}
|
||||
|
||||
static struct qeth_buffer_pool_entry *
|
||||
qeth_get_buffer_pool_entry(struct qeth_card *card)
|
||||
{
|
||||
struct qeth_buffer_pool_entry *entry;
|
||||
|
||||
QETH_DBF_TEXT(trace, 6, "gtbfplen");
|
||||
if (!list_empty(&card->qdio.in_buf_pool.entry_list)) {
|
||||
entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
|
||||
struct qeth_buffer_pool_entry, list);
|
||||
list_del_init(&entry->list);
|
||||
return entry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
|
||||
{
|
||||
struct qeth_buffer_pool_entry *pool_entry;
|
||||
int i;
|
||||
|
||||
pool_entry = qeth_get_buffer_pool_entry(card);
|
||||
|
||||
pool_entry = qeth_find_free_buffer_pool_entry(card);
|
||||
if (!pool_entry)
|
||||
return 1;
|
||||
/*
|
||||
* since the buffer is accessed only from the input_tasklet
|
||||
* there shouldn't be a need to synchronize; also, since we use
|
||||
@ -2648,6 +2746,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
|
||||
buf->buffer->element[i].flags = 0;
|
||||
}
|
||||
buf->state = QETH_QDIO_BUF_EMPTY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2682,6 +2781,7 @@ qeth_queue_input_buffer(struct qeth_card *card, int index)
|
||||
int count;
|
||||
int i;
|
||||
int rc;
|
||||
int newcount = 0;
|
||||
|
||||
QETH_DBF_TEXT(trace,6,"queinbuf");
|
||||
count = (index < queue->next_buf_to_init)?
|
||||
@ -2692,9 +2792,27 @@ qeth_queue_input_buffer(struct qeth_card *card, int index)
|
||||
/* only requeue at a certain threshold to avoid SIGAs */
|
||||
if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){
|
||||
for (i = queue->next_buf_to_init;
|
||||
i < queue->next_buf_to_init + count; ++i)
|
||||
qeth_init_input_buffer(card,
|
||||
&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]);
|
||||
i < queue->next_buf_to_init + count; ++i) {
|
||||
if (qeth_init_input_buffer(card,
|
||||
&queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) {
|
||||
break;
|
||||
} else {
|
||||
newcount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (newcount < count) {
|
||||
/* we are in memory shortage so we switch back to
|
||||
traditional skb allocation and drop packages */
|
||||
if (atomic_cmpxchg(&card->force_alloc_skb, 0, 1))
|
||||
printk(KERN_WARNING
|
||||
"qeth: switch to alloc skb\n");
|
||||
count = newcount;
|
||||
} else {
|
||||
if (atomic_cmpxchg(&card->force_alloc_skb, 1, 0))
|
||||
printk(KERN_WARNING "qeth: switch to sg\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* according to old code it should be avoided to requeue all
|
||||
* 128 buffers in order to benefit from PCI avoidance.
|
||||
@ -6494,6 +6612,7 @@ qeth_hardsetup_card(struct qeth_card *card)
|
||||
|
||||
QETH_DBF_TEXT(setup, 2, "hrdsetup");
|
||||
|
||||
atomic_set(&card->force_alloc_skb, 0);
|
||||
retry:
|
||||
if (retries < 3){
|
||||
PRINT_WARN("Retrying to do IDX activates.\n");
|
||||
|
@ -212,6 +212,12 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
|
||||
" Skb fragments sent in SG mode : %u\n\n",
|
||||
card->perf_stats.sg_skbs_sent,
|
||||
card->perf_stats.sg_frags_sent);
|
||||
seq_printf(s, " Skbs received in SG mode : %u\n"
|
||||
" Skb fragments received in SG mode : %u\n"
|
||||
" Page allocations for rx SG mode : %u\n\n",
|
||||
card->perf_stats.sg_skbs_rx,
|
||||
card->perf_stats.sg_frags_rx,
|
||||
card->perf_stats.sg_alloc_page_rx);
|
||||
seq_printf(s, " large_send tx (in Kbytes) : %u\n"
|
||||
" large_send count : %u\n\n",
|
||||
card->perf_stats.large_send_bytes >> 10,
|
||||
|
@ -64,6 +64,7 @@ extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
|
||||
|
||||
/* Ethernet (EMAC & MACB) */
|
||||
struct at91_eth_data {
|
||||
u32 phy_mask;
|
||||
u8 phy_irq_pin; /* PHY IRQ */
|
||||
u8 is_rmii; /* using RMII interface? */
|
||||
};
|
||||
|
@ -21,6 +21,7 @@ void at32_map_usart(unsigned int hw_id, unsigned int line);
|
||||
struct platform_device *at32_add_device_usart(unsigned int id);
|
||||
|
||||
struct eth_platform_data {
|
||||
u32 phy_mask;
|
||||
u8 is_rmii;
|
||||
};
|
||||
struct platform_device *
|
||||
|
@ -271,8 +271,11 @@ ieee80211softmac_assoc_work(struct work_struct *work)
|
||||
*/
|
||||
dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
|
||||
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
|
||||
if (ieee80211softmac_start_scan(mac))
|
||||
if (ieee80211softmac_start_scan(mac)) {
|
||||
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
|
||||
mac->associnfo.associating = 0;
|
||||
mac->associnfo.associated = 0;
|
||||
}
|
||||
goto out;
|
||||
} else {
|
||||
mac->associnfo.associating = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user