Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits)
  qlcnic: adding co maintainer
  ixgbe: add support for active DA cables
  ixgbe: dcb, do not tag tc_prio_control frames
  ixgbe: fix ixgbe_tx_is_paused logic
  ixgbe: always enable vlan strip/insert when DCB is enabled
  ixgbe: remove some redundant code in setting FCoE FIP filter
  ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp
  ixgbe: fix header len when unsplit packet overflows to data buffer
  ipv6: Never schedule DAD timer on dead address
  ipv6: Use POSTDAD state
  ipv6: Use state_lock to protect ifa state
  ipv6: Replace inet6_ifaddr->dead with state
  cxgb4: notify upper drivers if the device is already up when they load
  cxgb4: keep interrupts available when the ports are brought down
  cxgb4: fix initial addition of MAC address
  cnic: Return SPQ credit to bnx2x after ring setup and shutdown.
  cnic: Convert cnic_local_flags to atomic ops.
  can: Fix SJA1000 command register writes on SMP systems
  bridge: fix build for CONFIG_SYSFS disabled
  ARCNET: Limit com20020 PCI ID matches for SOHARD cards
  ...

Fix up various conflicts with pcmcia tree drivers/net/
{pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and
wireless/orinoco/spectrum_cs.c} and feature removal
(Documentation/feature-removal-schedule.txt).

Also fix a non-content conflict due to pm_qos_requirement getting
renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
This commit is contained in:
Linus Torvalds
2010-05-20 21:04:44 -07:00
1455 changed files with 95973 additions and 48342 deletions

View File

@@ -2062,8 +2062,132 @@ int proc_dostring(struct ctl_table *table, int write,
buffer, lenp, ppos);
}
static size_t proc_skip_spaces(char **buf)
{
size_t ret;
char *tmp = skip_spaces(*buf);
ret = tmp - *buf;
*buf = tmp;
return ret;
}
static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
static void proc_skip_char(char **buf, size_t *size, const char v)
{
while (*size) {
if (**buf != v)
break;
(*size)--;
(*buf)++;
}
}
#define TMPBUFLEN 22
/**
* proc_get_long - reads an ASCII formated integer from a user buffer
*
* @buf - a kernel buffer
* @size - size of the kernel buffer
* @val - this is where the number will be stored
* @neg - set to %TRUE if number is negative
* @perm_tr - a vector which contains the allowed trailers
* @perm_tr_len - size of the perm_tr vector
* @tr - pointer to store the trailer character
*
* In case of success 0 is returned and buf and size are updated with
* the amount of bytes read. If tr is non NULL and a trailing
* character exist (size is non zero after returning from this
* function) tr is updated with the trailing character.
*/
static int proc_get_long(char **buf, size_t *size,
unsigned long *val, bool *neg,
const char *perm_tr, unsigned perm_tr_len, char *tr)
{
int len;
char *p, tmp[TMPBUFLEN];
if (!*size)
return -EINVAL;
len = *size;
if (len > TMPBUFLEN - 1)
len = TMPBUFLEN - 1;
memcpy(tmp, *buf, len);
tmp[len] = 0;
p = tmp;
if (*p == '-' && *size > 1) {
*neg = true;
p++;
} else
*neg = false;
if (!isdigit(*p))
return -EINVAL;
*val = simple_strtoul(p, &p, 0);
len = p - tmp;
/* We don't know if the next char is whitespace thus we may accept
* invalid integers (e.g. 1234...a) or two integers instead of one
* (e.g. 123...1). So lets not allow such large numbers. */
if (len == TMPBUFLEN - 1)
return -EINVAL;
if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
return -EINVAL;
if (tr && (len < *size))
*tr = *p;
*buf += len;
*size -= len;
return 0;
}
/**
* proc_put_long - coverts an integer to a decimal ASCII formated string
*
* @buf - the user buffer
* @size - the size of the user buffer
* @val - the integer to be converted
* @neg - sign of the number, %TRUE for negative
*
* In case of success 0 is returned and buf and size are updated with
* the amount of bytes read.
*/
static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
bool neg)
{
int len;
char tmp[TMPBUFLEN], *p = tmp;
sprintf(p, "%s%lu", neg ? "-" : "", val);
len = strlen(tmp);
if (len > *size)
len = *size;
if (copy_to_user(*buf, tmp, len))
return -EFAULT;
*size -= len;
*buf += len;
return 0;
}
#undef TMPBUFLEN
static int proc_put_char(void __user **buf, size_t *size, char c)
{
if (*size) {
char __user **buffer = (char __user **)buf;
if (put_user(c, *buffer))
return -EFAULT;
(*size)--, (*buffer)++;
*buf = *buffer;
}
return 0;
}
static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
int *valp,
int write, void *data)
{
@@ -2072,33 +2196,31 @@ static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
} else {
int val = *valp;
if (val < 0) {
*negp = -1;
*negp = true;
*lvalp = (unsigned long)-val;
} else {
*negp = 0;
*negp = false;
*lvalp = (unsigned long)val;
}
}
return 0;
}
static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
int write, void __user *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(int *negp, unsigned long *lvalp, int *valp,
int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
int write, void *data),
void *data)
{
#define TMPBUFLEN 21
int *i, vleft, first = 1, neg;
unsigned long lval;
size_t left, len;
int *i, vleft, first = 1, err = 0;
unsigned long page = 0;
size_t left;
char *kbuf;
char buf[TMPBUFLEN], *p;
char __user *s = buffer;
if (!tbl_data || !table->maxlen || !*lenp ||
(*ppos && !write)) {
if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
*lenp = 0;
return 0;
}
@@ -2110,89 +2232,69 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
if (!conv)
conv = do_proc_dointvec_conv;
for (; left && vleft--; i++, first=0) {
if (write) {
while (left) {
char c;
if (get_user(c, s))
return -EFAULT;
if (!isspace(c))
break;
left--;
s++;
}
if (!left)
break;
neg = 0;
len = left;
if (len > sizeof(buf) - 1)
len = sizeof(buf) - 1;
if (copy_from_user(buf, s, len))
return -EFAULT;
buf[len] = 0;
p = buf;
if (*p == '-' && left > 1) {
neg = 1;
p++;
}
if (*p < '0' || *p > '9')
break;
lval = simple_strtoul(p, &p, 0);
len = p-buf;
if ((len < left) && *p && !isspace(*p))
break;
s += len;
left -= len;
if (conv(&neg, &lval, i, 1, data))
break;
} else {
p = buf;
if (!first)
*p++ = '\t';
if (conv(&neg, &lval, i, 0, data))
break;
sprintf(p, "%s%lu", neg ? "-" : "", lval);
len = strlen(buf);
if (len > left)
len = left;
if(copy_to_user(s, buf, len))
return -EFAULT;
left -= len;
s += len;
}
}
if (!write && !first && left) {
if(put_user('\n', s))
return -EFAULT;
left--, s++;
}
if (write) {
while (left) {
char c;
if (get_user(c, s++))
return -EFAULT;
if (!isspace(c))
if (left > PAGE_SIZE - 1)
left = PAGE_SIZE - 1;
page = __get_free_page(GFP_TEMPORARY);
kbuf = (char *) page;
if (!kbuf)
return -ENOMEM;
if (copy_from_user(kbuf, buffer, left)) {
err = -EFAULT;
goto free;
}
kbuf[left] = 0;
}
for (; left && vleft--; i++, first=0) {
unsigned long lval;
bool neg;
if (write) {
left -= proc_skip_spaces(&kbuf);
err = proc_get_long(&kbuf, &left, &lval, &neg,
proc_wspace_sep,
sizeof(proc_wspace_sep), NULL);
if (err)
break;
if (conv(&neg, &lval, i, 1, data)) {
err = -EINVAL;
break;
}
} else {
if (conv(&neg, &lval, i, 0, data)) {
err = -EINVAL;
break;
}
if (!first)
err = proc_put_char(&buffer, &left, '\t');
if (err)
break;
err = proc_put_long(&buffer, &left, lval, neg);
if (err)
break;
left--;
}
}
if (write && first)
return -EINVAL;
if (!write && !first && left && !err)
err = proc_put_char(&buffer, &left, '\n');
if (write && !err)
left -= proc_skip_spaces(&kbuf);
free:
if (write) {
free_page(page);
if (first)
return err ? : -EINVAL;
}
*lenp -= left;
*ppos += *lenp;
return 0;
#undef TMPBUFLEN
return err;
}
static int do_proc_dointvec(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(int *negp, unsigned long *lvalp, int *valp,
int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
int write, void *data),
void *data)
{
@@ -2260,8 +2362,8 @@ struct do_proc_dointvec_minmax_conv_param {
int *max;
};
static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
int *valp,
static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
int *valp,
int write, void *data)
{
struct do_proc_dointvec_minmax_conv_param *param = data;
@@ -2274,10 +2376,10 @@ static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
} else {
int val = *valp;
if (val < 0) {
*negp = -1;
*negp = true;
*lvalp = (unsigned long)-val;
} else {
*negp = 0;
*negp = false;
*lvalp = (unsigned long)val;
}
}
@@ -2317,102 +2419,78 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
unsigned long convmul,
unsigned long convdiv)
{
#define TMPBUFLEN 21
unsigned long *i, *min, *max, val;
int vleft, first=1, neg;
size_t len, left;
char buf[TMPBUFLEN], *p;
char __user *s = buffer;
if (!data || !table->maxlen || !*lenp ||
(*ppos && !write)) {
unsigned long *i, *min, *max;
int vleft, first = 1, err = 0;
unsigned long page = 0;
size_t left;
char *kbuf;
if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
*lenp = 0;
return 0;
}
i = (unsigned long *) data;
min = (unsigned long *) table->extra1;
max = (unsigned long *) table->extra2;
vleft = table->maxlen / sizeof(unsigned long);
left = *lenp;
if (write) {
if (left > PAGE_SIZE - 1)
left = PAGE_SIZE - 1;
page = __get_free_page(GFP_TEMPORARY);
kbuf = (char *) page;
if (!kbuf)
return -ENOMEM;
if (copy_from_user(kbuf, buffer, left)) {
err = -EFAULT;
goto free;
}
kbuf[left] = 0;
}
for (; left && vleft--; i++, min++, max++, first=0) {
unsigned long val;
if (write) {
while (left) {
char c;
if (get_user(c, s))
return -EFAULT;
if (!isspace(c))
break;
left--;
s++;
}
if (!left)
break;
neg = 0;
len = left;
if (len > TMPBUFLEN-1)
len = TMPBUFLEN-1;
if (copy_from_user(buf, s, len))
return -EFAULT;
buf[len] = 0;
p = buf;
if (*p == '-' && left > 1) {
neg = 1;
p++;
}
if (*p < '0' || *p > '9')
break;
val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
len = p-buf;
if ((len < left) && *p && !isspace(*p))
bool neg;
left -= proc_skip_spaces(&kbuf);
err = proc_get_long(&kbuf, &left, &val, &neg,
proc_wspace_sep,
sizeof(proc_wspace_sep), NULL);
if (err)
break;
if (neg)
val = -val;
s += len;
left -= len;
if(neg)
continue;
if ((min && val < *min) || (max && val > *max))
continue;
*i = val;
} else {
p = buf;
val = convdiv * (*i) / convmul;
if (!first)
*p++ = '\t';
sprintf(p, "%lu", convdiv * (*i) / convmul);
len = strlen(buf);
if (len > left)
len = left;
if(copy_to_user(s, buf, len))
return -EFAULT;
left -= len;
s += len;
err = proc_put_char(&buffer, &left, '\t');
err = proc_put_long(&buffer, &left, val, false);
if (err)
break;
}
}
if (!write && !first && left) {
if(put_user('\n', s))
return -EFAULT;
left--, s++;
}
if (!write && !first && left && !err)
err = proc_put_char(&buffer, &left, '\n');
if (write && !err)
left -= proc_skip_spaces(&kbuf);
free:
if (write) {
while (left) {
char c;
if (get_user(c, s++))
return -EFAULT;
if (!isspace(c))
break;
left--;
}
free_page(page);
if (first)
return err ? : -EINVAL;
}
if (write && first)
return -EINVAL;
*lenp -= left;
*ppos += *lenp;
return 0;
#undef TMPBUFLEN
return err;
}
static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
@@ -2473,7 +2551,7 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
}
static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
int *valp,
int write, void *data)
{
@@ -2485,10 +2563,10 @@ static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
int val = *valp;
unsigned long lval;
if (val < 0) {
*negp = -1;
*negp = true;
lval = (unsigned long)-val;
} else {
*negp = 0;
*negp = false;
lval = (unsigned long)val;
}
*lvalp = lval / HZ;
@@ -2496,7 +2574,7 @@ static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
return 0;
}
static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
int *valp,
int write, void *data)
{
@@ -2508,10 +2586,10 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
int val = *valp;
unsigned long lval;
if (val < 0) {
*negp = -1;
*negp = true;
lval = (unsigned long)-val;
} else {
*negp = 0;
*negp = false;
lval = (unsigned long)val;
}
*lvalp = jiffies_to_clock_t(lval);
@@ -2519,7 +2597,7 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
return 0;
}
static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
int *valp,
int write, void *data)
{
@@ -2529,10 +2607,10 @@ static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
int val = *valp;
unsigned long lval;
if (val < 0) {
*negp = -1;
*negp = true;
lval = (unsigned long)-val;
} else {
*negp = 0;
*negp = false;
lval = (unsigned long)val;
}
*lvalp = jiffies_to_msecs(lval);
@@ -2629,6 +2707,157 @@ static int proc_do_cad_pid(struct ctl_table *table, int write,
return 0;
}
/**
* proc_do_large_bitmap - read/write from/to a large bitmap
* @table: the sysctl table
* @write: %TRUE if this is a write to the sysctl file
* @buffer: the user buffer
* @lenp: the size of the user buffer
* @ppos: file position
*
* The bitmap is stored at table->data and the bitmap length (in bits)
* in table->maxlen.
*
* We use a range comma separated format (e.g. 1,3-4,10-10) so that
* large bitmaps may be represented in a compact manner. Writing into
* the file will clear the bitmap then update it with the given input.
*
* Returns 0 on success.
*/
int proc_do_large_bitmap(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int err = 0;
bool first = 1;
size_t left = *lenp;
unsigned long bitmap_len = table->maxlen;
unsigned long *bitmap = (unsigned long *) table->data;
unsigned long *tmp_bitmap = NULL;
char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
if (!bitmap_len || !left || (*ppos && !write)) {
*lenp = 0;
return 0;
}
if (write) {
unsigned long page = 0;
char *kbuf;
if (left > PAGE_SIZE - 1)
left = PAGE_SIZE - 1;
page = __get_free_page(GFP_TEMPORARY);
kbuf = (char *) page;
if (!kbuf)
return -ENOMEM;
if (copy_from_user(kbuf, buffer, left)) {
free_page(page);
return -EFAULT;
}
kbuf[left] = 0;
tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
GFP_KERNEL);
if (!tmp_bitmap) {
free_page(page);
return -ENOMEM;
}
proc_skip_char(&kbuf, &left, '\n');
while (!err && left) {
unsigned long val_a, val_b;
bool neg;
err = proc_get_long(&kbuf, &left, &val_a, &neg, tr_a,
sizeof(tr_a), &c);
if (err)
break;
if (val_a >= bitmap_len || neg) {
err = -EINVAL;
break;
}
val_b = val_a;
if (left) {
kbuf++;
left--;
}
if (c == '-') {
err = proc_get_long(&kbuf, &left, &val_b,
&neg, tr_b, sizeof(tr_b),
&c);
if (err)
break;
if (val_b >= bitmap_len || neg ||
val_a > val_b) {
err = -EINVAL;
break;
}
if (left) {
kbuf++;
left--;
}
}
while (val_a <= val_b)
set_bit(val_a++, tmp_bitmap);
first = 0;
proc_skip_char(&kbuf, &left, '\n');
}
free_page(page);
} else {
unsigned long bit_a, bit_b = 0;
while (left) {
bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
if (bit_a >= bitmap_len)
break;
bit_b = find_next_zero_bit(bitmap, bitmap_len,
bit_a + 1) - 1;
if (!first) {
err = proc_put_char(&buffer, &left, ',');
if (err)
break;
}
err = proc_put_long(&buffer, &left, bit_a, false);
if (err)
break;
if (bit_a != bit_b) {
err = proc_put_char(&buffer, &left, '-');
if (err)
break;
err = proc_put_long(&buffer, &left, bit_b, false);
if (err)
break;
}
first = 0; bit_b++;
}
if (!err)
err = proc_put_char(&buffer, &left, '\n');
}
if (!err) {
if (write) {
if (*ppos)
bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
else
memcpy(bitmap, tmp_bitmap,
BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long));
}
kfree(tmp_bitmap);
*lenp -= left;
*ppos += *lenp;
return 0;
} else {
kfree(tmp_bitmap);
return err;
}
}
#else /* CONFIG_PROC_FS */
int proc_dostring(struct ctl_table *table, int write,