aoecmd.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 709 行 · 第 1/2 页

C
709
字号
			d->rttavg = MAXTIMER;	}	d->timer.expires = jiffies + TIMERTICK;	add_timer(&d->timer);	spin_unlock_irqrestore(&d->lock, flags);	aoenet_xmit(sl);}/* this function performs work that has been deferred until sleeping is OK */voidaoecmd_sleepwork(void *vp){	struct aoedev *d = (struct aoedev *) vp;	if (d->flags & DEVFL_GDALLOC)		aoeblk_gdalloc(d);	if (d->flags & DEVFL_NEWSIZE) {		struct block_device *bd;		unsigned long flags;		u64 ssize;		ssize = d->gd->capacity;		bd = bdget_disk(d->gd, 0);		if (bd) {			mutex_lock(&bd->bd_inode->i_mutex);			i_size_write(bd->bd_inode, (loff_t)ssize<<9);			mutex_unlock(&bd->bd_inode->i_mutex);			bdput(bd);		}		spin_lock_irqsave(&d->lock, flags);		d->flags |= DEVFL_UP;		d->flags &= ~DEVFL_NEWSIZE;		spin_unlock_irqrestore(&d->lock, flags);	}}static voidataid_complete(struct aoedev *d, unsigned char *id){	u64 ssize;	u16 n;	/* word 83: command set supported */	n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));	/* word 86: command set/feature enabled */	n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));	if (n & (1<<10)) {	/* bit 10: LBA 48 */		d->flags |= DEVFL_EXT;		/* word 100: number lba48 sectors */		ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));		/* set as in ide-disk.c:init_idedisk_capacity */		d->geo.cylinders = ssize;		d->geo.cylinders /= (255 * 63);		d->geo.heads = 255;		d->geo.sectors = 63;	} else {		d->flags &= ~DEVFL_EXT;		/* number lba28 sectors */		ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));		/* NOTE: obsolete in ATA 6 */		d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));		d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));		d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));	}	if (d->ssize != ssize)		printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "			"sectors\n", (unsigned long long)mac_addr(d->addr),			d->aoemajor, d->aoeminor,			d->fw_ver, (long long)ssize);	d->ssize = ssize;	d->geo.start = 0;	if (d->gd != NULL) {		d->gd->capacity = ssize;		d->flags |= DEVFL_NEWSIZE;	} else {		if (d->flags & DEVFL_GDALLOC) {			printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n",			       __FUNCTION__,			       "can't schedule work for",			       d->aoemajor, d->aoeminor,			       "it's already on! (This really shouldn't happen).\n");			return;		}		d->flags |= DEVFL_GDALLOC;	}	schedule_work(&d->work);}static voidcalc_rttavg(struct aoedev *d, int rtt){	register long n;	n = rtt;	if (n < MINTIMER)		n = MINTIMER;	else if (n > MAXTIMER)		n = MAXTIMER;	/* g == .25; cf. Congestion Avoidance and Control, Jacobson & Karels; 1988 */	n -= d->rttavg;	d->rttavg += n >> 2;}voidaoecmd_ata_rsp(struct sk_buff *skb){	struct aoedev *d;	struct aoe_hdr *hin;	struct aoe_atahdr *ahin, *ahout;	struct frame *f;	struct buf *buf;	struct sk_buff *sl;	register long n;	ulong flags;	char ebuf[128];	u16 aoemajor;	hin = (struct aoe_hdr *) skb->mac.raw;	aoemajor = be16_to_cpu(hin->major);	d = aoedev_by_aoeaddr(aoemajor, hin->minor);	if (d == NULL) {		snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "			"for unknown device %d.%d\n",			 aoemajor, hin->minor);		aoechr_error(ebuf);		return;	}	spin_lock_irqsave(&d->lock, flags);	f = getframe(d, be32_to_cpu(hin->tag));	if (f == NULL) {		spin_unlock_irqrestore(&d->lock, flags);		snprintf(ebuf, sizeof ebuf,			"%15s e%d.%d    tag=%08x@%08lx\n",			"unexpected rsp",			be16_to_cpu(hin->major),			hin->minor,			be32_to_cpu(hin->tag),			jiffies);		aoechr_error(ebuf);		return;	}	calc_rttavg(d, tsince(f->tag));	ahin = (struct aoe_atahdr *) (hin+1);	ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr));	buf = f->buf;	if (ahout->cmdstat == WIN_IDENTIFY)		d->flags &= ~DEVFL_PAUSE;	if (ahin->cmdstat & 0xa9) {	/* these bits cleared on success */		printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "			"stat=%2.2Xh from e%ld.%ld\n", 			ahout->cmdstat, ahin->cmdstat,			d->aoemajor, d->aoeminor);		if (buf)			buf->flags |= BUFFL_FAIL;	} else {		switch (ahout->cmdstat) {		case WIN_READ:		case WIN_READ_EXT:			n = ahout->scnt << 9;			if (skb->len - sizeof *hin - sizeof *ahin < n) {				printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "					"ata data size in read.  skb->len=%d\n",					skb->len);				/* fail frame f?  just returning will rexmit. */				spin_unlock_irqrestore(&d->lock, flags);				return;			}			memcpy(f->bufaddr, ahin+1, n);		case WIN_WRITE:		case WIN_WRITE_EXT:			break;		case WIN_IDENTIFY:			if (skb->len - sizeof *hin - sizeof *ahin < 512) {				printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size "					"in ataid.  skb->len=%d\n", skb->len);				spin_unlock_irqrestore(&d->lock, flags);				return;			}			ataid_complete(d, (char *) (ahin+1));			break;		default:			printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized "			       "outbound ata command %2.2Xh for %d.%d\n", 			       ahout->cmdstat,			       be16_to_cpu(hin->major),			       hin->minor);		}	}	if (buf) {		buf->nframesout -= 1;		if (buf->nframesout == 0 && buf->resid == 0) {			unsigned long duration = jiffies - buf->start_time;			unsigned long n_sect = buf->bio->bi_size >> 9;			struct gendisk *disk = d->gd;			const int rw = bio_data_dir(buf->bio);			disk_stat_inc(disk, ios[rw]);			disk_stat_add(disk, ticks[rw], duration);			disk_stat_add(disk, sectors[rw], n_sect);			disk_stat_add(disk, io_ticks, duration);			n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;			bio_endio(buf->bio, buf->bio->bi_size, n);			mempool_free(buf, d->bufpool);		}	}	f->buf = NULL;	f->tag = FREETAG;	aoecmd_work(d);	sl = d->sendq_hd;	d->sendq_hd = d->sendq_tl = NULL;	spin_unlock_irqrestore(&d->lock, flags);	aoenet_xmit(sl);}voidaoecmd_cfg(ushort aoemajor, unsigned char aoeminor){	struct sk_buff *sl;	sl = aoecmd_cfg_pkts(aoemajor, aoeminor, NULL);	aoenet_xmit(sl);} /* * Since we only call this in one place (and it only prepares one frame) * we just return the skb.  Usually we'd chain it up to the aoedev sendq. */static struct sk_buff *aoecmd_ata_id(struct aoedev *d){	struct aoe_hdr *h;	struct aoe_atahdr *ah;	struct frame *f;	struct sk_buff *skb;	f = getframe(d, FREETAG);	if (f == NULL) {		printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame.  "			"This shouldn't happen.\n");		return NULL;	}	/* initialize the headers & frame */	h = (struct aoe_hdr *) f->data;	ah = (struct aoe_atahdr *) (h+1);	f->ndata = sizeof *h + sizeof *ah;	memset(h, 0, f->ndata);	f->tag = aoehdr_atainit(d, h);	f->waited = 0;	f->writedatalen = 0;	/* set up ata header */	ah->scnt = 1;	ah->cmdstat = WIN_IDENTIFY;	ah->lba3 = 0xa0;	skb = skb_prepare(d, f);	d->rttavg = MAXTIMER;	d->timer.function = rexmit_timer;	return skb;} voidaoecmd_cfg_rsp(struct sk_buff *skb){	struct aoedev *d;	struct aoe_hdr *h;	struct aoe_cfghdr *ch;	ulong flags, sysminor, aoemajor;	u16 bufcnt;	struct sk_buff *sl;	enum { MAXFRAMES = 16 };	h = (struct aoe_hdr *) skb->mac.raw;	ch = (struct aoe_cfghdr *) (h+1);	/*	 * Enough people have their dip switches set backwards to	 * warrant a loud message for this special case.	 */	aoemajor = be16_to_cpu(h->major);	if (aoemajor == 0xfff) {		printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf "			"address is all ones.  Check shelf dip switches\n");		return;	}	sysminor = SYSMINOR(aoemajor, h->minor);	if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) {		printk(KERN_INFO			"aoe: e%ld.%d: minor number too large\n", 			aoemajor, (int) h->minor);		return;	}	bufcnt = be16_to_cpu(ch->bufcnt);	if (bufcnt > MAXFRAMES)	/* keep it reasonable */		bufcnt = MAXFRAMES;	d = aoedev_by_sysminor_m(sysminor, bufcnt);	if (d == NULL) {		printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n");		return;	}	spin_lock_irqsave(&d->lock, flags);	/* permit device to migrate mac and network interface */	d->ifp = skb->dev;	memcpy(d->addr, h->src, sizeof d->addr);	/* don't change users' perspective */	if (d->nopen && !(d->flags & DEVFL_PAUSE)) {		spin_unlock_irqrestore(&d->lock, flags);		return;	}	d->flags |= DEVFL_PAUSE;	/* force pause */	d->fw_ver = be16_to_cpu(ch->fwver);	/* check for already outstanding ataid */	sl = aoedev_isbusy(d) == 0 ? aoecmd_ata_id(d) : NULL;	spin_unlock_irqrestore(&d->lock, flags);	aoenet_xmit(sl);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?