diff options
Diffstat (limited to 'drivers/net/ll_temac_main.c')
-rw-r--r-- | drivers/net/ll_temac_main.c | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 6474c4973d3a..b5c6279cc5a3 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c | |||
@@ -193,6 +193,35 @@ static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, | |||
193 | #endif | 193 | #endif |
194 | 194 | ||
195 | /** | 195 | /** |
196 | * * temac_dma_bd_release - Release buffer descriptor rings | ||
197 | */ | ||
198 | static void temac_dma_bd_release(struct net_device *ndev) | ||
199 | { | ||
200 | struct temac_local *lp = netdev_priv(ndev); | ||
201 | int i; | ||
202 | |||
203 | for (i = 0; i < RX_BD_NUM; i++) { | ||
204 | if (!lp->rx_skb[i]) | ||
205 | break; | ||
206 | else { | ||
207 | dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys, | ||
208 | XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE); | ||
209 | dev_kfree_skb(lp->rx_skb[i]); | ||
210 | } | ||
211 | } | ||
212 | if (lp->rx_bd_v) | ||
213 | dma_free_coherent(ndev->dev.parent, | ||
214 | sizeof(*lp->rx_bd_v) * RX_BD_NUM, | ||
215 | lp->rx_bd_v, lp->rx_bd_p); | ||
216 | if (lp->tx_bd_v) | ||
217 | dma_free_coherent(ndev->dev.parent, | ||
218 | sizeof(*lp->tx_bd_v) * TX_BD_NUM, | ||
219 | lp->tx_bd_v, lp->tx_bd_p); | ||
220 | if (lp->rx_skb) | ||
221 | kfree(lp->rx_skb); | ||
222 | } | ||
223 | |||
224 | /** | ||
196 | * temac_dma_bd_init - Setup buffer descriptor rings | 225 | * temac_dma_bd_init - Setup buffer descriptor rings |
197 | */ | 226 | */ |
198 | static int temac_dma_bd_init(struct net_device *ndev) | 227 | static int temac_dma_bd_init(struct net_device *ndev) |
@@ -202,14 +231,29 @@ static int temac_dma_bd_init(struct net_device *ndev) | |||
202 | int i; | 231 | int i; |
203 | 232 | ||
204 | lp->rx_skb = kzalloc(sizeof(*lp->rx_skb) * RX_BD_NUM, GFP_KERNEL); | 233 | lp->rx_skb = kzalloc(sizeof(*lp->rx_skb) * RX_BD_NUM, GFP_KERNEL); |
234 | if (!lp->rx_skb) { | ||
235 | dev_err(&ndev->dev, | ||
236 | "can't allocate memory for DMA RX buffer\n"); | ||
237 | goto out; | ||
238 | } | ||
205 | /* allocate the tx and rx ring buffer descriptors. */ | 239 | /* allocate the tx and rx ring buffer descriptors. */ |
206 | /* returns a virtual addres and a physical address. */ | 240 | /* returns a virtual addres and a physical address. */ |
207 | lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, | 241 | lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, |
208 | sizeof(*lp->tx_bd_v) * TX_BD_NUM, | 242 | sizeof(*lp->tx_bd_v) * TX_BD_NUM, |
209 | &lp->tx_bd_p, GFP_KERNEL); | 243 | &lp->tx_bd_p, GFP_KERNEL); |
244 | if (!lp->tx_bd_v) { | ||
245 | dev_err(&ndev->dev, | ||
246 | "unable to allocate DMA TX buffer descriptors"); | ||
247 | goto out; | ||
248 | } | ||
210 | lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, | 249 | lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, |
211 | sizeof(*lp->rx_bd_v) * RX_BD_NUM, | 250 | sizeof(*lp->rx_bd_v) * RX_BD_NUM, |
212 | &lp->rx_bd_p, GFP_KERNEL); | 251 | &lp->rx_bd_p, GFP_KERNEL); |
252 | if (!lp->rx_bd_v) { | ||
253 | dev_err(&ndev->dev, | ||
254 | "unable to allocate DMA RX buffer descriptors"); | ||
255 | goto out; | ||
256 | } | ||
213 | 257 | ||
214 | memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM); | 258 | memset(lp->tx_bd_v, 0, sizeof(*lp->tx_bd_v) * TX_BD_NUM); |
215 | for (i = 0; i < TX_BD_NUM; i++) { | 259 | for (i = 0; i < TX_BD_NUM; i++) { |
@@ -227,7 +271,7 @@ static int temac_dma_bd_init(struct net_device *ndev) | |||
227 | 271 | ||
228 | if (skb == 0) { | 272 | if (skb == 0) { |
229 | dev_err(&ndev->dev, "alloc_skb error %d\n", i); | 273 | dev_err(&ndev->dev, "alloc_skb error %d\n", i); |
230 | return -1; | 274 | goto out; |
231 | } | 275 | } |
232 | lp->rx_skb[i] = skb; | 276 | lp->rx_skb[i] = skb; |
233 | /* returns physical address of skb->data */ | 277 | /* returns physical address of skb->data */ |
@@ -258,6 +302,10 @@ static int temac_dma_bd_init(struct net_device *ndev) | |||
258 | lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p); | 302 | lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p); |
259 | 303 | ||
260 | return 0; | 304 | return 0; |
305 | |||
306 | out: | ||
307 | temac_dma_bd_release(ndev); | ||
308 | return -ENOMEM; | ||
261 | } | 309 | } |
262 | 310 | ||
263 | /* --------------------------------------------------------------------- | 311 | /* --------------------------------------------------------------------- |
@@ -505,7 +553,10 @@ static void temac_device_reset(struct net_device *ndev) | |||
505 | } | 553 | } |
506 | lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); | 554 | lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE); |
507 | 555 | ||
508 | temac_dma_bd_init(ndev); | 556 | if (temac_dma_bd_init(ndev)) { |
557 | dev_err(&ndev->dev, | ||
558 | "temac_device_reset descriptor allocation failed\n"); | ||
559 | } | ||
509 | 560 | ||
510 | temac_indirect_out32(lp, XTE_RXC0_OFFSET, 0); | 561 | temac_indirect_out32(lp, XTE_RXC0_OFFSET, 0); |
511 | temac_indirect_out32(lp, XTE_RXC1_OFFSET, 0); | 562 | temac_indirect_out32(lp, XTE_RXC1_OFFSET, 0); |
@@ -837,6 +888,8 @@ static int temac_stop(struct net_device *ndev) | |||
837 | phy_disconnect(lp->phy_dev); | 888 | phy_disconnect(lp->phy_dev); |
838 | lp->phy_dev = NULL; | 889 | lp->phy_dev = NULL; |
839 | 890 | ||
891 | temac_dma_bd_release(ndev); | ||
892 | |||
840 | return 0; | 893 | return 0; |
841 | } | 894 | } |
842 | 895 | ||
@@ -862,6 +915,7 @@ static const struct net_device_ops temac_netdev_ops = { | |||
862 | .ndo_stop = temac_stop, | 915 | .ndo_stop = temac_stop, |
863 | .ndo_start_xmit = temac_start_xmit, | 916 | .ndo_start_xmit = temac_start_xmit, |
864 | .ndo_set_mac_address = netdev_set_mac_address, | 917 | .ndo_set_mac_address = netdev_set_mac_address, |
918 | .ndo_validate_addr = eth_validate_addr, | ||
865 | //.ndo_set_multicast_list = temac_set_multicast_list, | 919 | //.ndo_set_multicast_list = temac_set_multicast_list, |
866 | #ifdef CONFIG_NET_POLL_CONTROLLER | 920 | #ifdef CONFIG_NET_POLL_CONTROLLER |
867 | .ndo_poll_controller = temac_poll_controller, | 921 | .ndo_poll_controller = temac_poll_controller, |
@@ -978,19 +1032,22 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) | |||
978 | dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs); | 1032 | dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs); |
979 | } else { | 1033 | } else { |
980 | dev_err(&op->dev, "unable to map DMA registers\n"); | 1034 | dev_err(&op->dev, "unable to map DMA registers\n"); |
1035 | of_node_put(np); | ||
981 | goto err_iounmap; | 1036 | goto err_iounmap; |
982 | } | 1037 | } |
983 | } | 1038 | } |
984 | 1039 | ||
985 | lp->rx_irq = irq_of_parse_and_map(np, 0); | 1040 | lp->rx_irq = irq_of_parse_and_map(np, 0); |
986 | lp->tx_irq = irq_of_parse_and_map(np, 1); | 1041 | lp->tx_irq = irq_of_parse_and_map(np, 1); |
1042 | |||
1043 | of_node_put(np); /* Finished with the DMA node; drop the reference */ | ||
1044 | |||
987 | if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { | 1045 | if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { |
988 | dev_err(&op->dev, "could not determine irqs\n"); | 1046 | dev_err(&op->dev, "could not determine irqs\n"); |
989 | rc = -ENOMEM; | 1047 | rc = -ENOMEM; |
990 | goto err_iounmap_2; | 1048 | goto err_iounmap_2; |
991 | } | 1049 | } |
992 | 1050 | ||
993 | of_node_put(np); /* Finished with the DMA node; drop the reference */ | ||
994 | 1051 | ||
995 | /* Retrieve the MAC address */ | 1052 | /* Retrieve the MAC address */ |
996 | addr = of_get_property(op->dev.of_node, "local-mac-address", &size); | 1053 | addr = of_get_property(op->dev.of_node, "local-mac-address", &size); |