diff options
Diffstat (limited to 'drivers')
114 files changed, 1306 insertions, 977 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 8f5565b..fa9bb74 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3067,7 +3067,10 @@ static int raw_cmd_copyout(int cmd, void __user *param, int ret; while (ptr) { - ret = copy_to_user(param, ptr, sizeof(*ptr)); + struct floppy_raw_cmd cmd = *ptr; + cmd.next = NULL; + cmd.kernel_data = NULL; + ret = copy_to_user(param, &cmd, sizeof(cmd)); if (ret) return -EFAULT; param += sizeof(struct floppy_raw_cmd); @@ -3121,10 +3124,11 @@ loop: return -ENOMEM; *rcmd = ptr; ret = copy_from_user(ptr, param, sizeof(*ptr)); - if (ret) - return -EFAULT; ptr->next = NULL; ptr->buffer_length = 0; + ptr->kernel_data = NULL; + if (ret) + return -EFAULT; param += sizeof(struct floppy_raw_cmd); if (ptr->cmd_count > 33) /* the command may now also take up the space @@ -3140,7 +3144,6 @@ loop: for (i = 0; i < 16; i++) ptr->reply[i] = 0; ptr->resultcode = 0; - ptr->kernel_data = NULL; if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { if (ptr->length <= 0) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index be571fe..a83b57e 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x04CA, 0x3004) }, { USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3006) }, + { USB_DEVICE(0x04CA, 0x3007) }, { USB_DEVICE(0x04CA, 0x3008) }, { USB_DEVICE(0x04CA, 0x300b) }, { USB_DEVICE(0x0930, 0x0219) }, @@ -131,6 +132,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f338b0c..a7dfbf9 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -152,6 +152,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, @@ -1485,10 +1486,8 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_BCM92035) hdev->setup = btusb_setup_bcm92035; - if (id->driver_info & BTUSB_INTEL) { - usb_enable_autosuspend(data->udev); + if (id->driver_info & BTUSB_INTEL) hdev->setup = btusb_setup_intel; - } /* Interface numbers are hardcoded in the specification */ data->isoc = usb_ifnum_to_if(data->udev, 1); diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index a535c7b..4223912 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -100,6 +100,8 @@ void __init vexpress_osc_of_setup(struct device_node *node) struct clk *clk; u32 range[2]; + vexpress_sysreg_of_early_init(); + osc = kzalloc(sizeof(*osc), GFP_KERNEL); if (!osc) return; diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 148d707..ccdd4c7 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -369,7 +369,7 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, return; /* Can only change if privileged. */ - if (!capable(CAP_NET_ADMIN)) { + if (!__netlink_ns_capable(nsp, &init_user_ns, CAP_NET_ADMIN)) { err = EPERM; goto out; } diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index d86196c..24c28e3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -106,7 +106,7 @@ config AT91_ADC Say yes here to build support for Atmel AT91 ADC. config EXYNOS_ADC - bool "Exynos ADC driver support" + tristate "Exynos ADC driver support" depends on OF help Core support for the ADC block found in the Samsung EXYNOS series @@ -114,7 +114,7 @@ config EXYNOS_ADC this resource. config LP8788_ADC - bool "LP8788 ADC driver" + tristate "LP8788 ADC driver" depends on MFD_LP8788 help Say yes here to build support for TI LP8788 ADC. diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index d25b262..affa93f 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -344,7 +344,7 @@ static int exynos_adc_probe(struct platform_device *pdev) exynos_adc_hw_init(info); - ret = of_platform_populate(np, exynos_adc_match, NULL, &pdev->dev); + ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev); if (ret < 0) { dev_err(&pdev->dev, "failed adding child nodes\n"); goto err_of_populate; @@ -353,7 +353,7 @@ static int exynos_adc_probe(struct platform_device *pdev) return 0; err_of_populate: - device_for_each_child(&pdev->dev, NULL, + device_for_each_child(&indio_dev->dev, NULL, exynos_adc_remove_devices); regulator_disable(info->vdd); clk_disable_unprepare(info->clk); @@ -369,7 +369,7 @@ static int exynos_adc_remove(struct platform_device *pdev) struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct exynos_adc *info = iio_priv(indio_dev); - device_for_each_child(&pdev->dev, NULL, + device_for_each_child(&indio_dev->dev, NULL, exynos_adc_remove_devices); regulator_disable(info->vdd); clk_disable_unprepare(info->clk); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index cb9f96b..d8ad606 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -660,6 +660,7 @@ static int inv_mpu_probe(struct i2c_client *client, { struct inv_mpu6050_state *st; struct iio_dev *indio_dev; + struct inv_mpu6050_platform_data *pdata; int result; if (!i2c_check_functionality(client->adapter, @@ -672,8 +673,10 @@ static int inv_mpu_probe(struct i2c_client *client, st = iio_priv(indio_dev); st->client = client; - st->plat_data = *(struct inv_mpu6050_platform_data - *)dev_get_platdata(&client->dev); + pdata = (struct inv_mpu6050_platform_data + *)dev_get_platdata(&client->dev); + if (pdata) + st->plat_data = *pdata; /* power is turned on inside check chip type*/ result = inv_check_and_setup_chip(st, id); if (result) diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index 51dae91..96d1df0 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -425,7 +425,7 @@ afterXPR: if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp - 1]); } - AfterMOX1: + AfterMOX1: ; #endif } } diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 7ff473c..8d659e6 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -431,7 +431,7 @@ int ubiblock_create(struct ubi_volume_info *vi) * Create one workqueue per volume (per registered block device). * Rembember workqueues are cheap, they're not threads. */ - dev->wq = alloc_workqueue(gd->disk_name, 0, 0); + dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name); if (!dev->wq) goto out_free_queue; INIT_WORK(&dev->work, ubiblock_do_work); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 02317c1..0f3425d 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -671,6 +671,8 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); self_check_in_wl_tree(ubi, e, &ubi->free); + ubi->free_count--; + ubi_assert(ubi->free_count >= 0); rb_erase(&e->u.rb, &ubi->free); return e; @@ -684,6 +686,9 @@ int ubi_wl_get_peb(struct ubi_device *ubi) peb = __wl_get_peb(ubi); spin_unlock(&ubi->wl_lock); + if (peb < 0) + return peb; + err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset, ubi->peb_size - ubi->vid_hdr_aloffset); if (err) { @@ -1068,6 +1073,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, /* Give the unused PEB back */ wl_tree_add(e2, &ubi->free); + ubi->free_count++; goto out_cancel; } self_check_in_wl_tree(ubi, e1, &ubi->used); diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 0e8b268..5f6babc 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -534,7 +534,7 @@ static ssize_t bonding_show_min_links(struct device *d, { struct bonding *bond = to_bond(d); - return sprintf(buf, "%d\n", bond->params.min_links); + return sprintf(buf, "%u\n", bond->params.min_links); } static ssize_t bonding_store_min_links(struct device *d, diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig index 61ffc12..8ab7103 100644 --- a/drivers/net/can/c_can/Kconfig +++ b/drivers/net/can/c_can/Kconfig @@ -14,6 +14,13 @@ config CAN_C_CAN_PLATFORM SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com) boards like am335x, dm814x, dm813x and dm811x. +config CAN_C_CAN_STRICT_FRAME_ORDERING + bool "Force a strict RX CAN frame order (may cause frame loss)" + ---help--- + The RX split buffer prevents packet reordering but can cause packet + loss. Only enable this option when you accept to lose CAN frames + in favour of getting the received CAN frames in the correct order. + config CAN_C_CAN_PCI tristate "Generic PCI Bus based C_CAN/D_CAN driver" depends on PCI diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index a5c8dcf..a2ca820 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -60,6 +60,8 @@ #define CONTROL_IE BIT(1) #define CONTROL_INIT BIT(0) +#define CONTROL_IRQMSK (CONTROL_EIE | CONTROL_IE | CONTROL_SIE) + /* test register */ #define TEST_RX BIT(7) #define TEST_TX1 BIT(6) @@ -108,11 +110,14 @@ #define IF_COMM_CONTROL BIT(4) #define IF_COMM_CLR_INT_PND BIT(3) #define IF_COMM_TXRQST BIT(2) +#define IF_COMM_CLR_NEWDAT IF_COMM_TXRQST #define IF_COMM_DATAA BIT(1) #define IF_COMM_DATAB BIT(0) -#define IF_COMM_ALL (IF_COMM_MASK | IF_COMM_ARB | \ - IF_COMM_CONTROL | IF_COMM_TXRQST | \ - IF_COMM_DATAA | IF_COMM_DATAB) + +/* TX buffer setup */ +#define IF_COMM_TX (IF_COMM_ARB | IF_COMM_CONTROL | \ + IF_COMM_TXRQST | \ + IF_COMM_DATAA | IF_COMM_DATAB) /* For the low buffers we clear the interrupt bit, but keep newdat */ #define IF_COMM_RCV_LOW (IF_COMM_MASK | IF_COMM_ARB | \ @@ -120,12 +125,19 @@ IF_COMM_DATAA | IF_COMM_DATAB) /* For the high buffers we clear the interrupt bit and newdat */ -#define IF_COMM_RCV_HIGH (IF_COMM_RCV_LOW | IF_COMM_TXRQST) +#define IF_COMM_RCV_HIGH (IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT) + + +/* Receive setup of message objects */ +#define IF_COMM_RCV_SETUP (IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL) + +/* Invalidation of message objects */ +#define IF_COMM_INVAL (IF_COMM_ARB | IF_COMM_CONTROL) /* IFx arbitration */ -#define IF_ARB_MSGVAL BIT(15) -#define IF_ARB_MSGXTD BIT(14) -#define IF_ARB_TRANSMIT BIT(13) +#define IF_ARB_MSGVAL BIT(31) +#define IF_ARB_MSGXTD BIT(30) +#define IF_ARB_TRANSMIT BIT(29) /* IFx message control */ #define IF_MCONT_NEWDAT BIT(15) @@ -139,19 +151,17 @@ #define IF_MCONT_EOB BIT(7) #define IF_MCONT_DLC_MASK 0xf +#define IF_MCONT_RCV (IF_MCONT_RXIE | IF_MCONT_UMASK) +#define IF_MCONT_RCV_EOB (IF_MCONT_RCV | IF_MCONT_EOB) + +#define IF_MCONT_TX (IF_MCONT_TXIE | IF_MCONT_EOB) + /* * Use IF1 for RX and IF2 for TX */ #define IF_RX 0 #define IF_TX 1 -/* status interrupt */ -#define STATUS_INTERRUPT 0x8000 - -/* global interrupt masks */ -#define ENABLE_ALL_INTERRUPTS 1 -#define DISABLE_ALL_INTERRUPTS 0 - /* minimum timeout for checking BUSY status */ #define MIN_TIMEOUT_VALUE 6 @@ -171,6 +181,7 @@ enum c_can_lec_type { LEC_BIT0_ERROR, LEC_CRC_ERROR, LEC_UNUSED, + LEC_MASK = LEC_UNUSED, }; /* @@ -226,143 +237,115 @@ static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) priv->raminit(priv, enable); } -static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) +static void c_can_irq_control(struct c_can_priv *priv, bool enable) { - return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) + - C_CAN_MSG_OBJ_TX_FIRST; -} - -static inline int get_tx_echo_msg_obj(int txecho) -{ - return (txecho & C_CAN_NEXT_MSG_OBJ_MASK) + C_CAN_MSG_OBJ_TX_FIRST; -} - -static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index) -{ - u32 val = priv->read_reg(priv, index); - val |= ((u32) priv->read_reg(priv, index + 1)) << 16; - return val; -} - -static void c_can_enable_all_interrupts(struct c_can_priv *priv, - int enable) -{ - unsigned int cntrl_save = priv->read_reg(priv, - C_CAN_CTRL_REG); + u32 ctrl = priv->read_reg(priv, C_CAN_CTRL_REG) & ~CONTROL_IRQMSK; if (enable) - cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE); - else - cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE); + ctrl |= CONTROL_IRQMSK; - priv->write_reg(priv, C_CAN_CTRL_REG, cntrl_save); + priv->write_reg(priv, C_CAN_CTRL_REG, ctrl); } -static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface) +static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj) { - int count = MIN_TIMEOUT_VALUE; + struct c_can_priv *priv = netdev_priv(dev); + int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface); + + priv->write_reg(priv, reg + 1, cmd); + priv->write_reg(priv, reg, obj); - while (count && priv->read_reg(priv, - C_CAN_IFACE(COMREQ_REG, iface)) & - IF_COMR_BUSY) { - count--; + for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) { + if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY)) + return; udelay(1); } + netdev_err(dev, "Updating object timed out\n"); - if (!count) - return 1; +} - return 0; +static inline void c_can_object_get(struct net_device *dev, int iface, + u32 obj, u32 cmd) +{ + c_can_obj_update(dev, iface, cmd, obj); } -static inline void c_can_object_get(struct net_device *dev, - int iface, int objno, int mask) +static inline void c_can_object_put(struct net_device *dev, int iface, + u32 obj, u32 cmd) { - struct c_can_priv *priv = netdev_priv(dev); + c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj); +} - /* - * As per specs, after writting the message object number in the - * IF command request register the transfer b/w interface - * register and message RAM must be complete in 6 CAN-CLK - * period. - */ - priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface), - IFX_WRITE_LOW_16BIT(mask)); - priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface), - IFX_WRITE_LOW_16BIT(objno)); +/* + * Note: According to documentation clearing TXIE while MSGVAL is set + * is not allowed, but works nicely on C/DCAN. And that lowers the I/O + * load significantly. + */ +static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj) +{ + struct c_can_priv *priv = netdev_priv(dev); - if (c_can_msg_obj_is_busy(priv, iface)) - netdev_err(dev, "timed out in object get\n"); + priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); + c_can_object_put(dev, iface, obj, IF_COMM_INVAL); } -static inline void c_can_object_put(struct net_device *dev, - int iface, int objno, int mask) +static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj) { struct c_can_priv *priv = netdev_priv(dev); - /* - * As per specs, after writting the message object number in the - * IF command request register the transfer b/w interface - * register and message RAM must be complete in 6 CAN-CLK - * period. - */ - priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface), - (IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask))); - priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface), - IFX_WRITE_LOW_16BIT(objno)); - - if (c_can_msg_obj_is_busy(priv, iface)) - netdev_err(dev, "timed out in object put\n"); + priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); + priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0); + c_can_inval_tx_object(dev, iface, obj); } -static void c_can_write_msg_object(struct net_device *dev, - int iface, struct can_frame *frame, int objno) +static void c_can_setup_tx_object(struct net_device *dev, int iface, + struct can_frame *frame, int idx) { - int i; - u16 flags = 0; - unsigned int id; struct c_can_priv *priv = netdev_priv(dev); - - if (!(frame->can_id & CAN_RTR_FLAG)) - flags |= IF_ARB_TRANSMIT; + u16 ctrl = IF_MCONT_TX | frame->can_dlc; + bool rtr = frame->can_id & CAN_RTR_FLAG; + u32 arb = IF_ARB_MSGVAL; + int i; if (frame->can_id & CAN_EFF_FLAG) { - id = frame->can_id & CAN_EFF_MASK; - flags |= IF_ARB_MSGXTD; - } else - id = ((frame->can_id & CAN_SFF_MASK) << 18); + arb |= frame->can_id & CAN_EFF_MASK; + arb |= IF_ARB_MSGXTD; + } else { + arb |= (frame->can_id & CAN_SFF_MASK) << 18; + } + + if (!rtr) + arb |= IF_ARB_TRANSMIT; - flags |= IF_ARB_MSGVAL; + /* + * If we change the DIR bit, we need to invalidate the buffer + * first, i.e. clear the MSGVAL flag in the arbiter. + */ + if (rtr != (bool)test_bit(idx, &priv->tx_dir)) { + u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST; + + c_can_inval_msg_object(dev, iface, obj); + change_bit(idx, &priv->tx_dir); + } + + priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), arb); + priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), arb >> 16); - priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), - IFX_WRITE_LOW_16BIT(id)); - priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), flags | - IFX_WRITE_HIGH_16BIT(id)); + priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); for (i = 0; i < frame->can_dlc; i += 2) { priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2, frame->data[i] | (frame->data[i + 1] << 8)); } - - /* enable interrupt for this message object */ - priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), - IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB | - frame->can_dlc); - c_can_object_put(dev, iface, objno, IF_COMM_ALL); } static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev, - int iface, - int ctrl_mask) + int iface) { int i; - struct c_can_priv *priv = netdev_priv(dev); - for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) { - priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), - ctrl_mask & ~IF_MCONT_NEWDAT); - c_can_object_put(dev, iface, i, IF_COMM_CONTROL); - } + for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) + c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT); } static int c_can_handle_lost_msg_obj(struct net_device *dev, @@ -377,6 +360,9 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev, priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); + stats->rx_errors++; + stats->rx_over_errors++; + /* create an error msg */ skb = alloc_can_err_skb(dev, &frame); if (unlikely(!skb)) @@ -384,22 +370,18 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev, frame->can_id |= CAN_ERR_CRTL; frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - stats->rx_errors++; - stats->rx_over_errors++; netif_receive_skb(skb); return 1; } -static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) +static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl) { - u16 flags, data; - int i; - unsigned int val; - struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; - struct sk_buff *skb; + struct c_can_priv *priv = netdev_priv(dev); struct can_frame *frame; + struct sk_buff *skb; + u32 arb, data; skb = alloc_can_skb(dev, &frame); if (!skb) { @@ -409,115 +391,82 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) frame->can_dlc = get_can_dlc(ctrl & 0x0F); - flags = priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)); - val = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface)) | - (flags << 16); + arb = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface)); + arb |= priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)) << 16; - if (flags & IF_ARB_MSGXTD) - frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG; + if (arb & IF_ARB_MSGXTD) + frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG; else - frame->can_id = (val >> 18) & CAN_SFF_MASK; + frame->can_id = (arb >> 18) & CAN_SFF_MASK; - if (flags & IF_ARB_TRANSMIT) + if (arb & IF_ARB_TRANSMIT) { frame->can_id |= CAN_RTR_FLAG; - else { - for (i = 0; i < frame->can_dlc; i += 2) { - data = priv->read_reg(priv, - C_CAN_IFACE(DATA1_REG, iface) + i / 2); + } else { + int i, dreg = C_CAN_IFACE(DATA1_REG, iface); + + for (i = 0; i < frame->can_dlc; i += 2, dreg ++) { + data = priv->read_reg(priv, dreg); frame->data[i] = data; frame->data[i + 1] = data >> 8; } } - netif_receive_skb(skb); - stats->rx_packets++; stats->rx_bytes += frame->can_dlc; + + netif_receive_skb(skb); return 0; } static void c_can_setup_receive_object(struct net_device *dev, int iface, - int objno, unsigned int mask, - unsigned int id, unsigned int mcont) + u32 obj, u32 mask, u32 id, u32 mcont) { struct c_can_priv *priv = netdev_priv(dev); - priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), - IFX_WRITE_LOW_16BIT(mask)); - - /* According to C_CAN documentation, the reserved bit - * in IFx_MASK2 register is fixed 1 - */ - priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), - IFX_WRITE_HIGH_16BIT(mask) | BIT(13)); + mask |= BIT(29); + priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), mask); + priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), mask >> 16); - priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), - IFX_WRITE_LOW_16BIT(id)); - priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), - (IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id))); + id |= IF_ARB_MSGVAL; + priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), id); + priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), id >> 16); priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont); - c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); - - netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, - c_can_read_reg32(priv, C_CAN_MSGVAL1_REG)); -} - -static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno) -{ - struct c_can_priv *priv = netdev_priv(dev); - - priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0); - priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0); - priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0); - - c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL); - - netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, - c_can_read_reg32(priv, C_CAN_MSGVAL1_REG)); -} - -static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno) -{ - int val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG); - - /* - * as transmission request register's bit n-1 corresponds to - * message object n, we need to handle the same properly. - */ - if (val & (1 << (objno - 1))) - return 1; - - return 0; + c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP); } static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, - struct net_device *dev) + struct net_device *dev) { - u32 msg_obj_no; - struct c_can_priv *priv = netdev_priv(dev); struct can_frame *frame = (struct can_frame *)skb->data; + struct c_can_priv *priv = netdev_priv(dev); + u32 idx, obj; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; - - spin_lock_bh(&priv->xmit_lock); - msg_obj_no = get_tx_next_msg_obj(priv); - - /* prepare message object for transmission */ - c_can_write_msg_object(dev, IF_TX, frame, msg_obj_no); - priv->dlc[msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST] = frame->can_dlc; - can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); - /* - * we have to stop the queue in case of a wrap around or - * if the next TX message object is still in use + * This is not a FIFO. C/D_CAN sends out the buffers + * prioritized. The lowest buffer number wins. */ - priv->tx_next++; - if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) || - (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0) + idx = fls(atomic_read(&priv->tx_active)); + obj = idx + C_CAN_MSG_OBJ_TX_FIRST; + + /* If this is the last buffer, stop the xmit queue */ + if (idx == C_CAN_MSG_OBJ_TX_NUM - 1) netif_stop_queue(dev); - spin_unlock_bh(&priv->xmit_lock); + /* + * Store the message in the interface so we can call + * can_put_echo_skb(). We must do this before we enable + * transmit as we might race against do_tx(). + */ + c_can_setup_tx_object(dev, IF_TX, frame, idx); + priv->dlc[idx] = frame->can_dlc; + can_put_echo_skb(skb, dev, idx); + + /* Update the active bits */ + atomic_add((1 << idx), &priv->tx_active); + /* Start transmission */ + c_can_object_put(dev, IF_TX, obj, IF_COMM_TX); return NETDEV_TX_OK; } @@ -594,11 +543,10 @@ static void c_can_configure_msg_objects(struct net_device *dev) /* setup receive message objects */ for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) - c_can_setup_receive_object(dev, IF_RX, i, 0, 0, - (IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB); + c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV); c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0, - IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK); + IF_MCONT_RCV_EOB); } /* @@ -612,30 +560,22 @@ static int c_can_chip_config(struct net_device *dev) struct c_can_priv *priv = netdev_priv(dev); /* enable automatic retransmission */ - priv->write_reg(priv, C_CAN_CTRL_REG, - CONTROL_ENABLE_AR); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { /* loopback + silent mode : useful for hot self-test */ - priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | - CONTROL_SIE | CONTROL_IE | CONTROL_TEST); - priv->write_reg(priv, C_CAN_TEST_REG, - TEST_LBACK | TEST_SILENT); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); + priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT); } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { /* loopback mode : useful for self-test function */ - priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | - CONTROL_SIE | CONTROL_IE | CONTROL_TEST); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK); } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { /* silent mode : bus-monitoring mode */ - priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | - CONTROL_SIE | CONTROL_IE | CONTROL_TEST); + priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT); - } else - /* normal mode*/ - priv->write_reg(priv, C_CAN_CTRL_REG, - CONTROL_EIE | CONTROL_SIE | CONTROL_IE); + } /* configure message objects */ c_can_configure_msg_objects(dev); @@ -643,6 +583,11 @@ static int c_can_chip_config(struct net_device *dev) /* set a `lec` value so that we can check for updates later */ priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); + /* Clear all internal status */ + atomic_set(&priv->tx_active, 0); + priv->rxmasked = 0; + priv->tx_dir = 0; + /* set bittiming params */ return c_can_set_bittiming(dev); } @@ -657,13 +602,11 @@ static int c_can_start(struct net_device *dev) if (err) return err; - priv->can.state = CAN_STATE_ERROR_ACTIVE; - - /* reset tx helper pointers */ - priv->tx_next = priv->tx_echo = 0; + /* Setup the command for new messages */ + priv->comm_rcv_high = priv->type != BOSCH_D_CAN ? + IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH; - /* enable status change, error and module interrupts */ - c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); + priv->can.state = CAN_STATE_ERROR_ACTIVE; return 0; } @@ -672,15 +615,13 @@ static void c_can_stop(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); - /* disable all interrupts */ - c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); - - /* set the state as STOPPED */ + c_can_irq_control(priv, false); priv->can.state = CAN_STATE_STOPPED; } static int c_can_set_mode(struct net_device *dev, enum can_mode mode) { + struct c_can_priv *priv = netdev_priv(dev); int err; switch (mode) { @@ -689,6 +630,7 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode) if (err) return err; netif_wake_queue(dev); + c_can_irq_control(priv, true); break; default: return -EOPNOTSUPP; @@ -724,42 +666,29 @@ static int c_can_get_berr_counter(const struct net_device *dev, return err; } -/* - * priv->tx_echo holds the number of the oldest can_frame put for - * transmission into the hardware, but not yet ACKed by the CAN tx - * complete IRQ. - * - * We iterate from priv->tx_echo to priv->tx_next and check if the - * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted packet, stop looking for more. - */ static void c_can_do_tx(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; - u32 val, obj, pkts = 0, bytes = 0; - - spin_lock_bh(&priv->xmit_lock); + u32 idx, obj, pkts = 0, bytes = 0, pend, clr; - for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { - obj = get_tx_echo_msg_obj(priv->tx_echo); - val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG); + clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG); - if (val & (1 << (obj - 1))) - break; - - can_get_echo_skb(dev, obj - C_CAN_MSG_OBJ_TX_FIRST); - bytes += priv->dlc[obj - C_CAN_MSG_OBJ_TX_FIRST]; + while ((idx = ffs(pend))) { + idx--; + pend &= ~(1 << idx); + obj = idx + C_CAN_MSG_OBJ_TX_FIRST; + c_can_inval_tx_object(dev, IF_RX, obj); + can_get_echo_skb(dev, idx); + bytes += priv->dlc[idx]; pkts++; - c_can_inval_msg_object(dev, IF_TX, obj); } - /* restart queue if wrap-up or if queue stalled on last pkt */ - if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) || - ((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0)) - netif_wake_queue(dev); + /* Clear the bits in the tx_active mask */ + atomic_sub(clr, &priv->tx_active); - spin_unlock_bh(&priv->xmit_lock); + if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1))) + netif_wake_queue(dev); if (pkts) { stats->tx_bytes += bytes; @@ -800,18 +729,42 @@ static u32 c_can_adjust_pending(u32 pend) return pend & ~((1 << lasts) - 1); } +static inline void c_can_rx_object_get(struct net_device *dev, + struct c_can_priv *priv, u32 obj) +{ +#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING + if (obj < C_CAN_MSG_RX_LOW_LAST) + c_can_object_get(dev, IF_RX, obj, IF_COMM_RCV_LOW); + else +#endif + c_can_object_get(dev, IF_RX, obj, priv->comm_rcv_high); +} + +static inline void c_can_rx_finalize(struct net_device *dev, + struct c_can_priv *priv, u32 obj) +{ +#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING + if (obj < C_CAN_MSG_RX_LOW_LAST) + priv->rxmasked |= BIT(obj - 1); + else if (obj == C_CAN_MSG_RX_LOW_LAST) { + priv->rxmasked = 0; + /* activate all lower message objects */ + c_can_activate_all_lower_rx_msg_obj(dev, IF_RX); + } +#endif + if (priv->type != BOSCH_D_CAN) + c_can_object_get(dev, IF_RX, obj, IF_COMM_CLR_NEWDAT); +} + static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, u32 pend, int quota) { - u32 pkts = 0, ctrl, obj, mcmd; + u32 pkts = 0, ctrl, obj; while ((obj = ffs(pend)) && quota > 0) { pend &= ~BIT(obj - 1); - mcmd = obj < C_CAN_MSG_RX_LOW_LAST ? - IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH; - - c_can_object_get(dev, IF_RX, obj, mcmd); + c_can_rx_object_get(dev, priv, obj); ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX)); if (ctrl & IF_MCONT_MSGLST) { @@ -833,9 +786,7 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, /* read the data from the message object */ c_can_read_msg_object(dev, IF_RX, ctrl); - if (obj == C_CAN_MSG_RX_LOW_LAST) - /* activate all lower message objects */ - c_can_activate_all_lower_rx_msg_obj(dev, IF_RX, ctrl); + c_can_rx_finalize(dev, priv, obj); pkts++; quota--; @@ -844,6 +795,16 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, return pkts; } +static inline u32 c_can_get_pending(struct c_can_priv *priv) +{ + u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG); + +#ifdef CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING + pend &= ~priv->rxmasked; +#endif + return pend; +} + /* * theory of operation: * @@ -853,6 +814,8 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, * has arrived. To work-around this issue, we keep two groups of message * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT. * + * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = y + * * To ensure in-order frame reception we use the following * approach while re-activating a message object to receive further * frames: @@ -865,6 +828,14 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv, * - if the current message object number is greater than * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of * only this message object. + * + * This can cause packet loss! + * + * If CONFIG_CAN_C_CAN_STRICT_FRAME_ORDERING = n + * + * We clear the newdat bit right away. + * + * This can result in packet reordering when the readout is slow. */ static int c_can_do_rx_poll(struct net_device *dev, int quota) { @@ -880,7 +851,7 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) while (quota > 0) { if (!pend) { - pend = priv->read_reg(priv, C_CAN_INTPND1_REG); + pend = c_can_get_pending(priv); if (!pend) break; /* @@ -905,12 +876,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) return pkts; } -static inline int c_can_has_and_handle_berr(struct c_can_priv *priv) -{ - return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && - (priv->current_status & LEC_UNUSED); -} - static int c_can_handle_state_change(struct net_device *dev, enum c_can_bus_error_types error_type) { @@ -922,6 +887,26 @@ static int c_can_handle_state_change(struct net_device *dev, struct sk_buff *skb; struct can_berr_counter bec; + switch (error_type) { + case C_CAN_ERROR_WARNING: + /* error warning state */ + priv->can.can_stats.error_warning++; + priv->can.state = CAN_STATE_ERROR_WARNING; + break; + case C_CAN_ERROR_PASSIVE: + /* error passive state */ + priv->can.can_stats.error_passive++; + priv->can.state = CAN_STATE_ERROR_PASSIVE; + break; + case C_CAN_BUS_OFF: + /* bus-off state */ + priv->can.state = CAN_STATE_BUS_OFF; + can_bus_off(dev); + break; + default: + break; + } + /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) @@ -935,8 +920,6 @@ static int c_can_handle_state_change(struct net_device *dev, switch (error_type) { case C_CAN_ERROR_WARNING: /* error warning state */ - priv->can.can_stats.error_warning++; - priv->can.state = CAN_STATE_ERROR_WARNING; cf->can_id |= CAN_ERR_CRTL; cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : @@ -947,8 +930,6 @@ static int c_can_handle_state_change(struct net_device *dev, break; case C_CAN_ERROR_PASSIVE: /* error passive state */ - priv->can.can_stats.error_passive++; - priv->can.state = CAN_STATE_ERROR_PASSIVE; cf->can_id |= CAN_ERR_CRTL; if (rx_err_passive) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; @@ -960,22 +941,16 @@ static int c_can_handle_state_change(struct net_device *dev, break; case C_CAN_BUS_OFF: /* bus-off state */ - priv->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; - /* - * disable all interrupts in bus-off mode to ensure that - * the CPU is not hogged down - */ - c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); can_bus_off(dev); break; default: break; } - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); return 1; } @@ -996,6 +971,13 @@ static int c_can_handle_bus_err(struct net_device *dev, if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) return 0; + if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) + return 0; + + /* common for all type of bus errors */ + priv->can.can_stats.bus_error++; + stats->rx_errors++; + /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) @@ -1005,10 +987,6 @@ static int c_can_handle_bus_err(struct net_device *dev, * check for 'last error code' which tells us the * type of the last error to occur on the CAN bus */ - - /* common for all type of bus errors */ - priv->can.can_stats.bus_error++; - stats->rx_errors++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; cf->data[2] |= CAN_ERR_PROT_UNSPEC; @@ -1043,95 +1021,64 @@ static int c_can_handle_bus_err(struct net_device *dev, break; } - /* set a `lec` value so that we can check for updates later */ - priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); - - netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; - + netif_receive_skb(skb); return 1; } static int c_can_poll(struct napi_struct *napi, int quota) { - u16 irqstatus; - int lec_type = 0; - int work_done = 0; struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); + u16 curr, last = priv->last_status; + int work_done = 0; - irqstatus = priv->irqstatus; - if (!irqstatus) - goto end; + priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG); + /* Ack status on C_CAN. D_CAN is self clearing */ + if (priv->type != BOSCH_D_CAN) + priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); - /* status events have the highest priority */ - if (irqstatus == STATUS_INTERRUPT) { - priv->current_status = priv->read_reg(priv, - C_CAN_STS_REG); - - /* handle Tx/Rx events */ - if (priv->current_status & STATUS_TXOK) - priv->write_reg(priv, C_CAN_STS_REG, - priv->current_status & ~STATUS_TXOK); - - if (priv->current_status & STATUS_RXOK) - priv->write_reg(priv, C_CAN_STS_REG, - priv->current_status & ~STATUS_RXOK); - - /* handle state changes */ - if ((priv->current_status & STATUS_EWARN) && - (!(priv->last_status & STATUS_EWARN))) { - netdev_dbg(dev, "entered error warning state\n"); - work_done += c_can_handle_state_change(dev, - C_CAN_ERROR_WARNING); - } - if ((priv->current_status & STATUS_EPASS) && - (!(priv->last_status & STATUS_EPASS))) { - netdev_dbg(dev, "entered error passive state\n"); - work_done += c_can_handle_state_change(dev, - C_CAN_ERROR_PASSIVE); - } - if ((priv->current_status & STATUS_BOFF) && - (!(priv->last_status & STATUS_BOFF))) { - netdev_dbg(dev, "entered bus off state\n"); - work_done += c_can_handle_state_change(dev, - C_CAN_BUS_OFF); - } + /* handle state changes */ + if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) { + netdev_dbg(dev, "entered error warning state\n"); + work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING); + } - /* handle bus recovery events */ - if ((!(priv->current_status & STATUS_BOFF)) && - (priv->last_status & STATUS_BOFF)) { - netdev_dbg(dev, "left bus off state\n"); - priv->can.state = CAN_STATE_ERROR_ACTIVE; - } - if ((!(priv->current_status & STATUS_EPASS)) && - (priv->last_status & STATUS_EPASS)) { - netdev_dbg(dev, "left error passive state\n"); - priv->can.state = CAN_STATE_ERROR_ACTIVE; - } + if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) { + netdev_dbg(dev, "entered error passive state\n"); + work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); + } + + if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) { + netdev_dbg(dev, "entered bus off state\n"); + work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF); + goto end; + } - priv->last_status = priv->current_status; - - /* handle lec errors on the bus */ - lec_type = c_can_has_and_handle_berr(priv); - if (lec_type) - work_done += c_can_handle_bus_err(dev, lec_type); - } else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) && - (irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) { - /* handle events corresponding to receive message objects */ - work_done += c_can_do_rx_poll(dev, (quota - work_done)); - } else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) && - (irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) { - /* handle events corresponding to transmit message objects */ - c_can_do_tx(dev); + /* handle bus recovery events */ + if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) { + netdev_dbg(dev, "left bus off state\n"); + priv->can.state = CAN_STATE_ERROR_ACTIVE; + } + if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) { + netdev_dbg(dev, "left error passive state\n"); + priv->can.state = CAN_STATE_ERROR_ACTIVE; } + /* handle lec errors on the bus */ + work_done += c_can_handle_bus_err(dev, curr & LEC_MASK); + + /* Handle Tx/Rx events. We do this unconditionally */ + work_done += c_can_do_rx_poll(dev, (quota - work_done)); + c_can_do_tx(dev); + end: if (work_done < quota) { napi_complete(napi); - /* enable all IRQs */ - c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); + /* enable all IRQs if we are not in bus off state */ + if (priv->can.state != CAN_STATE_BUS_OFF) + c_can_irq_control(priv, true); } return work_done; @@ -1142,12 +1089,11 @@ static irqreturn_t c_can_isr(int irq, void *dev_id) struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - priv->irqstatus = priv->read_reg(priv, C_CAN_INT_REG); - if (!priv->irqstatus) + if (!priv->read_reg(priv, C_CAN_INT_REG)) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ - c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); + c_can_irq_control(priv, false); napi_schedule(&priv->napi); return IRQ_HANDLED; @@ -1184,6 +1130,8 @@ static int c_can_open(struct net_device *dev) can_led_event(dev, CAN_LED_EVENT_OPEN); napi_enable(&priv->napi); + /* enable status change, error and module interrupts */ + c_can_irq_control(priv, true); netif_start_queue(dev); return 0; @@ -1226,7 +1174,6 @@ struct net_device *alloc_c_can_dev(void) return NULL; priv = netdev_priv(dev); - spin_lock_init(&priv->xmit_lock); netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT); priv->dev = dev; @@ -1281,6 +1228,7 @@ int c_can_power_up(struct net_device *dev) u32 val; unsigned long time_out; struct c_can_priv *priv = netdev_priv(dev); + int ret; if (!(dev->flags & IFF_UP)) return 0; @@ -1307,7 +1255,11 @@ int c_can_power_up(struct net_device *dev) if (time_after(jiffies, time_out)) return -ETIMEDOUT; - return c_can_start(dev); + ret = c_can_start(dev); + if (!ret) + c_can_irq_control(priv, true); + + return ret; } EXPORT_SYMBOL_GPL(c_can_power_up); #endif diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index faa8404..c56f1b1 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -22,14 +22,6 @@ #ifndef C_CAN_H #define C_CAN_H -/* - * IFx register masks: - * allow easy operation on 16-bit registers when the - * argument is 32-bit instead - */ -#define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF) -#define IFX_WRITE_HIGH_16BIT(x) (((x) & 0xFFFF0000) >> 16) - /* message object split */ #define C_CAN_NO_OF_OBJECTS 32 #define C_CAN_MSG_OBJ_RX_NUM 16 @@ -45,8 +37,6 @@ #define C_CAN_MSG_OBJ_RX_SPLIT 9 #define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1) - -#define C_CAN_NEXT_MSG_OBJ_MASK (C_CAN_MSG_OBJ_TX_NUM - 1) #define RECEIVE_OBJECT_BITS 0x0000ffff enum reg { @@ -183,23 +173,20 @@ struct c_can_priv { struct napi_struct napi; struct net_device *dev; struct device *device; - spinlock_t xmit_lock; - int tx_object; - int current_status; + atomic_t tx_active; + unsigned long tx_dir; int last_status; u16 (*read_reg) (struct c_can_priv *priv, enum reg index); void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val); void __iomem *base; const u16 *regs; - unsigned long irq_flags; /* for request_irq() */ - unsigned int tx_next; - unsigned int tx_echo; void *priv; /* for board-specific data */ - u16 irqstatus; enum c_can_dev_id type; u32 __iomem *raminit_ctrlreg; - unsigned int instance; + int instance; void (*raminit) (const struct c_can_priv *priv, bool enable); + u32 comm_rcv_high; + u32 rxmasked; u32 dlc[C_CAN_MSG_OBJ_TX_NUM]; }; diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index bce0be5..fe5f630 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -84,8 +84,11 @@ static int c_can_pci_probe(struct pci_dev *pdev, goto out_disable_device; } - pci_set_master(pdev); - pci_enable_msi(pdev); + ret = pci_enable_msi(pdev); + if (!ret) { + dev_info(&pdev->dev, "MSI enabled\n"); + pci_set_master(pdev); + } addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); if (!addr) { @@ -132,6 +135,8 @@ static int c_can_pci_probe(struct pci_dev *pdev, goto out_free_c_can; } + priv->type = c_can_pci_data->type; + /* Configure access to registers */ switch (c_can_pci_data->reg_align) { case C_CAN_REG_ALIGN_32: diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 806d927..1df0b32 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -222,7 +222,7 @@ static int c_can_plat_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->raminit_ctrlreg) || (int)priv->instance < 0) + if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0) dev_info(&pdev->dev, "control memory is not used for raminit\n"); else priv->raminit = c_can_hw_raminit; diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index c7a2604..e318e87 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -256,7 +256,7 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt, /* Check if the CAN device has bit-timing parameters */ if (!btc) - return -ENOTSUPP; + return -EOPNOTSUPP; /* * Depending on the given can_bittiming parameter structure the CAN diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index df136a2..014695d 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -46,6 +46,7 @@ static int clk[MAXDEV]; static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; +static spinlock_t indirect_lock[MAXDEV]; /* lock for indirect access mode */ module_param_array(port, ulong, NULL, S_IRUGO); MODULE_PARM_DESC(port, "I/O port number"); @@ -101,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv, static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv, int reg) { - unsigned long base = (unsigned long)priv->reg_base; + unsigned long flags, base = (unsigned long)priv->reg_base; + u8 readval; + spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags); outb(reg, base); - return inb(base + 1); + readval = inb(base + 1); + spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags); + + return readval; } static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv, int reg, u8 val) { - unsigned long base = (unsigned long)priv->reg_base; + unsigned long flags, base = (unsigned long)priv->reg_base; + spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags); outb(reg, base); outb(val, base + 1); + spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags); } static int sja1000_isa_probe(struct platform_device *pdev) @@ -169,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) if (iosize == SJA1000_IOSIZE_INDIRECT) { priv->read_reg = sja1000_isa_port_read_reg_indirect; priv->write_reg = sja1000_isa_port_write_reg_indirect; + spin_lock_init(&indirect_lock[idx]); } else { priv->read_reg = sja1000_isa_port_read_reg; priv->write_reg = sja1000_isa_port_write_reg; @@ -198,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); + dev->dev_id = idx; err = register_sja1000dev(dev); if (err) { diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index f5b16e0..dcf9196 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -322,13 +322,13 @@ static void slcan_write_wakeup(struct tty_struct *tty) if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) return; - spin_lock(&sl->lock); + spin_lock_bh(&sl->lock); if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ sl->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); netif_wake_queue(sl->dev); return; } @@ -336,7 +336,7 @@ static void slcan_write_wakeup(struct tty_struct *tty) actual = tty->ops->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); } /* Send a can_frame to a TTY queue. */ diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig index 80c1ab7..fdddba5 100644 --- a/drivers/net/ethernet/altera/Kconfig +++ b/drivers/net/ethernet/altera/Kconfig @@ -1,5 +1,6 @@ config ALTERA_TSE tristate "Altera Triple-Speed Ethernet MAC support" + depends on HAS_DMA select PHYLIB ---help--- This driver supports the Altera Triple-Speed (TSE) Ethernet MAC. diff --git a/drivers/net/ethernet/altera/altera_msgdma.c b/drivers/net/ethernet/altera/altera_msgdma.c index 3df1866..4d1f2fd 100644 --- a/drivers/net/ethernet/altera/altera_msgdma.c +++ b/drivers/net/ethernet/altera/altera_msgdma.c @@ -18,6 +18,7 @@ #include "altera_utils.h" #include "altera_tse.h" #include "altera_msgdmahw.h" +#include "altera_msgdma.h" /* No initialization work to do for MSGDMA */ int msgdma_initialize(struct altera_tse_private *priv) @@ -29,6 +30,10 @@ void msgdma_uninitialize(struct altera_tse_private *priv) { } +void msgdma_start_rxdma(struct altera_tse_private *priv) +{ +} + void msgdma_reset(struct altera_tse_private *priv) { int counter; @@ -154,7 +159,7 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv) /* Put buffer to the mSGDMA RX FIFO */ -int msgdma_add_rx_desc(struct altera_tse_private *priv, +void msgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *rxbuffer) { struct msgdma_extended_desc *desc = priv->rx_dma_desc; @@ -175,7 +180,6 @@ int msgdma_add_rx_desc(struct altera_tse_private *priv, iowrite32(0, &desc->burst_seq_num); iowrite32(0x00010001, &desc->stride); iowrite32(control, &desc->control); - return 1; } /* status is returned on upper 16 bits, diff --git a/drivers/net/ethernet/altera/altera_msgdma.h b/drivers/net/ethernet/altera/altera_msgdma.h index 7f0f5bf..42cf61c 100644 --- a/drivers/net/ethernet/altera/altera_msgdma.h +++ b/drivers/net/ethernet/altera/altera_msgdma.h @@ -25,10 +25,11 @@ void msgdma_disable_txirq(struct altera_tse_private *); void msgdma_clear_rxirq(struct altera_tse_private *); void msgdma_clear_txirq(struct altera_tse_private *); u32 msgdma_tx_completions(struct altera_tse_private *); -int msgdma_add_rx_desc(struct altera_tse_private *, struct tse_buffer *); +void msgdma_add_rx_desc(struct altera_tse_private *, struct tse_buffer *); int msgdma_tx_buffer(struct altera_tse_private *, struct tse_buffer *); u32 msgdma_rx_status(struct altera_tse_private *); int msgdma_initialize(struct altera_tse_private *); void msgdma_uninitialize(struct altera_tse_private *); +void msgdma_start_rxdma(struct altera_tse_private *); #endif /* __ALTERA_MSGDMA_H__ */ diff --git a/drivers/net/ethernet/altera/altera_sgdma.c b/drivers/net/ethernet/altera/altera_sgdma.c index 0ee9663..9ce8630 100644 --- a/drivers/net/ethernet/altera/altera_sgdma.c +++ b/drivers/net/ethernet/altera/altera_sgdma.c @@ -20,15 +20,15 @@ #include "altera_sgdmahw.h" #include "altera_sgdma.h" -static void sgdma_descrip(struct sgdma_descrip *desc, - struct sgdma_descrip *ndesc, - dma_addr_t ndesc_phys, - dma_addr_t raddr, - dma_addr_t waddr, - u16 length, - int generate_eop, - int rfixed, - int wfixed); +static void sgdma_setup_descrip(struct sgdma_descrip *desc, + struct sgdma_descrip *ndesc, + dma_addr_t ndesc_phys, + dma_addr_t raddr, + dma_addr_t waddr, + u16 length, + int generate_eop, + int rfixed, + int wfixed); static int sgdma_async_write(struct altera_tse_private *priv, struct sgdma_descrip *desc); @@ -64,11 +64,15 @@ queue_rx_peekhead(struct altera_tse_private *priv); int sgdma_initialize(struct altera_tse_private *priv) { - priv->txctrlreg = SGDMA_CTRLREG_ILASTD; + priv->txctrlreg = SGDMA_CTRLREG_ILASTD | + SGDMA_CTRLREG_INTEN; priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP | + SGDMA_CTRLREG_INTEN | SGDMA_CTRLREG_ILASTD; + priv->sgdmadesclen = sizeof(struct sgdma_descrip); + INIT_LIST_HEAD(&priv->txlisthd); INIT_LIST_HEAD(&priv->rxlisthd); @@ -93,6 +97,16 @@ int sgdma_initialize(struct altera_tse_private *priv) return -EINVAL; } + /* Initialize descriptor memory to all 0's, sync memory to cache */ + memset(priv->tx_dma_desc, 0, priv->txdescmem); + memset(priv->rx_dma_desc, 0, priv->rxdescmem); + + dma_sync_single_for_device(priv->device, priv->txdescphys, + priv->txdescmem, DMA_TO_DEVICE); + + dma_sync_single_for_device(priv->device, priv->rxdescphys, + priv->rxdescmem, DMA_TO_DEVICE); + return 0; } @@ -130,26 +144,23 @@ void sgdma_reset(struct altera_tse_private *priv) iowrite32(0, &prxsgdma->control); } +/* For SGDMA, interrupts remain enabled after initially enabling, + * so no need to provide implementations for abstract enable + * and disable + */ + void sgdma_enable_rxirq(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr; - priv->rxctrlreg |= SGDMA_CTRLREG_INTEN; - tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN); } void sgdma_enable_txirq(struct altera_tse_private *priv) { - struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr; - priv->txctrlreg |= SGDMA_CTRLREG_INTEN; - tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN); } -/* for SGDMA, RX interrupts remain enabled after enabling */ void sgdma_disable_rxirq(struct altera_tse_private *priv) { } -/* for SGDMA, TX interrupts remain enabled after enabling */ void sgdma_disable_txirq(struct altera_tse_private *priv) { } @@ -184,15 +195,15 @@ int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer) if (sgdma_txbusy(priv)) return 0; - sgdma_descrip(cdesc, /* current descriptor */ - ndesc, /* next descriptor */ - sgdma_txphysaddr(priv, ndesc), - buffer->dma_addr, /* address of packet to xmit */ - 0, /* write addr 0 for tx dma */ - buffer->len, /* length of packet */ - SGDMA_CONTROL_EOP, /* Generate EOP */ - 0, /* read fixed */ - SGDMA_CONTROL_WR_FIXED); /* Generate SOP */ + sgdma_setup_descrip(cdesc, /* current descriptor */ + ndesc, /* next descriptor */ + sgdma_txphysaddr(priv, ndesc), + buffer->dma_addr, /* address of packet to xmit */ + 0, /* write addr 0 for tx dma */ + buffer->len, /* length of packet */ + SGDMA_CONTROL_EOP, /* Generate EOP */ + 0, /* read fixed */ + SGDMA_CONTROL_WR_FIXED); /* Generate SOP */ pktstx = sgdma_async_write(priv, cdesc); @@ -219,11 +230,15 @@ u32 sgdma_tx_completions(struct altera_tse_private *priv) return ready; } -int sgdma_add_rx_desc(struct altera_tse_private *priv, - struct tse_buffer *rxbuffer) +void sgdma_start_rxdma(struct altera_tse_private *priv) +{ + sgdma_async_read(priv); +} + +void sgdma_add_rx_desc(struct altera_tse_private *priv, + struct tse_buffer *rxbuffer) { queue_rx(priv, rxbuffer); - return sgdma_async_read(priv); } /* status is returned on upper 16 bits, @@ -240,28 +255,52 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) unsigned int pktstatus = 0; struct tse_buffer *rxbuffer = NULL; - dma_sync_single_for_cpu(priv->device, - priv->rxdescphys, - priv->rxdescmem, - DMA_BIDIRECTIONAL); + u32 sts = ioread32(&csr->status); desc = &base[0]; - if ((ioread32(&csr->status) & SGDMA_STSREG_EOP) || - (desc->status & SGDMA_STATUS_EOP)) { + if (sts & SGDMA_STSREG_EOP) { + dma_sync_single_for_cpu(priv->device, + priv->rxdescphys, + priv->sgdmadesclen, + DMA_FROM_DEVICE); + pktlength = desc->bytes_xferred; pktstatus = desc->status & 0x3f; rxstatus = pktstatus; rxstatus = rxstatus << 16; rxstatus |= (pktlength & 0xffff); - desc->status = 0; + if (rxstatus) { + desc->status = 0; - rxbuffer = dequeue_rx(priv); - if (rxbuffer == NULL) - netdev_err(priv->dev, - "sgdma rx and rx queue empty!\n"); + rxbuffer = dequeue_rx(priv); + if (rxbuffer == NULL) + netdev_info(priv->dev, + "sgdma rx and rx queue empty!\n"); + + /* Clear control */ + iowrite32(0, &csr->control); + /* clear status */ + iowrite32(0xf, &csr->status); - /* kick the rx sgdma after reaping this descriptor */ + /* kick the rx sgdma after reaping this descriptor */ + pktsrx = sgdma_async_read(priv); + + } else { + /* If the SGDMA indicated an end of packet on recv, + * then it's expected that the rxstatus from the + * descriptor is non-zero - meaning a valid packet + * with a nonzero length, or an error has been + * indicated. if not, then all we can do is signal + * an error and return no packet received. Most likely + * there is a system design error, or an error in the + * underlying kernel (cache or cache management problem) + */ + netdev_err(priv->dev, + "SGDMA RX Error Info: %x, %x, %x\n", + sts, desc->status, rxstatus); + } + } else if (sts == 0) { pktsrx = sgdma_async_read(priv); } @@ -270,15 +309,15 @@ u32 sgdma_rx_status(struct altera_tse_private *priv) /* Private functions */ -static void sgdma_descrip(struct sgdma_descrip *desc, - struct sgdma_descrip *ndesc, - dma_addr_t ndesc_phys, - dma_addr_t raddr, - dma_addr_t waddr, - u16 length, - int generate_eop, - int rfixed, - int wfixed) +static void sgdma_setup_descrip(struct sgdma_descrip *desc, + struct sgdma_descrip *ndesc, + dma_addr_t ndesc_phys, + dma_addr_t raddr, + dma_addr_t waddr, + u16 length, + int generate_eop, + int rfixed, + int wfixed) { /* Clear the next descriptor as not owned by hardware */ u32 ctrl = ndesc->control; @@ -319,35 +358,29 @@ static int sgdma_async_read(struct altera_tse_private *priv) struct sgdma_descrip *cdesc = &descbase[0]; struct sgdma_descrip *ndesc = &descbase[1]; - unsigned int sts = ioread32(&csr->status); struct tse_buffer *rxbuffer = NULL; if (!sgdma_rxbusy(priv)) { rxbuffer = queue_rx_peekhead(priv); - if (rxbuffer == NULL) + if (rxbuffer == NULL) { + netdev_err(priv->dev, "no rx buffers available\n"); return 0; - - sgdma_descrip(cdesc, /* current descriptor */ - ndesc, /* next descriptor */ - sgdma_rxphysaddr(priv, ndesc), - 0, /* read addr 0 for rx dma */ - rxbuffer->dma_addr, /* write addr for rx dma */ - 0, /* read 'til EOP */ - 0, /* EOP: NA for rx dma */ - 0, /* read fixed: NA for rx dma */ - 0); /* SOP: NA for rx DMA */ - - /* clear control and status */ - iowrite32(0, &csr->control); - - /* If status available, clear those bits */ - if (sts & 0xf) - iowrite32(0xf, &csr->status); + } + + sgdma_setup_descrip(cdesc, /* current descriptor */ + ndesc, /* next descriptor */ + sgdma_rxphysaddr(priv, ndesc), + 0, /* read addr 0 for rx dma */ + rxbuffer->dma_addr, /* write addr for rx dma */ + 0, /* read 'til EOP */ + 0, /* EOP: NA for rx dma */ + 0, /* read fixed: NA for rx dma */ + 0); /* SOP: NA for rx DMA */ dma_sync_single_for_device(priv->device, priv->rxdescphys, - priv->rxdescmem, - DMA_BIDIRECTIONAL); + priv->sgdmadesclen, + DMA_TO_DEVICE); iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)), &csr->next_descrip); @@ -374,7 +407,7 @@ static int sgdma_async_write(struct altera_tse_private *priv, iowrite32(0x1f, &csr->status); dma_sync_single_for_device(priv->device, priv->txdescphys, - priv->txdescmem, DMA_TO_DEVICE); + priv->sgdmadesclen, DMA_TO_DEVICE); iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)), &csr->next_descrip); diff --git a/drivers/net/ethernet/altera/altera_sgdma.h b/drivers/net/ethernet/altera/altera_sgdma.h index 07d4717..584977e 100644 --- a/drivers/net/ethernet/altera/altera_sgdma.h +++ b/drivers/net/ethernet/altera/altera_sgdma.h @@ -26,10 +26,11 @@ void sgdma_clear_rxirq(struct altera_tse_private *); void sgdma_clear_txirq(struct altera_tse_private *); int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *); u32 sgdma_tx_completions(struct altera_tse_private *); -int sgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *); +void sgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *); void sgdma_status(struct altera_tse_private *); u32 sgdma_rx_status(struct altera_tse_private *); int sgdma_initialize(struct altera_tse_private *); void sgdma_uninitialize(struct altera_tse_private *); +void sgdma_start_rxdma(struct altera_tse_private *); #endif /* __ALTERA_SGDMA_H__ */ diff --git a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h index 8feeed0..465c4aa 100644 --- a/drivers/net/ethernet/altera/altera_tse.h +++ b/drivers/net/ethernet/altera/altera_tse.h @@ -58,6 +58,8 @@ /* MAC function configuration default settings */ #define ALTERA_TSE_TX_IPG_LENGTH 12 +#define ALTERA_TSE_PAUSE_QUANTA 0xffff + #define GET_BIT_VALUE(v, bit) (((v) >> (bit)) & 0x1) /* MAC Command_Config Register Bit Definitions @@ -390,10 +392,11 @@ struct altera_dmaops { void (*clear_rxirq)(struct altera_tse_private *); int (*tx_buffer)(struct altera_tse_private *, struct tse_buffer *); u32 (*tx_completions)(struct altera_tse_private *); - int (*add_rx_desc)(struct altera_tse_private *, struct tse_buffer *); + void (*add_rx_desc)(struct altera_tse_private *, struct tse_buffer *); u32 (*get_rx_status)(struct altera_tse_private *); int (*init_dma)(struct altera_tse_private *); void (*uninit_dma)(struct altera_tse_private *); + void (*start_rxdma)(struct altera_tse_private *); }; /* This structure is private to each device. @@ -453,6 +456,7 @@ struct altera_tse_private { u32 rxctrlreg; dma_addr_t rxdescphys; dma_addr_t txdescphys; + size_t sgdmadesclen; struct list_head txlisthd; struct list_head rxlisthd; diff --git a/drivers/net/ethernet/altera/altera_tse_ethtool.c b/drivers/net/ethernet/altera/altera_tse_ethtool.c index 319ca74..76133ca 100644 --- a/drivers/net/ethernet/altera/altera_tse_ethtool.c +++ b/drivers/net/ethernet/altera/altera_tse_ethtool.c @@ -77,7 +77,7 @@ static void tse_get_drvinfo(struct net_device *dev, struct altera_tse_private *priv = netdev_priv(dev); u32 rev = ioread32(&priv->mac_dev->megacore_revision); - strcpy(info->driver, "Altera TSE MAC IP Driver"); + strcpy(info->driver, "altera_tse"); strcpy(info->version, "v8.0"); snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d", rev & 0xFFFF, (rev & 0xFFFF0000) >> 16); @@ -185,6 +185,12 @@ static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs, * how to do any special formatting of this data. * This version number will need to change if and * when this register table is changed. + * + * version[31:0] = 1: Dump the first 128 TSE Registers + * Upper bits are all 0 by default + * + * Upper 16-bits will indicate feature presence for + * Ethtool register decoding in future version. */ regs->version = 1; diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index c70a29e..e44a4ae 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -224,6 +224,7 @@ static int tse_init_rx_buffer(struct altera_tse_private *priv, dev_kfree_skb_any(rxbuffer->skb); return -EINVAL; } + rxbuffer->dma_addr &= (dma_addr_t)~3; rxbuffer->len = len; return 0; } @@ -425,9 +426,10 @@ static int tse_rx(struct altera_tse_private *priv, int limit) priv->dev->stats.rx_bytes += pktlength; entry = next_entry; + + tse_rx_refill(priv); } - tse_rx_refill(priv); return count; } @@ -520,7 +522,6 @@ static irqreturn_t altera_isr(int irq, void *dev_id) struct altera_tse_private *priv; unsigned long int flags; - if (unlikely(!dev)) { pr_err("%s: invalid dev pointer\n", __func__); return IRQ_NONE; @@ -868,13 +869,13 @@ static int init_mac(struct altera_tse_private *priv) /* Disable RX/TX shift 16 for alignment of all received frames on 16-bit * start address */ - tse_clear_bit(&mac->rx_cmd_stat, ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16); + tse_set_bit(&mac->rx_cmd_stat, ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16); tse_clear_bit(&mac->tx_cmd_stat, ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 | ALTERA_TSE_TX_CMD_STAT_OMIT_CRC); /* Set the MAC options */ cmd = ioread32(&mac->command_config); - cmd |= MAC_CMDCFG_PAD_EN; /* Padding Removal on Receive */ + cmd &= ~MAC_CMDCFG_PAD_EN; /* No padding Removal on Receive */ cmd &= ~MAC_CMDCFG_CRC_FWD; /* CRC Removal */ cmd |= MAC_CMDCFG_RX_ERR_DISC; /* Automatically discard frames * with CRC errors @@ -882,8 +883,16 @@ static int init_mac(struct altera_tse_private *priv) cmd |= MAC_CMDCFG_CNTL_FRM_ENA; cmd &= ~MAC_CMDCFG_TX_ENA; cmd &= ~MAC_CMDCFG_RX_ENA; + + /* Default speed and duplex setting, full/100 */ + cmd &= ~MAC_CMDCFG_HD_ENA; + cmd &= ~MAC_CMDCFG_ETH_SPEED; + cmd &= ~MAC_CMDCFG_ENA_10; + iowrite32(cmd, &mac->command_config); + iowrite32(ALTERA_TSE_PAUSE_QUANTA, &mac->pause_quanta); + if (netif_msg_hw(priv)) dev_dbg(priv->device, "MAC post-initialization: CMD_CONFIG = 0x%08x\n", cmd); @@ -1085,17 +1094,19 @@ static int tse_open(struct net_device *dev) spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags); - /* Start MAC Rx/Tx */ - spin_lock(&priv->mac_cfg_lock); - tse_set_mac(priv, true); - spin_unlock(&priv->mac_cfg_lock); - if (priv->phydev) phy_start(priv->phydev); napi_enable(&priv->napi); netif_start_queue(dev); + priv->dmaops->start_rxdma(priv); + + /* Start MAC Rx/Tx */ + spin_lock(&priv->mac_cfg_lock); + tse_set_mac(priv, true); + spin_unlock(&priv->mac_cfg_lock); + return 0; tx_request_irq_error: @@ -1167,7 +1178,6 @@ static struct net_device_ops altera_tse_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; - static int request_and_map(struct platform_device *pdev, const char *name, struct resource **res, void __iomem **ptr) { @@ -1235,7 +1245,7 @@ static int altera_tse_probe(struct platform_device *pdev) /* Get the mapped address to the SGDMA descriptor memory */ ret = request_and_map(pdev, "s1", &dma_res, &descmap); if (ret) - goto out_free; + goto err_free_netdev; /* Start of that memory is for transmit descriptors */ priv->tx_dma_desc = descmap; @@ -1254,24 +1264,24 @@ static int altera_tse_probe(struct platform_device *pdev) if (upper_32_bits(priv->rxdescmem_busaddr)) { dev_dbg(priv->device, "SGDMA bus addresses greater than 32-bits\n"); - goto out_free; + goto err_free_netdev; } if (upper_32_bits(priv->txdescmem_busaddr)) { dev_dbg(priv->device, "SGDMA bus addresses greater than 32-bits\n"); - goto out_free; + goto err_free_netdev; } } else if (priv->dmaops && priv->dmaops->altera_dtype == ALTERA_DTYPE_MSGDMA) { ret = request_and_map(pdev, "rx_resp", &dma_res, &priv->rx_dma_resp); if (ret) - goto out_free; + goto err_free_netdev; ret = request_and_map(pdev, "tx_desc", &dma_res, &priv->tx_dma_desc); if (ret) - goto out_free; + goto err_free_netdev; priv->txdescmem = resource_size(dma_res); priv->txdescmem_busaddr = dma_res->start; @@ -1279,13 +1289,13 @@ static int altera_tse_probe(struct platform_device *pdev) ret = request_and_map(pdev, "rx_desc", &dma_res, &priv->rx_dma_desc); if (ret) - goto out_free; + goto err_free_netdev; priv->rxdescmem = resource_size(dma_res); priv->rxdescmem_busaddr = dma_res->start; } else { - goto out_free; + goto err_free_netdev; } if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) @@ -1294,26 +1304,26 @@ static int altera_tse_probe(struct platform_device *pdev) else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); else - goto out_free; + goto err_free_netdev; /* MAC address space */ ret = request_and_map(pdev, "control_port", &control_port, (void __iomem **)&priv->mac_dev); if (ret) - goto out_free; + goto err_free_netdev; /* xSGDMA Rx Dispatcher address space */ ret = request_and_map(pdev, "rx_csr", &dma_res, &priv->rx_dma_csr); if (ret) - goto out_free; + goto err_free_netdev; /* xSGDMA Tx Dispatcher address space */ ret = request_and_map(pdev, "tx_csr", &dma_res, &priv->tx_dma_csr); if (ret) - goto out_free; + goto err_free_netdev; /* Rx IRQ */ @@ -1321,7 +1331,7 @@ static int altera_tse_probe(struct platform_device *pdev) if (priv->rx_irq == -ENXIO) { dev_err(&pdev->dev, "cannot obtain Rx IRQ\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } /* Tx IRQ */ @@ -1329,7 +1339,7 @@ static int altera_tse_probe(struct platform_device *pdev) if (priv->tx_irq == -ENXIO) { dev_err(&pdev->dev, "cannot obtain Tx IRQ\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } /* get FIFO depths from device tree */ @@ -1337,14 +1347,14 @@ static int altera_tse_probe(struct platform_device *pdev) &priv->rx_fifo_depth)) { dev_err(&pdev->dev, "cannot obtain rx-fifo-depth\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } if (of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &priv->rx_fifo_depth)) { dev_err(&pdev->dev, "cannot obtain tx-fifo-depth\n"); ret = -ENXIO; - goto out_free; + goto err_free_netdev; } /* get hash filter settings for this instance */ @@ -1393,7 +1403,7 @@ static int altera_tse_probe(struct platform_device *pdev) ((priv->phy_addr >= 0) && (priv->phy_addr < PHY_MAX_ADDR)))) { dev_err(&pdev->dev, "invalid phy-addr specified %d\n", priv->phy_addr); - goto out_free; + goto err_free_netdev; } /* Create/attach to MDIO bus */ @@ -1401,7 +1411,7 @@ static int altera_tse_probe(struct platform_device *pdev) atomic_add_return(1, &instance_count)); if (ret) - goto out_free; + goto err_free_netdev; /* initialize netdev */ ether_setup(ndev); @@ -1438,7 +1448,7 @@ static int altera_tse_probe(struct platform_device *pdev) ret = register_netdev(ndev); if (ret) { dev_err(&pdev->dev, "failed to register TSE net device\n"); - goto out_free_mdio; + goto err_register_netdev; } platform_set_drvdata(pdev, ndev); @@ -1455,13 +1465,16 @@ static int altera_tse_probe(struct platform_device *pdev) ret = init_phy(ndev); if (ret != 0) { netdev_err(ndev, "Cannot attach to PHY (error: %d)\n", ret); - goto out_free_mdio; + goto err_init_phy; } return 0; -out_free_mdio: +err_init_phy: + unregister_netdev(ndev); +err_register_netdev: + netif_napi_del(&priv->napi); altera_tse_mdio_destroy(ndev); -out_free: +err_free_netdev: free_netdev(ndev); return ret; } @@ -1496,6 +1509,7 @@ struct altera_dmaops altera_dtype_sgdma = { .get_rx_status = sgdma_rx_status, .init_dma = sgdma_initialize, .uninit_dma = sgdma_uninitialize, + .start_rxdma = sgdma_start_rxdma, }; struct altera_dmaops altera_dtype_msgdma = { @@ -1514,6 +1528,7 @@ struct altera_dmaops altera_dtype_msgdma = { .get_rx_status = msgdma_rx_status, .init_dma = msgdma_initialize, .uninit_dma = msgdma_uninitialize, + .start_rxdma = msgdma_start_rxdma, }; static struct of_device_id altera_tse_ids[] = { diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h index 928fac6..53f85bf 100644 --- a/drivers/net/ethernet/arc/emac.h +++ b/drivers/net/ethernet/arc/emac.h @@ -11,6 +11,7 @@ #include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/phy.h> +#include <linux/clk.h> /* STATUS and ENABLE Register bit masks */ #define TXINT_MASK (1<<0) /* Transmit interrupt */ @@ -131,6 +132,7 @@ struct arc_emac_priv { struct mii_bus *bus; void __iomem *regs; + struct clk *clk; struct napi_struct napi; struct net_device_stats stats; diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index eeecc29..d647a7d 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -574,6 +574,18 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } +static void arc_emac_set_address_internal(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + unsigned int addr_low, addr_hi; + + addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); + addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); + + arc_reg_set(priv, R_ADDRL, addr_low); + arc_reg_set(priv, R_ADDRH, addr_hi); +} + /** * arc_emac_set_address - Set the MAC address for this device. * @ndev: Pointer to net_device structure. @@ -587,9 +599,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) */ static int arc_emac_set_address(struct net_device *ndev, void *p) { - struct arc_emac_priv *priv = netdev_priv(ndev); struct sockaddr *addr = p; - unsigned int addr_low, addr_hi; if (netif_running(ndev)) return -EBUSY; @@ -599,11 +609,7 @@ static int arc_emac_set_address(struct net_device *ndev, void *p) memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); - addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); - addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); - - arc_reg_set(priv, R_ADDRL, addr_low); - arc_reg_set(priv, R_ADDRH, addr_hi); + arc_emac_set_address_internal(ndev); return 0; } @@ -643,13 +649,6 @@ static int arc_emac_probe(struct platform_device *pdev) return -ENODEV; } - /* Get CPU clock frequency from device tree */ - if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &clock_frequency)) { - dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); - return -EINVAL; - } - /* Get IRQ from device tree */ irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (!irq) { @@ -677,17 +676,36 @@ static int arc_emac_probe(struct platform_device *pdev) priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs); if (IS_ERR(priv->regs)) { err = PTR_ERR(priv->regs); - goto out; + goto out_netdev; } dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); + priv->clk = of_clk_get(pdev->dev.of_node, 0); + if (IS_ERR(priv->clk)) { + /* Get CPU clock frequency from device tree */ + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &clock_frequency)) { + dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); + err = -EINVAL; + goto out_netdev; + } + } else { + err = clk_prepare_enable(priv->clk); + if (err) { + dev_err(&pdev->dev, "failed to enable clock\n"); + goto out_clkget; + } + + clock_frequency = clk_get_rate(priv->clk); + } + id = arc_reg_get(priv, R_ID); /* Check for EMAC revision 5 or 7, magic number */ if (!(id == 0x0005fd02 || id == 0x0007fd02)) { dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); err = -ENODEV; - goto out; + goto out_clken; } dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); @@ -702,7 +720,7 @@ static int arc_emac_probe(struct platform_device *pdev) ndev->name, ndev); if (err) { dev_err(&pdev->dev, "could not allocate IRQ\n"); - goto out; + goto out_clken; } /* Get MAC address from device tree */ @@ -713,6 +731,7 @@ static int arc_emac_probe(struct platform_device *pdev) else eth_hw_addr_random(ndev); + arc_emac_set_address_internal(ndev); dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr); /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */ @@ -722,7 +741,7 @@ static int arc_emac_probe(struct platform_device *pdev) if (!priv->rxbd) { dev_err(&pdev->dev, "failed to allocate data buffers\n"); err = -ENOMEM; - goto out; + goto out_clken; } priv->txbd = priv->rxbd + RX_BD_NUM; @@ -734,7 +753,7 @@ static int arc_emac_probe(struct platform_device *pdev) err = arc_mdio_probe(pdev, priv); if (err) { dev_err(&pdev->dev, "failed to probe MII bus\n"); - goto out; + goto out_clken; } priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, @@ -742,7 +761,7 @@ static int arc_emac_probe(struct platform_device *pdev) if (!priv->phy_dev) { dev_err(&pdev->dev, "of_phy_connect() failed\n"); err = -ENODEV; - goto out; + goto out_mdio; } dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n", @@ -752,14 +771,25 @@ static int arc_emac_probe(struct platform_device *pdev) err = register_netdev(ndev); if (err) { - netif_napi_del(&priv->napi); dev_err(&pdev->dev, "failed to register network device\n"); - goto out; + goto out_netif_api; } return 0; -out: +out_netif_api: + netif_napi_del(&priv->napi); + phy_disconnect(priv->phy_dev); + priv->phy_dev = NULL; +out_mdio: + arc_mdio_remove(priv); +out_clken: + if (!IS_ERR(priv->clk)) + clk_disable_unprepare(priv->clk); +out_clkget: + if (!IS_ERR(priv->clk)) + clk_put(priv->clk); +out_netdev: free_netdev(ndev); return err; } @@ -774,6 +804,12 @@ static int arc_emac_remove(struct platform_device *pdev) arc_mdio_remove(priv); unregister_netdev(ndev); netif_napi_del(&priv->napi); + + if (!IS_ERR(priv->clk)) { + clk_disable_unprepare(priv->clk); + clk_put(priv->clk); + } + free_netdev(ndev); return 0; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index a78edac..b260913 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -13233,6 +13233,8 @@ static void __bnx2x_remove(struct pci_dev *pdev, iounmap(bp->doorbells); bnx2x_release_firmware(bp); + } else { + bnx2x_vf_pci_dealloc(bp); } bnx2x_free_mem_bp(bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 5c523b3..81cc2d9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -427,7 +427,9 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp, if (filter->add && filter->type == BNX2X_VF_FILTER_VLAN && (atomic_read(&bnx2x_vfq(vf, qid, vlan_count)) >= vf_vlan_rules_cnt(vf))) { - BNX2X_ERR("No credits for vlan\n"); + BNX2X_ERR("No credits for vlan [%d >= %d]\n", + atomic_read(&bnx2x_vfq(vf, qid, vlan_count)), + vf_vlan_rules_cnt(vf)); return -ENOMEM; } @@ -610,6 +612,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf, } /* add new mcasts */ + mcast.mcast_list_len = mc_num; rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_ADD); if (rc) BNX2X_ERR("Faled to add multicasts\n"); @@ -837,6 +840,29 @@ int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid) return 0; } +static void bnx2x_iov_re_set_vlan_filters(struct bnx2x *bp, + struct bnx2x_virtf *vf, + int new) +{ + int num = vf_vlan_rules_cnt(vf); + int diff = new - num; + bool rc = true; + + DP(BNX2X_MSG_IOV, "vf[%d] - %d vlan filter credits [previously %d]\n", + vf->abs_vfid, new, num); + + if (diff > 0) + rc = bp->vlans_pool.get(&bp->vlans_pool, diff); + else if (diff < 0) + rc = bp->vlans_pool.put(&bp->vlans_pool, -diff); + + if (rc) + vf_vlan_rules_cnt(vf) = new; + else + DP(BNX2X_MSG_IOV, "vf[%d] - Failed to configure vlan filter credits change\n", + vf->abs_vfid); +} + /* must be called after the number of PF queues and the number of VFs are * both known */ @@ -854,9 +880,11 @@ bnx2x_iov_static_resc(struct bnx2x *bp, struct bnx2x_virtf *vf) resc->num_mac_filters = 1; /* divvy up vlan rules */ + bnx2x_iov_re_set_vlan_filters(bp, vf, 0); vlan_count = bp->vlans_pool.check(&bp->vlans_pool); vlan_count = 1 << ilog2(vlan_count); - resc->num_vlan_filters = vlan_count / BNX2X_NR_VIRTFN(bp); + bnx2x_iov_re_set_vlan_filters(bp, vf, + vlan_count / BNX2X_NR_VIRTFN(bp)); /* no real limitation */ resc->num_mc_filters = 0; @@ -1478,10 +1506,6 @@ int bnx2x_iov_nic_init(struct bnx2x *bp) bnx2x_iov_static_resc(bp, vf); /* queues are initialized during VF-ACQUIRE */ - - /* reserve the vf vlan credit */ - bp->vlans_pool.get(&bp->vlans_pool, vf_vlan_rules_cnt(vf)); - vf->filter_state = 0; vf->sp_cl_id = bnx2x_fp(bp, 0, cl_id); @@ -1912,11 +1936,12 @@ int bnx2x_vf_chk_avail_resc(struct bnx2x *bp, struct bnx2x_virtf *vf, u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf); + /* Save a vlan filter for the Hypervisor */ return ((req_resc->num_rxqs <= rxq_cnt) && (req_resc->num_txqs <= txq_cnt) && (req_resc->num_sbs <= vf_sb_count(vf)) && (req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) && - (req_resc->num_vlan_filters <= vf_vlan_rules_cnt(vf))); + (req_resc->num_vlan_filters <= vf_vlan_rules_visible_cnt(vf))); } /* CORE VF API */ @@ -1972,14 +1997,14 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf); if (resc->num_mac_filters) vf_mac_rules_cnt(vf) = resc->num_mac_filters; - if (resc->num_vlan_filters) - vf_vlan_rules_cnt(vf) = resc->num_vlan_filters; + /* Add an additional vlan filter credit for the hypervisor */ + bnx2x_iov_re_set_vlan_filters(bp, vf, resc->num_vlan_filters + 1); DP(BNX2X_MSG_IOV, "Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n", vf_sb_count(vf), vf_rxq_count(vf), vf_txq_count(vf), vf_mac_rules_cnt(vf), - vf_vlan_rules_cnt(vf)); + vf_vlan_rules_visible_cnt(vf)); /* Initialize the queues */ if (!vf->vfqs) { @@ -2896,6 +2921,14 @@ void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp) return bp->regview + PXP_VF_ADDR_DB_START; } +void bnx2x_vf_pci_dealloc(struct bnx2x *bp) +{ + BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, + sizeof(struct bnx2x_vf_mbx_msg)); + BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping, + sizeof(union pf_vf_bulletin)); +} + int bnx2x_vf_pci_alloc(struct bnx2x *bp) { mutex_init(&bp->vf2pf_mutex); @@ -2915,10 +2948,7 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp) return 0; alloc_mem_err: - BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping, - sizeof(struct bnx2x_vf_mbx_msg)); - BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping, - sizeof(union pf_vf_bulletin)); + bnx2x_vf_pci_dealloc(bp); return -ENOMEM; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 8bf7645..6929adb 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -159,6 +159,8 @@ struct bnx2x_virtf { #define vf_mac_rules_cnt(vf) ((vf)->alloc_resc.num_mac_filters) #define vf_vlan_rules_cnt(vf) ((vf)->alloc_resc.num_vlan_filters) #define vf_mc_rules_cnt(vf) ((vf)->alloc_resc.num_mc_filters) + /* Hide a single vlan filter credit for the hypervisor */ +#define vf_vlan_rules_visible_cnt(vf) (vf_vlan_rules_cnt(vf) - 1) u8 sb_count; /* actual number of SBs */ u8 igu_base_id; /* base igu status block id */ @@ -502,6 +504,7 @@ static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp, enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp); void bnx2x_timer_sriov(struct bnx2x *bp); void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp); +void bnx2x_vf_pci_dealloc(struct bnx2x *bp); int bnx2x_vf_pci_alloc(struct bnx2x *bp); int bnx2x_enable_sriov(struct bnx2x *bp); void bnx2x_disable_sriov(struct bnx2x *bp); @@ -568,6 +571,7 @@ static inline void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp) return NULL; } +static inline void bnx2x_vf_pci_dealloc(struct bnx2 *bp) {return 0; } static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; } static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {} static inline int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs) {return 0; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 0622884..0c067e8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -1163,7 +1163,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, bnx2x_vf_max_queue_cnt(bp, vf); resc->num_sbs = vf_sb_count(vf); resc->num_mac_filters = vf_mac_rules_cnt(vf); - resc->num_vlan_filters = vf_vlan_rules_cnt(vf); + resc->num_vlan_filters = vf_vlan_rules_visible_cnt(vf); resc->num_mc_filters = 0; if (status == PFVF_STATUS_SUCCESS) { diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index 7e49c43..9e089d2 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig @@ -4,7 +4,7 @@ config NET_CADENCE bool "Cadence devices" - depends on HAS_IOMEM && (ARM || AVR32 || COMPILE_TEST) + depends on HAS_IOMEM && (ARM || AVR32 || MICROBLAZE || COMPILE_TEST) default y ---help--- If you have a network (Ethernet) card belonging to this class, say Y. @@ -30,7 +30,7 @@ config ARM_AT91_ETHER config MACB tristate "Cadence MACB/GEM support" - depends on HAS_DMA && (PLATFORM_AT32AP || ARCH_AT91 || ARCH_PICOXCELL || ARCH_ZYNQ || COMPILE_TEST) + depends on HAS_DMA && (PLATFORM_AT32AP || ARCH_AT91 || ARCH_PICOXCELL || ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST) select PHYLIB ---help--- The Cadence MACB ethernet interface is found on many Atmel AT32 and diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index ca97005..e9daa07 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -599,25 +599,16 @@ static void gem_rx_refill(struct macb *bp) { unsigned int entry; struct sk_buff *skb; - struct macb_dma_desc *desc; dma_addr_t paddr; while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, RX_RING_SIZE) > 0) { - u32 addr, ctrl; - entry = macb_rx_ring_wrap(bp->rx_prepared_head); - desc = &bp->rx_ring[entry]; /* Make hw descriptor updates visible to CPU */ rmb(); - addr = desc->addr; - ctrl = desc->ctrl; bp->rx_prepared_head++; - if ((addr & MACB_BIT(RX_USED))) - continue; - if (bp->rx_skbuff[entry] == NULL) { /* allocate sk_buff for this free entry in ring */ skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size); @@ -698,7 +689,6 @@ static int gem_rx(struct macb *bp, int budget) if (!(addr & MACB_BIT(RX_USED))) break; - desc->addr &= ~MACB_BIT(RX_USED); bp->rx_tail++; count++; @@ -891,16 +881,15 @@ static int macb_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete(napi); - /* - * We've done what we can to clean the buffers. Make sure we - * get notified when new packets arrive. - */ - macb_writel(bp, IER, MACB_RX_INT_FLAGS); - /* Packets received while interrupts were disabled */ status = macb_readl(bp, RSR); - if (unlikely(status)) + if (status) { + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_BIT(RCOMP)); napi_reschedule(napi); + } else { + macb_writel(bp, IER, MACB_RX_INT_FLAGS); + } } /* TODO: Handle errors */ @@ -951,6 +940,10 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) if (unlikely(status & (MACB_TX_ERR_FLAGS))) { macb_writel(bp, IDR, MACB_TX_INT_FLAGS); schedule_work(&bp->tx_error_task); + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_TX_ERR_FLAGS); + break; } @@ -968,6 +961,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) bp->hw_stats.gem.rx_overruns++; else bp->hw_stats.macb.rx_overruns++; + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_BIT(ISR_ROVR)); } if (status & MACB_BIT(HRESP)) { @@ -977,6 +973,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) * (work queue?) */ netdev_err(dev, "DMA bus error: HRESP not OK\n"); + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_BIT(HRESP)); } status = macb_readl(bp, ISR); @@ -1113,7 +1112,7 @@ static void gem_free_rx_buffers(struct macb *bp) desc = &bp->rx_ring[i]; addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr)); - dma_unmap_single(&bp->pdev->dev, addr, skb->len, + dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); skb = NULL; diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig index d40c994..570222c 100644 --- a/drivers/net/ethernet/chelsio/Kconfig +++ b/drivers/net/ethernet/chelsio/Kconfig @@ -67,13 +67,13 @@ config CHELSIO_T3 will be called cxgb3. config CHELSIO_T4 - tristate "Chelsio Communications T4 Ethernet support" + tristate "Chelsio Communications T4/T5 Ethernet support" depends on PCI select FW_LOADER select MDIO ---help--- - This driver supports Chelsio T4-based gigabit and 10Gb Ethernet - adapters. + This driver supports Chelsio T4 and T5 based gigabit, 10Gb Ethernet + adapter and T5 based 40Gb Ethernet adapter. For general information about Chelsio and our products, visit our website at <http://www.chelsio.com>. @@ -87,11 +87,12 @@ config CHELSIO_T4 will be called cxgb4. config CHELSIO_T4VF - tristate "Chelsio Communications T4 Virtual Function Ethernet support" + tristate "Chelsio Communications T4/T5 Virtual Function Ethernet support" depends on PCI ---help--- - This driver supports Chelsio T4-based gigabit and 10Gb Ethernet - adapters with PCI-E SR-IOV Virtual Functions. + This driver supports Chelsio T4 and T5 based gigabit, 10Gb Ethernet + adapters and T5 based 40Gb Ethernet adapters with PCI-E SR-IOV Virtual + Functions. For general information about Chelsio and our products, visit our website at <http://www.chelsio.com>. diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 6fe5891..24e16e3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -5870,6 +5870,8 @@ static void print_port_info(const struct net_device *dev) spd = " 2.5 GT/s"; else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB) spd = " 5 GT/s"; + else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_8_0GB) + spd = " 8 GT/s"; if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M) bufp += sprintf(bufp, "100/"); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 9125d9a..e2d4247 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -121,6 +121,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id); static irqreturn_t gfar_transmit(int irq, void *dev_id); static irqreturn_t gfar_interrupt(int irq, void *dev_id); static void adjust_link(struct net_device *dev); +static noinline void gfar_update_link_state(struct gfar_private *priv); static int init_phy(struct net_device *dev); static int gfar_probe(struct platform_device *ofdev); static int gfar_remove(struct platform_device *ofdev); @@ -3076,41 +3077,6 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id) return IRQ_HANDLED; } -static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) -{ - struct phy_device *phydev = priv->phydev; - u32 val = 0; - - if (!phydev->duplex) - return val; - - if (!priv->pause_aneg_en) { - if (priv->tx_pause_en) - val |= MACCFG1_TX_FLOW; - if (priv->rx_pause_en) - val |= MACCFG1_RX_FLOW; - } else { - u16 lcl_adv, rmt_adv; - u8 flowctrl; - /* get link partner capabilities */ - rmt_adv = 0; - if (phydev->pause) - rmt_adv = LPA_PAUSE_CAP; - if (phydev->asym_pause) - rmt_adv |= LPA_PAUSE_ASYM; - - lcl_adv = mii_advertise_flowctrl(phydev->advertising); - - flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); - if (flowctrl & FLOW_CTRL_TX) - val |= MACCFG1_TX_FLOW; - if (flowctrl & FLOW_CTRL_RX) - val |= MACCFG1_RX_FLOW; - } - - return val; -} - /* Called every time the controller might need to be made * aware of new link state. The PHY code conveys this * information through variables in the phydev structure, and this @@ -3120,83 +3086,12 @@ static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) static void adjust_link(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->gfargrp[0].regs; struct phy_device *phydev = priv->phydev; - int new_state = 0; - if (test_bit(GFAR_RESETTING, &priv->state)) - return; - - if (phydev->link) { - u32 tempval1 = gfar_read(®s->maccfg1); - u32 tempval = gfar_read(®s->maccfg2); - u32 ecntrl = gfar_read(®s->ecntrl); - - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. - */ - if (phydev->duplex != priv->oldduplex) { - new_state = 1; - if (!(phydev->duplex)) - tempval &= ~(MACCFG2_FULL_DUPLEX); - else - tempval |= MACCFG2_FULL_DUPLEX; - - priv->oldduplex = phydev->duplex; - } - - if (phydev->speed != priv->oldspeed) { - new_state = 1; - switch (phydev->speed) { - case 1000: - tempval = - ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); - - ecntrl &= ~(ECNTRL_R100); - break; - case 100: - case 10: - tempval = - ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); - - /* Reduced mode distinguishes - * between 10 and 100 - */ - if (phydev->speed == SPEED_100) - ecntrl |= ECNTRL_R100; - else - ecntrl &= ~(ECNTRL_R100); - break; - default: - netif_warn(priv, link, dev, - "Ack! Speed (%d) is not 10/100/1000!\n", - phydev->speed); - break; - } - - priv->oldspeed = phydev->speed; - } - - tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); - tempval1 |= gfar_get_flowctrl_cfg(priv); - - gfar_write(®s->maccfg1, tempval1); - gfar_write(®s->maccfg2, tempval); - gfar_write(®s->ecntrl, ecntrl); - - if (!priv->oldlink) { - new_state = 1; - priv->oldlink = 1; - } - } else if (priv->oldlink) { - new_state = 1; - priv->oldlink = 0; - priv->oldspeed = 0; - priv->oldduplex = -1; - } - - if (new_state && netif_msg_link(priv)) - phy_print_status(phydev); + if (unlikely(phydev->link != priv->oldlink || + phydev->duplex != priv->oldduplex || + phydev->speed != priv->oldspeed)) + gfar_update_link_state(priv); } /* Update the hash table based on the current list of multicast @@ -3442,6 +3337,114 @@ static irqreturn_t gfar_error(int irq, void *grp_id) return IRQ_HANDLED; } +static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) +{ + struct phy_device *phydev = priv->phydev; + u32 val = 0; + + if (!phydev->duplex) + return val; + + if (!priv->pause_aneg_en) { + if (priv->tx_pause_en) + val |= MACCFG1_TX_FLOW; + if (priv->rx_pause_en) + val |= MACCFG1_RX_FLOW; + } else { + u16 lcl_adv, rmt_adv; + u8 flowctrl; + /* get link partner capabilities */ + rmt_adv = 0; + if (phydev->pause) + rmt_adv = LPA_PAUSE_CAP; + if (phydev->asym_pause) + rmt_adv |= LPA_PAUSE_ASYM; + + lcl_adv = mii_advertise_flowctrl(phydev->advertising); + + flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); + if (flowctrl & FLOW_CTRL_TX) + val |= MACCFG1_TX_FLOW; + if (flowctrl & FLOW_CTRL_RX) + val |= MACCFG1_RX_FLOW; + } + + return val; +} + +static noinline void gfar_update_link_state(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + struct phy_device *phydev = priv->phydev; + + if (unlikely(test_bit(GFAR_RESETTING, &priv->state))) + return; + + if (phydev->link) { + u32 tempval1 = gfar_read(®s->maccfg1); + u32 tempval = gfar_read(®s->maccfg2); + u32 ecntrl = gfar_read(®s->ecntrl); + + if (phydev->duplex != priv->oldduplex) { + if (!(phydev->duplex)) + tempval &= ~(MACCFG2_FULL_DUPLEX); + else + tempval |= MACCFG2_FULL_DUPLEX; + + priv->oldduplex = phydev->duplex; + } + + if (phydev->speed != priv->oldspeed) { + switch (phydev->speed) { + case 1000: + tempval = + ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII); + + ecntrl &= ~(ECNTRL_R100); + break; + case 100: + case 10: + tempval = + ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); + + /* Reduced mode distinguishes + * between 10 and 100 + */ + if (phydev->speed == SPEED_100) + ecntrl |= ECNTRL_R100; + else + ecntrl &= ~(ECNTRL_R100); + break; + default: + netif_warn(priv, link, priv->ndev, + "Ack! Speed (%d) is not 10/100/1000!\n", + phydev->speed); + break; + } + + priv->oldspeed = phydev->speed; + } + + tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); + tempval1 |= gfar_get_flowctrl_cfg(priv); + + gfar_write(®s->maccfg1, tempval1); + gfar_write(®s->maccfg2, tempval); + gfar_write(®s->ecntrl, ecntrl); + + if (!priv->oldlink) + priv->oldlink = 1; + + } else if (priv->oldlink) { + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + } + + if (netif_msg_link(priv)) + phy_print_status(phydev); +} + static struct of_device_id gfar_match[] = { { diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 891dbee..76d7070 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -533,6 +533,9 @@ static int gfar_spauseparam(struct net_device *dev, struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 oldadv, newadv; + if (!phydev) + return -ENODEV; + if (!(phydev->supported & SUPPORTED_Pause) || (!(phydev->supported & SUPPORTED_Asym_Pause) && (epause->rx_pause != epause->tx_pause))) diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 9866f26..f0bbd42 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -186,7 +186,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) { u16 phy_reg = 0; u32 phy_id = 0; - s32 ret_val; + s32 ret_val = 0; u16 retry_count; u32 mac_reg = 0; @@ -217,11 +217,13 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) /* In case the PHY needs to be in mdio slow mode, * set slow mode and try to get the PHY id again. */ - hw->phy.ops.release(hw); - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (!ret_val) - ret_val = e1000e_get_phy_id(hw); - hw->phy.ops.acquire(hw); + if (hw->mac.type < e1000_pch_lpt) { + hw->phy.ops.release(hw); + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (!ret_val) + ret_val = e1000e_get_phy_id(hw); + hw->phy.ops.acquire(hw); + } if (ret_val) return false; @@ -842,6 +844,17 @@ s32 e1000_set_eee_pchlan(struct e1000_hw *hw) } } + if (hw->phy.type == e1000_phy_82579) { + ret_val = e1000_read_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, + &data); + if (ret_val) + goto release; + + data &= ~I82579_LPI_100_PLL_SHUT; + ret_val = e1000_write_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, + data); + } + /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); if (ret_val) @@ -1314,14 +1327,17 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) return ret_val; } - /* When connected at 10Mbps half-duplex, 82579 parts are excessively + /* When connected at 10Mbps half-duplex, some parts are excessively * aggressive resulting in many collisions. To avoid this, increase * the IPG and reduce Rx latency in the PHY. */ - if ((hw->mac.type == e1000_pch2lan) && link) { + if (((hw->mac.type == e1000_pch2lan) || + (hw->mac.type == e1000_pch_lpt)) && link) { u32 reg; reg = er32(STATUS); if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { + u16 emi_addr; + reg = er32(TIPG); reg &= ~E1000_TIPG_IPGT_MASK; reg |= 0xFF; @@ -1332,8 +1348,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) return ret_val; - ret_val = - e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0); + if (hw->mac.type == e1000_pch2lan) + emi_addr = I82579_RX_CONFIG; + else + emi_addr = I217_RX_CONFIG; + + ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0); hw->phy.ops.release(hw); @@ -2493,51 +2513,44 @@ release: * e1000_k1_gig_workaround_lv - K1 Si workaround * @hw: pointer to the HW structure * - * Workaround to set the K1 beacon duration for 82579 parts + * Workaround to set the K1 beacon duration for 82579 parts in 10Mbps + * Disable K1 in 1000Mbps and 100Mbps **/ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) { s32 ret_val = 0; u16 status_reg = 0; - u32 mac_reg; - u16 phy_reg; if (hw->mac.type != e1000_pch2lan) return 0; - /* Set K1 beacon duration based on 1Gbps speed or otherwise */ + /* Set K1 beacon duration based on 10Mbs speed */ ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); if (ret_val) return ret_val; if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { - mac_reg = er32(FEXTNVM4); - mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; - - ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); - if (ret_val) - return ret_val; - - if (status_reg & HV_M_STATUS_SPEED_1000) { + if (status_reg & + (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) { u16 pm_phy_reg; - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; - phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; - /* LV 1G Packet drop issue wa */ + /* LV 1G/100 Packet drop issue wa */ ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg); if (ret_val) return ret_val; - pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA; + pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE; ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg); if (ret_val) return ret_val; } else { + u32 mac_reg; + + mac_reg = er32(FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; - phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; + ew32(FEXTNVM4, mac_reg); } - ew32(FEXTNVM4, mac_reg); - ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); } return ret_val; diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index bead50f..5515126 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h @@ -232,16 +232,19 @@ #define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */ #define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ #define I82579_RX_CONFIG 0x3412 /* Receive configuration */ +#define I82579_LPI_PLL_SHUT 0x4412 /* LPI PLL Shut Enable */ #define I82579_EEE_PCS_STATUS 0x182E /* IEEE MMD Register 3.1 >> 8 */ #define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */ #define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */ #define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */ #define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE */ #define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE */ +#define I82579_LPI_100_PLL_SHUT (1 << 2) /* 100M LPI PLL Shut Enabled */ #define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */ #define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */ #define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */ #define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */ +#define I217_RX_CONFIG 0xB20C /* Receive configuration */ #define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */ #define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index d50c91e..3e69386 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1165,7 +1165,7 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work) dev_kfree_skb_any(adapter->tx_hwtstamp_skb); adapter->tx_hwtstamp_skb = NULL; adapter->tx_hwtstamp_timeouts++; - e_warn("clearing Tx timestamp hang"); + e_warn("clearing Tx timestamp hang\n"); } else { /* reschedule to check later */ schedule_work(&adapter->tx_hwtstamp_work); @@ -5687,7 +5687,7 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, static int e1000_change_mtu(struct net_device *netdev, int new_mtu) { struct e1000_adapter *adapter = netdev_priv(netdev); - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; + int max_frame = new_mtu + VLAN_HLEN + ETH_HLEN + ETH_FCS_LEN; /* Jumbo frame support */ if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) && @@ -6235,6 +6235,7 @@ static int __e1000_resume(struct pci_dev *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP static int e1000e_pm_thaw(struct device *dev) { struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); @@ -6255,7 +6256,6 @@ static int e1000e_pm_thaw(struct device *dev) return 0; } -#ifdef CONFIG_PM_SLEEP static int e1000e_pm_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); diff --git a/drivers/net/ethernet/intel/e1000e/phy.h b/drivers/net/ethernet/intel/e1000e/phy.h index 3841bcc..537d278 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.h +++ b/drivers/net/ethernet/intel/e1000e/phy.h @@ -164,6 +164,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw); #define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 #define HV_M_STATUS_SPEED_MASK 0x0300 #define HV_M_STATUS_SPEED_1000 0x0200 +#define HV_M_STATUS_SPEED_100 0x0100 #define HV_M_STATUS_LINK_UP 0x0040 #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 861b722..cf0761f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2897,12 +2897,9 @@ static irqreturn_t i40e_intr(int irq, void *data) u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0); if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) { - ena_mask &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; + icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; i40e_ptp_tx_hwtstamp(pf); - prttsyn_stat &= ~I40E_PRTTSYN_STAT_0_TXTIME_MASK; } - - wr32(hw, I40E_PRTTSYN_STAT_0, prttsyn_stat); } /* If a critical error is pending we have no choice but to reset the @@ -4271,6 +4268,14 @@ static int i40e_open(struct net_device *netdev) if (err) return err; + /* configure global TSO hardware offload settings */ + wr32(&pf->hw, I40E_GLLAN_TSOMSK_F, be32_to_cpu(TCP_FLAG_PSH | + TCP_FLAG_FIN) >> 16); + wr32(&pf->hw, I40E_GLLAN_TSOMSK_M, be32_to_cpu(TCP_FLAG_PSH | + TCP_FLAG_FIN | + TCP_FLAG_CWR) >> 16); + wr32(&pf->hw, I40E_GLLAN_TSOMSK_L, be32_to_cpu(TCP_FLAG_CWR) >> 16); + #ifdef CONFIG_I40E_VXLAN vxlan_get_rx_port(netdev); #endif @@ -6712,6 +6717,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_IPV6_CSUM | NETIF_F_TSO | + NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_RXCSUM | NETIF_F_NTUPLE | diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 262bdf1..8129918 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -160,7 +160,7 @@ static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) udelay(5); } if (ret_code == I40E_ERR_TIMEOUT) - hw_dbg(hw, "Done bit in GLNVM_SRCTL not set"); + hw_dbg(hw, "Done bit in GLNVM_SRCTL not set\n"); return ret_code; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index e33ec6c..e61e637 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -239,7 +239,7 @@ static void i40e_ptp_tx_work(struct work_struct *work) dev_kfree_skb_any(pf->ptp_tx_skb); pf->ptp_tx_skb = NULL; pf->tx_hwtstamp_timeouts++; - dev_warn(&pf->pdev->dev, "clearing Tx timestamp hang"); + dev_warn(&pf->pdev->dev, "clearing Tx timestamp hang\n"); return; } @@ -321,7 +321,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi) pf->last_rx_ptp_check = jiffies; pf->rx_hwtstamp_cleared++; dev_warn(&vsi->back->pdev->dev, - "%s: clearing Rx timestamp hang", + "%s: clearing Rx timestamp hang\n", __func__); } } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 0f5d96a..9478ddc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -418,7 +418,7 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi, } break; default: - dev_info(&pf->pdev->dev, "Could not specify spec type %d", + dev_info(&pf->pdev->dev, "Could not specify spec type %d\n", input->flow_type); ret = -EINVAL; } @@ -478,7 +478,7 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring, pf->flags |= I40E_FLAG_FDIR_REQUIRES_REINIT; } } else { - dev_info(&pdev->dev, "FD filter programming error"); + dev_info(&pdev->dev, "FD filter programming error\n"); } } else if (error == (0x1 << I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) { @@ -1713,9 +1713,11 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, I40E_TX_FLAGS_VLAN_PRIO_SHIFT; if (tx_flags & I40E_TX_FLAGS_SW_VLAN) { struct vlan_ethhdr *vhdr; - if (skb_header_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - return -ENOMEM; + int rc; + + rc = skb_cow_head(skb, 0); + if (rc < 0) + return rc; vhdr = (struct vlan_ethhdr *)skb->data; vhdr->h_vlan_TCI = htons(tx_flags >> I40E_TX_FLAGS_VLAN_SHIFT); @@ -1743,20 +1745,18 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, u64 *cd_type_cmd_tso_mss, u32 *cd_tunneling) { u32 cd_cmd, cd_tso_len, cd_mss; + struct ipv6hdr *ipv6h; struct tcphdr *tcph; struct iphdr *iph; u32 l4len; int err; - struct ipv6hdr *ipv6h; if (!skb_is_gso(skb)) return 0; - if (skb_header_cloned(skb)) { - err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - if (err) - return err; - } + err = skb_cow_head(skb, 0); + if (err < 0) + return err; if (protocol == htons(ETH_P_IP)) { iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb); diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c index db96339..f67f8a1 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.c +++ b/drivers/net/ethernet/intel/igb/e1000_i210.c @@ -365,7 +365,7 @@ static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data) word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); if (word_address == address) { *data = INVM_DWORD_TO_WORD_DATA(invm_dword); - hw_dbg("Read INVM Word 0x%02x = %x", + hw_dbg("Read INVM Word 0x%02x = %x\n", address, *data); status = E1000_SUCCESS; break; diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index 5910a93..1e0c404 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -929,11 +929,10 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) */ if (hw->fc.requested_mode == e1000_fc_full) { hw->fc.current_mode = e1000_fc_full; - hw_dbg("Flow Control = FULL.\r\n"); + hw_dbg("Flow Control = FULL.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; - hw_dbg("Flow Control = " - "RX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = RX PAUSE frames only.\n"); } } /* For receiving PAUSE frames ONLY. @@ -948,7 +947,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_tx_pause; - hw_dbg("Flow Control = TX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = TX PAUSE frames only.\n"); } /* For transmitting PAUSE frames ONLY. * @@ -962,7 +961,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { hw->fc.current_mode = e1000_fc_rx_pause; - hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = RX PAUSE frames only.\n"); } /* Per the IEEE spec, at this point flow control should be * disabled. However, we want to consider that we could @@ -988,10 +987,10 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw) (hw->fc.requested_mode == e1000_fc_tx_pause) || (hw->fc.strict_ieee)) { hw->fc.current_mode = e1000_fc_none; - hw_dbg("Flow Control = NONE.\r\n"); + hw_dbg("Flow Control = NONE.\n"); } else { hw->fc.current_mode = e1000_fc_rx_pause; - hw_dbg("Flow Control = RX PAUSE frames only.\r\n"); + hw_dbg("Flow Control = RX PAUSE frames only.\n"); } /* Now we need to do one last check... If we auto- diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index fb98d46..16430a8 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5193,8 +5193,10 @@ void igb_update_stats(struct igb_adapter *adapter, rcu_read_lock(); for (i = 0; i < adapter->num_rx_queues; i++) { - u32 rqdpc = rd32(E1000_RQDPC(i)); struct igb_ring *ring = adapter->rx_ring[i]; + u32 rqdpc = rd32(E1000_RQDPC(i)); + if (hw->mac.type >= e1000_i210) + wr32(E1000_RQDPC(i), 0); if (rqdpc) { ring->rx_stats.drops += rqdpc; diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 9209d65..ab25e49 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -389,7 +389,7 @@ static void igb_ptp_tx_work(struct work_struct *work) adapter->ptp_tx_skb = NULL; clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); adapter->tx_hwtstamp_timeouts++; - dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang"); + dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang\n"); return; } @@ -451,7 +451,7 @@ void igb_ptp_rx_hang(struct igb_adapter *adapter) rd32(E1000_RXSTMPH); adapter->last_rx_ptp_check = jiffies; adapter->rx_hwtstamp_cleared++; - dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang"); + dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang\n"); } } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 1a12c1d..c6c4ca7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -256,7 +256,6 @@ struct ixgbe_ring { struct ixgbe_tx_buffer *tx_buffer_info; struct ixgbe_rx_buffer *rx_buffer_info; }; - unsigned long last_rx_timestamp; unsigned long state; u8 __iomem *tail; dma_addr_t dma; /* phys. address of descriptor ring */ @@ -770,6 +769,7 @@ struct ixgbe_adapter { unsigned long ptp_tx_start; unsigned long last_overflow_check; unsigned long last_rx_ptp_check; + unsigned long last_rx_timestamp; spinlock_t tmreg_lock; struct cyclecounter cc; struct timecounter tc; @@ -944,24 +944,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter); void ixgbe_ptp_stop(struct ixgbe_adapter *adapter); void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter); void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter); -void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, - struct sk_buff *skb); -static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring, - union ixgbe_adv_rx_desc *rx_desc, - struct sk_buff *skb) -{ - if (unlikely(!ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) - return; - - __ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); - - /* - * Update the last_rx_timestamp timer in order to enable watchdog check - * for error case of latched timestamp on a dropped packet. - */ - rx_ring->last_rx_timestamp = jiffies; -} - +void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb); int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 24fba39..981b8a7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1195,7 +1195,7 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw, */ hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0]; - hw_dbg(hw, "Detected EEPROM page size = %d words.", + hw_dbg(hw, "Detected EEPROM page size = %d words.\n", hw->eeprom.word_page_size); out: return status; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c4c526b..d62e7a2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1664,7 +1664,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, ixgbe_rx_checksum(rx_ring, rx_desc, skb); - ixgbe_ptp_rx_hwtstamp(rx_ring, rx_desc, skb); + if (unlikely(ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) + ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector->adapter, skb); if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 23f7652..a76af8e2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -536,7 +536,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; - hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out"); + hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out\n"); } return status; @@ -745,7 +745,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; - hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out"); + hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out\n"); } return status; @@ -1175,7 +1175,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) status = 0; } else { if (hw->allow_unsupported_sfp) { - e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules."); + e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.\n"); status = 0; } else { hw_dbg(hw, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 63515a6..8902ae6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -435,10 +435,8 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter) void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - struct ixgbe_ring *rx_ring; u32 tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); unsigned long rx_event; - int n; /* if we don't have a valid timestamp in the registers, just update the * timeout counter and exit @@ -450,18 +448,15 @@ void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) /* determine the most recent watchdog or rx_timestamp event */ rx_event = adapter->last_rx_ptp_check; - for (n = 0; n < adapter->num_rx_queues; n++) { - rx_ring = adapter->rx_ring[n]; - if (time_after(rx_ring->last_rx_timestamp, rx_event)) - rx_event = rx_ring->last_rx_timestamp; - } + if (time_after(adapter->last_rx_timestamp, rx_event)) + rx_event = adapter->last_rx_timestamp; /* only need to read the high RXSTMP register to clear the lock */ if (time_is_before_jiffies(rx_event + 5*HZ)) { IXGBE_READ_REG(hw, IXGBE_RXSTMPH); adapter->last_rx_ptp_check = jiffies; - e_warn(drv, "clearing RX Timestamp hang"); + e_warn(drv, "clearing RX Timestamp hang\n"); } } @@ -517,7 +512,7 @@ static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work) dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; clear_bit_unlock(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state); - e_warn(drv, "clearing Tx Timestamp hang"); + e_warn(drv, "clearing Tx Timestamp hang\n"); return; } @@ -530,35 +525,22 @@ static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work) } /** - * __ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp - * @q_vector: structure containing interrupt and ring information + * ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp + * @adapter: pointer to adapter struct * @skb: particular skb to send timestamp with * * if the timestamp is valid, we convert it into the timecounter ns * value, then store that result into the shhwtstamps structure which * is passed up the network stack */ -void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, - struct sk_buff *skb) +void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb) { - struct ixgbe_adapter *adapter; - struct ixgbe_hw *hw; + struct ixgbe_hw *hw = &adapter->hw; struct skb_shared_hwtstamps *shhwtstamps; u64 regval = 0, ns; u32 tsyncrxctl; unsigned long flags; - /* we cannot process timestamps on a ring without a q_vector */ - if (!q_vector || !q_vector->adapter) - return; - - adapter = q_vector->adapter; - hw = &adapter->hw; - - /* - * Read the tsyncrxctl register afterwards in order to prevent taking an - * I/O hit on every packet. - */ tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) return; @@ -566,13 +548,17 @@ void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL); regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32; - spin_lock_irqsave(&adapter->tmreg_lock, flags); ns = timecounter_cyc2time(&adapter->tc, regval); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); shhwtstamps = skb_hwtstamps(skb); shhwtstamps->hwtstamp = ns_to_ktime(ns); + + /* Update the last_rx_timestamp timer in order to enable watchdog check + * for error case of latched timestamp on a dropped packet. + */ + adapter->last_rx_timestamp = jiffies; } int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c index b161a52..9d5ced2 100644 --- a/drivers/net/ethernet/marvell/mvmdio.c +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -232,7 +232,7 @@ static int orion_mdio_probe(struct platform_device *pdev) clk_prepare_enable(dev->clk); dev->err_interrupt = platform_get_irq(pdev, 0); - if (dev->err_interrupt != -ENXIO) { + if (dev->err_interrupt > 0) { ret = devm_request_irq(&pdev->dev, dev->err_interrupt, orion_mdio_err_irq, IRQF_SHARED, pdev->name, dev); @@ -241,6 +241,9 @@ static int orion_mdio_probe(struct platform_device *pdev) writel(MVMDIO_ERR_INT_SMI_DONE, dev->regs + MVMDIO_ERR_INT_MASK); + + } else if (dev->err_interrupt == -EPROBE_DEFER) { + return -EPROBE_DEFER; } mutex_init(&dev->lock); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index cef267e..7cf9dad 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -754,10 +754,10 @@ static void mlx4_request_modules(struct mlx4_dev *dev) has_eth_port = true; } - if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) - request_module_nowait(IB_DRV_NAME); if (has_eth_port) request_module_nowait(EN_DRV_NAME); + if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) + request_module_nowait(IB_DRV_NAME); } /* @@ -2440,7 +2440,8 @@ slave_start: * No return code for this call, just warn the user in case of PCI * express device capabilities are under-satisfied by the bus. */ - mlx4_check_pcie_caps(dev); + if (!mlx4_is_slave(dev)) + mlx4_check_pcie_caps(dev); /* In master functions, the communication channel must be initialized * after obtaining its address from fw */ diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index cfcad26..b5b3549 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -1106,6 +1106,9 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, } if (found_ix >= 0) { + /* Calculate a slave_gid which is the slave number in the gid + * table and not a globally unique slave number. + */ if (found_ix < MLX4_ROCE_PF_GIDS) slave_gid = 0; else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % num_vfs) * @@ -1118,41 +1121,43 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid, ((vf_gids % num_vfs) * ((vf_gids / num_vfs + 1)))) / (vf_gids / num_vfs)) + vf_gids % num_vfs + 1; + /* Calculate the globally unique slave id */ if (slave_gid) { struct mlx4_active_ports exclusive_ports; struct mlx4_active_ports actv_ports; struct mlx4_slaves_pport slaves_pport_actv; unsigned max_port_p_one; - int num_slaves_before = 1; + int num_vfs_before = 0; + int candidate_slave_gid; + /* Calculate how many VFs are on the previous port, if exists */ for (i = 1; i < port; i++) { bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); - set_bit(i, exclusive_ports.ports); + set_bit(i - 1, exclusive_ports.ports); slaves_pport_actv = mlx4_phys_to_slaves_pport_actv( dev, &exclusive_ports); - num_slaves_before += bitmap_weight( + num_vfs_before += bitmap_weight( slaves_pport_actv.slaves, dev->num_vfs + 1); } - if (slave_gid < num_slaves_before) { - bitmap_zero(exclusive_ports.ports, dev->caps.num_ports); - set_bit(port - 1, exclusive_ports.ports); - slaves_pport_actv = - mlx4_phys_to_slaves_pport_actv( - dev, &exclusive_ports); - slave_gid += bitmap_weight( - slaves_pport_actv.slaves, - dev->num_vfs + 1) - - num_slaves_before; - } - actv_ports = mlx4_get_active_ports(dev, slave_gid); + /* candidate_slave_gid isn't necessarily the correct slave, but + * it has the same number of ports and is assigned to the same + * ports as the real slave we're looking for. On dual port VF, + * slave_gid = [single port VFs on port <port>] + + * [offset of the current slave from the first dual port VF] + + * 1 (for the PF). + */ + candidate_slave_gid = slave_gid + num_vfs_before; + + actv_ports = mlx4_get_active_ports(dev, candidate_slave_gid); max_port_p_one = find_first_bit( actv_ports.ports, dev->caps.num_ports) + bitmap_weight(actv_ports.ports, dev->caps.num_ports) + 1; + /* Calculate the real slave number */ for (i = 1; i < max_port_p_one; i++) { if (i == port) continue; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 3b5f53e..1c3fdd4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -3733,6 +3733,25 @@ static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, } } +static int mlx4_adjust_port(struct mlx4_dev *dev, int slave, + u8 *gid, enum mlx4_protocol prot) +{ + int real_port; + + if (prot != MLX4_PROT_ETH) + return 0; + + if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0 || + dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { + real_port = mlx4_slave_convert_port(dev, slave, gid[5]); + if (real_port < 0) + return -EINVAL; + gid[5] = real_port; + } + + return 0; +} + int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -3768,6 +3787,10 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, if (err) goto ex_detach; } else { + err = mlx4_adjust_port(dev, slave, gid, prot); + if (err) + goto ex_put; + err = rem_mcg_res(dev, slave, rqp, gid, prot, type, ®_id); if (err) goto ex_put; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index dbf7539..0bc9148 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2374,6 +2374,14 @@ void qlcnic_set_drv_version(struct qlcnic_adapter *adapter) qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd); } +/* Reset firmware API lock */ +static void qlcnic_reset_api_lock(struct qlcnic_adapter *adapter) +{ + qlcnic_api_lock(adapter); + qlcnic_api_unlock(adapter); +} + + static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2476,6 +2484,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (qlcnic_82xx_check(adapter)) { qlcnic_check_vf(adapter, ent); adapter->portnum = adapter->ahw->pci_func; + qlcnic_reset_api_lock(adapter); err = qlcnic_start_firmware(adapter); if (err) { dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n" diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 0638c18..6afe9c1 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -1370,7 +1370,7 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, rsp = qlcnic_sriov_alloc_bc_trans(&trans); if (rsp) - return rsp; + goto free_cmd; rsp = qlcnic_sriov_prepare_bc_hdr(trans, cmd, seq, QLC_BC_COMMAND); if (rsp) @@ -1425,6 +1425,13 @@ err_out: cleanup_transaction: qlcnic_sriov_cleanup_transaction(trans); + +free_cmd: + if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) { + qlcnic_free_mbx_args(cmd); + kfree(cmd); + } + return rsp; } diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h index 6203c7d..4501964 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h @@ -358,6 +358,8 @@ struct sxgbe_core_ops { /* Enable disable checksum offload operations */ void (*enable_rx_csum)(void __iomem *ioaddr); void (*disable_rx_csum)(void __iomem *ioaddr); + void (*enable_rxqueue)(void __iomem *ioaddr, int queue_num); + void (*disable_rxqueue)(void __iomem *ioaddr, int queue_num); }; const struct sxgbe_core_ops *sxgbe_get_core_ops(void); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c index c4da7a2..58c3569 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c @@ -165,6 +165,26 @@ static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed) writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG); } +static void sxgbe_core_enable_rxqueue(void __iomem *ioaddr, int queue_num) +{ + u32 reg_val; + + reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG); + reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num); + reg_val |= SXGBE_CORE_RXQ_ENABLE; + writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG); +} + +static void sxgbe_core_disable_rxqueue(void __iomem *ioaddr, int queue_num) +{ + u32 reg_val; + + reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG); + reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num); + reg_val |= SXGBE_CORE_RXQ_DISABLE; + writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG); +} + static void sxgbe_set_eee_mode(void __iomem *ioaddr) { u32 ctrl; @@ -254,6 +274,8 @@ static const struct sxgbe_core_ops core_ops = { .set_eee_pls = sxgbe_set_eee_pls, .enable_rx_csum = sxgbe_enable_rx_csum, .disable_rx_csum = sxgbe_disable_rx_csum, + .enable_rxqueue = sxgbe_core_enable_rxqueue, + .disable_rxqueue = sxgbe_core_disable_rxqueue, }; const struct sxgbe_core_ops *sxgbe_get_core_ops(void) diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c index e896dbb..2686bb5 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c @@ -45,10 +45,10 @@ static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd, p->tdes23.tx_rd_des23.first_desc = is_fd; p->tdes23.tx_rd_des23.buf1_size = buf1_len; - p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.total_pkt_len = pkt_len; + p->tdes23.tx_rd_des23.tx_pkt_len.pkt_len.total_pkt_len = pkt_len; if (cksum) - p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.cksum_ctl = cic_full; + p->tdes23.tx_rd_des23.cksum_ctl = cic_full; } /* Set VLAN control information */ @@ -233,6 +233,12 @@ static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p) p->rdes23.rx_rd_des23.own_bit = 1; } +/* Set Interrupt on completion bit */ +static void sxgbe_set_rx_int_on_com(struct sxgbe_rx_norm_desc *p) +{ + p->rdes23.rx_rd_des23.int_on_com = 1; +} + /* Get the receive frame size */ static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p) { @@ -498,6 +504,7 @@ static const struct sxgbe_desc_ops desc_ops = { .init_rx_desc = sxgbe_init_rx_desc, .get_rx_owner = sxgbe_get_rx_owner, .set_rx_owner = sxgbe_set_rx_owner, + .set_rx_int_on_com = sxgbe_set_rx_int_on_com, .get_rx_frame_len = sxgbe_get_rx_frame_len, .get_rx_fd_status = sxgbe_get_rx_fd_status, .get_rx_ld_status = sxgbe_get_rx_ld_status, diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h index 838cb9f..1860932 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h @@ -39,22 +39,22 @@ struct sxgbe_tx_norm_desc { u32 int_on_com:1; /* TDES3 */ union { - u32 tcp_payload_len:18; + u16 tcp_payload_len; struct { u32 total_pkt_len:15; u32 reserved1:1; - u32 cksum_ctl:2; - } cksum_pktlen; + } pkt_len; } tx_pkt_len; - u32 tse_bit:1; - u32 tcp_hdr_len:4; - u32 sa_insert_ctl:3; - u32 crc_pad_ctl:2; - u32 last_desc:1; - u32 first_desc:1; - u32 ctxt_bit:1; - u32 own_bit:1; + u16 cksum_ctl:2; + u16 tse_bit:1; + u16 tcp_hdr_len:4; + u16 sa_insert_ctl:3; + u16 crc_pad_ctl:2; + u16 last_desc:1; + u16 first_desc:1; + u16 ctxt_bit:1; + u16 own_bit:1; } tx_rd_des23; /* tx write back Desc 2,3 */ @@ -70,25 +70,20 @@ struct sxgbe_tx_norm_desc { struct sxgbe_rx_norm_desc { union { - u32 rdes0; /* buf1 address */ - struct { + u64 rdes01; /* buf1 address */ + union { u32 out_vlan_tag:16; u32 in_vlan_tag:16; - } wb_rx_des0; - } rd_wb_des0; - - union { - u32 rdes1; /* buf2 address or buf1[63:32] */ - u32 rss_hash; /* Write-back RX */ - } rd_wb_des1; + u32 rss_hash; + } rx_wb_des01; + } rdes01; union { /* RX Read format Desc 2,3 */ struct{ /* RDES2 */ - u32 buf2_addr; + u64 buf2_addr:62; /* RDES3 */ - u32 buf2_hi_addr:30; u32 int_on_com:1; u32 own_bit:1; } rx_rd_des23; @@ -263,6 +258,9 @@ struct sxgbe_desc_ops { /* Set own bit */ void (*set_rx_owner)(struct sxgbe_rx_norm_desc *p); + /* Set Interrupt on completion bit */ + void (*set_rx_int_on_com)(struct sxgbe_rx_norm_desc *p); + /* Get the receive frame size */ int (*get_rx_frame_len)(struct sxgbe_rx_norm_desc *p); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c index 4d989ff..bb9b5b8 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c @@ -23,21 +23,8 @@ /* DMA core initialization */ static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map) { - int retry_count = 10; u32 reg_val; - /* reset the DMA */ - writel(SXGBE_DMA_SOFT_RESET, ioaddr + SXGBE_DMA_MODE_REG); - while (retry_count--) { - if (!(readl(ioaddr + SXGBE_DMA_MODE_REG) & - SXGBE_DMA_SOFT_RESET)) - break; - mdelay(10); - } - - if (retry_count < 0) - return -EBUSY; - reg_val = readl(ioaddr + SXGBE_DMA_SYSBUS_MODE_REG); /* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register. diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index 27e8c82..82a9a98 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c @@ -1076,6 +1076,9 @@ static int sxgbe_open(struct net_device *dev) /* Initialize the MAC Core */ priv->hw->mac->core_init(priv->ioaddr); + SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { + priv->hw->mac->enable_rxqueue(priv->ioaddr, queue_num); + } /* Request the IRQ lines */ ret = devm_request_irq(priv->device, priv->irq, sxgbe_common_interrupt, @@ -1453,6 +1456,7 @@ static void sxgbe_rx_refill(struct sxgbe_priv_data *priv) /* Added memory barrier for RX descriptor modification */ wmb(); priv->hw->desc->set_rx_owner(p); + priv->hw->desc->set_rx_int_on_com(p); /* Added memory barrier for RX descriptor modification */ wmb(); } @@ -2070,6 +2074,24 @@ static int sxgbe_hw_init(struct sxgbe_priv_data * const priv) return 0; } +static int sxgbe_sw_reset(void __iomem *addr) +{ + int retry_count = 10; + + writel(SXGBE_DMA_SOFT_RESET, addr + SXGBE_DMA_MODE_REG); + while (retry_count--) { + if (!(readl(addr + SXGBE_DMA_MODE_REG) & + SXGBE_DMA_SOFT_RESET)) + break; + mdelay(10); + } + + if (retry_count < 0) + return -EBUSY; + + return 0; +} + /** * sxgbe_drv_probe * @device: device pointer @@ -2102,6 +2124,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, priv->plat = plat_dat; priv->ioaddr = addr; + ret = sxgbe_sw_reset(priv->ioaddr); + if (ret) + goto error_free_netdev; + /* Verify driver arguments */ sxgbe_verify_args(); @@ -2218,9 +2244,14 @@ error_free_netdev: int sxgbe_drv_remove(struct net_device *ndev) { struct sxgbe_priv_data *priv = netdev_priv(ndev); + u8 queue_num; netdev_info(ndev, "%s: removing driver\n", __func__); + SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { + priv->hw->mac->disable_rxqueue(priv->ioaddr, queue_num); + } + priv->hw->dma->stop_rx(priv->ioaddr, SXGBE_RX_QUEUES); priv->hw->dma->stop_tx(priv->ioaddr, SXGBE_TX_QUEUES); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c index 01af2cb..43ccb4a 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c @@ -27,7 +27,7 @@ #define SXGBE_SMA_PREAD_CMD 0x02 /* post read increament address */ #define SXGBE_SMA_READ_CMD 0x03 /* read command */ #define SXGBE_SMA_SKIP_ADDRFRM 0x00040000 /* skip the address frame */ -#define SXGBE_MII_BUSY 0x00800000 /* mii busy */ +#define SXGBE_MII_BUSY 0x00400000 /* mii busy */ static int sxgbe_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_data) { @@ -147,6 +147,7 @@ int sxgbe_mdio_register(struct net_device *ndev) struct sxgbe_mdio_bus_data *mdio_data = priv->plat->mdio_bus_data; int err, phy_addr; int *irqlist; + bool phy_found = false; bool act; /* allocate the new mdio bus */ @@ -162,7 +163,7 @@ int sxgbe_mdio_register(struct net_device *ndev) irqlist = priv->mii_irq; /* assign mii bus fields */ - mdio_bus->name = "samsxgbe"; + mdio_bus->name = "sxgbe"; mdio_bus->read = &sxgbe_mdio_read; mdio_bus->write = &sxgbe_mdio_write; snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x", @@ -216,13 +217,22 @@ int sxgbe_mdio_register(struct net_device *ndev) netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n", phy->phy_id, phy_addr, irq_str, dev_name(&phy->dev), act ? " active" : ""); + phy_found = true; } } + if (!phy_found) { + netdev_err(ndev, "PHY not found\n"); + goto phyfound_err; + } + priv->mii = mdio_bus; return 0; +phyfound_err: + err = -ENODEV; + mdiobus_unregister(mdio_bus); mdiobus_err: mdiobus_free(mdio_bus); return err; diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h index 5a89acb..56f8bf5 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h @@ -52,6 +52,10 @@ #define SXGBE_CORE_RX_CTL2_REG 0x00A8 #define SXGBE_CORE_RX_CTL3_REG 0x00AC +#define SXGBE_CORE_RXQ_ENABLE_MASK 0x0003 +#define SXGBE_CORE_RXQ_ENABLE 0x0002 +#define SXGBE_CORE_RXQ_DISABLE 0x0000 + /* Interrupt Registers */ #define SXGBE_CORE_INT_STATUS_REG 0x00B0 #define SXGBE_CORE_INT_ENABLE_REG 0x00B4 diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index d1b4dca..bcaa41a 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -147,18 +147,19 @@ MODULE_ALIAS("platform:smc91x"); */ #define MII_DELAY 1 -#if SMC_DEBUG > 0 -#define DBG(n, dev, args...) \ - do { \ - if (SMC_DEBUG >= (n)) \ - netdev_dbg(dev, args); \ +#define DBG(n, dev, fmt, ...) \ + do { \ + if (SMC_DEBUG >= (n)) \ + netdev_dbg(dev, fmt, ##__VA_ARGS__); \ } while (0) -#define PRINTK(dev, args...) netdev_info(dev, args) -#else -#define DBG(n, dev, args...) do { } while (0) -#define PRINTK(dev, args...) netdev_dbg(dev, args) -#endif +#define PRINTK(dev, fmt, ...) \ + do { \ + if (SMC_DEBUG > 0) \ + netdev_info(dev, fmt, ##__VA_ARGS__); \ + else \ + netdev_dbg(dev, fmt, ##__VA_ARGS__); \ + } while (0) #if SMC_DEBUG > 3 static void PRINT_PKT(u_char *buf, int length) @@ -191,7 +192,7 @@ static void PRINT_PKT(u_char *buf, int length) pr_cont("\n"); } #else -#define PRINT_PKT(x...) do { } while (0) +static inline void PRINT_PKT(u_char *buf, int length) { } #endif @@ -1781,7 +1782,7 @@ static int smc_findirq(struct smc_local *lp) int timeout = 20; unsigned long cookie; - DBG(2, dev, "%s: %s\n", CARDNAME, __func__); + DBG(2, lp->dev, "%s: %s\n", CARDNAME, __func__); cookie = probe_irq_on(); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 31e55fb..7918d51 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -382,6 +382,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) if (skb_is_gso(skb)) goto do_lso; + if ((skb->ip_summed == CHECKSUM_NONE) || + (skb->ip_summed == CHECKSUM_UNNECESSARY)) + goto do_send; + rndis_msg_size += NDIS_CSUM_PPI_SIZE; ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE, TCPIP_CHKSUM_PKTINFO); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 753a8c2..b0e2865 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -263,11 +263,9 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) const struct macvlan_dev *vlan = netdev_priv(dev); const struct macvlan_port *port = vlan->port; const struct macvlan_dev *dest; - __u8 ip_summed = skb->ip_summed; if (vlan->mode == MACVLAN_MODE_BRIDGE) { const struct ethhdr *eth = (void *)skb->data; - skb->ip_summed = CHECKSUM_UNNECESSARY; /* send to other bridge ports directly */ if (is_multicast_ether_addr(eth->h_dest)) { @@ -285,7 +283,6 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) } xmit_world: - skb->ip_summed = ip_summed; skb->dev = vlan->lowerdev; return dev_queue_xmit(skb); } diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index ff111a8..3381c4f 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -322,6 +322,15 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb) segs = nskb; } } else { + /* If we receive a partial checksum and the tap side + * doesn't support checksum offload, compute the checksum. + * Note: it doesn't matter which checksum feature to + * check, we either support them all or none. + */ + if (skb->ip_summed == CHECKSUM_PARTIAL && + !(features & NETIF_F_ALL_CSUM) && + skb_checksum_help(skb)) + goto drop; skb_queue_tail(&q->sk.sk_receive_queue, skb); } diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 5ad971a..d849684 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -246,13 +246,13 @@ static int ksz9021_load_values_from_of(struct phy_device *phydev, if (val1 != -1) newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0); - if (val2 != -1) + if (val2 != -2) newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4); - if (val3 != -1) + if (val3 != -3) newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8); - if (val4 != -1) + if (val4 != -4) newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12); return kszphy_extended_write(phydev, reg, newval); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 1b6d09a..a972056 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -765,6 +765,17 @@ void phy_state_machine(struct work_struct *work) break; if (phydev->link) { + if (AUTONEG_ENABLE == phydev->autoneg) { + err = phy_aneg_done(phydev); + if (err < 0) + break; + + if (!err) { + phydev->state = PHY_AN; + phydev->link_timeout = PHY_AN_TIMEOUT; + break; + } + } phydev->state = PHY_RUNNING; netif_carrier_on(phydev->attached_dev); phydev->adjust_link(phydev->attached_dev); diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index cc70ecf..ad4a94e 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -429,13 +429,13 @@ static void slip_write_wakeup(struct tty_struct *tty) if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) return; - spin_lock(&sl->lock); + spin_lock_bh(&sl->lock); if (sl->xleft <= 0) { /* Now serial buffer is almost free & we can start * transmission of another packet */ sl->dev->stats.tx_packets++; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); sl_unlock(sl); return; } @@ -443,7 +443,7 @@ static void slip_write_wakeup(struct tty_struct *tty) actual = tty->ops->write(tty, sl->xhead, sl->xleft); sl->xleft -= actual; sl->xhead += actual; - spin_unlock(&sl->lock); + spin_unlock_bh(&sl->lock); } static void sl_tx_timeout(struct net_device *dev) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 33008c1..767fe61 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2834,8 +2834,10 @@ static int team_device_event(struct notifier_block *unused, case NETDEV_UP: if (netif_carrier_ok(dev)) team_port_change_check(port, true); + break; case NETDEV_DOWN: team_port_change_check(port, false); + break; case NETDEV_CHANGE: if (netif_running(port->dev)) team_port_change_check(port, diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 549dbac..9a2bd11 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -785,7 +785,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) skb_out->len > CDC_NCM_MIN_TX_PKT) memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0, ctx->tx_max - skb_out->len); - else if ((skb_out->len % dev->maxpacket) == 0) + else if (skb_out->len < ctx->tx_max && (skb_out->len % dev->maxpacket) == 0) *skb_put(skb_out, 1) = 0; /* force short packet */ /* set final frame length */ diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index e3458e3..83208d4 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -669,6 +669,22 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x05c6, 0x920d, 5)}, {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */ + {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */ + {QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */ + {QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */ + {QMI_FIXED_INTF(0x16d8, 0x6280, 0)}, /* CMOTech CHU-628 */ + {QMI_FIXED_INTF(0x16d8, 0x7001, 0)}, /* CMOTech CHU-720S */ + {QMI_FIXED_INTF(0x16d8, 0x7002, 0)}, /* CMOTech 7002 */ + {QMI_FIXED_INTF(0x16d8, 0x7003, 4)}, /* CMOTech CHU-629K */ + {QMI_FIXED_INTF(0x16d8, 0x7004, 3)}, /* CMOTech 7004 */ + {QMI_FIXED_INTF(0x16d8, 0x7006, 5)}, /* CMOTech CGU-629 */ + {QMI_FIXED_INTF(0x16d8, 0x700a, 4)}, /* CMOTech CHU-629S */ + {QMI_FIXED_INTF(0x16d8, 0x7211, 0)}, /* CMOTech CHU-720I */ + {QMI_FIXED_INTF(0x16d8, 0x7212, 0)}, /* CMOTech 7212 */ + {QMI_FIXED_INTF(0x16d8, 0x7213, 0)}, /* CMOTech 7213 */ + {QMI_FIXED_INTF(0x16d8, 0x7251, 1)}, /* CMOTech 7251 */ + {QMI_FIXED_INTF(0x16d8, 0x7252, 1)}, /* CMOTech 7252 */ + {QMI_FIXED_INTF(0x16d8, 0x7253, 1)}, /* CMOTech 7253 */ {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, @@ -730,16 +746,28 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ + {QMI_FIXED_INTF(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC73xx */ + {QMI_FIXED_INTF(0x1199, 0x68c0, 10)}, /* Sierra Wireless MC73xx */ + {QMI_FIXED_INTF(0x1199, 0x68c0, 11)}, /* Sierra Wireless MC73xx */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ + {QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */ + {QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */ {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ + {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)}, /* Olivetti Olicard 200 */ + {QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)}, /* Olivetti Olicard 500 */ {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */ + {QMI_FIXED_INTF(0x413c, 0x81a2, 8)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a3, 8)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7b68746..8a852b5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1285,7 +1285,7 @@ static int virtnet_set_channels(struct net_device *dev, if (channels->rx_count || channels->tx_count || channels->other_count) return -EINVAL; - if (queue_pairs > vi->max_queue_pairs) + if (queue_pairs > vi->max_queue_pairs || queue_pairs == 0) return -EINVAL; get_online_cpus(); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 82355d5..4dbb2ed 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -389,8 +389,8 @@ static inline size_t vxlan_nlmsg_size(void) + nla_total_size(sizeof(struct nda_cacheinfo)); } -static void vxlan_fdb_notify(struct vxlan_dev *vxlan, - struct vxlan_fdb *fdb, int type) +static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, + struct vxlan_rdst *rd, int type) { struct net *net = dev_net(vxlan->dev); struct sk_buff *skb; @@ -400,8 +400,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, if (skb == NULL) goto errout; - err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, - first_remote_rtnl(fdb)); + err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd); if (err < 0) { /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); @@ -427,10 +426,7 @@ static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) .remote_vni = VXLAN_N_VID, }; - INIT_LIST_HEAD(&f.remotes); - list_add_rcu(&remote.list, &f.remotes); - - vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); + vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); } static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) @@ -438,11 +434,11 @@ static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) struct vxlan_fdb f = { .state = NUD_STALE, }; + struct vxlan_rdst remote = { }; - INIT_LIST_HEAD(&f.remotes); memcpy(f.eth_addr, eth_addr, ETH_ALEN); - vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); + vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); } /* Hash Ethernet address */ @@ -533,7 +529,8 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f, /* Add/update destinations for multicast */ static int vxlan_fdb_append(struct vxlan_fdb *f, - union vxlan_addr *ip, __be16 port, __u32 vni, __u32 ifindex) + union vxlan_addr *ip, __be16 port, __u32 vni, + __u32 ifindex, struct vxlan_rdst **rdp) { struct vxlan_rdst *rd; @@ -551,6 +548,7 @@ static int vxlan_fdb_append(struct vxlan_fdb *f, list_add_tail_rcu(&rd->list, &f->remotes); + *rdp = rd; return 1; } @@ -690,6 +688,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, __be16 port, __u32 vni, __u32 ifindex, __u8 ndm_flags) { + struct vxlan_rdst *rd = NULL; struct vxlan_fdb *f; int notify = 0; @@ -726,7 +725,8 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, if ((flags & NLM_F_APPEND) && (is_multicast_ether_addr(f->eth_addr) || is_zero_ether_addr(f->eth_addr))) { - int rc = vxlan_fdb_append(f, ip, port, vni, ifindex); + int rc = vxlan_fdb_append(f, ip, port, vni, ifindex, + &rd); if (rc < 0) return rc; @@ -756,15 +756,18 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, INIT_LIST_HEAD(&f->remotes); memcpy(f->eth_addr, mac, ETH_ALEN); - vxlan_fdb_append(f, ip, port, vni, ifindex); + vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); ++vxlan->addrcnt; hlist_add_head_rcu(&f->hlist, vxlan_fdb_head(vxlan, mac)); } - if (notify) - vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); + if (notify) { + if (rd == NULL) + rd = first_remote_rtnl(f); + vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH); + } return 0; } @@ -785,7 +788,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) "delete %pM\n", f->eth_addr); --vxlan->addrcnt; - vxlan_fdb_notify(vxlan, f, RTM_DELNEIGH); + vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_DELNEIGH); hlist_del_rcu(&f->hlist); call_rcu(&f->rcu, vxlan_fdb_free); @@ -919,6 +922,7 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], */ if (rd && !list_is_singular(&f->remotes)) { list_del_rcu(&rd->list); + vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); kfree_rcu(rd, rcu); goto out; } @@ -993,7 +997,7 @@ static bool vxlan_snoop(struct net_device *dev, rdst->remote_ip = *src_ip; f->updated = jiffies; - vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); + vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH); } else { /* learned new entry */ spin_lock(&vxlan->hash_lock); diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index a0398fe..be3eb2a 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform_device *pdev) int irq; int ret = 0; struct ath_hw *ah; - struct ath_common *common; char hw_name[64]; if (!dev_get_platdata(&pdev->dev)) { @@ -146,9 +145,6 @@ static int ath_ahb_probe(struct platform_device *pdev) wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", hw_name, (unsigned long)mem, irq); - common = ath9k_hw_common(sc->sc_ah); - /* Will be cleared in ath9k_start() */ - set_bit(ATH_OP_INVALID, &common->op_flags); return 0; err_irq: diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 6d47783..ba502a2 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, ATH9K_ANI_RSSI_THR_LOW, ATH9K_ANI_RSSI_THR_HIGH); + if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL) + immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; + if (!scan) aniState->ofdmNoiseImmunityLevel = immunityLevel; @@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW, ATH9K_ANI_RSSI_THR_HIGH); + if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL) + immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; + if (ah->opmode == NL80211_IFTYPE_STATION && BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW && immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 44d7449..3ba03dd 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -251,7 +251,6 @@ struct ath_atx_tid { s8 bar_index; bool sched; - bool paused; bool active; }; diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index d76e6e0..ffca918 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -72,7 +72,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf, ath_txq_lock(sc, txq); if (tid->active) { len += scnprintf(buf + len, size - len, - "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n", + "%3d%11d%10d%10d%10d%10d%9d%6d\n", tid->tidno, tid->seq_start, tid->seq_next, @@ -80,8 +80,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf, tid->baw_head, tid->baw_tail, tid->bar_index, - tid->sched, - tid->paused); + tid->sched); } ath_txq_unlock(sc, txq); } diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index cbbb02a..36ae649 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -783,6 +783,9 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, common = ath9k_hw_common(ah); ath9k_set_hw_capab(sc, hw); + /* Will be cleared in ath9k_start() */ + set_bit(ATH_OP_INVALID, &common->op_flags); + /* Initialize regulatory */ error = ath_regd_init(&common->regulatory, sc->hw->wiphy, ath9k_reg_notifier); diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 25304ad..914dbc6 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -784,7 +784,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct ath_softc *sc; struct ieee80211_hw *hw; - struct ath_common *common; u8 csz; u32 val; int ret = 0; @@ -877,10 +876,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n", hw_name, (unsigned long)sc->mem, pdev->irq); - /* Will be cleared in ath9k_start() */ - common = ath9k_hw_common(sc->sc_ah); - set_bit(ATH_OP_INVALID, &common->op_flags); - return 0; err_init: diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 6c9accd..19df969 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -975,6 +975,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) u64 tsf = 0; unsigned long flags; dma_addr_t new_buf_addr; + unsigned int budget = 512; if (edma) dma_type = DMA_BIDIRECTIONAL; @@ -1113,15 +1114,17 @@ requeue_drop_frag: } requeue: list_add_tail(&bf->list, &sc->rx.rxbuf); - if (flush) - continue; if (edma) { ath_rx_edma_buf_link(sc, qtype); } else { ath_rx_buf_relink(sc, bf); - ath9k_hw_rxena(ah); + if (!flush) + ath9k_hw_rxena(ah); } + + if (!budget--) + break; } while (1); if (!(ah->imask & ATH9K_INT_RXEOL)) { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 87cbec4..66acb2c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) { struct ath_atx_ac *ac = tid->ac; - if (tid->paused) - return; - if (tid->sched) return; @@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, ath_tx_tid_change_state(sc, txtid); txtid->active = true; - txtid->paused = true; *ssn = txtid->seq_start = txtid->seq_next; txtid->bar_index = -1; @@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) ath_txq_lock(sc, txq); txtid->active = false; - txtid->paused = false; ath_tx_flush_tid(sc, txtid); ath_tx_tid_change_state(sc, txtid); ath_txq_unlock_complete(sc, txq); @@ -1487,7 +1482,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) ath_txq_lock(sc, txq); ac->clear_ps_filter = true; - if (!tid->paused && ath_tid_has_buffered(tid)) { + if (ath_tid_has_buffered(tid)) { ath_tx_queue_tid(txq, tid); ath_txq_schedule(sc, txq); } @@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, ath_txq_lock(sc, txq); tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; - tid->paused = false; if (ath_tid_has_buffered(tid)) { ath_tx_queue_tid(txq, tid); @@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, continue; tid = ATH_AN_2_TID(an, i); - if (tid->paused) - continue; ath_txq_lock(sc, tid->ac->txq); while (nframes > 0) { @@ -1844,9 +1836,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) list_del(&tid->list); tid->sched = false; - if (tid->paused) - continue; - if (ath_tx_sched_aggr(sc, txq, tid, &stop)) sent = true; @@ -2698,7 +2687,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->baw_size = WME_MAX_BA; tid->baw_head = tid->baw_tail = 0; tid->sched = false; - tid->paused = false; tid->active = false; __skb_queue_head_init(&tid->buf_q); __skb_queue_head_init(&tid->retry_q); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index df130ef..c7c9f15 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -303,10 +303,10 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core, ci = core->chip; - /* if core is already in reset, just return */ + /* if core is already in reset, skip reset */ regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL); if ((regdata & BCMA_RESET_CTL_RESET) != 0) - return; + goto in_reset_configure; /* configure reset */ ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, @@ -322,6 +322,7 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core, SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) != BCMA_RESET_CTL_RESET, 300); +in_reset_configure: /* in-reset configure */ ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ddeb5a7..a87ee9b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -621,20 +621,18 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, bss_conf->bssid); /* - * Update the beacon. This is only required on USB devices. PCI - * devices fetch beacons periodically. - */ - if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev)) - rt2x00queue_update_beacon(rt2x00dev, vif); - - /* * Start/stop beaconing. */ if (changes & BSS_CHANGED_BEACON_ENABLED) { if (!bss_conf->enable_beacon && intf->enable_beacon) { - rt2x00queue_clear_beacon(rt2x00dev, vif); rt2x00dev->intf_beaconing--; intf->enable_beacon = false; + /* + * Clear beacon in the H/W for this vif. This is needed + * to disable beaconing on this particular interface + * and keep it running on other interfaces. + */ + rt2x00queue_clear_beacon(rt2x00dev, vif); if (rt2x00dev->intf_beaconing == 0) { /* @@ -645,11 +643,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, rt2x00queue_stop_queue(rt2x00dev->bcn); mutex_unlock(&intf->beacon_skb_mutex); } - - } else if (bss_conf->enable_beacon && !intf->enable_beacon) { rt2x00dev->intf_beaconing++; intf->enable_beacon = true; + /* + * Upload beacon to the H/W. This is only required on + * USB devices. PCI devices fetch beacons periodically. + */ + if (rt2x00_is_usb(rt2x00dev)) + rt2x00queue_update_beacon(rt2x00dev, vif); if (rt2x00dev->intf_beaconing == 1) { /* diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c index 06ef47c..5b4c225 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c @@ -293,7 +293,7 @@ static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, u8 *psaddr; __le16 fc; u16 type, ufc; - bool match_bssid, packet_toself, packet_beacon, addr; + bool match_bssid, packet_toself, packet_beacon = false, addr; tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 68b5c7e..07cb06d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -1001,7 +1001,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) err = _rtl92cu_init_mac(hw); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "init mac failed!\n"); - return err; + goto exit; } err = rtl92c_download_fw(hw); if (err) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 36b48be..2b3c78b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -49,6 +49,12 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) if (ieee80211_is_nullfunc(fc)) return QSLT_HIGH; + /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use + * queue V0 at priority 7; however, the RTL8192SE appears to have + * that queue at priority 6 + */ + if (skb->priority == 7) + return QSLT_VO; return skb->priority; } diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 5c8f822..4cdb64b 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -206,7 +206,7 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_hour = bcd2bin(regs[2] & 0x3f); tm->tm_mday = bcd2bin(regs[3] & 0x3f); tm->tm_wday = regs[4] & 0x7; - tm->tm_mon = bcd2bin(regs[5] & 0x1f); + tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1; tm->tm_year = bcd2bin(regs[6]) + 100; return rtc_valid_tm(tm); @@ -229,7 +229,7 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) regs[3] = bin2bcd(tm->tm_hour); regs[4] = bin2bcd(tm->tm_mday); regs[5] = tm->tm_wday; - regs[6] = bin2bcd(tm->tm_mon); + regs[6] = bin2bcd(tm->tm_mon + 1); regs[7] = bin2bcd(tm->tm_year - 100); msg.addr = client->addr; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 7f0af4f..6fd7d40 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -8293,7 +8293,6 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) mpt2sas_base_free_resources(ioc); pci_save_state(pdev); - pci_disable_device(pdev); pci_set_power_state(pdev, device_state); return 0; } diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index fe30ea9..109802f 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -77,7 +77,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) goto next_msg; } - if (!capable(CAP_SYS_ADMIN)) { + if (!netlink_capable(skb, CAP_SYS_ADMIN)) { err = -EPERM; goto next_msg; } diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 16bfd50..db3b494 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -750,8 +750,12 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) vscsi->affinity_hint_set = true; } else { - for (i = 0; i < vscsi->num_queues; i++) + for (i = 0; i < vscsi->num_queues; i++) { + if (!vscsi->req_vqs[i].vq) + continue; + virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); + } vscsi->affinity_hint_set = false; } diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index e2b4820..017d2f8 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -107,7 +107,7 @@ static int ad2s1200_probe(struct spi_device *spi) int pn, ret = 0; unsigned short *pins = spi->dev.platform_data; - for (pn = 0; pn < AD2S1200_PN; pn++) + for (pn = 0; pn < AD2S1200_PN; pn++) { ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT, DRV_NAME); if (ret) { @@ -115,6 +115,7 @@ static int ad2s1200_probe(struct spi_device *spi) pins[pn]); return ret; } + } indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 94f9e3a..0ff7fda 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -190,7 +190,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index) return hvc_driver; } -static int __init hvc_console_setup(struct console *co, char *options) +static int hvc_console_setup(struct console *co, char *options) { if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES) return -ENODEV; diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 41fe8a0..fe9d129 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2353,8 +2353,12 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, if (tty->ops->flush_chars) tty->ops->flush_chars(tty); } else { + struct n_tty_data *ldata = tty->disc_data; + while (nr > 0) { + mutex_lock(&ldata->output_lock); c = tty->ops->write(tty, b, nr); + mutex_unlock(&ldata->output_lock); if (c < 0) { retval = c; goto break_out; diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 0e1bf88..2d4bd39 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -555,7 +555,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) */ if ((p->port.type == PORT_XR17V35X) || (p->port.type == PORT_XR17D15X)) { - serial_out(p, UART_EXAR_SLEEP, 0xff); + serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0); return; } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f1d30f6..cf78d19 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -255,16 +255,15 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size, if (change || left < size) { /* This is the slow path - looking for new buffers to use */ if ((n = tty_buffer_alloc(port, size)) != NULL) { - unsigned long iflags; - n->flags = flags; buf->tail = n; - - spin_lock_irqsave(&buf->flush_lock, iflags); b->commit = b->used; + /* paired w/ barrier in flush_to_ldisc(); ensures the + * latest commit value can be read before the head is + * advanced to the next buffer + */ + smp_wmb(); b->next = n; - spin_unlock_irqrestore(&buf->flush_lock, iflags); - } else if (change) size = 0; else @@ -448,27 +447,28 @@ static void flush_to_ldisc(struct work_struct *work) mutex_lock(&buf->lock); while (1) { - unsigned long flags; struct tty_buffer *head = buf->head; + struct tty_buffer *next; int count; /* Ldisc or user is trying to gain exclusive access */ if (atomic_read(&buf->priority)) break; - spin_lock_irqsave(&buf->flush_lock, flags); + next = head->next; + /* paired w/ barrier in __tty_buffer_request_room(); + * ensures commit value read is not stale if the head + * is advancing to the next buffer + */ + smp_rmb(); count = head->commit - head->read; if (!count) { - if (head->next == NULL) { - spin_unlock_irqrestore(&buf->flush_lock, flags); + if (next == NULL) break; - } - buf->head = head->next; - spin_unlock_irqrestore(&buf->flush_lock, flags); + buf->head = next; tty_buffer_free(port, head); continue; } - spin_unlock_irqrestore(&buf->flush_lock, flags); count = receive_buf(tty, head, count); if (!count) @@ -523,7 +523,6 @@ void tty_buffer_init(struct tty_port *port) struct tty_bufhead *buf = &port->buf; mutex_init(&buf->lock); - spin_lock_init(&buf->flush_lock); tty_buffer_reset(&buf->sentinel, 0); buf->head = &buf->sentinel; buf->tail = &buf->sentinel; diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index f605ad8..cfd18bc 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1709,16 +1709,6 @@ static int at91udc_probe(struct platform_device *pdev) return -ENODEV; } - if (pdev->num_resources != 2) { - DBG("invalid num_resources\n"); - return -ENODEV; - } - if ((pdev->resource[0].flags != IORESOURCE_MEM) - || (pdev->resource[1].flags != IORESOURCE_IRQ)) { - DBG("invalid resource type\n"); - return -ENODEV; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENXIO; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 6f2c8d3..cf2734b 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -248,7 +248,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, break; } - if (pdata->have_sysif_regs && pdata->controller_ver && + if (pdata->have_sysif_regs && + pdata->controller_ver > FSL_USB_VER_1_6 && (phy_mode == FSL_USB2_PHY_ULPI)) { /* check PHY_CLK_VALID to get phy clk valid */ if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index c81c872..cd871b8 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -90,6 +90,24 @@ __acquires(ohci->lock) dl_done_list (ohci); finish_unlinks (ohci, ohci_frame_no(ohci)); + /* + * Some controllers don't handle "global" suspend properly if + * there are unsuspended ports. For these controllers, put all + * the enabled ports into suspend before suspending the root hub. + */ + if (ohci->flags & OHCI_QUIRK_GLOBAL_SUSPEND) { + __hc32 __iomem *portstat = ohci->regs->roothub.portstatus; + int i; + unsigned temp; + + for (i = 0; i < ohci->num_ports; (++i, ++portstat)) { + temp = ohci_readl(ohci, portstat); + if ((temp & (RH_PS_PES | RH_PS_PSS)) == + RH_PS_PES) + ohci_writel(ohci, RH_PS_PSS, portstat); + } + } + /* maybe resume can wake root hub */ if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) { ohci->hc_control |= OHCI_CTRL_RWE; diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 90879e9..bb15096 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -160,6 +160,7 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) ohci_dbg(ohci, "enabled AMD prefetch quirk\n"); } + ohci->flags |= OHCI_QUIRK_GLOBAL_SUSPEND; return 0; } diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 9250cad..4550ce0 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -405,6 +405,8 @@ struct ohci_hcd { #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/ #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ +#define OHCI_QUIRK_GLOBAL_SUSPEND 0x800 /* must suspend ports */ + // there are also chip quirks/bugs in init logic struct work_struct nec_work; /* Worker for NEC quirk */ diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c index c47e5a6..d03fadd 100644 --- a/drivers/usb/phy/phy-fsm-usb.c +++ b/drivers/usb/phy/phy-fsm-usb.c @@ -303,17 +303,18 @@ int otg_statemachine(struct otg_fsm *fsm) otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE); break; case OTG_STATE_A_WAIT_VRISE: - if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld || - fsm->a_wait_vrise_tmout) { + if (fsm->a_vbus_vld) otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); - } + else if (fsm->id || fsm->a_bus_drop || + fsm->a_wait_vrise_tmout) + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); break; case OTG_STATE_A_WAIT_BCON: if (!fsm->a_vbus_vld) otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); else if (fsm->b_conn) otg_set_state(fsm, OTG_STATE_A_HOST); - else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout) + else if (fsm->id || fsm->a_bus_drop || fsm->a_wait_bcon_tmout) otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); break; case OTG_STATE_A_HOST: diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 7ed681a..6c0a542 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -151,6 +151,21 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 0)}, /* Netgear AirCard 340U Device Management */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 2)}, /* Netgear AirCard 340U NMEA */ {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 3)}, /* Netgear AirCard 340U Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 0)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 3)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 0)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 2)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 0)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 2)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 3)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 0)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 2)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 3)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card Modem */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 0)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card Device Management */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 2)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card NMEA */ + {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 3)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card Modem */ { } /* Terminating entry */ }; diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 4ef2a80..008d805 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1851,7 +1851,7 @@ static int usbat_probe(struct usb_interface *intf, us->transport_name = "Shuttle USBAT"; us->transport = usbat_flash_transport; us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; + us->max_lun = 0; result = usb_stor_probe2(us); return result; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f4a82291..174a447 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -234,6 +234,20 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), +/* Reported by Daniele Forsi <dforsi@gmail.com> */ +UNUSUAL_DEV( 0x0421, 0x04b9, 0x0350, 0x0350, + "Nokia", + "5300", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + +/* Patch submitted by Victor A. Santos <victoraur.santos@gmail.com> */ +UNUSUAL_DEV( 0x0421, 0x05af, 0x0742, 0x0742, + "Nokia", + "305", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64), + /* Patch submitted by Mikhail Zolotaryov <lebon@lebon.org.ua> */ UNUSUAL_DEV( 0x0421, 0x06aa, 0x1110, 0x1110, "Nokia", |