forked from Minki/linux
Merge from-linus to-akpm
This commit is contained in:
commit
09d9200271
@ -334,7 +334,7 @@ static void __cpuinit tsc_sync_wait(void)
|
||||
{
|
||||
if (notscsync || !cpu_has_tsc)
|
||||
return;
|
||||
sync_tsc(boot_cpu_id);
|
||||
sync_tsc(0);
|
||||
}
|
||||
|
||||
static __init int notscsync_setup(char *s)
|
||||
|
@ -42,7 +42,7 @@ ACPI_MODULE_NAME("acpi_motherboard")
|
||||
*/
|
||||
#define IS_RESERVED_ADDR(base, len) \
|
||||
(((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \
|
||||
&& ((base) + (len) > 0x1000))
|
||||
&& ((base) + (len) > PCIBIOS_MIN_IO))
|
||||
/*
|
||||
* Clearing the flag (IORESOURCE_BUSY) allows drivers to use
|
||||
* the io ports if they really know they can use it, while
|
||||
|
@ -261,7 +261,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
|
||||
|
||||
static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
|
||||
{
|
||||
unsigned long long val;
|
||||
unsigned long pfn;
|
||||
|
||||
/* Turn a kernel-virtual address into a physical page frame */
|
||||
pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
|
||||
|
||||
/*
|
||||
* RED-PEN: on some architectures there is more mapped memory
|
||||
* than available in mem_map which pfn_valid checks
|
||||
@ -269,10 +273,10 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
|
||||
*
|
||||
* RED-PEN: vmalloc is not supported right now.
|
||||
*/
|
||||
if (!pfn_valid(vma->vm_pgoff))
|
||||
if (!pfn_valid(pfn))
|
||||
return -EIO;
|
||||
val = (u64)vma->vm_pgoff << PAGE_SHIFT;
|
||||
vma->vm_pgoff = __pa(val) >> PAGE_SHIFT;
|
||||
|
||||
vma->vm_pgoff = pfn;
|
||||
return mmap_mem(file, vma);
|
||||
}
|
||||
|
||||
|
@ -3789,6 +3789,7 @@ e1000_netpoll(struct net_device *netdev)
|
||||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
disable_irq(adapter->pdev->irq);
|
||||
e1000_intr(adapter->pdev->irq, netdev, NULL);
|
||||
e1000_clean_tx_irq(adapter);
|
||||
enable_irq(adapter->pdev->irq);
|
||||
}
|
||||
#endif
|
||||
|
@ -183,7 +183,7 @@
|
||||
* cross a page boundy.
|
||||
*/
|
||||
#define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
|
||||
#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
|
||||
|
||||
|
||||
struct SGentry {
|
||||
u32 address; /* bus! address */
|
||||
@ -235,7 +235,6 @@ struct ScsiReqBlk {
|
||||
u8 sg_count; /* No of HW sg entries for this request */
|
||||
u8 sg_index; /* Index of HW sg entry for this request */
|
||||
u32 total_xfer_length; /* Total number of bytes remaining to be transfered */
|
||||
void **virt_map;
|
||||
unsigned char *virt_addr; /* Virtual address of current transfer position */
|
||||
|
||||
/*
|
||||
@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
|
||||
reqlen, cmd->request_buffer, cmd->use_sg,
|
||||
srb->sg_count);
|
||||
|
||||
srb->virt_addr = page_address(sl->page);
|
||||
for (i = 0; i < srb->sg_count; i++) {
|
||||
u32 seglen = (u32)sg_dma_len(sl + i);
|
||||
sgp[i].address = (u32)sg_dma_address(sl + i);
|
||||
u32 busaddr = (u32)sg_dma_address(&sl[i]);
|
||||
u32 seglen = (u32)sl[i].length;
|
||||
sgp[i].address = busaddr;
|
||||
sgp[i].length = seglen;
|
||||
srb->total_xfer_length += seglen;
|
||||
srb->virt_map[i] = kmap(sl[i].page);
|
||||
}
|
||||
srb->virt_addr = srb->virt_map[0];
|
||||
sgp += srb->sg_count - 1;
|
||||
|
||||
/*
|
||||
@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
|
||||
int segment = cmd->use_sg;
|
||||
u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
|
||||
struct SGentry *psge = srb->segment_x + srb->sg_index;
|
||||
void **virt = srb->virt_map;
|
||||
|
||||
dprintkdbg(DBG_0,
|
||||
"sg_update_list: Transfered %i of %i bytes, %i remain\n",
|
||||
@ -2016,16 +2014,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
|
||||
|
||||
/* We have to walk the scatterlist to find it */
|
||||
sg = (struct scatterlist *)cmd->request_buffer;
|
||||
idx = 0;
|
||||
while (segment--) {
|
||||
unsigned long mask =
|
||||
~((unsigned long)sg->length - 1) & PAGE_MASK;
|
||||
if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
|
||||
srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
|
||||
srb->virt_addr = (page_address(sg->page)
|
||||
+ psge->address -
|
||||
(psge->address & PAGE_MASK));
|
||||
return;
|
||||
}
|
||||
++sg;
|
||||
++idx;
|
||||
}
|
||||
|
||||
dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
|
||||
@ -2151,7 +2149,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
|
||||
DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
|
||||
}
|
||||
/*
|
||||
* calculate all the residue data that not yet transfered
|
||||
* calculate all the residue data that not yet tranfered
|
||||
* SCSI transfer counter + left in SCSI FIFO data
|
||||
*
|
||||
* .....TRM_S1040_SCSI_COUNTER (24bits)
|
||||
@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
|
||||
struct scsi_cmnd *cmd = srb->cmd;
|
||||
enum dma_data_direction dir = cmd->sc_data_direction;
|
||||
if (cmd->use_sg && dir != PCI_DMA_NONE) {
|
||||
int i;
|
||||
/* unmap DC395x SG list */
|
||||
dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
|
||||
srb->sg_bus_addr, SEGMENTX_LEN);
|
||||
@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
|
||||
dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
|
||||
cmd->use_sg, cmd->request_buffer);
|
||||
/* unmap the sg segments */
|
||||
for (i = 0; i < srb->sg_count; i++)
|
||||
kunmap(virt_to_page(srb->virt_map[i]));
|
||||
pci_unmap_sg(acb->dev,
|
||||
(struct scatterlist *)cmd->request_buffer,
|
||||
cmd->use_sg, dir);
|
||||
@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
|
||||
|
||||
if (cmd->use_sg) {
|
||||
struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
|
||||
ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
|
||||
ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
|
||||
} else {
|
||||
ptr = (struct ScsiInqData *)(cmd->request_buffer);
|
||||
}
|
||||
@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
|
||||
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
|
||||
|
||||
for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
|
||||
kfree(acb->srb_array[i].segment_x);
|
||||
|
||||
vfree(acb->srb_array[0].virt_map);
|
||||
if (acb->srb_array[i].segment_x)
|
||||
kfree(acb->srb_array[i].segment_x);
|
||||
}
|
||||
|
||||
|
||||
@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
|
||||
int srb_idx = 0;
|
||||
unsigned i = 0;
|
||||
struct SGentry *ptr;
|
||||
void **virt_array;
|
||||
|
||||
for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
|
||||
for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
|
||||
acb->srb_array[i].segment_x = NULL;
|
||||
acb->srb_array[i].virt_map = NULL;
|
||||
}
|
||||
|
||||
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
|
||||
while (pages--) {
|
||||
@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
|
||||
ptr + (i * DC395x_MAX_SG_LISTENTRY);
|
||||
else
|
||||
dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
|
||||
|
||||
virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
|
||||
|
||||
if (!virt_array) {
|
||||
adapter_sg_tables_free(acb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
|
||||
acb->srb_array[i].virt_map = virt_array;
|
||||
virt_array += DC395x_MAX_SG_LISTENTRY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -628,7 +628,7 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
|
||||
int
|
||||
fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
|
||||
{
|
||||
int err;
|
||||
int err, flags = info->flags;
|
||||
|
||||
if (var->activate & FB_ACTIVATE_INV_MODE) {
|
||||
struct fb_videomode mode1, mode2;
|
||||
@ -682,7 +682,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
|
||||
!list_empty(&info->modelist))
|
||||
err = fb_add_videomode(&mode, &info->modelist);
|
||||
|
||||
if (!err && info->flags & FBINFO_MISC_USEREVENT) {
|
||||
if (!err && (flags & FBINFO_MISC_USEREVENT)) {
|
||||
struct fb_event event;
|
||||
|
||||
info->flags &= ~FBINFO_MISC_USEREVENT;
|
||||
|
@ -583,23 +583,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Map the fb and MMIO regions */
|
||||
dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
|
||||
(dinfo->aperture.physical, dinfo->aperture.size);
|
||||
if (!dinfo->aperture.virtual) {
|
||||
ERR_MSG("Cannot remap FB region.\n");
|
||||
cleanup(dinfo);
|
||||
return -ENODEV;
|
||||
}
|
||||
dinfo->mmio_base =
|
||||
(u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
|
||||
INTEL_REG_SIZE);
|
||||
if (!dinfo->mmio_base) {
|
||||
ERR_MSG("Cannot remap MMIO region.\n");
|
||||
cleanup(dinfo);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Get the chipset info. */
|
||||
dinfo->pci_chipset = pdev->device;
|
||||
|
||||
@ -630,9 +613,15 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dinfo->accel = 0;
|
||||
}
|
||||
|
||||
if (MB(voffset) < stolen_size)
|
||||
offset = (stolen_size >> 12);
|
||||
else
|
||||
offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
|
||||
|
||||
/* Framebuffer parameters - Use all the stolen memory if >= vram */
|
||||
if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
|
||||
if (ROUND_UP_TO_PAGE(stolen_size) >= ((offset << 12) + MB(vram))) {
|
||||
dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
|
||||
dinfo->fb.offset = 0;
|
||||
dinfo->fbmem_gart = 0;
|
||||
} else {
|
||||
dinfo->fb.size = MB(vram);
|
||||
@ -663,11 +652,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (MB(voffset) < stolen_size)
|
||||
offset = (stolen_size >> 12);
|
||||
else
|
||||
offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
|
||||
|
||||
/* set the mem offsets - set them after the already used pages */
|
||||
if (dinfo->accel) {
|
||||
dinfo->ring.offset = offset + gtt_info.current_memory;
|
||||
@ -682,6 +666,26 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
+ (dinfo->cursor.size >> 12);
|
||||
}
|
||||
|
||||
/* Map the fb and MMIO regions */
|
||||
/* ioremap only up to the end of used aperture */
|
||||
dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
|
||||
(dinfo->aperture.physical, (dinfo->fb.offset << 12)
|
||||
+ dinfo->fb.size);
|
||||
if (!dinfo->aperture.virtual) {
|
||||
ERR_MSG("Cannot remap FB region.\n");
|
||||
cleanup(dinfo);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dinfo->mmio_base =
|
||||
(u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
|
||||
INTEL_REG_SIZE);
|
||||
if (!dinfo->mmio_base) {
|
||||
ERR_MSG("Cannot remap MMIO region.\n");
|
||||
cleanup(dinfo);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Allocate memories (which aren't stolen) */
|
||||
if (dinfo->accel) {
|
||||
if (!(dinfo->gtt_ring_mem =
|
||||
|
@ -593,7 +593,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
|
||||
* Return 0 - device(s) present, 1 - no devices present.
|
||||
*/
|
||||
if (w1_reset_bus(dev)) {
|
||||
dev_info(&dev->dev, "No devices present on the wire.\n");
|
||||
dev_dbg(&dev->dev, "No devices present on the wire.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
Version 1.35
|
||||
------------
|
||||
Add writepage performance improvements. Fix path name conversions
|
||||
for long filenames on mounts which were done with "mapchars" mount option
|
||||
specified.
|
||||
|
||||
Version 1.34
|
||||
------------
|
||||
Fix error mapping of the TOO_MANY_LINKS (hardlinks) case.
|
||||
|
@ -2602,6 +2602,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||
if(name_len < PATH_MAX) {
|
||||
memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
|
||||
byte_count += name_len;
|
||||
/* 14 byte parm len above enough for 2 byte null terminator */
|
||||
pSMB->ResumeFileName[name_len] = 0;
|
||||
pSMB->ResumeFileName[name_len+1] = 0;
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
goto FNext2_err_exit;
|
||||
|
@ -611,6 +611,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
||||
src_char = source[i];
|
||||
switch (src_char) {
|
||||
case 0:
|
||||
target[j] = 0;
|
||||
goto ctoUCS_out;
|
||||
case ':':
|
||||
target[j] = cpu_to_le16(UNI_COLON);
|
||||
|
@ -402,7 +402,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev,
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
dev->last_wd = ret;
|
||||
dev->last_wd = watch->wd;
|
||||
watch->mask = mask;
|
||||
atomic_set(&watch->count, 0);
|
||||
INIT_LIST_HEAD(&watch->d_list);
|
||||
|
@ -2216,7 +2216,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
|
||||
if (!error) {
|
||||
const char *new_name = old_dentry->d_name.name;
|
||||
fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, new_dentry->d_inode);
|
||||
fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
|
||||
new_dentry->d_inode, old_dentry->d_inode);
|
||||
}
|
||||
fsnotify_oldname_free(old_name);
|
||||
|
||||
|
@ -593,6 +593,9 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode)
|
||||
*/
|
||||
inode->i_uid = current->fsuid;
|
||||
inode->i_mode = mode;
|
||||
/* Make inode invalid - just in case we are going to drop it before
|
||||
* the initialization happens */
|
||||
INODE_PKEY(inode)->k_objectid = 0;
|
||||
|
||||
if (dir->i_mode & S_ISGID) {
|
||||
inode->i_gid = dir->i_gid;
|
||||
|
@ -18,9 +18,11 @@ extern unsigned int pcibios_assign_all_busses(void);
|
||||
#define pcibios_scan_all_fns(a, b) 0
|
||||
|
||||
extern unsigned long pci_mem_start;
|
||||
#define PCIBIOS_MIN_IO 0x4000
|
||||
#define PCIBIOS_MIN_IO 0x1000
|
||||
#define PCIBIOS_MIN_MEM (pci_mem_start)
|
||||
|
||||
#define PCIBIOS_MIN_CARDBUS_IO 0x4000
|
||||
|
||||
void pcibios_config_init(void);
|
||||
struct pci_bus * pcibios_scan_root(int bus);
|
||||
|
||||
|
@ -406,7 +406,7 @@ register long __sc6 __asm__ ("r6") = (long) arg3; \
|
||||
register long __sc7 __asm__ ("r7") = (long) arg4; \
|
||||
register long __sc0 __asm__ ("r0") = (long) arg5; \
|
||||
register long __sc1 __asm__ ("r1") = (long) arg6; \
|
||||
__asm__ __volatile__ ("trapa #0x15" \
|
||||
__asm__ __volatile__ ("trapa #0x16" \
|
||||
: "=z" (__sc0) \
|
||||
: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \
|
||||
"r" (__sc3), "r" (__sc1) \
|
||||
|
@ -22,9 +22,11 @@ extern unsigned int pcibios_assign_all_busses(void);
|
||||
extern int no_iommu, force_iommu;
|
||||
|
||||
extern unsigned long pci_mem_start;
|
||||
#define PCIBIOS_MIN_IO 0x4000
|
||||
#define PCIBIOS_MIN_IO 0x1000
|
||||
#define PCIBIOS_MIN_MEM (pci_mem_start)
|
||||
|
||||
#define PCIBIOS_MIN_CARDBUS_IO 0x4000
|
||||
|
||||
void pcibios_config_init(void);
|
||||
struct pci_bus * pcibios_scan_root(int bus);
|
||||
extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
|
||||
const char *old_name, const char *new_name,
|
||||
int isdir, struct inode *target)
|
||||
int isdir, struct inode *target, struct inode *source)
|
||||
{
|
||||
u32 cookie = inotify_get_cookie();
|
||||
|
||||
@ -41,6 +41,10 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
|
||||
inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL);
|
||||
inotify_inode_is_dead(target);
|
||||
}
|
||||
|
||||
if (source) {
|
||||
inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -35,6 +35,7 @@ struct inotify_event {
|
||||
#define IN_CREATE 0x00000100 /* Subfile was created */
|
||||
#define IN_DELETE 0x00000200 /* Subfile was deleted */
|
||||
#define IN_DELETE_SELF 0x00000400 /* Self was deleted */
|
||||
#define IN_MOVE_SELF 0x00000800 /* Self was moved */
|
||||
|
||||
/* the following are legal events. they are sent as needed to any watch */
|
||||
#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */
|
||||
@ -56,7 +57,8 @@ struct inotify_event {
|
||||
*/
|
||||
#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
|
||||
IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
|
||||
IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF)
|
||||
IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
|
||||
IN_MOVE_SELF)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
struct netpoll;
|
||||
@ -26,6 +27,7 @@ struct netpoll {
|
||||
struct netpoll_info {
|
||||
spinlock_t poll_lock;
|
||||
int poll_owner;
|
||||
int tries;
|
||||
int rx_flags;
|
||||
spinlock_t rx_lock;
|
||||
struct netpoll *rx_np; /* netpoll that registered an rx_hook */
|
||||
@ -60,25 +62,31 @@ static inline int netpoll_rx(struct sk_buff *skb)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void netpoll_poll_lock(struct net_device *dev)
|
||||
static inline void *netpoll_poll_lock(struct net_device *dev)
|
||||
{
|
||||
rcu_read_lock(); /* deal with race on ->npinfo */
|
||||
if (dev->npinfo) {
|
||||
spin_lock(&dev->npinfo->poll_lock);
|
||||
dev->npinfo->poll_owner = smp_processor_id();
|
||||
return dev->npinfo;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void netpoll_poll_unlock(struct net_device *dev)
|
||||
static inline void netpoll_poll_unlock(void *have)
|
||||
{
|
||||
if (dev->npinfo) {
|
||||
dev->npinfo->poll_owner = -1;
|
||||
spin_unlock(&dev->npinfo->poll_lock);
|
||||
struct netpoll_info *npi = have;
|
||||
|
||||
if (npi) {
|
||||
npi->poll_owner = -1;
|
||||
spin_unlock(&npi->poll_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#else
|
||||
#define netpoll_rx(a) 0
|
||||
#define netpoll_poll_lock(a)
|
||||
#define netpoll_poll_lock(a) 0
|
||||
#define netpoll_poll_unlock(a)
|
||||
#endif
|
||||
|
||||
|
@ -255,7 +255,7 @@ struct sk_buff {
|
||||
nohdr:1;
|
||||
/* 3 bits spare */
|
||||
__u8 pkt_type;
|
||||
__u16 protocol;
|
||||
__be16 protocol;
|
||||
|
||||
void (*destructor)(struct sk_buff *skb);
|
||||
#ifdef CONFIG_NETFILTER
|
||||
|
@ -1696,7 +1696,8 @@ static void net_rx_action(struct softirq_action *h)
|
||||
struct softnet_data *queue = &__get_cpu_var(softnet_data);
|
||||
unsigned long start_time = jiffies;
|
||||
int budget = netdev_budget;
|
||||
|
||||
void *have;
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
while (!list_empty(&queue->poll_list)) {
|
||||
@ -1709,10 +1710,10 @@ static void net_rx_action(struct softirq_action *h)
|
||||
|
||||
dev = list_entry(queue->poll_list.next,
|
||||
struct net_device, poll_list);
|
||||
netpoll_poll_lock(dev);
|
||||
have = netpoll_poll_lock(dev);
|
||||
|
||||
if (dev->quota <= 0 || dev->poll(dev, &budget)) {
|
||||
netpoll_poll_unlock(dev);
|
||||
netpoll_poll_unlock(have);
|
||||
local_irq_disable();
|
||||
list_del(&dev->poll_list);
|
||||
list_add_tail(&dev->poll_list, &queue->poll_list);
|
||||
@ -1721,7 +1722,7 @@ static void net_rx_action(struct softirq_action *h)
|
||||
else
|
||||
dev->quota = dev->weight;
|
||||
} else {
|
||||
netpoll_poll_unlock(dev);
|
||||
netpoll_poll_unlock(have);
|
||||
dev_put(dev);
|
||||
local_irq_disable();
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define MAX_UDP_CHUNK 1460
|
||||
#define MAX_SKBS 32
|
||||
#define MAX_QUEUE_DEPTH (MAX_SKBS / 2)
|
||||
#define MAX_RETRIES 20000
|
||||
|
||||
static DEFINE_SPINLOCK(skb_list_lock);
|
||||
static int nr_skbs;
|
||||
@ -248,14 +249,14 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
|
||||
int status;
|
||||
struct netpoll_info *npinfo;
|
||||
|
||||
repeat:
|
||||
if(!np || !np->dev || !netif_running(np->dev)) {
|
||||
if (!np || !np->dev || !netif_running(np->dev)) {
|
||||
__kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* avoid recursion */
|
||||
npinfo = np->dev->npinfo;
|
||||
|
||||
/* avoid recursion */
|
||||
if (npinfo->poll_owner == smp_processor_id() ||
|
||||
np->dev->xmit_lock_owner == smp_processor_id()) {
|
||||
if (np->drop)
|
||||
@ -265,30 +266,37 @@ repeat:
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&np->dev->xmit_lock);
|
||||
np->dev->xmit_lock_owner = smp_processor_id();
|
||||
do {
|
||||
npinfo->tries--;
|
||||
spin_lock(&np->dev->xmit_lock);
|
||||
np->dev->xmit_lock_owner = smp_processor_id();
|
||||
|
||||
/*
|
||||
* network drivers do not expect to be called if the queue is
|
||||
* stopped.
|
||||
*/
|
||||
if (netif_queue_stopped(np->dev)) {
|
||||
/*
|
||||
* network drivers do not expect to be called if the queue is
|
||||
* stopped.
|
||||
*/
|
||||
if (netif_queue_stopped(np->dev)) {
|
||||
np->dev->xmit_lock_owner = -1;
|
||||
spin_unlock(&np->dev->xmit_lock);
|
||||
netpoll_poll(np);
|
||||
udelay(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
status = np->dev->hard_start_xmit(skb, np->dev);
|
||||
np->dev->xmit_lock_owner = -1;
|
||||
spin_unlock(&np->dev->xmit_lock);
|
||||
|
||||
netpoll_poll(np);
|
||||
goto repeat;
|
||||
}
|
||||
/* success */
|
||||
if(!status) {
|
||||
npinfo->tries = MAX_RETRIES; /* reset */
|
||||
return;
|
||||
}
|
||||
|
||||
status = np->dev->hard_start_xmit(skb, np->dev);
|
||||
np->dev->xmit_lock_owner = -1;
|
||||
spin_unlock(&np->dev->xmit_lock);
|
||||
|
||||
/* transmit busy */
|
||||
if(status) {
|
||||
/* transmit busy */
|
||||
netpoll_poll(np);
|
||||
goto repeat;
|
||||
}
|
||||
udelay(50);
|
||||
} while (npinfo->tries > 0);
|
||||
}
|
||||
|
||||
void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
|
||||
@ -349,15 +357,11 @@ static void arp_reply(struct sk_buff *skb)
|
||||
unsigned char *arp_ptr;
|
||||
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
|
||||
u32 sip, tip;
|
||||
unsigned long flags;
|
||||
struct sk_buff *send_skb;
|
||||
struct netpoll *np = NULL;
|
||||
|
||||
spin_lock_irqsave(&npinfo->rx_lock, flags);
|
||||
if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
|
||||
np = npinfo->rx_np;
|
||||
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
|
||||
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
@ -639,9 +643,11 @@ int netpoll_setup(struct netpoll *np)
|
||||
if (!npinfo)
|
||||
goto release;
|
||||
|
||||
npinfo->rx_flags = 0;
|
||||
npinfo->rx_np = NULL;
|
||||
npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
|
||||
npinfo->poll_owner = -1;
|
||||
npinfo->tries = MAX_RETRIES;
|
||||
npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
|
||||
} else
|
||||
npinfo = ndev->npinfo;
|
||||
@ -718,9 +724,16 @@ int netpoll_setup(struct netpoll *np)
|
||||
npinfo->rx_np = np;
|
||||
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
|
||||
}
|
||||
|
||||
/* fill up the skb queue */
|
||||
refill_skbs();
|
||||
|
||||
/* last thing to do is link it to the net device structure */
|
||||
ndev->npinfo = npinfo;
|
||||
|
||||
/* avoid racing with NAPI reading npinfo */
|
||||
synchronize_rcu();
|
||||
|
||||
return 0;
|
||||
|
||||
release:
|
||||
|
Loading…
Reference in New Issue
Block a user