Commit 618a821d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6:
  - cxgb3 engine microcode load
  cxgb3 - Fix dev->priv usage
  qeth: Drop ARP packages on HiperSockets interface with NOARP attribute.
  qeth: provide specific message for OSA-adapters exclusively used
  qeth: crash during reboot after failing online setting
  qeth: Announce tx checksumming for qeth devices in TSO/EDDP mode
  qeth: dont return the return values of void functions.
  qeth: enforce a rate limit for inbound scatter gather messages
  qeth: ungrouping a device must not be interruptible
  netxen: fix crashes during module unload
  netxen: Avoid firmware load in PCI probe
  PS3: fix the bug that 'ifconfig down' would hang
  IOC3: Program UART predividers.
parents 5e7a3927 47330077
......@@ -916,7 +916,7 @@ int cxio_rdev_open(struct cxio_rdev *rdev_p)
PDBG("%s opening rnic dev %s\n", __FUNCTION__, rdev_p->dev_name);
memset(&rdev_p->ctrl_qp, 0, sizeof(rdev_p->ctrl_qp));
if (!rdev_p->t3cdev_p)
rdev_p->t3cdev_p = T3CDEV(netdev_p);
rdev_p->t3cdev_p = dev2t3cdev(netdev_p);
rdev_p->t3cdev_p->ulp = (void *) rdev_p;
err = rdev_p->t3cdev_p->ctl(rdev_p->t3cdev_p, RDMA_GET_PARAMS,
&(rdev_p->rnic_info));
......
......@@ -50,7 +50,9 @@ typedef irqreturn_t(*intr_handler_t) (int, void *);
struct vlan_group;
struct adapter;
struct port_info {
struct adapter *adapter;
struct vlan_group *vlan_grp;
const struct port_type_info *port_type;
u8 port_id;
......
......@@ -679,7 +679,8 @@ const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
int t3_seeprom_wp(struct adapter *adapter, int enable);
int t3_check_tpsram_version(struct adapter *adapter);
int t3_get_tp_version(struct adapter *adapter, u32 *vers);
int t3_check_tpsram_version(struct adapter *adapter, int *must_load);
int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
int t3_set_proto_sram(struct adapter *adap, u8 *data);
int t3_read_flash(struct adapter *adapter, unsigned int addr,
......
This diff is collapsed.
......@@ -593,6 +593,16 @@ int cxgb3_alloc_stid(struct t3cdev *tdev, struct cxgb3_client *client,
EXPORT_SYMBOL(cxgb3_alloc_stid);
/* Get the t3cdev associated with a net_device */
struct t3cdev *dev2t3cdev(struct net_device *dev)
{
const struct port_info *pi = netdev_priv(dev);
return (struct t3cdev *)pi->adapter;
}
EXPORT_SYMBOL(dev2t3cdev);
static int do_smt_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
{
struct cpl_smt_write_rpl *rpl = cplhdr(skb);
......@@ -925,7 +935,7 @@ void cxgb_neigh_update(struct neighbour *neigh)
struct net_device *dev = neigh->dev;
if (dev && (is_offloading(dev))) {
struct t3cdev *tdev = T3CDEV(dev);
struct t3cdev *tdev = dev2t3cdev(dev);
BUG_ON(!tdev);
t3_l2t_update(tdev, neigh);
......@@ -973,9 +983,9 @@ void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
"device ignored.\n", __FUNCTION__);
return;
}
tdev = T3CDEV(olddev);
tdev = dev2t3cdev(olddev);
BUG_ON(!tdev);
if (tdev != T3CDEV(newdev)) {
if (tdev != dev2t3cdev(newdev)) {
printk(KERN_WARNING "%s: Redirect to different "
"offload device ignored.\n", __FUNCTION__);
return;
......
......@@ -51,6 +51,8 @@ void cxgb3_offload_deactivate(struct adapter *adapter);
void cxgb3_set_dummy_ops(struct t3cdev *dev);
struct t3cdev *dev2t3cdev(struct net_device *dev);
/*
* Client registration. Users of T3 driver must register themselves.
* The T3 driver will call the add function of every client for each T3
......
......@@ -1073,7 +1073,7 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned int ndesc, pidx, credits, gen, compl;
const struct port_info *pi = netdev_priv(dev);
struct adapter *adap = dev->priv;
struct adapter *adap = pi->adapter;
struct sge_qset *qs = dev2qset(dev);
struct sge_txq *q = &qs->txq[TXQ_ETH];
......@@ -1326,7 +1326,8 @@ static void restart_ctrlq(unsigned long data)
struct sk_buff *skb;
struct sge_qset *qs = (struct sge_qset *)data;
struct sge_txq *q = &qs->txq[TXQ_CTRL];
struct adapter *adap = qs->netdev->priv;
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
spin_lock(&q->lock);
again:reclaim_completed_tx_imm(q);
......@@ -1531,7 +1532,8 @@ static void restart_offloadq(unsigned long data)
struct sk_buff *skb;
struct sge_qset *qs = (struct sge_qset *)data;
struct sge_txq *q = &qs->txq[TXQ_OFLD];
struct adapter *adap = qs->netdev->priv;
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
spin_lock(&q->lock);
again:reclaim_completed_tx(adap, q);
......@@ -1675,7 +1677,8 @@ static inline void deliver_partial_bundle(struct t3cdev *tdev,
*/
static int ofld_poll(struct net_device *dev, int *budget)
{
struct adapter *adapter = dev->priv;
const struct port_info *pi = netdev_priv(dev);
struct adapter *adapter = pi->adapter;
struct sge_qset *qs = dev2qset(dev);
struct sge_rspq *q = &qs->rspq;
int work_done, limit = min(*budget, dev->quota), avail = limit;
......@@ -2075,7 +2078,8 @@ static inline int is_pure_response(const struct rsp_desc *r)
*/
static int napi_rx_handler(struct net_device *dev, int *budget)
{
struct adapter *adap = dev->priv;
const struct port_info *pi = netdev_priv(dev);
struct adapter *adap = pi->adapter;
struct sge_qset *qs = dev2qset(dev);
int effective_budget = min(*budget, dev->quota);
......@@ -2205,7 +2209,8 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q)
irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
{
struct sge_qset *qs = cookie;
struct adapter *adap = qs->netdev->priv;
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
struct sge_rspq *q = &qs->rspq;
spin_lock(&q->lock);
......@@ -2224,7 +2229,8 @@ irqreturn_t t3_sge_intr_msix(int irq, void *cookie)
irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie)
{
struct sge_qset *qs = cookie;
struct adapter *adap = qs->netdev->priv;
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
struct sge_rspq *q = &qs->rspq;
spin_lock(&q->lock);
......@@ -2508,7 +2514,8 @@ static void sge_timer_cb(unsigned long data)
{
spinlock_t *lock;
struct sge_qset *qs = (struct sge_qset *)data;
struct adapter *adap = qs->netdev->priv;
const struct port_info *pi = netdev_priv(qs->netdev);
struct adapter *adap = pi->adapter;
if (spin_trylock(&qs->txq[TXQ_ETH].lock)) {
reclaim_completed_tx(adap, &qs->txq[TXQ_ETH]);
......
......@@ -848,16 +848,15 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr,
}
/**
* t3_check_tpsram_version - read the tp sram version
* t3_get_tp_version - read the tp sram version
* @adapter: the adapter
* @vers: where to place the version
*
* Reads the protocol sram version from serial eeprom.
* Reads the protocol sram version from sram.
*/
int t3_check_tpsram_version(struct adapter *adapter)
int t3_get_tp_version(struct adapter *adapter, u32 *vers)
{
int ret;
u32 vers;
unsigned int major, minor;
/* Get version loaded in SRAM */
t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
......@@ -866,7 +865,32 @@ int t3_check_tpsram_version(struct adapter *adapter)
if (ret)
return ret;
vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
*vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
return 0;
}
/**
* t3_check_tpsram_version - read the tp sram version
* @adapter: the adapter
* @must_load: set to 1 if loading a new microcode image is required
*
* Reads the protocol sram version from flash.
*/
int t3_check_tpsram_version(struct adapter *adapter, int *must_load)
{
int ret;
u32 vers;
unsigned int major, minor;
if (adapter->params.rev == T3_REV_A)
return 0;
*must_load = 1;
ret = t3_get_tp_version(adapter, &vers);
if (ret)
return ret;
major = G_TP_VERSION_MAJOR(vers);
minor = G_TP_VERSION_MINOR(vers);
......@@ -874,6 +898,16 @@ int t3_check_tpsram_version(struct adapter *adapter)
if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
return 0;
if (major != TP_VERSION_MAJOR)
CH_ERR(adapter, "found wrong TP version (%u.%u), "
"driver needs version %d.%d\n", major, minor,
TP_VERSION_MAJOR, TP_VERSION_MINOR);
else {
*must_load = 0;
CH_ERR(adapter, "found wrong TP version (%u.%u), "
"driver compiled for version %d.%d\n", major, minor,
TP_VERSION_MAJOR, TP_VERSION_MINOR);
}
return -EINVAL;
}
......
......@@ -42,9 +42,6 @@
#define T3CNAMSIZ 16
/* Get the t3cdev associated with a net_device */
#define T3CDEV(netdev) (struct t3cdev *)(netdev->priv)
struct cxgb3_client;
enum t3ctype {
......
......@@ -48,6 +48,7 @@
#ifdef CONFIG_SERIAL_8250
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#endif
#include <linux/netdevice.h>
......@@ -1151,13 +1152,41 @@ static int ioc3_is_menet(struct pci_dev *pdev)
* Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working
* around ioc3 oddities in this respect.
*
* The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
* The IOC3 serials use a 22MHz clock rate with an additional divider which
* can be programmed in the SCR register if the DLAB bit is set.
*
* Register to interrupt zero because we share the interrupt with
* the serial driver which we don't properly support yet.
*
* Can't use UPF_IOREMAP as the whole of IOC3 resources have already been
* registered.
*/
static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
{
#define COSMISC_CONSTANT 6
struct uart_port port = {
.irq = 0,
.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
.iotype = UPIO_MEM,
.regshift = 0,
.uartclk = (22000000 << 1) / COSMISC_CONSTANT,
.membase = (unsigned char __iomem *) uart,
.mapbase = (unsigned long) uart,
};
unsigned char lcr;
lcr = uart->iu_lcr;
uart->iu_lcr = lcr | UART_LCR_DLAB;
uart->iu_scr = COSMISC_CONSTANT,
uart->iu_lcr = lcr;
uart->iu_lcr;
serial8250_register_port(&port);
}
static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
{
struct uart_port port;
/*
* We need to recognice and treat the fourth MENET serial as it
* does not have an SuperIO chip attached to it, therefore attempting
......@@ -1171,24 +1200,35 @@ static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
return;
/*
* Register to interrupt zero because we share the interrupt with
* the serial driver which we don't properly support yet.
*
* Can't use UPF_IOREMAP as the whole of IOC3 resources have already
* been registered.
* Switch IOC3 to PIO mode. It probably already was but let's be
* paranoid
*/
memset(&port, 0, sizeof(port));
port.irq = 0;
port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
port.iotype = UPIO_MEM;
port.regshift = 0;
port.uartclk = 22000000 / 3;
port.membase = (unsigned char *) &ioc3->sregs.uarta;
serial8250_register_port(&port);
port.membase = (unsigned char *) &ioc3->sregs.uartb;
serial8250_register_port(&port);
ioc3->gpcr_s = GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL;
ioc3->gpcr_s;
ioc3->gppr_6 = 0;
ioc3->gppr_6;
ioc3->gppr_7 = 0;
ioc3->gppr_7;
ioc3->sscr_a = ioc3->sscr_a & ~SSCR_DMA_EN;
ioc3->sscr_a;
ioc3->sscr_b = ioc3->sscr_b & ~SSCR_DMA_EN;
ioc3->sscr_b;
/* Disable all SA/B interrupts except for SA/B_INT in SIO_IEC. */
ioc3->sio_iec &= ~ (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL |
SIO_IR_SA_RX_HIGH | SIO_IR_SA_RX_TIMER |
SIO_IR_SA_DELTA_DCD | SIO_IR_SA_DELTA_CTS |
SIO_IR_SA_TX_EXPLICIT | SIO_IR_SA_MEMERR);
ioc3->sio_iec |= SIO_IR_SA_INT;
ioc3->sscr_a = 0;
ioc3->sio_iec &= ~ (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL |
SIO_IR_SB_RX_HIGH | SIO_IR_SB_RX_TIMER |
SIO_IR_SB_DELTA_DCD | SIO_IR_SB_DELTA_CTS |
SIO_IR_SB_TX_EXPLICIT | SIO_IR_SB_MEMERR);
ioc3->sio_iec |= SIO_IR_SB_INT;
ioc3->sscr_b = 0;
ioc3_8250_register(&ioc3->sregs.uarta);
ioc3_8250_register(&ioc3->sregs.uartb);
}
#endif
......
......@@ -649,9 +649,11 @@ enum {
#define PCIX_INT_VECTOR (0x10100)
#define PCIX_INT_MASK (0x10104)
#define PCIX_MN_WINDOW (0x10200)
#define PCIX_MN_WINDOW_F0 (0x10200)
#define PCIX_MN_WINDOW(_f) (PCIX_MN_WINDOW_F0 + (0x20 * (_f)))
#define PCIX_MS_WINDOW (0x10204)
#define PCIX_SN_WINDOW (0x10208)
#define PCIX_SN_WINDOW_F0 (0x10208)
#define PCIX_SN_WINDOW(_f) (PCIX_SN_WINDOW_F0 + (0x20 * (_f)))
#define PCIX_CRB_WINDOW (0x10210)
#define PCIX_CRB_WINDOW_F0 (0x10210)
#define PCIX_CRB_WINDOW_F1 (0x10230)
......
......@@ -904,11 +904,11 @@ netxen_nic_pci_set_window(struct netxen_adapter *adapter,
ddr_mn_window = window;
writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
NETXEN_PCIX_PH_REG
(PCIX_MN_WINDOW)));
(PCIX_MN_WINDOW(adapter->ahw.pci_func))));
/* MUST make sure window is set before we forge on... */
readl(PCI_OFFSET_SECOND_RANGE(adapter,
NETXEN_PCIX_PH_REG
(PCIX_MN_WINDOW)));
(PCIX_MN_WINDOW(adapter->ahw.pci_func))));
}
addr -= (window * NETXEN_WINDOW_ONE);
addr += NETXEN_PCI_DDR_NET;
......@@ -929,11 +929,11 @@ netxen_nic_pci_set_window(struct netxen_adapter *adapter,
writel((window << 22),
PCI_OFFSET_SECOND_RANGE(adapter,
NETXEN_PCIX_PH_REG
(PCIX_SN_WINDOW)));
(PCIX_SN_WINDOW(adapter->ahw.pci_func))));
/* MUST make sure window is set before we forge on... */
readl(PCI_OFFSET_SECOND_RANGE(adapter,
NETXEN_PCIX_PH_REG
(PCIX_SN_WINDOW)));
(PCIX_SN_WINDOW(adapter->ahw.pci_func))));
}
addr -= (window * 0x400000);
addr += NETXEN_PCI_QDR_NET;
......
......@@ -639,10 +639,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
NETXEN_CRB_NORMALIZE(adapter,
NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
/* Handshake with the card before we register the devices. */
writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
netxen_pinit_from_rom(adapter, 0);
msleep(1);
netxen_load_firmware(adapter);
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
}
......@@ -750,9 +746,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netxen_nic_disable_int(adapter);
if (adapter->irq)
free_irq(adapter->irq, adapter);
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
init_firmware_done++;
netxen_free_hw_resources(adapter);
......@@ -776,13 +769,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
}
}
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
vfree(adapter->cmd_buf_arr);
pci_disable_device(pdev);
if (adapter->portnum == 0) {
if (init_firmware_done) {
i = 100;
......@@ -833,12 +821,19 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
}
}
if (adapter->irq)
free_irq(adapter->irq, adapter);
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
iounmap(adapter->ahw.db_base);
iounmap(adapter->ahw.pci_base0);
iounmap(adapter->ahw.pci_base1);
iounmap(adapter->ahw.pci_base2);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_netdev(netdev);
......
......@@ -556,7 +556,6 @@ static int gelic_net_stop(struct net_device *netdev)
{
struct gelic_net_card *card = netdev_priv(netdev);
netif_poll_disable(netdev);
netif_stop_queue(netdev);
/* turn off DMA, force end */
......
......@@ -1178,9 +1178,9 @@ qeth_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr,
char *buf)
{
if (proto == QETH_PROT_IPV4)
return qeth_ipaddr4_to_string(addr, buf);
qeth_ipaddr4_to_string(addr, buf);
else if (proto == QETH_PROT_IPV6)
return qeth_ipaddr6_to_string(addr, buf);
qeth_ipaddr6_to_string(addr, buf);
}
static inline int
......
......@@ -561,7 +561,7 @@ qeth_set_offline(struct ccwgroup_device *cgdev)
}
static int
qeth_wait_for_threads(struct qeth_card *card, unsigned long threads);
qeth_threads_running(struct qeth_card *card, unsigned long threads);
static void
......@@ -576,8 +576,7 @@ qeth_remove_device(struct ccwgroup_device *cgdev)
if (!card)
return;
if (qeth_wait_for_threads(card, 0xffffffff))
return;
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (cgdev->state == CCWGROUP_ONLINE){
card->use_hard_stop = 1;
......@@ -1542,8 +1541,13 @@ qeth_idx_write_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
card = CARD_FROM_CDEV(channel->ccwdev);
if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
PRINT_ERR("IDX_ACTIVATE on write channel device %s: negative "
"reply\n", CARD_WDEV_ID(card));
if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
"adapter exclusively used by another host\n",
CARD_WDEV_ID(card));
else
PRINT_ERR("IDX_ACTIVATE on write channel device %s: "
"negative reply\n", CARD_WDEV_ID(card));
goto out;
}
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
......@@ -1597,8 +1601,13 @@ qeth_idx_read_cb(struct qeth_channel *channel, struct qeth_cmd_buffer *iob)
goto out;
}
if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
PRINT_ERR("IDX_ACTIVATE on read channel device %s: negative "
"reply\n", CARD_RDEV_ID(card));
if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
"adapter exclusively used by another host\n",
CARD_RDEV_ID(card));
else
PRINT_ERR("IDX_ACTIVATE on read channel device %s: "
"negative reply\n", CARD_RDEV_ID(card));
goto out;
}
......@@ -2496,7 +2505,7 @@ qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
struct iphdr *ip_hdr;
QETH_DBF_TEXT(trace,5,"skbfktr");
skb_set_mac_header(skb, -QETH_FAKE_LL_LEN_TR);
skb_set_mac_header(skb, (int)-QETH_FAKE_LL_LEN_TR);
/* this is a fake ethernet header */
fake_hdr = tr_hdr(skb);
......@@ -2804,13 +2813,16 @@ qeth_queue_input_buffer(struct qeth_card *card, int index)
if (newcount < count) {
/* we are in memory shortage so we switch back to
traditional skb allocation and drop packages */
if (atomic_cmpxchg(&card->force_alloc_skb, 0, 1))
printk(KERN_WARNING
"qeth: switch to alloc skb\n");
if (!atomic_read(&card->force_alloc_skb) &&
net_ratelimit())
PRINT_WARN("Switch to alloc skb\n");
atomic_set(&card->force_alloc_skb, 3);
count = newcount;
} else {
if (atomic_cmpxchg(&card->force_alloc_skb, 1, 0))
printk(KERN_WARNING "qeth: switch to sg\n");
if ((atomic_read(&card->force_alloc_skb) == 1) &&
net_ratelimit())
PRINT_WARN("Switch to sg\n");
atomic_add_unless(&card->force_alloc_skb, -1, 0);
}
/*
......@@ -3354,10 +3366,12 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
while (i > 0)
kfree(card->qdio.out_qs[--i]);
kfree(card->qdio.out_qs);
card->qdio.out_qs = NULL;
out_freepool:
qeth_free_buffer_pool(card);
out_freeinq:
kfree(card->qdio.in_q);
card->qdio.in_q = NULL;
out_nomem:
atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
return -ENOMEM;
......@@ -3373,16 +3387,20 @@ qeth_free_qdio_buffers(struct qeth_card *card)
QETH_QDIO_UNINITIALIZED)
return;
kfree(card->qdio.in_q);
card->qdio.in_q = NULL;
/* inbound buffer pool */
qeth_free_buffer_pool(card);
/* free outbound qdio_qs */
for (i = 0; i < card->qdio.no_out_queues; ++i){
if (card->qdio.out_qs) {
for (i = 0; i < card->qdio.no_out_queues; ++i) {
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
qeth_clear_output_buffer(card->qdio.out_qs[i],
&card->qdio.out_qs[i]->bufs[j]);
kfree(card->qdio.out_qs[i]);
}
kfree(card->qdio.out_qs);
card->qdio.out_qs = NULL;
}
}
static void
......@@ -3393,7 +3411,7 @@ qeth_clear_qdio_buffers(struct qeth_card *card)
QETH_DBF_TEXT(trace, 2, "clearqdbf");
/* clear outbound buffers to free skbs */
for (i = 0; i < card->qdio.no_out_queues; ++i)
if (card->qdio.out_qs[i]){
if (card->qdio.out_qs && card->qdio.out_qs[i]) {
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
qeth_clear_output_buffer(card->qdio.out_qs[i],
&card->qdio.out_qs[i]->bufs[j]);
......@@ -4553,6 +4571,53 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr,
return elements_needed;
}
static void qeth_tx_csum(struct sk_buff *skb)
{
int tlen;
if (skb->protocol == htons(ETH_P_IP)) {
tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
switch (ip_hdr(skb)->protocol) {
case IPPROTO_TCP:
tcp_hdr(skb)->check = 0;
tcp_hdr(skb)->check = csum_tcpudp_magic(
ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
tlen, ip_hdr(skb)->protocol,
skb_checksum(skb, skb_transport_offset(skb),
tlen, 0));
break;
case IPPROTO_UDP:
udp_hdr(skb)->check = 0;
udp_hdr(skb)->check = csum_tcpudp_magic(
ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
tlen, ip_hdr(skb)->protocol,
skb_checksum(skb, skb_transport_offset(skb),
tlen, 0));
break;
}
} else if (skb->protocol == htons(ETH_P_IPV6)) {
switch (ipv6_hdr(skb)->nexthdr) {
case IPPROTO_TCP:
tcp_hdr(skb)->check = 0;
tcp_hdr(skb)->check = csum_ipv6_magic(
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
ipv6_hdr(skb)->payload_len,
ipv6_hdr(skb)->nexthdr,
skb_checksum(skb, skb_transport_offset(skb),
ipv6_hdr(skb)->payload_len, 0));
break;
case IPPROTO_UDP:
udp_hdr(skb)->check = 0;
udp_hdr(skb)->check = csum_ipv6_magic(
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
ipv6_hdr(skb)->payload_len,
ipv6_hdr(skb)->nexthdr,
skb_checksum(skb, skb_transport_offset(skb),
ipv6_hdr(skb)->payload_len, 0));
break;
}
}
}
static int
qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
......@@ -4638,12 +4703,22 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
elements_needed += elems;
}
if ((large_send == QETH_LARGE_SEND_NO) &&
(skb->ip_summed == CHECKSUM_PARTIAL))
qeth_tx_csum(new_skb);
if (card->info.type != QETH_CARD_TYPE_IQD)
rc = qeth_do_send_packet(card, queue, new_skb, hdr,
elements_needed, ctx);
else
else {
if ((skb->protocol == htons(ETH_P_ARP)) &&
(card->dev->flags & IFF_NOARP)) {
__qeth_free_new_skb(skb, new_skb);
return -EPERM;
}
rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
elements_needed, ctx);
}
if (!rc) {
card->stats.tx_packets++;
card->stats.tx_bytes += tx_bytes;
......@@ -6385,20 +6460,18 @@ qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
static u32
qeth_ethtool_get_tx_csum(struct net_device *dev)
{
/* We may need to say that we support tx csum offload if
* we do EDDP or TSO. There are discussions going on to
* enforce rules in the stack and in ethtool that make
* SG and TSO depend on HW_CSUM. At the moment there are
* no such rules....
* If we say yes here, we have to checksum outbound packets
* any time. */
return 0;
return (dev->features & NETIF_F_HW_CSUM) != 0;
}
static int
qeth_ethtool_set_tx_csum(struct net_device *dev, u32 data)
{
return -EINVAL;
if (data)
dev->features |= NETIF_F_HW_CSUM;
else
dev->features &= ~NETIF_F_HW_CSUM;
return 0;
}
static u32
......@@ -7412,7 +7485,8 @@ qeth_start_ipa_tso(struct qeth_card *card)
}
if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)){
card->options.large_send = QETH_LARGE_SEND_NO;
card->dev->features &= ~ (NETIF_F_TSO | NETIF_F_SG);
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
NETIF_F_HW_CSUM);
}
return rc;
}
......@@ -7552,22 +7626,26 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
card->options.large_send = type;
switch (card->options.large_send) {
case QETH_LARGE_SEND_EDDP:
card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
NETIF_F_HW_CSUM;
break;
case QETH_LARGE_SEND_TSO:
if (qeth_is_supported(card, IPA_OUTBOUND_TSO)){
card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
NETIF_F_HW_CSUM;
} else {
PRINT_WARN("TSO not supported on %s. "
"large_send set to 'no'.\n",
card->dev->name);
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
NETIF_F_HW_CSUM);
card->options.large_send = QETH_LARGE_SEND_NO;
rc = -EOPNOTSUPP;
}
break;
default: /* includes QETH_LARGE_SEND_NO */
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
NETIF_F_HW_CSUM);
break;
}
if (card->state == CARD_STATE_UP)
......
......@@ -565,6 +565,7 @@ extern unsigned char IDX_ACTIVATE_WRITE[];
#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer+0x20)
#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08]&3)==2)
#define QETH_IDX_REPLY_LEVEL(buffer) (buffer+0x12)
#define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
#define PDU_ENCAPSULATION(buffer) \
(buffer + *(buffer + (*(buffer+0x0b)) + \
......
......@@ -1760,10 +1760,10 @@ qeth_remove_device_attributes(struct device *dev)
{
struct qeth_card *card = dev->driver_data;
if (card->info.type == QETH_CARD_TYPE_OSN)
return sysfs_remove_group(&dev->kobj,
&qeth_osn_device_attr_group);
if (card->info.type == QETH_CARD_TYPE_OSN) {
sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group);
return;
}
sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment