diff options
Diffstat (limited to 'drivers/net/ethernet/toshiba/ps3_gelic_net.c')
| -rw-r--r-- | drivers/net/ethernet/toshiba/ps3_gelic_net.c | 433 |
1 files changed, 229 insertions, 204 deletions
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c index ad32af67e618..d35d1f3c10a1 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * PS3 gelic network driver. * @@ -10,20 +11,6 @@ * * Authors : Utz Bacher <utz.bacher@de.ibm.com> * Jens Osterkamp <Jens.Osterkamp@de.ibm.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #undef DEBUG @@ -102,6 +89,19 @@ static void gelic_card_get_ether_port_status(struct gelic_card *card, } } +/** + * gelic_descr_get_status -- returns the status of a descriptor + * @descr: descriptor to look at + * + * returns the status as in the hw_regs.dmac_cmd_status field of the descriptor + */ +static enum gelic_descr_dma_status +gelic_descr_get_status(struct gelic_descr *descr) +{ + return be32_to_cpu(descr->hw_regs.dmac_cmd_status) & + GELIC_DESCR_DMA_STAT_MASK; +} + static int gelic_card_set_link_mode(struct gelic_card *card, int mode) { int status; @@ -153,15 +153,15 @@ static void gelic_card_enable_rxdmac(struct gelic_card *card) if (gelic_descr_get_status(card->rx_chain.head) != GELIC_DESCR_DMA_CARDOWNED) { printk(KERN_ERR "%s: status=%x\n", __func__, - be32_to_cpu(card->rx_chain.head->dmac_cmd_status)); + be32_to_cpu(card->rx_chain.head->hw_regs.dmac_cmd_status)); printk(KERN_ERR "%s: nextphy=%x\n", __func__, - be32_to_cpu(card->rx_chain.head->next_descr_addr)); + be32_to_cpu(card->rx_chain.head->hw_regs.next_descr_addr)); printk(KERN_ERR "%s: head=%p\n", __func__, card->rx_chain.head); } #endif status = lv1_net_start_rx_dma(bus_id(card), dev_id(card), - card->rx_chain.head->bus_addr, 0); + card->rx_chain.head->link.cpu_addr, 0); if (status) dev_info(ctodev(card), "lv1_net_start_rx_dma failed, status=%d\n", status); @@ -196,8 +196,8 @@ static void gelic_card_disable_rxdmac(struct gelic_card *card) static void gelic_descr_set_status(struct gelic_descr *descr, enum gelic_descr_dma_status status) { - descr->dmac_cmd_status = cpu_to_be32(status | - (be32_to_cpu(descr->dmac_cmd_status) & + descr->hw_regs.dmac_cmd_status = cpu_to_be32(status | + (be32_to_cpu(descr->hw_regs.dmac_cmd_status) & ~GELIC_DESCR_DMA_STAT_MASK)); /* * dma_cmd_status field is used to indicate whether the descriptor @@ -225,13 +225,14 @@ static void gelic_card_reset_chain(struct gelic_card *card, for (descr = start_descr; start_descr != descr->next; descr++) { gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); - descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); + descr->hw_regs.next_descr_addr + = cpu_to_be32(descr->next->link.cpu_addr); } chain->head = start_descr; chain->tail = (descr - 1); - (descr - 1)->next_descr_addr = 0; + (descr - 1)->hw_regs.next_descr_addr = 0; } void gelic_card_up(struct gelic_card *card) @@ -259,6 +260,7 @@ void gelic_card_down(struct gelic_card *card) if (atomic_dec_if_positive(&card->users) == 0) { pr_debug("%s: real do\n", __func__); napi_disable(&card->napi); + timer_delete_sync(&card->rx_oom_timer); /* * Disable irq. Wireless interrupts will * be disabled later if any @@ -278,18 +280,6 @@ void gelic_card_down(struct gelic_card *card) } /** - * gelic_descr_get_status -- returns the status of a descriptor - * @descr: descriptor to look at - * - * returns the status as in the dmac_cmd_status field of the descriptor - */ -static enum gelic_descr_dma_status -gelic_descr_get_status(struct gelic_descr *descr) -{ - return be32_to_cpu(descr->dmac_cmd_status) & GELIC_DESCR_DMA_STAT_MASK; -} - -/** * gelic_card_free_chain - free descriptor chain * @card: card structure * @descr_in: address of desc @@ -299,10 +289,12 @@ static void gelic_card_free_chain(struct gelic_card *card, { struct gelic_descr *descr; - for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) { - dma_unmap_single(ctodev(card), descr->bus_addr, - GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL); - descr->bus_addr = 0; + for (descr = descr_in; descr && descr->link.cpu_addr; + descr = descr->next) { + dma_unmap_single(ctodev(card), descr->link.cpu_addr, + descr->link.size, DMA_BIDIRECTIONAL); + descr->link.cpu_addr = 0; + descr->link.size = 0; } } @@ -331,13 +323,19 @@ static int gelic_card_init_chain(struct gelic_card *card, /* set up the hardware pointers in each descriptor */ for (i = 0; i < no; i++, descr++) { gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); - descr->bus_addr = - dma_map_single(ctodev(card), descr, - GELIC_DESCR_SIZE, - DMA_BIDIRECTIONAL); - if (!descr->bus_addr) - goto iommu_error; + descr->link.size = sizeof(struct gelic_hw_regs); + descr->link.cpu_addr = dma_map_single(ctodev(card), descr, + descr->link.size, DMA_BIDIRECTIONAL); + + if (dma_mapping_error(ctodev(card), descr->link.cpu_addr)) { + for (i--, descr--; 0 <= i; i--, descr--) { + dma_unmap_single(ctodev(card), + descr->link.cpu_addr, descr->link.size, + DMA_BIDIRECTIONAL); + } + return -ENOMEM; + } descr->next = descr + 1; descr->prev = descr - 1; @@ -349,82 +347,85 @@ static int gelic_card_init_chain(struct gelic_card *card, /* chain bus addr of hw descriptor */ descr = start_descr; for (i = 0; i < no; i++, descr++) { - descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); + descr->hw_regs.next_descr_addr = + cpu_to_be32(descr->next->link.cpu_addr); } chain->head = start_descr; chain->tail = start_descr; /* do not chain last hw descriptor */ - (descr - 1)->next_descr_addr = 0; + (descr - 1)->hw_regs.next_descr_addr = 0; return 0; - -iommu_error: - for (i--, descr--; 0 <= i; i--, descr--) - if (descr->bus_addr) - dma_unmap_single(ctodev(card), descr->bus_addr, - GELIC_DESCR_SIZE, - DMA_BIDIRECTIONAL); - return -ENOMEM; } /** * gelic_descr_prepare_rx - reinitializes a rx descriptor * @card: card structure * @descr: descriptor to re-init + * @napi_mode: is it running in napi poll * * return 0 on success, <0 on failure * * allocates a new rx skb, iommu-maps it and attaches it to the descriptor. * Activate the descriptor state-wise + * + * Gelic RX sk_buffs must be aligned to GELIC_NET_RXBUF_ALIGN and the length + * must be a multiple of GELIC_NET_RXBUF_ALIGN. */ static int gelic_descr_prepare_rx(struct gelic_card *card, - struct gelic_descr *descr) + struct gelic_descr *descr, + bool napi_mode) { + static const unsigned int rx_skb_size = + ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) + + GELIC_NET_RXBUF_ALIGN - 1; + dma_addr_t cpu_addr; int offset; - unsigned int bufsize; if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) dev_info(ctodev(card), "%s: ERROR status\n", __func__); - /* we need to round up the buffer size to a multiple of 128 */ - bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); - /* and we need to have it 128 byte aligned, therefore we allocate a - * bit more */ - descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); + descr->hw_regs.dmac_cmd_status = 0; + descr->hw_regs.result_size = 0; + descr->hw_regs.valid_size = 0; + descr->hw_regs.data_error = 0; + descr->hw_regs.payload.dev_addr = 0; + descr->hw_regs.payload.size = 0; + + if (napi_mode) + descr->skb = napi_alloc_skb(&card->napi, rx_skb_size); + else + descr->skb = netdev_alloc_skb(*card->netdev, rx_skb_size); if (!descr->skb) { - descr->buf_addr = 0; /* tell DMAC don't touch memory */ - dev_info(ctodev(card), - "%s:allocate skb failed !!\n", __func__); + descr->hw_regs.payload.dev_addr = 0; /* tell DMAC don't touch memory */ return -ENOMEM; } - descr->buf_size = cpu_to_be32(bufsize); - descr->dmac_cmd_status = 0; - descr->result_size = 0; - descr->valid_size = 0; - descr->data_error = 0; offset = ((unsigned long)descr->skb->data) & (GELIC_NET_RXBUF_ALIGN - 1); if (offset) skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset); /* io-mmu-map the skb */ - descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), - descr->skb->data, - GELIC_NET_MAX_MTU, - DMA_FROM_DEVICE)); - if (!descr->buf_addr) { + cpu_addr = dma_map_single(ctodev(card), descr->skb->data, + GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE); + descr->hw_regs.payload.dev_addr = cpu_to_be32(cpu_addr); + if (dma_mapping_error(ctodev(card), cpu_addr)) { dev_kfree_skb_any(descr->skb); descr->skb = NULL; dev_info(ctodev(card), "%s:Could not iommu-map rx buffer\n", __func__); gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); return -ENOMEM; - } else { - gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); - return 0; } + + descr->hw_regs.payload.size = cpu_to_be32(GELIC_NET_MAX_FRAME); + descr->hw_regs.payload.dev_addr = cpu_to_be32(cpu_addr); + + gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); + + return 0; } /** @@ -439,14 +440,15 @@ static void gelic_card_release_rx_chain(struct gelic_card *card) do { if (descr->skb) { dma_unmap_single(ctodev(card), - be32_to_cpu(descr->buf_addr), - descr->skb->len, - DMA_FROM_DEVICE); - descr->buf_addr = 0; + be32_to_cpu(descr->hw_regs.payload.dev_addr), + descr->skb->len, + DMA_FROM_DEVICE); + descr->hw_regs.payload.dev_addr = 0; + descr->hw_regs.payload.size = 0; dev_kfree_skb_any(descr->skb); descr->skb = NULL; gelic_descr_set_status(descr, - GELIC_DESCR_DMA_NOT_IN_USE); + GELIC_DESCR_DMA_NOT_IN_USE); } descr = descr->next; } while (descr != card->rx_chain.head); @@ -467,7 +469,7 @@ static int gelic_card_fill_rx_chain(struct gelic_card *card) do { if (!descr->skb) { - ret = gelic_descr_prepare_rx(card, descr); + ret = gelic_descr_prepare_rx(card, descr, false); if (ret) goto rewind; } @@ -508,19 +510,20 @@ static void gelic_descr_release_tx(struct gelic_card *card, { struct sk_buff *skb = descr->skb; - BUG_ON(!(be32_to_cpu(descr->data_status) & GELIC_DESCR_TX_TAIL)); + BUG_ON(!(be32_to_cpu(descr->hw_regs.data_status) & GELIC_DESCR_TX_TAIL)); - dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), skb->len, - DMA_TO_DEVICE); + dma_unmap_single(ctodev(card), + be32_to_cpu(descr->hw_regs.payload.dev_addr), skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(skb); - descr->buf_addr = 0; - descr->buf_size = 0; - descr->next_descr_addr = 0; - descr->result_size = 0; - descr->valid_size = 0; - descr->data_status = 0; - descr->data_error = 0; + descr->hw_regs.payload.dev_addr = 0; + descr->hw_regs.payload.size = 0; + descr->hw_regs.next_descr_addr = 0; + descr->hw_regs.result_size = 0; + descr->hw_regs.valid_size = 0; + descr->hw_regs.data_status = 0; + descr->hw_regs.data_error = 0; descr->skb = NULL; /* set descr status */ @@ -701,7 +704,7 @@ gelic_card_get_next_tx_descr(struct gelic_card *card) } /** - * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field + * gelic_descr_set_tx_cmdstat - sets the tx descriptor command field * @descr: descriptor structure to fill out * @skb: packet to consider * @@ -713,7 +716,7 @@ static void gelic_descr_set_tx_cmdstat(struct gelic_descr *descr, struct sk_buff *skb) { if (skb->ip_summed != CHECKSUM_PARTIAL) - descr->dmac_cmd_status = + descr->hw_regs.dmac_cmd_status = cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | GELIC_DESCR_TX_DMA_FRAME_TAIL); else { @@ -721,19 +724,19 @@ static void gelic_descr_set_tx_cmdstat(struct gelic_descr *descr, * if yes: tcp? udp? */ if (skb->protocol == htons(ETH_P_IP)) { if (ip_hdr(skb)->protocol == IPPROTO_TCP) - descr->dmac_cmd_status = + descr->hw_regs.dmac_cmd_status = cpu_to_be32(GELIC_DESCR_DMA_CMD_TCP_CHKSUM | GELIC_DESCR_TX_DMA_FRAME_TAIL); else if (ip_hdr(skb)->protocol == IPPROTO_UDP) - descr->dmac_cmd_status = + descr->hw_regs.dmac_cmd_status = cpu_to_be32(GELIC_DESCR_DMA_CMD_UDP_CHKSUM | GELIC_DESCR_TX_DMA_FRAME_TAIL); else /* * the stack should checksum non-tcp and non-udp * packets on his own: NETIF_F_IP_CSUM */ - descr->dmac_cmd_status = + descr->hw_regs.dmac_cmd_status = cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | GELIC_DESCR_TX_DMA_FRAME_TAIL); } @@ -754,7 +757,7 @@ static struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb, return NULL; dev_kfree_skb_any(sk_tmp); } - veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); + veth = skb_push(skb, VLAN_HLEN); /* Move the mac addresses to the top of buffer */ memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); @@ -794,18 +797,18 @@ static int gelic_descr_prepare_tx(struct gelic_card *card, buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE); - if (!buf) { + if (dma_mapping_error(ctodev(card), buf)) { dev_err(ctodev(card), "dma map 2 failed (%p, %i). Dropping packet\n", skb->data, skb->len); return -ENOMEM; } - descr->buf_addr = cpu_to_be32(buf); - descr->buf_size = cpu_to_be32(skb->len); + descr->hw_regs.payload.dev_addr = cpu_to_be32(buf); + descr->hw_regs.payload.size = cpu_to_be32(skb->len); descr->skb = skb; - descr->data_status = 0; - descr->next_descr_addr = 0; /* terminate hw descr */ + descr->hw_regs.data_status = 0; + descr->hw_regs.next_descr_addr = 0; /* terminate hw descr */ gelic_descr_set_tx_cmdstat(descr, skb); /* bump free descriptor pointer */ @@ -830,7 +833,7 @@ static int gelic_card_kick_txdma(struct gelic_card *card, if (gelic_descr_get_status(descr) == GELIC_DESCR_DMA_CARDOWNED) { card->tx_dma_progress = 1; status = lv1_net_start_tx_dma(bus_id(card), dev_id(card), - descr->bus_addr, 0); + descr->link.cpu_addr, 0); if (status) { card->tx_dma_progress = 0; dev_info(ctodev(card), "lv1_net_start_txdma failed," \ @@ -845,9 +848,9 @@ static int gelic_card_kick_txdma(struct gelic_card *card, * @skb: packet to send out * @netdev: interface device structure * - * returns 0 on success, <0 on failure + * returns NETDEV_TX_OK on success, NETDEV_TX_BUSY on failure */ -int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) +netdev_tx_t gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) { struct gelic_card *card = netdev_card(netdev); struct gelic_descr *descr; @@ -883,7 +886,8 @@ int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) * link this prepared descriptor to previous one * to achieve high performance */ - descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); + descr->prev->hw_regs.next_descr_addr = + cpu_to_be32(descr->link.cpu_addr); /* * as hardware descriptor is modified in the above lines, * ensure that the hardware sees it @@ -896,12 +900,12 @@ int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) */ netdev->stats.tx_dropped++; /* don't trigger BUG_ON() in gelic_descr_release_tx */ - descr->data_status = cpu_to_be32(GELIC_DESCR_TX_TAIL); + descr->hw_regs.data_status = cpu_to_be32(GELIC_DESCR_TX_TAIL); gelic_descr_release_tx(card, descr); /* reset head */ card->tx_chain.head = descr; /* reset hw termination */ - descr->prev->next_descr_addr = 0; + descr->prev->hw_regs.next_descr_addr = 0; dev_info(ctodev(card), "%s: kick failure\n", __func__); } @@ -926,21 +930,21 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr, struct sk_buff *skb = descr->skb; u32 data_status, data_error; - data_status = be32_to_cpu(descr->data_status); - data_error = be32_to_cpu(descr->data_error); + data_status = be32_to_cpu(descr->hw_regs.data_status); + data_error = be32_to_cpu(descr->hw_regs.data_error); /* unmap skb buffer */ - dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), - GELIC_NET_MAX_MTU, - DMA_FROM_DEVICE); - - skb_put(skb, be32_to_cpu(descr->valid_size)? - be32_to_cpu(descr->valid_size) : - be32_to_cpu(descr->result_size)); - if (!descr->valid_size) + dma_unmap_single(ctodev(card), + be32_to_cpu(descr->hw_regs.payload.dev_addr), + be32_to_cpu(descr->hw_regs.payload.size), DMA_FROM_DEVICE); + + skb_put(skb, be32_to_cpu(descr->hw_regs.valid_size)? + be32_to_cpu(descr->hw_regs.valid_size) : + be32_to_cpu(descr->hw_regs.result_size)); + if (!descr->hw_regs.valid_size) dev_info(ctodev(card), "buffer full %x %x %x\n", - be32_to_cpu(descr->result_size), - be32_to_cpu(descr->buf_size), - be32_to_cpu(descr->dmac_cmd_status)); + be32_to_cpu(descr->hw_regs.result_size), + be32_to_cpu(descr->hw_regs.payload.size), + be32_to_cpu(descr->hw_regs.dmac_cmd_status)); descr->skb = NULL; /* @@ -965,14 +969,15 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr, netdev->stats.rx_bytes += skb->len; /* pass skb up to stack */ - netif_receive_skb(skb); + napi_gro_receive(&card->napi, skb); } /** * gelic_card_decode_one_descr - processes an rx descriptor * @card: card structure * - * returns 1 if a packet has been sent to the stack, otherwise 0 + * returns 1 if a packet has been sent to the stack, -ENOMEM on skb alloc + * failure, otherwise 0 * * processes an rx descriptor by iommu-unmapping the data buffer and passing * the packet up to the stack @@ -983,16 +988,18 @@ static int gelic_card_decode_one_descr(struct gelic_card *card) struct gelic_descr_chain *chain = &card->rx_chain; struct gelic_descr *descr = chain->head; struct net_device *netdev = NULL; - int dmac_chain_ended; + int dmac_chain_ended = 0; + int prepare_rx_ret; status = gelic_descr_get_status(descr); if (status == GELIC_DESCR_DMA_CARDOWNED) return 0; - if (status == GELIC_DESCR_DMA_NOT_IN_USE) { + if (status == GELIC_DESCR_DMA_NOT_IN_USE || !descr->skb) { dev_dbg(ctodev(card), "dormant descr? %p\n", descr); - return 0; + dmac_chain_ended = 1; + goto refill; } /* netdevice select */ @@ -1050,24 +1057,26 @@ static int gelic_card_decode_one_descr(struct gelic_card *card) refill: /* is the current descriptor terminated with next_descr == NULL? */ - dmac_chain_ended = - be32_to_cpu(descr->dmac_cmd_status) & - GELIC_DESCR_RX_DMA_CHAIN_END; + if (!dmac_chain_ended) + dmac_chain_ended = + be32_to_cpu(descr->hw_regs.dmac_cmd_status) & + GELIC_DESCR_RX_DMA_CHAIN_END; /* * So that always DMAC can see the end * of the descriptor chain to avoid * from unwanted DMAC overrun. */ - descr->next_descr_addr = 0; + descr->hw_regs.next_descr_addr = 0; /* change the descriptor state: */ gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); /* - * this call can fail, but for now, just leave this - * decriptor without skb + * this call can fail, propagate the error */ - gelic_descr_prepare_rx(card, descr); + prepare_rx_ret = gelic_descr_prepare_rx(card, descr, true); + if (prepare_rx_ret) + return prepare_rx_ret; chain->tail = descr; chain->head = descr->next; @@ -1075,7 +1084,8 @@ refill: /* * Set this descriptor the end of the chain. */ - descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); + descr->prev->hw_regs.next_descr_addr = + cpu_to_be32(descr->link.cpu_addr); /* * If dmac chain was met, DMAC stopped. @@ -1088,6 +1098,13 @@ refill: return 1; } +static void gelic_rx_oom_timer(struct timer_list *t) +{ + struct gelic_card *card = timer_container_of(card, t, rx_oom_timer); + + napi_schedule(&card->napi); +} + /** * gelic_net_poll - NAPI poll function called by the stack to return packets * @napi: napi structure @@ -1100,40 +1117,30 @@ static int gelic_net_poll(struct napi_struct *napi, int budget) { struct gelic_card *card = container_of(napi, struct gelic_card, napi); int packets_done = 0; + int work_result = 0; while (packets_done < budget) { - if (!gelic_card_decode_one_descr(card)) + work_result = gelic_card_decode_one_descr(card); + if (work_result != 1) break; packets_done++; } + if (work_result == -ENOMEM) { + napi_complete_done(napi, packets_done); + mod_timer(&card->rx_oom_timer, jiffies + 1); + return packets_done; + } + if (packets_done < budget) { - napi_complete(napi); + napi_complete_done(napi, packets_done); gelic_card_rx_irq_on(card); } return packets_done; } -/** - * gelic_net_change_mtu - changes the MTU of an interface - * @netdev: interface device structure - * @new_mtu: new MTU value - * - * returns 0 on success, <0 on failure - */ -int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) -{ - /* no need to re-alloc skbs or so -- the max mtu is about 2.3k - * and mtu is outbound only anyway */ - if ((new_mtu < GELIC_NET_MIN_MTU) || - (new_mtu > GELIC_NET_MAX_MTU)) { - return -EINVAL; - } - netdev->mtu = new_mtu; - return 0; -} -/** +/* * gelic_card_interrupt - event handler for gelic_net */ static irqreturn_t gelic_card_interrupt(int irq, void *ptr) @@ -1181,7 +1188,7 @@ static irqreturn_t gelic_card_interrupt(int irq, void *ptr) * gelic_net_poll_controller - artificial interrupt for netconsole etc. * @netdev: interface device structure * - * see Documentation/networking/netconsole.txt + * see Documentation/networking/netconsole.rst */ void gelic_net_poll_controller(struct net_device *netdev) { @@ -1220,65 +1227,72 @@ int gelic_net_open(struct net_device *netdev) void gelic_net_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) { - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + strscpy(info->driver, DRV_NAME, sizeof(info->driver)); + strscpy(info->version, DRV_VERSION, sizeof(info->version)); } -static int gelic_ether_get_settings(struct net_device *netdev, - struct ethtool_cmd *cmd) +static int gelic_ether_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) { struct gelic_card *card = netdev_card(netdev); + u32 supported, advertising; gelic_card_get_ether_port_status(card, 0); if (card->ether_port_status & GELIC_LV1_ETHER_FULL_DUPLEX) - cmd->duplex = DUPLEX_FULL; + cmd->base.duplex = DUPLEX_FULL; else - cmd->duplex = DUPLEX_HALF; + cmd->base.duplex = DUPLEX_HALF; switch (card->ether_port_status & GELIC_LV1_ETHER_SPEED_MASK) { case GELIC_LV1_ETHER_SPEED_10: - ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->base.speed = SPEED_10; break; case GELIC_LV1_ETHER_SPEED_100: - ethtool_cmd_speed_set(cmd, SPEED_100); + cmd->base.speed = SPEED_100; break; case GELIC_LV1_ETHER_SPEED_1000: - ethtool_cmd_speed_set(cmd, SPEED_1000); + cmd->base.speed = SPEED_1000; break; default: pr_info("%s: speed unknown\n", __func__); - ethtool_cmd_speed_set(cmd, SPEED_10); + cmd->base.speed = SPEED_10; break; } - cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | + supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full; - cmd->advertising = cmd->supported; + advertising = supported; if (card->link_mode & GELIC_LV1_ETHER_AUTO_NEG) { - cmd->autoneg = AUTONEG_ENABLE; + cmd->base.autoneg = AUTONEG_ENABLE; } else { - cmd->autoneg = AUTONEG_DISABLE; - cmd->advertising &= ~ADVERTISED_Autoneg; + cmd->base.autoneg = AUTONEG_DISABLE; + advertising &= ~ADVERTISED_Autoneg; } - cmd->port = PORT_TP; + cmd->base.port = PORT_TP; + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + advertising); return 0; } -static int gelic_ether_set_settings(struct net_device *netdev, - struct ethtool_cmd *cmd) +static int +gelic_ether_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) { struct gelic_card *card = netdev_card(netdev); u64 mode; int ret; - if (cmd->autoneg == AUTONEG_ENABLE) { + if (cmd->base.autoneg == AUTONEG_ENABLE) { mode = GELIC_LV1_ETHER_AUTO_NEG; } else { - switch (cmd->speed) { + switch (cmd->base.speed) { case SPEED_10: mode = GELIC_LV1_ETHER_SPEED_10; break; @@ -1291,9 +1305,9 @@ static int gelic_ether_set_settings(struct net_device *netdev, default: return -EINVAL; } - if (cmd->duplex == DUPLEX_FULL) + if (cmd->base.duplex == DUPLEX_FULL) { mode |= GELIC_LV1_ETHER_FULL_DUPLEX; - else if (cmd->speed == SPEED_1000) { + } else if (cmd->base.speed == SPEED_1000) { pr_info("1000 half duplex is not supported.\n"); return -EINVAL; } @@ -1388,11 +1402,11 @@ done: static const struct ethtool_ops gelic_ether_ethtool_ops = { .get_drvinfo = gelic_net_get_drvinfo, - .get_settings = gelic_ether_get_settings, - .set_settings = gelic_ether_set_settings, .get_link = ethtool_op_get_link, .get_wol = gelic_net_get_wol, .set_wol = gelic_net_set_wol, + .get_link_ksettings = gelic_ether_get_link_ksettings, + .set_link_ksettings = gelic_ether_set_link_ksettings, }; /** @@ -1426,10 +1440,11 @@ out: /** * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in. * @netdev: interface device structure + * @txqueue: unused * * called, if tx hangs. Schedules a task that resets the interface */ -void gelic_net_tx_timeout(struct net_device *netdev) +void gelic_net_tx_timeout(struct net_device *netdev, unsigned int txqueue) { struct gelic_card *card; @@ -1446,7 +1461,6 @@ static const struct net_device_ops gelic_netdevice_ops = { .ndo_stop = gelic_net_stop, .ndo_start_xmit = gelic_net_xmit, .ndo_set_rx_mode = gelic_net_set_multi, - .ndo_change_mtu = gelic_net_change_mtu, .ndo_tx_timeout = gelic_net_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -1458,6 +1472,7 @@ static const struct net_device_ops gelic_netdevice_ops = { /** * gelic_ether_setup_netdev_ops - initialization of net_device operations * @netdev: net_device structure + * @napi: napi structure * * fills out function pointers in the net_device structure */ @@ -1466,14 +1481,13 @@ static void gelic_ether_setup_netdev_ops(struct net_device *netdev, { netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; /* NAPI */ - netif_napi_add(netdev, napi, - gelic_net_poll, GELIC_NET_NAPI_WEIGHT); + netif_napi_add(netdev, napi, gelic_net_poll); netdev->ethtool_ops = &gelic_ether_ethtool_ops; netdev->netdev_ops = &gelic_netdevice_ops; } /** - * gelic_ether_setup_netdev - initialization of net_device + * gelic_net_setup_netdev - initialization of net_device * @netdev: net_device structure * @card: card structure * @@ -1503,7 +1517,7 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card) __func__, status); return -EINVAL; } - memcpy(netdev->dev_addr, &v1, ETH_ALEN); + eth_hw_addr_set(netdev, (u8 *)&v1); if (card->vlan_required) { netdev->hard_header_len += VLAN_HLEN; @@ -1514,6 +1528,10 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card) netdev->features |= NETIF_F_VLAN_CHALLENGED; } + /* MTU range: 64 - 1518 */ + netdev->min_mtu = GELIC_NET_MIN_MTU; + netdev->max_mtu = GELIC_NET_MAX_MTU; + status = register_netdev(netdev); if (status) { dev_err(ctodev(card), "%s:Couldn't register %s %d\n", @@ -1526,14 +1544,16 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card) return 0; } +#define GELIC_ALIGN (32) + /** * gelic_alloc_card_net - allocates net_device and card structure + * @netdev: interface device structure * * returns the card structure or NULL in case of errors * * the card and net_device structures are linked to each other */ -#define GELIC_ALIGN (32) static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev) { struct gelic_card *card; @@ -1562,7 +1582,7 @@ static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev) * alloc netdev */ *netdev = alloc_etherdev(sizeof(struct gelic_port)); - if (!netdev) { + if (!*netdev) { kfree(card->unalign); return NULL; } @@ -1582,6 +1602,8 @@ static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev) mutex_init(&card->updown_lock); atomic_set(&card->users, 0); + timer_setup(&card->rx_oom_timer, gelic_rx_oom_timer, 0); + return card; } @@ -1656,7 +1678,7 @@ static void gelic_card_get_vlan_info(struct gelic_card *card) dev_info(ctodev(card), "internal vlan %s\n", card->vlan_required? "enabled" : "disabled"); } -/** +/* * ps3_gelic_driver_probe - add a device to the control of this driver */ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) @@ -1727,7 +1749,7 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) goto fail_alloc_irq; } result = request_irq(card->irq, gelic_card_interrupt, - IRQF_DISABLED, netdev->name, card); + 0, netdev->name, card); if (result) { dev_info(ctodev(card), "%s:request_irq failed (%d)\n", @@ -1740,12 +1762,14 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) GELIC_CARD_PORT_STATUS_CHANGED; - if (gelic_card_init_chain(card, &card->tx_chain, - card->descr, GELIC_NET_TX_DESCRIPTORS)) + result = gelic_card_init_chain(card, &card->tx_chain, + card->descr, GELIC_NET_TX_DESCRIPTORS); + if (result) goto fail_alloc_tx; - if (gelic_card_init_chain(card, &card->rx_chain, - card->descr + GELIC_NET_TX_DESCRIPTORS, - GELIC_NET_RX_DESCRIPTORS)) + result = gelic_card_init_chain(card, &card->rx_chain, + card->descr + GELIC_NET_TX_DESCRIPTORS, + GELIC_NET_RX_DESCRIPTORS); + if (result) goto fail_alloc_rx; /* head of chain */ @@ -1755,7 +1779,8 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) card->rx_top, card->tx_top, sizeof(struct gelic_descr), GELIC_NET_RX_DESCRIPTORS); /* allocate rx skbs */ - if (gelic_card_alloc_rx_skbs(card)) + result = gelic_card_alloc_rx_skbs(card); + if (result) goto fail_alloc_skbs; spin_lock_init(&card->tx_lock); @@ -1767,13 +1792,14 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) gelic_ether_setup_netdev_ops(netdev, &card->napi); result = gelic_net_setup_netdev(netdev, card); if (result) { - dev_dbg(&dev->core, "%s: setup_netdev failed %d", + dev_dbg(&dev->core, "%s: setup_netdev failed %d\n", __func__, result); goto fail_setup_netdev; } #ifdef CONFIG_GELIC_WIRELESS - if (gelic_wl_driver_probe(card)) { + result = gelic_wl_driver_probe(card); + if (result) { dev_dbg(&dev->core, "%s: WL init failed\n", __func__); goto fail_setup_netdev; } @@ -1788,7 +1814,7 @@ fail_alloc_rx: gelic_card_free_chain(card, card->tx_chain.head); fail_alloc_tx: free_irq(card->irq, card); - netdev->irq = NO_IRQ; + netdev->irq = 0; fail_request_irq: ps3_sb_event_receive_port_destroy(dev, card->irq); fail_alloc_irq: @@ -1807,11 +1833,11 @@ fail_open: return result; } -/** +/* * ps3_gelic_driver_remove - remove a device from the control of this driver */ -static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) +static void ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) { struct gelic_card *card = ps3_system_bus_get_drvdata(dev); struct net_device *netdev0; @@ -1840,7 +1866,7 @@ static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) netdev0 = card->netdev[GELIC_PORT_ETHERNET_0]; /* disconnect event port */ free_irq(card->irq, card); - netdev0->irq = NO_IRQ; + netdev0->irq = 0; ps3_sb_event_receive_port_destroy(card->dev, card->irq); wait_event(card->waitq, @@ -1860,7 +1886,6 @@ static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) ps3_close_hv_device(dev); pr_debug("%s: done\n", __func__); - return 0; } static struct ps3_system_bus_driver ps3_gelic_driver = { |
