/** * struct ksz_desc_info - Descriptor information data structure * @ring: First descriptor in the ring. * @cur: Current descriptor being manipulated. * @ring_virt: First hardware descriptor in the ring. * @ring_phys: The physical address of the first descriptor of the ring. * @size: Size of hardware descriptor. * @alloc: Number of descriptors allocated. * @avail: Number of descriptors available for use. * @last: Index for last descriptor released to hardware. * @next: Index for next descriptor available for use. * @mask: Mask for index wrapping.
*/ struct ksz_desc_info { struct ksz_desc *ring; struct ksz_desc *cur; struct ksz_hw_desc *ring_virt;
u32 ring_phys; int size; int alloc; int avail; int last; int next; int mask;
};
/** * struct ksz_port_mib - Port MIB data structure * @cnt_ptr: Current pointer to MIB counter index. * @link_down: Indication the link has just gone down. * @state: Connection status of the port. * @mib_start: The starting counter index. Some ports do not start at 0. * @counter: 64-bit MIB counter value. * @dropped: Temporary buffer to remember last read packet dropped values. * * MIB counters needs to be read periodically so that counters do not get * overflowed and give incorrect values. A right balance is needed to * satisfy this condition and not waste too much CPU time. * * It is pointless to read MIB counters when the port is disconnected. The * @state provides the connection status so that MIB counters are read only * when the port is connected. The @link_down indicates the port is just * disconnected so that all MIB counters are read one last time to update the * information.
*/ struct ksz_port_mib {
u8 cnt_ptr;
u8 link_down;
u8 state;
u8 mib_start;
/** * struct ksz_port_cfg - Port configuration data structure * @vid: VID value. * @member: Port membership. * @port_prio: Port priority. * @rx_rate: Receive priority rate. * @tx_rate: Transmit priority rate. * @stp_state: Current Spanning Tree Protocol state.
*/ struct ksz_port_cfg {
u16 vid;
u8 member;
u8 port_prio;
u32 rx_rate[PRIO_QUEUES];
u32 tx_rate[PRIO_QUEUES]; int stp_state;
};
/** * struct ksz_switch - KSZ8842 switch data structure * @mac_table: MAC table entries information. * @vlan_table: VLAN table entries information. * @port_cfg: Port configuration information. * @diffserv: DiffServ priority settings. Possible values from 6-bit of ToS * (bit7 ~ bit2) field. * @p_802_1p: 802.1P priority settings. Possible values from 3-bit of 802.1p * Tag priority field. * @br_addr: Bridge address. Used for STP. * @other_addr: Other MAC address. Used for multiple network device mode. * @broad_per: Broadcast storm percentage. * @member: Current port membership. Used for STP.
*/ struct ksz_switch { struct ksz_mac_table mac_table[STATIC_MAC_TABLE_ENTRIES]; struct ksz_vlan_table vlan_table[VLAN_TABLE_ENTRIES]; struct ksz_port_cfg port_cfg[TOTAL_PORT_NUM];
/** * struct ksz_port_info - Port information data structure * @state: Connection status of the port. * @tx_rate: Transmit rate divided by 10000 to get Mbit. * @duplex: Duplex mode. * @advertised: Advertised auto-negotiation setting. Used to determine link. * @partner: Auto-negotiation partner setting. Used to determine link. * @port_id: Port index to access actual hardware register. * @pdev: Pointer to OS dependent network device.
*/ struct ksz_port_info {
uint state;
uint tx_rate;
u8 duplex;
u8 advertised;
u8 partner;
u8 port_id; void *pdev;
};
/** * struct ksz_hw - KSZ884X hardware data structure * @io: Virtual address assigned. * @ksz_switch: Pointer to KSZ8842 switch. * @port_info: Port information. * @port_mib: Port MIB information. * @dev_count: Number of network devices this hardware supports. * @dst_ports: Destination ports in switch for transmission. * @id: Hardware ID. Used for display only. * @mib_cnt: Number of MIB counters this hardware has. * @mib_port_cnt: Number of ports with MIB counters. * @tx_cfg: Cached transmit control settings. * @rx_cfg: Cached receive control settings. * @intr_mask: Current interrupt mask. * @intr_set: Current interrup set. * @intr_blocked: Interrupt blocked. * @rx_desc_info: Receive descriptor information. * @tx_desc_info: Transmit descriptor information. * @tx_int_cnt: Transmit interrupt count. Used for TX optimization. * @tx_int_mask: Transmit interrupt mask. Used for TX optimization. * @tx_size: Transmit data size. Used for TX optimization. * The maximum is defined by MAX_TX_HELD_SIZE. * @perm_addr: Permanent MAC address. * @override_addr: Overridden MAC address. * @address: Additional MAC address entries. * @addr_list_size: Additional MAC address list size. * @mac_override: Indication of MAC address overridden. * @promiscuous: Counter to keep track of promiscuous mode set. * @all_multi: Counter to keep track of all multicast mode set. * @multi_list: Multicast address entries. * @multi_bits: Cached multicast hash table settings. * @multi_list_size: Multicast address list size. * @enabled: Indication of hardware enabled. * @rx_stop: Indication of receive process stop. * @reserved2: none * @features: Hardware features to enable. * @overrides: Hardware features to override. * @parent: Pointer to parent, network device private structure.
*/ struct ksz_hw { void __iomem *io;
struct ksz_switch *ksz_switch; struct ksz_port_info port_info[SWITCH_PORT_NUM]; struct ksz_port_mib port_mib[TOTAL_PORT_NUM]; int dev_count; int dst_ports; int id; int mib_cnt; int mib_port_cnt;
/** * struct ksz_port - Virtual port data structure * @duplex: Duplex mode setting. 1 for half duplex, 2 for full * duplex, and 0 for auto, which normally results in full * duplex. * @speed: Speed setting. 10 for 10 Mbit, 100 for 100 Mbit, and * 0 for auto, which normally results in 100 Mbit. * @force_link: Force link setting. 0 for auto-negotiation, and 1 for * force. * @flow_ctrl: Flow control setting. PHY_NO_FLOW_CTRL for no flow * control, and PHY_FLOW_CTRL for flow control. * PHY_TX_ONLY and PHY_RX_ONLY are not supported for 100 * Mbit PHY. * @first_port: Index of first port this port supports. * @mib_port_cnt: Number of ports with MIB counters. * @port_cnt: Number of ports this port supports. * @counter: Port statistics counter. * @hw: Pointer to hardware structure. * @linked: Pointer to port information linked to this port.
*/ struct ksz_port {
u8 duplex;
u8 speed;
u8 force_link;
u8 flow_ctrl;
int first_port; int mib_port_cnt; int port_cnt;
u64 counter[OID_COUNTER_LAST];
/** * struct ksz_timer_info - Timer information data structure * @timer: Kernel timer. * @cnt: Running timer counter. * @max: Number of times to run timer; -1 for infinity. * @period: Timer period in jiffies.
*/ struct ksz_timer_info { struct timer_list timer; int cnt; int max; int period;
};
/** * struct ksz_counter_info - OS dependent counter information data structure * @counter: Wait queue to wakeup after counters are read. * @time: Next time in jiffies to read counter. * @read: Indication of counters read in full or not.
*/ struct ksz_counter_info {
wait_queue_head_t counter; unsignedlong time; int read;
};
/** * struct dev_info - Network device information data structure * @dev: Pointer to network device. * @pdev: Pointer to PCI device. * @hw: Hardware structure. * @desc_pool: Physical memory used for descriptor pool. * @hwlock: Spinlock to prevent hardware from accessing. * @lock: Mutex lock to prevent device from accessing. * @dev_rcv: Receive process function used. * @last_skb: Socket buffer allocated for descriptor rx fragments. * @skb_index: Buffer index for receiving fragments. * @skb_len: Buffer length for receiving fragments. * @mib_read: Workqueue to read MIB counters. * @mib_timer_info: Timer to read MIB counters. * @counter: Used for MIB reading. * @mtu: Current MTU used. The default is REGULAR_RX_BUF_SIZE; * the maximum is MAX_RX_BUF_SIZE. * @opened: Counter to keep track of device open. * @rx_tasklet: Receive processing tasklet. * @tx_tasklet: Transmit processing tasklet. * @wol_enable: Wake-on-LAN enable set by ethtool. * @wol_support: Wake-on-LAN support used by ethtool. * @pme_wait: Used for KSZ8841 power management.
*/ struct dev_info { struct net_device *dev; struct pci_dev *pdev;
int wol_enable; int wol_support; unsignedlong pme_wait;
};
/** * struct dev_priv - Network device private data structure * @adapter: Adapter device information. * @port: Port information. * @monitor_timer_info: Timer to monitor ports. * @proc_sem: Semaphore for proc accessing. * @id: Device ID. * @mii_if: MII interface information. * @advertising: Temporary variable to store advertised settings. * @msg_enable: The message flags controlling driver output. * @media_state: The connection status of the device. * @multicast: The all multicast state of the device. * @promiscuous: The promiscuous state of the device.
*/ struct dev_priv { struct dev_info *adapter; struct ksz_port port; struct ksz_timer_info monitor_timer_info;
struct semaphore proc_sem; int id;
struct mii_if_info mii_if;
u32 advertising;
u32 msg_enable; int media_state; int multicast; int promiscuous;
};
/** * hw_turn_on_intr - turn on specified interrupts * @hw: The hardware instance. * @bit: The interrupt bits to be on. * * This routine turns on the specified interrupts in the interrupt mask so that * those interrupts will be enabled.
*/ staticvoid hw_turn_on_intr(struct ksz_hw *hw, u32 bit)
{
hw->intr_mask |= bit;
if (!hw->intr_blocked)
hw_set_intr(hw, hw->intr_mask);
}
/** * hw_block_intr - block hardware interrupts * @hw: The hardware instance. * * This function blocks all interrupts of the hardware and returns the current * interrupt enable mask so that interrupts can be restored later. * * Return the current interrupt enable mask.
*/ static uint hw_block_intr(struct ksz_hw *hw)
{
uint interrupt = 0;
#define HW_DELAY(hw, reg) \ do { \
readw(hw->io + reg); \
} while (0)
/** * sw_r_table - read 4 bytes of data from switch table * @hw: The hardware instance. * @table: The table selector. * @addr: The address of the table entry. * @data: Buffer to store the read data. * * This routine reads 4 bytes of data from the table of the switch. * Hardware interrupts are disabled to minimize corruption of read data.
*/ staticvoid sw_r_table(struct ksz_hw *hw, int table, u16 addr, u32 *data)
{
u16 ctrl_addr;
uint interrupt;
/** * sw_w_table_64 - write 8 bytes of data to the switch table * @hw: The hardware instance. * @table: The table selector. * @addr: The address of the table entry. * @data_hi: The high part of data to be written (bit63 ~ bit32). * @data_lo: The low part of data to be written (bit31 ~ bit0). * * This routine writes 8 bytes of data to the table of the switch. * Hardware interrupts are disabled to minimize corruption of written data.
*/ staticvoid sw_w_table_64(struct ksz_hw *hw, int table, u16 addr, u32 data_hi,
u32 data_lo)
{
u16 ctrl_addr;
uint interrupt;
/** * sw_w_sta_mac_table - write to the static MAC table * @hw: The hardware instance. * @addr: The address of the table entry. * @mac_addr: The MAC address. * @ports: The port members. * @override: The flag to override the port receive/transmit settings. * @valid: The flag to indicate entry is valid. * @use_fid: The flag to indicate the FID is valid. * @fid: The FID value. * * This routine writes an entry of the static MAC table of the switch. It * calls sw_w_table_64() to write the data.
*/ staticvoid sw_w_sta_mac_table(struct ksz_hw *hw, u16 addr, u8 *mac_addr,
u8 ports, int override, int valid, int use_fid, u8 fid)
{
u32 data_hi;
u32 data_lo;
/** * sw_r_vlan_table - read from the VLAN table * @hw: The hardware instance. * @addr: The address of the table entry. * @vid: Buffer to store the VID. * @fid: Buffer to store the VID. * @member: Buffer to store the port membership. * * This function reads an entry of the VLAN table of the switch. It calls * sw_r_table() to get the data. * * Return 0 if the entry is valid; otherwise -1.
*/ staticint sw_r_vlan_table(struct ksz_hw *hw, u16 addr, u16 *vid, u8 *fid,
u8 *member)
{
u32 data;
/** * port_r_mib_cnt - read MIB counter * @hw: The hardware instance. * @port: The port index. * @addr: The address of the counter. * @cnt: Buffer to store the counter. * * This routine reads a MIB counter of the port. * Hardware interrupts are disabled to minimize corruption of read data.
*/ staticvoid port_r_mib_cnt(struct ksz_hw *hw, int port, u16 addr, u64 *cnt)
{
u32 data;
u16 ctrl_addr;
uint interrupt; int timeout;
for (timeout = 100; timeout > 0; timeout--) {
data = readl(hw->io + KS884X_ACC_DATA_0_OFFSET);
if (data & MIB_COUNTER_VALID) { if (data & MIB_COUNTER_OVERFLOW)
*cnt += MIB_COUNTER_VALUE + 1;
*cnt += data & MIB_COUNTER_VALUE; break;
}
}
hw_restore_intr(hw, interrupt);
}
/** * port_r_mib_pkt - read dropped packet counts * @hw: The hardware instance. * @port: The port index. * @last: last one * @cnt: Buffer to store the receive and transmit dropped packet counts. * * This routine reads the dropped packet counts of the port. * Hardware interrupts are disabled to minimize corruption of read data.
*/ staticvoid port_r_mib_pkt(struct ksz_hw *hw, int port, u32 *last, u64 *cnt)
{
u32 cur;
u32 data;
u16 ctrl_addr;
uint interrupt; int index;
index = KS_MIB_PACKET_DROPPED_RX_0 + port; do {
interrupt = hw_block_intr(hw);
data &= MIB_PACKET_DROPPED;
cur = *last; if (data != cur) {
*last = data; if (data < cur)
data += MIB_PACKET_DROPPED + 1;
data -= cur;
*cnt += data;
}
++last;
++cnt;
index -= KS_MIB_PACKET_DROPPED_TX -
KS_MIB_PACKET_DROPPED_TX_0 + 1;
} while (index >= KS_MIB_PACKET_DROPPED_TX_0 + port);
}
/** * port_r_cnt - read MIB counters periodically * @hw: The hardware instance. * @port: The port index. * * This routine is used to read the counters of the port periodically to avoid * counter overflow. The hardware should be acquired first before calling this * routine. * * Return non-zero when not all counters not read.
*/ staticint port_r_cnt(struct ksz_hw *hw, int port)
{ struct ksz_port_mib *mib = &hw->port_mib[port];
if (mib->mib_start < PORT_COUNTER_NUM) while (mib->cnt_ptr < PORT_COUNTER_NUM) {
port_r_mib_cnt(hw, port, mib->cnt_ptr,
&mib->counter[mib->cnt_ptr]);
++mib->cnt_ptr;
} if (hw->mib_cnt > PORT_COUNTER_NUM)
port_r_mib_pkt(hw, port, mib->dropped,
&mib->counter[PORT_COUNTER_NUM]);
mib->cnt_ptr = 0; return 0;
}
/** * port_init_cnt - initialize MIB counter values * @hw: The hardware instance. * @port: The port index. * * This routine is used to initialize all counters to zero if the hardware * cannot do it after reset.
*/ staticvoid port_init_cnt(struct ksz_hw *hw, int port)
{ struct ksz_port_mib *mib = &hw->port_mib[port];
mib->cnt_ptr = 0; if (mib->mib_start < PORT_COUNTER_NUM) do {
port_r_mib_cnt(hw, port, mib->cnt_ptr,
&mib->counter[mib->cnt_ptr]);
++mib->cnt_ptr;
} while (mib->cnt_ptr < PORT_COUNTER_NUM); if (hw->mib_cnt > PORT_COUNTER_NUM)
port_r_mib_pkt(hw, port, mib->dropped,
&mib->counter[PORT_COUNTER_NUM]);
memset((void *) mib->counter, 0, sizeof(u64) * TOTAL_PORT_COUNTER_NUM);
mib->cnt_ptr = 0;
}
/* * Port functions
*/
/** * port_cfg - set port register bits * @hw: The hardware instance. * @port: The port index. * @offset: The offset of the port register. * @bits: The data bits to set. * @set: The flag indicating whether the bits are to be set or not. * * This routine sets or resets the specified bits of the port register.
*/ staticvoid port_cfg(struct ksz_hw *hw, int port, int offset, u16 bits, int set)
{
u32 addr;
u16 data;
PORT_CTRL_ADDR(port, addr);
addr += offset;
data = readw(hw->io + addr); if (set)
data |= bits; else
data &= ~bits;
writew(data, hw->io + addr);
}
/** * port_r8 - read byte from port register * @hw: The hardware instance. * @port: The port index. * @offset: The offset of the port register. * @data: Buffer to store the data. * * This routine reads a byte from the port register.
*/ staticvoid port_r8(struct ksz_hw *hw, int port, int offset, u8 *data)
{
u32 addr;
/** * port_r16 - read word from port register. * @hw: The hardware instance. * @port: The port index. * @offset: The offset of the port register. * @data: Buffer to store the data. * * This routine reads a word from the port register.
*/ staticvoid port_r16(struct ksz_hw *hw, int port, int offset, u16 *data)
{
u32 addr;
/** * port_w16 - write word to port register. * @hw: The hardware instance. * @port: The port index. * @offset: The offset of the port register. * @data: Data to write. * * This routine writes a word to the port register.
*/ staticvoid port_w16(struct ksz_hw *hw, int port, int offset, u16 data)
{
u32 addr;
/** * sw_chk - check switch register bits * @hw: The hardware instance. * @addr: The address of the switch register. * @bits: The data bits to check. * * This function checks whether the specified bits of the switch register are * set or not. * * Return 0 if the bits are not set.
*/ staticint sw_chk(struct ksz_hw *hw, u32 addr, u16 bits)
{
u16 data;
/** * sw_cfg - set switch register bits * @hw: The hardware instance. * @addr: The address of the switch register. * @bits: The data bits to set. * @set: The flag indicating whether the bits are to be set or not. * * This function sets or resets the specified bits of the switch register.
*/ staticvoid sw_cfg(struct ksz_hw *hw, u32 addr, u16 bits, int set)
{
u16 data;
data = readw(hw->io + addr); if (set)
data |= bits; else
data &= ~bits;
writew(data, hw->io + addr);
}
/* Bandwidth */
staticinlinevoid port_cfg_broad_storm(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_1_OFFSET, PORT_BROADCAST_STORM, set);
}
/* Driver set switch broadcast storm protection at 10% rate. */ #define BROADCAST_STORM_PROTECTION_RATE 10
/** * sw_cfg_broad_storm - configure broadcast storm threshold * @hw: The hardware instance. * @percent: Broadcast storm threshold in percent of transmit rate. * * This routine configures the broadcast storm threshold of the switch.
*/ staticvoid sw_cfg_broad_storm(struct ksz_hw *hw, u8 percent)
{
u16 data;
u32 value = ((u32) BROADCAST_STORM_VALUE * (u32) percent / 100);
if (value > BROADCAST_STORM_RATE)
value = BROADCAST_STORM_RATE;
data = readw(hw->io + KS8842_SWITCH_CTRL_3_OFFSET);
data &= ~(BROADCAST_STORM_RATE_LO | BROADCAST_STORM_RATE_HI);
data |= ((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8);
writew(data, hw->io + KS8842_SWITCH_CTRL_3_OFFSET);
}
/** * sw_get_broad_storm - get broadcast storm threshold * @hw: The hardware instance. * @percent: Buffer to store the broadcast storm threshold percentage. * * This routine retrieves the broadcast storm threshold of the switch.
*/ staticvoid sw_get_broad_storm(struct ksz_hw *hw, u8 *percent)
{ int num;
u16 data;
data = readw(hw->io + KS8842_SWITCH_CTRL_3_OFFSET);
num = (data & BROADCAST_STORM_RATE_HI);
num <<= 8;
num |= (data & BROADCAST_STORM_RATE_LO) >> 8;
num = DIV_ROUND_CLOSEST(num * 100, BROADCAST_STORM_VALUE);
*percent = (u8) num;
}
/** * sw_dis_broad_storm - disable broadstorm * @hw: The hardware instance. * @port: The port index. * * This routine disables the broadcast storm limit function of the switch.
*/ staticvoid sw_dis_broad_storm(struct ksz_hw *hw, int port)
{
port_cfg_broad_storm(hw, port, 0);
}
/** * sw_ena_broad_storm - enable broadcast storm * @hw: The hardware instance. * @port: The port index. * * This routine enables the broadcast storm limit function of the switch.
*/ staticvoid sw_ena_broad_storm(struct ksz_hw *hw, int port)
{
sw_cfg_broad_storm(hw, hw->ksz_switch->broad_per);
port_cfg_broad_storm(hw, port, 1);
}
/** * sw_init_broad_storm - initialize broadcast storm * @hw: The hardware instance. * * This routine initializes the broadcast storm limit function of the switch.
*/ staticvoid sw_init_broad_storm(struct ksz_hw *hw)
{ int port;
hw->ksz_switch->broad_per = 1;
sw_cfg_broad_storm(hw, hw->ksz_switch->broad_per); for (port = 0; port < TOTAL_PORT_NUM; port++)
sw_dis_broad_storm(hw, port);
sw_cfg(hw, KS8842_SWITCH_CTRL_2_OFFSET, MULTICAST_STORM_DISABLE, 1);
}
/** * hw_cfg_broad_storm - configure broadcast storm * @hw: The hardware instance. * @percent: Broadcast storm threshold in percent of transmit rate. * * This routine configures the broadcast storm threshold of the switch. * It is called by user functions. The hardware should be acquired first.
*/ staticvoid hw_cfg_broad_storm(struct ksz_hw *hw, u8 percent)
{ if (percent > 100)
percent = 100;
/** * sw_dis_prio_rate - disable switch priority rate * @hw: The hardware instance. * @port: The port index. * * This routine disables the priority rate function of the switch.
*/ staticvoid sw_dis_prio_rate(struct ksz_hw *hw, int port)
{
u32 addr;
/** * sw_init_prio_rate - initialize switch prioirty rate * @hw: The hardware instance. * * This routine initializes the priority rate function of the switch.
*/ staticvoid sw_init_prio_rate(struct ksz_hw *hw)
{ int port; int prio; struct ksz_switch *sw = hw->ksz_switch;
for (port = 0; port < TOTAL_PORT_NUM; port++) { for (prio = 0; prio < PRIO_QUEUES; prio++) {
sw->port_cfg[port].rx_rate[prio] =
sw->port_cfg[port].tx_rate[prio] = 0;
}
sw_dis_prio_rate(hw, port);
}
}
/* Communication */
staticinlinevoid port_cfg_back_pressure(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_2_OFFSET, PORT_BACK_PRESSURE, set);
}
/* Mirroring */
staticinlinevoid port_cfg_mirror_sniffer(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_2_OFFSET, PORT_MIRROR_SNIFFER, set);
}
staticinlinevoid port_cfg_mirror_rx(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_2_OFFSET, PORT_MIRROR_RX, set);
}
staticinlinevoid port_cfg_mirror_tx(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_2_OFFSET, PORT_MIRROR_TX, set);
}
staticinlinevoid port_cfg_diffserv(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_1_OFFSET, PORT_DIFFSERV_ENABLE, set);
}
staticinlinevoid port_cfg_802_1p(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_1_OFFSET, PORT_802_1P_ENABLE, set);
}
staticinlinevoid port_cfg_replace_vid(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_2_OFFSET, PORT_USER_PRIORITY_CEILING, set);
}
staticinlinevoid port_cfg_prio(struct ksz_hw *hw, int p, int set)
{
port_cfg(hw, p,
KS8842_PORT_CTRL_1_OFFSET, PORT_PRIO_QUEUE_ENABLE, set);
}
/** * sw_dis_diffserv - disable switch DiffServ priority * @hw: The hardware instance. * @port: The port index. * * This routine disables the DiffServ priority function of the switch.
*/ staticvoid sw_dis_diffserv(struct ksz_hw *hw, int port)
{
port_cfg_diffserv(hw, port, 0);
}
/** * sw_dis_802_1p - disable switch 802.1p priority * @hw: The hardware instance. * @port: The port index. * * This routine disables the 802.1p priority function of the switch.
*/ staticvoid sw_dis_802_1p(struct ksz_hw *hw, int port)
{
port_cfg_802_1p(hw, port, 0);
}
/** * sw_cfg_replace_null_vid - * @hw: The hardware instance. * @set: The flag to disable or enable. *
*/ staticvoid sw_cfg_replace_null_vid(struct ksz_hw *hw, int set)
{
sw_cfg(hw, KS8842_SWITCH_CTRL_3_OFFSET, SWITCH_REPLACE_NULL_VID, set);
}
/** * sw_cfg_replace_vid - enable switch 802.10 priority re-mapping * @hw: The hardware instance. * @port: The port index. * @set: The flag to disable or enable. * * This routine enables the 802.1p priority re-mapping function of the switch. * That allows 802.1p priority field to be replaced with the port's default * tag's priority value if the ingress packet's 802.1p priority has a higher * priority than port's default tag's priority.
*/ staticvoid sw_cfg_replace_vid(struct ksz_hw *hw, int port, int set)
{
port_cfg_replace_vid(hw, port, set);
}
/** * sw_cfg_port_based - configure switch port based priority * @hw: The hardware instance. * @port: The port index. * @prio: The priority to set. * * This routine configures the port based priority of the switch.
*/ staticvoid sw_cfg_port_based(struct ksz_hw *hw, int port, u8 prio)
{
u16 data;
if (prio > PORT_BASED_PRIORITY_BASE)
prio = PORT_BASED_PRIORITY_BASE;
hw->ksz_switch->port_cfg[port].port_prio = prio;
port_r16(hw, port, KS8842_PORT_CTRL_1_OFFSET, &data);
data &= ~PORT_BASED_PRIORITY_MASK;
data |= prio << PORT_BASED_PRIORITY_SHIFT;
port_w16(hw, port, KS8842_PORT_CTRL_1_OFFSET, data);
}
/** * sw_dis_multi_queue - disable transmit multiple queues * @hw: The hardware instance. * @port: The port index. * * This routine disables the transmit multiple queues selection of the switch * port. Only single transmit queue on the port.
*/ staticvoid sw_dis_multi_queue(struct ksz_hw *hw, int port)
{
port_cfg_prio(hw, port, 0);
}
/** * sw_init_prio - initialize switch priority * @hw: The hardware instance. * * This routine initializes the switch QoS priority functions.
*/ staticvoid sw_init_prio(struct ksz_hw *hw)
{ int port; int tos; struct ksz_switch *sw = hw->ksz_switch;
/* * Init all the 802.1p tag priority value to be assigned to different * priority queue.
*/
sw->p_802_1p[0] = 0;
sw->p_802_1p[1] = 0;
sw->p_802_1p[2] = 1;
sw->p_802_1p[3] = 1;
sw->p_802_1p[4] = 2;
sw->p_802_1p[5] = 2;
sw->p_802_1p[6] = 3;
sw->p_802_1p[7] = 3;
/* * Init all the DiffServ priority value to be assigned to priority * queue 0.
*/ for (tos = 0; tos < DIFFSERV_ENTRIES; tos++)
sw->diffserv[tos] = 0;
/* All QoS functions disabled. */ for (port = 0; port < TOTAL_PORT_NUM; port++) {
sw_dis_multi_queue(hw, port);
sw_dis_diffserv(hw, port);
sw_dis_802_1p(hw, port);
sw_cfg_replace_vid(hw, port, 0);
/** * port_get_def_vid - get port default VID. * @hw: The hardware instance. * @port: The port index. * @vid: Buffer to store the VID. * * This routine retrieves the default VID of the port.
*/ staticvoid port_get_def_vid(struct ksz_hw *hw, int port, u16 *vid)
{
u32 addr;
/** * sw_init_vlan - initialize switch VLAN * @hw: The hardware instance. * * This routine initializes the VLAN function of the switch.
*/ staticvoid sw_init_vlan(struct ksz_hw *hw)
{ int port; int entry; struct ksz_switch *sw = hw->ksz_switch;
data = readb(hw->io + addr);
data &= ~PORT_VLAN_MEMBERSHIP;
data |= (member & PORT_MASK);
writeb(data, hw->io + addr);
hw->ksz_switch->port_cfg[port].member = member;
}
/** * sw_set_addr - configure switch MAC address * @hw: The hardware instance. * @mac_addr: The MAC address. * * This function configures the MAC address of the switch.
*/ staticvoid sw_set_addr(struct ksz_hw *hw, u8 *mac_addr)
{ int i;
for (i = 0; i < 6; i += 2) {
writeb(mac_addr[i], hw->io + KS8842_MAC_ADDR_0_OFFSET + i);
writeb(mac_addr[1 + i], hw->io + KS8842_MAC_ADDR_1_OFFSET + i);
}
}
/** * sw_set_global_ctrl - set switch global control * @hw: The hardware instance. * * This routine sets the global control of the switch function.
*/ staticvoid sw_set_global_ctrl(struct ksz_hw *hw)
{
u16 data;
/* Enable switch MII flow control. */
data = readw(hw->io + KS8842_SWITCH_CTRL_3_OFFSET);
data |= SWITCH_FLOW_CTRL;
writew(data, hw->io + KS8842_SWITCH_CTRL_3_OFFSET);
data = readw(hw->io + KS8842_SWITCH_CTRL_1_OFFSET);
/* Enable aggressive back off algorithm in half duplex mode. */
data |= SWITCH_AGGR_BACKOFF;
/* Enable automatic fast aging when link changed detected. */
data |= SWITCH_AGING_ENABLE;
data |= SWITCH_LINK_AUTO_AGING;
if (hw->overrides & FAST_AGING)
data |= SWITCH_FAST_AGING; else
data &= ~SWITCH_FAST_AGING;
writew(data, hw->io + KS8842_SWITCH_CTRL_1_OFFSET);
data = readw(hw->io + KS8842_SWITCH_CTRL_2_OFFSET);
/* Enable no excessive collision drop. */
data |= NO_EXC_COLLISION_DROP;
writew(data, hw->io + KS8842_SWITCH_CTRL_2_OFFSET);
}
/** * port_set_stp_state - configure port spanning tree state * @hw: The hardware instance. * @port: The port index. * @state: The spanning tree state. * * This routine configures the spanning tree state of the port.
*/ staticvoid port_set_stp_state(struct ksz_hw *hw, int port, int state)
{
u16 data;
port_r16(hw, port, KS8842_PORT_CTRL_2_OFFSET, &data); switch (state) { case STP_STATE_DISABLED:
data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE);
data |= PORT_LEARN_DISABLE; break; case STP_STATE_LISTENING: /* * No need to turn on transmit because of port direct mode. * Turning on receive is required if static MAC table is not setup.
*/
data &= ~PORT_TX_ENABLE;
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.