aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ucc_geth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r--drivers/net/ucc_geth.c534
1 files changed, 114 insertions, 420 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index c87747bb24c..11441225bf4 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -188,17 +188,6 @@ static void mem_disp(u8 *addr, int size)
}
#endif /* DEBUG */
-#ifdef CONFIG_UGETH_FILTERING
-static void enqueue(struct list_head *node, struct list_head *lh)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ugeth_lock, flags);
- list_add_tail(node, lh);
- spin_unlock_irqrestore(&ugeth_lock, flags);
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static struct list_head *dequeue(struct list_head *lh)
{
unsigned long flags;
@@ -391,23 +380,6 @@ static int dump_init_enet_entries(struct ucc_geth_private *ugeth,
}
#endif
-#ifdef CONFIG_UGETH_FILTERING
-static struct enet_addr_container *get_enet_addr_container(void)
-{
- struct enet_addr_container *enet_addr_cont;
-
- /* allocate memory */
- enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL);
- if (!enet_addr_cont) {
- ugeth_err("%s: No memory for enet_addr_container object.",
- __func__);
- return NULL;
- }
-
- return enet_addr_cont;
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont)
{
kfree(enet_addr_cont);
@@ -420,28 +392,6 @@ static void set_mac_addr(__be16 __iomem *reg, u8 *mac)
out_be16(&reg[2], ((u16)mac[1] << 8) | mac[0]);
}
-#ifdef CONFIG_UGETH_FILTERING
-static int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth,
- u8 *p_enet_addr, u8 paddr_num)
-{
- struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
-
- if (!(paddr_num < NUM_OF_PADDRS)) {
- ugeth_warn("%s: Illegal paddr_num.", __func__);
- return -EINVAL;
- }
-
- p_82xx_addr_filt =
- (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
- addressfiltering;
-
- /* Ethernet frames are defined in Little Endian mode, */
- /* therefore to insert the address we reverse the bytes. */
- set_mac_addr(&p_82xx_addr_filt->paddr[paddr_num].h, p_enet_addr);
- return 0;
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num)
{
struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
@@ -492,40 +442,30 @@ static void magic_packet_detection_enable(struct ucc_geth_private *ugeth)
{
struct ucc_fast_private *uccf;
struct ucc_geth __iomem *ug_regs;
- u32 maccfg2, uccm;
uccf = ugeth->uccf;
ug_regs = ugeth->ug_regs;
/* Enable interrupts for magic packet detection */
- uccm = in_be32(uccf->p_uccm);
- uccm |= UCCE_MPD;
- out_be32(uccf->p_uccm, uccm);
+ setbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
/* Enable magic packet detection */
- maccfg2 = in_be32(&ug_regs->maccfg2);
- maccfg2 |= MACCFG2_MPE;
- out_be32(&ug_regs->maccfg2, maccfg2);
+ setbits32(&ug_regs->maccfg2, MACCFG2_MPE);
}
static void magic_packet_detection_disable(struct ucc_geth_private *ugeth)
{
struct ucc_fast_private *uccf;
struct ucc_geth __iomem *ug_regs;
- u32 maccfg2, uccm;
uccf = ugeth->uccf;
ug_regs = ugeth->ug_regs;
/* Disable interrupts for magic packet detection */
- uccm = in_be32(uccf->p_uccm);
- uccm &= ~UCCE_MPD;
- out_be32(uccf->p_uccm, uccm);
+ clrbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
/* Disable magic packet detection */
- maccfg2 = in_be32(&ug_regs->maccfg2);
- maccfg2 &= ~MACCFG2_MPE;
- out_be32(&ug_regs->maccfg2, maccfg2);
+ clrbits32(&ug_regs->maccfg2, MACCFG2_MPE);
}
#endif /* MAGIC_PACKET */
@@ -635,7 +575,8 @@ static void get_statistics(struct ucc_geth_private *ugeth,
/* Hardware only if user handed pointer and driver actually
gathers hardware statistics */
- if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) {
+ if (hardware_statistics &&
+ (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) {
hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
@@ -1231,9 +1172,7 @@ int init_flow_control_params(u32 automatic_flow_control_mode,
out_be32(uempr_register, value);
/* Set UPSMR register */
- value = in_be32(upsmr_register);
- value |= automatic_flow_control_mode;
- out_be32(upsmr_register, value);
+ setbits32(upsmr_register, automatic_flow_control_mode);
value = in_be32(maccfg1_register);
if (rx_flow_control_enable)
@@ -1250,14 +1189,11 @@ static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
u32 __iomem *upsmr_register,
u16 __iomem *uescr_register)
{
- u32 upsmr_value = 0;
u16 uescr_value = 0;
+
/* Enable hardware statistics gathering if requested */
- if (enable_hardware_statistics) {
- upsmr_value = in_be32(upsmr_register);
- upsmr_value |= UPSMR_HSE;
- out_be32(upsmr_register, upsmr_value);
- }
+ if (enable_hardware_statistics)
+ setbits32(upsmr_register, UCC_GETH_UPSMR_HSE);
/* Clear hardware statistics counters */
uescr_value = in_be16(uescr_register);
@@ -1283,23 +1219,17 @@ static int init_firmware_statistics_gathering_mode(int
{
/* Note: this function does not check if */
/* the parameters it receives are NULL */
- u16 temoder_value;
- u32 remoder_value;
if (enable_tx_firmware_statistics) {
out_be32(tx_rmon_base_ptr,
tx_firmware_statistics_structure_address);
- temoder_value = in_be16(temoder_register);
- temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE;
- out_be16(temoder_register, temoder_value);
+ setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE);
}
if (enable_rx_firmware_statistics) {
out_be32(rx_rmon_base_ptr,
rx_firmware_statistics_structure_address);
- remoder_value = in_be32(remoder_register);
- remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE;
- out_be32(remoder_register, remoder_value);
+ setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE);
}
return 0;
@@ -1366,15 +1296,12 @@ static int init_check_frame_length_mode(int length_check,
static int init_preamble_length(u8 preamble_length,
u32 __iomem *maccfg2_register)
{
- u32 value = 0;
-
if ((preamble_length < 3) || (preamble_length > 7))
return -EINVAL;
- value = in_be32(maccfg2_register);
- value &= ~MACCFG2_PREL_MASK;
- value |= (preamble_length << MACCFG2_PREL_SHIFT);
- out_be32(maccfg2_register, value);
+ clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK,
+ preamble_length << MACCFG2_PREL_SHIFT);
+
return 0;
}
@@ -1387,19 +1314,19 @@ static int init_rx_parameters(int reject_broadcast,
value = in_be32(upsmr_register);
if (reject_broadcast)
- value |= UPSMR_BRO;
+ value |= UCC_GETH_UPSMR_BRO;
else
- value &= ~UPSMR_BRO;
+ value &= ~UCC_GETH_UPSMR_BRO;
if (receive_short_frames)
- value |= UPSMR_RSH;
+ value |= UCC_GETH_UPSMR_RSH;
else
- value &= ~UPSMR_RSH;
+ value &= ~UCC_GETH_UPSMR_RSH;
if (promiscuous)
- value |= UPSMR_PRO;
+ value |= UCC_GETH_UPSMR_PRO;
else
- value &= ~UPSMR_PRO;
+ value &= ~UCC_GETH_UPSMR_PRO;
out_be32(upsmr_register, value);
@@ -1460,26 +1387,27 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
/* Set UPSMR */
upsmr = in_be32(&uf_regs->upsmr);
- upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM);
+ upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
+ UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- upsmr |= UPSMR_RPM;
+ upsmr |= UCC_GETH_UPSMR_RPM;
switch (ugeth->max_speed) {
case SPEED_10:
- upsmr |= UPSMR_R10M;
+ upsmr |= UCC_GETH_UPSMR_R10M;
/* FALLTHROUGH */
case SPEED_100:
if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI)
- upsmr |= UPSMR_RMM;
+ upsmr |= UCC_GETH_UPSMR_RMM;
}
}
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- upsmr |= UPSMR_TBIM;
+ upsmr |= UCC_GETH_UPSMR_TBIM;
}
out_be32(&uf_regs->upsmr, upsmr);
@@ -1567,9 +1495,9 @@ static void adjust_link(struct net_device *dev)
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
if (phydev->speed == SPEED_10)
- upsmr |= UPSMR_R10M;
+ upsmr |= UCC_GETH_UPSMR_R10M;
else
- upsmr &= ~(UPSMR_R10M);
+ upsmr &= ~UCC_GETH_UPSMR_R10M;
}
break;
default:
@@ -1615,8 +1543,8 @@ static int init_phy(struct net_device *dev)
priv->oldspeed = 0;
priv->oldduplex = -1;
- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus,
- priv->ug_info->phy_address);
+ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->ug_info->mdio_bus,
+ priv->ug_info->phy_address);
phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface);
@@ -1647,14 +1575,13 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
struct ucc_fast_private *uccf;
u32 cecr_subblock;
u32 temp;
+ int i = 10;
uccf = ugeth->uccf;
/* Mask GRACEFUL STOP TX interrupt bit and clear it */
- temp = in_be32(uccf->p_uccm);
- temp &= ~UCCE_GRA;
- out_be32(uccf->p_uccm, temp);
- out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */
+ clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA);
+ out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */
/* Issue host command */
cecr_subblock =
@@ -1664,8 +1591,9 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
/* Wait for command to complete */
do {
+ msleep(10);
temp = in_be32(uccf->p_ucce);
- } while (!(temp & UCCE_GRA));
+ } while (!(temp & UCC_GETH_UCCE_GRA) && --i);
uccf->stopped_tx = 1;
@@ -1677,6 +1605,7 @@ static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth)
struct ucc_fast_private *uccf;
u32 cecr_subblock;
u8 temp;
+ int i = 10;
uccf = ugeth->uccf;
@@ -1694,9 +1623,9 @@ static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth)
ucc_num);
qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
QE_CR_PROTOCOL_ETHERNET, 0);
-
+ msleep(10);
temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
- } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
+ } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i);
uccf->stopped_rx = 1;
@@ -1799,196 +1728,6 @@ static void ugeth_dump_regs(struct ucc_geth_private *ugeth)
#endif
}
-#ifdef CONFIG_UGETH_FILTERING
-static int ugeth_ext_filtering_serialize_tad(struct ucc_geth_tad_params *
- p_UccGethTadParams,
- struct qe_fltr_tad *qe_fltr_tad)
-{
- u16 temp;
-
- /* Zero serialized TAD */
- memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE);
-
- qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V; /* Must have this */
- if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode ||
- (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
- || (p_UccGethTadParams->vnontag_op !=
- UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP)
- )
- qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF;
- if (p_UccGethTadParams->reject_frame)
- qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ;
- temp =
- (u16) (((u16) p_UccGethTadParams->
- vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT);
- qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */
-
- qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff); /* lower bits */
- if (p_UccGethTadParams->vnontag_op ==
- UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT)
- qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP;
- qe_fltr_tad->serialized[1] |=
- p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT;
-
- qe_fltr_tad->serialized[2] |=
- p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT;
- /* upper bits */
- qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8);
- /* lower bits */
- qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff);
-
- return 0;
-}
-
-static struct enet_addr_container_t
- *ugeth_82xx_filtering_get_match_addr_in_hash(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr)
-{
- struct enet_addr_container *enet_addr_cont;
- struct list_head *p_lh;
- u16 i, num;
- int32_t j;
- u8 *p_counter;
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
- p_lh = &ugeth->group_hash_q;
- p_counter = &(ugeth->numGroupAddrInHash);
- } else {
- p_lh = &ugeth->ind_hash_q;
- p_counter = &(ugeth->numIndAddrInHash);
- }
-
- if (!p_lh)
- return NULL;
-
- num = *p_counter;
-
- for (i = 0; i < num; i++) {
- enet_addr_cont =
- (struct enet_addr_container *)
- ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
- for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {
- if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])
- break;
- if (j == 0)
- return enet_addr_cont; /* Found */
- }
- enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
- }
- return NULL;
-}
-
-static int ugeth_82xx_filtering_add_addr_in_hash(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr)
-{
- enum ucc_geth_enet_address_recognition_location location;
- struct enet_addr_container *enet_addr_cont;
- struct list_head *p_lh;
- u8 i;
- u32 limit;
- u8 *p_counter;
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
- p_lh = &ugeth->group_hash_q;
- limit = ugeth->ug_info->maxGroupAddrInHash;
- location =
- UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH;
- p_counter = &(ugeth->numGroupAddrInHash);
- } else {
- p_lh = &ugeth->ind_hash_q;
- limit = ugeth->ug_info->maxIndAddrInHash;
- location =
- UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH;
- p_counter = &(ugeth->numIndAddrInHash);
- }
-
- if ((enet_addr_cont =
- ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) {
- list_add(p_lh, &enet_addr_cont->node); /* Put it back */
- return 0;
- }
- if ((!p_lh) || (!(*p_counter < limit)))
- return -EBUSY;
- if (!(enet_addr_cont = get_enet_addr_container()))
- return -ENOMEM;
- for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
- (enet_addr_cont->address)[i] = (*p_enet_addr)[i];
- enet_addr_cont->location = location;
- enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
- ++(*p_counter);
-
- hw_add_addr_in_hash(ugeth, enet_addr_cont->address);
- return 0;
-}
-
-static int ugeth_82xx_filtering_clear_addr_in_hash(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr)
-{
- struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
- struct enet_addr_container *enet_addr_cont;
- struct ucc_fast_private *uccf;
- enum comm_dir comm_dir;
- u16 i, num;
- struct list_head *p_lh;
- u32 *addr_h, *addr_l;
- u8 *p_counter;
-
- uccf = ugeth->uccf;
-
- p_82xx_addr_filt =
- (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
- addressfiltering;
-
- if (!
- (enet_addr_cont =
- ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr)))
- return -ENOENT;
-
- /* It's been found and removed from the CQ. */
- /* Now destroy its container */
- put_enet_addr_container(enet_addr_cont);
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
- addr_h = &(p_82xx_addr_filt->gaddr_h);
- addr_l = &(p_82xx_addr_filt->gaddr_l);
- p_lh = &ugeth->group_hash_q;
- p_counter = &(ugeth->numGroupAddrInHash);
- } else {
- addr_h = &(p_82xx_addr_filt->iaddr_h);
- addr_l = &(p_82xx_addr_filt->iaddr_l);
- p_lh = &ugeth->ind_hash_q;
- p_counter = &(ugeth->numIndAddrInHash);
- }
-
- comm_dir = 0;
- if (uccf->enabled_tx)
- comm_dir |= COMM_DIR_TX;
- if (uccf->enabled_rx)
- comm_dir |= COMM_DIR_RX;
- if (comm_dir)
- ugeth_disable(ugeth, comm_dir);
-
- /* Clear the hash table. */
- out_be32(addr_h, 0x00000000);
- out_be32(addr_l, 0x00000000);
-
- /* Add all remaining CQ elements back into hash */
- num = --(*p_counter);
- for (i = 0; i < num; i++) {
- enet_addr_cont =
- (struct enet_addr_container *)
- ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
- hw_add_addr_in_hash(ugeth, enet_addr_cont->address);
- enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
- }
-
- if (comm_dir)
- ugeth_enable(ugeth, comm_dir);
-
- return 0;
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *
ugeth,
enum enet_addr_type
@@ -2051,28 +1790,6 @@ static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *
return 0;
}
-#ifdef CONFIG_UGETH_FILTERING
-static int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr,
- u8 paddr_num)
-{
- int i;
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR)
- ugeth_warn
- ("%s: multicast address added to paddr will have no "
- "effect - is this what you wanted?",
- __func__);
-
- ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */
- /* store address in our database */
- for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
- ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i];
- /* put in hardware */
- return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num);
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth,
u8 paddr_num)
{
@@ -2215,7 +1932,10 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
while (!list_empty(&ugeth->ind_hash_q))
put_enet_addr_container(ENET_ADDR_CONT_ENTRY
(dequeue(&ugeth->ind_hash_q)));
-
+ if (ugeth->ug_regs) {
+ iounmap(ugeth->ug_regs);
+ ugeth->ug_regs = NULL;
+ }
}
static void ucc_geth_set_multi(struct net_device *dev)
@@ -2231,12 +1951,9 @@ static void ucc_geth_set_multi(struct net_device *dev)
uf_regs = ugeth->uccf->uf_regs;
if (dev->flags & IFF_PROMISC) {
-
- out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr) | UPSMR_PRO);
-
+ setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
} else {
-
- out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr)&~UPSMR_PRO);
+ clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
p_82xx_addr_filt =
(struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->
@@ -2276,7 +1993,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
{
struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
struct phy_device *phydev = ugeth->phydev;
- u32 tempval;
ugeth_vdbg("%s: IN", __func__);
@@ -2293,11 +2009,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
out_be32(ugeth->uccf->p_ucce, 0xffffffff);
/* Disable Rx and Tx */
- tempval = in_be32(&ug_regs->maccfg1);
- tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
- out_be32(&ug_regs->maccfg1, tempval);
-
- free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
+ clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
ucc_geth_memclean(ugeth);
}
@@ -2411,19 +2123,23 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
/* Generate uccm_mask for receive */
uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
for (i = 0; i < ug_info->numQueuesRx; i++)
- uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i);
+ uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i);
for (i = 0; i < ug_info->numQueuesTx; i++)
- uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
+ uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i);
/* Initialize the general fast UCC block. */
if (ucc_fast_init(uf_info, &ugeth->uccf)) {
if (netif_msg_probe(ugeth))
ugeth_err("%s: Failed to init uccf.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
- ugeth->ug_regs = (struct ucc_geth __iomem *) ioremap(uf_info->regs, sizeof(struct ucc_geth));
+ ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs));
+ if (!ugeth->ug_regs) {
+ if (netif_msg_probe(ugeth))
+ ugeth_err("%s: Failed to ioremap regs.", __func__);
+ return -ENOMEM;
+ }
return 0;
}
@@ -2439,7 +2155,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
struct ucc_geth __iomem *ug_regs;
int ret_val = -EINVAL;
u32 remoder = UCC_GETH_REMODER_INIT;
- u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
+ u32 init_enet_pram_offset, cecr_subblock, command;
u32 ifstat, i, j, size, l2qt, l3qt, length;
u16 temoder = UCC_GETH_TEMODER_INIT;
u16 test;
@@ -2475,7 +2191,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Bad number of Rx threads value.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
break;
}
@@ -2500,7 +2215,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Bad number of Tx threads value.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
break;
}
@@ -2537,10 +2251,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
&uf_regs->upsmr,
&ug_regs->uempr, &ug_regs->maccfg1);
- maccfg1 = in_be32(&ug_regs->maccfg1);
- maccfg1 |= MACCFG1_ENABLE_RX;
- maccfg1 |= MACCFG1_ENABLE_TX;
- out_be32(&ug_regs->maccfg1, maccfg1);
+ setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
/* Set IPGIFG */
/* For more details see the hardware spec. */
@@ -2554,7 +2265,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: IPGIFG initialization parameter too large.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -2572,7 +2282,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Half Duplex initialization parameter too large.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -2627,7 +2336,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate memory for Tx bd rings.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
/* Zero unused end of bd ring, according to spec */
@@ -2663,7 +2371,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate memory for Rx bd rings.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
}
@@ -2679,7 +2386,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Could not allocate tx_skbuff",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2711,7 +2417,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Could not allocate rx_skbuff",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2745,7 +2450,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_tx_glbl_pram =
@@ -2768,7 +2472,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2798,7 +2501,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2842,7 +2544,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_scheduler.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2893,7 +2594,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
("%s: Can not allocate DPRAM memory for"
" p_tx_fw_statistics_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_tx_fw_statistics_pram =
@@ -2933,7 +2633,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_rx_glbl_pram =
@@ -2955,7 +2654,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2979,7 +2677,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for"
" p_rx_fw_statistics_pram.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_rx_fw_statistics_pram =
@@ -3002,7 +2699,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for"
" p_rx_irq_coalescing_tbl.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3071,7 +2767,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3148,7 +2843,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Null Extended Filtering Chain Pointer.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
}
@@ -3162,7 +2856,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for"
" p_exf_glbl_param.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3210,7 +2903,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate memory for"
" p_UccInitEnetParamShadows.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
/* Zero out *p_init_enet_param_shadow */
@@ -3245,7 +2937,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Invalid largest External Lookup Key Size.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
}
ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
@@ -3272,7 +2963,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -3288,7 +2978,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -3298,7 +2987,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill Rx bds with buffers.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
}
@@ -3310,7 +2998,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
p_init_enet_pram =
@@ -3352,28 +3039,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
return 0;
}
-/* ucc_geth_timeout gets called when a packet has not been
- * transmitted after a set amount of time.
- * For now, assume that clearing out all the structures, and
- * starting over will fix the problem. */
-static void ucc_geth_timeout(struct net_device *dev)
-{
- struct ucc_geth_private *ugeth = netdev_priv(dev);
-
- ugeth_vdbg("%s: IN", __func__);
-
- dev->stats.tx_errors++;
-
- ugeth_dump_regs(ugeth);
-
- if (dev->flags & IFF_UP) {
- ucc_geth_stop(ugeth);
- ucc_geth_startup(ugeth);
- }
-
- netif_tx_schedule_all(dev);
-}
-
/* This is called by the kernel when a frame is ready for transmission. */
/* It is pointed to by the dev->hard_start_xmit function pointer */
static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -3502,8 +3167,6 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
netif_receive_skb(skb);
}
- ugeth->dev->last_rx = jiffies;
-
skb = get_new_skb(ugeth, bd);
if (!skb) {
if (netif_msg_rx_err(ugeth))
@@ -3578,7 +3241,6 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
static int ucc_geth_poll(struct napi_struct *napi, int budget)
{
struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi);
- struct net_device *dev = ugeth->dev;
struct ucc_geth_info *ug_info;
int howmany, i;
@@ -3589,14 +3251,8 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget)
howmany += ucc_geth_rx(ugeth, i, budget - howmany);
if (howmany < budget) {
- struct ucc_fast_private *uccf;
- u32 uccm;
-
- netif_rx_complete(dev, napi);
- uccf = ugeth->uccf;
- uccm = in_be32(uccf->p_uccm);
- uccm |= UCCE_RX_EVENTS;
- out_be32(uccf->p_uccm, uccm);
+ netif_rx_complete(napi);
+ setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS);
}
return howmany;
@@ -3626,17 +3282,17 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
/* check for receive events that require processing */
if (ucce & UCCE_RX_EVENTS) {
- if (netif_rx_schedule_prep(dev, &ugeth->napi)) {
+ if (netif_rx_schedule_prep(&ugeth->napi)) {
uccm &= ~UCCE_RX_EVENTS;
out_be32(uccf->p_uccm, uccm);
- __netif_rx_schedule(dev, &ugeth->napi);
+ __netif_rx_schedule(&ugeth->napi);
}
}
/* Tx event processing */
if (ucce & UCCE_TX_EVENTS) {
spin_lock(&ugeth->lock);
- tx_mask = UCCE_TXBF_SINGLE_MASK;
+ tx_mask = UCC_GETH_UCCE_TXB0;
for (i = 0; i < ug_info->numQueuesTx; i++) {
if (ucce & tx_mask)
ucc_geth_tx(dev, i);
@@ -3648,12 +3304,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
/* Errors and other events */
if (ucce & UCCE_OTHER) {
- if (ucce & UCCE_BSY) {
+ if (ucce & UCC_GETH_UCCE_BSY)
dev->stats.rx_errors++;
- }
- if (ucce & UCCE_TXE) {
+ if (ucce & UCC_GETH_UCCE_TXE)
dev->stats.tx_errors++;
- }
}
return IRQ_HANDLED;
@@ -3697,7 +3351,7 @@ static int ucc_geth_open(struct net_device *dev)
if (err) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name);
- return err;
+ goto out_err_stop;
}
napi_enable(&ugeth->napi);
@@ -3738,22 +3392,19 @@ static int ucc_geth_open(struct net_device *dev)
phy_start(ugeth->phydev);
- err =
- request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0,
- "UCC Geth", dev);
+ err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
if (err) {
if (netif_msg_ifup(ugeth))
- ugeth_err("%s: Cannot get IRQ for net device, aborting.",
- dev->name);
- ucc_geth_stop(ugeth);
+ ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
goto out_err;
}
- err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+ err = request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler,
+ 0, "UCC Geth", dev);
if (err) {
if (netif_msg_ifup(ugeth))
- ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
- ucc_geth_stop(ugeth);
+ ugeth_err("%s: Cannot get IRQ for net device, aborting.",
+ dev->name);
goto out_err;
}
@@ -3763,7 +3414,8 @@ static int ucc_geth_open(struct net_device *dev)
out_err:
napi_disable(&ugeth->napi);
-
+out_err_stop:
+ ucc_geth_stop(ugeth);
return err;
}
@@ -3778,6 +3430,8 @@ static int ucc_geth_close(struct net_device *dev)
ucc_geth_stop(ugeth);
+ free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
+
phy_disconnect(ugeth->phydev);
ugeth->phydev = NULL;
@@ -3786,6 +3440,45 @@ static int ucc_geth_close(struct net_device *dev)
return 0;
}
+/* Reopen device. This will reset the MAC and PHY. */
+static void ucc_geth_timeout_work(struct work_struct *work)
+{
+ struct ucc_geth_private *ugeth;
+ struct net_device *dev;
+
+ ugeth = container_of(work, struct ucc_geth_private, timeout_work);
+ dev = ugeth->dev;
+
+ ugeth_vdbg("%s: IN", __func__);
+
+ dev->stats.tx_errors++;
+
+ ugeth_dump_regs(ugeth);
+
+ if (dev->flags & IFF_UP) {
+ /*
+ * Must reset MAC *and* PHY. This is done by reopening
+ * the device.
+ */
+ ucc_geth_close(dev);
+ ucc_geth_open(dev);
+ }
+
+ netif_tx_schedule_all(dev);
+}
+
+/*
+ * ucc_geth_timeout gets called when a packet has not been
+ * transmitted after a set amount of time.
+ */
+static void ucc_geth_timeout(struct net_device *dev)
+{
+ struct ucc_geth_private *ugeth = netdev_priv(dev);
+
+ netif_carrier_off(dev);
+ schedule_work(&ugeth->timeout_work);
+}
+
static phy_interface_t to_phy_interface(const char *phy_connection_type)
{
if (strcasecmp(phy_connection_type, "mii") == 0)
@@ -4026,6 +3719,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
dev->hard_start_xmit = ucc_geth_start_xmit;
dev->tx_timeout = ucc_geth_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+ INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work);
netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT);
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ucc_netpoll;